You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by mc...@apache.org on 2015/11/23 21:46:51 UTC

[40/50] [abbrv] nifi git commit: NIFI-655: - Refactoring web security to use Spring Security Java Configuration. - Introducing security in Web UI in order to get JWT.

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>