http://git-wip-us.apache.org/repos/asf/nifi/blob/aaf14c45/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-storage.js ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-storage.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-storage.js new file mode 100644 index 0000000..7b0c3f6 --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-storage.js @@ -0,0 +1,172 @@ +/* + * 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. + */ + +/* global nf, d3 */ + +nf.Storage = (function () { + + // Store items for two days before being eligible for removal. + var TWO_DAYS = nf.Common.MILLIS_PER_DAY * 2; + + /** + * Checks the expiration for the specified entry. + * + * @param {object} entry + * @returns {boolean} + */ + var checkExpiration = function (entry) { + if (nf.Common.isDefinedAndNotNull(entry.expires)) { + // get the expiration + var expires = new Date(entry.expires); + var now = new Date(); + + // return whether the expiration date has passed + return expires.valueOf() < now.valueOf(); + } else { + return false; + } + }; + + /** + * Gets an enty for the key. The entry expiration is not checked. + * + * @param {string} key + */ + var getEntry = function (key) { + try { + // parse the entry + var entry = JSON.parse(localStorage.getItem(key)); + + // ensure the entry and item are present + if (nf.Common.isDefinedAndNotNull(entry)) { + return entry; + } else { + return null; + } + } catch (e) { + return null; + } + }; + + return { + /** + * Initializes the storage. Items will be persisted for two days. Once the scripts runs + * thereafter, all eligible items will be removed. This strategy does not support persistence. + */ + init: function () { + for (var i = 0; i < localStorage.length; i++) { + try { + // get the next item + var key = localStorage.key(i); + + // attempt to get the item which will expire if necessary + nf.Storage.getItem(key); + } catch (e) { + } + } + }, + + /** + * Stores the specified item. + * + * @param {string} key + * @param {object} item + * @param {integer} expires + */ + setItem: function (key, item, expires) { + // calculate the expiration + expires = nf.Common.isDefinedAndNotNull(expires) ? expires : new Date().valueOf() + TWO_DAYS; + + // create the entry + var entry = { + expires: expires, + item: item + }; + + // store the item + localStorage.setItem(key, JSON.stringify(entry)); + }, + + /** + * Returns whether there is an entry for this key. This will not check the expiration. If + * the entry is expired, it will return null on a subsequent getItem invocation. + * + * @param {string} key + * @returns {boolean} + */ + hasItem: function (key) { + return getEntry(key) !== null; + }, + + /** + * Gets the item with the specified key. If an item with this key does + * not exist, null is returned. If an item exists but cannot be parsed + * or is malformed/unrecognized, null is returned. + * + * @param {type} key + */ + getItem: function (key) { + var entry = getEntry(key); + if (entry === null) { + return null; + } + + // if the entry is expired, drop it and return null + if (checkExpiration(entry)) { + nf.Storage.removeItem(key); + return null; + } + + // if the entry has the specified field return its value + if (nf.Common.isDefinedAndNotNull(entry['item'])) { + return entry['item']; + } else { + return null; + } + }, + + /** + * Gets the expiration for the specified item. This will not check the expiration. If + * the entry is expired, it will return null on a subsequent getItem invocation. + * + * @param {string} key + * @returns {integer} + */ + getItemExpiration: function (key) { + var entry = getEntry(key); + if (entry === null) { + return null; + } + + // if the entry has the specified field return its value + if (nf.Common.isDefinedAndNotNull(entry['expires'])) { + return entry['expires']; + } else { + return null; + } + }, + + /** + * Removes the item with the specified key. + * + * @param {type} key + */ + removeItem: function (key) { + localStorage.removeItem(key); + } + }; +}()); \ No newline at end of file
http://git-wip-us.apache.org/repos/asf/nifi/blob/aaf14c45/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance.js ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance.js index 0edbe08..876e06d 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance.js @@ -174,6 +174,8 @@ nf.Provenance = (function () { * Initializes the status page. */ init: function () { + nf.Storage.init(); + // load the users authorities and detect if the NiFi is clustered $.when(loadControllerConfig(), loadAuthorities(), detectedCluster()).done(function () { // create the provenance table http://git-wip-us.apache.org/repos/asf/nifi/blob/aaf14c45/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/summary/nf-summary.js ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/summary/nf-summary.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/summary/nf-summary.js index 97f8626..4f06662 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/summary/nf-summary.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/summary/nf-summary.js @@ -128,6 +128,8 @@ nf.Summary = (function () { * Initializes the status page. */ init: function () { + nf.Storage.init(); + // intialize the summary table initializeSummaryTable().done(function () { // load the table http://git-wip-us.apache.org/repos/asf/nifi/blob/aaf14c45/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/templates/nf-templates.js ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/templates/nf-templates.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/templates/nf-templates.js index b55bee2..678e352 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/templates/nf-templates.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/templates/nf-templates.js @@ -204,6 +204,8 @@ nf.Templates = (function () { * Initializes the templates page. */ init: function () { + nf.Storage.init(); + // load the users authorities loadAuthorities().done(function () { http://git-wip-us.apache.org/repos/asf/nifi/blob/aaf14c45/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/users/nf-users.js ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/users/nf-users.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/users/nf-users.js index 96f73a5..9364aec 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/users/nf-users.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/users/nf-users.js @@ -116,6 +116,8 @@ nf.Users = (function () { * Initializes the counters page. */ init: function () { + nf.Storage.init(); + // load the users authorities loadAuthorities().done(function () { // create the counters table http://git-wip-us.apache.org/repos/asf/nifi/blob/aaf14c45/nifi-nar-bundles/nifi-ldap-iaa-providers-bundle/nifi-ldap-iaa-providers-nar/pom.xml ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-ldap-iaa-providers-bundle/nifi-ldap-iaa-providers-nar/pom.xml b/nifi-nar-bundles/nifi-ldap-iaa-providers-bundle/nifi-ldap-iaa-providers-nar/pom.xml new file mode 100644 index 0000000..59681b9 --- /dev/null +++ b/nifi-nar-bundles/nifi-ldap-iaa-providers-bundle/nifi-ldap-iaa-providers-nar/pom.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.nifi</groupId> + <artifactId>nifi-ldap-iaa-providers-bundle</artifactId> + <version>0.3.1-SNAPSHOT</version> + </parent> + <artifactId>nifi-ldap-iaa-providers-nar</artifactId> + <packaging>nar</packaging> + <dependencies> + <dependency> + <groupId>org.apache.nifi</groupId> + <artifactId>nifi-ldap-iaa-providers</artifactId> + </dependency> + </dependencies> + <name>nifi-ldap-iaa-providers-nar</name> +</project> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/nifi/blob/aaf14c45/nifi-nar-bundles/nifi-ldap-iaa-providers-bundle/nifi-ldap-iaa-providers/pom.xml ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-ldap-iaa-providers-bundle/nifi-ldap-iaa-providers/pom.xml b/nifi-nar-bundles/nifi-ldap-iaa-providers-bundle/nifi-ldap-iaa-providers/pom.xml new file mode 100644 index 0000000..5cbd6f9 --- /dev/null +++ b/nifi-nar-bundles/nifi-ldap-iaa-providers-bundle/nifi-ldap-iaa-providers/pom.xml @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.nifi</groupId> + <artifactId>nifi-ldap-iaa-providers-bundle</artifactId> + <version>0.3.1-SNAPSHOT</version> + </parent> + <artifactId>nifi-ldap-iaa-providers</artifactId> + <packaging>jar</packaging> + <dependencies> + <dependency> + <groupId>org.apache.nifi</groupId> + <artifactId>nifi-api</artifactId> + </dependency> + <dependency> + <groupId>org.apache.nifi</groupId> + <artifactId>nifi-utils</artifactId> + </dependency> + <dependency> + <groupId>org.apache.nifi</groupId> + <artifactId>nifi-security-utils</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.security</groupId> + <artifactId>spring-security-ldap</artifactId> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-beans</artifactId> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-context</artifactId> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-tx</artifactId> + </dependency> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> + </dependency> + </dependencies> + <name>nifi-ldap-iaa-providers</name> +</project> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/nifi/blob/aaf14c45/nifi-nar-bundles/nifi-ldap-iaa-providers-bundle/nifi-ldap-iaa-providers/src/main/java/org/apache/nifi/ldap/LdapAuthenticationStrategy.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-ldap-iaa-providers-bundle/nifi-ldap-iaa-providers/src/main/java/org/apache/nifi/ldap/LdapAuthenticationStrategy.java b/nifi-nar-bundles/nifi-ldap-iaa-providers-bundle/nifi-ldap-iaa-providers/src/main/java/org/apache/nifi/ldap/LdapAuthenticationStrategy.java new file mode 100644 index 0000000..7124ce1 --- /dev/null +++ b/nifi-nar-bundles/nifi-ldap-iaa-providers-bundle/nifi-ldap-iaa-providers/src/main/java/org/apache/nifi/ldap/LdapAuthenticationStrategy.java @@ -0,0 +1,27 @@ +/* + * 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; + +/** + * + */ +public enum LdapAuthenticationStrategy { + + ANONYMOUS, + SIMPLE, + START_TLS +} http://git-wip-us.apache.org/repos/asf/nifi/blob/aaf14c45/nifi-nar-bundles/nifi-ldap-iaa-providers-bundle/nifi-ldap-iaa-providers/src/main/java/org/apache/nifi/ldap/LdapProvider.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-ldap-iaa-providers-bundle/nifi-ldap-iaa-providers/src/main/java/org/apache/nifi/ldap/LdapProvider.java b/nifi-nar-bundles/nifi-ldap-iaa-providers-bundle/nifi-ldap-iaa-providers/src/main/java/org/apache/nifi/ldap/LdapProvider.java new file mode 100644 index 0000000..4dc7ea4 --- /dev/null +++ b/nifi-nar-bundles/nifi-ldap-iaa-providers-bundle/nifi-ldap-iaa-providers/src/main/java/org/apache/nifi/ldap/LdapProvider.java @@ -0,0 +1,279 @@ +/* + * 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 java.io.IOException; +import java.security.KeyManagementException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import javax.net.ssl.SSLContext; +import org.apache.commons.lang3.StringUtils; +import org.apache.nifi.authentication.AuthenticationResponse; +import org.apache.nifi.authentication.LoginCredentials; +import org.apache.nifi.authentication.LoginIdentityProvider; +import org.apache.nifi.authentication.LoginIdentityProviderConfigurationContext; +import org.apache.nifi.authentication.LoginIdentityProviderInitializationContext; +import org.apache.nifi.authentication.exception.IdentityAccessException; +import org.apache.nifi.authentication.exception.InvalidLoginCredentialsException; +import org.apache.nifi.authorization.exception.ProviderCreationException; +import org.apache.nifi.authorization.exception.ProviderDestructionException; +import org.apache.nifi.security.util.SslContextFactory; +import org.apache.nifi.security.util.SslContextFactory.ClientAuth; +import org.apache.nifi.util.FormatUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.ldap.CommunicationException; +import org.springframework.ldap.core.support.AbstractTlsDirContextAuthenticationStrategy; +import org.springframework.ldap.core.support.DefaultTlsDirContextAuthenticationStrategy; +import org.springframework.ldap.core.support.LdapContextSource; +import org.springframework.ldap.core.support.SimpleDirContextAuthenticationStrategy; +import org.springframework.security.authentication.AuthenticationServiceException; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.ldap.authentication.AbstractLdapAuthenticationProvider; +import org.springframework.security.ldap.authentication.BindAuthenticator; +import org.springframework.security.ldap.authentication.LdapAuthenticationProvider; +import org.springframework.security.ldap.search.FilterBasedLdapUserSearch; +import org.springframework.security.ldap.search.LdapUserSearch; +import org.springframework.security.ldap.userdetails.LdapUserDetails; + +/** + * Abstract LDAP based implementation of a login identity provider. + */ +public class LdapProvider implements LoginIdentityProvider { + + private static final Logger logger = LoggerFactory.getLogger(LdapProvider.class); + + private AbstractLdapAuthenticationProvider provider; + private String issuer; + private long expiration; + + @Override + public final void initialize(final LoginIdentityProviderInitializationContext initializationContext) throws ProviderCreationException { + this.issuer = getClass().getSimpleName(); + } + + @Override + public final void onConfigured(final LoginIdentityProviderConfigurationContext configurationContext) throws ProviderCreationException { + final String rawExpiration = configurationContext.getProperty("Authentication Expiration"); + if (StringUtils.isBlank(rawExpiration)) { + throw new ProviderCreationException("The Authentication Expiration must be specified."); + } + + try { + expiration = FormatUtils.getTimeDuration(rawExpiration, TimeUnit.MILLISECONDS); + } catch (final IllegalArgumentException iae) { + throw new ProviderCreationException(String.format("The Expiration Duration '%s' is not a valid time duration", rawExpiration)); + } + + final LdapContextSource context = new LdapContextSource(); + + final Map<String, Object> baseEnvironment = new HashMap<>(); + + // connect/read time out + 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; + try { + authenticationStrategy = LdapAuthenticationStrategy.valueOf(rawAuthenticationStrategy); + } catch (final IllegalArgumentException iae) { + throw new ProviderCreationException(String.format("Unrecognized authentication strategy '%s'. Possible values are [%s]", + rawAuthenticationStrategy, StringUtils.join(LdapAuthenticationStrategy.values(), ", "))); + } + + switch (authenticationStrategy) { + case ANONYMOUS: + context.setAnonymousReadOnly(true); + break; + default: + final String userDn = configurationContext.getProperty("Manager DN"); + final String password = configurationContext.getProperty("Manager Password"); + + context.setUserDn(userDn); + context.setPassword(password); + + switch (authenticationStrategy) { + case SIMPLE: + context.setAuthenticationStrategy(new SimpleDirContextAuthenticationStrategy()); + break; + case START_TLS: + final AbstractTlsDirContextAuthenticationStrategy tlsAuthenticationStrategy = new DefaultTlsDirContextAuthenticationStrategy(); + + // shutdown gracefully + final String rawShutdownGracefully = configurationContext.getProperty("TLS - Shutdown Gracefully"); + if (StringUtils.isNotBlank(rawShutdownGracefully)) { + final boolean shutdownGracefully = Boolean.TRUE.toString().equalsIgnoreCase(rawShutdownGracefully); + 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(), ", "))); + } + } + + 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); + } + + context.setAuthenticationStrategy(tlsAuthenticationStrategy); + break; + } + break; + } + + // referrals + final String rawReferralStrategy = configurationContext.getProperty("Referral Strategy"); + + final ReferralStrategy referralStrategy; + try { + referralStrategy = ReferralStrategy.valueOf(rawReferralStrategy); + } catch (final IllegalArgumentException iae) { + throw new ProviderCreationException(String.format("Unrecgonized authentication strategy '%s'. Possible values are [%s]", + rawAuthenticationStrategy, StringUtils.join(ReferralStrategy.values(), ", "))); + } + + context.setReferral(referralStrategy.toString()); + + // url + final String url = configurationContext.getProperty("Url"); + + if (StringUtils.isBlank(url)) { + throw new ProviderCreationException("LDAP identity provider 'Url' must be specified."); + } + + // connection + context.setUrl(url); + + // search criteria + final String userSearchBase = configurationContext.getProperty("User Search Base"); + final String userSearchFilter = configurationContext.getProperty("User Search Filter"); + + if (StringUtils.isBlank(userSearchBase) || StringUtils.isBlank(userSearchFilter)) { + throw new ProviderCreationException("LDAP identity provider 'User Search Base' and 'User Search Filter' must be specified."); + } + + final LdapUserSearch userSearch = new FilterBasedLdapUserSearch(userSearchBase, userSearchFilter, context); + + // bind + final BindAuthenticator authenticator = new BindAuthenticator(context); + authenticator.setUserSearch(userSearch); + + try { + // handling initializing beans + context.afterPropertiesSet(); + authenticator.afterPropertiesSet(); + } catch (final Exception e) { + throw new ProviderCreationException(e.getMessage(), e); + } + + // create the underlying provider + provider = new LdapAuthenticationProvider(authenticator); + } + + private void setTimeout(final LoginIdentityProviderConfigurationContext configurationContext, + final Map<String, Object> baseEnvironment, + final String configurationProperty, + final String environmentKey) { + + final String rawTimeout = configurationContext.getProperty(configurationProperty); + if (StringUtils.isNotBlank(rawTimeout)) { + try { + final Long timeout = FormatUtils.getTimeDuration(rawTimeout, TimeUnit.MILLISECONDS); + baseEnvironment.put(environmentKey, timeout.toString()); + } catch (final IllegalArgumentException iae) { + throw new ProviderCreationException(String.format("The %s '%s' is not a valid time duration", configurationProperty, rawTimeout)); + } + } + } + + @Override + public final AuthenticationResponse authenticate(final LoginCredentials credentials) throws InvalidLoginCredentialsException, IdentityAccessException { + if (provider == null) { + throw new IdentityAccessException("The LDAP authentication provider is not initialized."); + } + + try { + // perform the authentication + final UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(credentials.getUsername(), credentials.getPassword()); + final Authentication authentication = provider.authenticate(token); + + // attempt to get the ldap user details to get the DN + if (authentication.getPrincipal() instanceof LdapUserDetails) { + final LdapUserDetails userDetails = (LdapUserDetails) authentication.getPrincipal(); + return new AuthenticationResponse(userDetails.getDn(), credentials.getUsername(), expiration, issuer); + } else { + return new AuthenticationResponse(authentication.getName(), credentials.getUsername(), expiration, issuer); + } + } catch (final CommunicationException | AuthenticationServiceException e) { + logger.error(e.getMessage()); + if (logger.isDebugEnabled()) { + logger.debug(StringUtils.EMPTY, e); + } + throw new IdentityAccessException("Unable to query the configured directory server. See the logs for additional details.", e); + } catch (final BadCredentialsException bce) { + throw new InvalidLoginCredentialsException(bce.getMessage(), bce); + } + } + + @Override + public final void preDestruction() throws ProviderDestructionException { + } + +} http://git-wip-us.apache.org/repos/asf/nifi/blob/aaf14c45/nifi-nar-bundles/nifi-ldap-iaa-providers-bundle/nifi-ldap-iaa-providers/src/main/java/org/apache/nifi/ldap/ReferralStrategy.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-ldap-iaa-providers-bundle/nifi-ldap-iaa-providers/src/main/java/org/apache/nifi/ldap/ReferralStrategy.java b/nifi-nar-bundles/nifi-ldap-iaa-providers-bundle/nifi-ldap-iaa-providers/src/main/java/org/apache/nifi/ldap/ReferralStrategy.java new file mode 100644 index 0000000..f4c5131 --- /dev/null +++ b/nifi-nar-bundles/nifi-ldap-iaa-providers-bundle/nifi-ldap-iaa-providers/src/main/java/org/apache/nifi/ldap/ReferralStrategy.java @@ -0,0 +1,39 @@ +/* + * 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; + +/** + * + */ +public enum ReferralStrategy { + + FOLLOW("follow"), + INGORE("ignore"), + THROW("throw"); + + private final String value; + + private ReferralStrategy(String value) { + this.value = value; + } + + @Override + public String toString() { + return value; + } + +} http://git-wip-us.apache.org/repos/asf/nifi/blob/aaf14c45/nifi-nar-bundles/nifi-ldap-iaa-providers-bundle/nifi-ldap-iaa-providers/src/main/resources/META-INF/services/org.apache.nifi.authentication.LoginIdentityProvider ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-ldap-iaa-providers-bundle/nifi-ldap-iaa-providers/src/main/resources/META-INF/services/org.apache.nifi.authentication.LoginIdentityProvider b/nifi-nar-bundles/nifi-ldap-iaa-providers-bundle/nifi-ldap-iaa-providers/src/main/resources/META-INF/services/org.apache.nifi.authentication.LoginIdentityProvider new file mode 100644 index 0000000..b5ca1fe --- /dev/null +++ b/nifi-nar-bundles/nifi-ldap-iaa-providers-bundle/nifi-ldap-iaa-providers/src/main/resources/META-INF/services/org.apache.nifi.authentication.LoginIdentityProvider @@ -0,0 +1,15 @@ +# 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. +org.apache.nifi.ldap.LdapProvider \ No newline at end of file http://git-wip-us.apache.org/repos/asf/nifi/blob/aaf14c45/nifi-nar-bundles/nifi-ldap-iaa-providers-bundle/pom.xml ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-ldap-iaa-providers-bundle/pom.xml b/nifi-nar-bundles/nifi-ldap-iaa-providers-bundle/pom.xml new file mode 100644 index 0000000..e038c2c --- /dev/null +++ b/nifi-nar-bundles/nifi-ldap-iaa-providers-bundle/pom.xml @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.nifi</groupId> + <artifactId>nifi-nar-bundles</artifactId> + <version>0.3.1-SNAPSHOT</version> + </parent> + <artifactId>nifi-ldap-iaa-providers-bundle</artifactId> + <packaging>pom</packaging> + <modules> + <module>nifi-ldap-iaa-providers</module> + <module>nifi-ldap-iaa-providers-nar</module> + </modules> + <dependencyManagement> + <dependencies> + <dependency> + <groupId>org.apache.nifi</groupId> + <artifactId>nifi-ldap-iaa-providers</artifactId> + <version>0.3.1-SNAPSHOT</version> + </dependency> + </dependencies> + </dependencyManagement> +</project> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/nifi/blob/aaf14c45/nifi-nar-bundles/pom.xml ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/pom.xml b/nifi-nar-bundles/pom.xml index 4c0925f..a9c7728 100644 --- a/nifi-nar-bundles/pom.xml +++ b/nifi-nar-bundles/pom.xml @@ -48,6 +48,7 @@ <module>nifi-avro-bundle</module> <module>nifi-couchbase-bundle</module> <module>nifi-azure-bundle</module> + <module>nifi-ldap-iaa-providers-bundle</module> </modules> <dependencyManagement> <dependencies> http://git-wip-us.apache.org/repos/asf/nifi/blob/aaf14c45/pom.xml ---------------------------------------------------------------------- diff --git a/pom.xml b/pom.xml index 0708812..249f01c 100644 --- a/pom.xml +++ b/pom.xml @@ -1,14 +1,14 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- 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. --> +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. --> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> @@ -91,7 +91,7 @@ <jetty.version>9.2.11.v20150529</jetty.version> <lucene.version>4.10.4</lucene.version> <spring.version>4.1.6.RELEASE</spring.version> - <spring.security.version>3.2.7.RELEASE</spring.security.version> + <spring.security.version>4.0.3.RELEASE</spring.security.version> <jersey.version>1.19</jersey.version> <hadoop.version>2.6.2</hadoop.version> <hadoop.guava.version>12.0.1</hadoop.guava.version> @@ -290,8 +290,8 @@ <version>2.2.1</version> <exclusions> <!-- | Exclude the quartz 2.2.1 bundled version of c3p0 because it is - lgpl licensed | We also don't use the JDBC related features of quartz for - which the dependency would matter --> + lgpl licensed | We also don't use the JDBC related features of quartz for + which the dependency would matter --> <exclusion> <groupId>c3p0</groupId> <artifactId>c3p0</artifactId> @@ -361,7 +361,7 @@ <version>${spring.version}</version> <exclusions> <!-- <artifactId>jcl-over-slf4j</artifactId> is used in dependencies - section --> + section --> <exclusion> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> @@ -504,6 +504,29 @@ </exclusions> </dependency> <dependency> + <groupId>org.springframework.security</groupId> + <artifactId>spring-security-ldap</artifactId> + <version>${spring.security.version}</version> + <exclusions> + <exclusion> + <groupId>org.springframework</groupId> + <artifactId>spring-core</artifactId> + </exclusion> + <exclusion> + <groupId>org.springframework</groupId> + <artifactId>spring-beans</artifactId> + </exclusion> + <exclusion> + <groupId>org.springframework</groupId> + <artifactId>spring-context</artifactId> + </exclusion> + <exclusion> + <groupId>org.springframework</groupId> + <artifactId>spring-tx</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.5</version> @@ -977,6 +1000,12 @@ </dependency> <dependency> <groupId>org.apache.nifi</groupId> + <artifactId>nifi-ldap-iaa-providers-nar</artifactId> + <version>0.3.1-SNAPSHOT</version> + <type>nar</type> + </dependency> + <dependency> + <groupId>org.apache.nifi</groupId> <artifactId>nifi-properties</artifactId> <version>0.4.0-SNAPSHOT</version> </dependency> @@ -1262,7 +1291,7 @@ <module name="OuterTypeFilename" /> <module name="LineLength"> <!-- needs extra, because Eclipse formatter ignores the ending left - brace --> + brace --> <property name="max" value="200" /> <property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://" /> </module> @@ -1352,11 +1381,11 @@ <profiles> <profile> <!-- Checks style and licensing requirements. This is a good idea to run - for contributions and for the release process. While it would be nice to - run always these plugins can considerably slow the build and have proven - to create unstable builds in our multi-module project and when building using - multiple threads. The stability issues seen with Checkstyle in multi-module - builds include false-positives and false negatives. --> + for contributions and for the release process. While it would be nice to + run always these plugins can considerably slow the build and have proven + to create unstable builds in our multi-module project and when building using + multiple threads. The stability issues seen with Checkstyle in multi-module + builds include false-positives and false negatives. --> <id>contrib-check</id> <build> <plugins>
