diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/EntityRepository.java b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/EntityRepository.java index e3a8e11967b..f07a6eee9eb 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/EntityRepository.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/EntityRepository.java @@ -1270,8 +1270,8 @@ public abstract class EntityRepository { return; } - if (updatedByBot()) { - // Revert changes to extension field, if being updated by a bot + if (updatedByBot() && operation == Operation.PUT) { + // Revert extension field, if being updated by a bot with a PUT request to avoid overwriting custom extension updated.setExtension(original.getExtension()); return; } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TeamRepository.java b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TeamRepository.java index ffad52de87b..60c6c912140 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TeamRepository.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TeamRepository.java @@ -339,7 +339,7 @@ public class TeamRepository extends EntityRepository { private List getChildren(UUID teamId) throws IOException { if (teamId.equals(organization.getId())) { // For organization all the parentless teams are children List children = daoCollection.teamDAO().listTeamsUnderOrganization(teamId.toString()); - return EntityUtil.populateEntityReferencesById(children, Entity.TEAM); + return EntityUtil.populateEntityReferencesById(EntityUtil.toIDs(children), Entity.TEAM); } List children = findTo(teamId, TEAM, Relationship.PARENT_OF, TEAM); return EntityUtil.populateEntityReferences(children, TEAM); diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/UserRepository.java b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/UserRepository.java index d59f9854aaf..02c80f34fde 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/UserRepository.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/UserRepository.java @@ -205,7 +205,7 @@ public class UserRepository extends EntityRepository { private List getTeamChildren(UUID teamId) throws IOException { if (teamId.equals(organization.getId())) { // For organization all the parentless teams are children List children = daoCollection.teamDAO().listTeamsUnderOrganization(teamId.toString()); - return EntityUtil.populateEntityReferencesById(children, Entity.TEAM); + return EntityUtil.populateEntityReferencesById(EntityUtil.toIDs(children), Entity.TEAM); } List children = findTo(teamId, TEAM, Relationship.PARENT_OF, TEAM); return EntityUtil.populateEntityReferences(children, TEAM); diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/resources/permissions/PermissionsResource.java b/openmetadata-service/src/main/java/org/openmetadata/service/resources/permissions/PermissionsResource.java index fe0ef70f5b7..0a34c6a693e 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/resources/permissions/PermissionsResource.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/resources/permissions/PermissionsResource.java @@ -19,6 +19,7 @@ import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; +import java.io.IOException; import java.util.List; import java.util.UUID; import javax.ws.rs.GET; @@ -31,13 +32,19 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.SecurityContext; import lombok.NonNull; import org.openmetadata.schema.EntityInterface; +import org.openmetadata.schema.type.EntityReference; +import org.openmetadata.schema.type.MetadataOperation; import org.openmetadata.schema.type.ResourcePermission; import org.openmetadata.service.Entity; import org.openmetadata.service.jdbi3.CollectionDAO; import org.openmetadata.service.jdbi3.EntityRepository; import org.openmetadata.service.resources.Collection; +import org.openmetadata.service.resources.EntityResource; import org.openmetadata.service.security.Authorizer; +import org.openmetadata.service.security.policyevaluator.OperationContext; +import org.openmetadata.service.security.policyevaluator.PolicyEvaluator; import org.openmetadata.service.security.policyevaluator.ResourceContext; +import org.openmetadata.service.util.EntityUtil; import org.openmetadata.service.util.ResultList; @Path("/v1/permissions") @@ -173,6 +180,37 @@ public class PermissionsResource { return authorizer.getPermission(securityContext, user, resourceContext); } + @GET + @Path("/policies") + @Operation( + operationId = "getPermissionsForPolicies", + summary = "Get permissions for a set of policies", + tags = "permission", + responses = { + @ApiResponse( + responseCode = "200", + description = "Permissions for a set of policies", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = ResourcePermissionList.class))) + }) + public ResultList getPermissionForPolicies( + @Context SecurityContext securityContext, + @Parameter(description = "List of policy of ids", schema = @Schema(type = "UUID")) @QueryParam("ids") + List ids) + throws IOException { + // User must have read access to policies + OperationContext operationContext = new OperationContext(Entity.POLICY, MetadataOperation.VIEW_ALL); + EntityRepository dao = Entity.getEntityRepository(Entity.POLICY); + for (UUID id : ids) { + ResourceContext resourceContext = EntityResource.getResourceContext(Entity.POLICY, dao).id(id).build(); + authorizer.authorize(securityContext, operationContext, resourceContext); + } + List policies = EntityUtil.populateEntityReferencesById(ids, Entity.POLICY); + return new ResourcePermissionList(PolicyEvaluator.listPermission(policies)); + } + static class ResourcePermissionList extends ResultList { @SuppressWarnings("unused") public ResourcePermissionList() {} diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/security/DefaultAuthorizer.java b/openmetadata-service/src/main/java/org/openmetadata/service/security/DefaultAuthorizer.java index 11305f7cebc..17bb0b1425e 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/security/DefaultAuthorizer.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/security/DefaultAuthorizer.java @@ -20,6 +20,7 @@ import static org.openmetadata.schema.teams.authn.SSOAuthMechanism.SsoServiceTyp import static org.openmetadata.schema.teams.authn.SSOAuthMechanism.SsoServiceType.CUSTOM_OIDC; import static org.openmetadata.schema.teams.authn.SSOAuthMechanism.SsoServiceType.GOOGLE; import static org.openmetadata.schema.teams.authn.SSOAuthMechanism.SsoServiceType.OKTA; +import static org.openmetadata.schema.type.Permission.Access.ALLOW; import static org.openmetadata.service.Entity.ADMIN_USER_NAME; import static org.openmetadata.service.exception.CatalogExceptionMessage.notAdmin; import static org.openmetadata.service.resources.teams.UserResource.USER_PROTECTED_FIELDS; @@ -45,7 +46,6 @@ import org.openmetadata.schema.teams.authn.BasicAuthMechanism; import org.openmetadata.schema.teams.authn.JWTAuthMechanism; import org.openmetadata.schema.teams.authn.JWTTokenExpiry; import org.openmetadata.schema.teams.authn.SSOAuthMechanism; -import org.openmetadata.schema.type.Permission.Access; import org.openmetadata.schema.type.ResourcePermission; import org.openmetadata.service.Entity; import org.openmetadata.service.OpenMetadataApplicationConfig; @@ -184,24 +184,18 @@ public class DefaultAuthorizer implements Authorizer { public List listPermissions(SecurityContext securityContext, String user) { SubjectContext subjectContext = getSubjectContext(securityContext); subjectContext = changeSubjectContext(user, subjectContext); - - if (subjectContext.isAdmin() || subjectContext.isBot()) { - // Admins and bots have permissions to do all operations. - return PolicyEvaluator.getResourcePermissions(Access.ALLOW); - } - return PolicyEvaluator.listPermission(subjectContext); + return subjectContext.isAdmin() + ? PolicyEvaluator.getResourcePermissions(ALLOW) // Admin has permissions to do all operations. + : PolicyEvaluator.listPermission(subjectContext); } @Override public ResourcePermission getPermission(SecurityContext securityContext, String user, String resourceType) { SubjectContext subjectContext = getSubjectContext(securityContext); subjectContext = changeSubjectContext(user, subjectContext); - - if (subjectContext.isAdmin() || subjectContext.isBot()) { - // Admins and bots have permissions to do all operations. - return PolicyEvaluator.getResourcePermission(resourceType, Access.ALLOW); - } - return PolicyEvaluator.getPermission(subjectContext, resourceType); + return subjectContext.isAdmin() + ? PolicyEvaluator.getResourcePermission(resourceType, ALLOW) // Admin has permissions to do all operations. + : PolicyEvaluator.getPermission(subjectContext, resourceType); } @Override @@ -209,12 +203,9 @@ public class DefaultAuthorizer implements Authorizer { SecurityContext securityContext, String user, ResourceContextInterface resourceContext) { SubjectContext subjectContext = getSubjectContext(securityContext); subjectContext = changeSubjectContext(user, subjectContext); - - if (subjectContext.isAdmin() || subjectContext.isBot()) { - // Admins and bots have permissions to do all operations. - return PolicyEvaluator.getResourcePermission(resourceContext.getResource(), Access.ALLOW); - } - return PolicyEvaluator.getPermission(subjectContext, resourceContext); + return subjectContext.isAdmin() + ? PolicyEvaluator.getResourcePermission(resourceContext.getResource(), ALLOW) // Admin all permissions + : PolicyEvaluator.getPermission(subjectContext, resourceContext); } @Override diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/security/policyevaluator/PolicyEvaluator.java b/openmetadata-service/src/main/java/org/openmetadata/service/security/policyevaluator/PolicyEvaluator.java index 84418ba8b95..e53e8c4e64d 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/security/policyevaluator/PolicyEvaluator.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/security/policyevaluator/PolicyEvaluator.java @@ -24,6 +24,7 @@ import lombok.NonNull; import lombok.extern.slf4j.Slf4j; import org.openmetadata.schema.entity.policies.Policy; import org.openmetadata.schema.entity.policies.accessControl.Rule; +import org.openmetadata.schema.type.EntityReference; import org.openmetadata.schema.type.MetadataOperation; import org.openmetadata.schema.type.Permission; import org.openmetadata.schema.type.Permission.Access; @@ -33,6 +34,7 @@ import org.openmetadata.service.ResourceRegistry; import org.openmetadata.service.exception.CatalogExceptionMessage; import org.openmetadata.service.security.AuthorizationException; import org.openmetadata.service.security.policyevaluator.SubjectContext.PolicyContext; +import org.openmetadata.service.security.policyevaluator.SubjectContext.PolicyIterator; /** * PolicyEvaluator for {@link MetadataOperation metadata operations} based on OpenMetadata's internal {@link Policy} @@ -155,6 +157,20 @@ public class PolicyEvaluator { return new ArrayList<>(resourcePermissionMap.values()); } + /** Returns a list of operations that a user can perform on all the resources. */ + public static List listPermission(@NonNull List policies) { + Map resourcePermissionMap = initResourcePermissions(); + PolicyIterator policyIterator = new PolicyIterator("", "", null, policies); + while (policyIterator.hasNext()) { + PolicyContext policyContext = policyIterator.next(); + for (CompiledRule rule : policyContext.getRules()) { + LOG.debug("Evaluating {}:{}:{}\n", policyContext.getRoleName(), policyContext.getPolicyName(), rule.getName()); + rule.setPermission(resourcePermissionMap, policyContext); + } + } + return new ArrayList<>(resourcePermissionMap.values()); + } + /** Returns a list of operations that a user can perform on the given resource/entity type */ public static ResourcePermission getPermission(@NonNull SubjectContext subjectContext, String resourceType) { // Initialize all permissions to NOT_ALLOW diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/security/policyevaluator/SubjectContext.java b/openmetadata-service/src/main/java/org/openmetadata/service/security/policyevaluator/SubjectContext.java index 2765d3b3cb5..1762350b96e 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/security/policyevaluator/SubjectContext.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/security/policyevaluator/SubjectContext.java @@ -141,11 +141,11 @@ public class SubjectContext { private int policyIndex = 0; private final List policies; - PolicyIterator(String entityType, String entityName, String roleName, List policy) { + PolicyIterator(String entityType, String entityName, String roleName, List policies) { this.entityType = entityType; this.entityName = entityName; this.roleName = roleName; - this.policies = listOrEmpty(policy); + this.policies = listOrEmpty(policies); } @Override diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/util/EntityUtil.java b/openmetadata-service/src/main/java/org/openmetadata/service/util/EntityUtil.java index c7cac036356..7d5a0375f9a 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/util/EntityUtil.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/util/EntityUtil.java @@ -28,7 +28,6 @@ import java.util.Optional; import java.util.UUID; import java.util.function.BiPredicate; import java.util.regex.Pattern; -import java.util.stream.Collectors; import javax.ws.rs.WebApplicationException; import lombok.Getter; import lombok.NonNull; @@ -222,14 +221,10 @@ public final class EntityUtil { return refs; } - public static List populateEntityReferencesById(List ids, @NonNull String entityType) + public static List populateEntityReferencesById(List list, String entityType) throws IOException { - List refs = new ArrayList<>(ids.size()); - for (String id : ids) { - refs.add(Entity.getEntityReferenceById(entityType, UUID.fromString(id), ALL)); - } - refs.sort(compareEntityReference); - return refs; + List refs = toEntityReferences(list, entityType); + return populateEntityReferences(refs); } public static EntityReference validateEntityLink(EntityLink entityLink) { @@ -285,6 +280,12 @@ public final class EntityUtil { return entityReferences; } + public static List toIDs(List list) { + List ids = new ArrayList<>(list.size()); + list.forEach(entry -> ids.add(UUID.fromString(entry))); + return ids; + } + public static List toEntityReferences(List ids, String entityType) { if (ids == null) { return null; @@ -339,13 +340,6 @@ public final class EntityUtil { } } - public static List getIDList(List refList) { - if (refList == null) { - return Collections.emptyList(); - } - return refList.stream().sorted(compareEntityReference).map(EntityReference::getId).collect(Collectors.toList()); - } - /** Entity version extension name formed by entityType.version.versionNumber. Example - `table.version.0.1` */ public static String getVersionExtension(String entityType, Double version) { return String.format("%s.%s", getVersionExtensionPrefix(entityType), version.toString()); diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/resources/permissions/PermissionsResourceTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/resources/permissions/PermissionsResourceTest.java index 00d25671815..267116b045f 100644 --- a/openmetadata-service/src/test/java/org/openmetadata/service/resources/permissions/PermissionsResourceTest.java +++ b/openmetadata-service/src/test/java/org/openmetadata/service/resources/permissions/PermissionsResourceTest.java @@ -37,6 +37,7 @@ import static org.openmetadata.service.util.TestUtils.assertResponse; import java.io.IOException; import java.net.URISyntaxException; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; @@ -78,12 +79,33 @@ class PermissionsResourceTest extends OpenMetadataApplicationTest { private static List ORG_RULES; private static final String DATA_STEWARD_ROLE_NAME = "DataSteward"; + private static Policy DATA_STEWARD_POLICY; private static final String DATA_STEWARD_POLICY_NAME = "DataStewardPolicy"; private static List DATA_STEWARD_RULES; private static final String DATA_CONSUMER_ROLE_NAME = "DataConsumer"; + private static Policy DATA_CONSUMER_POLICY; private static final String DATA_CONSUMER_POLICY_NAME = "DataConsumerPolicy"; private static List DATA_CONSUMER_RULES; + private static List DATA_CONSUMER_ALLOWED = + List.of( + VIEW_ALL, + VIEW_BASIC, + VIEW_USAGE, + VIEW_DATA_PROFILE, + VIEW_SAMPLE_DATA, + VIEW_BASIC, + VIEW_TESTS, + VIEW_QUERIES, + EDIT_DESCRIPTION, + EDIT_TAGS); + + private static List DATA_STEWARD_ALLOWED = new ArrayList<>(DATA_CONSUMER_ALLOWED); + + static { + // Additional permissions over DATA_CONSUMER + DATA_STEWARD_ALLOWED.addAll(List.of(EDIT_OWNER, EDIT_DISPLAY_NAME, EDIT_LINEAGE)); + } private static final String DATA_STEWARD_USER_NAME = "user-data-steward"; private static User DATA_STEWARD_USER; @@ -95,13 +117,9 @@ class PermissionsResourceTest extends OpenMetadataApplicationTest { new TableResourceTest().setup(test); PolicyResourceTest policyResourceTest = new PolicyResourceTest(); - Policy ORG_POLICY = + Policy orgPolicy = policyResourceTest.getEntityByName(ORG_POLICY_NAME, null, PolicyResource.FIELDS, ADMIN_AUTH_HEADERS); - ORG_RULES = ORG_POLICY.getRules(); - - Policy DATA_STEWARD_POLICY = - policyResourceTest.getEntityByName(DATA_STEWARD_POLICY_NAME, null, PolicyResource.FIELDS, ADMIN_AUTH_HEADERS); - DATA_STEWARD_RULES = DATA_STEWARD_POLICY.getRules(); + ORG_RULES = orgPolicy.getRules(); DATA_STEWARD_POLICY = policyResourceTest.getEntityByName(DATA_STEWARD_POLICY_NAME, null, PolicyResource.FIELDS, ADMIN_AUTH_HEADERS); @@ -109,7 +127,7 @@ class PermissionsResourceTest extends OpenMetadataApplicationTest { DATA_STEWARD_USER = EntityResourceTest.USER_WITH_DATA_STEWARD_ROLE; - Policy DATA_CONSUMER_POLICY = + DATA_CONSUMER_POLICY = policyResourceTest.getEntityByName(DATA_CONSUMER_POLICY_NAME, null, PolicyResource.FIELDS, ADMIN_AUTH_HEADERS); DATA_CONSUMER_RULES = DATA_CONSUMER_POLICY.getRules(); @@ -129,12 +147,14 @@ class PermissionsResourceTest extends OpenMetadataApplicationTest { @Test void get_admin_permissions() throws HttpResponseException { + // Ensure an admin has all the permissions List actualPermissions = getPermissions(ADMIN_AUTH_HEADERS); assertEquals(PolicyEvaluator.getResourcePermissions(ALLOW), actualPermissions); } @Test void get_dataConsumer_permissions() throws HttpResponseException { + // Ensure data consumer has permissions based on his role and the inherited roles List conditional = List.of(ALL); // All operations are conditionally allowed // Validate permissions for all resources as logged-in user @@ -142,7 +162,7 @@ class PermissionsResourceTest extends OpenMetadataApplicationTest { List actualPermissions = getPermissions(authHeaders); assertDataConsumerPermissions(actualPermissions, conditional); - // Validate permissions for DATA_CONSUMER_USER as admin and validate it + // Validate permissions for all resources for data consumer as admin actualPermissions = getPermissions(DATA_CONSUMER_USER_NAME, ADMIN_AUTH_HEADERS); assertDataConsumerPermissions(actualPermissions, conditional); @@ -152,7 +172,7 @@ class PermissionsResourceTest extends OpenMetadataApplicationTest { assertDataConsumerPermission(actualPermission, conditional); } - // Validate permission as admin user for each resource one at a time + // Validate permission of data consumer as admin user for each resource one at a time for (ResourceDescriptor rd : ResourceRegistry.listResourceDescriptors()) { ResourcePermission actualPermission = getPermission(rd.getName(), DATA_CONSUMER_USER_NAME, authHeaders); assertDataConsumerPermission(actualPermission, conditional); @@ -194,6 +214,58 @@ class PermissionsResourceTest extends OpenMetadataApplicationTest { assertDataConsumerPermission(actualPermission, Collections.emptyList()); } + @Test + void get_dataSteward_permissions() throws HttpResponseException { + Map authHeaders = SecurityUtil.authHeaders(DATA_STEWARD_USER_NAME + "@open-metadata.org"); + List actualPermissions = getPermissions(authHeaders); + + for (ResourcePermission actualPermission : actualPermissions) { // For all resources + assertDataStewardPermission(actualPermission); + } + } + + @Test + void get_policyPermissions() throws HttpResponseException { + // Get permissions for DATA_CONSUMER policy and assert it is correct + List policies = new ArrayList<>(List.of(DATA_CONSUMER_POLICY.getId())); + List actual = getPermissionsForPolicies(policies, ADMIN_AUTH_HEADERS); + for (ResourcePermission actualPermission : actual) { // For every resource + for (Permission permission : actualPermission.getPermissions()) { + if (DATA_CONSUMER_ALLOWED.contains(permission.getOperation())) { + assertPermissionAllowed(permission, null, DATA_CONSUMER_POLICY_NAME, DATA_CONSUMER_RULES); + } else { + assertPermissionNotAllowed(permission); + } + } + } + + // Get permissions for DATA_CONSUMER and DATA_STEWARD policies and assert it is correct + policies.add(DATA_STEWARD_POLICY.getId()); + actual = getPermissionsForPolicies(policies, ADMIN_AUTH_HEADERS); + for (ResourcePermission actualPermission : actual) { // For every resource + for (Permission permission : actualPermission.getPermissions()) { + if (DATA_CONSUMER_ALLOWED.contains(permission.getOperation())) { + assertPermissionAllowed(permission, null, DATA_CONSUMER_POLICY_NAME, DATA_CONSUMER_RULES); + } else if (DATA_STEWARD_ALLOWED.contains(permission.getOperation())) { + assertPermissionAllowed(permission, null, DATA_STEWARD_POLICY_NAME, DATA_STEWARD_RULES); + } else { + assertPermissionNotAllowed(permission); + } + } + } + } + + private void assertDataStewardPermission(ResourcePermission actualPermission) { + // Only allowed operations in DataConsumerRole. All other operations are conditionalAllow by default + for (Permission permission : actualPermission.getPermissions()) { + if (DATA_STEWARD_ALLOWED.contains(permission.getOperation())) { + assertPermissionAllowed(permission, DATA_STEWARD_ROLE_NAME, DATA_STEWARD_POLICY_NAME, DATA_STEWARD_RULES); + } else { + assertPermissionConditional(permission, null, ORG_POLICY_NAME, ORG_RULES); + } + } + } + private void assertAllOperationsAllowed(ResourcePermission actualPermission) { assertEquals(Entity.TABLE, actualPermission.getResource()); for (Permission permission : actualPermission.getPermissions()) { @@ -205,70 +277,36 @@ class PermissionsResourceTest extends OpenMetadataApplicationTest { private void assertDataConsumerPermissions( List actualPermissions, List conditional) { // Only allowed operations in DataConsumerRole. All other operations are notAllow by default - for (ResourcePermission actualPermission : actualPermissions) { // For all resources - assertDataConsumerPermission(actualPermission, conditional); + for (ResourcePermission actualPermission : actualPermissions) { // For every resource + assertDataConsumerPermission(actualPermission, conditional); // assert permission } } private void assertDataConsumerPermission(ResourcePermission actualPermission, List conditional) { - List allowed = - List.of( - VIEW_ALL, - VIEW_BASIC, - VIEW_USAGE, - VIEW_DATA_PROFILE, - VIEW_SAMPLE_DATA, - VIEW_BASIC, - VIEW_TESTS, - VIEW_QUERIES, - EDIT_DESCRIPTION, - EDIT_TAGS); - // Only allowed operations in DataConsumerRole. All other operations are conditional allow or not allow for (Permission permission : actualPermission.getPermissions()) { - if (allowed.contains(permission.getOperation())) { - assertPermission(permission, ALLOW, DATA_CONSUMER_ROLE_NAME, DATA_CONSUMER_POLICY_NAME, DATA_CONSUMER_RULES); + if (DATA_CONSUMER_ALLOWED.contains(permission.getOperation())) { + assertPermissionAllowed(permission, DATA_CONSUMER_ROLE_NAME, DATA_CONSUMER_POLICY_NAME, DATA_CONSUMER_RULES); } else if (conditional.contains(permission.getOperation()) || conditional.contains(ALL)) { - assertPermission(permission, CONDITIONAL_ALLOW, null, ORG_POLICY_NAME, ORG_RULES); + assertPermissionConditional(permission, null, ORG_POLICY_NAME, ORG_RULES); } else { - assertPermission(permission, NOT_ALLOW, null, null, null); + assertPermissionNotAllowed(permission); } } } - @Test - void get_dataSteward_permissions() throws HttpResponseException { - Map authHeaders = SecurityUtil.authHeaders(DATA_STEWARD_USER_NAME + "@open-metadata.org"); - List actualPermissions = getPermissions(authHeaders); - - for (ResourcePermission actualPermission : actualPermissions) { // For all resources - assertDataStewardPermission(actualPermission); - } + private void assertPermissionAllowed( + Permission permission, String expectedRole, String expectedPolicy, List expectedRules) { + assertPermission(permission, ALLOW, expectedRole, expectedPolicy, expectedRules); } - private void assertDataStewardPermission(ResourcePermission actualPermission) { - // Only allowed operations in DataConsumerRole. All other operations are conditionalAllow by default - List allowed = - List.of( - VIEW_ALL, - VIEW_BASIC, - VIEW_USAGE, - VIEW_DATA_PROFILE, - VIEW_SAMPLE_DATA, - VIEW_TESTS, - VIEW_QUERIES, - EDIT_OWNER, - EDIT_DISPLAY_NAME, - EDIT_LINEAGE, - EDIT_DESCRIPTION, - EDIT_TAGS); - for (Permission permission : actualPermission.getPermissions()) { - if (allowed.contains(permission.getOperation())) { - assertPermission(permission, ALLOW, DATA_STEWARD_ROLE_NAME, DATA_STEWARD_POLICY_NAME, DATA_STEWARD_RULES); - } else { - assertPermission(permission, CONDITIONAL_ALLOW, null, ORG_POLICY_NAME, ORG_RULES); - } - } + private void assertPermissionConditional( + Permission permission, String expectedRole, String expectedPolicy, List expectedRules) { + assertPermission(permission, CONDITIONAL_ALLOW, expectedRole, expectedPolicy, expectedRules); + } + + private void assertPermissionNotAllowed(Permission permission) { + assertPermission(permission, NOT_ALLOW, null, null, null); } private void assertPermission( @@ -315,4 +353,13 @@ class PermissionsResourceTest extends OpenMetadataApplicationTest { target = user != null ? target.queryParam("user", user) : target; return TestUtils.get(target, ResourcePermission.class, authHeaders); } + + public List getPermissionsForPolicies(List policyIds, Map authHeaders) + throws HttpResponseException { + WebTarget target = getResource("permissions/policies"); + for (UUID policyId : policyIds) { + target = target.queryParam("ids", policyId); + } + return TestUtils.get(target, ResourcePermissionList.class, authHeaders).getData(); + } }