You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by bb...@apache.org on 2017/11/07 18:50:18 UTC

[02/17] nifi-registry git commit: NIFIREG-33 Add LDAP and JWT auth support

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/90f36dd2/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/token/NiFiAuthenticationToken.java
----------------------------------------------------------------------
diff --git a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/token/NiFiAuthenticationToken.java b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/token/NiFiAuthenticationToken.java
new file mode 100644
index 0000000..19e56c5
--- /dev/null
+++ b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/token/NiFiAuthenticationToken.java
@@ -0,0 +1,55 @@
+/*
+ * 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.registry.web.security.authentication.token;
+
+import org.springframework.security.authentication.AbstractAuthenticationToken;
+import org.springframework.security.core.userdetails.UserDetails;
+
+/**
+ * An authentication token that represents an Authenticated and Authorized user of the NiFi Apis. The authorities are based off the specified UserDetails.
+ */
+public class NiFiAuthenticationToken extends AbstractAuthenticationToken {
+
+    final UserDetails nifiUserDetails;
+
+    public NiFiAuthenticationToken(final UserDetails nifiUserDetails) {
+        super(nifiUserDetails.getAuthorities());
+        super.setAuthenticated(true);
+        setDetails(nifiUserDetails);
+        this.nifiUserDetails = nifiUserDetails;
+    }
+
+    @Override
+    public Object getCredentials() {
+        return nifiUserDetails.getPassword();
+    }
+
+    @Override
+    public Object getPrincipal() {
+        return nifiUserDetails;
+    }
+
+    @Override
+    public final void setAuthenticated(boolean authenticated) {
+        throw new IllegalArgumentException("Cannot change the authenticated state.");
+    }
+
+    @Override
+    public String toString() {
+        return nifiUserDetails.getUsername();
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/90f36dd2/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/SubjectDnX509PrincipalExtractor.java
----------------------------------------------------------------------
diff --git a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/SubjectDnX509PrincipalExtractor.java b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/SubjectDnX509PrincipalExtractor.java
new file mode 100644
index 0000000..a9deae1
--- /dev/null
+++ b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/SubjectDnX509PrincipalExtractor.java
@@ -0,0 +1,35 @@
+/*
+ * 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.registry.web.security.authentication.x509;
+
+import org.springframework.security.web.authentication.preauth.x509.X509PrincipalExtractor;
+import org.springframework.stereotype.Component;
+
+import java.security.cert.X509Certificate;
+
+/**
+ * Principal extractor for extracting a DN.
+ */
+@Component
+public class SubjectDnX509PrincipalExtractor implements X509PrincipalExtractor {
+
+    @Override
+    public Object extractPrincipal(X509Certificate cert) {
+        return cert.getSubjectDN().getName().trim();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/90f36dd2/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/X509AuthenticationFilter.java
----------------------------------------------------------------------
diff --git a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/X509AuthenticationFilter.java b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/X509AuthenticationFilter.java
new file mode 100644
index 0000000..fa0fce2
--- /dev/null
+++ b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/X509AuthenticationFilter.java
@@ -0,0 +1,64 @@
+/*
+ * 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.registry.web.security.authentication.x509;
+
+import org.apache.nifi.registry.web.security.authentication.NiFiAuthenticationFilter;
+import org.apache.nifi.registry.web.security.authentication.ProxiedEntitiesUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.web.authentication.preauth.x509.X509PrincipalExtractor;
+
+import javax.servlet.http.HttpServletRequest;
+import java.security.cert.X509Certificate;
+
+/**
+ * Custom X509 filter that will inspect the HTTP headers for a proxied user before extracting the user details from the client certificate.
+ */
+public class X509AuthenticationFilter extends NiFiAuthenticationFilter {
+
+    private static final Logger logger = LoggerFactory.getLogger(X509AuthenticationFilter.class);
+
+    private X509CertificateExtractor certificateExtractor;
+    private X509PrincipalExtractor principalExtractor;
+
+    @Override
+    public Authentication attemptAuthentication(final HttpServletRequest request) {
+        // only suppport x509 login when running securely
+        if (!request.isSecure()) {
+            return null;
+        }
+
+        // look for a client certificate
+        final X509Certificate[] certificates = certificateExtractor.extractClientCertificate(request);
+        if (certificates == null) {
+            return null;
+        }
+
+        return new X509AuthenticationRequestToken(request.getHeader(ProxiedEntitiesUtils.PROXY_ENTITIES_CHAIN), principalExtractor, certificates, request.getRemoteAddr());
+    }
+
+    /* setters */
+    public void setCertificateExtractor(X509CertificateExtractor certificateExtractor) {
+        this.certificateExtractor = certificateExtractor;
+    }
+
+    public void setPrincipalExtractor(X509PrincipalExtractor principalExtractor) {
+        this.principalExtractor = principalExtractor;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/90f36dd2/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/X509AuthenticationProvider.java
----------------------------------------------------------------------
diff --git a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/X509AuthenticationProvider.java b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/X509AuthenticationProvider.java
new file mode 100644
index 0000000..3e935a2
--- /dev/null
+++ b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/X509AuthenticationProvider.java
@@ -0,0 +1,166 @@
+/*
+ * 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.registry.web.security.authentication.x509;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.registry.security.authorization.exception.AccessDeniedException;
+import org.apache.nifi.registry.security.authorization.Authorizer;
+import org.apache.nifi.registry.security.authorization.RequestAction;
+import org.apache.nifi.registry.security.authorization.Resource;
+import org.apache.nifi.registry.security.authorization.UserContextKeys;
+import org.apache.nifi.registry.security.authorization.resource.Authorizable;
+import org.apache.nifi.registry.security.authorization.resource.ResourceFactory;
+import org.apache.nifi.registry.security.authorization.user.NiFiUser;
+import org.apache.nifi.registry.security.authorization.user.NiFiUserDetails;
+import org.apache.nifi.registry.security.authorization.user.StandardNiFiUser;
+import org.apache.nifi.registry.properties.NiFiRegistryProperties;
+import org.apache.nifi.registry.web.response.AuthenticationResponse;
+import org.apache.nifi.registry.web.security.authentication.exception.InvalidAuthenticationException;
+import org.apache.nifi.registry.web.security.authentication.NiFiAuthenticationProvider;
+import org.apache.nifi.registry.web.security.authentication.ProxiedEntitiesUtils;
+import org.apache.nifi.registry.web.security.authentication.exception.UntrustedProxyException;
+import org.apache.nifi.registry.web.security.authentication.token.NiFiAuthenticationToken;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.Set;
+
+@Component
+public class X509AuthenticationProvider extends NiFiAuthenticationProvider {
+
+    private static final Authorizable PROXY_AUTHORIZABLE = new Authorizable() {
+        @Override
+        public Authorizable getParentAuthorizable() {
+            return null;
+        }
+
+        @Override
+        public Resource getResource() {
+            return ResourceFactory.getProxyResource();
+        }
+    };
+
+    private X509IdentityProvider certificateIdentityProvider;
+    private Authorizer authorizer;
+
+    @Autowired
+    public X509AuthenticationProvider(
+            final X509IdentityProvider certificateIdentityProvider,
+            final Authorizer authorizer,
+            final NiFiRegistryProperties properties) {
+        super(properties, authorizer);
+        this.certificateIdentityProvider = certificateIdentityProvider;
+        this.authorizer = authorizer;
+    }
+
+    @Override
+    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
+        final X509AuthenticationRequestToken request = (X509AuthenticationRequestToken) authentication;
+
+        // attempt to authenticate if certificates were found
+        final AuthenticationResponse authenticationResponse;
+        try {
+            authenticationResponse = certificateIdentityProvider.authenticate(request.getCertificates());
+        } catch (final IllegalArgumentException iae) {
+            throw new InvalidAuthenticationException(iae.getMessage(), iae);
+        }
+
+        if (StringUtils.isBlank(request.getProxiedEntitiesChain())) {
+            final String mappedIdentity = mapIdentity(authenticationResponse.getIdentity());
+            return new NiFiAuthenticationToken(new NiFiUserDetails(
+                    new StandardNiFiUser.Builder()
+                            .identity(mappedIdentity)
+                            .groups(getUserGroups(mappedIdentity))
+                            .clientAddress(request.getClientAddress())
+                            .build()));
+        } else {
+            // build the entire proxy chain if applicable - <end-user><proxy1><proxy2>
+            final List<String> proxyChain = new ArrayList<>(ProxiedEntitiesUtils.tokenizeProxiedEntitiesChain(request.getProxiedEntitiesChain()));
+            proxyChain.add(authenticationResponse.getIdentity());
+
+            // add the chain as appropriate to each proxy
+            NiFiUser proxy = null;
+            for (final ListIterator<String> chainIter = proxyChain.listIterator(proxyChain.size()); chainIter.hasPrevious(); ) {
+                String identity = chainIter.previous();
+
+                // determine if the user is anonymous
+                final boolean isAnonymous = StringUtils.isBlank(identity);
+                if (isAnonymous) {
+                    identity = StandardNiFiUser.ANONYMOUS_IDENTITY;
+                } else {
+                    identity = mapIdentity(identity);
+                }
+
+                final Set<String> groups = getUserGroups(identity);
+
+                // Only set the client address for client making the request because we don't know the clientAddress of the proxied entities
+                String clientAddress = (proxy == null) ? request.getClientAddress() : null;
+                proxy = createUser(identity, groups, proxy, clientAddress, isAnonymous);
+
+                if (chainIter.hasPrevious()) {
+                    try {
+                        PROXY_AUTHORIZABLE.authorize(authorizer, RequestAction.WRITE, proxy);
+                    } catch (final AccessDeniedException e) {
+                        throw new UntrustedProxyException(String.format("Untrusted proxy %s", identity));
+                    }
+                }
+            }
+
+            return new NiFiAuthenticationToken(new NiFiUserDetails(proxy));
+        }
+    }
+
+    /**
+     * Returns a regular user populated with the provided values, or if the user should be anonymous, a well-formed instance of the anonymous user with the provided values.
+     *
+     * @param identity      the user's identity
+     * @param chain         the proxied entities
+     * @param clientAddress the requesting IP address
+     * @param isAnonymous   if true, an anonymous user will be returned (identity will be ignored)
+     * @return the populated user
+     */
+    protected static NiFiUser createUser(String identity, Set<String> groups, NiFiUser chain, String clientAddress, boolean isAnonymous) {
+        if (isAnonymous) {
+            return StandardNiFiUser.populateAnonymousUser(chain, clientAddress);
+        } else {
+            return new StandardNiFiUser.Builder().identity(identity).groups(groups).chain(chain).clientAddress(clientAddress).build();
+        }
+    }
+
+    private Map<String, String> getUserContext(final X509AuthenticationRequestToken request) {
+        final Map<String, String> userContext;
+        if (!StringUtils.isBlank(request.getClientAddress())) {
+            userContext = new HashMap<>();
+            userContext.put(UserContextKeys.CLIENT_ADDRESS.name(), request.getClientAddress());
+        } else {
+            userContext = null;
+        }
+        return userContext;
+    }
+
+    @Override
+    public boolean supports(Class<?> authentication) {
+        return X509AuthenticationRequestToken.class.isAssignableFrom(authentication);
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/90f36dd2/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/X509AuthenticationRequestToken.java
----------------------------------------------------------------------
diff --git a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/X509AuthenticationRequestToken.java b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/X509AuthenticationRequestToken.java
new file mode 100644
index 0000000..d5aca23
--- /dev/null
+++ b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/X509AuthenticationRequestToken.java
@@ -0,0 +1,75 @@
+/*
+ * 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.registry.web.security.authentication.x509;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.registry.web.security.authentication.NiFiAuthenticationRequestToken;
+import org.springframework.security.web.authentication.preauth.x509.X509PrincipalExtractor;
+
+import java.security.cert.X509Certificate;
+
+/**
+ * This is an authentication request with a given JWT token.
+ */
+public class X509AuthenticationRequestToken extends NiFiAuthenticationRequestToken {
+
+    private final String proxiedEntitiesChain;
+    private final X509PrincipalExtractor principalExtractor;
+    private final X509Certificate[] certificates;
+
+    /**
+     * Creates a representation of the jwt authentication request for a user.
+     *
+     * @param proxiedEntitiesChain   The http servlet request
+     * @param certificates  The certificate chain
+     */
+    public X509AuthenticationRequestToken(final String proxiedEntitiesChain, final X509PrincipalExtractor principalExtractor, final X509Certificate[] certificates, final String clientAddress) {
+        super(clientAddress);
+        setAuthenticated(false);
+        this.proxiedEntitiesChain = proxiedEntitiesChain;
+        this.principalExtractor = principalExtractor;
+        this.certificates = certificates;
+    }
+
+    @Override
+    public Object getCredentials() {
+        return null;
+    }
+
+    @Override
+    public Object getPrincipal() {
+        if (StringUtils.isBlank(proxiedEntitiesChain)) {
+            return principalExtractor.extractPrincipal(certificates[0]);
+        } else {
+            return String.format("%s<%s>", proxiedEntitiesChain, principalExtractor.extractPrincipal(certificates[0]));
+        }
+    }
+
+    public String getProxiedEntitiesChain() {
+        return proxiedEntitiesChain;
+    }
+
+    public X509Certificate[] getCertificates() {
+        return certificates;
+    }
+
+    @Override
+    public String toString() {
+        return getName();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/90f36dd2/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/X509CertificateExtractor.java
----------------------------------------------------------------------
diff --git a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/X509CertificateExtractor.java b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/X509CertificateExtractor.java
new file mode 100644
index 0000000..34ceada
--- /dev/null
+++ b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/X509CertificateExtractor.java
@@ -0,0 +1,55 @@
+/*
+ * 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.registry.web.security.authentication.x509;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.http.HttpServletRequest;
+import java.security.cert.X509Certificate;
+
+/**
+ * Extracts client certificates from Http requests.
+ */
+@Component
+public class X509CertificateExtractor {
+
+    private final Logger logger = LoggerFactory.getLogger(getClass());
+
+    /**
+     * Extract the client certificate from the specified HttpServletRequest or
+     * null if none is specified.
+     *
+     * @param request http request
+     * @return cert
+     */
+    public X509Certificate[] extractClientCertificate(HttpServletRequest request) {
+        X509Certificate[] certs = (X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate");
+
+        if (certs != null && certs.length > 0) {
+            return certs;
+        }
+
+        if (logger.isDebugEnabled()) {
+            logger.debug("No client certificate found in request.");
+        }
+
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/90f36dd2/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/X509CertificateValidator.java
----------------------------------------------------------------------
diff --git a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/X509CertificateValidator.java b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/X509CertificateValidator.java
new file mode 100644
index 0000000..d748b93
--- /dev/null
+++ b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/X509CertificateValidator.java
@@ -0,0 +1,49 @@
+/*
+ * 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.registry.web.security.authentication.x509;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateNotYetValidException;
+import java.security.cert.X509Certificate;
+
+/**
+ * Extracts client certificates from Http requests.
+ */
+@Component
+public class X509CertificateValidator {
+
+    private final Logger logger = LoggerFactory.getLogger(getClass());
+
+    /**
+     * Extract the client certificate from the specified HttpServletRequest or null if none is specified.
+     *
+     * @param certificates the client certificates
+     * @throws CertificateExpiredException cert is expired
+     * @throws CertificateNotYetValidException cert is not yet valid
+     */
+    public void validateClientCertificate(final X509Certificate[] certificates)
+            throws CertificateExpiredException, CertificateNotYetValidException {
+
+        // ensure the cert is valid
+        certificates[0].checkValidity();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/90f36dd2/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/X509IdentityProvider.java
----------------------------------------------------------------------
diff --git a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/X509IdentityProvider.java b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/X509IdentityProvider.java
new file mode 100644
index 0000000..692b318
--- /dev/null
+++ b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/X509IdentityProvider.java
@@ -0,0 +1,104 @@
+/*
+ * 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.registry.web.security.authentication.x509;
+
+import org.apache.nifi.registry.web.response.AuthenticationResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.web.authentication.preauth.x509.X509PrincipalExtractor;
+import org.springframework.stereotype.Component;
+
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateNotYetValidException;
+import java.security.cert.X509Certificate;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Identity provider for extract the authenticating a ServletRequest with a X509Certificate.
+ */
+@Component
+public class X509IdentityProvider {
+
+    private static final Logger logger = LoggerFactory.getLogger(X509IdentityProvider.class);
+
+    private final String issuer = getClass().getSimpleName();
+
+    private X509CertificateValidator certificateValidator;
+    private X509PrincipalExtractor principalExtractor;
+
+    @Autowired
+    public X509IdentityProvider(X509CertificateValidator certificateValidator, X509PrincipalExtractor principalExtractor) {
+        this.certificateValidator = certificateValidator;
+        this.principalExtractor = principalExtractor;
+    }
+
+    /**
+     * Authenticates the specified request by checking certificate validity.
+     *
+     * @param certificates the client certificates
+     * @return an authentication response
+     * @throws IllegalArgumentException the request did not contain a valid certificate (or no certificate)
+     */
+    public AuthenticationResponse authenticate(final X509Certificate[] certificates) throws IllegalArgumentException {
+        // ensure the cert was found
+        if (certificates == null || certificates.length == 0) {
+            throw new IllegalArgumentException("The specified request does not contain a client certificate.");
+        }
+
+        // extract the principal
+        final Object certificatePrincipal = principalExtractor.extractPrincipal(certificates[0]);
+        final String principal = certificatePrincipal.toString();
+
+        try {
+            certificateValidator.validateClientCertificate(certificates);
+        } catch (CertificateExpiredException cee) {
+            final String message = String.format("Client certificate for (%s) is expired.", principal);
+            logger.info(message, cee);
+            if (logger.isDebugEnabled()) {
+                logger.debug("", cee);
+            }
+            throw new IllegalArgumentException(message, cee);
+        } catch (CertificateNotYetValidException cnyve) {
+            final String message = String.format("Client certificate for (%s) is not yet valid.", principal);
+            logger.info(message, cnyve);
+            if (logger.isDebugEnabled()) {
+                logger.debug("", cnyve);
+            }
+            throw new IllegalArgumentException(message, cnyve);
+        } catch (final Exception e) {
+            logger.info(e.getMessage());
+            if (logger.isDebugEnabled()) {
+                logger.debug("", e);
+            }
+            throw new IllegalArgumentException(e.getMessage(), e);
+        }
+
+        // build the authentication response
+        return new AuthenticationResponse(principal, principal, TimeUnit.MILLISECONDS.convert(12, TimeUnit.HOURS), issuer);
+    }
+
+    /* setters */
+    public void setCertificateValidator(X509CertificateValidator certificateValidator) {
+        this.certificateValidator = certificateValidator;
+    }
+
+    public void setPrincipalExtractor(X509PrincipalExtractor principalExtractor) {
+        this.principalExtractor = principalExtractor;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/90f36dd2/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/token/LoginAuthenticationToken.java
----------------------------------------------------------------------
diff --git a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/token/LoginAuthenticationToken.java b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/token/LoginAuthenticationToken.java
deleted file mode 100644
index 86c8634..0000000
--- a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/token/LoginAuthenticationToken.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * 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.registry.web.security.token;
-
-import org.apache.nifi.registry.security.util.CertificateUtils;
-import org.springframework.security.authentication.AbstractAuthenticationToken;
-
-import java.text.SimpleDateFormat;
-import java.util.Calendar;
-
-/**
- * This is an Authentication Token for logging in. Once a user is authenticated, they can be issued an ID token.
- */
-public class LoginAuthenticationToken extends AbstractAuthenticationToken {
-
-    private final String identity;
-    private final String username;
-    private final long expiration;
-    private final String issuer;
-
-    /**
-     * Creates a representation of the authentication token for a user.
-     *
-     * @param identity   The unique identifier for this user
-     * @param expiration The relative time to expiration in milliseconds
-     * @param issuer     The IdentityProvider implementation that generated this token
-     */
-    public LoginAuthenticationToken(final String identity, final long expiration, final String issuer) {
-        this(identity, null, expiration, issuer);
-    }
-
-    /**
-     * Creates a representation of the authentication token for a user.
-     *
-     * @param identity   The unique identifier for this user (cannot be null or empty)
-     * @param username   The preferred username for this user
-     * @param expiration The relative time to expiration in milliseconds
-     * @param issuer     The IdentityProvider implementation that generated this token
-     */
-    public LoginAuthenticationToken(final String identity, final String username, final long expiration, final String issuer) {
-        super(null);
-        setAuthenticated(true);
-        this.identity = identity;
-        this.username = username;
-        this.issuer = issuer;
-        Calendar now = Calendar.getInstance();
-        this.expiration = now.getTimeInMillis() + expiration;
-    }
-
-    @Override
-    public Object getCredentials() {
-        return null;
-    }
-
-    @Override
-    public Object getPrincipal() {
-        return identity;
-    }
-
-    /**
-     * Returns the expiration instant in milliseconds. This value is an absolute point in time (i.e. Nov
-     * 16, 2015 11:30:00.000 GMT), not a relative time (i.e. 60 minutes). It is calculated by adding the
-     * relative expiration from the constructor to the timestamp at object creation.
-     *
-     * @return the expiration in millis
-     */
-    public long getExpiration() {
-        return expiration;
-    }
-
-    public String getIssuer() {
-        return issuer;
-    }
-
-    @Override
-    public String getName() {
-        if (username == null) {
-            // if the username is a DN this will extract the username or CN... if not will return what was passed
-            return CertificateUtils.extractUsername(identity);
-        } else {
-            return username;
-        }
-    }
-
-    @Override
-    public String toString() {
-        Calendar expirationTime = Calendar.getInstance();
-        expirationTime.setTimeInMillis(getExpiration());
-        long remainingTime = expirationTime.getTimeInMillis() - Calendar.getInstance().getTimeInMillis();
-
-        SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss.SSS");
-        dateFormat.setTimeZone(expirationTime.getTimeZone());
-        String expirationTimeString = dateFormat.format(expirationTime.getTime());
-
-        return new StringBuilder("LoginAuthenticationToken for ")
-                .append(getName())
-                .append(" issued by ")
-                .append(getIssuer())
-                .append(" expiring at ")
-                .append(expirationTimeString)
-                .append(" [")
-                .append(getExpiration())
-                .append(" ms, ")
-                .append(remainingTime)
-                .append(" ms remaining]")
-                .toString();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/90f36dd2/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/token/NiFiAuthenticationToken.java
----------------------------------------------------------------------
diff --git a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/token/NiFiAuthenticationToken.java b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/token/NiFiAuthenticationToken.java
deleted file mode 100644
index 5ea9e5b..0000000
--- a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/token/NiFiAuthenticationToken.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.registry.web.security.token;
-
-import org.springframework.security.authentication.AbstractAuthenticationToken;
-import org.springframework.security.core.userdetails.UserDetails;
-
-/**
- * An authentication token that represents an Authenticated and Authorized user of the NiFi Apis. The authorities are based off the specified UserDetails.
- */
-public class NiFiAuthenticationToken extends AbstractAuthenticationToken {
-
-    final UserDetails nifiUserDetails;
-
-    public NiFiAuthenticationToken(final UserDetails nifiUserDetails) {
-        super(nifiUserDetails.getAuthorities());
-        super.setAuthenticated(true);
-        setDetails(nifiUserDetails);
-        this.nifiUserDetails = nifiUserDetails;
-    }
-
-    @Override
-    public Object getCredentials() {
-        return nifiUserDetails.getPassword();
-    }
-
-    @Override
-    public Object getPrincipal() {
-        return nifiUserDetails;
-    }
-
-    @Override
-    public final void setAuthenticated(boolean authenticated) {
-        throw new IllegalArgumentException("Cannot change the authenticated state.");
-    }
-
-    @Override
-    public String toString() {
-        return nifiUserDetails.getUsername();
-    }
-}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/90f36dd2/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/token/OtpAuthenticationToken.java
----------------------------------------------------------------------
diff --git a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/token/OtpAuthenticationToken.java b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/token/OtpAuthenticationToken.java
deleted file mode 100644
index f49e97d..0000000
--- a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/token/OtpAuthenticationToken.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.registry.web.security.token;
-
-import org.springframework.security.authentication.AbstractAuthenticationToken;
-
-/**
- * This is an Authentication Token for logging in. Once a user is authenticated, they can be issued an ID token.
- */
-public class OtpAuthenticationToken extends AbstractAuthenticationToken {
-
-    private final String identity;
-
-    /**
-     * Creates a representation of the otp authentication token for a user.
-     *
-     * @param identity   The unique identifier for this user
-     */
-    public OtpAuthenticationToken(final String identity) {
-        super(null);
-        setAuthenticated(true);
-        this.identity = identity;
-    }
-
-    @Override
-    public Object getCredentials() {
-        return null;
-    }
-
-    @Override
-    public Object getPrincipal() {
-        return identity;
-    }
-
-    @Override
-    public String toString() {
-        return new StringBuilder("OtpAuthenticationToken for ")
-                .append(getName())
-                .toString();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/90f36dd2/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/x509/SubjectDnX509PrincipalExtractor.java
----------------------------------------------------------------------
diff --git a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/x509/SubjectDnX509PrincipalExtractor.java b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/x509/SubjectDnX509PrincipalExtractor.java
deleted file mode 100644
index f8ab1fe..0000000
--- a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/x509/SubjectDnX509PrincipalExtractor.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.registry.web.security.x509;
-
-import org.springframework.security.web.authentication.preauth.x509.X509PrincipalExtractor;
-
-import java.security.cert.X509Certificate;
-
-/**
- * Principal extractor for extracting a DN.
- */
-public class SubjectDnX509PrincipalExtractor implements X509PrincipalExtractor {
-
-    @Override
-    public Object extractPrincipal(X509Certificate cert) {
-        return cert.getSubjectDN().getName().trim();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/90f36dd2/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/x509/X509AuthenticationFilter.java
----------------------------------------------------------------------
diff --git a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/x509/X509AuthenticationFilter.java b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/x509/X509AuthenticationFilter.java
deleted file mode 100644
index df8bbbf..0000000
--- a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/x509/X509AuthenticationFilter.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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.registry.web.security.x509;
-
-import org.apache.nifi.registry.web.security.NiFiAuthenticationFilter;
-import org.apache.nifi.registry.web.security.ProxiedEntitiesUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.web.authentication.preauth.x509.X509PrincipalExtractor;
-
-import javax.servlet.http.HttpServletRequest;
-import java.security.cert.X509Certificate;
-
-/**
- * Custom X509 filter that will inspect the HTTP headers for a proxied user before extracting the user details from the client certificate.
- */
-public class X509AuthenticationFilter extends NiFiAuthenticationFilter {
-
-    private static final Logger logger = LoggerFactory.getLogger(X509AuthenticationFilter.class);
-
-    private X509CertificateExtractor certificateExtractor;
-    private X509PrincipalExtractor principalExtractor;
-
-    @Override
-    public Authentication attemptAuthentication(final HttpServletRequest request) {
-        // only suppport x509 login when running securely
-        if (!request.isSecure()) {
-            return null;
-        }
-
-        // look for a client certificate
-        final X509Certificate[] certificates = certificateExtractor.extractClientCertificate(request);
-        if (certificates == null) {
-            return null;
-        }
-
-        return new X509AuthenticationRequestToken(request.getHeader(ProxiedEntitiesUtils.PROXY_ENTITIES_CHAIN), principalExtractor, certificates, request.getRemoteAddr());
-    }
-
-    /* setters */
-    public void setCertificateExtractor(X509CertificateExtractor certificateExtractor) {
-        this.certificateExtractor = certificateExtractor;
-    }
-
-    public void setPrincipalExtractor(X509PrincipalExtractor principalExtractor) {
-        this.principalExtractor = principalExtractor;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/90f36dd2/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/x509/X509AuthenticationProvider.java
----------------------------------------------------------------------
diff --git a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/x509/X509AuthenticationProvider.java b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/x509/X509AuthenticationProvider.java
deleted file mode 100644
index 5ed7859..0000000
--- a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/x509/X509AuthenticationProvider.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * 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.registry.web.security.x509;
-
-import org.apache.commons.lang3.StringUtils;
-import org.apache.nifi.registry.authorization.exception.AccessDeniedException;
-import org.apache.nifi.registry.authorization.Authorizer;
-import org.apache.nifi.registry.authorization.RequestAction;
-import org.apache.nifi.registry.authorization.Resource;
-import org.apache.nifi.registry.authorization.UserContextKeys;
-import org.apache.nifi.registry.authorization.resource.Authorizable;
-import org.apache.nifi.registry.authorization.resource.ResourceFactory;
-import org.apache.nifi.registry.authorization.user.NiFiUser;
-import org.apache.nifi.registry.authorization.user.NiFiUserDetails;
-import org.apache.nifi.registry.authorization.user.StandardNiFiUser;
-import org.apache.nifi.registry.properties.NiFiRegistryProperties;
-import org.apache.nifi.registry.web.response.AuthenticationResponse;
-import org.apache.nifi.registry.web.security.InvalidAuthenticationException;
-import org.apache.nifi.registry.web.security.NiFiAuthenticationProvider;
-import org.apache.nifi.registry.web.security.ProxiedEntitiesUtils;
-import org.apache.nifi.registry.web.security.UntrustedProxyException;
-import org.apache.nifi.registry.web.security.token.NiFiAuthenticationToken;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.AuthenticationException;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Map;
-import java.util.Set;
-
-/**
- *
- */
-public class X509AuthenticationProvider extends NiFiAuthenticationProvider {
-
-    private static final Authorizable PROXY_AUTHORIZABLE = new Authorizable() {
-        @Override
-        public Authorizable getParentAuthorizable() {
-            return null;
-        }
-
-        @Override
-        public Resource getResource() {
-            return ResourceFactory.getProxyResource();
-        }
-    };
-
-    private X509IdentityProvider certificateIdentityProvider;
-    private Authorizer authorizer;
-
-    public X509AuthenticationProvider(
-            final X509IdentityProvider certificateIdentityProvider,
-            final Authorizer authorizer,
-            final NiFiRegistryProperties properties) {
-        super(properties, authorizer);
-        this.certificateIdentityProvider = certificateIdentityProvider;
-        this.authorizer = authorizer;
-    }
-
-    @Override
-    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
-        final X509AuthenticationRequestToken request = (X509AuthenticationRequestToken) authentication;
-
-        // attempt to authenticate if certificates were found
-        final AuthenticationResponse authenticationResponse;
-        try {
-            authenticationResponse = certificateIdentityProvider.authenticate(request.getCertificates());
-        } catch (final IllegalArgumentException iae) {
-            throw new InvalidAuthenticationException(iae.getMessage(), iae);
-        }
-
-        if (StringUtils.isBlank(request.getProxiedEntitiesChain())) {
-            final String mappedIdentity = mapIdentity(authenticationResponse.getIdentity());
-            return new NiFiAuthenticationToken(new NiFiUserDetails(
-                    new StandardNiFiUser.Builder()
-                            .identity(mappedIdentity)
-                            .groups(getUserGroups(mappedIdentity))
-                            .clientAddress(request.getClientAddress())
-                            .build()));
-        } else {
-            // build the entire proxy chain if applicable - <end-user><proxy1><proxy2>
-            final List<String> proxyChain = new ArrayList<>(ProxiedEntitiesUtils.tokenizeProxiedEntitiesChain(request.getProxiedEntitiesChain()));
-            proxyChain.add(authenticationResponse.getIdentity());
-
-            // add the chain as appropriate to each proxy
-            NiFiUser proxy = null;
-            for (final ListIterator<String> chainIter = proxyChain.listIterator(proxyChain.size()); chainIter.hasPrevious(); ) {
-                String identity = chainIter.previous();
-
-                // determine if the user is anonymous
-                final boolean isAnonymous = StringUtils.isBlank(identity);
-                if (isAnonymous) {
-                    identity = StandardNiFiUser.ANONYMOUS_IDENTITY;
-                } else {
-                    identity = mapIdentity(identity);
-                }
-
-                final Set<String> groups = getUserGroups(identity);
-
-                // Only set the client address for client making the request because we don't know the clientAddress of the proxied entities
-                String clientAddress = (proxy == null) ? request.getClientAddress() : null;
-                proxy = createUser(identity, groups, proxy, clientAddress, isAnonymous);
-
-                if (chainIter.hasPrevious()) {
-                    try {
-                        PROXY_AUTHORIZABLE.authorize(authorizer, RequestAction.WRITE, proxy);
-                    } catch (final AccessDeniedException e) {
-                        throw new UntrustedProxyException(String.format("Untrusted proxy %s", identity));
-                    }
-                }
-            }
-
-            return new NiFiAuthenticationToken(new NiFiUserDetails(proxy));
-        }
-    }
-
-    /**
-     * Returns a regular user populated with the provided values, or if the user should be anonymous, a well-formed instance of the anonymous user with the provided values.
-     *
-     * @param identity      the user's identity
-     * @param chain         the proxied entities
-     * @param clientAddress the requesting IP address
-     * @param isAnonymous   if true, an anonymous user will be returned (identity will be ignored)
-     * @return the populated user
-     */
-    protected static NiFiUser createUser(String identity, Set<String> groups, NiFiUser chain, String clientAddress, boolean isAnonymous) {
-        if (isAnonymous) {
-            return StandardNiFiUser.populateAnonymousUser(chain, clientAddress);
-        } else {
-            return new StandardNiFiUser.Builder().identity(identity).groups(groups).chain(chain).clientAddress(clientAddress).build();
-        }
-    }
-
-    private Map<String, String> getUserContext(final X509AuthenticationRequestToken request) {
-        final Map<String, String> userContext;
-        if (!StringUtils.isBlank(request.getClientAddress())) {
-            userContext = new HashMap<>();
-            userContext.put(UserContextKeys.CLIENT_ADDRESS.name(), request.getClientAddress());
-        } else {
-            userContext = null;
-        }
-        return userContext;
-    }
-
-    @Override
-    public boolean supports(Class<?> authentication) {
-        return X509AuthenticationRequestToken.class.isAssignableFrom(authentication);
-    }
-}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/90f36dd2/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/x509/X509AuthenticationRequestToken.java
----------------------------------------------------------------------
diff --git a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/x509/X509AuthenticationRequestToken.java b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/x509/X509AuthenticationRequestToken.java
deleted file mode 100644
index 22bc8bd..0000000
--- a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/x509/X509AuthenticationRequestToken.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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.registry.web.security.x509;
-
-import org.apache.commons.lang3.StringUtils;
-import org.apache.nifi.registry.web.security.NiFiAuthenticationRequestToken;
-import org.springframework.security.web.authentication.preauth.x509.X509PrincipalExtractor;
-
-import java.security.cert.X509Certificate;
-
-/**
- * This is an authentication request with a given JWT token.
- */
-public class X509AuthenticationRequestToken extends NiFiAuthenticationRequestToken {
-
-    private final String proxiedEntitiesChain;
-    private final X509PrincipalExtractor principalExtractor;
-    private final X509Certificate[] certificates;
-
-    /**
-     * Creates a representation of the jwt authentication request for a user.
-     *
-     * @param proxiedEntitiesChain   The http servlet request
-     * @param certificates  The certificate chain
-     */
-    public X509AuthenticationRequestToken(final String proxiedEntitiesChain, final X509PrincipalExtractor principalExtractor, final X509Certificate[] certificates, final String clientAddress) {
-        super(clientAddress);
-        setAuthenticated(false);
-        this.proxiedEntitiesChain = proxiedEntitiesChain;
-        this.principalExtractor = principalExtractor;
-        this.certificates = certificates;
-    }
-
-    @Override
-    public Object getCredentials() {
-        return null;
-    }
-
-    @Override
-    public Object getPrincipal() {
-        if (StringUtils.isBlank(proxiedEntitiesChain)) {
-            return principalExtractor.extractPrincipal(certificates[0]);
-        } else {
-            return String.format("%s<%s>", proxiedEntitiesChain, principalExtractor.extractPrincipal(certificates[0]));
-        }
-    }
-
-    public String getProxiedEntitiesChain() {
-        return proxiedEntitiesChain;
-    }
-
-    public X509Certificate[] getCertificates() {
-        return certificates;
-    }
-
-    @Override
-    public String toString() {
-        return getName();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/90f36dd2/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/x509/X509CertificateExtractor.java
----------------------------------------------------------------------
diff --git a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/x509/X509CertificateExtractor.java b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/x509/X509CertificateExtractor.java
deleted file mode 100644
index ad62b37..0000000
--- a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/x509/X509CertificateExtractor.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.registry.web.security.x509;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.servlet.http.HttpServletRequest;
-import java.security.cert.X509Certificate;
-
-/**
- * Extracts client certificates from Http requests.
- */
-public class X509CertificateExtractor {
-
-    private final Logger logger = LoggerFactory.getLogger(getClass());
-
-    /**
-     * Extract the client certificate from the specified HttpServletRequest or
-     * null if none is specified.
-     *
-     * @param request http request
-     * @return cert
-     */
-    public X509Certificate[] extractClientCertificate(HttpServletRequest request) {
-        X509Certificate[] certs = (X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate");
-
-        if (certs != null && certs.length > 0) {
-            return certs;
-        }
-
-        if (logger.isDebugEnabled()) {
-            logger.debug("No client certificate found in request.");
-        }
-
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/90f36dd2/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/x509/X509CertificateValidator.java
----------------------------------------------------------------------
diff --git a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/x509/X509CertificateValidator.java b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/x509/X509CertificateValidator.java
deleted file mode 100644
index fe2c3e5..0000000
--- a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/x509/X509CertificateValidator.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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.registry.web.security.x509;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.security.cert.CertificateExpiredException;
-import java.security.cert.CertificateNotYetValidException;
-import java.security.cert.X509Certificate;
-
-/**
- * Extracts client certificates from Http requests.
- */
-public class X509CertificateValidator {
-
-    private final Logger logger = LoggerFactory.getLogger(getClass());
-
-    /**
-     * Extract the client certificate from the specified HttpServletRequest or null if none is specified.
-     *
-     * @param certificates the client certificates
-     * @throws CertificateExpiredException cert is expired
-     * @throws CertificateNotYetValidException cert is not yet valid
-     */
-    public void validateClientCertificate(final X509Certificate[] certificates)
-            throws CertificateExpiredException, CertificateNotYetValidException {
-
-        // ensure the cert is valid
-        certificates[0].checkValidity();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/90f36dd2/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/x509/X509IdentityProvider.java
----------------------------------------------------------------------
diff --git a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/x509/X509IdentityProvider.java b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/x509/X509IdentityProvider.java
deleted file mode 100644
index 38aa0b4..0000000
--- a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/x509/X509IdentityProvider.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * 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.registry.web.security.x509;
-
-import org.apache.nifi.registry.web.response.AuthenticationResponse;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.security.web.authentication.preauth.x509.X509PrincipalExtractor;
-
-import java.security.cert.CertificateExpiredException;
-import java.security.cert.CertificateNotYetValidException;
-import java.security.cert.X509Certificate;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Identity provider for extract the authenticating a ServletRequest with a X509Certificate.
- */
-public class X509IdentityProvider {
-
-    private static final Logger logger = LoggerFactory.getLogger(X509IdentityProvider.class);
-
-    private final String issuer = getClass().getSimpleName();
-
-    private X509CertificateValidator certificateValidator;
-    private X509PrincipalExtractor principalExtractor;
-
-    /**
-     * Authenticates the specified request by checking certificate validity.
-     *
-     * @param certificates the client certificates
-     * @return an authentication response
-     * @throws IllegalArgumentException the request did not contain a valid certificate (or no certificate)
-     */
-    public AuthenticationResponse authenticate(final X509Certificate[] certificates) throws IllegalArgumentException {
-        // ensure the cert was found
-        if (certificates == null || certificates.length == 0) {
-            throw new IllegalArgumentException("The specified request does not contain a client certificate.");
-        }
-
-        // extract the principal
-        final Object certificatePrincipal = principalExtractor.extractPrincipal(certificates[0]);
-        final String principal = certificatePrincipal.toString();
-
-        try {
-            certificateValidator.validateClientCertificate(certificates);
-        } catch (CertificateExpiredException cee) {
-            final String message = String.format("Client certificate for (%s) is expired.", principal);
-            logger.info(message, cee);
-            if (logger.isDebugEnabled()) {
-                logger.debug("", cee);
-            }
-            throw new IllegalArgumentException(message, cee);
-        } catch (CertificateNotYetValidException cnyve) {
-            final String message = String.format("Client certificate for (%s) is not yet valid.", principal);
-            logger.info(message, cnyve);
-            if (logger.isDebugEnabled()) {
-                logger.debug("", cnyve);
-            }
-            throw new IllegalArgumentException(message, cnyve);
-        } catch (final Exception e) {
-            logger.info(e.getMessage());
-            if (logger.isDebugEnabled()) {
-                logger.debug("", e);
-            }
-            throw new IllegalArgumentException(e.getMessage(), e);
-        }
-
-        // build the authentication response
-        return new AuthenticationResponse(principal, principal, TimeUnit.MILLISECONDS.convert(12, TimeUnit.HOURS), issuer);
-    }
-
-    /* setters */
-    public void setCertificateValidator(X509CertificateValidator certificateValidator) {
-        this.certificateValidator = certificateValidator;
-    }
-
-    public void setPrincipalExtractor(X509PrincipalExtractor principalExtractor) {
-        this.principalExtractor = principalExtractor;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/90f36dd2/nifi-registry-web-api/src/main/xsd/identity-providers.xsd
----------------------------------------------------------------------
diff --git a/nifi-registry-web-api/src/main/xsd/identity-providers.xsd b/nifi-registry-web-api/src/main/xsd/identity-providers.xsd
new file mode 100644
index 0000000..bcca014
--- /dev/null
+++ b/nifi-registry-web-api/src/main/xsd/identity-providers.xsd
@@ -0,0 +1,50 @@
+<?xml version="1.0"?>
+<!--
+  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.
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+    <!-- role -->
+    <xs:complexType name="Provider">
+        <xs:sequence>
+            <xs:element name="identifier" type="NonEmptyStringType"/>
+            <xs:element name="class" type="NonEmptyStringType"/>
+            <xs:element name="property" type="Property" minOccurs="0" maxOccurs="unbounded" />
+        </xs:sequence>
+    </xs:complexType>
+
+    <!-- Name/Value properties-->
+    <xs:complexType name="Property">
+        <xs:simpleContent>
+            <xs:extension base="xs:string">
+                <xs:attribute name="name" type="NonEmptyStringType"/>
+                <xs:attribute name="encryption" type="xs:string"/>
+            </xs:extension>
+        </xs:simpleContent>
+    </xs:complexType>
+
+    <xs:simpleType name="NonEmptyStringType">
+        <xs:restriction base="xs:string">
+            <xs:minLength value="1"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <!-- login identity provider -->
+    <xs:element name="identityProviders">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="provider" type="Provider" minOccurs="0" maxOccurs="unbounded"/>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+</xs:schema>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/90f36dd2/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/NiFiRegistryApiTestApplication.java
----------------------------------------------------------------------
diff --git a/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/NiFiRegistryApiTestApplication.java b/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/NiFiRegistryApiTestApplication.java
deleted file mode 100644
index 01b0269..0000000
--- a/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/NiFiRegistryApiTestApplication.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.registry;
-
-import org.apache.nifi.registry.db.DataSourceFactory;
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.boot.builder.SpringApplicationBuilder;
-import org.springframework.boot.web.support.SpringBootServletInitializer;
-import org.springframework.context.annotation.ComponentScan;
-import org.springframework.context.annotation.FilterType;
-
-import java.util.Properties;
-
-@SpringBootApplication
-@ComponentScan(
-        excludeFilters = {
-                @ComponentScan.Filter(
-                        type = FilterType.ASSIGNABLE_TYPE,
-                        value = SpringBootServletInitializer.class), // Avoid loading NiFiRegistryApiApplication
-                @ComponentScan.Filter(
-                        type = FilterType.ASSIGNABLE_TYPE,
-                        value = DataSourceFactory.class), // Avoid loading DataSourceFactory
-                @ComponentScan.Filter(
-                        type = FilterType.REGEX,
-                        pattern = "org\\.apache\\.nifi\\.registry\\.NiFiRegistryPropertiesFactory"), // Avoid loading NiFiRegistryPropertiesFactory
-        })
-public class NiFiRegistryApiTestApplication extends SpringBootServletInitializer {
-
-    @Override
-    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
-        final Properties fixedProps = new Properties();
-        fixedProps.setProperty("spring.jpa.hibernate.ddl-auto", "none");
-        fixedProps.setProperty("spring.jpa.hibernate.naming.physical-strategy", "org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl");
-
-        return application
-                .sources(NiFiRegistryApiTestApplication.class)
-                .properties(fixedProps);
-    }
-
-    public static void main(String[] args) {
-        SpringApplication.run(NiFiRegistryApiTestApplication.class, args);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/90f36dd2/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/NiFiRegistryTestApiApplication.java
----------------------------------------------------------------------
diff --git a/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/NiFiRegistryTestApiApplication.java b/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/NiFiRegistryTestApiApplication.java
new file mode 100644
index 0000000..e55fb21
--- /dev/null
+++ b/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/NiFiRegistryTestApiApplication.java
@@ -0,0 +1,40 @@
+/*
+ * 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.registry;
+
+import org.apache.nifi.registry.db.DataSourceFactory;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.web.support.SpringBootServletInitializer;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.FilterType;
+
+@SpringBootApplication
+@ComponentScan(
+        excludeFilters = {
+                @ComponentScan.Filter(
+                        type = FilterType.ASSIGNABLE_TYPE,
+                        value = SpringBootServletInitializer.class), // Avoid loading NiFiRegistryApiApplication
+                @ComponentScan.Filter(
+                        type = FilterType.ASSIGNABLE_TYPE,
+                        value = DataSourceFactory.class), // Avoid loading DataSourceFactory
+                @ComponentScan.Filter(
+                        type = FilterType.REGEX,
+                        pattern = "org\\.apache\\.nifi\\.registry\\.NiFiRegistryPropertiesFactory"), // Avoid loading NiFiRegistryPropertiesFactory
+        })
+public class NiFiRegistryTestApiApplication extends SpringBootServletInitializer {
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/90f36dd2/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/SecureLdapTestApiApplication.java
----------------------------------------------------------------------
diff --git a/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/SecureLdapTestApiApplication.java b/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/SecureLdapTestApiApplication.java
new file mode 100644
index 0000000..fea8349
--- /dev/null
+++ b/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/SecureLdapTestApiApplication.java
@@ -0,0 +1,45 @@
+/*
+ * 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.registry;
+
+import org.apache.nifi.registry.db.DataSourceFactory;
+import org.apache.nifi.registry.security.authorization.AuthorizerFactory;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.web.support.SpringBootServletInitializer;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.FilterType;
+
+@SpringBootApplication
+@ComponentScan(
+        basePackages = "org.apache.nifi.registry",
+        excludeFilters = {
+                @ComponentScan.Filter(
+                        type = FilterType.ASSIGNABLE_TYPE,
+                        value = SpringBootServletInitializer.class), // Avoid loading NiFiRegistryApiApplication
+                @ComponentScan.Filter(
+                        type = FilterType.ASSIGNABLE_TYPE,
+                        value = DataSourceFactory.class), // Avoid loading DataSourceFactory
+                @ComponentScan.Filter(
+                        type = FilterType.ASSIGNABLE_TYPE,
+                        value = AuthorizerFactory.class), // Avoid loading AuthorizerFactory.getAuthorizer(), as we need to add it again with test-specific @DependsOn annotation
+                @ComponentScan.Filter(
+                        type = FilterType.REGEX,
+                        pattern = "org\\.apache\\.nifi\\.registry\\.NiFiRegistryPropertiesFactory"), // Avoid loading NiFiRegistryPropertiesFactory
+        })
+public class SecureLdapTestApiApplication extends SpringBootServletInitializer {
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/90f36dd2/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/web/api/SecureFileIT.java
----------------------------------------------------------------------
diff --git a/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/web/api/SecureFileIT.java b/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/web/api/SecureFileIT.java
index d04e79b..2ca3caa 100644
--- a/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/web/api/SecureFileIT.java
+++ b/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/web/api/SecureFileIT.java
@@ -16,7 +16,7 @@
  */
 package org.apache.nifi.registry.web.api;
 
-import org.apache.nifi.registry.NiFiRegistryApiTestApplication;
+import org.apache.nifi.registry.NiFiRegistryTestApiApplication;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.skyscreamer.jsonassert.JSONAssert;
@@ -39,7 +39,7 @@ import static org.junit.Assert.assertEquals;
  */
 @RunWith(SpringRunner.class)
 @SpringBootTest(
-        classes = NiFiRegistryApiTestApplication.class,
+        classes = NiFiRegistryTestApiApplication.class,
         webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
         properties = "spring.profiles.include=ITSecureFile")
 @Import(SecureITClientConfiguration.class)