http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/kerberos/KerberosIdentityProvider.java
----------------------------------------------------------------------
diff --git 
a/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/kerberos/KerberosIdentityProvider.java
 
b/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/kerberos/KerberosIdentityProvider.java
new file mode 100644
index 0000000..5e6e7bb
--- /dev/null
+++ 
b/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/kerberos/KerberosIdentityProvider.java
@@ -0,0 +1,111 @@
+/*
+ * 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.kerberos;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.registry.security.authentication.AuthenticationRequest;
+import org.apache.nifi.registry.security.authentication.AuthenticationResponse;
+import 
org.apache.nifi.registry.security.authentication.BasicAuthIdentityProvider;
+import 
org.apache.nifi.registry.security.authentication.IdentityProviderConfigurationContext;
+import 
org.apache.nifi.registry.security.authentication.exception.IdentityAccessException;
+import 
org.apache.nifi.registry.security.authentication.exception.InvalidCredentialsException;
+import 
org.apache.nifi.registry.security.exception.SecurityProviderCreationException;
+import 
org.apache.nifi.registry.security.exception.SecurityProviderDestructionException;
+import org.apache.nifi.registry.util.FormatUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import 
org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.AuthenticationException;
+import 
org.springframework.security.kerberos.authentication.KerberosAuthenticationProvider;
+import 
org.springframework.security.kerberos.authentication.sun.SunJaasKerberosClient;
+
+import java.util.concurrent.TimeUnit;
+
+public class KerberosIdentityProvider extends BasicAuthIdentityProvider {
+
+    private static final Logger logger = 
LoggerFactory.getLogger(KerberosIdentityProvider.class);
+    private static final String issuer = 
KerberosIdentityProvider.class.getSimpleName();
+    private static final String default_expiration = "12 hours";
+
+    private KerberosAuthenticationProvider provider;
+
+    private long expiration;
+
+    @Override
+    public void onConfigured(IdentityProviderConfigurationContext 
configurationContext) throws SecurityProviderCreationException {
+
+        String rawDebug = configurationContext.getProperty("Enable Debug");
+        boolean enableDebug = (rawDebug != null && 
rawDebug.equalsIgnoreCase("true"));
+
+        String rawExpiration = 
configurationContext.getProperty("Authentication Expiration");
+        if (StringUtils.isBlank(rawExpiration)) {
+            rawExpiration = default_expiration;
+            logger.info("No Authentication Expiration specified, defaulting to 
" + default_expiration);
+        }
+
+        try {
+            expiration = FormatUtils.getTimeDuration(rawExpiration, 
TimeUnit.MILLISECONDS);
+        } catch (final IllegalArgumentException iae) {
+            throw new SecurityProviderCreationException(
+                    String.format("The Expiration Duration '%s' is not a valid 
time duration", rawExpiration));
+        }
+
+        provider = new KerberosAuthenticationProvider();
+        SunJaasKerberosClient client = new SunJaasKerberosClient();
+        client.setDebug(enableDebug);
+        provider.setKerberosClient(client);
+        provider.setUserDetailsService(new KerberosUserDetailsService());
+
+    }
+
+    @Override
+    public AuthenticationResponse authenticate(AuthenticationRequest 
authenticationRequest) throws InvalidCredentialsException, 
IdentityAccessException {
+
+        if (provider == null) {
+            throw new IdentityAccessException("The Kerberos authentication 
provider is not initialized.");
+        }
+
+        try {
+            // perform the authentication
+            final String username = authenticationRequest.getUsername();
+            final Object credentials = authenticationRequest.getCredentials();
+            final String password = credentials != null && credentials 
instanceof String ? (String) credentials : null;
+
+            // perform the authentication
+            final UsernamePasswordAuthenticationToken token = new 
UsernamePasswordAuthenticationToken(username, credentials);
+            logger.debug("Created authentication token " + token.toString());
+
+            final Authentication authentication = provider.authenticate(token);
+            logger.debug("Ran provider.authenticate(token) and returned 
authentication for " +
+                    "principal={} with name={} and isAuthenticated={}",
+                    authentication.getPrincipal(),
+                    authentication.getName(),
+                    authentication.isAuthenticated());
+
+            return new AuthenticationResponse(authentication.getName(), 
username, expiration, issuer);
+        } catch (final AuthenticationException e) {
+            throw new InvalidCredentialsException(e.getMessage(), e);
+        }
+
+    }
+
+    @Override
+    public void preDestruction() throws SecurityProviderDestructionException {
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/kerberos/KerberosSpnegoFactory.java
----------------------------------------------------------------------
diff --git 
a/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/kerberos/KerberosSpnegoFactory.java
 
b/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/kerberos/KerberosSpnegoFactory.java
new file mode 100644
index 0000000..16211ed
--- /dev/null
+++ 
b/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/kerberos/KerberosSpnegoFactory.java
@@ -0,0 +1,67 @@
+/*
+ * 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.kerberos;
+
+import org.apache.nifi.registry.properties.NiFiRegistryProperties;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import 
org.springframework.security.kerberos.authentication.KerberosServiceAuthenticationProvider;
+import 
org.springframework.security.kerberos.authentication.KerberosTicketValidator;
+
+@Configuration
+public class KerberosSpnegoFactory {
+
+    @Autowired
+    private NiFiRegistryProperties properties;
+
+    @Autowired(required = false)
+    private KerberosTicketValidator kerberosTicketValidator;
+
+    private KerberosServiceAuthenticationProvider 
kerberosServiceAuthenticationProvider;
+    private KerberosSpnegoIdentityProvider kerberosSpnegoIdentityProvider;
+
+    @Bean
+    public KerberosSpnegoIdentityProvider kerberosSpnegoIdentityProvider() 
throws Exception {
+
+        if (kerberosSpnegoIdentityProvider == null && 
properties.isKerberosSpnegoSupportEnabled()) {
+            kerberosSpnegoIdentityProvider = new 
KerberosSpnegoIdentityProvider(
+                    kerberosServiceAuthenticationProvider(),
+                    properties);
+        }
+
+        return kerberosSpnegoIdentityProvider;
+    }
+
+
+    private KerberosServiceAuthenticationProvider 
kerberosServiceAuthenticationProvider() throws Exception {
+
+        if (kerberosServiceAuthenticationProvider == null && 
properties.isKerberosSpnegoSupportEnabled()) {
+
+            KerberosServiceAuthenticationProvider ksap = new 
KerberosServiceAuthenticationProvider();
+            ksap.setTicketValidator(kerberosTicketValidator);
+            ksap.setUserDetailsService(new KerberosUserDetailsService());
+            ksap.afterPropertiesSet();
+
+            kerberosServiceAuthenticationProvider = ksap;
+
+        }
+
+        return kerberosServiceAuthenticationProvider;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/kerberos/KerberosSpnegoIdentityProvider.java
----------------------------------------------------------------------
diff --git 
a/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/kerberos/KerberosSpnegoIdentityProvider.java
 
b/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/kerberos/KerberosSpnegoIdentityProvider.java
new file mode 100644
index 0000000..e611b53
--- /dev/null
+++ 
b/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/kerberos/KerberosSpnegoIdentityProvider.java
@@ -0,0 +1,184 @@
+/*
+ * 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.kerberos;
+
+import org.apache.nifi.registry.properties.NiFiRegistryProperties;
+import org.apache.nifi.registry.security.authentication.AuthenticationRequest;
+import org.apache.nifi.registry.security.authentication.AuthenticationResponse;
+import org.apache.nifi.registry.security.authentication.IdentityProvider;
+import 
org.apache.nifi.registry.security.authentication.IdentityProviderConfigurationContext;
+import org.apache.nifi.registry.security.authentication.IdentityProviderUsage;
+import 
org.apache.nifi.registry.security.authentication.exception.IdentityAccessException;
+import 
org.apache.nifi.registry.security.authentication.exception.InvalidCredentialsException;
+import 
org.apache.nifi.registry.security.exception.SecurityProviderCreationException;
+import 
org.apache.nifi.registry.security.exception.SecurityProviderDestructionException;
+import org.apache.nifi.registry.security.util.CryptoUtils;
+import org.apache.nifi.registry.util.FormatUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.lang.Nullable;
+import org.springframework.security.authentication.AuthenticationDetailsSource;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.crypto.codec.Base64;
+import 
org.springframework.security.kerberos.authentication.KerberosServiceAuthenticationProvider;
+import 
org.springframework.security.kerberos.authentication.KerberosServiceRequestToken;
+import 
org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.http.HttpServletRequest;
+import java.nio.charset.StandardCharsets;
+import java.util.concurrent.TimeUnit;
+
+@Component
+public class KerberosSpnegoIdentityProvider implements IdentityProvider {
+
+    private static final Logger logger = 
LoggerFactory.getLogger(KerberosSpnegoIdentityProvider.class);
+
+    private static final String issuer = 
KerberosSpnegoIdentityProvider.class.getSimpleName();
+
+    private static final IdentityProviderUsage usage = new 
IdentityProviderUsage() {
+        @Override
+        public String getText() {
+            return "The Kerberos user credentials must be passed in the HTTP 
Authorization header as specified by SPNEGO-based Kerberos. " +
+                    "That is: 'Authorization: Negotiate <kerberosTicket>', " +
+                    "where <kerberosTicket> is a value that will be validated 
by this identity provider against a Kerberos cluster.";
+        }
+
+        @Override
+        public AuthType getAuthType() {
+            return AuthType.NEGOTIATE;
+        }
+    };
+
+    private static final String AUTHORIZATION = "Authorization";
+    private static final String AUTHORIZATION_NEGOTIATE = "Negotiate";
+
+    private long expiration = TimeUnit.MILLISECONDS.convert(12, 
TimeUnit.HOURS);;
+    private KerberosServiceAuthenticationProvider 
kerberosServiceAuthenticationProvider;
+    private AuthenticationDetailsSource<HttpServletRequest, ?> 
authenticationDetailsSource;
+
+    @Autowired
+    public KerberosSpnegoIdentityProvider(
+            @Nullable  KerberosServiceAuthenticationProvider 
kerberosServiceAuthenticationProvider,
+            NiFiRegistryProperties properties) {
+        this.kerberosServiceAuthenticationProvider = 
kerberosServiceAuthenticationProvider;
+        authenticationDetailsSource = new WebAuthenticationDetailsSource();
+
+        final String expirationFromProperties = 
properties.getKerberosSpnegoAuthenticationExpiration();
+        if (expirationFromProperties != null) {
+            long expiration = 
FormatUtils.getTimeDuration(expirationFromProperties, TimeUnit.MILLISECONDS);
+        }
+    }
+
+    @Override
+    public IdentityProviderUsage getUsageInstructions() {
+        return usage;
+    }
+
+    @Override
+    public AuthenticationRequest extractCredentials(HttpServletRequest 
request) {
+
+        // Only support Kerberos authentication when running securely
+        if (!request.isSecure()) {
+            return null;
+        }
+
+        String headerValue = request.getHeader(AUTHORIZATION);
+
+        if (!isValidKerberosHeader(headerValue)) {
+            return null;
+        }
+
+        logger.debug("Detected 'Authorization: Negotiate header in request 
{}", request.getRequestURL());
+        byte[] base64Token = headerValue.substring(headerValue.indexOf(" ") + 
1).getBytes(StandardCharsets.UTF_8);
+        byte[] kerberosTicket = Base64.decode(base64Token);
+        if (kerberosTicket != null) {
+            logger.debug("Successfully decoded SPNEGO/Kerberos ticket passed 
in Authorization: Negotiate <ticket> header.", request.getRequestURL());
+        }
+
+        return new AuthenticationRequest(null, kerberosTicket, 
authenticationDetailsSource.buildDetails(request));
+
+    }
+
+    @Override
+    public AuthenticationResponse authenticate(AuthenticationRequest 
authenticationRequest) throws InvalidCredentialsException, 
IdentityAccessException {
+
+        if (authenticationRequest == null) {
+            logger.info("Cannot authenticate null authenticationRequest, 
returning null.");
+            return null;
+        }
+
+        final Object credentials = authenticationRequest.getCredentials();
+        byte[] kerberosTicket = credentials != null && credentials instanceof 
byte[] ? (byte[]) authenticationRequest.getCredentials() : null;
+
+        if (credentials == null) {
+            logger.info("Kerberos Ticket not found in authenticationRequest 
credentials, returning null.");
+            return null;
+        }
+
+        if (kerberosServiceAuthenticationProvider == null) {
+            throw new IdentityAccessException("The Kerberos authentication 
provider is not initialized.");
+        }
+
+        try {
+            KerberosServiceRequestToken kerberosServiceRequestToken = new 
KerberosServiceRequestToken(kerberosTicket);
+            
kerberosServiceRequestToken.setDetails(authenticationRequest.getDetails());
+            Authentication authentication = 
kerberosServiceAuthenticationProvider.authenticate(kerberosServiceRequestToken);
+            if (authentication == null) {
+                throw new InvalidCredentialsException("Kerberos credentials 
could not be authenticated.");
+            }
+
+            final String kerberosPrincipal = authentication.getName();
+
+            return new AuthenticationResponse(kerberosPrincipal, 
kerberosPrincipal, expiration, issuer);
+
+        } catch (AuthenticationException e) {
+            String authFailedMessage = "Kerberos credentials could not be 
authenticated.";
+
+            /* Kerberos uses encryption with up to AES-256, specifically 
AES256-CTS-HMAC-SHA1-96.
+             * That is not available in every JRE, particularly if Unlimited 
Strength Encryption
+             * policies are not installed in the Java home lib dir. The 
Kerberos lib does not
+             * differentiate between failures due to decryption and those due 
to bad credentials
+             * without walking the causes of the exception, so this check puts 
something
+             * potentially useful in the logs for those troubleshooting 
Kerberos authentication. */
+            if (!Boolean.FALSE.equals(CryptoUtils.isCryptoRestricted())) {
+                authFailedMessage += " This Java Runtime does not support 
unlimited strength encryption. " +
+                        "This could cause Kerberos authentication to fail as 
it can require AES-256.";
+            }
+
+            logger.info(authFailedMessage);
+            throw new InvalidCredentialsException(authFailedMessage, e);
+        }
+
+    }
+
+    @Override
+    public void onConfigured(IdentityProviderConfigurationContext 
configurationContext) throws SecurityProviderCreationException {
+        throw new 
SecurityProviderCreationException(KerberosSpnegoIdentityProvider.class.getSimpleName()
 +
+                " does not currently support being loaded via 
IdentityProviderFactory");
+    }
+
+    @Override
+    public void preDestruction() throws SecurityProviderDestructionException {
+    }
+
+    public boolean isValidKerberosHeader(String headerValue) {
+        return headerValue != null && 
(headerValue.startsWith(AUTHORIZATION_NEGOTIATE + " ") || 
headerValue.startsWith("Kerberos "));
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/kerberos/KerberosTicketValidatorFactory.java
----------------------------------------------------------------------
diff --git 
a/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/kerberos/KerberosTicketValidatorFactory.java
 
b/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/kerberos/KerberosTicketValidatorFactory.java
new file mode 100644
index 0000000..ed3e6eb
--- /dev/null
+++ 
b/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/kerberos/KerberosTicketValidatorFactory.java
@@ -0,0 +1,69 @@
+/*
+ * 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.kerberos;
+
+import org.apache.nifi.registry.properties.NiFiRegistryProperties;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.io.FileSystemResource;
+import 
org.springframework.security.kerberos.authentication.KerberosTicketValidator;
+import 
org.springframework.security.kerberos.authentication.sun.GlobalSunJaasKerberosConfig;
+import 
org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator;
+
+import java.io.File;
+
+@Configuration
+public class KerberosTicketValidatorFactory {
+
+    private NiFiRegistryProperties properties;
+
+    private KerberosTicketValidator kerberosTicketValidator;
+
+    @Autowired
+    public KerberosTicketValidatorFactory(NiFiRegistryProperties properties) {
+        this.properties = properties;
+    }
+
+    @Bean
+    public KerberosTicketValidator kerberosTicketValidator() throws Exception {
+
+        if (kerberosTicketValidator == null && 
properties.isKerberosSpnegoSupportEnabled()) {
+
+            // Configure SunJaasKerberos (global)
+            final File krb5ConfigFile = 
properties.getKerberosConfigurationFile();
+            if (krb5ConfigFile != null) {
+                final GlobalSunJaasKerberosConfig krb5Config = new 
GlobalSunJaasKerberosConfig();
+                
krb5Config.setKrbConfLocation(krb5ConfigFile.getAbsolutePath());
+                krb5Config.afterPropertiesSet();
+            }
+
+            // Create ticket validator to inject into 
KerberosServiceAuthenticationProvider
+            SunJaasKerberosTicketValidator ticketValidator = new 
SunJaasKerberosTicketValidator();
+            
ticketValidator.setServicePrincipal(properties.getKerberosSpnegoPrincipal());
+            ticketValidator.setKeyTabLocation(new 
FileSystemResource(properties.getKerberosSpnegoKeytabLocation()));
+            ticketValidator.afterPropertiesSet();
+
+            kerberosTicketValidator = ticketValidator;
+
+        }
+
+        return kerberosTicketValidator;
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/kerberos/KerberosUserDetailsService.java
----------------------------------------------------------------------
diff --git 
a/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/kerberos/KerberosUserDetailsService.java
 
b/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/kerberos/KerberosUserDetailsService.java
new file mode 100644
index 0000000..5471906
--- /dev/null
+++ 
b/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/kerberos/KerberosUserDetailsService.java
@@ -0,0 +1,38 @@
+/*
+ * 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.kerberos;
+
+import org.springframework.security.core.authority.AuthorityUtils;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+
+public class KerberosUserDetailsService implements UserDetailsService {
+
+    @Override
+    public UserDetails loadUserByUsername(String username) throws 
UsernameNotFoundException {
+        return new User(
+                username,
+                "notUsed",
+                true,
+                true,
+                true,
+                true,
+                AuthorityUtils.createAuthorityList("ROLE_USER"));
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/SubjectDnX509PrincipalExtractor.java
----------------------------------------------------------------------
diff --git 
a/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/SubjectDnX509PrincipalExtractor.java
 
b/nifi-registry-core/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-core/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/6f26290d/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/X509CertificateExtractor.java
----------------------------------------------------------------------
diff --git 
a/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/X509CertificateExtractor.java
 
b/nifi-registry-core/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-core/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/6f26290d/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/X509IdentityAuthenticationProvider.java
----------------------------------------------------------------------
diff --git 
a/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/X509IdentityAuthenticationProvider.java
 
b/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/X509IdentityAuthenticationProvider.java
new file mode 100644
index 0000000..aefdd5b
--- /dev/null
+++ 
b/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/X509IdentityAuthenticationProvider.java
@@ -0,0 +1,131 @@
+/*
+ * 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.properties.NiFiRegistryProperties;
+import org.apache.nifi.registry.security.authentication.AuthenticationRequest;
+import 
org.apache.nifi.registry.web.security.authentication.AuthenticationRequestToken;
+import org.apache.nifi.registry.security.authentication.AuthenticationResponse;
+import org.apache.nifi.registry.security.authentication.IdentityProvider;
+import 
org.apache.nifi.registry.web.security.authentication.IdentityAuthenticationProvider;
+import 
org.apache.nifi.registry.web.security.authentication.AuthenticationSuccessToken;
+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.exception.AccessDeniedException;
+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.security.util.ProxiedEntitiesUtils;
+import 
org.apache.nifi.registry.web.security.authentication.exception.UntrustedProxyException;
+
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Set;
+
+public class X509IdentityAuthenticationProvider extends 
IdentityAuthenticationProvider {
+
+    private static final Authorizable PROXY_AUTHORIZABLE = new Authorizable() {
+        @Override
+        public Authorizable getParentAuthorizable() {
+            return null;
+        }
+
+        @Override
+        public Resource getResource() {
+            return ResourceFactory.getProxyResource();
+        }
+    };
+
+    public X509IdentityAuthenticationProvider(NiFiRegistryProperties 
properties, Authorizer authorizer, IdentityProvider identityProvider) {
+        super(properties, authorizer, identityProvider);
+    }
+
+    @Override
+    protected AuthenticationSuccessToken buildAuthenticatedToken(
+            AuthenticationRequestToken requestToken,
+            AuthenticationResponse response) {
+
+        AuthenticationRequest authenticationRequest = 
requestToken.getAuthenticationRequest();
+
+        String proxiedEntitiesChain = authenticationRequest.getDetails() != 
null
+                ? (String)authenticationRequest.getDetails()
+                : null;
+
+        if (StringUtils.isBlank(proxiedEntitiesChain)) {
+            return super.buildAuthenticatedToken(requestToken, response);
+        }
+
+        // build the entire proxy chain if applicable - 
<end-user><proxy1><proxy2>
+        final List<String> proxyChain = 
ProxiedEntitiesUtils.tokenizeProxiedEntitiesChain(proxiedEntitiesChain);
+        proxyChain.add(response.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) ? 
requestToken.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 AuthenticationSuccessToken(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
+     */
+    private 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();
+        }
+    }
+
+
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/X509IdentityProvider.java
----------------------------------------------------------------------
diff --git 
a/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/X509IdentityProvider.java
 
b/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/X509IdentityProvider.java
new file mode 100644
index 0000000..2a1856e
--- /dev/null
+++ 
b/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/X509IdentityProvider.java
@@ -0,0 +1,174 @@
+/*
+ * 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.security.authentication.AuthenticationRequest;
+import org.apache.nifi.registry.security.authentication.AuthenticationResponse;
+import org.apache.nifi.registry.security.authentication.IdentityProvider;
+import 
org.apache.nifi.registry.security.authentication.IdentityProviderConfigurationContext;
+import org.apache.nifi.registry.security.authentication.IdentityProviderUsage;
+import 
org.apache.nifi.registry.security.authentication.exception.InvalidCredentialsException;
+import 
org.apache.nifi.registry.security.exception.SecurityProviderCreationException;
+import 
org.apache.nifi.registry.security.exception.SecurityProviderDestructionException;
+import org.apache.nifi.registry.security.util.ProxiedEntitiesUtils;
+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 javax.servlet.http.HttpServletRequest;
+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 implements IdentityProvider {
+
+    private static final Logger logger = 
LoggerFactory.getLogger(X509IdentityProvider.class);
+
+    private static final String issuer = 
X509IdentityProvider.class.getSimpleName();
+
+    private static final long expiration = TimeUnit.MILLISECONDS.convert(12, 
TimeUnit.HOURS);
+
+    private static final IdentityProviderUsage usage = new 
IdentityProviderUsage() {
+        @Override
+        public String getText() {
+            return "The client must connect over HTTPS and must provide a 
client certificate during the TLS handshake. " +
+                    "Additionally, the client may declare itself a proxy for 
another user identity by populating the " +
+                    ProxiedEntitiesUtils.PROXY_ENTITIES_CHAIN + " HTTP header 
field with a value of the format " +
+                    
"'<end-user-identity><proxy1-identity><proxy2-identity>...<proxyN-identity>'" +
+                    "for all identities in the chain prior to this client. If 
the " + ProxiedEntitiesUtils.PROXY_ENTITIES_CHAIN +
+                    " header is present in the request, this client's identity 
will be extracted from the client certificate " +
+                    "used for TLS and added to the end of the chain, and then 
the entire chain will be authorized. Each proxy " +
+                    "will be authorized to have 'write' access to '/proxy', 
and the originating user identity will be " +
+                    "authorized for access to the resource being accessed in 
the request.";
+        }
+
+        @Override
+        public AuthType getAuthType() {
+            return AuthType.OTHER.httpAuthScheme("TLS-client-cert");
+        }
+    };
+
+    private X509PrincipalExtractor principalExtractor;
+    private X509CertificateExtractor certificateExtractor;
+
+    @Autowired
+    public X509IdentityProvider(X509PrincipalExtractor principalExtractor, 
X509CertificateExtractor certificateExtractor) {
+        this.principalExtractor = principalExtractor;
+        this.certificateExtractor = certificateExtractor;
+    }
+
+    @Override
+    public IdentityProviderUsage getUsageInstructions() {
+        return usage;
+    }
+
+    /**
+     * Extracts certificate-based credentials from an {@link 
HttpServletRequest}.
+     *
+     * The resulting {@link AuthenticationRequest} will be populated as:
+     *  - username: principal DN from first client cert
+     *  - credentials: first client certificate (X509Certificate)
+     *  - details: proxied-entities chain (String)
+     *
+     * @param servletRequest the {@link HttpServletRequest} request that may 
contain credentials understood by this IdentityProvider
+     * @return a populated AuthenticationRequest or null if the credentials 
could not be found.
+     */
+    @Override
+    public AuthenticationRequest extractCredentials(HttpServletRequest 
servletRequest) {
+
+        // only support x509 login when running securely
+        if (!servletRequest.isSecure()) {
+            return null;
+        }
+
+        // look for a client certificate
+        final X509Certificate[] certificates = 
certificateExtractor.extractClientCertificate(servletRequest);
+        if (certificates == null || certificates.length == 0) {
+            return null;
+        }
+
+        // extract the principal
+        final Object certificatePrincipal = 
principalExtractor.extractPrincipal(certificates[0]);
+        final String principal = certificatePrincipal.toString();
+
+        // extract the proxiedEntitiesChain header value from the 
servletRequest
+        String proxiedEntitiesChainHeader = 
servletRequest.getHeader(ProxiedEntitiesUtils.PROXY_ENTITIES_CHAIN);
+
+        return new AuthenticationRequest(principal, certificates[0], 
proxiedEntitiesChainHeader);
+
+    }
+
+    /**
+     * For a given {@link AuthenticationRequest}, this validates the client 
certificate and creates a populated {@link AuthenticationResponse}.
+     *
+     * The {@link AuthenticationRequest} authenticationRequest paramenter is 
expected to be populated as:
+     *  - username: principal DN from first client cert
+     *  - credentials: first client certificate (X509Certificate)
+     *  - details: proxied-entities chain (String)
+     *
+     * @param authenticationRequest the request, containing identity claim 
credentials for the IdentityProvider to authenticate and determine an identity
+     */
+    @Override
+    public AuthenticationResponse authenticate(AuthenticationRequest 
authenticationRequest) throws InvalidCredentialsException {
+
+        if (authenticationRequest == null || 
authenticationRequest.getUsername() == null) {
+            return null;
+        }
+
+        String principal = authenticationRequest.getUsername();
+
+        try {
+            X509Certificate clientCertificate = 
(X509Certificate)authenticationRequest.getCredentials();
+            validateClientCertificate(clientCertificate);
+        } catch (CertificateExpiredException cee) {
+            final String message = String.format("Client certificate for (%s) 
is expired.", principal);
+            logger.warn(message, cee);
+            throw new InvalidCredentialsException(message, cee);
+        } catch (CertificateNotYetValidException cnyve) {
+            final String message = String.format("Client certificate for (%s) 
is not yet valid.", principal);
+            logger.warn(message, cnyve);
+            throw new InvalidCredentialsException(message, cnyve);
+        } catch (final Exception e) {
+            logger.warn(e.getMessage(), e);
+        }
+
+        // build the authentication response
+        return new AuthenticationResponse(principal, principal, expiration, 
issuer);
+    }
+
+    @Override
+    public void onConfigured(IdentityProviderConfigurationContext 
configurationContext) throws SecurityProviderCreationException {
+        throw new 
SecurityProviderCreationException(X509IdentityProvider.class.getSimpleName() +
+                " does not currently support being loaded via 
IdentityProviderFactory");
+    }
+
+    @Override
+    public void preDestruction() throws SecurityProviderDestructionException {}
+
+
+    private void validateClientCertificate(X509Certificate certificate) throws 
CertificateExpiredException, CertificateNotYetValidException {
+        certificate.checkValidity();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authorization/HttpMethodAuthorizationRules.java
----------------------------------------------------------------------
diff --git 
a/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authorization/HttpMethodAuthorizationRules.java
 
b/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authorization/HttpMethodAuthorizationRules.java
new file mode 100644
index 0000000..c940359
--- /dev/null
+++ 
b/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authorization/HttpMethodAuthorizationRules.java
@@ -0,0 +1,48 @@
+/*
+ * 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.authorization;
+
+import org.apache.nifi.registry.security.authorization.RequestAction;
+import org.springframework.http.HttpMethod;
+
+public interface HttpMethodAuthorizationRules {
+
+    default boolean requiresAuthorization(HttpMethod httpMethod) {
+        return true;
+    }
+
+    default RequestAction mapHttpMethodToAction(HttpMethod httpMethod) {
+
+        switch (httpMethod) {
+            case TRACE:
+            case OPTIONS:
+            case HEAD:
+            case GET:
+                return RequestAction.READ;
+            case POST:
+            case PUT:
+            case PATCH:
+                return RequestAction.WRITE;
+            case DELETE:
+                return RequestAction.DELETE;
+            default:
+                throw new IllegalArgumentException("Unknown http method: " + 
httpMethod);
+        }
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authorization/ResourceAuthorizationFilter.java
----------------------------------------------------------------------
diff --git 
a/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authorization/ResourceAuthorizationFilter.java
 
b/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authorization/ResourceAuthorizationFilter.java
new file mode 100644
index 0000000..6e551e1
--- /dev/null
+++ 
b/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authorization/ResourceAuthorizationFilter.java
@@ -0,0 +1,218 @@
+/*
+ * 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.authorization;
+
+import org.apache.nifi.registry.security.authorization.AuthorizableLookup;
+import org.apache.nifi.registry.security.authorization.RequestAction;
+import 
org.apache.nifi.registry.security.authorization.exception.AccessDeniedException;
+import org.apache.nifi.registry.security.authorization.resource.Authorizable;
+import org.apache.nifi.registry.security.authorization.resource.ResourceType;
+import org.apache.nifi.registry.security.authorization.user.NiFiUser;
+import org.apache.nifi.registry.security.authorization.user.NiFiUserUtils;
+import org.apache.nifi.registry.service.AuthorizationService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpMethod;
+import org.springframework.web.filter.GenericFilterBean;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * This filter is designed to perform a resource authorization check in the 
Spring Security filter chain.
+ *
+ * It authorizes the current authenticated user for the {@link RequestAction} 
(based on the HttpMethod) requested
+ * on the {@link ResourceType} (based on the URI path).
+ *
+ * This filter is designed to be place after any authentication and before any 
application endpoints.
+ *
+ * This filter can be used in place of or in addition to authorization checks 
that occur in the application
+ * downstream of this filter.
+ *
+ * To configure this filter, provide an {@link AuthorizationService} that will 
be used to perform the authorization
+ * check, as well as a set of rules that control which resource and HTTP 
methods are handled by this filter.
+ *
+ * Any (ResourceType, HttpMethod) pair that is not configured to require 
authorization by this filter will be
+ * allowed to proceed in the filter chain without an authorization check.
+ *
+ * Any (ResourceType, HttpMethod) pair that is configured to require 
authorization by this filter will map
+ * the HttpMethod to a NiFi Registry RequestAction (configurable when creating 
this filter), and the
+ * (Resource Authorizable, RequestAction) pair will be sent to the 
AuthorizationService, which will use the
+ * configured Authorizer to authorize the current user for the action on the 
requested resource.
+ */
+public class ResourceAuthorizationFilter extends GenericFilterBean {
+
+    private static final Logger logger = 
LoggerFactory.getLogger(ResourceAuthorizationFilter.class);
+
+    private Map<ResourceType, HttpMethodAuthorizationRules> 
resourceTypeAuthorizationRules;
+    private AuthorizationService authorizationService;
+    private AuthorizableLookup authorizableLookup;
+
+    ResourceAuthorizationFilter(Builder builder) {
+        if (builder.getAuthorizationService() == null || 
builder.getResourceTypeAuthorizationRules() == null) {
+            throw new IllegalArgumentException("Builder is missing one or more 
required fields [authorizationService, resourceTypeAuthorizationRules].");
+        }
+        this.resourceTypeAuthorizationRules = 
builder.getResourceTypeAuthorizationRules();
+        this.authorizationService = builder.getAuthorizationService();
+        this.authorizableLookup = 
this.authorizationService.getAuthorizableLookup();
+    }
+
+    @Override
+    public void doFilter(ServletRequest servletRequest, ServletResponse 
servletResponse, FilterChain filterChain) throws IOException, ServletException {
+
+        HttpServletRequest httpServletRequest = (HttpServletRequest) 
servletRequest;
+        HttpServletResponse httpServletResponse = (HttpServletResponse) 
servletResponse;
+
+        boolean authorizationCheckIsRequired = false;
+        String resourcePath = null;
+        RequestAction action = null;
+
+        // Only require authorization if the NiFi Registry is running securely.
+        if (servletRequest.isSecure()) {
+
+            // Only require authorization for resources for which this filter 
has been configured
+            resourcePath = httpServletRequest.getServletPath();
+            if (resourcePath != null) {
+                final ResourceType resourceType = 
ResourceType.mapFullResourcePathToResourceType(resourcePath);
+                final HttpMethodAuthorizationRules authorizationRules = 
resourceTypeAuthorizationRules.get(resourceType);
+                if (authorizationRules != null) {
+                    final String httpMethodStr = 
httpServletRequest.getMethod().toUpperCase();
+                    HttpMethod httpMethod = HttpMethod.resolve(httpMethodStr);
+
+                    // Only require authorization for HTTP methods included in 
this resource type's rule set
+                    if (httpMethod != null && 
authorizationRules.requiresAuthorization(httpMethod)) {
+                        authorizationCheckIsRequired = true;
+                        action = 
authorizationRules.mapHttpMethodToAction(httpMethod);
+                    }
+                }
+            }
+        }
+
+        if (!authorizationCheckIsRequired) {
+            forwardRequestWithoutAuthorizationCheck(httpServletRequest, 
httpServletResponse, filterChain);
+            return;
+        }
+
+        // Perform authorization check
+        try {
+            authorizeAccess(resourcePath, action);
+            successfulAuthorization(httpServletRequest, httpServletResponse, 
filterChain);
+        } catch (Exception e) {
+            logger.debug("Exception occurred while performing authorization 
check.", e);
+            failedAuthorization(httpServletRequest, httpServletResponse, 
filterChain, e);
+        }
+    }
+
+    private boolean userIsAuthenticated() {
+        NiFiUser user = NiFiUserUtils.getNiFiUser();
+        return (user != null && !user.isAnonymous());
+    }
+
+    private void authorizeAccess(String path, RequestAction action) throws 
AccessDeniedException {
+
+        if (path == null || action == null) {
+            throw new IllegalArgumentException("Authorization is required, but 
a required input [resource, action] is absent.");
+        }
+
+        Authorizable authorizable = 
authorizableLookup.getAuthorizableByResource(path);
+
+        if (authorizable == null) {
+            throw new IllegalStateException("Resource Authorization Filter 
configured for non-authorizable resource: " + path);
+        }
+
+        // throws AccessDeniedException if current user is not authorized to 
perform requested action on resource
+        authorizationService.authorize(authorizable, action);
+    }
+
+    private void forwardRequestWithoutAuthorizationCheck(HttpServletRequest 
req, HttpServletResponse res, FilterChain chain) throws IOException, 
ServletException {
+        logger.debug("Request filter authorization check is not required for 
this HTTP Method on this resource. " +
+                "Allowing request to proceed. An additional authorization 
check might be performed downstream of this filter.");
+        chain.doFilter(req, res);
+    }
+
+    private void successfulAuthorization(HttpServletRequest req, 
HttpServletResponse res, FilterChain chain) throws IOException, 
ServletException {
+        logger.debug("Request filter authorization check passed. Allowing 
request to proceed.");
+        chain.doFilter(req, res);
+    }
+
+    private void failedAuthorization(HttpServletRequest request, 
HttpServletResponse response, FilterChain chain, Exception failure) throws 
IOException, ServletException {
+        logger.debug("Request filter authorization check failed. Blocking 
access.");
+
+        NiFiUser user = NiFiUserUtils.getNiFiUser();
+        final String identity = (user != null) ? user.toString() : "<no user 
found>";
+        final int status = !userIsAuthenticated() ? 
HttpServletResponse.SC_UNAUTHORIZED : HttpServletResponse.SC_FORBIDDEN;
+
+        logger.info("{} does not have permission to perform this action on the 
requested resource. {} Returning {} response.", identity, failure.getMessage(), 
status);
+        logger.debug("", failure);
+
+        if (!response.isCommitted()) {
+            response.setStatus(status);
+            response.setContentType("text/plain");
+            response.getWriter().println(String.format("Access is denied due 
to: %s Contact the system administrator.", failure.getLocalizedMessage()));
+        }
+    }
+
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    public static class Builder {
+
+        private AuthorizationService authorizationService;
+        final private Map<ResourceType, HttpMethodAuthorizationRules> 
resourceTypeAuthorizationRules;
+
+        // create via ResourceAuthorizationFilter.builder()
+        private Builder() {
+            this.resourceTypeAuthorizationRules = new HashMap<>();
+        }
+
+        public AuthorizationService getAuthorizationService() {
+            return authorizationService;
+        }
+
+        public Builder setAuthorizationService(AuthorizationService 
authorizationService) {
+            this.authorizationService = authorizationService;
+            return this;
+        }
+
+        public Map<ResourceType, HttpMethodAuthorizationRules> 
getResourceTypeAuthorizationRules() {
+            return resourceTypeAuthorizationRules;
+        }
+
+        public Builder addResourceType(ResourceType resourceType) {
+            this.resourceTypeAuthorizationRules.put(resourceType, new 
HttpMethodAuthorizationRules() {});
+            return this;
+        }
+
+        public Builder addResourceType(ResourceType resourceType, 
HttpMethodAuthorizationRules authorizationRules) {
+            this.resourceTypeAuthorizationRules.put(resourceType, 
authorizationRules);
+            return this;
+        }
+
+        public ResourceAuthorizationFilter build() {
+            return new ResourceAuthorizationFilter(this);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authorization/StandardHttpMethodAuthorizationRules.java
----------------------------------------------------------------------
diff --git 
a/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authorization/StandardHttpMethodAuthorizationRules.java
 
b/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authorization/StandardHttpMethodAuthorizationRules.java
new file mode 100644
index 0000000..daa5a37
--- /dev/null
+++ 
b/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authorization/StandardHttpMethodAuthorizationRules.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.web.security.authorization;
+
+import org.springframework.http.HttpMethod;
+
+import java.util.EnumSet;
+import java.util.Set;
+
+public class StandardHttpMethodAuthorizationRules implements 
HttpMethodAuthorizationRules {
+
+    final private Set<HttpMethod> methodsRequiringAuthorization;
+
+    public StandardHttpMethodAuthorizationRules() {
+        this(EnumSet.allOf(HttpMethod.class));
+    }
+
+    public StandardHttpMethodAuthorizationRules(Set<HttpMethod> 
methodsRequiringAuthorization) {
+        this.methodsRequiringAuthorization = methodsRequiringAuthorization;
+    }
+
+    @Override
+    public boolean requiresAuthorization(HttpMethod httpMethod) {
+        return methodsRequiringAuthorization.contains(httpMethod);
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-web-api/src/main/resources/META-INF/LICENSE
----------------------------------------------------------------------
diff --git 
a/nifi-registry-core/nifi-registry-web-api/src/main/resources/META-INF/LICENSE 
b/nifi-registry-core/nifi-registry-web-api/src/main/resources/META-INF/LICENSE
new file mode 100644
index 0000000..cd25b0a
--- /dev/null
+++ 
b/nifi-registry-core/nifi-registry-web-api/src/main/resources/META-INF/LICENSE
@@ -0,0 +1,352 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
+
+This product bundles 'asm' which is available under a 3-Clause BSD style 
license.
+For details see http://asm.ow2.org/asmdex-license.html
+
+    Copyright (c) 2012 France Télécom
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions
+    are met:
+    1. Redistributions of source code must retain the above copyright
+       notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+       notice, this list of conditions and the following disclaimer in the
+       documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the names of its
+       contributors may be used to endorse or promote products derived from
+       this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+    THE POSSIBILITY OF SUCH DAMAGE.
+
+The binary distribution of this product bundles 'Antlr 3' which is available
+under a "3-clause BSD" license.  For details see 
http://www.antlr3.org/license.html
+
+    Copyright (c) 2010 Terence Parr
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+
+    Redistributions of source code must retain the above copyright notice, this
+    list of conditions and the following disclaimer.
+    Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+    Neither the name of the author nor the names of its contributors may be 
used
+    to endorse or promote products derived from this software without specific
+    prior written permission.
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+    THE POSSIBILITY OF SUCH DAMAGE.
+
+The binary distribution of this product bundles 'Bouncy Castle JDK 1.5'
+under an MIT style license.
+
+    Copyright (c) 2000 - 2015 The Legion of the Bouncy Castle Inc. 
(http://www.bouncycastle.org)
+
+    Permission is hereby granted, free of charge, to any person obtaining a 
copy
+    of this software and associated documentation files (the "Software"), to 
deal
+    in the Software without restriction, including without limitation the 
rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+    THE SOFTWARE.
+
+The binary distribution of this product bundles 'Slf4j' which is available 
under
+an MIT license.
+
+    Copyright (c) 2004-2013 QOS.ch
+     All rights reserved.
+
+     Permission is hereby granted, free  of charge, to any person obtaining
+     a  copy  of this  software  and  associated  documentation files  (the
+     "Software"), to  deal in  the Software without  restriction, including
+     without limitation  the rights to  use, copy, modify,  merge, publish,
+     distribute,  sublicense, and/or sell  copies of  the Software,  and to
+     permit persons to whom the Software  is furnished to do so, subject to
+     the following conditions:
+
+     The  above  copyright  notice  and  this permission  notice  shall  be
+     included in all copies or substantial portions of the Software.
+
+     THE  SOFTWARE IS  PROVIDED  "AS  IS", WITHOUT  WARRANTY  OF ANY  KIND,
+     EXPRESS OR  IMPLIED, INCLUDING  BUT NOT LIMITED  TO THE  WARRANTIES OF
+     MERCHANTABILITY,    FITNESS    FOR    A   PARTICULAR    PURPOSE    AND
+     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+     LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+     OF CONTRACT, TORT OR OTHERWISE,  ARISING FROM, OUT OF OR IN CONNECTION
+     WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+The binary distribution of this product bundles 'dom4j' which is available 
under
+a "3-Clause BSD" license. For details: 
https://github.com/dom4j/dom4j/blob/master/LICENSE
+
+    Copyright 2001-2016 (C) MetaStuff, Ltd. and DOM4J contributors. All Rights 
Reserved.
+
+    Redistribution and use of this software and associated documentation
+    ("Software"), with or without modification, are permitted provided
+    that the following conditions are met:
+
+    1. Redistributions of source code must retain copyright
+       statements and notices.  Redistributions must also contain a
+       copy of this document.
+
+    2. Redistributions in binary form must reproduce the
+       above copyright notice, this list of conditions and the
+       following disclaimer in the documentation and/or other
+       materials provided with the distribution.
+
+    3. The name "DOM4J" must not be used to endorse or promote
+       products derived from this Software without prior written
+       permission of MetaStuff, Ltd.  For written permission,
+       please contact dom4j-i...@metastuff.com.
+
+    4. Products derived from this Software may not be called "DOM4J"
+       nor may "DOM4J" appear in their names without prior written
+       permission of MetaStuff, Ltd. DOM4J is a registered
+       trademark of MetaStuff, Ltd.
+
+    5. Due credit should be given to the DOM4J Project - 
https://dom4j.github.io/
+
+    THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS
+    ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
+    NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+    FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
+    METASTUFF, LTD. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+    STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+    OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file

Reply via email to