mirror of https://github.com/apache/nifi.git
NIFI-1916 Updating FileAuthorizer to extend AbstractPolicyBasedAuthorizer and adding intial loading of data users, groups, and policies
- Implementing CRUD operations and unit tests for Users - Implementing CRUD operations and unit tests for Groups - Implementing CRUD operations and unit tests for AccessPolicies - Adding support for seeding with an initial admin user - Fixing delete for user and group so it removes references from policies - Adding example to authorizations.xml - Adding back the old users schema in preparation for auto-converting to the new format, and providing the AuthorizationConfigurationContext with access to the root process group id - Refactoring some of the FileAuthorizer to ensure thread safety - Adding /groups to policies created for initial admin - This closes #473
This commit is contained in:
parent
806f4d549d
commit
8d8a9cba79
|
@ -27,13 +27,15 @@ public abstract class AbstractPolicyBasedAuthorizer implements Authorizer {
|
|||
|
||||
@Override
|
||||
public final AuthorizationResult authorize(AuthorizationRequest request) throws AuthorizationAccessException {
|
||||
final Set<AccessPolicy> policies = getAccessPolicies(request.getResource());
|
||||
final UsersAndAccessPolicies usersAndAccessPolicies = getUsersAndAccessPolicies();
|
||||
final String resourceIdentifier = request.getResource().getIdentifier();
|
||||
|
||||
final Set<AccessPolicy> policies = usersAndAccessPolicies.getAccessPolicies(resourceIdentifier);
|
||||
if (policies == null || policies.isEmpty()) {
|
||||
return AuthorizationResult.resourceNotFound();
|
||||
}
|
||||
|
||||
final User user = getUserByIdentity(request.getIdentity());
|
||||
final User user = usersAndAccessPolicies.getUser(request.getIdentity());
|
||||
|
||||
if (user == null) {
|
||||
return AuthorizationResult.denied("Unknown user with identity " + request.getIdentity());
|
||||
|
@ -209,12 +211,11 @@ public abstract class AbstractPolicyBasedAuthorizer implements Authorizer {
|
|||
public abstract Set<AccessPolicy> getAccessPolicies() throws AuthorizationAccessException;
|
||||
|
||||
/**
|
||||
* Retrieves the access policies for the given Resource.
|
||||
* Returns the UserAccessPolicies instance.
|
||||
*
|
||||
* @param resource the resource to retrieve policies for
|
||||
* @return a set of policies for the given resource, or an empty set if there are none
|
||||
* @return the UserAccessPolicies instance
|
||||
* @throws AuthorizationAccessException if there was an unexpected error performing the operation
|
||||
*/
|
||||
public abstract Set<AccessPolicy> getAccessPolicies(Resource resource) throws AuthorizationAccessException;
|
||||
public abstract UsersAndAccessPolicies getUsersAndAccessPolicies() throws AuthorizationAccessException;
|
||||
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ public class AccessPolicy {
|
|||
|
||||
private final String identifier;
|
||||
|
||||
private final Resource resource;
|
||||
private final String resource;
|
||||
|
||||
private final Set<String> users;
|
||||
|
||||
|
@ -36,7 +36,7 @@ public class AccessPolicy {
|
|||
|
||||
private final Set<RequestAction> actions;
|
||||
|
||||
private AccessPolicy(final AccessPolicyBuilder builder) {
|
||||
private AccessPolicy(final Builder builder) {
|
||||
this.identifier = builder.identifier;
|
||||
this.resource = builder.resource;
|
||||
this.users = Collections.unmodifiableSet(new HashSet<>(builder.users));
|
||||
|
@ -51,10 +51,6 @@ public class AccessPolicy {
|
|||
throw new IllegalArgumentException("Resource can not be null");
|
||||
}
|
||||
|
||||
if ((this.users == null || this.users.isEmpty()) && (this.groups == null || this.groups.isEmpty())) {
|
||||
throw new IllegalArgumentException("Users & Groups can not both be null or empty");
|
||||
}
|
||||
|
||||
if (this.actions == null || this.actions.isEmpty()) {
|
||||
throw new IllegalArgumentException("Actions can not be null or empty");
|
||||
}
|
||||
|
@ -70,7 +66,7 @@ public class AccessPolicy {
|
|||
/**
|
||||
* @return the resource for this policy
|
||||
*/
|
||||
public Resource getResource() {
|
||||
public String getResource() {
|
||||
return resource;
|
||||
}
|
||||
|
||||
|
@ -116,16 +112,16 @@ public class AccessPolicy {
|
|||
@Override
|
||||
public String toString() {
|
||||
return String.format("identifier[%s], resource[%s], users[%s], groups[%s], action[%s]",
|
||||
getIdentifier(), getResource().getIdentifier(), getUsers(), getGroups(), getActions());
|
||||
getIdentifier(), getResource(), getUsers(), getGroups(), getActions());
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder for Access Policies.
|
||||
*/
|
||||
public static class AccessPolicyBuilder {
|
||||
public static class Builder {
|
||||
|
||||
private String identifier;
|
||||
private Resource resource;
|
||||
private String resource;
|
||||
private Set<String> users = new HashSet<>();
|
||||
private Set<String> groups = new HashSet<>();
|
||||
private Set<RequestAction> actions = new HashSet<>();
|
||||
|
@ -134,7 +130,7 @@ public class AccessPolicy {
|
|||
/**
|
||||
* Default constructor for building a new AccessPolicy.
|
||||
*/
|
||||
public AccessPolicyBuilder() {
|
||||
public Builder() {
|
||||
this.fromPolicy = false;
|
||||
}
|
||||
|
||||
|
@ -145,7 +141,7 @@ public class AccessPolicy {
|
|||
*
|
||||
* @param other the existing access policy to initialize from
|
||||
*/
|
||||
public AccessPolicyBuilder(final AccessPolicy other) {
|
||||
public Builder(final AccessPolicy other) {
|
||||
if (other == null) {
|
||||
throw new IllegalArgumentException("Can not initialize builder with a null access policy");
|
||||
}
|
||||
|
@ -168,7 +164,7 @@ public class AccessPolicy {
|
|||
* @return the builder
|
||||
* @throws IllegalStateException if this method is called when this builder was constructed from an existing Policy
|
||||
*/
|
||||
public AccessPolicyBuilder identifier(final String identifier) {
|
||||
public Builder identifier(final String identifier) {
|
||||
if (fromPolicy) {
|
||||
throw new IllegalStateException(
|
||||
"Identifier can not be changed when initialized from an existing policy");
|
||||
|
@ -184,7 +180,7 @@ public class AccessPolicy {
|
|||
* @param resource the resource to set
|
||||
* @return the builder
|
||||
*/
|
||||
public AccessPolicyBuilder resource(final Resource resource) {
|
||||
public Builder resource(final String resource) {
|
||||
this.resource = resource;
|
||||
return this;
|
||||
}
|
||||
|
@ -195,7 +191,7 @@ public class AccessPolicy {
|
|||
* @param users the users to add
|
||||
* @return the builder
|
||||
*/
|
||||
public AccessPolicyBuilder addUsers(final Set<String> users) {
|
||||
public Builder addUsers(final Set<String> users) {
|
||||
if (users != null) {
|
||||
this.users.addAll(users);
|
||||
}
|
||||
|
@ -208,7 +204,7 @@ public class AccessPolicy {
|
|||
* @param user the user to add
|
||||
* @return the builder
|
||||
*/
|
||||
public AccessPolicyBuilder addUser(final String user) {
|
||||
public Builder addUser(final String user) {
|
||||
if (user != null) {
|
||||
this.users.add(user);
|
||||
}
|
||||
|
@ -221,7 +217,7 @@ public class AccessPolicy {
|
|||
* @param users the users to remove
|
||||
* @return the builder
|
||||
*/
|
||||
public AccessPolicyBuilder removeUsers(final Set<String> users) {
|
||||
public Builder removeUsers(final Set<String> users) {
|
||||
if (users != null) {
|
||||
this.users.removeAll(users);
|
||||
}
|
||||
|
@ -234,7 +230,7 @@ public class AccessPolicy {
|
|||
* @param user the user to remove
|
||||
* @return the builder
|
||||
*/
|
||||
public AccessPolicyBuilder removeUser(final String user) {
|
||||
public Builder removeUser(final String user) {
|
||||
if (user != null) {
|
||||
this.users.remove(user);
|
||||
}
|
||||
|
@ -246,7 +242,7 @@ public class AccessPolicy {
|
|||
*
|
||||
* @return the builder
|
||||
*/
|
||||
public AccessPolicyBuilder clearUsers() {
|
||||
public Builder clearUsers() {
|
||||
this.users.clear();
|
||||
return this;
|
||||
}
|
||||
|
@ -257,7 +253,7 @@ public class AccessPolicy {
|
|||
* @param groups the groups to add
|
||||
* @return the builder
|
||||
*/
|
||||
public AccessPolicyBuilder addGroups(final Set<String> groups) {
|
||||
public Builder addGroups(final Set<String> groups) {
|
||||
if (groups != null) {
|
||||
this.groups.addAll(groups);
|
||||
}
|
||||
|
@ -270,7 +266,7 @@ public class AccessPolicy {
|
|||
* @param group the group to add
|
||||
* @return the builder
|
||||
*/
|
||||
public AccessPolicyBuilder addGroup(final String group) {
|
||||
public Builder addGroup(final String group) {
|
||||
if (group != null) {
|
||||
this.groups.add(group);
|
||||
}
|
||||
|
@ -283,7 +279,7 @@ public class AccessPolicy {
|
|||
* @param groups the groups to remove
|
||||
* @return the builder
|
||||
*/
|
||||
public AccessPolicyBuilder removeGroups(final Set<String> groups) {
|
||||
public Builder removeGroups(final Set<String> groups) {
|
||||
if (groups != null) {
|
||||
this.groups.removeAll(groups);
|
||||
}
|
||||
|
@ -296,7 +292,7 @@ public class AccessPolicy {
|
|||
* @param group the group to remove
|
||||
* @return the builder
|
||||
*/
|
||||
public AccessPolicyBuilder removeGroup(final String group) {
|
||||
public Builder removeGroup(final String group) {
|
||||
if (group != null) {
|
||||
this.groups.remove(group);
|
||||
}
|
||||
|
@ -308,7 +304,7 @@ public class AccessPolicy {
|
|||
*
|
||||
* @return the builder
|
||||
*/
|
||||
public AccessPolicyBuilder clearGroups() {
|
||||
public Builder clearGroups() {
|
||||
this.groups.clear();
|
||||
return this;
|
||||
}
|
||||
|
@ -319,7 +315,7 @@ public class AccessPolicy {
|
|||
* @param action the action to add
|
||||
* @return the builder
|
||||
*/
|
||||
public AccessPolicyBuilder addAction(final RequestAction action) {
|
||||
public Builder addAction(final RequestAction action) {
|
||||
this.actions.add(action);
|
||||
return this;
|
||||
}
|
||||
|
@ -330,7 +326,7 @@ public class AccessPolicy {
|
|||
* @param action the action to remove
|
||||
* @return the builder
|
||||
*/
|
||||
public AccessPolicyBuilder removeAction(final RequestAction action) {
|
||||
public Builder removeAction(final RequestAction action) {
|
||||
this.actions.remove(action);
|
||||
return this;
|
||||
}
|
||||
|
@ -340,7 +336,7 @@ public class AccessPolicy {
|
|||
*
|
||||
* @return the builder
|
||||
*/
|
||||
public AccessPolicyBuilder clearActions() {
|
||||
public Builder clearActions() {
|
||||
this.actions.clear();
|
||||
return this;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,11 @@ public interface AuthorizerConfigurationContext {
|
|||
*/
|
||||
String getIdentifier();
|
||||
|
||||
/**
|
||||
* @return the id of the root process group
|
||||
*/
|
||||
String getRootGroupId();
|
||||
|
||||
/**
|
||||
* Retrieves all properties the component currently understands regardless
|
||||
* of whether a value has been set for them or not. If no value is present
|
||||
|
|
|
@ -32,7 +32,7 @@ public class Group {
|
|||
|
||||
private final Set<String> users;
|
||||
|
||||
private Group(final GroupBuilder builder) {
|
||||
private Group(final Builder builder) {
|
||||
this.identifier = builder.identifier;
|
||||
this.name = builder.name;
|
||||
this.users = Collections.unmodifiableSet(new HashSet<>(builder.users));
|
||||
|
@ -61,6 +61,9 @@ public class Group {
|
|||
}
|
||||
|
||||
/**
|
||||
* NOTE: This set of users is populated when retrieving an existing group and will be ignored when adding a new Group.
|
||||
* To add a User to a group, it should be done by adding or updating a User with the appropriate Group id.
|
||||
*
|
||||
* @return an unmodifiable set of user identifiers that belong to this group
|
||||
*/
|
||||
public Set<String> getUsers() {
|
||||
|
@ -94,14 +97,14 @@ public class Group {
|
|||
/**
|
||||
* Builder for creating Groups.
|
||||
*/
|
||||
public static class GroupBuilder {
|
||||
public static class Builder {
|
||||
|
||||
private String identifier;
|
||||
private String name;
|
||||
private Set<String> users = new HashSet<>();
|
||||
private final boolean fromGroup;
|
||||
|
||||
public GroupBuilder() {
|
||||
public Builder() {
|
||||
this.fromGroup = false;
|
||||
}
|
||||
|
||||
|
@ -112,7 +115,7 @@ public class Group {
|
|||
*
|
||||
* @param other the existing access policy to initialize from
|
||||
*/
|
||||
public GroupBuilder(final Group other) {
|
||||
public Builder(final Group other) {
|
||||
if (other == null) {
|
||||
throw new IllegalArgumentException("Provided group can not be null");
|
||||
}
|
||||
|
@ -131,7 +134,7 @@ public class Group {
|
|||
* @return the builder
|
||||
* @throws IllegalStateException if this method is called when this builder was constructed from an existing Group
|
||||
*/
|
||||
public GroupBuilder identifier(final String identifier) {
|
||||
public Builder identifier(final String identifier) {
|
||||
if (fromGroup) {
|
||||
throw new IllegalStateException(
|
||||
"Identifier can not be changed when initialized from an existing group");
|
||||
|
@ -147,7 +150,7 @@ public class Group {
|
|||
* @param name the name
|
||||
* @return the builder
|
||||
*/
|
||||
public GroupBuilder name(final String name) {
|
||||
public Builder name(final String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
@ -158,7 +161,7 @@ public class Group {
|
|||
* @param users a set of users to add
|
||||
* @return the builder
|
||||
*/
|
||||
public GroupBuilder addUsers(final Set<String> users) {
|
||||
public Builder addUsers(final Set<String> users) {
|
||||
if (users != null) {
|
||||
this.users.addAll(users);
|
||||
}
|
||||
|
@ -171,7 +174,7 @@ public class Group {
|
|||
* @param user the user to add
|
||||
* @return the builder
|
||||
*/
|
||||
public GroupBuilder addUser(final String user) {
|
||||
public Builder addUser(final String user) {
|
||||
if (user != null) {
|
||||
this.users.add(user);
|
||||
}
|
||||
|
@ -184,7 +187,7 @@ public class Group {
|
|||
* @param user the user to remove
|
||||
* @return the builder
|
||||
*/
|
||||
public GroupBuilder removeUser(final String user) {
|
||||
public Builder removeUser(final String user) {
|
||||
if (user != null) {
|
||||
this.users.remove(user);
|
||||
}
|
||||
|
@ -197,7 +200,7 @@ public class Group {
|
|||
* @param users the users to remove
|
||||
* @return the builder
|
||||
*/
|
||||
public GroupBuilder removeUsers(final Set<String> users) {
|
||||
public Builder removeUsers(final Set<String> users) {
|
||||
if (users != null) {
|
||||
this.users.removeAll(users);
|
||||
}
|
||||
|
@ -209,7 +212,7 @@ public class Group {
|
|||
*
|
||||
* @return the builder
|
||||
*/
|
||||
public GroupBuilder clearUsers() {
|
||||
public Builder clearUsers() {
|
||||
this.users.clear();
|
||||
return this;
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ public class User {
|
|||
|
||||
private final Set<String> groups;
|
||||
|
||||
private User(final UserBuilder builder) {
|
||||
private User(final Builder builder) {
|
||||
this.identifier = builder.identifier;
|
||||
this.identity = builder.identity;
|
||||
this.groups = Collections.unmodifiableSet(new HashSet<>(builder.groups));
|
||||
|
@ -94,7 +94,7 @@ public class User {
|
|||
/**
|
||||
* Builder for Users.
|
||||
*/
|
||||
public static class UserBuilder {
|
||||
public static class Builder {
|
||||
|
||||
private String identifier;
|
||||
private String identity;
|
||||
|
@ -104,7 +104,7 @@ public class User {
|
|||
/**
|
||||
* Default constructor for building a new User.
|
||||
*/
|
||||
public UserBuilder() {
|
||||
public Builder() {
|
||||
this.fromUser = false;
|
||||
}
|
||||
|
||||
|
@ -115,7 +115,7 @@ public class User {
|
|||
*
|
||||
* @param other the existing user to initialize from
|
||||
*/
|
||||
public UserBuilder(final User other) {
|
||||
public Builder(final User other) {
|
||||
if (other == null) {
|
||||
throw new IllegalArgumentException("Provided user can not be null");
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ public class User {
|
|||
* @return the builder
|
||||
* @throws IllegalStateException if this method is called when this builder was constructed from an existing User
|
||||
*/
|
||||
public UserBuilder identifier(final String identifier) {
|
||||
public Builder identifier(final String identifier) {
|
||||
if (fromUser) {
|
||||
throw new IllegalStateException(
|
||||
"Identifier can not be changed when initialized from an existing user");
|
||||
|
@ -150,7 +150,7 @@ public class User {
|
|||
* @param identity the identity to set
|
||||
* @return the builder
|
||||
*/
|
||||
public UserBuilder identity(final String identity) {
|
||||
public Builder identity(final String identity) {
|
||||
this.identity = identity;
|
||||
return this;
|
||||
}
|
||||
|
@ -161,7 +161,7 @@ public class User {
|
|||
* @param groups the groups to add
|
||||
* @return the builder
|
||||
*/
|
||||
public UserBuilder addGroups(final Set<String> groups) {
|
||||
public Builder addGroups(final Set<String> groups) {
|
||||
if (groups != null) {
|
||||
this.groups.addAll(groups);
|
||||
}
|
||||
|
@ -174,7 +174,7 @@ public class User {
|
|||
* @param group the group to add
|
||||
* @return the builder
|
||||
*/
|
||||
public UserBuilder addGroup(final String group) {
|
||||
public Builder addGroup(final String group) {
|
||||
if (group != null) {
|
||||
this.groups.add(group);
|
||||
}
|
||||
|
@ -187,7 +187,7 @@ public class User {
|
|||
* @param groups the groups to remove
|
||||
* @return the builder
|
||||
*/
|
||||
public UserBuilder removeGroups(final Set<String> groups) {
|
||||
public Builder removeGroups(final Set<String> groups) {
|
||||
if (groups != null) {
|
||||
this.groups.removeAll(groups);
|
||||
}
|
||||
|
@ -200,7 +200,7 @@ public class User {
|
|||
* @param group the group to remove
|
||||
* @return the builder
|
||||
*/
|
||||
public UserBuilder removeGroup(final String group) {
|
||||
public Builder removeGroup(final String group) {
|
||||
if (group != null) {
|
||||
this.groups.remove(group);
|
||||
}
|
||||
|
@ -212,7 +212,7 @@ public class User {
|
|||
*
|
||||
* @return the builder
|
||||
*/
|
||||
public UserBuilder clearGroups() {
|
||||
public Builder clearGroups() {
|
||||
this.groups.clear();
|
||||
return this;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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.authorization;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A holder object to provide atomic access to policies for a given resource and users by
|
||||
* identity. Implementations must ensure consistent access to the data backing this instance.
|
||||
*/
|
||||
public interface UsersAndAccessPolicies {
|
||||
|
||||
/**
|
||||
* Retrieves the set of access policies for a given resource.
|
||||
*
|
||||
* @param resourceIdentifier the resource identifier to retrieve policies for
|
||||
* @return the set of access policies for the given resource
|
||||
*/
|
||||
public Set<AccessPolicy> getAccessPolicies(final String resourceIdentifier);
|
||||
|
||||
/**
|
||||
* Retrieves a user by an identity string.
|
||||
*
|
||||
* @param identity the identity of the user to retrieve
|
||||
* @return the user with the given identity
|
||||
*/
|
||||
public User getUser(final String identity);
|
||||
|
||||
}
|
|
@ -42,26 +42,28 @@ public class TestAbstractPolicyBasedAuthorizer {
|
|||
@Test
|
||||
public void testApproveBasedOnUser() {
|
||||
AbstractPolicyBasedAuthorizer authorizer = Mockito.mock(AbstractPolicyBasedAuthorizer.class);
|
||||
UsersAndAccessPolicies usersAndAccessPolicies = Mockito.mock(UsersAndAccessPolicies.class);
|
||||
when(authorizer.getUsersAndAccessPolicies()).thenReturn(usersAndAccessPolicies);
|
||||
|
||||
final String userIdentifier = "userIdentifier1";
|
||||
final String userIdentity = "userIdentity1";
|
||||
|
||||
final Set<AccessPolicy> policiesForResource = new HashSet<>();
|
||||
policiesForResource.add(new AccessPolicy.AccessPolicyBuilder()
|
||||
policiesForResource.add(new AccessPolicy.Builder()
|
||||
.identifier("1")
|
||||
.resource(TEST_RESOURCE)
|
||||
.resource(TEST_RESOURCE.getIdentifier())
|
||||
.addUser(userIdentifier)
|
||||
.addAction(RequestAction.READ)
|
||||
.build());
|
||||
|
||||
when(authorizer.getAccessPolicies(TEST_RESOURCE)).thenReturn(policiesForResource);
|
||||
when(usersAndAccessPolicies.getAccessPolicies(TEST_RESOURCE.getIdentifier())).thenReturn(policiesForResource);
|
||||
|
||||
final User user = new User.UserBuilder()
|
||||
final User user = new User.Builder()
|
||||
.identity(userIdentity)
|
||||
.identifier(userIdentifier)
|
||||
.build();
|
||||
|
||||
when(authorizer.getUserByIdentity(userIdentity)).thenReturn(user);
|
||||
when(usersAndAccessPolicies.getUser(userIdentity)).thenReturn(user);
|
||||
|
||||
final AuthorizationRequest request = new AuthorizationRequest.Builder()
|
||||
.identity(userIdentity)
|
||||
|
@ -77,28 +79,30 @@ public class TestAbstractPolicyBasedAuthorizer {
|
|||
@Test
|
||||
public void testApprovedBasedOnGroup() {
|
||||
AbstractPolicyBasedAuthorizer authorizer = Mockito.mock(AbstractPolicyBasedAuthorizer.class);
|
||||
UsersAndAccessPolicies usersAndAccessPolicies = Mockito.mock(UsersAndAccessPolicies.class);
|
||||
when(authorizer.getUsersAndAccessPolicies()).thenReturn(usersAndAccessPolicies);
|
||||
|
||||
final String userIdentifier = "userIdentifier1";
|
||||
final String userIdentity = "userIdentity1";
|
||||
final String groupIdentifier = "groupIdentifier1";
|
||||
|
||||
final Set<AccessPolicy> policiesForResource = new HashSet<>();
|
||||
policiesForResource.add(new AccessPolicy.AccessPolicyBuilder()
|
||||
policiesForResource.add(new AccessPolicy.Builder()
|
||||
.identifier("1")
|
||||
.resource(TEST_RESOURCE)
|
||||
.resource(TEST_RESOURCE.getIdentifier())
|
||||
.addGroup(groupIdentifier)
|
||||
.addAction(RequestAction.READ)
|
||||
.build());
|
||||
|
||||
when(authorizer.getAccessPolicies(TEST_RESOURCE)).thenReturn(policiesForResource);
|
||||
when(usersAndAccessPolicies.getAccessPolicies(TEST_RESOURCE.getIdentifier())).thenReturn(policiesForResource);
|
||||
|
||||
final User user = new User.UserBuilder()
|
||||
final User user = new User.Builder()
|
||||
.identity(userIdentity)
|
||||
.identifier(userIdentifier)
|
||||
.addGroup(groupIdentifier)
|
||||
.build();
|
||||
|
||||
when(authorizer.getUserByIdentity(userIdentity)).thenReturn(user);
|
||||
when(usersAndAccessPolicies.getUser(userIdentity)).thenReturn(user);
|
||||
|
||||
final AuthorizationRequest request = new AuthorizationRequest.Builder()
|
||||
.identity(userIdentity)
|
||||
|
@ -114,26 +118,28 @@ public class TestAbstractPolicyBasedAuthorizer {
|
|||
@Test
|
||||
public void testDeny() {
|
||||
AbstractPolicyBasedAuthorizer authorizer = Mockito.mock(AbstractPolicyBasedAuthorizer.class);
|
||||
UsersAndAccessPolicies usersAndAccessPolicies = Mockito.mock(UsersAndAccessPolicies.class);
|
||||
when(authorizer.getUsersAndAccessPolicies()).thenReturn(usersAndAccessPolicies);
|
||||
|
||||
final String userIdentifier = "userIdentifier1";
|
||||
final String userIdentity = "userIdentity1";
|
||||
|
||||
final Set<AccessPolicy> policiesForResource = new HashSet<>();
|
||||
policiesForResource.add(new AccessPolicy.AccessPolicyBuilder()
|
||||
policiesForResource.add(new AccessPolicy.Builder()
|
||||
.identifier("1")
|
||||
.resource(TEST_RESOURCE)
|
||||
.resource(TEST_RESOURCE.getIdentifier())
|
||||
.addUser("NOT_USER_1")
|
||||
.addAction(RequestAction.READ)
|
||||
.build());
|
||||
|
||||
when(authorizer.getAccessPolicies(TEST_RESOURCE)).thenReturn(policiesForResource);
|
||||
when(usersAndAccessPolicies.getAccessPolicies(TEST_RESOURCE.getIdentifier())).thenReturn(policiesForResource);
|
||||
|
||||
final User user = new User.UserBuilder()
|
||||
final User user = new User.Builder()
|
||||
.identity(userIdentity)
|
||||
.identifier(userIdentifier)
|
||||
.build();
|
||||
|
||||
when(authorizer.getUserByIdentity(userIdentity)).thenReturn(user);
|
||||
when(usersAndAccessPolicies.getUser(userIdentity)).thenReturn(user);
|
||||
|
||||
final AuthorizationRequest request = new AuthorizationRequest.Builder()
|
||||
.identity(userIdentity)
|
||||
|
@ -149,7 +155,10 @@ public class TestAbstractPolicyBasedAuthorizer {
|
|||
@Test
|
||||
public void testResourceNotFound() {
|
||||
AbstractPolicyBasedAuthorizer authorizer = Mockito.mock(AbstractPolicyBasedAuthorizer.class);
|
||||
when(authorizer.getAccessPolicies(TEST_RESOURCE)).thenReturn(new HashSet<>());
|
||||
UsersAndAccessPolicies usersAndAccessPolicies = Mockito.mock(UsersAndAccessPolicies.class);
|
||||
when(authorizer.getUsersAndAccessPolicies()).thenReturn(usersAndAccessPolicies);
|
||||
|
||||
when(usersAndAccessPolicies.getAccessPolicies(TEST_RESOURCE.getIdentifier())).thenReturn(new HashSet<>());
|
||||
|
||||
final AuthorizationRequest request = new AuthorizationRequest.Builder()
|
||||
.identity("userIdentity")
|
||||
|
|
|
@ -28,17 +28,7 @@ import static org.junit.Assert.fail;
|
|||
|
||||
public class TestAccessPolicy {
|
||||
|
||||
static final Resource TEST_RESOURCE = new Resource() {
|
||||
@Override
|
||||
public String getIdentifier() {
|
||||
return "1";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "resource1";
|
||||
}
|
||||
};
|
||||
static final String TEST_RESOURCE = "1";
|
||||
|
||||
@Test
|
||||
public void testSimpleCreation() {
|
||||
|
@ -47,7 +37,7 @@ public class TestAccessPolicy {
|
|||
final String user2 = "user2";
|
||||
final RequestAction action = RequestAction.READ;
|
||||
|
||||
final AccessPolicy policy = new AccessPolicy.AccessPolicyBuilder()
|
||||
final AccessPolicy policy = new AccessPolicy.Builder()
|
||||
.identifier(identifier)
|
||||
.resource(TEST_RESOURCE)
|
||||
.addUser(user1)
|
||||
|
@ -58,7 +48,7 @@ public class TestAccessPolicy {
|
|||
assertEquals(identifier, policy.getIdentifier());
|
||||
|
||||
assertNotNull(policy.getResource());
|
||||
assertEquals(TEST_RESOURCE.getIdentifier(), policy.getResource().getIdentifier());
|
||||
assertEquals(TEST_RESOURCE, policy.getResource());
|
||||
|
||||
assertNotNull(policy.getUsers());
|
||||
assertEquals(2, policy.getUsers().size());
|
||||
|
@ -72,7 +62,7 @@ public class TestAccessPolicy {
|
|||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testMissingIdentifier() {
|
||||
new AccessPolicy.AccessPolicyBuilder()
|
||||
new AccessPolicy.Builder()
|
||||
.resource(TEST_RESOURCE)
|
||||
.addUser("user1")
|
||||
.addAction(RequestAction.READ)
|
||||
|
@ -81,25 +71,27 @@ public class TestAccessPolicy {
|
|||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testMissingResource() {
|
||||
new AccessPolicy.AccessPolicyBuilder()
|
||||
new AccessPolicy.Builder()
|
||||
.identifier("1")
|
||||
.addUser("user1")
|
||||
.addAction(RequestAction.READ)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test
|
||||
public void testMissingUsersAndGroups() {
|
||||
new AccessPolicy.AccessPolicyBuilder()
|
||||
final AccessPolicy policy = new AccessPolicy.Builder()
|
||||
.identifier("1")
|
||||
.resource(TEST_RESOURCE)
|
||||
.addAction(RequestAction.READ)
|
||||
.build();
|
||||
|
||||
assertNotNull(policy);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testMissingActions() {
|
||||
new AccessPolicy.AccessPolicyBuilder()
|
||||
new AccessPolicy.Builder()
|
||||
.identifier("1")
|
||||
.resource(TEST_RESOURCE)
|
||||
.addUser("user1")
|
||||
|
@ -115,7 +107,7 @@ public class TestAccessPolicy {
|
|||
final String group2 = "group2";
|
||||
final RequestAction action = RequestAction.READ;
|
||||
|
||||
final AccessPolicy policy = new AccessPolicy.AccessPolicyBuilder()
|
||||
final AccessPolicy policy = new AccessPolicy.Builder()
|
||||
.identifier(identifier)
|
||||
.resource(TEST_RESOURCE)
|
||||
.addUser(user1)
|
||||
|
@ -128,7 +120,7 @@ public class TestAccessPolicy {
|
|||
assertEquals(identifier, policy.getIdentifier());
|
||||
|
||||
assertNotNull(policy.getResource());
|
||||
assertEquals(TEST_RESOURCE.getIdentifier(), policy.getResource().getIdentifier());
|
||||
assertEquals(TEST_RESOURCE, policy.getResource());
|
||||
|
||||
assertNotNull(policy.getUsers());
|
||||
assertEquals(2, policy.getUsers().size());
|
||||
|
@ -144,28 +136,28 @@ public class TestAccessPolicy {
|
|||
assertEquals(1, policy.getActions().size());
|
||||
assertTrue(policy.getActions().contains(action));
|
||||
|
||||
final AccessPolicy policy2 = new AccessPolicy.AccessPolicyBuilder(policy).build();
|
||||
final AccessPolicy policy2 = new AccessPolicy.Builder(policy).build();
|
||||
assertEquals(policy.getIdentifier(), policy2.getIdentifier());
|
||||
assertEquals(policy.getResource().getIdentifier(), policy2.getResource().getIdentifier());
|
||||
assertEquals(policy.getResource(), policy2.getResource());
|
||||
assertEquals(policy.getUsers(), policy2.getUsers());
|
||||
assertEquals(policy.getActions(), policy2.getActions());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void testFromPolicyAndChangeIdentifier() {
|
||||
final AccessPolicy policy = new AccessPolicy.AccessPolicyBuilder()
|
||||
final AccessPolicy policy = new AccessPolicy.Builder()
|
||||
.identifier("1")
|
||||
.resource(TEST_RESOURCE)
|
||||
.addUser("user1")
|
||||
.addAction(RequestAction.READ)
|
||||
.build();
|
||||
|
||||
new AccessPolicy.AccessPolicyBuilder(policy).identifier("2").build();
|
||||
new AccessPolicy.Builder(policy).identifier("2").build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddRemoveClearUsers() {
|
||||
final AccessPolicy.AccessPolicyBuilder builder = new AccessPolicy.AccessPolicyBuilder()
|
||||
final AccessPolicy.Builder builder = new AccessPolicy.Builder()
|
||||
.identifier("1")
|
||||
.resource(TEST_RESOURCE)
|
||||
.addUser("user1")
|
||||
|
@ -201,17 +193,14 @@ public class TestAccessPolicy {
|
|||
assertEquals(1, policy4.getUsers().size());
|
||||
assertTrue(policy4.getUsers().contains("user2"));
|
||||
|
||||
try {
|
||||
builder.clearUsers().build();
|
||||
fail("should have thrown exception");
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
||||
}
|
||||
final AccessPolicy policy5 = builder.clearUsers().build();
|
||||
assertEquals(0, policy5.getUsers().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddRemoveClearGroups() {
|
||||
final AccessPolicy.AccessPolicyBuilder builder = new AccessPolicy.AccessPolicyBuilder()
|
||||
final AccessPolicy.Builder builder = new AccessPolicy.Builder()
|
||||
.identifier("1")
|
||||
.resource(TEST_RESOURCE)
|
||||
.addGroup("group1")
|
||||
|
@ -247,18 +236,13 @@ public class TestAccessPolicy {
|
|||
assertEquals(1, policy4.getGroups().size());
|
||||
assertTrue(policy4.getGroups().contains("group2"));
|
||||
|
||||
try {
|
||||
builder.clearGroups().build();
|
||||
fail("should have thrown exception");
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
||||
}
|
||||
final AccessPolicy policy5 = builder.clearGroups().build();
|
||||
assertEquals(0, policy5.getUsers().size());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testAddRemoveClearActions() {
|
||||
final AccessPolicy.AccessPolicyBuilder builder = new AccessPolicy.AccessPolicyBuilder()
|
||||
final AccessPolicy.Builder builder = new AccessPolicy.Builder()
|
||||
.identifier("1")
|
||||
.resource(TEST_RESOURCE)
|
||||
.addUser("user1")
|
||||
|
|
|
@ -34,7 +34,7 @@ public class TestGroup {
|
|||
final String user1 = "user1";
|
||||
final String user2 = "user2";
|
||||
|
||||
final Group group = new Group.GroupBuilder()
|
||||
final Group group = new Group.Builder()
|
||||
.identifier(id)
|
||||
.name(name)
|
||||
.addUser(user1)
|
||||
|
@ -52,7 +52,7 @@ public class TestGroup {
|
|||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testMissingId() {
|
||||
new Group.GroupBuilder()
|
||||
new Group.Builder()
|
||||
.name("group1")
|
||||
.addUser("user1")
|
||||
.addUser("user2")
|
||||
|
@ -61,7 +61,7 @@ public class TestGroup {
|
|||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testMissingName() {
|
||||
new Group.GroupBuilder()
|
||||
new Group.Builder()
|
||||
.identifier("1")
|
||||
.addUser("user1")
|
||||
.addUser("user2")
|
||||
|
@ -73,7 +73,7 @@ public class TestGroup {
|
|||
final String id = "1";
|
||||
final String name = "group1";
|
||||
|
||||
final Group group = new Group.GroupBuilder()
|
||||
final Group group = new Group.Builder()
|
||||
.identifier(id)
|
||||
.name(name)
|
||||
.build();
|
||||
|
@ -92,7 +92,7 @@ public class TestGroup {
|
|||
final String user1 = "user1";
|
||||
final String user2 = "user2";
|
||||
|
||||
final Group group1 = new Group.GroupBuilder()
|
||||
final Group group1 = new Group.Builder()
|
||||
.identifier(id)
|
||||
.name(name)
|
||||
.addUser(user1)
|
||||
|
@ -107,7 +107,7 @@ public class TestGroup {
|
|||
assertTrue(group1.getUsers().contains(user1));
|
||||
assertTrue(group1.getUsers().contains(user2));
|
||||
|
||||
final Group group2 = new Group.GroupBuilder(group1).build();
|
||||
final Group group2 = new Group.Builder(group1).build();
|
||||
assertEquals(group1.getIdentifier(), group2.getIdentifier());
|
||||
assertEquals(group1.getName(), group2.getName());
|
||||
assertEquals(group1.getUsers(), group2.getUsers());
|
||||
|
@ -115,18 +115,18 @@ public class TestGroup {
|
|||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void testFromGroupAndChangeIdentifier() {
|
||||
final Group group1 = new Group.GroupBuilder()
|
||||
final Group group1 = new Group.Builder()
|
||||
.identifier("1")
|
||||
.name("group1")
|
||||
.addUser("user1")
|
||||
.build();
|
||||
|
||||
new Group.GroupBuilder(group1).identifier("2").build();
|
||||
new Group.Builder(group1).identifier("2").build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddRemoveClearUsers() {
|
||||
final Group.GroupBuilder builder = new Group.GroupBuilder()
|
||||
final Group.Builder builder = new Group.Builder()
|
||||
.identifier("1")
|
||||
.name("group1")
|
||||
.addUser("user1");
|
||||
|
|
|
@ -34,7 +34,7 @@ public class TestUser {
|
|||
final String group1 = "group1";
|
||||
final String group2 = "group2";
|
||||
|
||||
final User user = new User.UserBuilder()
|
||||
final User user = new User.Builder()
|
||||
.identifier(identifier)
|
||||
.identity(identity)
|
||||
.addGroup(group1)
|
||||
|
@ -52,7 +52,7 @@ public class TestUser {
|
|||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testMissingIdentifier() {
|
||||
new User.UserBuilder()
|
||||
new User.Builder()
|
||||
.identity("user1")
|
||||
.addGroup("group1")
|
||||
.addGroup("group2")
|
||||
|
@ -61,7 +61,7 @@ public class TestUser {
|
|||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testMissingIdentity() {
|
||||
new User.UserBuilder()
|
||||
new User.Builder()
|
||||
.identifier("1")
|
||||
.addGroup("group1")
|
||||
.addGroup("group2")
|
||||
|
@ -73,7 +73,7 @@ public class TestUser {
|
|||
final String identifier = "1";
|
||||
final String identity = "user1";
|
||||
|
||||
final User user = new User.UserBuilder()
|
||||
final User user = new User.Builder()
|
||||
.identifier(identifier)
|
||||
.identity(identity)
|
||||
.build();
|
||||
|
@ -92,7 +92,7 @@ public class TestUser {
|
|||
final String group1 = "group1";
|
||||
final String group2 = "group2";
|
||||
|
||||
final User user = new User.UserBuilder()
|
||||
final User user = new User.Builder()
|
||||
.identifier(identifier)
|
||||
.identity(identity)
|
||||
.addGroup(group1)
|
||||
|
@ -107,7 +107,7 @@ public class TestUser {
|
|||
assertTrue(user.getGroups().contains(group1));
|
||||
assertTrue(user.getGroups().contains(group2));
|
||||
|
||||
final User user2 = new User.UserBuilder(user).build();
|
||||
final User user2 = new User.Builder(user).build();
|
||||
assertEquals(user.getIdentifier(), user2.getIdentifier());
|
||||
assertEquals(user.getIdentity(), user2.getIdentity());
|
||||
assertEquals(user.getGroups(), user2.getGroups());
|
||||
|
@ -115,19 +115,19 @@ public class TestUser {
|
|||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void testFromUserAndChangeIdentifier() {
|
||||
final User user = new User.UserBuilder()
|
||||
final User user = new User.Builder()
|
||||
.identifier("1")
|
||||
.identity("user1")
|
||||
.addGroup("group1")
|
||||
.addGroup("group2")
|
||||
.build();
|
||||
|
||||
new User.UserBuilder(user).identifier("2").build();
|
||||
new User.Builder(user).identifier("2").build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddRemoveClearGroups() {
|
||||
final User.UserBuilder builder = new User.UserBuilder()
|
||||
final User.Builder builder = new User.Builder()
|
||||
.identifier("1")
|
||||
.identity("user1")
|
||||
.addGroup("group1");
|
||||
|
|
|
@ -35,6 +35,10 @@
|
|||
<groupId>org.apache.nifi</groupId>
|
||||
<artifactId>nifi-file-authorizer</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.nifi</groupId>
|
||||
<artifactId>nifi-authorizer</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- mark these nifi artifacts as provided since it is included in the lib -->
|
||||
<dependency>
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>nifi-framework</artifactId>
|
||||
<groupId>org.apache.nifi</groupId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>nifi-authorizer</artifactId>
|
||||
|
||||
<build>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>src/main/xsd</directory>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>jaxb2-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>current</id>
|
||||
<goals>
|
||||
<goal>xjc</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<packageName>org.apache.nifi.authorization.generated</packageName>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
<configuration>
|
||||
<excludes>**/authorization/generated/*.java,</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.nifi</groupId>
|
||||
<artifactId>nifi-framework-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.nifi</groupId>
|
||||
<artifactId>nifi-nar-utils</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
|
@ -23,6 +23,7 @@ import org.apache.nifi.authorization.exception.AuthorizerCreationException;
|
|||
import org.apache.nifi.authorization.exception.AuthorizerDestructionException;
|
||||
import org.apache.nifi.authorization.generated.Authorizers;
|
||||
import org.apache.nifi.authorization.generated.Property;
|
||||
import org.apache.nifi.controller.FlowController;
|
||||
import org.apache.nifi.nar.ExtensionManager;
|
||||
import org.apache.nifi.nar.NarCloseable;
|
||||
import org.apache.nifi.util.NiFiProperties;
|
||||
|
@ -71,8 +72,13 @@ public class AuthorizerFactoryBean implements FactoryBean, DisposableBean, Autho
|
|||
|
||||
private Authorizer authorizer;
|
||||
private NiFiProperties properties;
|
||||
private FlowController flowController;
|
||||
private final Map<String, Authorizer> authorizers = new HashMap<>();
|
||||
|
||||
public void setFlowController(FlowController flowController) {
|
||||
this.flowController = flowController;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Authorizer getAuthorizer(String identifier) {
|
||||
return authorizers.get(identifier);
|
||||
|
@ -189,7 +195,7 @@ public class AuthorizerFactoryBean implements FactoryBean, DisposableBean, Autho
|
|||
authorizerProperties.put(property.getName(), property.getValue());
|
||||
}
|
||||
|
||||
return new StandardAuthorizerConfigurationContext(authorizer.getIdentifier(), authorizerProperties);
|
||||
return new StandardAuthorizerConfigurationContext(authorizer.getIdentifier(), flowController.getRootGroupId(), authorizerProperties);
|
||||
}
|
||||
|
||||
private void performMethodInjection(final Authorizer instance, final Class authorizerClass) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
|
|
@ -21,6 +21,7 @@
|
|||
<!-- user/entity authorizer -->
|
||||
<bean id="authorizer" class="org.apache.nifi.authorization.AuthorizerFactoryBean">
|
||||
<property name="properties" ref="nifiProperties"/>
|
||||
<property name="flowController" ref="flowController"/>
|
||||
</bean>
|
||||
|
||||
</beans>
|
|
@ -36,14 +36,28 @@
|
|||
<artifactId>jaxb2-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>xjc</id>
|
||||
<id>authorizations</id>
|
||||
<goals>
|
||||
<goal>xjc</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<schemaDirectory>src/main/xsd</schemaDirectory>
|
||||
<schemaFiles>authorizations.xsd</schemaFiles>
|
||||
<packageName>org.apache.nifi.authorization.file.generated</packageName>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>users</id>
|
||||
<goals>
|
||||
<goal>xjc</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<schemaDirectory>src/main/xsd</schemaDirectory>
|
||||
<schemaFiles>users.xsd</schemaFiles>
|
||||
<packageName>org.apache.nifi.user.generated</packageName>
|
||||
<clearOutputDir>false</clearOutputDir>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<outputDirectory>${project.build.directory}/generated-sources/jaxb</outputDirectory>
|
||||
|
@ -53,7 +67,7 @@
|
|||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
<configuration>
|
||||
<excludes>**/authorization/file/generated/*.java</excludes>
|
||||
<excludes>**/authorization/file/generated/*.java,**/user/generated/*.java</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
|
|
@ -0,0 +1,355 @@
|
|||
/*
|
||||
* 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.authorization;
|
||||
|
||||
|
||||
import org.apache.nifi.authorization.file.generated.Authorizations;
|
||||
import org.apache.nifi.authorization.file.generated.Groups;
|
||||
import org.apache.nifi.authorization.file.generated.Policies;
|
||||
import org.apache.nifi.authorization.file.generated.Users;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A holder to provide atomic access to data structures.
|
||||
*/
|
||||
public class AuthorizationsHolder implements UsersAndAccessPolicies {
|
||||
|
||||
private final Authorizations authorizations;
|
||||
|
||||
private final Set<AccessPolicy> allPolicies;
|
||||
private final Map<String, Set<AccessPolicy>> policiesByResource;
|
||||
private final Map<String, AccessPolicy> policiesById;
|
||||
|
||||
private final Set<User> allUsers;
|
||||
private final Map<String,User> usersById;
|
||||
private final Map<String,User> usersByIdentity;
|
||||
|
||||
private final Set<Group> allGroups;
|
||||
private final Map<String,Group> groupsById;
|
||||
|
||||
/**
|
||||
* Creates a new holder and populates all convenience data structures.
|
||||
*
|
||||
* @param authorizations the current authorizations instance
|
||||
*/
|
||||
public AuthorizationsHolder(final Authorizations authorizations) {
|
||||
this.authorizations = authorizations;
|
||||
|
||||
// load all users
|
||||
final Users users = authorizations.getUsers();
|
||||
final Set<User> allUsers = Collections.unmodifiableSet(createUsers(users));
|
||||
|
||||
// load all groups
|
||||
final Groups groups = authorizations.getGroups();
|
||||
final Set<Group> allGroups = Collections.unmodifiableSet(createGroups(groups, users));
|
||||
|
||||
// load all access policies
|
||||
final Policies policies = authorizations.getPolicies();
|
||||
final Set<AccessPolicy> allPolicies = Collections.unmodifiableSet(createAccessPolicies(policies));
|
||||
|
||||
// create a convenience map to retrieve a user by id
|
||||
final Map<String, User> userByIdMap = Collections.unmodifiableMap(createUserByIdMap(allUsers));
|
||||
|
||||
// create a convenience map to retrieve a user by identity
|
||||
final Map<String, User> userByIdentityMap = Collections.unmodifiableMap(createUserByIdentityMap(allUsers));
|
||||
|
||||
// create a convenience map to retrieve a group by id
|
||||
final Map<String, Group> groupByIdMap = Collections.unmodifiableMap(createGroupByIdMap(allGroups));
|
||||
|
||||
// create a convenience map from resource id to policies
|
||||
final Map<String, Set<AccessPolicy>> policiesByResourceMap = Collections.unmodifiableMap(createResourcePolicyMap(allPolicies));
|
||||
|
||||
// create a convenience map from policy id to policy
|
||||
final Map<String, AccessPolicy> policiesByIdMap = Collections.unmodifiableMap(createPoliciesByIdMap(allPolicies));
|
||||
|
||||
// set all the holders
|
||||
this.allUsers = allUsers;
|
||||
this.allGroups = allGroups;
|
||||
this.allPolicies = allPolicies;
|
||||
this.usersById = userByIdMap;
|
||||
this.usersByIdentity = userByIdentityMap;
|
||||
this.groupsById = groupByIdMap;
|
||||
this.policiesByResource = policiesByResourceMap;
|
||||
this.policiesById = policiesByIdMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates AccessPolicies from the JAXB Policies.
|
||||
*
|
||||
* @param policies the JAXB Policies element
|
||||
* @return a set of AccessPolicies corresponding to the provided Resources
|
||||
*/
|
||||
private Set<AccessPolicy> createAccessPolicies(org.apache.nifi.authorization.file.generated.Policies policies) {
|
||||
Set<AccessPolicy> allPolicies = new HashSet<>();
|
||||
if (policies == null || policies.getPolicy() == null) {
|
||||
return allPolicies;
|
||||
}
|
||||
|
||||
// load the new authorizations
|
||||
for (final org.apache.nifi.authorization.file.generated.Policy policy : policies.getPolicy()) {
|
||||
final String policyIdentifier = policy.getIdentifier();
|
||||
final String resourceIdentifier = policy.getResource();
|
||||
|
||||
// start a new builder and set the policy and resource identifiers
|
||||
final AccessPolicy.Builder builder = new AccessPolicy.Builder()
|
||||
.identifier(policyIdentifier)
|
||||
.resource(resourceIdentifier);
|
||||
|
||||
// add each user identifier
|
||||
for (org.apache.nifi.authorization.file.generated.Policy.User user : policy.getUser()) {
|
||||
builder.addUser(user.getIdentifier());
|
||||
}
|
||||
|
||||
// add each group identifier
|
||||
for (org.apache.nifi.authorization.file.generated.Policy.Group group : policy.getGroup()) {
|
||||
builder.addGroup(group.getIdentifier());
|
||||
}
|
||||
|
||||
// add the appropriate request actions
|
||||
final String authorizationCode = policy.getAction();
|
||||
if (authorizationCode.contains(FileAuthorizer.READ_CODE)) {
|
||||
builder.addAction(RequestAction.READ);
|
||||
}
|
||||
if (authorizationCode.contains(FileAuthorizer.WRITE_CODE)) {
|
||||
builder.addAction(RequestAction.WRITE);
|
||||
}
|
||||
|
||||
// build the policy and add it to the map
|
||||
allPolicies.add(builder.build());
|
||||
}
|
||||
|
||||
return allPolicies;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a set of Users from the JAXB Users.
|
||||
*
|
||||
* @param users the JAXB Users
|
||||
* @return a set of API Users matching the provided JAXB Users
|
||||
*/
|
||||
private Set<User> createUsers(org.apache.nifi.authorization.file.generated.Users users) {
|
||||
Set<User> allUsers = new HashSet<>();
|
||||
if (users == null || users.getUser() == null) {
|
||||
return allUsers;
|
||||
}
|
||||
|
||||
for (org.apache.nifi.authorization.file.generated.User user : users.getUser()) {
|
||||
final User.Builder builder = new User.Builder()
|
||||
.identity(user.getIdentity())
|
||||
.identifier(user.getIdentifier());
|
||||
|
||||
if (user.getGroup() != null) {
|
||||
for (org.apache.nifi.authorization.file.generated.User.Group group : user.getGroup()) {
|
||||
builder.addGroup(group.getIdentifier());
|
||||
}
|
||||
}
|
||||
|
||||
allUsers.add(builder.build());
|
||||
}
|
||||
|
||||
return allUsers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a set of Groups from the JAXB Groups.
|
||||
*
|
||||
* @param groups the JAXB Groups
|
||||
* @return a set of API Groups matching the provided JAXB Groups
|
||||
*/
|
||||
private Set<Group> createGroups(org.apache.nifi.authorization.file.generated.Groups groups,
|
||||
org.apache.nifi.authorization.file.generated.Users users) {
|
||||
Set<Group> allGroups = new HashSet<>();
|
||||
if (groups == null || groups.getGroup() == null) {
|
||||
return allGroups;
|
||||
}
|
||||
|
||||
for (org.apache.nifi.authorization.file.generated.Group group : groups.getGroup()) {
|
||||
final Group.Builder builder = new Group.Builder()
|
||||
.identifier(group.getIdentifier())
|
||||
.name(group.getName());
|
||||
|
||||
// need to figured out what users are in this group by going through the users list
|
||||
final Set<String> groupUsers = getUsersForGroup(users, group.getIdentifier());
|
||||
builder.addUsers(groupUsers);
|
||||
|
||||
allGroups.add(builder.build());
|
||||
}
|
||||
|
||||
return allGroups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the set of user identifiers that are part of the given group.
|
||||
*
|
||||
* @param users the JAXB Users element
|
||||
* @param groupId the group id to get the users for
|
||||
* @return the user identifiers that belong to the group with the given identifier
|
||||
*/
|
||||
private Set<String> getUsersForGroup(org.apache.nifi.authorization.file.generated.Users users, final String groupId) {
|
||||
Set<String> groupUsers = new HashSet<>();
|
||||
|
||||
if (users != null && users.getUser()!= null) {
|
||||
for (org.apache.nifi.authorization.file.generated.User user : users.getUser()) {
|
||||
if (user.getGroup() != null) {
|
||||
for (org.apache.nifi.authorization.file.generated.User.Group group : user.getGroup()) {
|
||||
if (group.getIdentifier().equals(groupId)) {
|
||||
groupUsers.add(user.getIdentifier());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return groupUsers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a map from resource identifier to the set of policies for the given resource.
|
||||
*
|
||||
* @param allPolicies the set of all policies
|
||||
* @return a map from resource identifier to policies
|
||||
*/
|
||||
private Map<String, Set<AccessPolicy>> createResourcePolicyMap(final Set<AccessPolicy> allPolicies) {
|
||||
Map<String, Set<AccessPolicy>> resourcePolicies = new HashMap<>();
|
||||
|
||||
for (AccessPolicy policy : allPolicies) {
|
||||
Set<AccessPolicy> policies = resourcePolicies.get(policy.getResource());
|
||||
if (policies == null) {
|
||||
policies = new HashSet<>();
|
||||
resourcePolicies.put(policy.getResource(), policies);
|
||||
}
|
||||
policies.add(policy);
|
||||
}
|
||||
|
||||
return resourcePolicies;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Map from user identifier to User.
|
||||
*
|
||||
* @param users the set of all users
|
||||
* @return the Map from user identifier to User
|
||||
*/
|
||||
private Map<String,User> createUserByIdMap(final Set<User> users) {
|
||||
Map<String,User> usersMap = new HashMap<>();
|
||||
for (User user : users) {
|
||||
usersMap.put(user.getIdentifier(), user);
|
||||
}
|
||||
return usersMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Map from user identity to User.
|
||||
*
|
||||
* @param users the set of all users
|
||||
* @return the Map from user identity to User
|
||||
*/
|
||||
private Map<String,User> createUserByIdentityMap(final Set<User> users) {
|
||||
Map<String,User> usersMap = new HashMap<>();
|
||||
for (User user : users) {
|
||||
usersMap.put(user.getIdentity(), user);
|
||||
}
|
||||
return usersMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Map from group identifier to Group.
|
||||
*
|
||||
* @param groups the set of all groups
|
||||
* @return the Map from group identifier to Group
|
||||
*/
|
||||
private Map<String,Group> createGroupByIdMap(final Set<Group> groups) {
|
||||
Map<String,Group> groupsMap = new HashMap<>();
|
||||
for (Group group : groups) {
|
||||
groupsMap.put(group.getIdentifier(), group);
|
||||
}
|
||||
return groupsMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Map from policy identifier to AccessPolicy.
|
||||
*
|
||||
* @param policies the set of all access policies
|
||||
* @return the Map from policy identifier to AccessPolicy
|
||||
*/
|
||||
private Map<String, AccessPolicy> createPoliciesByIdMap(final Set<AccessPolicy> policies) {
|
||||
Map<String,AccessPolicy> policyMap = new HashMap<>();
|
||||
for (AccessPolicy policy : policies) {
|
||||
policyMap.put(policy.getIdentifier(), policy);
|
||||
}
|
||||
return policyMap;
|
||||
}
|
||||
|
||||
public Authorizations getAuthorizations() {
|
||||
return authorizations;
|
||||
}
|
||||
|
||||
public Set<AccessPolicy> getAllPolicies() {
|
||||
return allPolicies;
|
||||
}
|
||||
|
||||
public Map<String, Set<AccessPolicy>> getPoliciesByResource() {
|
||||
return policiesByResource;
|
||||
}
|
||||
|
||||
public Map<String, AccessPolicy> getPoliciesById() {
|
||||
return policiesById;
|
||||
}
|
||||
|
||||
public Set<User> getAllUsers() {
|
||||
return allUsers;
|
||||
}
|
||||
|
||||
public Map<String, User> getUsersById() {
|
||||
return usersById;
|
||||
}
|
||||
|
||||
public Map<String, User> getUsersByIdentity() {
|
||||
return usersByIdentity;
|
||||
}
|
||||
|
||||
public Set<Group> getAllGroups() {
|
||||
return allGroups;
|
||||
}
|
||||
|
||||
public Map<String, Group> getGroupsById() {
|
||||
return groupsById;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<AccessPolicy> getAccessPolicies(String resourceIdentifier) {
|
||||
if (resourceIdentifier == null) {
|
||||
throw new IllegalArgumentException("Resource Identifier cannot be null");
|
||||
}
|
||||
return policiesByResource.get(resourceIdentifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public User getUser(String identity) {
|
||||
if (identity == null) {
|
||||
throw new IllegalArgumentException("Identity cannot be null");
|
||||
}
|
||||
return usersByIdentity.get(identity);
|
||||
}
|
||||
|
||||
}
|
|
@ -20,51 +20,49 @@ import org.apache.commons.lang3.StringUtils;
|
|||
import org.apache.nifi.authorization.annotation.AuthorizerContext;
|
||||
import org.apache.nifi.authorization.exception.AuthorizationAccessException;
|
||||
import org.apache.nifi.authorization.exception.AuthorizerCreationException;
|
||||
import org.apache.nifi.authorization.file.generated.Authorization;
|
||||
import org.apache.nifi.authorization.file.generated.Resources;
|
||||
import org.apache.nifi.authorization.file.generated.Resource;
|
||||
import org.apache.nifi.authorization.file.generated.Authorizations;
|
||||
import org.apache.nifi.authorization.file.generated.Groups;
|
||||
import org.apache.nifi.authorization.file.generated.Policies;
|
||||
import org.apache.nifi.authorization.file.generated.Policy;
|
||||
import org.apache.nifi.authorization.file.generated.Users;
|
||||
import org.apache.nifi.components.PropertyValue;
|
||||
import org.apache.nifi.util.NiFiProperties;
|
||||
import org.apache.nifi.util.file.FileUtils;
|
||||
import org.apache.nifi.util.file.monitor.MD5SumMonitor;
|
||||
import org.apache.nifi.util.file.monitor.SynchronousFileWatcher;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
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.Marshaller;
|
||||
import javax.xml.bind.Unmarshaller;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
import javax.xml.validation.Schema;
|
||||
import javax.xml.validation.SchemaFactory;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Date;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* Provides identity checks and grants authorities.
|
||||
*/
|
||||
public class FileAuthorizer implements Authorizer {
|
||||
public class FileAuthorizer extends AbstractPolicyBasedAuthorizer {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(FileAuthorizer.class);
|
||||
private static final String READ_CODE = "R";
|
||||
private static final String WRITE_CODE = "W";
|
||||
private static final String USERS_XSD = "/authorizations.xsd";
|
||||
private static final String JAXB_GENERATED_PATH = "org.apache.nifi.authorization.file.generated";
|
||||
private static final JAXBContext JAXB_CONTEXT = initializeJaxbContext();
|
||||
|
||||
static final String READ_CODE = "R";
|
||||
static final String WRITE_CODE = "W";
|
||||
|
||||
/**
|
||||
* Load the JAXBContext.
|
||||
*/
|
||||
|
@ -76,16 +74,23 @@ public class FileAuthorizer implements Authorizer {
|
|||
}
|
||||
}
|
||||
|
||||
private Schema schema;
|
||||
private SchemaFactory schemaFactory;
|
||||
private NiFiProperties properties;
|
||||
private File authorizationsFile;
|
||||
private File restoreAuthorizationsFile;
|
||||
private SynchronousFileWatcher fileWatcher;
|
||||
private ScheduledExecutorService fileWatcherExecutorService;
|
||||
private String rootGroupId;
|
||||
|
||||
private final AtomicReference<Map<String, Map<String, Set<RequestAction>>>> authorizations = new AtomicReference<>();
|
||||
private final AtomicReference<AuthorizationsHolder> authorizationsHolder = new AtomicReference<>();
|
||||
|
||||
@Override
|
||||
public void initialize(final AuthorizerInitializationContext initializationContext) throws AuthorizerCreationException {
|
||||
try {
|
||||
schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
|
||||
schema = schemaFactory.newSchema(FileAuthorizer.class.getResource(USERS_XSD));
|
||||
} catch (Exception e) {
|
||||
throw new AuthorizerCreationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -127,142 +132,142 @@ public class FileAuthorizer implements Authorizer {
|
|||
}
|
||||
}
|
||||
|
||||
final PropertyValue rawReloadInterval = configurationContext.getProperty("Reload Interval");
|
||||
final PropertyValue initialAdminIdentityProp = configurationContext.getProperty("Initial Admin Identity");
|
||||
final String initialAdminIdentity = initialAdminIdentityProp == null ? null : initialAdminIdentityProp.getValue();
|
||||
|
||||
long reloadInterval;
|
||||
try {
|
||||
reloadInterval = rawReloadInterval.asTimePeriod(TimeUnit.MILLISECONDS);
|
||||
} catch (final Exception iae) {
|
||||
logger.info(String.format("Unable to interpret reload interval '%s'. Using default of 30 seconds.", rawReloadInterval));
|
||||
reloadInterval = 30000L;
|
||||
// load the authorizations
|
||||
load(initialAdminIdentity);
|
||||
|
||||
// if we've copied the authorizations file to a restore directory synchronize it
|
||||
if (restoreAuthorizationsFile != null) {
|
||||
FileUtils.copyFile(authorizationsFile, restoreAuthorizationsFile, false, false, logger);
|
||||
}
|
||||
|
||||
// reload the authorizations
|
||||
reload();
|
||||
logger.info(String.format("Authorizations file loaded at %s", new Date().toString()));
|
||||
|
||||
// watch the file for modifications
|
||||
fileWatcher = new SynchronousFileWatcher(authorizationsFile.toPath(), new MD5SumMonitor());
|
||||
fileWatcherExecutorService = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
|
||||
@Override
|
||||
public Thread newThread(final Runnable r) {
|
||||
return new Thread(r, "Authorization File Reload Thread");
|
||||
}
|
||||
});
|
||||
fileWatcherExecutorService.scheduleWithFixedDelay(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
if (fileWatcher.checkAndReset()) {
|
||||
reload();
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
logger.warn("Unable to reload Authorizations file do to: " + e, e);
|
||||
}
|
||||
}
|
||||
}, reloadInterval, reloadInterval, TimeUnit.MILLISECONDS);
|
||||
} catch (IOException | AuthorizerCreationException | SAXException | JAXBException | IllegalStateException e) {
|
||||
this.rootGroupId = configurationContext.getRootGroupId();
|
||||
|
||||
} catch (IOException | AuthorizerCreationException | JAXBException | IllegalStateException e) {
|
||||
throw new AuthorizerCreationException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthorizationResult authorize(final AuthorizationRequest request) throws AuthorizationAccessException {
|
||||
// get the current authorizations
|
||||
final Map<String, Map<String, Set<RequestAction>>> currentAuthorizations = authorizations.get();
|
||||
|
||||
// get the requested resource
|
||||
final org.apache.nifi.authorization.Resource requestedResource = request.getResource();
|
||||
|
||||
// get the authorizations for the requested resources
|
||||
final Map<String, Set<RequestAction>> resourceAuthorizations = currentAuthorizations.get(requestedResource.getIdentifier());
|
||||
|
||||
// ensure the resource has authorizations
|
||||
if (resourceAuthorizations == null) {
|
||||
return AuthorizationResult.resourceNotFound();
|
||||
}
|
||||
|
||||
// get the user authorizations
|
||||
final Set<RequestAction> userAuthorizations = resourceAuthorizations.get(request.getIdentity());
|
||||
|
||||
// ensure the user has authorizations
|
||||
if (userAuthorizations == null) {
|
||||
return AuthorizationResult.denied();
|
||||
}
|
||||
|
||||
// ensure the appropriate response
|
||||
if (userAuthorizations.contains(request.getAction())) {
|
||||
return AuthorizationResult.approved();
|
||||
} else {
|
||||
return AuthorizationResult.denied();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reloads the authorized users file.
|
||||
* Loads the authorizations file and populates the AuthorizationsHolder, only called during start-up.
|
||||
*
|
||||
* @throws SAXException Unable to reload the authorized users file
|
||||
* @throws JAXBException Unable to reload the authorized users file
|
||||
* @throws IOException Unable to sync file with restore
|
||||
* @throws IllegalStateException Unable to sync file with restore
|
||||
*/
|
||||
private void reload() throws SAXException, JAXBException, IOException, IllegalStateException {
|
||||
// find the schema
|
||||
final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
|
||||
final Schema schema = schemaFactory.newSchema(FileAuthorizer.class.getResource(USERS_XSD));
|
||||
|
||||
private synchronized void load(final String initialAdminIdentity) throws JAXBException, IOException, IllegalStateException {
|
||||
// attempt to unmarshal
|
||||
final Unmarshaller unmarshaller = JAXB_CONTEXT.createUnmarshaller();
|
||||
unmarshaller.setSchema(schema);
|
||||
final JAXBElement<Resources> element = unmarshaller.unmarshal(new StreamSource(authorizationsFile), Resources.class);
|
||||
final Resources resources = element.getValue();
|
||||
final JAXBElement<Authorizations> element = unmarshaller.unmarshal(new StreamSource(authorizationsFile), Authorizations.class);
|
||||
|
||||
// new authorizations
|
||||
final Map<String, Map<String, Set<RequestAction>>> newAuthorizations = new HashMap<>();
|
||||
final Authorizations authorizations = element.getValue();
|
||||
|
||||
// load the new authorizations
|
||||
for (final Resource authorizedResource : resources.getResource()) {
|
||||
final String identifier = authorizedResource.getIdentifier();
|
||||
|
||||
// ensure the entry exists
|
||||
if (!newAuthorizations.containsKey(identifier)) {
|
||||
newAuthorizations.put(identifier, new HashMap<String, Set<RequestAction>>());
|
||||
}
|
||||
|
||||
// go through each authorization
|
||||
for (final Authorization authorization : authorizedResource.getAuthorization()) {
|
||||
final String identity = authorization.getIdentity();
|
||||
|
||||
// get the authorizations for this resource
|
||||
final Map<String, Set<RequestAction>> resourceAuthorizations = newAuthorizations.get(identifier);
|
||||
|
||||
// ensure the entry exists
|
||||
if (!resourceAuthorizations.containsKey(identity)) {
|
||||
resourceAuthorizations.put(identity, EnumSet.noneOf(RequestAction.class));
|
||||
}
|
||||
|
||||
final Set<RequestAction> authorizedActions = resourceAuthorizations.get(identity);
|
||||
final String authorizationCode = authorization.getAction();
|
||||
|
||||
// updated the actions for this identity
|
||||
if (authorizationCode.contains(READ_CODE)) {
|
||||
authorizedActions.add(RequestAction.READ);
|
||||
}
|
||||
if (authorizationCode.contains(WRITE_CODE)) {
|
||||
authorizedActions.add(RequestAction.WRITE);
|
||||
}
|
||||
}
|
||||
if (authorizations.getUsers() == null) {
|
||||
authorizations.setUsers(new Users());
|
||||
}
|
||||
if (authorizations.getGroups() == null) {
|
||||
authorizations.setGroups(new Groups());
|
||||
}
|
||||
if (authorizations.getPolicies() == null) {
|
||||
authorizations.setPolicies(new Policies());
|
||||
}
|
||||
|
||||
// set the new authorizations
|
||||
authorizations.set(newAuthorizations);
|
||||
final AuthorizationsHolder authorizationsHolder = new AuthorizationsHolder(authorizations);
|
||||
final boolean hasInitialAdminIdentity = (initialAdminIdentity != null && !StringUtils.isBlank(initialAdminIdentity));
|
||||
|
||||
// if we've copied a the authorizations file to a restore directory synchronize it
|
||||
if (restoreAuthorizationsFile != null) {
|
||||
FileUtils.copyFile(authorizationsFile, restoreAuthorizationsFile, false, false, logger);
|
||||
// if an initial admin was provided and there are no users or policies then automatically create the admin user & policies
|
||||
if (hasInitialAdminIdentity && authorizationsHolder.getAllUsers().isEmpty() && authorizationsHolder.getAllPolicies().isEmpty()) {
|
||||
populateInitialAdmin(authorizations, initialAdminIdentity);
|
||||
saveAndRefreshHolder(authorizations);
|
||||
} else {
|
||||
this.authorizationsHolder.set(authorizationsHolder);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the initial admin user and policies for access the flow and managing users and policies.
|
||||
*
|
||||
* @param adminIdentity the identity of the admin user
|
||||
*/
|
||||
private void populateInitialAdmin(final Authorizations authorizations, final String adminIdentity) {
|
||||
// generate an identifier and add a User with the given identifier and identity
|
||||
final UUID adminIdentifier = UUID.nameUUIDFromBytes(adminIdentity.getBytes(StandardCharsets.UTF_8));
|
||||
final User adminUser = new User.Builder().identifier(adminIdentifier.toString()).identity(adminIdentity).build();
|
||||
|
||||
final org.apache.nifi.authorization.file.generated.User jaxbAdminUser = createJAXBUser(adminUser);
|
||||
authorizations.getUsers().getUser().add(jaxbAdminUser);
|
||||
|
||||
// grant the user read access to the /flow resource
|
||||
final AccessPolicy flowPolicy = createInitialAdminPolicy("/flow", adminUser.getIdentifier(), RequestAction.READ);
|
||||
final Policy jaxbFlowPolicy = createJAXBPolicy(flowPolicy);
|
||||
authorizations.getPolicies().getPolicy().add(jaxbFlowPolicy);
|
||||
|
||||
// grant the user read/write access to the /users resource
|
||||
final AccessPolicy usersPolicy = createInitialAdminPolicy("/users", adminUser.getIdentifier(), RequestAction.READ, RequestAction.WRITE);
|
||||
final Policy jaxbUsersPolicy = createJAXBPolicy(usersPolicy);
|
||||
authorizations.getPolicies().getPolicy().add(jaxbUsersPolicy);
|
||||
|
||||
// grant the user read/write access to the /groups resource
|
||||
final AccessPolicy groupsPolicy = createInitialAdminPolicy("/groups", adminUser.getIdentifier(), RequestAction.READ, RequestAction.WRITE);
|
||||
final Policy jaxbGroupsPolicy = createJAXBPolicy(groupsPolicy);
|
||||
authorizations.getPolicies().getPolicy().add(jaxbGroupsPolicy);
|
||||
|
||||
// grant the user read/write access to the /policies resource
|
||||
final AccessPolicy policiesPolicy = createInitialAdminPolicy("/policies", adminUser.getIdentifier(), RequestAction.READ, RequestAction.WRITE);
|
||||
final Policy jaxbPoliciesPolicy = createJAXBPolicy(policiesPolicy);
|
||||
authorizations.getPolicies().getPolicy().add(jaxbPoliciesPolicy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an AccessPolicy based on the given parameters, generating an identifier from the resource and admin identity.
|
||||
*
|
||||
* @param resource the resource for the policy
|
||||
* @param adminIdentity the identity of the admin user to add to the policy
|
||||
* @param actions the actions for the policy
|
||||
* @return the AccessPolicy based on the given parameters
|
||||
*/
|
||||
private AccessPolicy createInitialAdminPolicy(final String resource, final String adminIdentity, final RequestAction ... actions) {
|
||||
final String uuidSeed = resource + adminIdentity;
|
||||
final UUID flowPolicyIdentifier = UUID.nameUUIDFromBytes(uuidSeed.getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
final AccessPolicy.Builder builder = new AccessPolicy.Builder()
|
||||
.identifier(flowPolicyIdentifier.toString())
|
||||
.resource(resource)
|
||||
.addUser(adminIdentity);
|
||||
|
||||
for (RequestAction action : actions) {
|
||||
builder.addAction(action);
|
||||
}
|
||||
|
||||
logger.info(String.format("Authorizations file loaded at %s", new Date().toString()));
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the Authorizations instance by marshalling to a file, then re-populates the
|
||||
* in-memory data structures and sets the new holder.
|
||||
*
|
||||
* Synchronized to ensure only one thread writes the file at a time.
|
||||
*
|
||||
* @param authorizations the authorizations to save and populate from
|
||||
* @throws AuthorizationAccessException if an error occurs saving the authorizations
|
||||
*/
|
||||
private synchronized void saveAndRefreshHolder(final Authorizations authorizations) throws AuthorizationAccessException {
|
||||
try {
|
||||
final Marshaller marshaller = JAXB_CONTEXT.createMarshaller();
|
||||
marshaller.setSchema(schema);
|
||||
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
|
||||
marshaller.marshal(authorizations, authorizationsFile);
|
||||
|
||||
final AuthorizationsHolder authorizationsHolder = new AuthorizationsHolder(authorizations);
|
||||
this.authorizationsHolder.set(authorizationsHolder);
|
||||
} catch (JAXBException e) {
|
||||
throw new AuthorizationAccessException("Unable to save Authorizations", e);
|
||||
}
|
||||
}
|
||||
|
||||
@AuthorizerContext
|
||||
|
@ -272,8 +277,404 @@ public class FileAuthorizer implements Authorizer {
|
|||
|
||||
@Override
|
||||
public void preDestruction() {
|
||||
if (fileWatcherExecutorService != null) {
|
||||
fileWatcherExecutorService.shutdown();
|
||||
|
||||
}
|
||||
|
||||
// ------------------ Groups ------------------
|
||||
|
||||
@Override
|
||||
public synchronized Group addGroup(Group group) throws AuthorizationAccessException {
|
||||
if (group == null) {
|
||||
throw new IllegalArgumentException("Group cannot be null");
|
||||
}
|
||||
|
||||
// create a new JAXB Group based on the incoming Group
|
||||
final org.apache.nifi.authorization.file.generated.Group jaxbGroup = new org.apache.nifi.authorization.file.generated.Group();
|
||||
jaxbGroup.setIdentifier(group.getIdentifier());
|
||||
jaxbGroup.setName(group.getName());
|
||||
|
||||
final Authorizations authorizations = this.authorizationsHolder.get().getAuthorizations();
|
||||
authorizations.getGroups().getGroup().add(jaxbGroup);
|
||||
saveAndRefreshHolder(authorizations);
|
||||
|
||||
final AuthorizationsHolder holder = this.authorizationsHolder.get();
|
||||
return holder.getGroupsById().get(group.getIdentifier());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Group getGroup(String identifier) throws AuthorizationAccessException {
|
||||
if (identifier == null) {
|
||||
return null;
|
||||
}
|
||||
return authorizationsHolder.get().getGroupsById().get(identifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Group updateGroup(Group group) throws AuthorizationAccessException {
|
||||
if (group == null) {
|
||||
throw new IllegalArgumentException("Group cannot be null");
|
||||
}
|
||||
|
||||
final Authorizations authorizations = this.authorizationsHolder.get().getAuthorizations();
|
||||
final List<org.apache.nifi.authorization.file.generated.Group> groups = authorizations.getGroups().getGroup();
|
||||
|
||||
// find the group that needs to be update
|
||||
org.apache.nifi.authorization.file.generated.Group updateGroup = null;
|
||||
for (org.apache.nifi.authorization.file.generated.Group jaxbGroup : groups) {
|
||||
if (jaxbGroup.getIdentifier().equals(group.getIdentifier())) {
|
||||
updateGroup = jaxbGroup;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if the group wasn't found return null, otherwise update the group and save changes
|
||||
if (updateGroup == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
updateGroup.setName(group.getName());
|
||||
saveAndRefreshHolder(authorizations);
|
||||
|
||||
final AuthorizationsHolder holder = this.authorizationsHolder.get();
|
||||
return holder.getGroupsById().get(group.getIdentifier());
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Group deleteGroup(Group group) throws AuthorizationAccessException {
|
||||
final Authorizations authorizations = this.authorizationsHolder.get().getAuthorizations();
|
||||
final List<org.apache.nifi.authorization.file.generated.Group> groups = authorizations.getGroups().getGroup();
|
||||
|
||||
// for each user iterate over the group references and remove the group reference if it matches the group being deleted
|
||||
for (org.apache.nifi.authorization.file.generated.User user : authorizations.getUsers().getUser()) {
|
||||
Iterator<org.apache.nifi.authorization.file.generated.User.Group> userGroupIter = user.getGroup().iterator();
|
||||
while (userGroupIter.hasNext()) {
|
||||
org.apache.nifi.authorization.file.generated.User.Group userGroup = userGroupIter.next();
|
||||
if (userGroup.getIdentifier().equals(group.getIdentifier())) {
|
||||
userGroupIter.remove();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// for each policy iterate over the group reference and remove the group reference if it matches the group being deleted
|
||||
for (Policy policy : authorizations.getPolicies().getPolicy()) {
|
||||
Iterator<Policy.Group> policyGroupIter = policy.getGroup().iterator();
|
||||
while (policyGroupIter.hasNext()) {
|
||||
Policy.Group policyGroup = policyGroupIter.next();
|
||||
if (policyGroup.getIdentifier().equals(group.getIdentifier())) {
|
||||
policyGroupIter.remove();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now remove the actual group from the top-level list of groups
|
||||
boolean removedGroup = false;
|
||||
Iterator<org.apache.nifi.authorization.file.generated.Group> iter = groups.iterator();
|
||||
while (iter.hasNext()) {
|
||||
org.apache.nifi.authorization.file.generated.Group jaxbGroup = iter.next();
|
||||
if (group.getIdentifier().equals(jaxbGroup.getIdentifier())) {
|
||||
iter.remove();
|
||||
removedGroup = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (removedGroup) {
|
||||
saveAndRefreshHolder(authorizations);
|
||||
return group;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Group> getGroups() throws AuthorizationAccessException {
|
||||
return authorizationsHolder.get().getAllGroups();
|
||||
}
|
||||
|
||||
// ------------------ Users ------------------
|
||||
|
||||
@Override
|
||||
public synchronized User addUser(final User user) throws AuthorizationAccessException {
|
||||
if (user == null) {
|
||||
throw new IllegalArgumentException("User cannot be null");
|
||||
}
|
||||
|
||||
final org.apache.nifi.authorization.file.generated.User jaxbUser = createJAXBUser(user);
|
||||
|
||||
final Authorizations authorizations = this.authorizationsHolder.get().getAuthorizations();
|
||||
authorizations.getUsers().getUser().add(jaxbUser);
|
||||
|
||||
saveAndRefreshHolder(authorizations);
|
||||
|
||||
final AuthorizationsHolder holder = authorizationsHolder.get();
|
||||
return holder.getUsersById().get(user.getIdentifier());
|
||||
}
|
||||
|
||||
private org.apache.nifi.authorization.file.generated.User createJAXBUser(User user) {
|
||||
final org.apache.nifi.authorization.file.generated.User jaxbUser = new org.apache.nifi.authorization.file.generated.User();
|
||||
jaxbUser.setIdentifier(user.getIdentifier());
|
||||
jaxbUser.setIdentity(user.getIdentity());
|
||||
|
||||
for (String groupIdentifier : user.getGroups()) {
|
||||
org.apache.nifi.authorization.file.generated.User.Group group = new org.apache.nifi.authorization.file.generated.User.Group();
|
||||
group.setIdentifier(groupIdentifier);
|
||||
jaxbUser.getGroup().add(group);
|
||||
}
|
||||
return jaxbUser;
|
||||
}
|
||||
|
||||
@Override
|
||||
public User getUser(final String identifier) throws AuthorizationAccessException {
|
||||
if (identifier == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final AuthorizationsHolder holder = authorizationsHolder.get();
|
||||
return holder.getUsersById().get(identifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public User getUserByIdentity(final String identity) throws AuthorizationAccessException {
|
||||
if (identity == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final AuthorizationsHolder holder = authorizationsHolder.get();
|
||||
return holder.getUsersByIdentity().get(identity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized User updateUser(final User user) throws AuthorizationAccessException {
|
||||
if (user == null) {
|
||||
throw new IllegalArgumentException("User cannot be null");
|
||||
}
|
||||
|
||||
final Authorizations authorizations = this.authorizationsHolder.get().getAuthorizations();
|
||||
final List<org.apache.nifi.authorization.file.generated.User> users = authorizations.getUsers().getUser();
|
||||
|
||||
// fine the User that needs to be updated
|
||||
org.apache.nifi.authorization.file.generated.User updateUser = null;
|
||||
for (org.apache.nifi.authorization.file.generated.User jaxbUser : users) {
|
||||
if (user.getIdentifier().equals(jaxbUser.getIdentifier())) {
|
||||
updateUser = jaxbUser;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if user wasn't found return null, otherwise update the user and save changes
|
||||
if (updateUser == null) {
|
||||
return null;
|
||||
} else {
|
||||
updateUser.setIdentity(user.getIdentity());
|
||||
|
||||
updateUser.getGroup().clear();
|
||||
for (String groupIdentifier : user.getGroups()) {
|
||||
org.apache.nifi.authorization.file.generated.User.Group group = new org.apache.nifi.authorization.file.generated.User.Group();
|
||||
group.setIdentifier(groupIdentifier);
|
||||
updateUser.getGroup().add(group);
|
||||
}
|
||||
|
||||
saveAndRefreshHolder(authorizations);
|
||||
|
||||
final AuthorizationsHolder holder = authorizationsHolder.get();
|
||||
return holder.getUsersById().get(user.getIdentifier());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized User deleteUser(final User user) throws AuthorizationAccessException {
|
||||
if (user == null) {
|
||||
throw new IllegalArgumentException("User cannot be null");
|
||||
}
|
||||
|
||||
final Authorizations authorizations = this.authorizationsHolder.get().getAuthorizations();
|
||||
final List<org.apache.nifi.authorization.file.generated.User> users = authorizations.getUsers().getUser();
|
||||
|
||||
// remove any references to the user being deleted from policies
|
||||
for (Policy policy : authorizations.getPolicies().getPolicy()) {
|
||||
Iterator<Policy.User> policyUserIter = policy.getUser().iterator();
|
||||
while (policyUserIter.hasNext()) {
|
||||
Policy.User policyUser = policyUserIter.next();
|
||||
if (policyUser.getIdentifier().equals(user.getIdentifier())) {
|
||||
policyUserIter.remove();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// remove the actual user if it exists
|
||||
boolean removedUser = false;
|
||||
Iterator<org.apache.nifi.authorization.file.generated.User> iter = users.iterator();
|
||||
while (iter.hasNext()) {
|
||||
org.apache.nifi.authorization.file.generated.User jaxbUser = iter.next();
|
||||
if (user.getIdentifier().equals(jaxbUser.getIdentifier())) {
|
||||
iter.remove();
|
||||
removedUser = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (removedUser) {
|
||||
saveAndRefreshHolder(authorizations);
|
||||
return user;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<User> getUsers() throws AuthorizationAccessException {
|
||||
return authorizationsHolder.get().getAllUsers();
|
||||
}
|
||||
|
||||
// ------------------ AccessPolicies ------------------
|
||||
|
||||
@Override
|
||||
public synchronized AccessPolicy addAccessPolicy(final AccessPolicy accessPolicy) throws AuthorizationAccessException {
|
||||
if (accessPolicy == null) {
|
||||
throw new IllegalArgumentException("AccessPolicy cannot be null");
|
||||
}
|
||||
|
||||
// create the new JAXB Policy
|
||||
final Policy policy = createJAXBPolicy(accessPolicy);
|
||||
|
||||
// add the new Policy to the top-level list of policies
|
||||
final Authorizations authorizations = this.authorizationsHolder.get().getAuthorizations();
|
||||
authorizations.getPolicies().getPolicy().add(policy);
|
||||
|
||||
saveAndRefreshHolder(authorizations);
|
||||
|
||||
final AuthorizationsHolder holder = authorizationsHolder.get();
|
||||
return holder.getPoliciesById().get(accessPolicy.getIdentifier());
|
||||
}
|
||||
|
||||
private Policy createJAXBPolicy(final AccessPolicy accessPolicy) {
|
||||
final Policy policy = new Policy();
|
||||
policy.setIdentifier(accessPolicy.getIdentifier());
|
||||
transferState(accessPolicy, policy);
|
||||
return policy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessPolicy getAccessPolicy(final String identifier) throws AuthorizationAccessException {
|
||||
if (identifier == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final AuthorizationsHolder holder = authorizationsHolder.get();
|
||||
return holder.getPoliciesById().get(identifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized AccessPolicy updateAccessPolicy(final AccessPolicy accessPolicy) throws AuthorizationAccessException {
|
||||
if (accessPolicy == null) {
|
||||
throw new IllegalArgumentException("AccessPolicy cannot be null");
|
||||
}
|
||||
|
||||
final Authorizations authorizations = this.authorizationsHolder.get().getAuthorizations();
|
||||
|
||||
// try to find an existing Authorization that matches the policy id
|
||||
Policy updatePolicy = null;
|
||||
for (Policy policy : authorizations.getPolicies().getPolicy()) {
|
||||
if (policy.getIdentifier().equals(accessPolicy.getIdentifier())) {
|
||||
updatePolicy = policy;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// no matching Policy so return null
|
||||
if (updatePolicy == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// update the Policy, save, reload, and return
|
||||
transferState(accessPolicy, updatePolicy);
|
||||
saveAndRefreshHolder(authorizations);
|
||||
|
||||
final AuthorizationsHolder holder = authorizationsHolder.get();
|
||||
return holder.getPoliciesById().get(accessPolicy.getIdentifier());
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized AccessPolicy deleteAccessPolicy(final AccessPolicy accessPolicy) throws AuthorizationAccessException {
|
||||
if (accessPolicy == null) {
|
||||
throw new IllegalArgumentException("AccessPolicy cannot be null");
|
||||
}
|
||||
|
||||
final Authorizations authorizations = this.authorizationsHolder.get().getAuthorizations();
|
||||
|
||||
// find the matching Policy and remove it
|
||||
boolean deletedPolicy = false;
|
||||
Iterator<Policy> policyIter = authorizations.getPolicies().getPolicy().iterator();
|
||||
while (policyIter.hasNext()) {
|
||||
final Policy policy = policyIter.next();
|
||||
if (policy.getIdentifier().equals(accessPolicy.getIdentifier())) {
|
||||
policyIter.remove();
|
||||
deletedPolicy = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// never found a matching Policy so return null
|
||||
if (!deletedPolicy) {
|
||||
return null;
|
||||
}
|
||||
|
||||
saveAndRefreshHolder(authorizations);
|
||||
return accessPolicy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<AccessPolicy> getAccessPolicies() throws AuthorizationAccessException {
|
||||
return authorizationsHolder.get().getAllPolicies();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UsersAndAccessPolicies getUsersAndAccessPolicies() throws AuthorizationAccessException {
|
||||
return authorizationsHolder.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the given Policy to the state of the provided AccessPolicy. Users and Groups will be cleared and
|
||||
* set to match the AccessPolicy, the resource and action will be set to match the AccessPolicy.
|
||||
*
|
||||
* Does not set the identifier.
|
||||
*
|
||||
* @param accessPolicy the AccessPolicy to transfer state from
|
||||
* @param policy the Policy to transfer state to
|
||||
*/
|
||||
private void transferState(AccessPolicy accessPolicy, Policy policy) {
|
||||
policy.setResource(accessPolicy.getResource());
|
||||
|
||||
// add users to the policy
|
||||
policy.getUser().clear();
|
||||
for (String userIdentifier : accessPolicy.getUsers()) {
|
||||
Policy.User policyUser = new Policy.User();
|
||||
policyUser.setIdentifier(userIdentifier);
|
||||
policy.getUser().add(policyUser);
|
||||
}
|
||||
|
||||
// add groups to the policy
|
||||
policy.getGroup().clear();
|
||||
for (String groupIdentifier : accessPolicy.getGroups()) {
|
||||
Policy.Group policyGroup = new Policy.Group();
|
||||
policyGroup.setIdentifier(groupIdentifier);
|
||||
policy.getGroup().add(policyGroup);
|
||||
}
|
||||
|
||||
// add the action to the policy
|
||||
boolean containsRead = accessPolicy.getActions().contains(RequestAction.READ);
|
||||
boolean containsWrite = accessPolicy.getActions().contains(RequestAction.WRITE);
|
||||
|
||||
if (containsRead && containsWrite) {
|
||||
policy.setAction(READ_CODE + WRITE_CODE);
|
||||
} else if (containsRead) {
|
||||
policy.setAction(READ_CODE);
|
||||
} else {
|
||||
policy.setAction(WRITE_CODE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -14,8 +14,58 @@
|
|||
limitations under the License.
|
||||
-->
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<!-- authorization -->
|
||||
<xs:complexType name="Authorization">
|
||||
|
||||
<!-- group -->
|
||||
<xs:complexType name="Group">
|
||||
<xs:attribute name="identifier">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:minLength value="1"/>
|
||||
<xs:pattern value=".*[^\s].*"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="name">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:minLength value="1"/>
|
||||
<xs:pattern value=".*[^\s].*"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<!-- groups -->
|
||||
<xs:complexType name="Groups">
|
||||
<xs:sequence>
|
||||
<xs:element name="group" type="Group" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<!-- user -->
|
||||
<xs:complexType name="User">
|
||||
<xs:sequence>
|
||||
<xs:element name="group" minOccurs="0" maxOccurs="unbounded" >
|
||||
<xs:complexType>
|
||||
<xs:attribute name="identifier">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:minLength value="1"/>
|
||||
<xs:pattern value=".*[^\s].*"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="identifier">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:minLength value="1"/>
|
||||
<xs:pattern value=".*[^\s].*"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="identity">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:string">
|
||||
|
@ -24,6 +74,59 @@
|
|||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<!-- users -->
|
||||
<xs:complexType name="Users">
|
||||
<xs:sequence>
|
||||
<xs:element name="user" type="User" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<!-- authorization -->
|
||||
<xs:complexType name="Policy">
|
||||
<xs:sequence>
|
||||
<xs:element name="group" minOccurs="0" maxOccurs="unbounded" >
|
||||
<xs:complexType>
|
||||
<xs:attribute name="identifier">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:minLength value="1"/>
|
||||
<xs:pattern value=".*[^\s].*"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="user" minOccurs="0" maxOccurs="unbounded" >
|
||||
<xs:complexType>
|
||||
<xs:attribute name="identifier">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:minLength value="1"/>
|
||||
<xs:pattern value=".*[^\s].*"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="identifier">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:minLength value="1"/>
|
||||
<xs:pattern value=".*[^\s].*"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="resource">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:minLength value="1"/>
|
||||
<xs:pattern value=".*[^\s].*"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="action">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:string">
|
||||
|
@ -34,27 +137,22 @@
|
|||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<!-- resource -->
|
||||
<xs:complexType name="Resource">
|
||||
<!-- resources -->
|
||||
<xs:complexType name="Policies">
|
||||
<xs:sequence>
|
||||
<xs:element name="authorization" type="Authorization" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xs:element name="policy" type="Policy" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="identifier">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:minLength value="1"/>
|
||||
<xs:pattern value=".*[^\s].*"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<!-- resources -->
|
||||
<xs:element name="resources">
|
||||
<!-- top-level authorizations element -->
|
||||
<xs:element name="authorizations">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="resource" type="Resource" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xs:element name="groups" type="Groups" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="users" type="Users" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="policies" type="Policies" minOccurs="0" maxOccurs="1" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
</xs:schema>
|
|
@ -0,0 +1,64 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<!-- role -->
|
||||
<xs:complexType name="Role">
|
||||
<xs:attribute name="name">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="ROLE_MONITOR"/>
|
||||
<xs:enumeration value="ROLE_PROVENANCE"/>
|
||||
<xs:enumeration value="ROLE_DFM"/>
|
||||
<xs:enumeration value="ROLE_ADMIN"/>
|
||||
<xs:enumeration value="ROLE_PROXY"/>
|
||||
<xs:enumeration value="ROLE_NIFI"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<!-- user -->
|
||||
<xs:complexType name="User">
|
||||
<xs:sequence>
|
||||
<xs:element name="role" type="Role" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="dn">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:minLength value="1"/>
|
||||
<xs:pattern value=".*[^\s].*"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="group">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:minLength value="1"/>
|
||||
<xs:pattern value=".*[^\s].*"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<!-- users -->
|
||||
<xs:element name="users">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="user" type="User" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:schema>
|
|
@ -31,9 +31,12 @@ import java.io.File;
|
|||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
@ -42,25 +45,57 @@ public class FileAuthorizerTest {
|
|||
|
||||
private static final String EMPTY_AUTHORIZATIONS_CONCISE =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
|
||||
+ "<resources/>";
|
||||
+ "<authorizations/>";
|
||||
|
||||
private static final String EMPTY_AUTHORIZATIONS =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
|
||||
+ "<resources>"
|
||||
+ "</resources>";
|
||||
+ "<authorizations>"
|
||||
+ "</authorizations>";
|
||||
|
||||
private static final String BAD_SCHEMA_AUTHORIZATIONS =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
|
||||
+ "<resource>"
|
||||
+ "</resource>";
|
||||
+ "<authorization>"
|
||||
+ "</authorization>";
|
||||
|
||||
private static final String SIMPLE_AUTHORIZATION_BY_USER =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" +
|
||||
"<authorizations>" +
|
||||
" <users>" +
|
||||
" <user identifier=\"user-1\" identity=\"user-1\"/>" +
|
||||
" <user identifier=\"user-2\" identity=\"user-2\"/>" +
|
||||
" </users>" +
|
||||
" <policies>" +
|
||||
" <policy identifier=\"policy-1\" resource=\"/flow\" action=\"R\">" +
|
||||
" <user identifier=\"user-1\" />" +
|
||||
" </policy>" +
|
||||
" </policies>" +
|
||||
"</authorizations>";
|
||||
|
||||
private static final String AUTHORIZATIONS =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
|
||||
+ "<resources>"
|
||||
+ "<resource identifier=\"/flow\">"
|
||||
+ "<authorization identity=\"user-1\" action=\"R\"/>"
|
||||
+ "</resource>"
|
||||
+ "</resources>";
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" +
|
||||
"<authorizations>" +
|
||||
" <groups>" +
|
||||
" <group identifier=\"group-1\" name=\"group-1\" />" +
|
||||
" <group identifier=\"group-2\" name=\"group-2\" />" +
|
||||
" </groups>" +
|
||||
" <users>" +
|
||||
" <user identifier=\"user-1\" identity=\"user-1\">" +
|
||||
" <group identifier=\"group-1\" />" +
|
||||
" <group identifier=\"group-2\" />" +
|
||||
" </user>\n" +
|
||||
" <user identifier=\"user-2\" identity=\"user-2\" />" +
|
||||
" </users>" +
|
||||
" <policies>" +
|
||||
" <policy identifier=\"policy-1\" resource=\"/flow\" action=\"RW\">" +
|
||||
" <group identifier=\"group-1\" />" +
|
||||
" <group identifier=\"group-2\" />" +
|
||||
" <user identifier=\"user-1\" />" +
|
||||
" </policy>" +
|
||||
" <policy identifier=\"policy-2\" resource=\"/flow\" action=\"RW\">" +
|
||||
" <user identifier=\"user-2\" />" +
|
||||
" </policy>" +
|
||||
" </policies>" +
|
||||
"</authorizations>";
|
||||
|
||||
private static final String UPDATED_AUTHORIZATIONS =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
|
||||
|
@ -104,7 +139,39 @@ public class FileAuthorizerTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testPostConstructionWhenRestoreDoesNotExist() throws Exception {
|
||||
public void testOnConfiguredWhenInitialAdminProvided() throws Exception {
|
||||
final String adminIdentity = "admin-user";
|
||||
|
||||
when(configurationContext.getProperty(Mockito.eq("Initial Admin Identity")))
|
||||
.thenReturn(new StandardPropertyValue(adminIdentity, null));
|
||||
|
||||
writeAuthorizationsFile(primary, EMPTY_AUTHORIZATIONS_CONCISE);
|
||||
authorizer.onConfigured(configurationContext);
|
||||
|
||||
final Set<User> users = authorizer.getUsers();
|
||||
assertEquals(1, users.size());
|
||||
|
||||
final User adminUser = users.iterator().next();
|
||||
assertEquals(adminIdentity, adminUser.getIdentity());
|
||||
|
||||
final Set<AccessPolicy> policies = authorizer.getAccessPolicies();
|
||||
assertEquals(4, policies.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnConfiguredWhenInitialAdminNotProvided() throws Exception {
|
||||
writeAuthorizationsFile(primary, EMPTY_AUTHORIZATIONS_CONCISE);
|
||||
authorizer.onConfigured(configurationContext);
|
||||
|
||||
final Set<User> users = authorizer.getUsers();
|
||||
assertEquals(0, users.size());
|
||||
|
||||
final Set<AccessPolicy> policies = authorizer.getAccessPolicies();
|
||||
assertEquals(0, policies.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnConfiguredWhenRestoreDoesNotExist() throws Exception {
|
||||
writeAuthorizationsFile(primary, EMPTY_AUTHORIZATIONS_CONCISE);
|
||||
authorizer.onConfigured(configurationContext);
|
||||
|
||||
|
@ -112,78 +179,622 @@ public class FileAuthorizerTest {
|
|||
}
|
||||
|
||||
@Test(expected = AuthorizerCreationException.class)
|
||||
public void testPostConstructionWhenPrimaryDoesNotExist() throws Exception {
|
||||
public void testOnConfiguredWhenPrimaryDoesNotExist() throws Exception {
|
||||
writeAuthorizationsFile(restore, EMPTY_AUTHORIZATIONS_CONCISE);
|
||||
authorizer.onConfigured(configurationContext);
|
||||
}
|
||||
|
||||
@Test(expected = AuthorizerCreationException.class)
|
||||
public void testPostConstructionWhenPrimaryDifferentThanRestore() throws Exception {
|
||||
public void testOnConfiguredWhenPrimaryDifferentThanRestore() throws Exception {
|
||||
writeAuthorizationsFile(primary, EMPTY_AUTHORIZATIONS);
|
||||
writeAuthorizationsFile(restore, EMPTY_AUTHORIZATIONS_CONCISE);
|
||||
authorizer.onConfigured(configurationContext);
|
||||
}
|
||||
|
||||
@Test(expected = AuthorizerCreationException.class)
|
||||
public void testBadSchema() throws Exception {
|
||||
public void testOnConfiguredWithBadSchema() throws Exception {
|
||||
writeAuthorizationsFile(primary, BAD_SCHEMA_AUTHORIZATIONS);
|
||||
authorizer.onConfigured(configurationContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAuthorizedUserAction() throws Exception {
|
||||
writeAuthorizationsFile(primary, AUTHORIZATIONS);
|
||||
writeAuthorizationsFile(primary, SIMPLE_AUTHORIZATION_BY_USER);
|
||||
authorizer.onConfigured(configurationContext);
|
||||
|
||||
final AuthorizationRequest request = new AuthorizationRequest.Builder().resource(ResourceFactory.getFlowResource()).identity("user-1").anonymous(false).accessAttempt(true).action(RequestAction
|
||||
.READ).build();
|
||||
final AuthorizationRequest request = new AuthorizationRequest.Builder()
|
||||
.resource(ResourceFactory.getFlowResource())
|
||||
.identity("user-1")
|
||||
.anonymous(false)
|
||||
.accessAttempt(true)
|
||||
.action(RequestAction.READ)
|
||||
.build();
|
||||
|
||||
final AuthorizationResult result = authorizer.authorize(request);
|
||||
assertTrue(Result.Approved.equals(result.getResult()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnauthorizedUser() throws Exception {
|
||||
writeAuthorizationsFile(primary, AUTHORIZATIONS);
|
||||
writeAuthorizationsFile(primary, SIMPLE_AUTHORIZATION_BY_USER);
|
||||
authorizer.onConfigured(configurationContext);
|
||||
|
||||
final AuthorizationRequest request =
|
||||
new AuthorizationRequest.Builder().resource(ResourceFactory.getFlowResource()).identity("user-2").anonymous(false).accessAttempt(true).action(RequestAction.READ).build();
|
||||
final AuthorizationRequest request = new AuthorizationRequest.Builder()
|
||||
.resource(ResourceFactory.getFlowResource())
|
||||
.identity("user-2")
|
||||
.anonymous(false)
|
||||
.accessAttempt(true)
|
||||
.action(RequestAction.READ)
|
||||
.build();
|
||||
|
||||
final AuthorizationResult result = authorizer.authorize(request);
|
||||
assertFalse(Result.Approved.equals(result.getResult()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnauthorizedAction() throws Exception {
|
||||
writeAuthorizationsFile(primary, AUTHORIZATIONS);
|
||||
writeAuthorizationsFile(primary, SIMPLE_AUTHORIZATION_BY_USER);
|
||||
authorizer.onConfigured(configurationContext);
|
||||
|
||||
final AuthorizationRequest request =
|
||||
new AuthorizationRequest.Builder().resource(ResourceFactory.getFlowResource()).identity("user-1").anonymous(false).accessAttempt(true).action(RequestAction.WRITE).build();
|
||||
final AuthorizationRequest request = new AuthorizationRequest.Builder()
|
||||
.resource(ResourceFactory.getFlowResource())
|
||||
.identity("user-1")
|
||||
.anonymous(false)
|
||||
.accessAttempt(true)
|
||||
.action(RequestAction.WRITE)
|
||||
.build();
|
||||
|
||||
final AuthorizationResult result = authorizer.authorize(request);
|
||||
assertFalse(Result.Approved.equals(result.getResult()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReloadAuthorizations() throws Exception {
|
||||
public void testGetAllUsersGroupsPolicies() throws Exception {
|
||||
writeAuthorizationsFile(primary, AUTHORIZATIONS);
|
||||
when(configurationContext.getProperty(Mockito.eq("Reload Interval"))).thenReturn(new StandardPropertyValue("1 sec", null));
|
||||
authorizer.onConfigured(configurationContext);
|
||||
|
||||
// ensure the user currently does not have write access
|
||||
final AuthorizationRequest request =
|
||||
new AuthorizationRequest.Builder().resource(ResourceFactory.getFlowResource()).identity("user-1").anonymous(false).accessAttempt(true).action(RequestAction.WRITE).build();
|
||||
AuthorizationResult result = authorizer.authorize(request);
|
||||
assertFalse(Result.Approved.equals(result.getResult()));
|
||||
final Set<Group> groups = authorizer.getGroups();
|
||||
assertEquals(2, groups.size());
|
||||
|
||||
// add write access for the user
|
||||
writeAuthorizationsFile(primary, UPDATED_AUTHORIZATIONS);
|
||||
boolean foundGroup1 = false;
|
||||
boolean foundGroup2 = false;
|
||||
|
||||
// wait at least one second for the file to be stale
|
||||
Thread.sleep(4000L);
|
||||
for (Group group : groups) {
|
||||
if (group.getIdentifier().equals("group-1") && group.getName().equals("group-1")
|
||||
&& group.getUsers().size() == 1 && group.getUsers().contains("user-1")) {
|
||||
foundGroup1 = true;
|
||||
} else if (group.getIdentifier().equals("group-2") && group.getName().equals("group-2")
|
||||
&& group.getUsers().size() == 1 && group.getUsers().contains("user-1")) {
|
||||
foundGroup2 = true;
|
||||
}
|
||||
}
|
||||
|
||||
// ensure the user does have write access now using the same request
|
||||
result = authorizer.authorize(request);
|
||||
assertTrue(Result.Approved.equals(result.getResult()));
|
||||
assertTrue(foundGroup1);
|
||||
assertTrue(foundGroup2);
|
||||
|
||||
final Set<User> users = authorizer.getUsers();
|
||||
assertEquals(2, users.size());
|
||||
|
||||
boolean foundUser1 = false;
|
||||
boolean foundUser2 = false;
|
||||
|
||||
for (User user : users) {
|
||||
if (user.getIdentifier().equals("user-1") && user.getIdentity().equals("user-1")
|
||||
&& user.getGroups().size() == 2 && user.getGroups().contains("group-1")
|
||||
&& user.getGroups().contains("group-2")) {
|
||||
foundUser1 = true;
|
||||
} else if (user.getIdentifier().equals("user-2") && user.getIdentity().equals("user-2")
|
||||
&& user.getGroups().size() == 0) {
|
||||
foundUser2 = true;
|
||||
}
|
||||
}
|
||||
|
||||
assertTrue(foundUser1);
|
||||
assertTrue(foundUser2);
|
||||
|
||||
final Set<AccessPolicy> policies = authorizer.getAccessPolicies();
|
||||
assertEquals(2, policies.size());
|
||||
|
||||
boolean foundPolicy1 = false;
|
||||
boolean foundPolicy2 = false;
|
||||
|
||||
for (AccessPolicy policy : policies) {
|
||||
if (policy.getIdentifier().equals("policy-1")
|
||||
&& policy.getResource().equals("/flow")
|
||||
&& policy.getActions().size() == 2
|
||||
&& policy.getActions().contains(RequestAction.READ)
|
||||
&& policy.getActions().contains(RequestAction.WRITE)
|
||||
&& policy.getGroups().size() == 2
|
||||
&& policy.getGroups().contains("group-1")
|
||||
&& policy.getGroups().contains("group-2")
|
||||
&& policy.getUsers().size() == 1
|
||||
&& policy.getUsers().contains("user-1")) {
|
||||
foundPolicy1 = true;
|
||||
} else if (policy.getIdentifier().equals("policy-2")
|
||||
&& policy.getResource().equals("/flow")
|
||||
&& policy.getActions().size() == 2
|
||||
&& policy.getActions().contains(RequestAction.READ)
|
||||
&& policy.getActions().contains(RequestAction.WRITE)
|
||||
&& policy.getGroups().size() == 0
|
||||
&& policy.getUsers().size() == 1
|
||||
&& policy.getUsers().contains("user-2")) {
|
||||
foundPolicy2 = true;
|
||||
}
|
||||
}
|
||||
|
||||
assertTrue(foundPolicy1);
|
||||
assertTrue(foundPolicy2);
|
||||
}
|
||||
|
||||
// --------------- User Tests ------------------------
|
||||
|
||||
@Test
|
||||
public void testAddUser() throws Exception {
|
||||
writeAuthorizationsFile(primary, EMPTY_AUTHORIZATIONS);
|
||||
authorizer.onConfigured(configurationContext);
|
||||
assertEquals(0, authorizer.getUsers().size());
|
||||
|
||||
final User user = new User.Builder()
|
||||
.identifier("user-1")
|
||||
.identity("user-identity-1")
|
||||
.addGroup("group1")
|
||||
.addGroup("group2")
|
||||
.build();
|
||||
|
||||
final User addedUser = authorizer.addUser(user);
|
||||
assertNotNull(addedUser);
|
||||
assertEquals(user.getIdentifier(), addedUser.getIdentifier());
|
||||
assertEquals(user.getIdentity(), addedUser.getIdentity());
|
||||
assertEquals(2, addedUser.getGroups().size());
|
||||
assertTrue(addedUser.getGroups().contains("group1"));
|
||||
assertTrue(addedUser.getGroups().contains("group2"));
|
||||
|
||||
final Set<User> users = authorizer.getUsers();
|
||||
assertEquals(1, users.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetUserByIdentifierWhenFound() throws Exception {
|
||||
writeAuthorizationsFile(primary, AUTHORIZATIONS);
|
||||
authorizer.onConfigured(configurationContext);
|
||||
assertEquals(2, authorizer.getUsers().size());
|
||||
|
||||
final String identifier = "user-1";
|
||||
final User user = authorizer.getUser(identifier);
|
||||
assertNotNull(user);
|
||||
assertEquals(identifier, user.getIdentifier());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetUserByIdentifierWhenNotFound() throws Exception {
|
||||
writeAuthorizationsFile(primary, AUTHORIZATIONS);
|
||||
authorizer.onConfigured(configurationContext);
|
||||
assertEquals(2, authorizer.getUsers().size());
|
||||
|
||||
final String identifier = "user-X";
|
||||
final User user = authorizer.getUser(identifier);
|
||||
assertNull(user);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetUserByIdentityWhenFound() throws Exception {
|
||||
writeAuthorizationsFile(primary, AUTHORIZATIONS);
|
||||
authorizer.onConfigured(configurationContext);
|
||||
assertEquals(2, authorizer.getUsers().size());
|
||||
|
||||
final String identity = "user-1";
|
||||
final User user = authorizer.getUserByIdentity(identity);
|
||||
assertNotNull(user);
|
||||
assertEquals(identity, user.getIdentifier());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetUserByIdentityWhenNotFound() throws Exception {
|
||||
writeAuthorizationsFile(primary, AUTHORIZATIONS);
|
||||
authorizer.onConfigured(configurationContext);
|
||||
assertEquals(2, authorizer.getUsers().size());
|
||||
|
||||
final String identity = "user-X";
|
||||
final User user = authorizer.getUserByIdentity(identity);
|
||||
assertNull(user);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteUser() throws Exception {
|
||||
writeAuthorizationsFile(primary, AUTHORIZATIONS);
|
||||
authorizer.onConfigured(configurationContext);
|
||||
assertEquals(2, authorizer.getUsers().size());
|
||||
|
||||
// retrieve user-1 and verify it exsits
|
||||
final User user = authorizer.getUser("user-1");
|
||||
assertEquals("user-1", user.getIdentifier());
|
||||
|
||||
final AccessPolicy policy1 = authorizer.getAccessPolicy("policy-1");
|
||||
assertTrue(policy1.getUsers().contains("user-1"));
|
||||
|
||||
// delete user-1
|
||||
final User deletedUser = authorizer.deleteUser(user);
|
||||
assertNotNull(deletedUser);
|
||||
assertEquals("user-1", deletedUser.getIdentifier());
|
||||
|
||||
// should be one less user
|
||||
assertEquals(1, authorizer.getUsers().size());
|
||||
assertNull(authorizer.getUser(user.getIdentifier()));
|
||||
|
||||
// verify policy-1 no longer has a reference to user-1
|
||||
final AccessPolicy updatedPolicy1 = authorizer.getAccessPolicy("policy-1");
|
||||
assertFalse(updatedPolicy1.getUsers().contains("user-1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteUserWhenNotFound() throws Exception {
|
||||
writeAuthorizationsFile(primary, AUTHORIZATIONS);
|
||||
authorizer.onConfigured(configurationContext);
|
||||
assertEquals(2, authorizer.getUsers().size());
|
||||
|
||||
//user that doesn't exist
|
||||
final User user = new User.Builder().identifier("user-X").identity("user-identity-X").build();
|
||||
|
||||
// should return null and still have 2 users because nothing was deleted
|
||||
final User deletedUser = authorizer.deleteUser(user);
|
||||
assertNull(deletedUser);
|
||||
assertEquals(2, authorizer.getUsers().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateUserWhenFound() throws Exception {
|
||||
writeAuthorizationsFile(primary, AUTHORIZATIONS);
|
||||
authorizer.onConfigured(configurationContext);
|
||||
assertEquals(2, authorizer.getUsers().size());
|
||||
|
||||
final User user = new User.Builder()
|
||||
.identifier("user-1")
|
||||
.identity("new-identity")
|
||||
.addGroup("new-group")
|
||||
.build();
|
||||
|
||||
final User updatedUser = authorizer.updateUser(user);
|
||||
assertNotNull(updatedUser);
|
||||
assertEquals(user.getIdentifier(), updatedUser.getIdentifier());
|
||||
assertEquals(user.getIdentity(), updatedUser.getIdentity());
|
||||
assertEquals(1, updatedUser.getGroups().size());
|
||||
assertTrue(updatedUser.getGroups().contains("new-group"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateUserWhenNotFound() throws Exception {
|
||||
writeAuthorizationsFile(primary, AUTHORIZATIONS);
|
||||
authorizer.onConfigured(configurationContext);
|
||||
assertEquals(2, authorizer.getUsers().size());
|
||||
|
||||
final User user = new User.Builder()
|
||||
.identifier("user-X")
|
||||
.identity("new-identity")
|
||||
.addGroup("new-group")
|
||||
.build();
|
||||
|
||||
final User updatedUser = authorizer.updateUser(user);
|
||||
assertNull(updatedUser);
|
||||
}
|
||||
|
||||
// --------------- Group Tests ------------------------
|
||||
|
||||
@Test
|
||||
public void testAddGroup() throws Exception {
|
||||
writeAuthorizationsFile(primary, EMPTY_AUTHORIZATIONS);
|
||||
authorizer.onConfigured(configurationContext);
|
||||
assertEquals(0, authorizer.getGroups().size());
|
||||
|
||||
final Group group = new Group.Builder()
|
||||
.identifier("group-id-1")
|
||||
.name("group-name-1")
|
||||
.addUser("user1") // should be ignored
|
||||
.build();
|
||||
|
||||
final Group addedGroup = authorizer.addGroup(group);
|
||||
assertNotNull(addedGroup);
|
||||
assertEquals(group.getIdentifier(), addedGroup.getIdentifier());
|
||||
assertEquals(group.getName(), addedGroup.getName());
|
||||
assertEquals(0, addedGroup.getUsers().size());
|
||||
|
||||
final Set<Group> groups = authorizer.getGroups();
|
||||
assertEquals(1, groups.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetGroupByIdentifierWhenFound() throws Exception {
|
||||
writeAuthorizationsFile(primary, AUTHORIZATIONS);
|
||||
authorizer.onConfigured(configurationContext);
|
||||
assertEquals(2, authorizer.getGroups().size());
|
||||
|
||||
final String identifier = "group-1";
|
||||
final Group group = authorizer.getGroup(identifier);
|
||||
assertNotNull(group);
|
||||
assertEquals(identifier, group.getIdentifier());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetGroupByIdentifierWhenNotFound() throws Exception {
|
||||
writeAuthorizationsFile(primary, AUTHORIZATIONS);
|
||||
authorizer.onConfigured(configurationContext);
|
||||
assertEquals(2, authorizer.getGroups().size());
|
||||
|
||||
final String identifier = "group-X";
|
||||
final Group group = authorizer.getGroup(identifier);
|
||||
assertNull(group);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteGroupWhenFound() throws Exception {
|
||||
writeAuthorizationsFile(primary, AUTHORIZATIONS);
|
||||
authorizer.onConfigured(configurationContext);
|
||||
assertEquals(2, authorizer.getGroups().size());
|
||||
|
||||
// retrieve user-1 and verify its in group-1
|
||||
final User user1 = authorizer.getUser("user-1");
|
||||
assertNotNull(user1);
|
||||
assertEquals(2, user1.getGroups().size());
|
||||
assertTrue(user1.getGroups().contains("group-1"));
|
||||
|
||||
final AccessPolicy policy1 = authorizer.getAccessPolicy("policy-1");
|
||||
assertTrue(policy1.getGroups().contains("group-1"));
|
||||
|
||||
// retrieve group-1
|
||||
final Group group = authorizer.getGroup("group-1");
|
||||
assertEquals("group-1", group.getIdentifier());
|
||||
|
||||
// delete group-1
|
||||
final Group deletedGroup = authorizer.deleteGroup(group);
|
||||
assertNotNull(deletedGroup);
|
||||
assertEquals("group-1", deletedGroup.getIdentifier());
|
||||
|
||||
// verify there is one less overall group
|
||||
assertEquals(1, authorizer.getGroups().size());
|
||||
|
||||
// verify we can no longer retrieve group-1 by identifier
|
||||
assertNull(authorizer.getGroup(group.getIdentifier()));
|
||||
|
||||
// verify user-1 is no longer in group-1
|
||||
final User updatedUser1 = authorizer.getUser("user-1");
|
||||
assertNotNull(updatedUser1);
|
||||
assertEquals(1, updatedUser1.getGroups().size());
|
||||
assertFalse(updatedUser1.getGroups().contains("group-1"));
|
||||
|
||||
// verify group-1 is no longer in policy-1
|
||||
final AccessPolicy updatedPolicy1 = authorizer.getAccessPolicy("policy-1");
|
||||
assertFalse(updatedPolicy1.getGroups().contains("group-1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteGroupWhenNotFound() throws Exception {
|
||||
writeAuthorizationsFile(primary, AUTHORIZATIONS);
|
||||
authorizer.onConfigured(configurationContext);
|
||||
assertEquals(2, authorizer.getGroups().size());
|
||||
|
||||
final Group group = new Group.Builder()
|
||||
.identifier("group-id-X")
|
||||
.name("group-name-X")
|
||||
.build();
|
||||
|
||||
final Group deletedGroup = authorizer.deleteGroup(group);
|
||||
assertNull(deletedGroup);
|
||||
assertEquals(2, authorizer.getGroups().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateGroupWhenFound() throws Exception {
|
||||
writeAuthorizationsFile(primary, AUTHORIZATIONS);
|
||||
authorizer.onConfigured(configurationContext);
|
||||
assertEquals(2, authorizer.getGroups().size());
|
||||
|
||||
final Group group = new Group.Builder()
|
||||
.identifier("group-1")
|
||||
.name("new-name")
|
||||
.build();
|
||||
|
||||
final Group updatedGroup = authorizer.updateGroup(group);
|
||||
assertEquals(group.getIdentifier(), updatedGroup.getIdentifier());
|
||||
assertEquals(group.getName(), updatedGroup.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateGroupWhenNotFound() throws Exception {
|
||||
writeAuthorizationsFile(primary, AUTHORIZATIONS);
|
||||
authorizer.onConfigured(configurationContext);
|
||||
assertEquals(2, authorizer.getGroups().size());
|
||||
|
||||
final Group group = new Group.Builder()
|
||||
.identifier("group-X")
|
||||
.name("group-X")
|
||||
.build();
|
||||
|
||||
final Group updatedGroup = authorizer.updateGroup(group);
|
||||
assertNull(updatedGroup);
|
||||
assertEquals(2, authorizer.getGroups().size());
|
||||
}
|
||||
|
||||
// --------------- AccessPolicy Tests ------------------------
|
||||
|
||||
@Test
|
||||
public void testAddAccessPolicy() throws Exception {
|
||||
writeAuthorizationsFile(primary, EMPTY_AUTHORIZATIONS);
|
||||
authorizer.onConfigured(configurationContext);
|
||||
assertEquals(0, authorizer.getAccessPolicies().size());
|
||||
|
||||
final AccessPolicy policy1 = new AccessPolicy.Builder()
|
||||
.identifier("policy-1")
|
||||
.resource("resource-1")
|
||||
.addUser("user-1")
|
||||
.addGroup("group-1")
|
||||
.addAction(RequestAction.READ)
|
||||
.build();
|
||||
|
||||
final AccessPolicy returnedPolicy1 = authorizer.addAccessPolicy(policy1);
|
||||
assertNotNull(returnedPolicy1);
|
||||
assertEquals(policy1.getIdentifier(), returnedPolicy1.getIdentifier());
|
||||
assertEquals(policy1.getResource(), returnedPolicy1.getResource());
|
||||
assertEquals(policy1.getUsers(), returnedPolicy1.getUsers());
|
||||
assertEquals(policy1.getGroups(), returnedPolicy1.getGroups());
|
||||
assertEquals(policy1.getActions(), returnedPolicy1.getActions());
|
||||
|
||||
assertEquals(1, authorizer.getAccessPolicies().size());
|
||||
|
||||
// second policy for the same resource
|
||||
final AccessPolicy policy2 = new AccessPolicy.Builder()
|
||||
.identifier("policy-2")
|
||||
.resource("resource-1")
|
||||
.addUser("user-1")
|
||||
.addGroup("group-1")
|
||||
.addAction(RequestAction.READ)
|
||||
.build();
|
||||
|
||||
final AccessPolicy returnedPolicy2 = authorizer.addAccessPolicy(policy2);
|
||||
assertNotNull(returnedPolicy2);
|
||||
assertEquals(2, authorizer.getAccessPolicies().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddAccessPolicyWithEmptyUsersAndGroups() throws Exception {
|
||||
writeAuthorizationsFile(primary, EMPTY_AUTHORIZATIONS);
|
||||
authorizer.onConfigured(configurationContext);
|
||||
assertEquals(0, authorizer.getAccessPolicies().size());
|
||||
|
||||
final AccessPolicy policy1 = new AccessPolicy.Builder()
|
||||
.identifier("policy-1")
|
||||
.resource("resource-1")
|
||||
.addAction(RequestAction.READ)
|
||||
.build();
|
||||
|
||||
final AccessPolicy returnedPolicy1 = authorizer.addAccessPolicy(policy1);
|
||||
assertNotNull(returnedPolicy1);
|
||||
assertEquals(policy1.getIdentifier(), returnedPolicy1.getIdentifier());
|
||||
assertEquals(policy1.getResource(), returnedPolicy1.getResource());
|
||||
assertEquals(policy1.getUsers(), returnedPolicy1.getUsers());
|
||||
assertEquals(policy1.getGroups(), returnedPolicy1.getGroups());
|
||||
assertEquals(policy1.getActions(), returnedPolicy1.getActions());
|
||||
|
||||
assertEquals(1, authorizer.getAccessPolicies().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAccessPolicy() throws Exception {
|
||||
writeAuthorizationsFile(primary, AUTHORIZATIONS);
|
||||
authorizer.onConfigured(configurationContext);
|
||||
assertEquals(2, authorizer.getAccessPolicies().size());
|
||||
|
||||
final AccessPolicy policy = authorizer.getAccessPolicy("policy-1");
|
||||
assertNotNull(policy);
|
||||
assertEquals("policy-1", policy.getIdentifier());
|
||||
assertEquals("/flow", policy.getResource());
|
||||
|
||||
assertEquals(2, policy.getActions().size());
|
||||
assertTrue(policy.getActions().contains(RequestAction.WRITE));
|
||||
assertTrue(policy.getActions().contains(RequestAction.READ));
|
||||
|
||||
assertEquals(1, policy.getUsers().size());
|
||||
assertTrue(policy.getUsers().contains("user-1"));
|
||||
|
||||
assertEquals(2, policy.getGroups().size());
|
||||
assertTrue(policy.getGroups().contains("group-1"));
|
||||
assertTrue(policy.getGroups().contains("group-2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAccessPolicyWhenNotFound() throws Exception {
|
||||
writeAuthorizationsFile(primary, AUTHORIZATIONS);
|
||||
authorizer.onConfigured(configurationContext);
|
||||
assertEquals(2, authorizer.getAccessPolicies().size());
|
||||
|
||||
final AccessPolicy policy = authorizer.getAccessPolicy("policy-X");
|
||||
assertNull(policy);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateAccessPolicy() throws Exception {
|
||||
writeAuthorizationsFile(primary, AUTHORIZATIONS);
|
||||
authorizer.onConfigured(configurationContext);
|
||||
assertEquals(2, authorizer.getAccessPolicies().size());
|
||||
|
||||
final AccessPolicy policy = new AccessPolicy.Builder()
|
||||
.identifier("policy-1")
|
||||
.resource("resource-A")
|
||||
.addUser("user-A")
|
||||
.addGroup("group-A")
|
||||
.addAction(RequestAction.READ)
|
||||
.build();
|
||||
|
||||
final AccessPolicy updateAccessPolicy = authorizer.updateAccessPolicy(policy);
|
||||
assertNotNull(updateAccessPolicy);
|
||||
assertEquals("policy-1", updateAccessPolicy.getIdentifier());
|
||||
assertEquals("resource-A", updateAccessPolicy.getResource());
|
||||
|
||||
assertEquals(1, updateAccessPolicy.getUsers().size());
|
||||
assertTrue(updateAccessPolicy.getUsers().contains("user-A"));
|
||||
|
||||
assertEquals(1, updateAccessPolicy.getGroups().size());
|
||||
assertTrue(updateAccessPolicy.getGroups().contains("group-A"));
|
||||
|
||||
assertEquals(1, updateAccessPolicy.getActions().size());
|
||||
assertTrue(updateAccessPolicy.getActions().contains(RequestAction.READ));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateAccessPolicyWhenResourceNotFound() throws Exception {
|
||||
writeAuthorizationsFile(primary, AUTHORIZATIONS);
|
||||
authorizer.onConfigured(configurationContext);
|
||||
assertEquals(2, authorizer.getAccessPolicies().size());
|
||||
|
||||
final AccessPolicy policy = new AccessPolicy.Builder()
|
||||
.identifier("policy-XXX")
|
||||
.resource("resource-A")
|
||||
.addUser("user-A")
|
||||
.addGroup("group-A")
|
||||
.addAction(RequestAction.READ)
|
||||
.build();
|
||||
|
||||
final AccessPolicy updateAccessPolicy = authorizer.updateAccessPolicy(policy);
|
||||
assertNull(updateAccessPolicy);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteAccessPolicy() throws Exception {
|
||||
writeAuthorizationsFile(primary, AUTHORIZATIONS);
|
||||
authorizer.onConfigured(configurationContext);
|
||||
assertEquals(2, authorizer.getAccessPolicies().size());
|
||||
|
||||
final AccessPolicy policy = new AccessPolicy.Builder()
|
||||
.identifier("policy-1")
|
||||
.resource("resource-A")
|
||||
.addUser("user-A")
|
||||
.addGroup("group-A")
|
||||
.addAction(RequestAction.READ)
|
||||
.build();
|
||||
|
||||
final AccessPolicy deletedAccessPolicy = authorizer.deleteAccessPolicy(policy);
|
||||
assertNotNull(deletedAccessPolicy);
|
||||
assertEquals(policy.getIdentifier(), deletedAccessPolicy.getIdentifier());
|
||||
|
||||
// should have one less policy, and get by policy id should return null
|
||||
assertEquals(1, authorizer.getAccessPolicies().size());
|
||||
assertNull(authorizer.getAccessPolicy(policy.getIdentifier()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteAccessPolicyWhenNotFound() throws Exception {
|
||||
writeAuthorizationsFile(primary, AUTHORIZATIONS);
|
||||
authorizer.onConfigured(configurationContext);
|
||||
assertEquals(2, authorizer.getAccessPolicies().size());
|
||||
|
||||
final AccessPolicy policy = new AccessPolicy.Builder()
|
||||
.identifier("policy-XXX")
|
||||
.resource("resource-A")
|
||||
.addUser("user-A")
|
||||
.addGroup("group-A")
|
||||
.addAction(RequestAction.READ)
|
||||
.build();
|
||||
|
||||
final AccessPolicy deletedAccessPolicy = authorizer.deleteAccessPolicy(policy);
|
||||
assertNull(deletedAccessPolicy);
|
||||
}
|
||||
|
||||
private static void writeAuthorizationsFile(final File file, final String content) throws Exception {
|
||||
|
|
|
@ -21,40 +21,7 @@
|
|||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>nifi-framework-authorization</artifactId>
|
||||
<build>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>src/main/xsd</directory>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>jaxb2-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>current</id>
|
||||
<goals>
|
||||
<goal>xjc</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<packageName>org.apache.nifi.authorization.generated</packageName>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
<configuration>
|
||||
<excludes>**/authorization/generated/*.java,</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.nifi</groupId>
|
||||
|
@ -64,22 +31,10 @@
|
|||
<groupId>org.apache.nifi</groupId>
|
||||
<artifactId>nifi-expression-language</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.nifi</groupId>
|
||||
<artifactId>nifi-properties</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.nifi</groupId>
|
||||
<artifactId>nifi-nar-utils</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
|
|
|
@ -29,10 +29,12 @@ import java.util.Map;
|
|||
public class StandardAuthorizerConfigurationContext implements AuthorizerConfigurationContext {
|
||||
|
||||
private final String identifier;
|
||||
private final String rootGroupId;
|
||||
private final Map<String, String> properties;
|
||||
|
||||
public StandardAuthorizerConfigurationContext(String identifier, Map<String, String> properties) {
|
||||
public StandardAuthorizerConfigurationContext(String identifier, String rootGroupId, Map<String, String> properties) {
|
||||
this.identifier = identifier;
|
||||
this.rootGroupId = rootGroupId;
|
||||
this.properties = Collections.unmodifiableMap(new HashMap<String, String>(properties));
|
||||
}
|
||||
|
||||
|
@ -41,6 +43,11 @@ public class StandardAuthorizerConfigurationContext implements AuthorizerConfigu
|
|||
return identifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRootGroupId() {
|
||||
return rootGroupId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getProperties() {
|
||||
return properties;
|
||||
|
|
|
@ -56,12 +56,17 @@
|
|||
/{type}/{id}/provenance - READ - allows user/entity to view provenance data from the underlying component
|
||||
- WRITE - NA
|
||||
-->
|
||||
<resources>
|
||||
<authorizations>
|
||||
<!--
|
||||
<resource identifier="/flow">
|
||||
<authorization identity="user-identity-1" action="R"></authorization>
|
||||
<authorization identity="user-identity-2" action="W"></authorization>
|
||||
<authorization identity="user-identity-3" action="RW"></authorization>
|
||||
</resource>
|
||||
<users>
|
||||
<user identifier="1" identity="" />
|
||||
</users>
|
||||
|
||||
<policies>
|
||||
<policy identifier="1" resource="/flow" action="RW">
|
||||
<user identifier="1" />
|
||||
</policy>
|
||||
</policies>
|
||||
-->
|
||||
</resources>
|
||||
|
||||
</authorizations>
|
|
@ -23,6 +23,6 @@
|
|||
<identifier>file-provider</identifier>
|
||||
<class>org.apache.nifi.authorization.FileAuthorizer</class>
|
||||
<property name="Authorizations File">./conf/authorizations.xml</property>
|
||||
<property name="Reload Interval">30 secs</property>
|
||||
<property name="Initial Admin Identity"></property>
|
||||
</authorizer>
|
||||
</authorizers>
|
|
@ -27,7 +27,7 @@ import org.springframework.context.annotation.ImportResource;
|
|||
@Import({NiFiWebApiSecurityConfiguration.class})
|
||||
@ImportResource({"classpath:nifi-context.xml",
|
||||
"classpath:nifi-administration-context.xml",
|
||||
"classpath:nifi-framework-authorization-context.xml",
|
||||
"classpath:nifi-authorizer-context.xml",
|
||||
"classpath:nifi-cluster-manager-context.xml",
|
||||
"classpath:nifi-cluster-protocol-context.xml",
|
||||
"classpath:nifi-web-security-context.xml",
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
<module>nifi-web</module>
|
||||
<module>nifi-resources</module>
|
||||
<module>nifi-documentation</module>
|
||||
<module>nifi-authorizer</module>
|
||||
</modules>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
|
|
|
@ -113,6 +113,11 @@
|
|||
<artifactId>nifi-file-authorizer</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.nifi</groupId>
|
||||
<artifactId>nifi-authorizer</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
</project>
|
||||
|
|
Loading…
Reference in New Issue