PHOENIX-6908 KerberosName$NoMatchingRule exception in QueryServer.PhoenixRemoteUserExtractor
diff --git a/phoenix-queryserver-it/src/it/java/org/apache/phoenix/end2end/HttpParamImpersonationQueryServerIT.java b/phoenix-queryserver-it/src/it/java/org/apache/phoenix/end2end/HttpParamImpersonationQueryServerIT.java
index ccde0e4..793925c 100644
--- a/phoenix-queryserver-it/src/it/java/org/apache/phoenix/end2end/HttpParamImpersonationQueryServerIT.java
+++ b/phoenix-queryserver-it/src/it/java/org/apache/phoenix/end2end/HttpParamImpersonationQueryServerIT.java
@@ -114,7 +114,7 @@
final String doAsUrlTemplate = getUrlTemplate();
final String tableName = "POSITIVE_IMPERSONATION";
final int numRows = 5;
- final UserGroupInformation serviceUgi = UserGroupInformation.loginUserFromKeytabAndReturnUGI(environment.getServicePrincipal(), environment.getServiceKeytab().getAbsolutePath());
+ final UserGroupInformation serviceUgi = UserGroupInformation.loginUserFromKeytabAndReturnUGI(environment.getServicePrincipal() + "@" + environment.getRealm(), environment.getServiceKeytab().getAbsolutePath());
serviceUgi.doAs(new PrivilegedExceptionAction<Void>() {
@Override public Void run() throws Exception {
createTable(tableName, numRows);
@@ -122,7 +122,7 @@
return null;
}
});
- UserGroupInformation user1Ugi = UserGroupInformation.loginUserFromKeytabAndReturnUGI(user1.getKey(), user1.getValue().getAbsolutePath());
+ UserGroupInformation user1Ugi = UserGroupInformation.loginUserFromKeytabAndReturnUGI(user1.getKey() + "@" + environment.getRealm(), user1.getValue().getAbsolutePath());
user1Ugi.doAs(new PrivilegedExceptionAction<Void>() {
@Override public Void run() throws Exception {
// This user should not be able to read the table
@@ -146,7 +146,7 @@
final String doAsUrlTemplate = getUrlTemplate();
final String tableName = "DISALLOWED_IMPERSONATION";
final int numRows = 5;
- final UserGroupInformation serviceUgi = UserGroupInformation.loginUserFromKeytabAndReturnUGI(environment.getServicePrincipal(), environment.getServiceKeytab().getAbsolutePath());
+ final UserGroupInformation serviceUgi = UserGroupInformation.loginUserFromKeytabAndReturnUGI(environment.getServicePrincipal() + "@" + environment.getRealm(), environment.getServiceKeytab().getAbsolutePath());
serviceUgi.doAs(new PrivilegedExceptionAction<Void>() {
@Override public Void run() throws Exception {
createTable(tableName, numRows);
@@ -154,7 +154,7 @@
return null;
}
});
- UserGroupInformation user2Ugi = UserGroupInformation.loginUserFromKeytabAndReturnUGI(user2.getKey(), user2.getValue().getAbsolutePath());
+ UserGroupInformation user2Ugi = UserGroupInformation.loginUserFromKeytabAndReturnUGI(user2.getKey() + "@" + environment.getRealm(), user2.getValue().getAbsolutePath());
user2Ugi.doAs(new PrivilegedExceptionAction<Void>() {
@Override public Void run() throws Exception {
// This user is disallowed to read this table
diff --git a/phoenix-queryserver-it/src/it/java/org/apache/phoenix/end2end/QueryServerEnvironment.java b/phoenix-queryserver-it/src/it/java/org/apache/phoenix/end2end/QueryServerEnvironment.java
index 40e6c04..9a24ce4 100644
--- a/phoenix-queryserver-it/src/it/java/org/apache/phoenix/end2end/QueryServerEnvironment.java
+++ b/phoenix-queryserver-it/src/it/java/org/apache/phoenix/end2end/QueryServerEnvironment.java
@@ -65,7 +65,7 @@
private final File KEYTAB_DIR = new File(TEMP_DIR, "keytabs");
private final List<File> USER_KEYTAB_FILES = new ArrayList<>();
- private static final String LOCAL_HOST_REVERSE_DNS_LOOKUP_NAME;
+ static final String LOCAL_HOST_REVERSE_DNS_LOOKUP_NAME;
static {
try {
@@ -142,7 +142,7 @@
for (int i = 1; i <= numUsers; i++) {
String principal = "user" + i;
File keytabFile = new File(KEYTAB_DIR, principal + ".keytab");
- KDC.createPrincipal(keytabFile, principal);
+ KDC.createPrincipal(keytabFile, principal + "/"+ LOCAL_HOST_REVERSE_DNS_LOOKUP_NAME + "@" + KDC.getRealm());
USER_KEYTAB_FILES.add(keytabFile);
}
}
@@ -151,7 +151,7 @@
if (!(offset > 0 && offset <= NUM_CREATED_USERS)) {
throw new IllegalArgumentException();
}
- return new AbstractMap.SimpleImmutableEntry<String, File>("user" + offset, USER_KEYTAB_FILES.get(offset - 1));
+ return new AbstractMap.SimpleImmutableEntry<String, File>("user" + offset + "/" + LOCAL_HOST_REVERSE_DNS_LOOKUP_NAME, USER_KEYTAB_FILES.get(offset - 1));
}
/**
@@ -325,6 +325,10 @@
: "");
}
+ public String getRealm() {
+ return KDC.getRealm();
+ }
+
public void stop() throws Exception {
// Remove our custom ConfigurationFactory for future tests
InstanceResolver.clearSingletons();
diff --git a/phoenix-queryserver/src/main/java/org/apache/phoenix/queryserver/server/QueryServer.java b/phoenix-queryserver/src/main/java/org/apache/phoenix/queryserver/server/QueryServer.java
index 2add30e..8619da1 100644
--- a/phoenix-queryserver/src/main/java/org/apache/phoenix/queryserver/server/QueryServer.java
+++ b/phoenix-queryserver/src/main/java/org/apache/phoenix/queryserver/server/QueryServer.java
@@ -551,7 +551,9 @@
public String extract(HttpServletRequest request) throws RemoteUserExtractionException {
if (request.getParameter(userExtractParam) != null) {
String extractedUser = paramRemoteUserExtractor.extract(request);
- UserGroupInformation ugi = UserGroupInformation.createRemoteUser(request.getRemoteUser());
+ UserGroupInformation ugi =
+ UserGroupInformation
+ .createRemoteUser(stripHostNameFromPrincipal(request.getRemoteUser()));
UserGroupInformation proxyUser = UserGroupInformation.createProxyUser(extractedUser, ugi);
// Check if this user is allowed to be impersonated.
@@ -597,17 +599,7 @@
// Proxy this user on top of the server's user (the real user). Get a cached instance, the
// LoadingCache will create a new instance for us if one isn't cached.
-
- // realm got removed from remoteUserName in CALCITE-4152
- // so we remove the instance name to avoid geting KerberosName$NoMatchingRule exception
-
- int atSignIndex = remoteUserName.indexOf('@');
- int separatorIndex = remoteUserName.indexOf('/');
- if (atSignIndex == -1 && separatorIndex > 0) {
- remoteUserName = remoteUserName.substring(0, separatorIndex);
- }
-
- UserGroupInformation proxyUser = createProxyUser(remoteUserName);
+ UserGroupInformation proxyUser = createProxyUser(stripHostNameFromPrincipal(remoteUserName));
// Execute the actual call as this proxy user
return proxyUser.doAs(new PrivilegedExceptionAction<T>() {
@@ -633,6 +625,27 @@
}
}
+ /**
+ * The new Jetty kerberos implementation that we use strips the realm from the principal, which
+ * and Hadoop cannot process that.
+ * This strips the hostname part as well, so that only the username remains.
+
+ * @param remoteUserName the principal as received from Jetty
+ * @return the principal without the hostname part
+ */
+ //TODO We are probably compensating for a Jetty a bug, which should really be fixed in Jetty
+ // See PHOENIX-6913
+ private static String stripHostNameFromPrincipal(String remoteUserName) {
+ // realm got removed from remoteUserName in CALCITE-4152
+ // so we remove the instance name to avoid geting KerberosName$NoMatchingRule exception
+ int atSignIndex = remoteUserName.indexOf('@');
+ int separatorIndex = remoteUserName.indexOf('/');
+ if (atSignIndex == -1 && separatorIndex > 0) {
+ remoteUserName = remoteUserName.substring(0, separatorIndex);
+ }
+ return remoteUserName;
+ }
+
public static void main(String[] argv) throws Exception {
int ret = ToolRunner.run(HBaseConfiguration.create(), new QueryServer(), argv);
System.exit(ret);