You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kyuubi.apache.org by fe...@apache.org on 2023/03/08 13:28:28 UTC
[kyuubi] branch branch-1.7 updated: [KYUUBI #4479] Restore JDBC Kerberos authentication behavior for UGI.doAs
This is an automated email from the ASF dual-hosted git repository.
feiwang pushed a commit to branch branch-1.7
in repository https://gitbox.apache.org/repos/asf/kyuubi.git
The following commit(s) were added to refs/heads/branch-1.7 by this push:
new 3bc536995 [KYUUBI #4479] Restore JDBC Kerberos authentication behavior for UGI.doAs
3bc536995 is described below
commit 3bc536995db3387d3242c19a5d55601f94f4f59d
Author: Cheng Pan <ch...@apache.org>
AuthorDate: Wed Mar 8 21:28:10 2023 +0800
[KYUUBI #4479] Restore JDBC Kerberos authentication behavior for UGI.doAs
### _Why are the changes needed?_
A typical use case of Hadoop UGI w/ Kyuubi Hive JDBC is
```
UserGroupInformation ugi = UserGroupInformation.getCurrentUser();
ugi.doAs(() -> {
Connection conn = DriverManager.getConnection(
"jdbc:kyuubi://host:10009/default;principal=kyuubi_HOST/ABC.ORG");
...
});
```
After https://github.com/apache/kyuubi/pull/3023, Kyuubi Hive JDBC implements the Kerberos authentication by using JDK directly instead of Hadoop `UserGroupInformation`, but it also introduce a breaking change for Hadoop users, including the above case. As workaround, user should add `kerberosAuthType=fromSubject` alongside w/ `principal=kyuubi_HOST/ABC.ORG` to make it work.
This PR propose to restore the behavior before https://github.com/apache/kyuubi/pull/3023 by handling UGI.doAs explicitly.
And this PR makes the `clientPrincipal` `clientKeytab` as the highest priority, so in below cases, `clientPrincipal` `clientKeytab` take effects instead of UGI.
```
UserGroupInformation ugi = UserGroupInformation.getCurrentUser();
ugi.doAs(() -> {
Connection conn = DriverManager.getConnection(
"jdbc:kyuubi://host:10009/default;principal=kyuubi_HOST/ABC.ORG;" +
"clientPrincipal=tom_HOST/ABC.ORG;clientKeytab=/path/xxx.keytab");
...
});
```
### _How was this patch tested?_
- [ ] Add some test cases that check the changes thoroughly including negative and positive cases if possible
- [ ] Add screenshots for manual tests if appropriate
- [ ] [Run test](https://kyuubi.readthedocs.io/en/master/develop_tools/testing.html#running-tests) locally before make a pull request
Closes #4479 from pan3793/detect-ugi.
Closes #4479
0e169abc6 [Cheng Pan] nit
19036e3d7 [Cheng Pan] reorder
e8faf9c56 [Cheng Pan] Restore JDBC kerberos authentication behavior for UGI.doAs
Authored-by: Cheng Pan <ch...@apache.org>
Signed-off-by: fwang12 <fw...@ebay.com>
(cherry picked from commit 17466ea41ab15766c0cc01473c18b1c56d6cbffb)
Signed-off-by: fwang12 <fw...@ebay.com>
---
.../apache/kyuubi/jdbc/hive/KyuubiConnection.java | 41 ++++++++++++++--------
1 file changed, 27 insertions(+), 14 deletions(-)
diff --git a/kyuubi-hive-jdbc/src/main/java/org/apache/kyuubi/jdbc/hive/KyuubiConnection.java b/kyuubi-hive-jdbc/src/main/java/org/apache/kyuubi/jdbc/hive/KyuubiConnection.java
index 0932ea565..2a485b24e 100644
--- a/kyuubi-hive-jdbc/src/main/java/org/apache/kyuubi/jdbc/hive/KyuubiConnection.java
+++ b/kyuubi-hive-jdbc/src/main/java/org/apache/kyuubi/jdbc/hive/KyuubiConnection.java
@@ -30,10 +30,7 @@ import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
-import java.security.AccessControlContext;
-import java.security.AccessController;
-import java.security.KeyStore;
-import java.security.SecureRandom;
+import java.security.*;
import java.sql.*;
import java.util.*;
import java.util.Map.Entry;
@@ -43,6 +40,7 @@ import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import javax.security.auth.Subject;
import javax.security.sasl.Sasl;
+import org.apache.commons.lang3.ClassUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.hive.service.rpc.thrift.*;
import org.apache.http.HttpRequestInterceptor;
@@ -813,11 +811,16 @@ public class KyuubiConnection implements SQLConnection, KyuubiLoggable {
return !AUTH_SIMPLE.equalsIgnoreCase(sessConfMap.get(AUTH_TYPE));
}
- private boolean isFromSubjectAuthMode() {
- return isSaslAuthMode()
- && hasSessionValue(AUTH_PRINCIPAL)
- && AUTH_KERBEROS_AUTH_TYPE_FROM_SUBJECT.equalsIgnoreCase(
- sessConfMap.get(AUTH_KERBEROS_AUTH_TYPE));
+ private boolean isHadoopUserGroupInformationDoAs() {
+ try {
+ @SuppressWarnings("unchecked")
+ Class<? extends Principal> HadoopUserClz =
+ (Class<? extends Principal>) ClassUtils.getClass("org.apache.hadoop.security.User");
+ Subject subject = Subject.getSubject(AccessController.getContext());
+ return subject != null && !subject.getPrincipals(HadoopUserClz).isEmpty();
+ } catch (ClassNotFoundException e) {
+ return false;
+ }
}
private boolean isKeytabAuthMode() {
@@ -827,6 +830,16 @@ public class KyuubiConnection implements SQLConnection, KyuubiLoggable {
&& hasSessionValue(AUTH_KYUUBI_CLIENT_KEYTAB);
}
+ private boolean isFromSubjectAuthMode() {
+ return isSaslAuthMode()
+ && hasSessionValue(AUTH_PRINCIPAL)
+ && !hasSessionValue(AUTH_KYUUBI_CLIENT_PRINCIPAL)
+ && !hasSessionValue(AUTH_KYUUBI_CLIENT_KEYTAB)
+ && (AUTH_KERBEROS_AUTH_TYPE_FROM_SUBJECT.equalsIgnoreCase(
+ sessConfMap.get(AUTH_KERBEROS_AUTH_TYPE))
+ || isHadoopUserGroupInformationDoAs());
+ }
+
private boolean isTgtCacheAuthMode() {
return isSaslAuthMode()
&& hasSessionValue(AUTH_PRINCIPAL)
@@ -843,15 +856,15 @@ public class KyuubiConnection implements SQLConnection, KyuubiLoggable {
}
private Subject createSubject() {
- if (isFromSubjectAuthMode()) {
+ if (isKeytabAuthMode()) {
+ String principal = sessConfMap.get(AUTH_KYUUBI_CLIENT_PRINCIPAL);
+ String keytab = sessConfMap.get(AUTH_KYUUBI_CLIENT_KEYTAB);
+ return KerberosAuthenticationManager.getKeytabAuthentication(principal, keytab).getSubject();
+ } else if (isFromSubjectAuthMode()) {
AccessControlContext context = AccessController.getContext();
return Subject.getSubject(context);
} else if (isTgtCacheAuthMode()) {
return KerberosAuthenticationManager.getTgtCacheAuthentication().getSubject();
- } else if (isKeytabAuthMode()) {
- String principal = sessConfMap.get(AUTH_KYUUBI_CLIENT_PRINCIPAL);
- String keytab = sessConfMap.get(AUTH_KYUUBI_CLIENT_KEYTAB);
- return KerberosAuthenticationManager.getKeytabAuthentication(principal, keytab).getSubject();
} else {
// This should never happen
throw new IllegalArgumentException("Unsupported auth mode");