mirror of https://github.com/apache/nifi.git
NIFI-2325:
- Adding support for LDAPS. This closes #1275. Signed-off-by: Andy LoPresto <alopresto@apache.org>
This commit is contained in:
parent
316cae16d3
commit
c5ef076786
|
@ -307,17 +307,17 @@ nifi.security.user.login.identity.provider=ldap-provider
|
|||
[options="header,footer"]
|
||||
|==================================================================================================================================================
|
||||
| Property Name | Description
|
||||
|`Authentication Strategy` | How the connection to the LDAP server is authenticated. Possible values are ANONYMOUS, SIMPLE, or START_TLS.
|
||||
|`Authentication Strategy` | How the connection to the LDAP server is authenticated. Possible values are ANONYMOUS, SIMPLE, LDAPS, or START_TLS.
|
||||
|`Manager DN` | The DN of the manager that is used to bind to the LDAP server to search for users.
|
||||
|`Manager Password` | The password of the manager that is used to bind to the LDAP server to search for users.
|
||||
|`TLS - Keystore` | Path to the Keystore that is used when connecting to LDAP using START_TLS.
|
||||
|`TLS - Keystore Password` | Password for the Keystore that is used when connecting to LDAP using START_TLS.
|
||||
|`TLS - Keystore Type` | Type of the Keystore that is used when connecting to LDAP using START_TLS (i.e. JKS or PKCS12).
|
||||
|`TLS - Truststore` | Path to the Truststore that is used when connecting to LDAP using START_TLS.
|
||||
|`TLS - Truststore Password` | Password for the Truststore that is used when connecting to LDAP using START_TLS.
|
||||
|`TLS - Truststore Type` | Type of the Truststore that is used when connecting to LDAP using START_TLS (i.e. JKS or PKCS12).
|
||||
|`TLS - Client Auth` | Client authentication policy when connecting to LDAP using START_TLS. Possible values are REQUIRED, WANT, NONE.
|
||||
|`TLS - Protocol` | Protocol to use when connecting to LDAP using START_TLS. (i.e. TLS, TLSv1.1, TLSv1.2, etc).
|
||||
|`TLS - Keystore` | Path to the Keystore that is used when connecting to LDAP using LDAPS or START_TLS.
|
||||
|`TLS - Keystore Password` | Password for the Keystore that is used when connecting to LDAP using LDAPS or START_TLS.
|
||||
|`TLS - Keystore Type` | Type of the Keystore that is used when connecting to LDAP using LDAPS or START_TLS (i.e. JKS or PKCS12).
|
||||
|`TLS - Truststore` | Path to the Truststore that is used when connecting to LDAP using LDAPS or START_TLS.
|
||||
|`TLS - Truststore Password` | Password for the Truststore that is used when connecting to LDAP using LDAPS or START_TLS.
|
||||
|`TLS - Truststore Type` | Type of the Truststore that is used when connecting to LDAP using LDAPS or START_TLS (i.e. JKS or PKCS12).
|
||||
|`TLS - Client Auth` | Client authentication policy when connecting to LDAP using LDAPS or START_TLS. Possible values are REQUIRED, WANT, NONE.
|
||||
|`TLS - Protocol` | Protocol to use when connecting to LDAP using LDAPS or START_TLS. (i.e. TLS, TLSv1.1, TLSv1.2, etc).
|
||||
|`TLS - Shutdown Gracefully` | Specifies whether the TLS should be shut down gracefully before the target context is closed. Defaults to false.
|
||||
|`Referral Strategy` | Strategy for handling referrals. Possible values are FOLLOW, IGNORE, THROW.
|
||||
|`Connect Timeout` | Duration of connect timeout. (i.e. 10 secs).
|
||||
|
|
|
@ -23,25 +23,25 @@
|
|||
Identity Provider for users logging in with username/password against an LDAP server.
|
||||
|
||||
'Authentication Strategy' - How the connection to the LDAP server is authenticated. Possible
|
||||
values are ANONYMOUS, SIMPLE, or START_TLS.
|
||||
values are ANONYMOUS, SIMPLE, LDAPS, or START_TLS.
|
||||
|
||||
'Manager DN' - The DN of the manager that is used to bind to the LDAP server to search for users.
|
||||
'Manager Password' - The password of the manager that is used to bind to the LDAP server to
|
||||
search for users.
|
||||
|
||||
'TLS - Keystore' - Path to the Keystore that is used when connecting to LDAP using START_TLS.
|
||||
'TLS - Keystore' - Path to the Keystore that is used when connecting to LDAP using LDAPS or START_TLS.
|
||||
'TLS - Keystore Password' - Password for the Keystore that is used when connecting to LDAP
|
||||
using START_TLS.
|
||||
using LDAPS or START_TLS.
|
||||
'TLS - Keystore Type' - Type of the Keystore that is used when connecting to LDAP using
|
||||
START_TLS (i.e. JKS or PKCS12).
|
||||
'TLS - Truststore' - Path to the Truststore that is used when connecting to LDAP using START_TLS.
|
||||
LDAPS or START_TLS (i.e. JKS or PKCS12).
|
||||
'TLS - Truststore' - Path to the Truststore that is used when connecting to LDAP using LDAPS or START_TLS.
|
||||
'TLS - Truststore Password' - Password for the Truststore that is used when connecting to
|
||||
LDAP using START_TLS.
|
||||
LDAP using LDAPS or START_TLS.
|
||||
'TLS - Truststore Type' - Type of the Truststore that is used when connecting to LDAP using
|
||||
START_TLS (i.e. JKS or PKCS12).
|
||||
'TLS - Client Auth' - Client authentication policy when connecting to LDAP using START_TLS.
|
||||
LDAPS or START_TLS (i.e. JKS or PKCS12).
|
||||
'TLS - Client Auth' - Client authentication policy when connecting to LDAP using LDAPS or START_TLS.
|
||||
Possible values are REQUIRED, WANT, NONE.
|
||||
'TLS - Protocol' - Protocol to use when connecting to LDAP using START_TLS. (i.e. TLS,
|
||||
'TLS - Protocol' - Protocol to use when connecting to LDAP using LDAPS or START_TLS. (i.e. TLS,
|
||||
TLSv1.1, TLSv1.2, etc).
|
||||
'TLS - Shutdown Gracefully' - Specifies whether the TLS should be shut down gracefully
|
||||
before the target context is closed. Defaults to false.
|
||||
|
|
|
@ -23,5 +23,6 @@ public enum LdapAuthenticationStrategy {
|
|||
|
||||
ANONYMOUS,
|
||||
SIMPLE,
|
||||
LDAPS,
|
||||
START_TLS
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ import org.springframework.security.ldap.search.FilterBasedLdapUserSearch;
|
|||
import org.springframework.security.ldap.search.LdapUserSearch;
|
||||
import org.springframework.security.ldap.userdetails.LdapUserDetails;
|
||||
|
||||
import javax.naming.Context;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import java.io.IOException;
|
||||
import java.security.KeyManagementException;
|
||||
|
@ -96,11 +97,6 @@ public class LdapProvider implements LoginIdentityProvider {
|
|||
setTimeout(configurationContext, baseEnvironment, "Connect Timeout", "com.sun.jndi.ldap.connect.timeout");
|
||||
setTimeout(configurationContext, baseEnvironment, "Read Timeout", "com.sun.jndi.ldap.read.timeout");
|
||||
|
||||
// set the base environment is necessary
|
||||
if (!baseEnvironment.isEmpty()) {
|
||||
context.setBaseEnvironmentProperties(baseEnvironment);
|
||||
}
|
||||
|
||||
// authentication strategy
|
||||
final String rawAuthenticationStrategy = configurationContext.getProperty("Authentication Strategy");
|
||||
final LdapAuthenticationStrategy authenticationStrategy;
|
||||
|
@ -126,6 +122,20 @@ public class LdapProvider implements LoginIdentityProvider {
|
|||
case SIMPLE:
|
||||
context.setAuthenticationStrategy(new SimpleDirContextAuthenticationStrategy());
|
||||
break;
|
||||
case LDAPS:
|
||||
context.setAuthenticationStrategy(new SimpleDirContextAuthenticationStrategy());
|
||||
|
||||
// indicate a secure connection
|
||||
baseEnvironment.put(Context.SECURITY_PROTOCOL, "ssl");
|
||||
|
||||
// get the configured ssl context
|
||||
final SSLContext ldapsSslContext = getConfiguredSslContext(configurationContext);
|
||||
if (ldapsSslContext != null) {
|
||||
// initialize the ldaps socket factory prior to use
|
||||
LdapsSocketFactory.initialize(ldapsSslContext.getSocketFactory());
|
||||
baseEnvironment.put("java.naming.ldap.factory.socket", LdapsSocketFactory.class.getName());
|
||||
}
|
||||
break;
|
||||
case START_TLS:
|
||||
final AbstractTlsDirContextAuthenticationStrategy tlsAuthenticationStrategy = new DefaultTlsDirContextAuthenticationStrategy();
|
||||
|
||||
|
@ -136,49 +146,13 @@ public class LdapProvider implements LoginIdentityProvider {
|
|||
tlsAuthenticationStrategy.setShutdownTlsGracefully(shutdownGracefully);
|
||||
}
|
||||
|
||||
final String rawKeystore = configurationContext.getProperty("TLS - Keystore");
|
||||
final String rawKeystorePassword = configurationContext.getProperty("TLS - Keystore Password");
|
||||
final String rawKeystoreType = configurationContext.getProperty("TLS - Keystore Type");
|
||||
final String rawTruststore = configurationContext.getProperty("TLS - Truststore");
|
||||
final String rawTruststorePassword = configurationContext.getProperty("TLS - Truststore Password");
|
||||
final String rawTruststoreType = configurationContext.getProperty("TLS - Truststore Type");
|
||||
final String rawClientAuth = configurationContext.getProperty("TLS - Client Auth");
|
||||
final String rawProtocol = configurationContext.getProperty("TLS - Protocol");
|
||||
|
||||
final ClientAuth clientAuth;
|
||||
if (StringUtils.isBlank(rawClientAuth)) {
|
||||
clientAuth = ClientAuth.NONE;
|
||||
} else {
|
||||
try {
|
||||
clientAuth = ClientAuth.valueOf(rawClientAuth);
|
||||
} catch (final IllegalArgumentException iae) {
|
||||
throw new ProviderCreationException(String.format("Unrecognized client auth '%s'. Possible values are [%s]",
|
||||
rawClientAuth, StringUtils.join(ClientAuth.values(), ", ")));
|
||||
}
|
||||
}
|
||||
|
||||
// ensure the protocol is specified
|
||||
if (StringUtils.isBlank(rawProtocol)) {
|
||||
throw new ProviderCreationException("TLS - Protocol must be specified.");
|
||||
}
|
||||
|
||||
try {
|
||||
final SSLContext sslContext;
|
||||
if (StringUtils.isBlank(rawKeystore)) {
|
||||
sslContext = SslContextFactory.createTrustSslContext(rawTruststore, rawTruststorePassword.toCharArray(), rawTruststoreType, rawProtocol);
|
||||
} else {
|
||||
if (StringUtils.isBlank(rawTruststore)) {
|
||||
sslContext = SslContextFactory.createSslContext(rawKeystore, rawKeystorePassword.toCharArray(), rawKeystoreType, rawProtocol);
|
||||
} else {
|
||||
sslContext = SslContextFactory.createSslContext(rawKeystore, rawKeystorePassword.toCharArray(), rawKeystoreType,
|
||||
rawTruststore, rawTruststorePassword.toCharArray(), rawTruststoreType, clientAuth, rawProtocol);
|
||||
}
|
||||
}
|
||||
tlsAuthenticationStrategy.setSslSocketFactory(sslContext.getSocketFactory());
|
||||
} catch (final KeyStoreException | NoSuchAlgorithmException | CertificateException | UnrecoverableKeyException | KeyManagementException | IOException e) {
|
||||
throw new ProviderCreationException(e.getMessage(), e);
|
||||
// get the configured ssl context
|
||||
final SSLContext startTlsSslContext = getConfiguredSslContext(configurationContext);
|
||||
if (startTlsSslContext != null) {
|
||||
tlsAuthenticationStrategy.setSslSocketFactory(startTlsSslContext.getSocketFactory());
|
||||
}
|
||||
|
||||
// set the authentication strategy
|
||||
context.setAuthenticationStrategy(tlsAuthenticationStrategy);
|
||||
break;
|
||||
}
|
||||
|
@ -241,6 +215,11 @@ public class LdapProvider implements LoginIdentityProvider {
|
|||
}
|
||||
}
|
||||
|
||||
// set the base environment is necessary
|
||||
if (!baseEnvironment.isEmpty()) {
|
||||
context.setBaseEnvironmentProperties(baseEnvironment);
|
||||
}
|
||||
|
||||
try {
|
||||
// handling initializing beans
|
||||
context.afterPropertiesSet();
|
||||
|
@ -269,6 +248,56 @@ public class LdapProvider implements LoginIdentityProvider {
|
|||
}
|
||||
}
|
||||
|
||||
private SSLContext getConfiguredSslContext(final LoginIdentityProviderConfigurationContext configurationContext) {
|
||||
final String rawKeystore = configurationContext.getProperty("TLS - Keystore");
|
||||
final String rawKeystorePassword = configurationContext.getProperty("TLS - Keystore Password");
|
||||
final String rawKeystoreType = configurationContext.getProperty("TLS - Keystore Type");
|
||||
final String rawTruststore = configurationContext.getProperty("TLS - Truststore");
|
||||
final String rawTruststorePassword = configurationContext.getProperty("TLS - Truststore Password");
|
||||
final String rawTruststoreType = configurationContext.getProperty("TLS - Truststore Type");
|
||||
final String rawClientAuth = configurationContext.getProperty("TLS - Client Auth");
|
||||
final String rawProtocol = configurationContext.getProperty("TLS - Protocol");
|
||||
|
||||
// create the ssl context
|
||||
final SSLContext sslContext;
|
||||
try {
|
||||
if (StringUtils.isBlank(rawKeystore) && StringUtils.isBlank(rawTruststore)) {
|
||||
sslContext = null;
|
||||
} else {
|
||||
// ensure the protocol is specified
|
||||
if (StringUtils.isBlank(rawProtocol)) {
|
||||
throw new ProviderCreationException("TLS - Protocol must be specified.");
|
||||
}
|
||||
|
||||
if (StringUtils.isBlank(rawKeystore)) {
|
||||
sslContext = SslContextFactory.createTrustSslContext(rawTruststore, rawTruststorePassword.toCharArray(), rawTruststoreType, rawProtocol);
|
||||
} else if (StringUtils.isBlank(rawTruststore)) {
|
||||
sslContext = SslContextFactory.createSslContext(rawKeystore, rawKeystorePassword.toCharArray(), rawKeystoreType, rawProtocol);
|
||||
} else {
|
||||
// determine the client auth if specified
|
||||
final ClientAuth clientAuth;
|
||||
if (StringUtils.isBlank(rawClientAuth)) {
|
||||
clientAuth = ClientAuth.NONE;
|
||||
} else {
|
||||
try {
|
||||
clientAuth = ClientAuth.valueOf(rawClientAuth);
|
||||
} catch (final IllegalArgumentException iae) {
|
||||
throw new ProviderCreationException(String.format("Unrecognized client auth '%s'. Possible values are [%s]",
|
||||
rawClientAuth, StringUtils.join(ClientAuth.values(), ", ")));
|
||||
}
|
||||
}
|
||||
|
||||
sslContext = SslContextFactory.createSslContext(rawKeystore, rawKeystorePassword.toCharArray(), rawKeystoreType,
|
||||
rawTruststore, rawTruststorePassword.toCharArray(), rawTruststoreType, clientAuth, rawProtocol);
|
||||
}
|
||||
}
|
||||
} catch (final KeyStoreException | NoSuchAlgorithmException | CertificateException | UnrecoverableKeyException | KeyManagementException | IOException e) {
|
||||
throw new ProviderCreationException(e.getMessage(), e);
|
||||
}
|
||||
|
||||
return sslContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final AuthenticationResponse authenticate(final LoginCredentials credentials) throws InvalidLoginCredentialsException, IdentityAccessException {
|
||||
if (provider == null) {
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.
|
||||
*/
|
||||
package org.apache.nifi.ldap;
|
||||
|
||||
import javax.net.SocketFactory;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
/**
|
||||
* SSLSocketFactory used when connecting to a Directory Server over LDAPS.
|
||||
*/
|
||||
public class LdapsSocketFactory extends SSLSocketFactory {
|
||||
|
||||
// singleton
|
||||
private static LdapsSocketFactory instance;
|
||||
|
||||
// delegate
|
||||
private SSLSocketFactory delegate;
|
||||
|
||||
/**
|
||||
* Initializes the LdapsSocketFactory with the specified SSLSocketFactory. The specified
|
||||
* socket factory will be used as a delegate for all subsequent instances of this class.
|
||||
*
|
||||
* @param sslSocketFactory delegate socket factory
|
||||
*/
|
||||
public static void initialize(final SSLSocketFactory sslSocketFactory) {
|
||||
instance = new LdapsSocketFactory(sslSocketFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the LdapsSocketFactory that was previously initialized.
|
||||
*
|
||||
* @return socket factory
|
||||
*/
|
||||
public static SocketFactory getDefault() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new LdapsSocketFactory.
|
||||
*
|
||||
* @param sslSocketFactory delegate socket factory
|
||||
*/
|
||||
private LdapsSocketFactory(final SSLSocketFactory sslSocketFactory) {
|
||||
delegate = sslSocketFactory;
|
||||
}
|
||||
|
||||
// delegate methods
|
||||
|
||||
@Override
|
||||
public String[] getSupportedCipherSuites() {
|
||||
return delegate.getSupportedCipherSuites();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getDefaultCipherSuites() {
|
||||
return delegate.getDefaultCipherSuites();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(Socket socket, String string, int i, boolean bln) throws IOException {
|
||||
return delegate.createSocket(socket, string, i, bln);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(InetAddress ia, int i, InetAddress ia1, int i1) throws IOException {
|
||||
return delegate.createSocket(ia, i, ia1, i1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(InetAddress ia, int i) throws IOException {
|
||||
return delegate.createSocket(ia, i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(String string, int i, InetAddress ia, int i1) throws IOException, UnknownHostException {
|
||||
return delegate.createSocket(string, i, ia, i1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(String string, int i) throws IOException, UnknownHostException {
|
||||
return delegate.createSocket(string, i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket() throws IOException {
|
||||
return delegate.createSocket();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue