/*
 * 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.security.authorization;

import org.apache.commons.lang3.StringUtils;
import org.apache.nifi.registry.extension.ExtensionCloseable;
import org.apache.nifi.registry.extension.ExtensionManager;
import org.apache.nifi.registry.properties.NiFiRegistryProperties;
import org.apache.nifi.registry.properties.SensitivePropertyProtectionException;
import org.apache.nifi.registry.properties.SensitivePropertyProvider;
import org.apache.nifi.registry.provider.StandardProviderFactory;
import org.apache.nifi.registry.security.authorization.annotation.AuthorizerContext;
import org.apache.nifi.registry.security.authorization.exception.AuthorizationAccessException;
import org.apache.nifi.registry.security.authorization.exception.UninheritableAuthorizationsException;
import org.apache.nifi.registry.security.authorization.generated.Authorizers;
import org.apache.nifi.registry.security.authorization.generated.Prop;
import org.apache.nifi.registry.security.exception.SecurityProviderCreationException;
import org.apache.nifi.registry.security.exception.SecurityProviderDestructionException;
import org.apache.nifi.registry.security.util.XmlUtils;
import org.apache.nifi.registry.service.RegistryService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.lang.Nullable;
import org.xml.sax.SAXException;

import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.stream.XMLStreamException;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Creates and configures Authorizers and their providers based on the configuration (authorizers.xml).
 *
 * This implementation of AuthorizerFactory in NiFi Registry is based on a combination of
 * NiFi's AuthorizerFactory and AuthorizerFactoryBean.
 */
@Configuration("authorizerFactory")
public class AuthorizerFactory implements UserGroupProviderLookup, AccessPolicyProviderLookup, AuthorizerLookup, DisposableBean {

    private static final Logger logger = LoggerFactory.getLogger(StandardProviderFactory.class);

    private static final String AUTHORIZERS_XSD = "/authorizers.xsd";
    private static final String JAXB_GENERATED_PATH = "org.apache.nifi.registry.security.authorization.generated";
    private static final JAXBContext JAXB_CONTEXT = initializeJaxbContext();

    /**
     * Load the JAXBContext.
     */
    private static JAXBContext initializeJaxbContext() {
        try {
            return JAXBContext.newInstance(JAXB_GENERATED_PATH, AuthorizerFactory.class.getClassLoader());
        } catch (JAXBException e) {
            throw new RuntimeException("Unable to create JAXBContext.", e);
        }
    }

    private final NiFiRegistryProperties properties;
    private final ExtensionManager extensionManager;
    private final SensitivePropertyProvider sensitivePropertyProvider;
    private final RegistryService registryService;

    private Authorizer authorizer;
    private final Map<String, UserGroupProvider> userGroupProviders = new HashMap<>();
    private final Map<String, AccessPolicyProvider> accessPolicyProviders = new HashMap<>();
    private final Map<String, Authorizer> authorizers = new HashMap<>();

    @Autowired
    public AuthorizerFactory(
            final NiFiRegistryProperties properties,
            final ExtensionManager extensionManager,
            @Nullable final SensitivePropertyProvider sensitivePropertyProvider,
            final RegistryService registryService) {

        this.properties = properties;
        this.extensionManager = extensionManager;
        this.sensitivePropertyProvider = sensitivePropertyProvider;
        this.registryService = registryService;

        if (this.properties == null) {
            throw new IllegalStateException("NiFiRegistryProperties cannot be null");
        }

        if (this.extensionManager == null) {
            throw new IllegalStateException("ExtensionManager cannot be null");
        }

        if (this.registryService == null) {
            throw new IllegalStateException("RegistryService cannot be null");
        }
    }

    /***** UserGroupProviderLookup *****/

    @Override
    public UserGroupProvider getUserGroupProvider(String identifier) {
        return userGroupProviders.get(identifier);
    }

    /***** AccessPolicyProviderLookup *****/

    @Override
    public AccessPolicyProvider getAccessPolicyProvider(String identifier) {
        return accessPolicyProviders.get(identifier);
    }


    /***** AuthorizerLookup *****/

    @Override
    public Authorizer getAuthorizer(String identifier) {
        return authorizers.get(identifier);
    }

    /***** AuthorizerFactory / DisposableBean *****/

