HADOOP-12862. LDAP Group Mapping over SSL can not specify trust store. Contributed by Wei-Chiu Chuang and Konstantin Shvachko.
(cherry picked from commit 2216bde322
)
This commit is contained in:
parent
2960592c6f
commit
99b5b9dce1
|
@ -2332,7 +2332,7 @@ public class Configuration implements Iterable<Map.Entry<String,String>>,
|
|||
* @return password or null if not found
|
||||
* @throws IOException
|
||||
*/
|
||||
protected char[] getPasswordFromCredentialProviders(String name)
|
||||
public char[] getPasswordFromCredentialProviders(String name)
|
||||
throws IOException {
|
||||
char[] pass = null;
|
||||
try {
|
||||
|
|
|
@ -109,6 +109,27 @@ public class LdapGroupsMapping
|
|||
public static final String LDAP_KEYSTORE_PASSWORD_FILE_KEY = LDAP_KEYSTORE_PASSWORD_KEY + ".file";
|
||||
public static final String LDAP_KEYSTORE_PASSWORD_FILE_DEFAULT = "";
|
||||
|
||||
|
||||
/**
|
||||
* File path to the location of the SSL truststore to use
|
||||
*/
|
||||
public static final String LDAP_TRUSTSTORE_KEY = LDAP_CONFIG_PREFIX +
|
||||
".ssl.truststore";
|
||||
|
||||
/**
|
||||
* The key of the credential entry containing the password for
|
||||
* the LDAP SSL truststore
|
||||
*/
|
||||
public static final String LDAP_TRUSTSTORE_PASSWORD_KEY =
|
||||
LDAP_CONFIG_PREFIX +".ssl.truststore.password";
|
||||
|
||||
/**
|
||||
* The path to a file containing the password for
|
||||
* the LDAP SSL truststore
|
||||
*/
|
||||
public static final String LDAP_TRUSTSTORE_PASSWORD_FILE_KEY =
|
||||
LDAP_TRUSTSTORE_PASSWORD_KEY + ".file";
|
||||
|
||||
/*
|
||||
* User to bind to the LDAP server with
|
||||
*/
|
||||
|
@ -226,6 +247,8 @@ public class LdapGroupsMapping
|
|||
private boolean useSsl;
|
||||
private String keystore;
|
||||
private String keystorePass;
|
||||
private String truststore;
|
||||
private String truststorePass;
|
||||
private String bindUser;
|
||||
private String bindPassword;
|
||||
private String userbaseDN;
|
||||
|
@ -526,8 +549,19 @@ public class LdapGroupsMapping
|
|||
// Set up SSL security, if necessary
|
||||
if (useSsl) {
|
||||
env.put(Context.SECURITY_PROTOCOL, "ssl");
|
||||
System.setProperty("javax.net.ssl.keyStore", keystore);
|
||||
System.setProperty("javax.net.ssl.keyStorePassword", keystorePass);
|
||||
if (!keystore.isEmpty()) {
|
||||
System.setProperty("javax.net.ssl.keyStore", keystore);
|
||||
}
|
||||
if (!keystorePass.isEmpty()) {
|
||||
System.setProperty("javax.net.ssl.keyStorePassword", keystorePass);
|
||||
}
|
||||
if (!truststore.isEmpty()) {
|
||||
System.setProperty("javax.net.ssl.trustStore", truststore);
|
||||
}
|
||||
if (!truststorePass.isEmpty()) {
|
||||
System.setProperty("javax.net.ssl.trustStorePassword",
|
||||
truststorePass);
|
||||
}
|
||||
}
|
||||
|
||||
env.put(Context.SECURITY_PRINCIPAL, bindUser);
|
||||
|
@ -572,15 +606,10 @@ public class LdapGroupsMapping
|
|||
if (ldapUrl == null || ldapUrl.isEmpty()) {
|
||||
throw new RuntimeException("LDAP URL is not configured");
|
||||
}
|
||||
|
||||
|
||||
useSsl = conf.getBoolean(LDAP_USE_SSL_KEY, LDAP_USE_SSL_DEFAULT);
|
||||
keystore = conf.get(LDAP_KEYSTORE_KEY, LDAP_KEYSTORE_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));
|
||||
if (useSsl) {
|
||||
loadSslConf(conf);
|
||||
}
|
||||
|
||||
bindUser = conf.get(BIND_USER_KEY, BIND_USER_DEFAULT);
|
||||
|
@ -643,6 +672,47 @@ public class LdapGroupsMapping
|
|||
this.conf = conf;
|
||||
}
|
||||
|
||||
private void loadSslConf(Configuration sslConf) {
|
||||
keystore = sslConf.get(LDAP_KEYSTORE_KEY, LDAP_KEYSTORE_DEFAULT);
|
||||
keystorePass = getPassword(sslConf, LDAP_KEYSTORE_PASSWORD_KEY,
|
||||
LDAP_KEYSTORE_PASSWORD_DEFAULT);
|
||||
if (keystorePass.isEmpty()) {
|
||||
keystorePass = extractPassword(sslConf.get(
|
||||
LDAP_KEYSTORE_PASSWORD_FILE_KEY,
|
||||
LDAP_KEYSTORE_PASSWORD_FILE_DEFAULT));
|
||||
}
|
||||
|
||||
truststore = sslConf.get(LDAP_TRUSTSTORE_KEY, "");
|
||||
truststorePass = getPasswordFromCredentialProviders(
|
||||
sslConf, LDAP_TRUSTSTORE_PASSWORD_KEY, "");
|
||||
if (truststorePass.isEmpty()) {
|
||||
truststorePass = extractPassword(
|
||||
sslConf.get(LDAP_TRUSTSTORE_PASSWORD_FILE_KEY, ""));
|
||||
}
|
||||
}
|
||||
|
||||
String getPasswordFromCredentialProviders(
|
||||
Configuration conf, String alias, String defaultPass) {
|
||||
String password = defaultPass;
|
||||
try {
|
||||
char[] passchars = conf.getPasswordFromCredentialProviders(alias);
|
||||
if (passchars != null) {
|
||||
password = new String(passchars);
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
LOG.warn("Exception while trying to get password for alias {}: {}",
|
||||
alias, ioe);
|
||||
}
|
||||
return password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Passwords should not be stored in configuration. Use
|
||||
* {@link #getPasswordFromCredentialProviders(
|
||||
* Configuration, String, String)}
|
||||
* to avoid reading passwords from a configuration file.
|
||||
*/
|
||||
@Deprecated
|
||||
String getPassword(Configuration conf, String alias, String defaultPass) {
|
||||
String password = defaultPass;
|
||||
try {
|
||||
|
|
|
@ -316,6 +316,27 @@
|
|||
</description>
|
||||
</property>
|
||||
|
||||
<property>
|
||||
<name>hadoop.security.group.mapping.ldap.ssl.truststore</name>
|
||||
<value></value>
|
||||
<description>
|
||||
File path to the SSL truststore that contains the root certificate used to
|
||||
sign the LDAP server's certificate. Specify this if the LDAP server's
|
||||
certificate is not signed by a well known certificate authority.
|
||||
</description>
|
||||
</property>
|
||||
|
||||
<property>
|
||||
<name>hadoop.security.group.mapping.ldap.ssl.truststore.password.file</name>
|
||||
<value></value>
|
||||
<description>
|
||||
The path to a file containing the password of the LDAP SSL truststore.
|
||||
|
||||
IMPORTANT: This file should be readable only by the Unix user running
|
||||
the daemons.
|
||||
</description>
|
||||
</property>
|
||||
|
||||
<property>
|
||||
<name>hadoop.security.group.mapping.ldap.bind.user</name>
|
||||
<value></value>
|
||||
|
|
|
@ -112,6 +112,9 @@ For some LDAP servers, such as Active Directory, the user object returned in the
|
|||
Therefore, it is possible to infer the user's groups from the first query without sending the second one, and it may reduce group name resolution latency incurred by the second query. If it fails to get group names, it will fall back to the typical two-query scenario and send the second query to get group names.
|
||||
To enable this feature, set `hadoop.security.group.mapping.ldap.search.attr.memberof` to `memberOf`, and Hadoop will resolve group names using this attribute in the user object.
|
||||
|
||||
If the LDAP server's certificate is not signed by a well known certificate authority, specify the path to the truststore in `hadoop.security.group.mapping.ldap.ssl.truststore`.
|
||||
Similar to keystore, specify the truststore password file in `hadoop.security.group.mapping.ldap.ssl.truststore.password.file`.
|
||||
|
||||
Composite Groups Mapping
|
||||
--------
|
||||
`CompositeGroupsMapping` works by enumerating a list of service providers in `hadoop.security.group.mapping.providers`.
|
||||
|
|
Loading…
Reference in New Issue