| /* |
| * 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.security.authorization.exception.AuthorizationAccessException; |
| import org.apache.nifi.registry.security.authorization.exception.UninheritableAuthorizationsException; |
| import org.apache.nifi.registry.security.exception.SecurityProviderCreationException; |
| import org.apache.nifi.registry.security.exception.SecurityProviderDestructionException; |
| import org.apache.nifi.registry.util.PropertyValue; |
| |
| import java.util.HashSet; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.regex.Matcher; |
| |
| public class CompositeConfigurableUserGroupProvider extends CompositeUserGroupProvider implements ConfigurableUserGroupProvider { |
| |
| static final String PROP_CONFIGURABLE_USER_GROUP_PROVIDER = "Configurable User Group Provider"; |
| |
| private UserGroupProviderLookup userGroupProviderLookup; |
| private ConfigurableUserGroupProvider configurableUserGroupProvider; |
| |
| public CompositeConfigurableUserGroupProvider() { |
| super(true); |
| } |
| |
| @Override |
| public void initialize(UserGroupProviderInitializationContext initializationContext) throws SecurityProviderCreationException { |
| userGroupProviderLookup = initializationContext.getUserGroupProviderLookup(); |
| |
| // initialize the CompositeUserGroupProvider |
| super.initialize(initializationContext); |
| } |
| |
| @Override |
| public void onConfigured(AuthorizerConfigurationContext configurationContext) throws SecurityProviderCreationException { |
| final PropertyValue configurableUserGroupProviderKey = configurationContext.getProperty(PROP_CONFIGURABLE_USER_GROUP_PROVIDER); |
| if (!configurableUserGroupProviderKey.isSet()) { |
| throw new SecurityProviderCreationException("The Configurable User Group Provider must be set."); |
| } |
| |
| final UserGroupProvider userGroupProvider = userGroupProviderLookup.getUserGroupProvider(configurableUserGroupProviderKey.getValue()); |
| |
| if (userGroupProvider == null) { |
| throw new SecurityProviderCreationException(String.format("Unable to locate the Configurable User Group Provider: %s", configurableUserGroupProviderKey)); |
| } |
| |
| if (!(userGroupProvider instanceof ConfigurableUserGroupProvider)) { |
| throw new SecurityProviderCreationException(String.format("The Configurable User Group Provider is not configurable: %s", configurableUserGroupProviderKey)); |
| } |
| |
| // Ensure that the ConfigurableUserGroupProvider is not also listed as one of the providers for the CompositeUserGroupProvider |
| for (Map.Entry<String,String> entry : configurationContext.getProperties().entrySet()) { |
| Matcher matcher = USER_GROUP_PROVIDER_PATTERN.matcher(entry.getKey()); |
| if (matcher.matches() && !StringUtils.isBlank(entry.getValue())) { |
| final String userGroupProviderKey = entry.getValue(); |
| |
| if (userGroupProviderKey.equals(configurableUserGroupProviderKey.getValue())) { |
| throw new SecurityProviderCreationException(String.format("Duplicate provider in Composite Configurable User Group Provider configuration: %s", userGroupProviderKey)); |
| } |
| } |
| } |
| |
| configurableUserGroupProvider = (ConfigurableUserGroupProvider) userGroupProvider; |
| |
| // configure the CompositeUserGroupProvider |
| super.onConfigured(configurationContext); |
| } |
| |
| @Override |
| public String getFingerprint() throws AuthorizationAccessException { |
| return configurableUserGroupProvider.getFingerprint(); |
| } |
| |
| @Override |
| public void inheritFingerprint(String fingerprint) throws AuthorizationAccessException { |
| configurableUserGroupProvider.inheritFingerprint(fingerprint); |
| } |
| |
| @Override |
| public void checkInheritability(String proposedFingerprint) throws AuthorizationAccessException, UninheritableAuthorizationsException { |
| configurableUserGroupProvider.checkInheritability(proposedFingerprint); |
| } |
| |
| @Override |
| public User addUser(User user) throws AuthorizationAccessException { |
| return configurableUserGroupProvider.addUser(user); |
| } |
| |
| @Override |
| public boolean isConfigurable(User user) { |
| return configurableUserGroupProvider.isConfigurable(user); |
| } |
| |
| @Override |
| public User updateUser(User user) throws AuthorizationAccessException { |
| return configurableUserGroupProvider.updateUser(user); |
| } |
| |
| @Override |
| public User deleteUser(User user) throws AuthorizationAccessException { |
| return configurableUserGroupProvider.deleteUser(user); |
| } |
| |
| @Override |
| public User deleteUser(String userIdentifier) throws AuthorizationAccessException { |
| return configurableUserGroupProvider.deleteUser(userIdentifier); |
| } |
| |
| @Override |
| public Group addGroup(Group group) throws AuthorizationAccessException { |
| return configurableUserGroupProvider.addGroup(group); |
| } |
| |
| @Override |
| public boolean isConfigurable(Group group) { |
| return configurableUserGroupProvider.isConfigurable(group); |
| } |
| |
| @Override |
| public Group updateGroup(Group group) throws AuthorizationAccessException { |
| return configurableUserGroupProvider.updateGroup(group); |
| } |
| |
| @Override |
| public Group deleteGroup(Group group) throws AuthorizationAccessException { |
| return configurableUserGroupProvider.deleteGroup(group); |
| } |
| |
| @Override |
| public Group deleteGroup(String groupIdentifier) throws AuthorizationAccessException { |
| return configurableUserGroupProvider.deleteGroup(groupIdentifier); |
| } |
| |
| @Override |
| public Set<User> getUsers() throws AuthorizationAccessException { |
| final Set<User> users = new HashSet<>(configurableUserGroupProvider.getUsers()); |
| users.addAll(super.getUsers()); |
| return users; |
| } |
| |
| @Override |
| public User getUser(String identifier) throws AuthorizationAccessException { |
| User user = configurableUserGroupProvider.getUser(identifier); |
| |
| if (user == null) { |
| user = super.getUser(identifier); |
| } |
| |
| return user; |
| } |
| |
| @Override |
| public User getUserByIdentity(String identity) throws AuthorizationAccessException { |
| User user = configurableUserGroupProvider.getUserByIdentity(identity); |
| |
| if (user == null) { |
| user = super.getUserByIdentity(identity); |
| } |
| |
| return user; |
| } |
| |
| @Override |
| public Set<Group> getGroups() throws AuthorizationAccessException { |
| final Set<Group> groups = new HashSet<>(configurableUserGroupProvider.getGroups()); |
| groups.addAll(super.getGroups()); |
| return groups; |
| } |
| |
| @Override |
| public Group getGroup(String identifier) throws AuthorizationAccessException { |
| Group group = configurableUserGroupProvider.getGroup(identifier); |
| |
| if (group == null) { |
| group = super.getGroup(identifier); |
| } |
| |
| return group; |
| } |
| |
| @Override |
| public UserAndGroups getUserAndGroups(String identity) throws AuthorizationAccessException { |
| |
| final CompositeUserAndGroups combinedResult; |
| |
| // First, lookup user and groups by identity and combine data from all providers |
| UserAndGroups configurableProviderResult = configurableUserGroupProvider.getUserAndGroups(identity); |
| UserAndGroups compositeProvidersResult = super.getUserAndGroups(identity); |
| |
| if (configurableProviderResult.getUser() != null && compositeProvidersResult.getUser() != null) { |
| throw new IllegalStateException("Multiple UserGroupProviders claim to provide user " + identity); |
| |
| } else if (configurableProviderResult.getUser() != null) { |
| combinedResult = new CompositeUserAndGroups(configurableProviderResult.getUser(), configurableProviderResult.getGroups()); |
| combinedResult.addAllGroups(compositeProvidersResult.getGroups()); |
| |
| } else if (compositeProvidersResult.getUser() != null) { |
| combinedResult = new CompositeUserAndGroups(compositeProvidersResult.getUser(), compositeProvidersResult.getGroups()); |
| combinedResult.addAllGroups(configurableProviderResult.getGroups()); |
| |
| } else { |
| return UserAndGroups.EMPTY; |
| } |
| |
| // Second, lookup groups containing the user identifier |
| String userIdentifier = combinedResult.getUser().getIdentifier(); |
| for (final Group group : configurableUserGroupProvider.getGroups()) { |
| if (group.getUsers() != null && group.getUsers().contains(userIdentifier)) { |
| combinedResult.addGroup(group); |
| } |
| } |
| for (final Group group : super.getGroups()) { |
| if (group.getUsers() != null && group.getUsers().contains(userIdentifier)) { |
| combinedResult.addGroup(group); |
| } |
| } |
| |
| return combinedResult; |
| } |
| |
| @Override |
| public void preDestruction() throws SecurityProviderDestructionException { |
| super.preDestruction(); |
| } |
| |
| } |