    @Bean
    public Authorizer getAuthorizer() throws AuthorizerFactoryException {
        if (authorizer == null) {
            if (properties.getSslPort() == null) {
                // use a default authorizer... only allowable when running not securely
                authorizer = createDefaultAuthorizer();
            } else {
                // look up the authorizer to use
                final String authorizerIdentifier = properties.getProperty(NiFiRegistryProperties.SECURITY_AUTHORIZER);

                // ensure the authorizer class name was specified
                if (StringUtils.isBlank(authorizerIdentifier)) {
                    throw new AuthorizerFactoryException("When running securely, the authorizer identifier must be specified in the nifi-registry.properties file.");
                } else {

                    try {
                        final Authorizers authorizerConfiguration = loadAuthorizersConfiguration();

                        // create each user group provider
                        for (final org.apache.nifi.registry.security.authorization.generated.UserGroupProvider userGroupProvider : authorizerConfiguration.getUserGroupProvider()) {
                            if (userGroupProviders.containsKey(userGroupProvider.getIdentifier())) {
                                throw new AuthorizerFactoryException("Duplicate User Group Provider identifier in Authorizers configuration: " + userGroupProvider.getIdentifier());
                            }
                            userGroupProviders.put(userGroupProvider.getIdentifier(), createUserGroupProvider(userGroupProvider.getIdentifier(), userGroupProvider.getClazz()));
                        }

                        // configure each user group provider
                        for (final org.apache.nifi.registry.security.authorization.generated.UserGroupProvider provider : authorizerConfiguration.getUserGroupProvider()) {
                            final UserGroupProvider instance = userGroupProviders.get(provider.getIdentifier());
                            instance.onConfigured(loadAuthorizerConfiguration(provider.getIdentifier(), provider.getProperty()));
                        }

                        // create each access policy provider
                        for (final org.apache.nifi.registry.security.authorization.generated.AccessPolicyProvider accessPolicyProvider : authorizerConfiguration.getAccessPolicyProvider()) {
                            if (accessPolicyProviders.containsKey(accessPolicyProvider.getIdentifier())) {
                                throw new AuthorizerFactoryException("Duplicate Access Policy Provider identifier in Authorizers configuration: " + accessPolicyProvider.getIdentifier());
                            }
                            accessPolicyProviders.put(accessPolicyProvider.getIdentifier(), createAccessPolicyProvider(accessPolicyProvider.getIdentifier(), accessPolicyProvider.getClazz()));
                        }

                        // configure each access policy provider
                        for (final org.apache.nifi.registry.security.authorization.generated.AccessPolicyProvider provider : authorizerConfiguration.getAccessPolicyProvider()) {
                            final AccessPolicyProvider instance = accessPolicyProviders.get(provider.getIdentifier());
                            instance.onConfigured(loadAuthorizerConfiguration(provider.getIdentifier(), provider.getProperty()));
                        }

                        // create each authorizer
                        for (final org.apache.nifi.registry.security.authorization.generated.Authorizer authorizer : authorizerConfiguration.getAuthorizer()) {
                            if (authorizers.containsKey(authorizer.getIdentifier())) {
                                throw new AuthorizerFactoryException("Duplicate Authorizer identifier in Authorizers configuration: " + authorizer.getIdentifier());
                            }
                            authorizers.put(authorizer.getIdentifier(), createAuthorizer(authorizer.getIdentifier(), authorizer.getClazz(), authorizer.getClasspath()));
                        }

                        // configure each authorizer
                        for (final org.apache.nifi.registry.security.authorization.generated.Authorizer provider : authorizerConfiguration.getAuthorizer()) {
                            final Authorizer instance = authorizers.get(provider.getIdentifier());
                            final Class authorizerClass = instance instanceof WrappedAuthorizer
                                    ? ((WrappedAuthorizer) instance).getBaseAuthorizer().getClass()
                                    : instance.getClass();
                            try (ExtensionCloseable extCloseable = ExtensionCloseable.withComponentClassLoader(extensionManager, authorizerClass)) {
                                instance.onConfigured(loadAuthorizerConfiguration(provider.getIdentifier(), provider.getProperty()));
                            }
                        }

                        // get the authorizer instance
                        authorizer = getAuthorizer(authorizerIdentifier);

                        // ensure it was found
                        if (authorizer == null) {
                            throw new AuthorizerFactoryException(String.format("The specified authorizer '%s' could not be found.", authorizerIdentifier));
                        }
                    } catch (AuthorizerFactoryException e) {
                        throw e;
                    } catch (Exception e) {
                        throw new AuthorizerFactoryException("Failed to construct Authorizer.", e);
                    }
                }
            }
        }
        return authorizer;
    }

    @Override
    public void destroy() throws Exception {
        if (authorizers != null) {
            authorizers.forEach((key, value) -> value.preDestruction());
        }

        if (accessPolicyProviders != null) {
            accessPolicyProviders.forEach((key, value) -> value.preDestruction());
        }

        if (userGroupProviders != null) {
            userGroupProviders.forEach((key, value) -> value.preDestruction());
        }
    }

