From a4f1292a53da3c0bbb75de459bc141ef722dd148 Mon Sep 17 00:00:00 2001 From: Brandon Li Date: Tue, 5 Aug 2014 23:55:30 +0000 Subject: [PATCH] HADOOP-10905. LdapGroupsMapping Should use configuration.getPassword for SSL and LDAP Passwords. Contributed by Larry McCay git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1616054 13f79535-47bb-0310-9956-ffa450edef68 --- .../hadoop-common/CHANGES.txt | 3 + .../hadoop/security/LdapGroupsMapping.java | 26 +++++++-- .../security/TestLdapGroupsMapping.java | 58 +++++++++++++++++++ 3 files changed, 83 insertions(+), 4 deletions(-) diff --git a/hadoop-common-project/hadoop-common/CHANGES.txt b/hadoop-common-project/hadoop-common/CHANGES.txt index 1b6964e4e6..bef2f76510 100644 --- a/hadoop-common-project/hadoop-common/CHANGES.txt +++ b/hadoop-common-project/hadoop-common/CHANGES.txt @@ -540,6 +540,9 @@ Release 2.6.0 - UNRELEASED HADOOP-10759. Remove hardcoded JAVA_HEAP_MAX. (Sam Liu via Eric Yang) + HADOOP-10905. LdapGroupsMapping Should use configuration.getPassword for SSL + and LDAP Passwords. (lmccay via brandonli) + Release 2.5.0 - UNRELEASED INCOMPATIBLE CHANGES diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/LdapGroupsMapping.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/LdapGroupsMapping.java index d92c469e5a..76f53804b3 100644 --- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/LdapGroupsMapping.java +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/LdapGroupsMapping.java @@ -312,15 +312,15 @@ public synchronized void setConf(Configuration conf) { useSsl = conf.getBoolean(LDAP_USE_SSL_KEY, LDAP_USE_SSL_DEFAULT); keystore = conf.get(LDAP_KEYSTORE_KEY, LDAP_KEYSTORE_DEFAULT); - keystorePass = - conf.get(LDAP_KEYSTORE_PASSWORD_KEY, LDAP_KEYSTORE_PASSWORD_DEFAULT); + keystorePass = getPassword(conf, LDAP_KEYSTORE_PASSWORD_KEY, + LDAP_KEYSTORE_PASSWORD_DEFAULT); if (keystorePass.isEmpty()) { keystorePass = extractPassword(conf.get(LDAP_KEYSTORE_PASSWORD_FILE_KEY, LDAP_KEYSTORE_PASSWORD_FILE_DEFAULT)); } bindUser = conf.get(BIND_USER_KEY, BIND_USER_DEFAULT); - bindPassword = conf.get(BIND_PASSWORD_KEY, BIND_PASSWORD_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)); @@ -341,7 +341,25 @@ public synchronized void setConf(Configuration conf) { this.conf = conf; } - + + String getPassword(Configuration conf, String alias, String defaultPass) { + String password = null; + try { + char[] passchars = conf.getPassword(alias); + if (passchars != null) { + password = new String(passchars); + } + else { + password = defaultPass; + } + } + catch (IOException ioe) { + LOG.warn("Exception while trying to password for alias " + alias + ": " + + ioe.getMessage()); + } + return password; + } + String extractPassword(String pwFile) { if (pwFile.isEmpty()) { // If there is no password file defined, we'll assume that we should do diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/TestLdapGroupsMapping.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/TestLdapGroupsMapping.java index 331e288e8b..95cbc0ae20 100644 --- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/TestLdapGroupsMapping.java +++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/TestLdapGroupsMapping.java @@ -17,6 +17,8 @@ */ package org.apache.hadoop.security; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.*; import java.io.File; @@ -38,6 +40,9 @@ import javax.naming.directory.SearchResult; import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.security.alias.CredentialProvider; +import org.apache.hadoop.security.alias.CredentialProviderFactory; +import org.apache.hadoop.security.alias.JavaKeyStoreProvider; import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -154,4 +159,57 @@ public void testExtractPassword() throws IOException { Assert.assertEquals("hadoop", mapping.extractPassword(secretFile.getPath())); } + + @Test + public void testConfGetPassword() throws Exception { + File testDir = new File(System.getProperty("test.build.data", + "target/test-dir")); + Configuration conf = new Configuration(); + final String ourUrl = + JavaKeyStoreProvider.SCHEME_NAME + "://file/" + testDir + "/test.jks"; + + File file = new File(testDir, "test.jks"); + file.delete(); + conf.set(CredentialProviderFactory.CREDENTIAL_PROVIDER_PATH, ourUrl); + + CredentialProvider provider = + CredentialProviderFactory.getProviders(conf).get(0); + char[] bindpass = {'b', 'i', 'n', 'd', 'p', 'a', 's', 's'}; + char[] storepass = {'s', 't', 'o', 'r', 'e', 'p', 'a', 's', 's'}; + + // ensure that we get nulls when the key isn't there + assertEquals(null, provider.getCredentialEntry( + LdapGroupsMapping.BIND_PASSWORD_KEY)); + assertEquals(null, provider.getCredentialEntry + (LdapGroupsMapping.LDAP_KEYSTORE_PASSWORD_KEY)); + + // create new aliases + try { + provider.createCredentialEntry( + LdapGroupsMapping.BIND_PASSWORD_KEY, bindpass); + + provider.createCredentialEntry( + LdapGroupsMapping.LDAP_KEYSTORE_PASSWORD_KEY, storepass); + provider.flush(); + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + // make sure we get back the right key + assertArrayEquals(bindpass, provider.getCredentialEntry( + LdapGroupsMapping.BIND_PASSWORD_KEY).getCredential()); + assertArrayEquals(storepass, provider.getCredentialEntry( + LdapGroupsMapping.LDAP_KEYSTORE_PASSWORD_KEY).getCredential()); + + LdapGroupsMapping mapping = new LdapGroupsMapping(); + Assert.assertEquals("bindpass", + 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", "")); + } }