PHOENIX-4533 Modified Query Server to use two sets of Kerberos credentials Signed-off-by: Josh Elser <els...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/57788e27 Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/57788e27 Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/57788e27 Branch: refs/heads/4.x-HBase-1.2 Commit: 57788e27ed5b11da21cb7827ae6a04dfb12529db Parents: 3996466 Author: Lev Bronshtein <lbronsht...@bloomberg.net> Authored: Wed Jan 31 22:37:50 2018 -0500 Committer: Josh Elser <els...@apache.org> Committed: Tue Feb 13 10:51:58 2018 -0500 ---------------------------------------------------------------------- .../org/apache/phoenix/query/QueryServices.java | 2 ++ .../HttpParamImpersonationQueryServerIT.java | 16 ++++++++++------ .../phoenix/end2end/SecureQueryServerIT.java | 15 +++++++++------ .../phoenix/queryserver/server/QueryServer.java | 17 ++++++++++++++--- 4 files changed, 35 insertions(+), 15 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/phoenix/blob/57788e27/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServices.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServices.java b/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServices.java index 2a31f09..0979e36 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServices.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServices.java @@ -235,7 +235,9 @@ public interface QueryServices extends SQLCloseable { public static final String QUERY_SERVER_ENV_LOGGING_ATTRIB = "phoenix.queryserver.envvars.logging.disabled"; public static final String QUERY_SERVER_ENV_LOGGING_SKIPWORDS_ATTRIB = "phoenix.queryserver.envvars.logging.skipwords"; public static final String QUERY_SERVER_KEYTAB_FILENAME_ATTRIB = "phoenix.queryserver.keytab.file"; + public static final String QUERY_SERVER_HTTP_KEYTAB_FILENAME_ATTRIB = "phoenix.queryserver.http.keytab.file"; public static final String QUERY_SERVER_KERBEROS_PRINCIPAL_ATTRIB = "phoenix.queryserver.kerberos.principal"; + public static final String QUERY_SERVER_KERBEROS_HTTP_PRINCIPAL_ATTRIB = "phoenix.queryserver.kerberos.http.principal"; public static final String QUERY_SERVER_DNS_NAMESERVER_ATTRIB = "phoenix.queryserver.dns.nameserver"; public static final String QUERY_SERVER_DNS_INTERFACE_ATTRIB = "phoenix.queryserver.dns.interface"; public static final String QUERY_SERVER_HBASE_SECURITY_CONF_ATTRIB = "hbase.security.authentication"; http://git-wip-us.apache.org/repos/asf/phoenix/blob/57788e27/phoenix-queryserver/src/it/java/org/apache/phoenix/end2end/HttpParamImpersonationQueryServerIT.java ---------------------------------------------------------------------- diff --git a/phoenix-queryserver/src/it/java/org/apache/phoenix/end2end/HttpParamImpersonationQueryServerIT.java b/phoenix-queryserver/src/it/java/org/apache/phoenix/end2end/HttpParamImpersonationQueryServerIT.java index ef9ff68..db27b9f 100644 --- a/phoenix-queryserver/src/it/java/org/apache/phoenix/end2end/HttpParamImpersonationQueryServerIT.java +++ b/phoenix-queryserver/src/it/java/org/apache/phoenix/end2end/HttpParamImpersonationQueryServerIT.java @@ -81,6 +81,7 @@ import com.google.common.collect.Maps; @Category(NeedsOwnMiniClusterTest.class) public class HttpParamImpersonationQueryServerIT { private static final Log LOG = LogFactory.getLog(HttpParamImpersonationQueryServerIT.class); + private static final List<TableName> SYSTEM_TABLE_NAMES = Arrays.asList(PhoenixDatabaseMetaData.SYSTEM_CATALOG_HBASE_TABLE_NAME, PhoenixDatabaseMetaData.SYSTEM_MUTEX_HBASE_TABLE_NAME, PhoenixDatabaseMetaData.SYSTEM_FUNCTION_HBASE_TABLE_NAME, @@ -93,6 +94,7 @@ public class HttpParamImpersonationQueryServerIT { private static final List<File> USER_KEYTAB_FILES = new ArrayList<>(); private static final String SPNEGO_PRINCIPAL = "HTTP/localhost"; + private static final String PQS_PRINCIPAL = "phoenixqs/localhost"; private static final String SERVICE_PRINCIPAL = "securecluster/localhost"; private static File KEYTAB; @@ -195,7 +197,7 @@ public class HttpParamImpersonationQueryServerIT { // use separate identies for HBase and HDFS results in a GSS initiate error. The quick // solution is to just use a single "service" principal instead of "hbase" and "hdfs" // (or "dn" and "nn") per usual. - KDC.createPrincipal(KEYTAB, SPNEGO_PRINCIPAL, SERVICE_PRINCIPAL); + KDC.createPrincipal(KEYTAB, SPNEGO_PRINCIPAL, PQS_PRINCIPAL, SERVICE_PRINCIPAL); // Start ZK by hand UTIL.startMiniZKCluster(); @@ -216,13 +218,15 @@ public class HttpParamImpersonationQueryServerIT { conf.setStrings(CoprocessorHost.REGION_COPROCESSOR_CONF_KEY, AccessController.class.getName(), TokenProvider.class.getName()); // Secure Phoenix setup - conf.set("phoenix.queryserver.kerberos.principal", SPNEGO_PRINCIPAL); + conf.set("phoenix.queryserver.kerberos.http.principal", SPNEGO_PRINCIPAL + "@" + KDC.getRealm()); + conf.set("phoenix.queryserver.http.keytab.file", KEYTAB.getAbsolutePath()); + conf.set("phoenix.queryserver.kerberos.principal", PQS_PRINCIPAL + "@" + KDC.getRealm()); conf.set("phoenix.queryserver.keytab.file", KEYTAB.getAbsolutePath()); conf.setBoolean(QueryServices.QUERY_SERVER_DISABLE_KERBEROS_LOGIN, true); conf.setInt(QueryServices.QUERY_SERVER_HTTP_PORT_ATTRIB, 0); // Required so that PQS can impersonate the end-users to HBase - conf.set("hadoop.proxyuser.HTTP.groups", "*"); - conf.set("hadoop.proxyuser.HTTP.hosts", "*"); + conf.set("hadoop.proxyuser.phoenixqs.groups", "*"); + conf.set("hadoop.proxyuser.phoenixqs.hosts", "*"); // user1 is allowed to impersonate others, user2 is not conf.set("hadoop.proxyuser.user1.groups", "*"); conf.set("hadoop.proxyuser.user1.hosts", "*"); @@ -261,8 +265,8 @@ public class HttpParamImpersonationQueryServerIT { private static void startQueryServer() throws Exception { PQS = new QueryServer(new String[0], UTIL.getConfiguration()); - // Get the SPNEGO ident for PQS to use - final UserGroupInformation ugi = UserGroupInformation.loginUserFromKeytabAndReturnUGI(SPNEGO_PRINCIPAL, KEYTAB.getAbsolutePath()); + // Get the PQS ident for PQS to use + final UserGroupInformation ugi = UserGroupInformation.loginUserFromKeytabAndReturnUGI(PQS_PRINCIPAL, KEYTAB.getAbsolutePath()); PQS_EXECUTOR = Executors.newSingleThreadExecutor(); // Launch PQS, doing in the Kerberos login instead of letting PQS do it itself (which would // break the HBase/HDFS logins also running in the same test case). http://git-wip-us.apache.org/repos/asf/phoenix/blob/57788e27/phoenix-queryserver/src/it/java/org/apache/phoenix/end2end/SecureQueryServerIT.java ---------------------------------------------------------------------- diff --git a/phoenix-queryserver/src/it/java/org/apache/phoenix/end2end/SecureQueryServerIT.java b/phoenix-queryserver/src/it/java/org/apache/phoenix/end2end/SecureQueryServerIT.java index 9e12444..c3ff885 100644 --- a/phoenix-queryserver/src/it/java/org/apache/phoenix/end2end/SecureQueryServerIT.java +++ b/phoenix-queryserver/src/it/java/org/apache/phoenix/end2end/SecureQueryServerIT.java @@ -76,6 +76,7 @@ public class SecureQueryServerIT { private static final List<File> USER_KEYTAB_FILES = new ArrayList<>(); private static final String SPNEGO_PRINCIPAL = "HTTP/localhost"; + private static final String PQS_PRINCIPAL = "phoenixqs/localhost"; private static final String SERVICE_PRINCIPAL = "securecluster/localhost"; private static File KEYTAB; @@ -178,7 +179,7 @@ public class SecureQueryServerIT { // use separate identies for HBase and HDFS results in a GSS initiate error. The quick // solution is to just use a single "service" principal instead of "hbase" and "hdfs" // (or "dn" and "nn") per usual. - KDC.createPrincipal(KEYTAB, SPNEGO_PRINCIPAL, SERVICE_PRINCIPAL); + KDC.createPrincipal(KEYTAB, SPNEGO_PRINCIPAL, PQS_PRINCIPAL, SERVICE_PRINCIPAL); // Start ZK by hand UTIL.startMiniZKCluster(); @@ -198,13 +199,15 @@ public class SecureQueryServerIT { TokenProvider.class.getName()); // Secure Phoenix setup - conf.set("phoenix.queryserver.kerberos.principal", SPNEGO_PRINCIPAL); + conf.set("phoenix.queryserver.kerberos.http.principal", SPNEGO_PRINCIPAL + "@" + KDC.getRealm()); + conf.set("phoenix.queryserver.http.keytab.file", KEYTAB.getAbsolutePath()); + conf.set("phoenix.queryserver.kerberos.principal", PQS_PRINCIPAL + "@" + KDC.getRealm()); conf.set("phoenix.queryserver.keytab.file", KEYTAB.getAbsolutePath()); conf.setBoolean(QueryServices.QUERY_SERVER_DISABLE_KERBEROS_LOGIN, true); conf.setInt(QueryServices.QUERY_SERVER_HTTP_PORT_ATTRIB, 0); // Required so that PQS can impersonate the end-users to HBase - conf.set("hadoop.proxyuser.HTTP.groups", "*"); - conf.set("hadoop.proxyuser.HTTP.hosts", "*"); + conf.set("hadoop.proxyuser.phoenixqs.groups", "*"); + conf.set("hadoop.proxyuser.phoenixqs.hosts", "*"); // Clear the cached singletons so we can inject our own. InstanceResolver.clearSingletons(); @@ -239,8 +242,8 @@ public class SecureQueryServerIT { private static void startQueryServer() throws Exception { PQS = new QueryServer(new String[0], UTIL.getConfiguration()); - // Get the SPNEGO ident for PQS to use - final UserGroupInformation ugi = UserGroupInformation.loginUserFromKeytabAndReturnUGI(SPNEGO_PRINCIPAL, KEYTAB.getAbsolutePath()); + // Get the PQS ident for PQS to use + final UserGroupInformation ugi = UserGroupInformation.loginUserFromKeytabAndReturnUGI(PQS_PRINCIPAL, KEYTAB.getAbsolutePath()); PQS_EXECUTOR = Executors.newSingleThreadExecutor(); // Launch PQS, doing in the Kerberos login instead of letting PQS do it itself (which would // break the HBase/HDFS logins also running in the same test case). http://git-wip-us.apache.org/repos/asf/phoenix/blob/57788e27/phoenix-queryserver/src/main/java/org/apache/phoenix/queryserver/server/QueryServer.java ---------------------------------------------------------------------- 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 288e4f5..6b1fcfe 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 @@ -244,6 +244,11 @@ public final class QueryServer extends Configured implements Tool, Runnable { String keytabPath = getConf().get(QueryServices.QUERY_SERVER_KEYTAB_FILENAME_ATTRIB); File keytab = new File(keytabPath); + String httpKeytabPath = getConf().get(QueryServices.QUERY_SERVER_HTTP_KEYTAB_FILENAME_ATTRIB, null); + String httpPrincipal = getConf().get(QueryServices.QUERY_SERVER_KERBEROS_HTTP_PRINCIPAL_ATTRIB, null); + File httpKeytab = null; + if (null != httpKeytabPath) + httpKeytab = new File(httpKeytabPath); String realmsString = getConf().get(QueryServices.QUERY_SERVER_KERBEROS_ALLOWED_REALMS, null); String[] additionalAllowedRealms = null; @@ -252,9 +257,15 @@ public final class QueryServer extends Configured implements Tool, Runnable { } // Enable SPNEGO and impersonation (through standard Hadoop configuration means) - builder.withSpnego(ugi.getUserName(), additionalAllowedRealms) - .withAutomaticLogin(keytab) - .withImpersonation(new PhoenixDoAsCallback(ugi, getConf())); + if ((null != httpKeytabPath) && (null != httpPrincipal)) + builder.withSpnego(httpPrincipal, additionalAllowedRealms) + .withAutomaticLogin(httpKeytab) + .withImpersonation(new PhoenixDoAsCallback(ugi, getConf())); + else + builder.withSpnego(ugi.getUserName(), additionalAllowedRealms) + .withAutomaticLogin(keytab) + .withImpersonation(new PhoenixDoAsCallback(ugi, getConf())); + } setRemoteUserExtractorIfNecessary(builder, getConf());