    private Authorizers loadAuthorizersConfiguration() throws Exception {
        final File authorizersConfigurationFile = properties.getAuthorizersConfigurationFile();

        // load the authorizers from the specified file
        if (authorizersConfigurationFile.exists()) {
            try {
                // find the schema
                final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
                final Schema schema = schemaFactory.newSchema(Authorizers.class.getResource(AUTHORIZERS_XSD));

                // attempt to unmarshal
                final Unmarshaller unmarshaller = JAXB_CONTEXT.createUnmarshaller();
                unmarshaller.setSchema(schema);
                final JAXBElement<Authorizers> element = unmarshaller.unmarshal(XmlUtils.createSafeReader(new StreamSource(authorizersConfigurationFile)), Authorizers.class);
                return element.getValue();
            } catch (XMLStreamException | SAXException | JAXBException e) {
                throw new Exception("Unable to load the authorizer configuration file at: " + authorizersConfigurationFile.getAbsolutePath(), e);
            }
        } else {
            throw new Exception("Unable to find the authorizer configuration file at " + authorizersConfigurationFile.getAbsolutePath());
        }
    }

    private AuthorizerConfigurationContext loadAuthorizerConfiguration(final String identifier, final List<Prop> properties) {
        final Map<String, String> authorizerProperties = new HashMap<>();

        for (final Prop property : properties) {
            if (!StringUtils.isBlank(property.getEncryption())) {
                String decryptedValue = decryptValue(property.getValue(), property.getEncryption());
                authorizerProperties.put(property.getName(), decryptedValue);
            } else {
                authorizerProperties.put(property.getName(), property.getValue());
            }
        }
        return new StandardAuthorizerConfigurationContext(identifier, authorizerProperties);
    }

    private UserGroupProvider createUserGroupProvider(final String identifier, final String userGroupProviderClassName) throws Exception {

        final UserGroupProvider instance;

        final ClassLoader classLoader = extensionManager.getExtensionClassLoader(userGroupProviderClassName);
        if (classLoader == null) {
            throw new IllegalStateException("Extension not found in any of the configured class loaders: " + userGroupProviderClassName);
        }

        // attempt to load the class
        Class<?> rawUserGroupProviderClass = Class.forName(userGroupProviderClassName, true, classLoader);
        Class<? extends UserGroupProvider> userGroupProviderClass = rawUserGroupProviderClass.asSubclass(UserGroupProvider.class);

        // otherwise create a new instance
        Constructor constructor = userGroupProviderClass.getConstructor();
        instance = (UserGroupProvider) constructor.newInstance();

        // method injection
        performMethodInjection(instance, userGroupProviderClass);

        // field injection
        performFieldInjection(instance, userGroupProviderClass);

        // call post construction lifecycle event
        instance.initialize(new StandardAuthorizerInitializationContext(identifier, this, this, this));

        return instance;
    }

    private AccessPolicyProvider createAccessPolicyProvider(final String identifier, final String accessPolicyProviderClassName) throws Exception {
        final AccessPolicyProvider instance;

        final ClassLoader classLoader = extensionManager.getExtensionClassLoader(accessPolicyProviderClassName);
        if (classLoader == null) {
            throw new IllegalStateException("Extension not found in any of the configured class loaders: " + accessPolicyProviderClassName);
        }

        // attempt to load the class
        Class<?> rawAccessPolicyProviderClass = Class.forName(accessPolicyProviderClassName, true, classLoader);
        Class<? extends AccessPolicyProvider> accessPolicyClass = rawAccessPolicyProviderClass.asSubclass(AccessPolicyProvider.class);

        // otherwise create a new instance
        Constructor constructor = accessPolicyClass.getConstructor();
        instance = (AccessPolicyProvider) constructor.newInstance();

        // method injection
        performMethodInjection(instance, accessPolicyClass);

        // field injection
        performFieldInjection(instance, accessPolicyClass);

        // call post construction lifecycle event
        instance.initialize(new StandardAuthorizerInitializationContext(identifier, this, this, this));

        return instance;
    }

    private Authorizer createAuthorizer(final String identifier, final String authorizerClassName, final String classpathResources) throws Exception {
        final Authorizer instance;

        final ClassLoader classLoader = extensionManager.getExtensionClassLoader(authorizerClassName);
        if (classLoader == null) {
            throw new IllegalStateException("Extension not found in any of the configured class loaders: " + authorizerClassName);
        }

        // attempt to load the class
        Class<?> rawAuthorizerClass = Class.forName(authorizerClassName, true, classLoader);
        Class<? extends Authorizer> authorizerClass = rawAuthorizerClass.asSubclass(Authorizer.class);

        // otherwise create a new instance
        Constructor constructor = authorizerClass.getConstructor();
        instance = (Authorizer) constructor.newInstance();

        // method injection
        performMethodInjection(instance, authorizerClass);

        // field injection
        performFieldInjection(instance, authorizerClass);

        // call post construction lifecycle event
        instance.initialize(new StandardAuthorizerInitializationContext(identifier, this, this, this));

        // wrap the instance Authorizer with checks to ensure integrity of data
        final Authorizer integrityCheckAuthorizer = installIntegrityChecks(instance);

        // wrap the integrity checked Authorizer with the FrameworkAuthorizer
        return createFrameworkAuthorizer(integrityCheckAuthorizer);
    }

