HDFS-16591. Setup JaasConfiguration in ZKCuratorManager when SASL is enabled
Fixes #4447 Signed-off-by: Owen O'Malley <oomalley@linkedin.com>
This commit is contained in:
parent
ebe3ed5cd3
commit
f4e8a4f36c
|
@ -0,0 +1,77 @@
|
||||||
|
/**
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License. See accompanying LICENSE file.
|
||||||
|
*/
|
||||||
|
package org.apache.hadoop.security.authentication.util;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.security.auth.login.AppConfigurationEntry;
|
||||||
|
import javax.security.auth.login.Configuration;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a programmatic version of a jaas.conf file. This can be used
|
||||||
|
* instead of writing a jaas.conf file and setting the system property,
|
||||||
|
* "java.security.auth.login.config", to point to that file. It is meant to be
|
||||||
|
* used for connecting to ZooKeeper.
|
||||||
|
*/
|
||||||
|
public class JaasConfiguration extends Configuration {
|
||||||
|
|
||||||
|
private final javax.security.auth.login.Configuration baseConfig =
|
||||||
|
javax.security.auth.login.Configuration.getConfiguration();
|
||||||
|
private final AppConfigurationEntry[] entry;
|
||||||
|
private final String entryName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an entry to the jaas configuration with the passed in name,
|
||||||
|
* principal, and keytab. The other necessary options will be set for you.
|
||||||
|
*
|
||||||
|
* @param entryName The name of the entry (e.g. "Client")
|
||||||
|
* @param principal The principal of the user
|
||||||
|
* @param keytab The location of the keytab
|
||||||
|
*/
|
||||||
|
public JaasConfiguration(String entryName, String principal, String keytab) {
|
||||||
|
this.entryName = entryName;
|
||||||
|
Map<String, String> options = new HashMap<>();
|
||||||
|
options.put("keyTab", keytab);
|
||||||
|
options.put("principal", principal);
|
||||||
|
options.put("useKeyTab", "true");
|
||||||
|
options.put("storeKey", "true");
|
||||||
|
options.put("useTicketCache", "false");
|
||||||
|
options.put("refreshKrb5Config", "true");
|
||||||
|
String jaasEnvVar = System.getenv("HADOOP_JAAS_DEBUG");
|
||||||
|
if ("true".equalsIgnoreCase(jaasEnvVar)) {
|
||||||
|
options.put("debug", "true");
|
||||||
|
}
|
||||||
|
entry = new AppConfigurationEntry[]{
|
||||||
|
new AppConfigurationEntry(getKrb5LoginModuleName(),
|
||||||
|
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
|
||||||
|
options)};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
|
||||||
|
return (entryName.equals(name)) ? entry : ((baseConfig != null)
|
||||||
|
? baseConfig.getAppConfigurationEntry(name) : null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getKrb5LoginModuleName() {
|
||||||
|
String krb5LoginModuleName;
|
||||||
|
if (System.getProperty("java.vendor").contains("IBM")) {
|
||||||
|
krb5LoginModuleName = "com.ibm.security.auth.module.Krb5LoginModule";
|
||||||
|
} else {
|
||||||
|
krb5LoginModuleName = "com.sun.security.auth.module.Krb5LoginModule";
|
||||||
|
}
|
||||||
|
return krb5LoginModuleName;
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,12 +17,9 @@ import org.apache.hadoop.thirdparty.com.google.common.annotations.VisibleForTest
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import javax.security.auth.login.AppConfigurationEntry;
|
|
||||||
import javax.security.auth.login.Configuration;
|
import javax.security.auth.login.Configuration;
|
||||||
import javax.servlet.ServletContext;
|
import javax.servlet.ServletContext;
|
||||||
import org.apache.curator.RetryPolicy;
|
import org.apache.curator.RetryPolicy;
|
||||||
|
@ -429,62 +426,4 @@ public class ZKSignerSecretProvider extends RolloverSignerSecretProvider {
|
||||||
return saslACL;
|
return saslACL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a programmatic version of a jaas.conf file. This can be used
|
|
||||||
* instead of writing a jaas.conf file and setting the system property,
|
|
||||||
* "java.security.auth.login.config", to point to that file. It is meant to be
|
|
||||||
* used for connecting to ZooKeeper.
|
|
||||||
*/
|
|
||||||
@InterfaceAudience.Private
|
|
||||||
public static class JaasConfiguration extends Configuration {
|
|
||||||
|
|
||||||
private final javax.security.auth.login.Configuration baseConfig =
|
|
||||||
javax.security.auth.login.Configuration.getConfiguration();
|
|
||||||
private static AppConfigurationEntry[] entry;
|
|
||||||
private String entryName;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add an entry to the jaas configuration with the passed in name,
|
|
||||||
* principal, and keytab. The other necessary options will be set for you.
|
|
||||||
*
|
|
||||||
* @param entryName The name of the entry (e.g. "Client")
|
|
||||||
* @param principal The principal of the user
|
|
||||||
* @param keytab The location of the keytab
|
|
||||||
*/
|
|
||||||
public JaasConfiguration(String entryName, String principal, String keytab) {
|
|
||||||
this.entryName = entryName;
|
|
||||||
Map<String, String> options = new HashMap<String, String>();
|
|
||||||
options.put("keyTab", keytab);
|
|
||||||
options.put("principal", principal);
|
|
||||||
options.put("useKeyTab", "true");
|
|
||||||
options.put("storeKey", "true");
|
|
||||||
options.put("useTicketCache", "false");
|
|
||||||
options.put("refreshKrb5Config", "true");
|
|
||||||
String jaasEnvVar = System.getenv("HADOOP_JAAS_DEBUG");
|
|
||||||
if (jaasEnvVar != null && "true".equalsIgnoreCase(jaasEnvVar)) {
|
|
||||||
options.put("debug", "true");
|
|
||||||
}
|
|
||||||
entry = new AppConfigurationEntry[]{
|
|
||||||
new AppConfigurationEntry(getKrb5LoginModuleName(),
|
|
||||||
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
|
|
||||||
options)};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
|
|
||||||
return (entryName.equals(name)) ? entry : ((baseConfig != null)
|
|
||||||
? baseConfig.getAppConfigurationEntry(name) : null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getKrb5LoginModuleName() {
|
|
||||||
String krb5LoginModuleName;
|
|
||||||
if (System.getProperty("java.vendor").contains("IBM")) {
|
|
||||||
krb5LoginModuleName = "com.ibm.security.auth.module.Krb5LoginModule";
|
|
||||||
} else {
|
|
||||||
krb5LoginModuleName = "com.sun.security.auth.module.Krb5LoginModule";
|
|
||||||
}
|
|
||||||
return krb5LoginModuleName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,8 +32,8 @@ public class TestJaasConfiguration {
|
||||||
krb5LoginModuleName = "com.sun.security.auth.module.Krb5LoginModule";
|
krb5LoginModuleName = "com.sun.security.auth.module.Krb5LoginModule";
|
||||||
}
|
}
|
||||||
|
|
||||||
ZKSignerSecretProvider.JaasConfiguration jConf =
|
JaasConfiguration jConf =
|
||||||
new ZKSignerSecretProvider.JaasConfiguration("foo", "foo/localhost",
|
new JaasConfiguration("foo", "foo/localhost",
|
||||||
"/some/location/foo.keytab");
|
"/some/location/foo.keytab");
|
||||||
AppConfigurationEntry[] entries = jConf.getAppConfigurationEntry("bar");
|
AppConfigurationEntry[] entries = jConf.getAppConfigurationEntry("bar");
|
||||||
Assert.assertNull(entries);
|
Assert.assertNull(entries);
|
||||||
|
|
|
@ -398,6 +398,10 @@ public class CommonConfigurationKeys extends CommonConfigurationKeysPublic {
|
||||||
public static final String ZK_AUTH = ZK_PREFIX + "auth";
|
public static final String ZK_AUTH = ZK_PREFIX + "auth";
|
||||||
/** Principal name for zookeeper servers. */
|
/** Principal name for zookeeper servers. */
|
||||||
public static final String ZK_SERVER_PRINCIPAL = ZK_PREFIX + "server.principal";
|
public static final String ZK_SERVER_PRINCIPAL = ZK_PREFIX + "server.principal";
|
||||||
|
/** Kerberos principal name for zookeeper connection. */
|
||||||
|
public static final String ZK_KERBEROS_PRINCIPAL = ZK_PREFIX + "kerberos.principal";
|
||||||
|
/** Kerberos keytab for zookeeper connection. */
|
||||||
|
public static final String ZK_KERBEROS_KEYTAB = ZK_PREFIX + "kerberos.keytab";
|
||||||
|
|
||||||
/** Address of the ZooKeeper ensemble. */
|
/** Address of the ZooKeeper ensemble. */
|
||||||
public static final String ZK_ADDRESS = ZK_PREFIX + "address";
|
public static final String ZK_ADDRESS = ZK_PREFIX + "address";
|
||||||
|
|
|
@ -24,15 +24,12 @@ import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import javax.security.auth.login.AppConfigurationEntry;
|
|
||||||
|
|
||||||
import org.apache.curator.ensemble.fixed.FixedEnsembleProvider;
|
import org.apache.curator.ensemble.fixed.FixedEnsembleProvider;
|
||||||
import org.apache.curator.framework.CuratorFramework;
|
import org.apache.curator.framework.CuratorFramework;
|
||||||
import org.apache.curator.framework.CuratorFrameworkFactory;
|
import org.apache.curator.framework.CuratorFrameworkFactory;
|
||||||
|
@ -53,6 +50,7 @@ import org.apache.hadoop.classification.InterfaceAudience.Private;
|
||||||
import org.apache.hadoop.classification.InterfaceStability.Unstable;
|
import org.apache.hadoop.classification.InterfaceStability.Unstable;
|
||||||
import org.apache.hadoop.conf.Configuration;
|
import org.apache.hadoop.conf.Configuration;
|
||||||
import org.apache.hadoop.security.SecurityUtil;
|
import org.apache.hadoop.security.SecurityUtil;
|
||||||
|
import org.apache.hadoop.security.authentication.util.JaasConfiguration;
|
||||||
import org.apache.hadoop.security.token.Token;
|
import org.apache.hadoop.security.token.Token;
|
||||||
import org.apache.hadoop.security.token.delegation.web.DelegationTokenManager;
|
import org.apache.hadoop.security.token.delegation.web.DelegationTokenManager;
|
||||||
import org.apache.hadoop.util.curator.ZKCuratorManager;
|
import org.apache.hadoop.util.curator.ZKCuratorManager;
|
||||||
|
@ -248,68 +246,6 @@ public abstract class ZKDelegationTokenSecretManager<TokenIdent extends Abstract
|
||||||
return principal.split("[/@]")[0];
|
return principal.split("[/@]")[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a programmatic version of a jaas.conf file. This can be used
|
|
||||||
* instead of writing a jaas.conf file and setting the system property,
|
|
||||||
* "java.security.auth.login.config", to point to that file. It is meant to be
|
|
||||||
* used for connecting to ZooKeeper.
|
|
||||||
*/
|
|
||||||
@InterfaceAudience.Private
|
|
||||||
public static class JaasConfiguration extends
|
|
||||||
javax.security.auth.login.Configuration {
|
|
||||||
|
|
||||||
private final javax.security.auth.login.Configuration baseConfig =
|
|
||||||
javax.security.auth.login.Configuration.getConfiguration();
|
|
||||||
private static AppConfigurationEntry[] entry;
|
|
||||||
private String entryName;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add an entry to the jaas configuration with the passed in name,
|
|
||||||
* principal, and keytab. The other necessary options will be set for you.
|
|
||||||
*
|
|
||||||
* @param entryName
|
|
||||||
* The name of the entry (e.g. "Client")
|
|
||||||
* @param principal
|
|
||||||
* The principal of the user
|
|
||||||
* @param keytab
|
|
||||||
* The location of the keytab
|
|
||||||
*/
|
|
||||||
public JaasConfiguration(String entryName, String principal, String keytab) {
|
|
||||||
this.entryName = entryName;
|
|
||||||
Map<String, String> options = new HashMap<String, String>();
|
|
||||||
options.put("keyTab", keytab);
|
|
||||||
options.put("principal", principal);
|
|
||||||
options.put("useKeyTab", "true");
|
|
||||||
options.put("storeKey", "true");
|
|
||||||
options.put("useTicketCache", "false");
|
|
||||||
options.put("refreshKrb5Config", "true");
|
|
||||||
String jaasEnvVar = System.getenv("HADOOP_JAAS_DEBUG");
|
|
||||||
if (jaasEnvVar != null && "true".equalsIgnoreCase(jaasEnvVar)) {
|
|
||||||
options.put("debug", "true");
|
|
||||||
}
|
|
||||||
entry = new AppConfigurationEntry[] {
|
|
||||||
new AppConfigurationEntry(getKrb5LoginModuleName(),
|
|
||||||
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
|
|
||||||
options) };
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
|
|
||||||
return (entryName.equals(name)) ? entry : ((baseConfig != null)
|
|
||||||
? baseConfig.getAppConfigurationEntry(name) : null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getKrb5LoginModuleName() {
|
|
||||||
String krb5LoginModuleName;
|
|
||||||
if (System.getProperty("java.vendor").contains("IBM")) {
|
|
||||||
krb5LoginModuleName = "com.ibm.security.auth.module.Krb5LoginModule";
|
|
||||||
} else {
|
|
||||||
krb5LoginModuleName = "com.sun.security.auth.module.Krb5LoginModule";
|
|
||||||
}
|
|
||||||
return krb5LoginModuleName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void startThreads() throws IOException {
|
public void startThreads() throws IOException {
|
||||||
if (!isExternalClient) {
|
if (!isExternalClient) {
|
||||||
|
|
|
@ -33,6 +33,7 @@ import org.apache.hadoop.classification.InterfaceAudience;
|
||||||
import org.apache.hadoop.conf.Configuration;
|
import org.apache.hadoop.conf.Configuration;
|
||||||
import org.apache.hadoop.fs.CommonConfigurationKeys;
|
import org.apache.hadoop.fs.CommonConfigurationKeys;
|
||||||
import org.apache.hadoop.security.SecurityUtil;
|
import org.apache.hadoop.security.SecurityUtil;
|
||||||
|
import org.apache.hadoop.security.authentication.util.JaasConfiguration;
|
||||||
import org.apache.hadoop.util.ZKUtil;
|
import org.apache.hadoop.util.ZKUtil;
|
||||||
import org.apache.zookeeper.CreateMode;
|
import org.apache.zookeeper.CreateMode;
|
||||||
import org.apache.zookeeper.Watcher;
|
import org.apache.zookeeper.Watcher;
|
||||||
|
@ -159,7 +160,9 @@ public final class ZKCuratorManager {
|
||||||
CuratorFramework client = CuratorFrameworkFactory.builder()
|
CuratorFramework client = CuratorFrameworkFactory.builder()
|
||||||
.connectString(zkHostPort)
|
.connectString(zkHostPort)
|
||||||
.zookeeperFactory(new HadoopZookeeperFactory(
|
.zookeeperFactory(new HadoopZookeeperFactory(
|
||||||
conf.get(CommonConfigurationKeys.ZK_SERVER_PRINCIPAL)))
|
conf.get(CommonConfigurationKeys.ZK_SERVER_PRINCIPAL),
|
||||||
|
conf.get(CommonConfigurationKeys.ZK_KERBEROS_PRINCIPAL),
|
||||||
|
conf.get(CommonConfigurationKeys.ZK_KERBEROS_KEYTAB)))
|
||||||
.sessionTimeoutMs(zkSessionTimeout)
|
.sessionTimeoutMs(zkSessionTimeout)
|
||||||
.retryPolicy(retryPolicy)
|
.retryPolicy(retryPolicy)
|
||||||
.authorization(authInfos)
|
.authorization(authInfos)
|
||||||
|
@ -445,10 +448,20 @@ public final class ZKCuratorManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class HadoopZookeeperFactory implements ZookeeperFactory {
|
public static class HadoopZookeeperFactory implements ZookeeperFactory {
|
||||||
|
public final static String JAAS_CLIENT_ENTRY = "HadoopZookeeperClient";
|
||||||
private final String zkPrincipal;
|
private final String zkPrincipal;
|
||||||
|
private final String kerberosPrincipal;
|
||||||
|
private final String kerberosKeytab;
|
||||||
|
|
||||||
public HadoopZookeeperFactory(String zkPrincipal) {
|
public HadoopZookeeperFactory(String zkPrincipal) {
|
||||||
|
this(zkPrincipal, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public HadoopZookeeperFactory(String zkPrincipal, String kerberosPrincipal,
|
||||||
|
String kerberosKeytab) {
|
||||||
this.zkPrincipal = zkPrincipal;
|
this.zkPrincipal = zkPrincipal;
|
||||||
|
this.kerberosPrincipal = kerberosPrincipal;
|
||||||
|
this.kerberosKeytab = kerberosKeytab;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -462,8 +475,32 @@ public final class ZKCuratorManager {
|
||||||
zkClientConfig.setProperty(ZKClientConfig.ZK_SASL_CLIENT_USERNAME,
|
zkClientConfig.setProperty(ZKClientConfig.ZK_SASL_CLIENT_USERNAME,
|
||||||
zkPrincipal);
|
zkPrincipal);
|
||||||
}
|
}
|
||||||
|
if (zkClientConfig.isSaslClientEnabled() && !isJaasConfigurationSet(zkClientConfig)) {
|
||||||
|
setJaasConfiguration(zkClientConfig);
|
||||||
|
}
|
||||||
return new ZooKeeper(connectString, sessionTimeout, watcher,
|
return new ZooKeeper(connectString, sessionTimeout, watcher,
|
||||||
canBeReadOnly, zkClientConfig);
|
canBeReadOnly, zkClientConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isJaasConfigurationSet(ZKClientConfig zkClientConfig) {
|
||||||
|
String clientConfig = zkClientConfig.getProperty(ZKClientConfig.LOGIN_CONTEXT_NAME_KEY,
|
||||||
|
ZKClientConfig.LOGIN_CONTEXT_NAME_KEY_DEFAULT);
|
||||||
|
return javax.security.auth.login.Configuration.getConfiguration()
|
||||||
|
.getAppConfigurationEntry(clientConfig) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setJaasConfiguration(ZKClientConfig zkClientConfig) throws IOException {
|
||||||
|
if (kerberosPrincipal == null || kerberosKeytab == null) {
|
||||||
|
LOG.warn("JaasConfiguration has not been set since kerberos principal "
|
||||||
|
+ "or keytab is not specified");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String principal = SecurityUtil.getServerPrincipal(kerberosPrincipal, "");
|
||||||
|
JaasConfiguration jconf = new JaasConfiguration(JAAS_CLIENT_ENTRY, principal,
|
||||||
|
kerberosKeytab);
|
||||||
|
javax.security.auth.login.Configuration.setConfiguration(jconf);
|
||||||
|
zkClientConfig.setProperty(ZKClientConfig.LOGIN_CONTEXT_NAME_KEY, JAAS_CLIENT_ENTRY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -25,11 +25,15 @@ import static org.junit.Assert.assertTrue;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.security.auth.login.AppConfigurationEntry;
|
||||||
import org.apache.curator.test.TestingServer;
|
import org.apache.curator.test.TestingServer;
|
||||||
import org.apache.hadoop.conf.Configuration;
|
import org.apache.hadoop.conf.Configuration;
|
||||||
import org.apache.hadoop.fs.CommonConfigurationKeys;
|
import org.apache.hadoop.fs.CommonConfigurationKeys;
|
||||||
|
import org.apache.hadoop.security.authentication.util.JaasConfiguration;
|
||||||
import org.apache.hadoop.util.ZKUtil;
|
import org.apache.hadoop.util.ZKUtil;
|
||||||
import org.apache.zookeeper.CreateMode;
|
import org.apache.zookeeper.CreateMode;
|
||||||
|
import org.apache.zookeeper.ZooKeeper;
|
||||||
|
import org.apache.zookeeper.client.ZKClientConfig;
|
||||||
import org.apache.zookeeper.data.ACL;
|
import org.apache.zookeeper.data.ACL;
|
||||||
import org.apache.zookeeper.data.Stat;
|
import org.apache.zookeeper.data.Stat;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
|
@ -154,4 +158,51 @@ public class TestZKCuratorManager {
|
||||||
assertFalse(curator.exists(node2));
|
assertFalse(curator.exists(node2));
|
||||||
assertTrue(Arrays.equals(setData, curator.getData(node1)));
|
assertTrue(Arrays.equals(setData, curator.getData(node1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testJaasConfiguration() throws Exception {
|
||||||
|
// Validate that HadoopZooKeeperFactory will set ZKConfig with given principals
|
||||||
|
ZKCuratorManager.HadoopZookeeperFactory factory1 =
|
||||||
|
new ZKCuratorManager.HadoopZookeeperFactory("foo1", "bar1", "bar1.keytab");
|
||||||
|
ZooKeeper zk1 = factory1.newZooKeeper("connString", 1000, null, false);
|
||||||
|
validateJaasConfiguration(ZKCuratorManager.HadoopZookeeperFactory.JAAS_CLIENT_ENTRY,
|
||||||
|
"bar1", "bar1.keytab", zk1);
|
||||||
|
|
||||||
|
// Validate that a new HadoopZooKeeperFactory will use the new principals
|
||||||
|
ZKCuratorManager.HadoopZookeeperFactory factory2 =
|
||||||
|
new ZKCuratorManager.HadoopZookeeperFactory("foo2", "bar2", "bar2.keytab");
|
||||||
|
ZooKeeper zk2 = factory2.newZooKeeper("connString", 1000, null, false);
|
||||||
|
validateJaasConfiguration(ZKCuratorManager.HadoopZookeeperFactory.JAAS_CLIENT_ENTRY,
|
||||||
|
"bar2", "bar2.keytab", zk2);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Setting global configuration
|
||||||
|
String testClientConfig = "TestClientConfig";
|
||||||
|
JaasConfiguration jconf = new JaasConfiguration(testClientConfig, "test", "test.keytab");
|
||||||
|
javax.security.auth.login.Configuration.setConfiguration(jconf);
|
||||||
|
System.setProperty(ZKClientConfig.LOGIN_CONTEXT_NAME_KEY, testClientConfig);
|
||||||
|
|
||||||
|
// Validate that a new HadoopZooKeeperFactory will use the global principals
|
||||||
|
ZKCuratorManager.HadoopZookeeperFactory factory3 =
|
||||||
|
new ZKCuratorManager.HadoopZookeeperFactory("foo3", "bar3", "bar3.keytab");
|
||||||
|
ZooKeeper zk3 = factory3.newZooKeeper("connString", 1000, null, false);
|
||||||
|
validateJaasConfiguration(testClientConfig, "test", "test.keytab", zk3);
|
||||||
|
} finally {
|
||||||
|
// Remove global configuration
|
||||||
|
System.clearProperty(ZKClientConfig.LOGIN_CONTEXT_NAME_KEY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateJaasConfiguration(String clientConfig, String principal, String keytab,
|
||||||
|
ZooKeeper zk) {
|
||||||
|
assertEquals("Validate that expected clientConfig is set in ZK config", clientConfig,
|
||||||
|
zk.getClientConfig().getProperty(ZKClientConfig.LOGIN_CONTEXT_NAME_KEY));
|
||||||
|
|
||||||
|
AppConfigurationEntry[] entries = javax.security.auth.login.Configuration.getConfiguration()
|
||||||
|
.getAppConfigurationEntry(clientConfig);
|
||||||
|
assertEquals("Validate that expected principal is set in Jaas config", principal,
|
||||||
|
entries[0].getOptions().get("principal"));
|
||||||
|
assertEquals("Validate that expected keytab is set in Jaas config", keytab,
|
||||||
|
entries[0].getOptions().get("keyTab"));
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -18,12 +18,12 @@
|
||||||
|
|
||||||
package org.apache.hadoop.registry.client.impl.zk;
|
package org.apache.hadoop.registry.client.impl.zk;
|
||||||
|
|
||||||
|
import org.apache.hadoop.security.authentication.util.JaasConfiguration;
|
||||||
import org.apache.hadoop.thirdparty.com.google.common.base.Preconditions;
|
import org.apache.hadoop.thirdparty.com.google.common.base.Preconditions;
|
||||||
import org.apache.hadoop.thirdparty.com.google.common.base.Splitter;
|
import org.apache.hadoop.thirdparty.com.google.common.base.Splitter;
|
||||||
import org.apache.hadoop.thirdparty.com.google.common.collect.Lists;
|
import org.apache.hadoop.thirdparty.com.google.common.collect.Lists;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.curator.framework.CuratorFrameworkFactory;
|
import org.apache.curator.framework.CuratorFrameworkFactory;
|
||||||
import org.apache.hadoop.classification.InterfaceAudience;
|
|
||||||
import org.apache.hadoop.conf.Configuration;
|
import org.apache.hadoop.conf.Configuration;
|
||||||
import org.apache.hadoop.security.UserGroupInformation;
|
import org.apache.hadoop.security.UserGroupInformation;
|
||||||
import org.apache.hadoop.security.authentication.util.KerberosUtil;
|
import org.apache.hadoop.security.authentication.util.KerberosUtil;
|
||||||
|
@ -46,11 +46,9 @@ import java.io.IOException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ListIterator;
|
import java.util.ListIterator;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
|
|
||||||
import static org.apache.hadoop.registry.client.impl.zk.ZookeeperConfigOptions.*;
|
import static org.apache.hadoop.registry.client.impl.zk.ZookeeperConfigOptions.*;
|
||||||
|
@ -798,65 +796,6 @@ public class RegistrySecurity extends AbstractService {
|
||||||
this.keytab = keytab;
|
this.keytab = keytab;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a programmatic version of a jaas.conf file. This can be used
|
|
||||||
* instead of writing a jaas.conf file and setting the system property,
|
|
||||||
* "java.security.auth.login.config", to point to that file. It is meant to be
|
|
||||||
* used for connecting to ZooKeeper.
|
|
||||||
*/
|
|
||||||
@InterfaceAudience.Private
|
|
||||||
public static class JaasConfiguration extends
|
|
||||||
javax.security.auth.login.Configuration {
|
|
||||||
|
|
||||||
private final javax.security.auth.login.Configuration baseConfig =
|
|
||||||
javax.security.auth.login.Configuration.getConfiguration();
|
|
||||||
private static AppConfigurationEntry[] entry;
|
|
||||||
private String entryName;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add an entry to the jaas configuration with the passed in name,
|
|
||||||
* principal, and keytab. The other necessary options will be set for you.
|
|
||||||
*
|
|
||||||
* @param entryName The name of the entry (e.g. "Client")
|
|
||||||
* @param principal The principal of the user
|
|
||||||
* @param keytab The location of the keytab
|
|
||||||
*/
|
|
||||||
public JaasConfiguration(String entryName, String principal, String keytab) {
|
|
||||||
this.entryName = entryName;
|
|
||||||
Map<String, String> options = new HashMap<String, String>();
|
|
||||||
options.put("keyTab", keytab);
|
|
||||||
options.put("principal", principal);
|
|
||||||
options.put("useKeyTab", "true");
|
|
||||||
options.put("storeKey", "true");
|
|
||||||
options.put("useTicketCache", "false");
|
|
||||||
options.put("refreshKrb5Config", "true");
|
|
||||||
String jaasEnvVar = System.getenv("HADOOP_JAAS_DEBUG");
|
|
||||||
if (jaasEnvVar != null && "true".equalsIgnoreCase(jaasEnvVar)) {
|
|
||||||
options.put("debug", "true");
|
|
||||||
}
|
|
||||||
entry = new AppConfigurationEntry[]{
|
|
||||||
new AppConfigurationEntry(getKrb5LoginModuleName(),
|
|
||||||
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
|
|
||||||
options)};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
|
|
||||||
return (entryName.equals(name)) ? entry : ((baseConfig != null)
|
|
||||||
? baseConfig.getAppConfigurationEntry(name) : null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getKrb5LoginModuleName() {
|
|
||||||
String krb5LoginModuleName;
|
|
||||||
if (System.getProperty("java.vendor").contains("IBM")) {
|
|
||||||
krb5LoginModuleName = "com.ibm.security.auth.module.Krb5LoginModule";
|
|
||||||
} else {
|
|
||||||
krb5LoginModuleName = "com.sun.security.auth.module.Krb5LoginModule";
|
|
||||||
}
|
|
||||||
return krb5LoginModuleName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the client properties. This forces the ZK client into
|
* Set the client properties. This forces the ZK client into
|
||||||
* failing if it can't auth.
|
* failing if it can't auth.
|
||||||
|
|
Loading…
Reference in New Issue