Repository: nifi-registry Updated Branches: refs/heads/master 31fe8434c -> a8786a807
NIFIREG-64 Updates Policy Authorization Behavior - Changes authorization to /policies to be based on /polices resource - Changes per-bucket policies to inherit from base /buckets policy - Cleans up framework classes related to Authorization This closes #52. Signed-off-by: Bryan Bende <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/nifi-registry/repo Commit: http://git-wip-us.apache.org/repos/asf/nifi-registry/commit/a8786a80 Tree: http://git-wip-us.apache.org/repos/asf/nifi-registry/tree/a8786a80 Diff: http://git-wip-us.apache.org/repos/asf/nifi-registry/diff/a8786a80 Branch: refs/heads/master Commit: a8786a807c0c015f60242c627509e818f87b4f9a Parents: 31fe843 Author: Kevin Doran <[email protected]> Authored: Mon Dec 11 12:02:23 2017 -0500 Committer: Bryan Bende <[email protected]> Committed: Tue Dec 12 15:33:46 2017 -0500 ---------------------------------------------------------------------- .../authorization/AuthorizableLookup.java | 8 -- .../StandardAuthorizableLookup.java | 91 ++++---------- .../resource/AccessPolicyAuthorizable.java | 122 ------------------- ...rcePolicyPermissionsThroughBaseResource.java | 36 ------ .../resource/InheritingAuthorizable.java | 85 +++++++++++++ .../authorization/resource/ResourceFactory.java | 6 - .../registry/service/AuthorizationService.java | 2 +- .../registry/web/api/AccessPolicyResource.java | 25 +--- .../nifi/registry/web/api/BucketResource.java | 12 +- .../nifi/registry/web/api/SecureLdapIT.java | 14 +++ 10 files changed, 141 insertions(+), 260 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/a8786a80/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/AuthorizableLookup.java ---------------------------------------------------------------------- diff --git a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/AuthorizableLookup.java b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/AuthorizableLookup.java index f5bbd4d..2cbe1af 100644 --- a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/AuthorizableLookup.java +++ b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/AuthorizableLookup.java @@ -65,14 +65,6 @@ public interface AuthorizableLookup { Authorizable getBucketAuthorizable(String bucketIdentifier); /** - * Get the authorizable for the policy of the specified resource. - * - * @param resource resource - * @return authorizable - */ - Authorizable getAccessPolicyByResource(String resource); - - /** * Get the authorizable of the specified resource. * * @param resource resource http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/a8786a80/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/StandardAuthorizableLookup.java ---------------------------------------------------------------------- diff --git a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/StandardAuthorizableLookup.java b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/StandardAuthorizableLookup.java index dfd9adc..3d54c62 100644 --- a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/StandardAuthorizableLookup.java +++ b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/StandardAuthorizableLookup.java @@ -18,8 +18,8 @@ package org.apache.nifi.registry.security.authorization; import org.apache.commons.lang3.StringUtils; import org.apache.nifi.registry.exception.ResourceNotFoundException; -import org.apache.nifi.registry.security.authorization.resource.AccessPolicyAuthorizable; import org.apache.nifi.registry.security.authorization.resource.Authorizable; +import org.apache.nifi.registry.security.authorization.resource.InheritingAuthorizable; import org.apache.nifi.registry.security.authorization.resource.ResourceFactory; import org.apache.nifi.registry.security.authorization.resource.ResourceType; import org.springframework.stereotype.Component; @@ -114,7 +114,8 @@ public class StandardAuthorizableLookup implements AuthorizableLookup { @Override public Authorizable getBucketAuthorizable(String bucketIdentifier) { - return new Authorizable() { + // Note - this returns a special Authorizable type that inherits permissions from the parent Authorizable + return new InheritingAuthorizable() { @Override public Authorizable getParentAuthorizable() { @@ -123,24 +124,13 @@ public class StandardAuthorizableLookup implements AuthorizableLookup { @Override public Resource getResource() { - return ResourceFactory.getBucketResource(bucketIdentifier, null); + return ResourceFactory.getBucketResource(bucketIdentifier, "Bucket with ID " + bucketIdentifier); } }; } @Override - public Authorizable getAccessPolicyByResource(final String resource) { - try { - return new AccessPolicyAuthorizable(getAuthorizableByResource(resource)); - } catch (final ResourceNotFoundException e) { - // the underlying component has been removed or resource is invalid... require /policies permissions - return POLICIES_AUTHORIZABLE; - } - } - - @Override public Authorizable getAuthorizableByResource(String resource) { - // parse the resource type ResourceType resourceType = null; for (ResourceType type : ResourceType.values()) { if (resource.equals(type.getValue()) || resource.startsWith(type.getValue() + "/")) { @@ -152,53 +142,19 @@ public class StandardAuthorizableLookup implements AuthorizableLookup { throw new ResourceNotFoundException("Unrecognized resource: " + resource); } - // if this is a policy resource, there should be another resource type - if (ResourceType.Policy.equals(resourceType)) { - final ResourceType primaryResourceType = resourceType; - - // get the resource type - resource = StringUtils.substringAfter(resource, resourceType.getValue()); - - for (ResourceType type : ResourceType.values()) { - if (resource.equals(type.getValue()) || resource.startsWith(type.getValue() + "/")) { - resourceType = type; - } - } - - if (resourceType == null) { - throw new ResourceNotFoundException("Unrecognized resource: " + resource); - } - - return new AccessPolicyAuthorizable(getAccessPolicy(resourceType, resource)); - } else { - return getAccessPolicy(resourceType, resource); - } + return getAuthorizableByResource(resourceType, resource); } - private Authorizable getAccessPolicy(final ResourceType resourceType, final String resource) { - final String slashComponentId = StringUtils.substringAfter(resource, resourceType.getValue()); - if (slashComponentId.startsWith("/")) { - return getAccessPolicyByResource(resourceType, slashComponentId.substring(1)); + private Authorizable getAuthorizableByResource(final ResourceType resourceType, final String resource) { + final String childResourceId = StringUtils.substringAfter(resource, resourceType.getValue()); + if (childResourceId.startsWith("/")) { + return getAuthorizableByChildResource(resourceType, childResourceId.substring(1)); } else { - return getAccessPolicyByResource(resourceType); + return getAuthorizableByResource(resourceType); } } - private Authorizable getAccessPolicyByResource(final ResourceType resourceType, final String childResourceId) { - Authorizable authorizable = null; - switch (resourceType) { - case Bucket: - authorizable = getBucketAuthorizable(childResourceId); - } - - if (authorizable == null) { - throw new IllegalArgumentException("An unexpected type of resource in this policy " + resourceType.getValue()); - } - - return authorizable; - } - - private Authorizable getAccessPolicyByResource(final ResourceType resourceType) { + private Authorizable getAuthorizableByResource(final ResourceType resourceType) { Authorizable authorizable = null; switch (resourceType) { @@ -209,17 +165,7 @@ public class StandardAuthorizableLookup implements AuthorizableLookup { authorizable = getPoliciesAuthorizable(); break; case Resource: - authorizable = new Authorizable() { - @Override - public Authorizable getParentAuthorizable() { - return null; - } - - @Override - public Resource getResource() { - return ResourceFactory.getResourceResource(); - } - }; + authorizable = getResourcesAuthorizable(); break; case Tenant: authorizable = getTenantsAuthorizable(); @@ -235,4 +181,17 @@ public class StandardAuthorizableLookup implements AuthorizableLookup { return authorizable; } + private Authorizable getAuthorizableByChildResource(final ResourceType baseResourceType, final String childResourceId) { + Authorizable authorizable; + switch (baseResourceType) { + case Bucket: + authorizable = getBucketAuthorizable(childResourceId); + break; + default: + throw new IllegalArgumentException("Unexpected lookup for child resource authorizable for base resource type " + baseResourceType.getValue()); + } + + return authorizable; + } + } http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/a8786a80/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/resource/AccessPolicyAuthorizable.java ---------------------------------------------------------------------- diff --git a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/resource/AccessPolicyAuthorizable.java b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/resource/AccessPolicyAuthorizable.java deleted file mode 100644 index de28565..0000000 --- a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/resource/AccessPolicyAuthorizable.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.nifi.registry.security.authorization.resource; - -import org.apache.nifi.registry.security.authorization.exception.AccessDeniedException; -import org.apache.nifi.registry.security.authorization.AuthorizationResult; -import org.apache.nifi.registry.security.authorization.AuthorizationResult.Result; -import org.apache.nifi.registry.security.authorization.Authorizer; -import org.apache.nifi.registry.security.authorization.RequestAction; -import org.apache.nifi.registry.security.authorization.Resource; -import org.apache.nifi.registry.security.authorization.user.NiFiUser; - -import java.util.Map; - -/** - * Authorizable for policies of an Authorizable. - */ -public class AccessPolicyAuthorizable implements Authorizable, EnforcePolicyPermissionsThroughBaseResource { - - private static final Authorizable POLICIES_AUTHORIZABLE = new Authorizable() { - @Override - public Authorizable getParentAuthorizable() { - return null; - } - - @Override - public Resource getResource() { - return ResourceFactory.getPoliciesResource(); - } - }; - - final Authorizable authorizable; - - public AccessPolicyAuthorizable(Authorizable authorizable) { - this.authorizable = authorizable; - } - - @Override - public Authorizable getBaseAuthorizable() { - return authorizable; - } - - @Override - public Authorizable getParentAuthorizable() { - final Authorizable effectiveAuthorizable = getEffectiveAuthorizable(); - if (effectiveAuthorizable.getParentAuthorizable() == null) { - return POLICIES_AUTHORIZABLE; - } else { - return new AccessPolicyAuthorizable(effectiveAuthorizable.getParentAuthorizable()); - } - } - - @Override - public Resource getResource() { - return ResourceFactory.getPolicyResource(getEffectiveAuthorizable().getResource()); - } - - private Authorizable getEffectiveAuthorizable() { - // possibly consider the base resource if the authorizable uses it to enforce policy permissions - if (authorizable instanceof EnforcePolicyPermissionsThroughBaseResource) { - final Authorizable baseAuthorizable = ((EnforcePolicyPermissionsThroughBaseResource) authorizable).getBaseAuthorizable(); - - // if the base authorizable is for a policy, we don't want to use the base otherwise it would keep unwinding and would eventually - // evaluate to the policy of the component and not the policy of the policies for the component - if (baseAuthorizable instanceof AccessPolicyAuthorizable) { - return authorizable; - } else { - return baseAuthorizable; - } - } else { - return authorizable; - } - } - - @Override - public AuthorizationResult checkAuthorization(Authorizer authorizer, RequestAction action, NiFiUser user, Map<String, String> resourceContext) { - if (user == null) { - throw new AccessDeniedException("Unknown user."); - } - - final AuthorizationResult resourceResult = Authorizable.super.checkAuthorization(authorizer, action, user, resourceContext); - - // if we're denied from the resource try inheriting - if (Result.Denied.equals(resourceResult.getResult())) { - return getParentAuthorizable().checkAuthorization(authorizer, action, user, resourceContext); - } else { - return resourceResult; - } - } - - @Override - public void authorize(Authorizer authorizer, RequestAction action, NiFiUser user, Map<String, String> resourceContext) throws AccessDeniedException { - if (user == null) { - throw new AccessDeniedException("Unknown user."); - } - - try { - Authorizable.super.authorize(authorizer, action, user, resourceContext); - } catch (final AccessDeniedException resourceDenied) { - // if we're denied from the resource try inheriting - try { - getParentAuthorizable().authorize(authorizer, action, user, resourceContext); - } catch (final AccessDeniedException policiesDenied) { - throw resourceDenied; - } - } - } -} http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/a8786a80/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/resource/EnforcePolicyPermissionsThroughBaseResource.java ---------------------------------------------------------------------- diff --git a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/resource/EnforcePolicyPermissionsThroughBaseResource.java b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/resource/EnforcePolicyPermissionsThroughBaseResource.java deleted file mode 100644 index 90fc143..0000000 --- a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/resource/EnforcePolicyPermissionsThroughBaseResource.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.nifi.registry.security.authorization.resource; - -/** - * Defers permissions on policies to the policies of the base authorizable. Required because we don't - * want to change the enforcement of the policies on the authorizable. For example... - * - * if a user has permissions to /policies/input-ports/1234 then they have permissions to the following - * - * - the policy for /buckets/1234 -> /policies/buckets/1234 - * - the policy for /policies/buckets/1234 -> /policies/policies/buckets/1234 - */ -public interface EnforcePolicyPermissionsThroughBaseResource { - - /** - * Returns the base authorizable. Cannot be null. - * - * @return base authorizable - */ - Authorizable getBaseAuthorizable(); -} http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/a8786a80/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/resource/InheritingAuthorizable.java ---------------------------------------------------------------------- diff --git a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/resource/InheritingAuthorizable.java b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/resource/InheritingAuthorizable.java new file mode 100644 index 0000000..b029229 --- /dev/null +++ b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/resource/InheritingAuthorizable.java @@ -0,0 +1,85 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.nifi.registry.security.authorization.resource; + +import org.apache.nifi.registry.security.authorization.AuthorizationResult; +import org.apache.nifi.registry.security.authorization.AuthorizationResult.Result; +import org.apache.nifi.registry.security.authorization.Authorizer; +import org.apache.nifi.registry.security.authorization.RequestAction; +import org.apache.nifi.registry.security.authorization.exception.AccessDeniedException; +import org.apache.nifi.registry.security.authorization.user.NiFiUser; + +import java.util.Map; + +public interface InheritingAuthorizable extends Authorizable { + + /** + * Returns the result of an authorization request for the specified user for the specified action on the specified + * resource. This method does not imply the user is directly attempting to access the specified resource. If the user is + * attempting a direct access use Authorizable.authorize(). + * + * @param authorizer authorizer + * @param action action + * @param user user + * @return is authorized + */ + default AuthorizationResult checkAuthorization(Authorizer authorizer, RequestAction action, NiFiUser user, Map<String, String> resourceContext) { + if (user == null) { + throw new AccessDeniedException("Unknown user."); + } + + final AuthorizationResult resourceResult = Authorizable.super.checkAuthorization(authorizer, action, user, resourceContext); + + // if we're denied from the resource try inheriting + if (Result.Denied.equals(resourceResult.getResult()) && getParentAuthorizable() != null) { + return getParentAuthorizable().checkAuthorization(authorizer, action, user, resourceContext); + } else { + return resourceResult; + } + } + + /** + * Authorizes the current user for the specified action on the specified resource. If the current user is + * not in the access policy for the specified resource, the parent authorizable resource will be checked, recursively + * + * @param authorizer authorizer + * @param action action + * @param user user + * @param resourceContext resource context + */ + default void authorize(Authorizer authorizer, RequestAction action, NiFiUser user, Map<String, String> resourceContext) throws AccessDeniedException { + if (user == null) { + throw new AccessDeniedException("Unknown user."); + } + + try { + Authorizable.super.authorize(authorizer, action, user, resourceContext); + } catch (final AccessDeniedException resourceDenied) { + // if we're denied from the resource try inheriting + try { + if (getParentAuthorizable() != null) { + getParentAuthorizable().authorize(authorizer, action, user, resourceContext); + } else { + throw resourceDenied; + } + } catch (final AccessDeniedException policiesDenied) { + throw resourceDenied; + } + } + } + +} http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/a8786a80/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/resource/ResourceFactory.java ---------------------------------------------------------------------- diff --git a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/resource/ResourceFactory.java b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/resource/ResourceFactory.java index 52c91c5..7882708 100644 --- a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/resource/ResourceFactory.java +++ b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/resource/ResourceFactory.java @@ -235,12 +235,6 @@ public final class ResourceFactory { case Bucket: safeDescription.append("Bucket"); break; - case Policy: - safeDescription.append("Policy"); - break; - case Tenant: - safeDescription.append("Tenant"); - break; default: safeDescription.append("Unknown resource type"); break; http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/a8786a80/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/AuthorizationService.java ---------------------------------------------------------------------- diff --git a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/AuthorizationService.java b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/AuthorizationService.java index 6c380b1..3bb29fb 100644 --- a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/AuthorizationService.java +++ b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/AuthorizationService.java @@ -466,7 +466,7 @@ public class AuthorizationService { resources.add(ResourceFactory.getBucketsResource()); // add all buckets for (final Bucket bucket : registryService.getBuckets()) { - resources.add(ResourceFactory.getChildResource(ResourceType.Bucket, bucket.getIdentifier(), bucket.getName())); + resources.add(ResourceFactory.getBucketResource(bucket.getIdentifier(), bucket.getName())); } } http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/a8786a80/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/AccessPolicyResource.java ---------------------------------------------------------------------- diff --git a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/AccessPolicyResource.java b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/AccessPolicyResource.java index 84cc555..2c96d70 100644 --- a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/AccessPolicyResource.java +++ b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/AccessPolicyResource.java @@ -16,7 +16,6 @@ */ package org.apache.nifi.registry.web.api; - import javax.servlet.http.HttpServletRequest; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; @@ -71,8 +70,6 @@ public class AccessPolicyResource extends AuthorizableApplicationResource { super(authorizer, authorizationService); } - // TODO - Verify that access control is done by the resource the policy is for, not the /policies resource itself. - /** * Create a new access policy. * @@ -110,7 +107,7 @@ public class AccessPolicyResource extends AuthorizableApplicationResource { } RequestAction.valueOfValue(requestAccessPolicy.getAction()); - authorizeAccessToResource(RequestAction.WRITE, requestAccessPolicy.getResource()); + authorizeAccess(RequestAction.WRITE); AccessPolicy createdPolicy = authorizationService.createAccessPolicy(requestAccessPolicy); @@ -172,7 +169,7 @@ public class AccessPolicyResource extends AuthorizableApplicationResource { verifyAuthorizerIsManaged(); final AccessPolicy accessPolicy = authorizationService.getAccessPolicy(identifier); - authorizeAccessToResource(RequestAction.READ, accessPolicy.getResource()); + authorizeAccess(RequestAction.READ); return generateOkResponse(accessPolicy).build(); } @@ -218,7 +215,7 @@ public class AccessPolicyResource extends AuthorizableApplicationResource { final RequestAction requestAction = RequestAction.valueOfValue(action); final String resource = "/" + rawResource; - authorizeAccessToResource(RequestAction.READ, resource); + authorizeAccess(RequestAction.READ); AccessPolicy accessPolicy = authorizationService.getAccessPolicy(resource, requestAction); return generateOkResponse(accessPolicy).build(); @@ -266,7 +263,7 @@ public class AccessPolicyResource extends AuthorizableApplicationResource { + "policy id of the requested resource (%s).", requestAccessPolicy.getIdentifier(), identifier)); } - authorizeAccessToPolicy(RequestAction.WRITE, identifier); + authorizeAccess(RequestAction.WRITE); AccessPolicy createdPolicy = authorizationService.updateAccessPolicy(requestAccessPolicy); @@ -302,7 +299,7 @@ public class AccessPolicyResource extends AuthorizableApplicationResource { final String identifier) { verifyAuthorizerSupportsConfigurablePolicies(); - authorizeAccessToPolicy(RequestAction.DELETE, identifier); + authorizeAccess(RequestAction.DELETE); AccessPolicy deletedPolicy = authorizationService.deleteAccessPolicy(identifier); return generateOkResponse(deletedPolicy).build(); } @@ -328,18 +325,6 @@ public class AccessPolicyResource extends AuthorizableApplicationResource { }); } - private void authorizeAccessToPolicy(RequestAction actionType, String accessPolicyIdentifier) { - AccessPolicy accessPolicy = authorizationService.getAccessPolicy(accessPolicyIdentifier); - authorizeAccessToResource(actionType, accessPolicy.getResource()); - } - - private void authorizeAccessToResource(RequestAction actionType, String resource) { - authorizationService.authorizeAccess(lookup -> { - final Authorizable accessPolicy = lookup.getAccessPolicyByResource(resource); - accessPolicy.authorize(authorizer, actionType, NiFiUserUtils.getNiFiUser()); - }); - } - private String generateAccessPolicyUri(final AccessPolicySummary accessPolicy) { return generateResourceUri("policies", accessPolicy.getIdentifier()); } http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/a8786a80/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/BucketResource.java ---------------------------------------------------------------------- diff --git a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/BucketResource.java b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/BucketResource.java index 82bb172..1ee2180 100644 --- a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/BucketResource.java +++ b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/BucketResource.java @@ -116,7 +116,8 @@ public class BucketResource extends AuthorizableApplicationResource { @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Gets all buckets", - notes = "The returned list will include only buckets for which the caller is authorized.", + notes = "The returned list will include only buckets for which the user is authorized." + + "If the user is not authorized for any buckets, this returns an empty list.", response = Bucket.class, responseContainer = "List" ) @@ -128,6 +129,15 @@ public class BucketResource extends AuthorizableApplicationResource { @ApiParam(value = SortParameter.API_PARAM_DESCRIPTION, format = "field:order", allowMultiple = true, example = "name:ASC") @QueryParam("sort") final List<String> sortParameters) { + + // Note: We don't explicitly check for access to (READ, /buckets) because + // a user might have access to individual buckets without top-level access. + // For example, a user that has (READ, /buckets/bucket-id-1) but not access + // to /buckets should not get a 403 error returned from this endpoint. + // This has the side effect that a user with no access to any buckets + // gets an empty array returned from this endpoint instead of 403 as one + // might expect. + final Set<String> authorizedBucketIds = getAuthorizedBucketIds(RequestAction.READ); if (authorizedBucketIds == null || authorizedBucketIds.isEmpty()) { http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/a8786a80/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/web/api/SecureLdapIT.java ---------------------------------------------------------------------- diff --git a/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/web/api/SecureLdapIT.java b/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/web/api/SecureLdapIT.java index 7cd9138..416e50d 100644 --- a/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/web/api/SecureLdapIT.java +++ b/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/web/api/SecureLdapIT.java @@ -427,6 +427,20 @@ public class SecureLdapIT extends IntegrationTestBase { assertEquals(201, adminGrantsReadAccessResponse.getStatus()); + // When: nifiadmin tries to list all buckets + final Bucket[] adminBuckets = client + .target(createURL("buckets")) + .request() + .header("Authorization", "Bearer " + adminAuthToken) + .get(Bucket[].class); + + // Then: the full list is returned (verifies that per-bucket access policies are additive to base /buckets policy) + assertNotNull(adminBuckets); + assertEquals(1, adminBuckets.length); + assertEquals(createdBucket.getIdentifier(), adminBuckets[0].getIdentifier()); + assertEquals(new Permissions().withCanRead(true).withCanWrite(true).withCanDelete(true), adminBuckets[0].getPermissions()); + + // When: user nobel re-queries /buckets final Bucket[] buckets2 = client .target(createURL("buckets"))