    private Authorizer createFrameworkAuthorizer(final Authorizer baseAuthorizer) {
        if (baseAuthorizer instanceof ManagedAuthorizer) {
            return new FrameworkManagedAuthorizer((ManagedAuthorizer) baseAuthorizer, registryService);
        } else {
            return new FrameworkAuthorizer(baseAuthorizer, registryService);
        }
    }

    private void performMethodInjection(final Object instance, final Class authorizerClass) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        for (final Method method : authorizerClass.getMethods()) {
            if (method.isAnnotationPresent(AuthorizerContext.class)) {
                // make the method accessible
                final boolean isAccessible = method.isAccessible();
                method.setAccessible(true);

                try {
                    final Class<?>[] argumentTypes = method.getParameterTypes();

                    // look for setters (single argument)
                    if (argumentTypes.length == 1) {
                        final Class<?> argumentType = argumentTypes[0];

                        // look for well known types
                        if (NiFiRegistryProperties.class.isAssignableFrom(argumentType)) {
                            // nifi properties injection
                            method.invoke(instance, properties);
                        }
                    }
                } finally {
                    method.setAccessible(isAccessible);
                }
            }
        }

        final Class parentClass = authorizerClass.getSuperclass();
        if (parentClass != null && Authorizer.class.isAssignableFrom(parentClass)) {
            performMethodInjection(instance, parentClass);
        }
    }

    private void performFieldInjection(final Object instance, final Class authorizerClass) throws IllegalArgumentException, IllegalAccessException {
        for (final Field field : authorizerClass.getDeclaredFields()) {
            if (field.isAnnotationPresent(AuthorizerContext.class)) {
                // make the method accessible
                final boolean isAccessible = field.isAccessible();
                field.setAccessible(true);

                try {
                    // get the type
                    final Class<?> fieldType = field.getType();

                    // only consider this field if it isn't set yet
                    if (field.get(instance) == null) {
                        // look for well known types
                        if (NiFiRegistryProperties.class.isAssignableFrom(fieldType)) {
                            // nifi properties injection
                            field.set(instance, properties);
                        }
                    }

                } finally {
                    field.setAccessible(isAccessible);
                }
            }
        }

        final Class parentClass = authorizerClass.getSuperclass();
        if (parentClass != null && Authorizer.class.isAssignableFrom(parentClass)) {
            performFieldInjection(instance, parentClass);
        }
    }

    private String decryptValue(String cipherText, String encryptionScheme) throws SensitivePropertyProtectionException {
        if (sensitivePropertyProvider == null) {
            throw new SensitivePropertyProtectionException("Sensitive Property Provider dependency was never wired, so protected" +
                    "properties cannot be decrypted. This usually indicates that a master key for this NiFi Registry was not " +
                    "detected and configured during the bootstrap startup sequence. Contact the system administrator.");
        }

        if (!sensitivePropertyProvider.getIdentifierKey().equalsIgnoreCase(encryptionScheme)) {
            throw new SensitivePropertyProtectionException("Identity Provider configuration XML was protected using " +
                    encryptionScheme +
                    ", but the configured Sensitive Property Provider supports " +
                    sensitivePropertyProvider.getIdentifierKey() +
                    ". Cannot configure this Identity Provider due to failing to decrypt protected configuration properties.");
        }

        return sensitivePropertyProvider.unprotect(cipherText);
    }


    /**
     * @return a default Authorizer to use when running unsecurely with no authorizer configured
     */
    private Authorizer createDefaultAuthorizer() {
        return new Authorizer() {
            @Override
            public AuthorizationResult authorize(final AuthorizationRequest request) throws AuthorizationAccessException {
                return AuthorizationResult.approved();
            }

            @Override
            public void initialize(AuthorizerInitializationContext initializationContext) throws SecurityProviderCreationException {
            }

            @Override
            public void onConfigured(AuthorizerConfigurationContext configurationContext) throws SecurityProviderCreationException {
            }

            @Override
            public void preDestruction() throws SecurityProviderCreationException {
            }
        };
    }

    private interface WrappedAuthorizer {
        Authorizer getBaseAuthorizer();
    }

    private static class ManagedAuthorizerWrapper implements ManagedAuthorizer, WrappedAuthorizer {
        private final ManagedAuthorizer baseManagedAuthorizer;

        public ManagedAuthorizerWrapper(ManagedAuthorizer baseManagedAuthorizer) {
            this.baseManagedAuthorizer = baseManagedAuthorizer;
        }

        @Override
        public Authorizer getBaseAuthorizer() {
            return baseManagedAuthorizer;
        }

        @Override
        public String getFingerprint() throws AuthorizationAccessException {
            return baseManagedAuthorizer.getFingerprint();
        }

        @Override
        public void inheritFingerprint(String fingerprint) throws AuthorizationAccessException {
            baseManagedAuthorizer.inheritFingerprint(fingerprint);
        }

        @Override
        public void checkInheritability(String proposedFingerprint) throws AuthorizationAccessException, UninheritableAuthorizationsException {
            baseManagedAuthorizer.checkInheritability(proposedFingerprint);
        }

        @Override
        public AccessPolicyProvider getAccessPolicyProvider() {
            final AccessPolicyProvider baseAccessPolicyProvider = baseManagedAuthorizer.getAccessPolicyProvider();
            if (baseAccessPolicyProvider instanceof ConfigurableAccessPolicyProvider) {
                final ConfigurableAccessPolicyProvider baseConfigurableAccessPolicyProvider = (ConfigurableAccessPolicyProvider) baseAccessPolicyProvider;
                return new ConfigurableAccessPolicyProvider() {
                    @Override
                    public String getFingerprint() throws AuthorizationAccessException {
                        return baseConfigurableAccessPolicyProvider.getFingerprint();
                    }

                    @Override
                    public void inheritFingerprint(String fingerprint) throws AuthorizationAccessException {
                        baseConfigurableAccessPolicyProvider.inheritFingerprint(fingerprint);
                    }

                    @Override
                    public void checkInheritability(String proposedFingerprint) throws AuthorizationAccessException, UninheritableAuthorizationsException {
                        baseConfigurableAccessPolicyProvider.checkInheritability(proposedFingerprint);
                    }

                    @Override
                    public AccessPolicy addAccessPolicy(AccessPolicy accessPolicy) throws AuthorizationAccessException {
                        if (policyExists(baseConfigurableAccessPolicyProvider, accessPolicy)) {
                            throw new IllegalStateException(String.format("Found multiple policies for '%s' with '%s'.", accessPolicy.getResource(), accessPolicy.getAction()));
                        }
                        return baseConfigurableAccessPolicyProvider.addAccessPolicy(accessPolicy);
                    }

                    @Override
                    public boolean isConfigurable(AccessPolicy accessPolicy) {
                        return baseConfigurableAccessPolicyProvider.isConfigurable(accessPolicy);
                    }

                    @Override
                    public AccessPolicy updateAccessPolicy(AccessPolicy accessPolicy) throws AuthorizationAccessException {
                        if (!baseConfigurableAccessPolicyProvider.isConfigurable(accessPolicy)) {
                            throw new IllegalArgumentException("The specified access policy is not support modification.");
                        }
                        return baseConfigurableAccessPolicyProvider.updateAccessPolicy(accessPolicy);
                    }

                    @Override
                    public AccessPolicy deleteAccessPolicy(AccessPolicy accessPolicy) throws AuthorizationAccessException {
                        if (!baseConfigurableAccessPolicyProvider.isConfigurable(accessPolicy)) {
                            throw new IllegalArgumentException("The specified access policy is not support modification.");
                        }
                        return baseConfigurableAccessPolicyProvider.deleteAccessPolicy(accessPolicy);
                    }

                    @Override
                    public AccessPolicy deleteAccessPolicy(String accessPolicyIdentifier) throws AuthorizationAccessException {
                        if (!baseConfigurableAccessPolicyProvider.isConfigurable(baseConfigurableAccessPolicyProvider.getAccessPolicy(accessPolicyIdentifier))) {
                            throw new IllegalArgumentException("The specified access policy is not support modification.");
                        }
                        return baseConfigurableAccessPolicyProvider.deleteAccessPolicy(accessPolicyIdentifier);
                    }

                    @Override
                    public Set<AccessPolicy> getAccessPolicies() throws AuthorizationAccessException {
                        return baseConfigurableAccessPolicyProvider.getAccessPolicies();
                    }

                    @Override
                    public AccessPolicy getAccessPolicy(String identifier) throws AuthorizationAccessException {
                        return baseConfigurableAccessPolicyProvider.getAccessPolicy(identifier);
                    }

                    @Override
                    public AccessPolicy getAccessPolicy(String resourceIdentifier, RequestAction action) throws AuthorizationAccessException {
                        return baseConfigurableAccessPolicyProvider.getAccessPolicy(resourceIdentifier, action);
                    }

                    @Override
                    public UserGroupProvider getUserGroupProvider() {
                        final UserGroupProvider baseUserGroupProvider = baseConfigurableAccessPolicyProvider.getUserGroupProvider();
                        if (baseUserGroupProvider instanceof ConfigurableUserGroupProvider) {
                            final ConfigurableUserGroupProvider baseConfigurableUserGroupProvider = (ConfigurableUserGroupProvider) baseUserGroupProvider;
                            return new ConfigurableUserGroupProvider() {
                                @Override
                                public String getFingerprint() throws AuthorizationAccessException {
                                    return baseConfigurableUserGroupProvider.getFingerprint();
                                }

                                @Override
                                public void inheritFingerprint(String fingerprint) throws AuthorizationAccessException {
                                    baseConfigurableUserGroupProvider.inheritFingerprint(fingerprint);
                                }

                                @Override
                                public void checkInheritability(String proposedFingerprint) throws AuthorizationAccessException, UninheritableAuthorizationsException {
                                    baseConfigurableUserGroupProvider.checkInheritability(proposedFingerprint);
                                }

                                @Override
                                public User addUser(User user) throws AuthorizationAccessException {
                                    if (userExists(baseConfigurableUserGroupProvider, user.getIdentifier(), user.getIdentity())) {
                                        throw new IllegalStateException(String.format("User/user group already exists with the identity '%s'.", user.getIdentity()));
                                    }
                                    return baseConfigurableUserGroupProvider.addUser(user);
                                }

                                @Override
                                public boolean isConfigurable(User user) {
                                    return baseConfigurableUserGroupProvider.isConfigurable(user);
                                }

                                @Override
                                public User updateUser(User user) throws AuthorizationAccessException {
                                    if (userExists(baseConfigurableUserGroupProvider, user.getIdentifier(), user.getIdentity())) {
                                        throw new IllegalStateException(String.format("User/user group already exists with the identity '%s'.", user.getIdentity()));
                                    }
                                    if (!baseConfigurableUserGroupProvider.isConfigurable(user)) {
                                        throw new IllegalArgumentException("The specified user does not support modification.");
                                    }
                                    return baseConfigurableUserGroupProvider.updateUser(user);
                                }

                                @Override
                                public User deleteUser(User user) throws AuthorizationAccessException {
                                    if (!baseConfigurableUserGroupProvider.isConfigurable(user)) {
                                        throw new IllegalArgumentException("The specified user does not support modification.");
                                    }
                                    return baseConfigurableUserGroupProvider.deleteUser(user);
                                }

                                @Override
                                public User deleteUser(String userIdentifier) throws AuthorizationAccessException {
                                    if (!baseConfigurableUserGroupProvider.isConfigurable(baseConfigurableUserGroupProvider.getUser(userIdentifier))) {
                                        throw new IllegalArgumentException("The specified user does not support modification.");
                                    }
                                    return baseConfigurableUserGroupProvider.deleteUser(userIdentifier);
                                }

                                @Override
                                public Group addGroup(Group group) throws AuthorizationAccessException {
                                    if (groupExists(baseConfigurableUserGroupProvider, group.getIdentifier(), group.getName())) {
                                        throw new IllegalStateException(String.format("User/user group already exists with the identity '%s'.", group.getName()));
                                    }
                                    if (!allGroupUsersExist(baseUserGroupProvider, group)) {
                                        throw new IllegalStateException(String.format("Cannot create group '%s' with users that don't exist.", group.getName()));
                                    }
                                    return baseConfigurableUserGroupProvider.addGroup(group);
                                }

                                @Override
                                public boolean isConfigurable(Group group) {
                                    return baseConfigurableUserGroupProvider.isConfigurable(group);
                                }

                                @Override
                                public Group updateGroup(Group group) throws AuthorizationAccessException {
                                    if (groupExists(baseConfigurableUserGroupProvider, group.getIdentifier(), group.getName())) {
                                        throw new IllegalStateException(String.format("User/user group already exists with the identity '%s'.", group.getName()));
                                    }
                                    if (!baseConfigurableUserGroupProvider.isConfigurable(group)) {
                                        throw new IllegalArgumentException("The specified group does not support modification.");
                                    }
                                    if (!allGroupUsersExist(baseUserGroupProvider, group)) {
                                        throw new IllegalStateException(String.format("Cannot update group '%s' to add users that don't exist.", group.getName()));
                                    }
                                    return baseConfigurableUserGroupProvider.updateGroup(group);
                                }

                                @Override
                                public Group deleteGroup(Group group) throws AuthorizationAccessException {
                                    if (!baseConfigurableUserGroupProvider.isConfigurable(group)) {
                                        throw new IllegalArgumentException("The specified group does not support modification.");
                                    }
                                    return baseConfigurableUserGroupProvider.deleteGroup(group);
                                }

                                @Override
                                public Group deleteGroup(String groupId) throws AuthorizationAccessException {
                                    if (!baseConfigurableUserGroupProvider.isConfigurable(baseConfigurableUserGroupProvider.getGroup(groupId))) {
                                        throw new IllegalArgumentException("The specified group does not support modification.");
                                    }
                                    return baseConfigurableUserGroupProvider.deleteGroup(groupId);
                                }

                                @Override
                                public Set<User> getUsers() throws AuthorizationAccessException {
                                    return baseConfigurableUserGroupProvider.getUsers();
                                }

                                @Override
                                public User getUser(String identifier) throws AuthorizationAccessException {
                                    return baseConfigurableUserGroupProvider.getUser(identifier);
                                }

                                @Override
                                public User getUserByIdentity(String identity) throws AuthorizationAccessException {
                                    return baseConfigurableUserGroupProvider.getUserByIdentity(identity);
                                }

                                @Override
                                public Set<Group> getGroups() throws AuthorizationAccessException {
                                    return baseConfigurableUserGroupProvider.getGroups();
                                }

                                @Override
                                public Group getGroup(String identifier) throws AuthorizationAccessException {
                                    return baseConfigurableUserGroupProvider.getGroup(identifier);
                                }

                                @Override
                                public UserAndGroups getUserAndGroups(String identity) throws AuthorizationAccessException {
                                    return baseConfigurableUserGroupProvider.getUserAndGroups(identity);
                                }

                                @Override
                                public void initialize(UserGroupProviderInitializationContext initializationContext) throws SecurityProviderCreationException {
                                    baseConfigurableUserGroupProvider.initialize(initializationContext);
                                }

                                @Override
                                public void onConfigured(AuthorizerConfigurationContext configurationContext) throws SecurityProviderCreationException {
                                    baseConfigurableUserGroupProvider.onConfigured(configurationContext);
                                }

                                @Override
                                public void preDestruction() throws SecurityProviderDestructionException {
                                    baseConfigurableUserGroupProvider.preDestruction();
                                }
                            };
                        } else {
                            return baseUserGroupProvider;
                        }
                    }

                    @Override
                    public void initialize(AccessPolicyProviderInitializationContext initializationContext) throws SecurityProviderCreationException {
                        baseConfigurableAccessPolicyProvider.initialize(initializationContext);
                    }

                    @Override
                    public void onConfigured(AuthorizerConfigurationContext configurationContext) throws SecurityProviderCreationException {
                        baseConfigurableAccessPolicyProvider.onConfigured(configurationContext);
                    }

                    @Override
                    public void preDestruction() throws SecurityProviderDestructionException {
                        baseConfigurableAccessPolicyProvider.preDestruction();
                    }
                };
            } else {
                return baseAccessPolicyProvider;
            }
        }

        @Override
        public AuthorizationResult authorize(AuthorizationRequest request) throws AuthorizationAccessException {
            final AuthorizationResult result = baseManagedAuthorizer.authorize(request);

            // audit the authorization request
            audit(baseManagedAuthorizer, request, result);

            return result;
        }

        @Override
        public void initialize(AuthorizerInitializationContext initializationContext) throws SecurityProviderCreationException {
            baseManagedAuthorizer.initialize(initializationContext);
        }

        @Override
        public void onConfigured(AuthorizerConfigurationContext configurationContext) throws SecurityProviderCreationException {
            baseManagedAuthorizer.onConfigured(configurationContext);

            final AccessPolicyProvider accessPolicyProvider = baseManagedAuthorizer.getAccessPolicyProvider();
            final UserGroupProvider userGroupProvider = accessPolicyProvider.getUserGroupProvider();

            // ensure that only one policy per resource-action exists
            for (AccessPolicy accessPolicy : accessPolicyProvider.getAccessPolicies()) {
                if (policyExists(accessPolicyProvider, accessPolicy)) {
                    throw new SecurityProviderCreationException(String.format("Found multiple policies for '%s' with '%s'.", accessPolicy.getResource(), accessPolicy.getAction()));
                }
            }

            // ensure that only one group exists per identity
            for (User user : userGroupProvider.getUsers()) {
                if (userExists(userGroupProvider, user.getIdentifier(), user.getIdentity())) {
                    throw new SecurityProviderCreationException(String.format("Found multiple users/user groups with identity '%s'.", user.getIdentity()));
                }
            }

            // ensure that only one group exists per identity
            for (Group group : userGroupProvider.getGroups()) {
                if (groupExists(userGroupProvider, group.getIdentifier(), group.getName())) {
                    throw new SecurityProviderCreationException(String.format("Found multiple users/user groups with name '%s'.", group.getName()));
                }
            }
        }

        @Override
        public void preDestruction() throws SecurityProviderDestructionException {
            baseManagedAuthorizer.preDestruction();
        }
    }

    private static class AuthorizerWrapper implements Authorizer, WrappedAuthorizer {
        private final Authorizer baseAuthorizer;

        public AuthorizerWrapper(Authorizer baseAuthorizer) {
            this.baseAuthorizer = baseAuthorizer;
        }

        @Override
        public Authorizer getBaseAuthorizer() {
            return baseAuthorizer;
        }

        @Override
        public AuthorizationResult authorize(AuthorizationRequest request) throws AuthorizationAccessException {
            final AuthorizationResult result = baseAuthorizer.authorize(request);

            // audit the authorization request
            audit(baseAuthorizer, request, result);

            return result;
        }

        @Override
        public void initialize(AuthorizerInitializationContext initializationContext) throws SecurityProviderCreationException {
            baseAuthorizer.initialize(initializationContext);
        }

        @Override
        public void onConfigured(AuthorizerConfigurationContext configurationContext) throws SecurityProviderCreationException {
            baseAuthorizer.onConfigured(configurationContext);
        }

        @Override
        public void preDestruction() throws SecurityProviderDestructionException {
            baseAuthorizer.preDestruction();
        }
    }

    private static Authorizer installIntegrityChecks(final Authorizer baseAuthorizer) {
        if (baseAuthorizer instanceof ManagedAuthorizer) {
            return new ManagedAuthorizerWrapper((ManagedAuthorizer) baseAuthorizer);
        } else {
            return new AuthorizerWrapper(baseAuthorizer);
        }
    }

    private static void audit(final Authorizer authorizer, final AuthorizationRequest request, final AuthorizationResult result) {
        // audit when...
        // 1 - the authorizer supports auditing
        // 2 - the request is an access attempt
        // 3 - the result is either approved/denied, when resource is not found a subsequent request may be following with the parent resource
        if (authorizer instanceof AuthorizationAuditor && request.isAccessAttempt() && !AuthorizationResult.Result.ResourceNotFound.equals(result.getResult())) {
            ((AuthorizationAuditor) authorizer).auditAccessAttempt(request, result);
        }
    }

    /**
     * Checks if another policy exists with the same resource and action as the given policy.
     *
     * @param checkAccessPolicy an access policy being checked
     * @return true if another access policy exists with the same resource and action, false otherwise
     */
    private static boolean policyExists(final AccessPolicyProvider accessPolicyProvider, final AccessPolicy checkAccessPolicy) {
        for (AccessPolicy accessPolicy : accessPolicyProvider.getAccessPolicies()) {
            if (!accessPolicy.getIdentifier().equals(checkAccessPolicy.getIdentifier())
                    && accessPolicy.getResource().equals(checkAccessPolicy.getResource())
                    && accessPolicy.getAction().equals(checkAccessPolicy.getAction())) {
                return true;
            }
        }
        return false;
    }

    /**
     * Checks if another user or group exists with the same identity.
     *
     * @param userGroupProvider the userGroupProvider to use to lookup the tenant
     * @param identifier identity of the tenant
     * @param identity identity of the tenant
     * @return true if another user exists with the same identity, false otherwise
     */
    private static boolean userExists(final UserGroupProvider userGroupProvider, final String identifier, final String identity) {
        for (User user : userGroupProvider.getUsers()) {
            if (!user.getIdentifier().equals(identifier)
                    && user.getIdentity().equals(identity)) {
                return true;
            }
        }

        return false;
    }

    private static boolean groupExists(final UserGroupProvider userGroupProvider, final String identifier, final String identity) {
        for (Group group : userGroupProvider.getGroups()) {
            if (!group.getIdentifier().equals(identifier)
                    && group.getName().equals(identity)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Check that all users in the group exist.
     *
     * @param userGroupProvider the userGroupProvider to use to lookup the users
     * @param group the group whose users will be checked for existence.
     * @return true if another user exists with the same identity, false otherwise
     */
    private static boolean allGroupUsersExist(final UserGroupProvider userGroupProvider, final Group group) {
        for (String userIdentifier : group.getUsers()) {
            User user = userGroupProvider.getUser(userIdentifier);
            if (user == null) {
                return false;
            }
        }

        return true;
    }

}
