From d086ca59e80eb00898fe75622da21ab6c653249c Mon Sep 17 00:00:00 2001 From: Istvan Toth Date: Thu, 16 Mar 2023 14:42:23 +0100 Subject: [PATCH] PHOENIX-6908 KerberosName$NoMatchingRule exception in QueryServer.PhoenixRemoteUserExtractor --- .../HttpParamImpersonationQueryServerIT.java | 8 ++-- .../end2end/QueryServerEnvironment.java | 10 +++-- .../queryserver/server/QueryServer.java | 37 +++++++++++++------ 3 files changed, 36 insertions(+), 19 deletions(-) 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 @@ public void testSuccessfulImpersonation() throws Exception { 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() { @Override public Void run() throws Exception { createTable(tableName, numRows); @@ -122,7 +122,7 @@ public void testSuccessfulImpersonation() throws Exception { 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() { @Override public Void run() throws Exception { // This user should not be able to read the table @@ -146,7 +146,7 @@ public void testDisallowedImpersonation() throws Exception { 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() { @Override public Void run() throws Exception { createTable(tableName, numRows); @@ -154,7 +154,7 @@ public void testDisallowedImpersonation() throws Exception { 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() { @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 @@ public class QueryServerEnvironment { private final File KEYTAB_DIR = new File(TEMP_DIR, "keytabs"); private final List 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 @@ private void createUsers(int numUsers) throws Exception { 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 @@ public Map.Entry getUser(int offset) { if (!(offset > 0 && offset <= NUM_CREATED_USERS)) { throw new IllegalArgumentException(); } - return new AbstractMap.SimpleImmutableEntry("user" + offset, USER_KEYTAB_FILES.get(offset - 1)); + return new AbstractMap.SimpleImmutableEntry("user" + offset + "/" + LOCAL_HOST_REVERSE_DNS_LOOKUP_NAME, USER_KEYTAB_FILES.get(offset - 1)); } /** @@ -325,6 +325,10 @@ public Void run() { : ""); } + 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 PhoenixRemoteUserExtractor(Configuration conf) { 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 @@ public T doAsRemoteUser(String remoteUserName, String remoteAddress, // 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() { @@ -633,6 +625,27 @@ SimpleLRUCache getCache() { } } + /** + * 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);