HADOOP-15995. Add ldap.bind.password.alias in LdapGroupsMapping to distinguish aliases when using multiple providers through CompositeGroupsMapping. Contributed by Lukas Majercak.

This commit is contained in:
Giovanni Matteo Fumarola 2018-12-12 11:10:24 -08:00
parent 82b798581d
commit 76efeacd5f
3 changed files with 68 additions and 7 deletions

View File

@ -149,6 +149,10 @@ public class LdapGroupsMapping
public static final String BIND_PASSWORD_FILE_KEY = BIND_PASSWORD_KEY + ".file";
public static final String BIND_PASSWORD_FILE_DEFAULT = "";
public static final String BIND_PASSWORD_ALIAS_KEY =
BIND_PASSWORD_KEY + ".alias";
public static final String BIND_PASSWORD_ALIAS_DEFAULT = "";
/*
* Base distinguished name to use for searches
*/
@ -662,12 +666,19 @@ public synchronized void setConf(Configuration conf) {
}
bindUser = conf.get(BIND_USER_KEY, BIND_USER_DEFAULT);
bindPassword = getPassword(conf, BIND_PASSWORD_KEY, BIND_PASSWORD_DEFAULT);
String alias = conf.get(BIND_PASSWORD_ALIAS_KEY,
BIND_PASSWORD_ALIAS_DEFAULT);
bindPassword = getPasswordFromCredentialProviders(conf, alias, "");
if (bindPassword.isEmpty()) {
bindPassword = extractPassword(
conf.get(BIND_PASSWORD_FILE_KEY, BIND_PASSWORD_FILE_DEFAULT));
bindPassword = getPassword(conf, BIND_PASSWORD_KEY,
BIND_PASSWORD_DEFAULT);
if (bindPassword.isEmpty()) {
bindPassword = extractPassword(
conf.get(BIND_PASSWORD_FILE_KEY, BIND_PASSWORD_FILE_DEFAULT));
}
}
String baseDN = conf.getTrimmed(BASE_DN_KEY, BASE_DN_DEFAULT);
// User search base which defaults to base dn.
@ -755,10 +766,10 @@ private void loadSslConf(Configuration sslConf) {
}
String getPasswordFromCredentialProviders(
Configuration conf, String alias, String defaultPass) {
Configuration config, String alias, String defaultPass) {
String password = defaultPass;
try {
char[] passchars = conf.getPasswordFromCredentialProviders(alias);
char[] passchars = config.getPasswordFromCredentialProviders(alias);
if (passchars != null) {
password = new String(passchars);
}

View File

@ -370,6 +370,16 @@
</description>
</property>
<property>
<name>hadoop.security.group.mapping.ldap.bind.password.alias</name>
<value></value>
<description>
The alias of the bind user to be used to get the password from credential
providers. If the alias is empty, property
hadoop.security.group.mapping.ldap.bind.password is used instead.
</description>
</property>
<property>
<name>hadoop.security.group.mapping.ldap.bind.password.file</name>
<value></value>

View File

@ -300,13 +300,53 @@ public void testConfGetPassword() throws Exception {
mapping.getPassword(conf, LdapGroupsMapping.BIND_PASSWORD_KEY, ""));
Assert.assertEquals("storepass",
mapping.getPassword(conf, LdapGroupsMapping.LDAP_KEYSTORE_PASSWORD_KEY,
""));
""));
// let's make sure that a password that doesn't exist returns an
// empty string as currently expected and used to trigger a call to
// extract password
Assert.assertEquals("", mapping.getPassword(conf,"invalid-alias", ""));
}
@Test
public void testConfGetPasswordUsingAlias() throws Exception {
File testDir = GenericTestUtils.getTestDir();
Configuration conf = getBaseConf();
final Path jksPath = new Path(testDir.toString(), "test.jks");
final String ourUrl =
JavaKeyStoreProvider.SCHEME_NAME + "://file" + jksPath.toUri();
File file = new File(testDir, "test.jks");
file.delete();
conf.set(CredentialProviderFactory.CREDENTIAL_PROVIDER_PATH, ourUrl);
// Set alias
String bindpassAlias = "bindpassAlias";
conf.set(LdapGroupsMapping.BIND_PASSWORD_ALIAS_KEY, bindpassAlias);
CredentialProvider provider =
CredentialProviderFactory.getProviders(conf).get(0);
char[] bindpass = "bindpass".toCharArray();
// Ensure that we get null when the key isn't there
assertNull(provider.getCredentialEntry(bindpassAlias));
// Create credential for the alias
provider.createCredentialEntry(bindpassAlias, bindpass);
provider.flush();
// Make sure we get back the right key
assertArrayEquals(bindpass, provider.getCredentialEntry(
bindpassAlias).getCredential());
LdapGroupsMapping mapping = new LdapGroupsMapping();
Assert.assertEquals("bindpass",
mapping.getPasswordFromCredentialProviders(conf, bindpassAlias, ""));
// Empty for an invalid alias
Assert.assertEquals("", mapping.getPasswordFromCredentialProviders(
conf, "invalid-alias", ""));
}
/**
* Test that if the {@link LdapGroupsMapping#CONNECTION_TIMEOUT} is set in the
* configuration, the LdapGroupsMapping connection will timeout by this value