mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-09-04 22:53:27 +00:00
This commit is contained in:
parent
4dad80e2fe
commit
263da23220
@ -108,7 +108,6 @@ public final class Entity {
|
||||
public static final String TEST_DEFINITION = "testDefinition";
|
||||
public static final String TEST_CONNECTION_DEFINITION = "testConnectionDefinition";
|
||||
public static final String WORKFLOW = "workflow";
|
||||
public static final String ALERT_ACTION = "alertAction";
|
||||
public static final String TEST_SUITE = "testSuite";
|
||||
public static final String KPI = "kpi";
|
||||
public static final String TEST_CASE = "testCase";
|
||||
@ -290,7 +289,6 @@ public final class Entity {
|
||||
|
||||
/** Retrieve the corresponding entity repository for a given entity name. */
|
||||
public static EntityRepository<? extends EntityInterface> getEntityRepository(@NonNull String entityType) {
|
||||
@SuppressWarnings("unchecked")
|
||||
EntityRepository<? extends EntityInterface> entityRepository = ENTITY_REPOSITORY_MAP.get(entityType);
|
||||
if (entityRepository == null) {
|
||||
throw EntityNotFoundException.byMessage(CatalogExceptionMessage.entityTypeNotFound(entityType));
|
||||
@ -301,7 +299,6 @@ public final class Entity {
|
||||
/** Retrieve the corresponding entity repository for a given entity name. */
|
||||
public static EntityRepository<? extends EntityInterface> getServiceEntityRepository(
|
||||
@NonNull ServiceType serviceType) {
|
||||
@SuppressWarnings("unchecked")
|
||||
EntityRepository<? extends EntityInterface> entityRepository =
|
||||
ENTITY_REPOSITORY_MAP.get(SERVICE_TYPE_ENTITY_MAP.get(serviceType));
|
||||
if (entityRepository == null) {
|
||||
|
@ -47,6 +47,7 @@ import org.openmetadata.service.exception.CatalogExceptionMessage;
|
||||
import org.openmetadata.service.jdbi3.CollectionDAO.EntityRelationshipRecord;
|
||||
import org.openmetadata.service.resources.policies.PolicyResource;
|
||||
import org.openmetadata.service.security.policyevaluator.CompiledRule;
|
||||
import org.openmetadata.service.security.policyevaluator.PolicyCache;
|
||||
import org.openmetadata.service.util.EntityUtil;
|
||||
import org.openmetadata.service.util.EntityUtil.Fields;
|
||||
|
||||
@ -118,6 +119,9 @@ public class PolicyRepository extends EntityRepository<Policy> {
|
||||
EntityReference location = policy.getLocation();
|
||||
policy.withLocation(null);
|
||||
store(policy, update);
|
||||
if (update) {
|
||||
PolicyCache.getInstance().invalidatePolicy(policy.getId());
|
||||
}
|
||||
policy.withLocation(location);
|
||||
}
|
||||
|
||||
@ -142,6 +146,12 @@ public class PolicyRepository extends EntityRepository<Policy> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void cleanup(Policy policy) throws IOException {
|
||||
super.cleanup(policy);
|
||||
PolicyCache.getInstance().invalidatePolicy(policy.getId());
|
||||
}
|
||||
|
||||
public void validateRules(Policy policy) {
|
||||
// Resolve JSON blobs into Rule object and perform schema based validation
|
||||
List<Rule> rules = policy.getRules();
|
||||
|
@ -32,6 +32,7 @@ import org.openmetadata.service.Entity;
|
||||
import org.openmetadata.service.exception.CatalogExceptionMessage;
|
||||
import org.openmetadata.service.jdbi3.CollectionDAO.EntityRelationshipRecord;
|
||||
import org.openmetadata.service.resources.teams.RoleResource;
|
||||
import org.openmetadata.service.security.policyevaluator.RoleCache;
|
||||
import org.openmetadata.service.util.EntityUtil;
|
||||
import org.openmetadata.service.util.EntityUtil.Fields;
|
||||
|
||||
@ -94,6 +95,9 @@ public class RoleRepository extends EntityRepository<Role> {
|
||||
List<EntityReference> policies = role.getPolicies();
|
||||
role.withPolicies(null);
|
||||
store(role, update);
|
||||
if (update) {
|
||||
RoleCache.getInstance().invalidateRole(role.getId());
|
||||
}
|
||||
role.withPolicies(policies);
|
||||
}
|
||||
|
||||
@ -117,6 +121,12 @@ public class RoleRepository extends EntityRepository<Role> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void cleanup(Role role) throws IOException {
|
||||
super.cleanup(role);
|
||||
RoleCache.getInstance().invalidateRole(role.getId());
|
||||
}
|
||||
|
||||
/** Handles entity updated from PUT and POST operation. */
|
||||
public class RoleUpdater extends EntityUpdater {
|
||||
public RoleUpdater(Role original, Role updated, Operation operation) {
|
||||
|
@ -132,6 +132,9 @@ public class TeamRepository extends EntityRepository<Team> {
|
||||
team.withUsers(null).withDefaultRoles(null).withInheritedRoles(null);
|
||||
|
||||
store(team, update);
|
||||
if (update) {
|
||||
SubjectCache.getInstance().invalidateTeam(team.getId());
|
||||
}
|
||||
|
||||
// Restore the relationships
|
||||
team.withUsers(users)
|
||||
|
@ -120,6 +120,9 @@ public class UserRepository extends EntityRepository<User> {
|
||||
}
|
||||
|
||||
store(user, update);
|
||||
if (update) {
|
||||
SubjectCache.getInstance().invalidateUser(user.getName());
|
||||
}
|
||||
|
||||
// Restore the relationships
|
||||
user.withRoles(roles).withTeams(teams);
|
||||
@ -142,6 +145,12 @@ public class UserRepository extends EntityRepository<User> {
|
||||
SubjectCache.getInstance().invalidateUser(entity.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void cleanup(User user) throws IOException {
|
||||
super.cleanup(user);
|
||||
SubjectCache.getInstance().invalidateUser(user.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public User setFields(User user, Fields fields) throws IOException {
|
||||
user.setProfile(fields.contains("profile") ? user.getProfile() : null);
|
||||
|
@ -300,7 +300,6 @@ public abstract class EntityResource<T extends EntityInterface, K extends Entity
|
||||
public static final MetadataOperation[] VIEW_ALL_OPERATIONS = {MetadataOperation.VIEW_ALL};
|
||||
|
||||
protected MetadataOperation[] getViewOperations(Fields fields) {
|
||||
|
||||
return VIEW_ALL_OPERATIONS;
|
||||
}
|
||||
|
||||
|
@ -370,10 +370,7 @@ public class PolicyResource extends EntityResource<Policy, PolicyRepository> {
|
||||
}))
|
||||
JsonPatch patch)
|
||||
throws IOException {
|
||||
Response response = patchInternal(uriInfo, securityContext, id, patch);
|
||||
Policy policy = (Policy) response.getEntity();
|
||||
PolicyCache.getInstance().invalidatePolicy(policy.getId());
|
||||
return response;
|
||||
return patchInternal(uriInfo, securityContext, id, patch);
|
||||
}
|
||||
|
||||
@PUT
|
||||
@ -393,9 +390,7 @@ public class PolicyResource extends EntityResource<Policy, PolicyRepository> {
|
||||
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreatePolicy create)
|
||||
throws IOException {
|
||||
Policy policy = getPolicy(create, securityContext.getUserPrincipal().getName());
|
||||
Response response = createOrUpdate(uriInfo, securityContext, policy);
|
||||
PolicyCache.getInstance().invalidatePolicy(policy.getId());
|
||||
return response;
|
||||
return createOrUpdate(uriInfo, securityContext, policy);
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@ -418,9 +413,7 @@ public class PolicyResource extends EntityResource<Policy, PolicyRepository> {
|
||||
boolean hardDelete,
|
||||
@Parameter(description = "Id of the policy", schema = @Schema(type = "UUID")) @PathParam("id") UUID id)
|
||||
throws IOException {
|
||||
Response response = delete(uriInfo, securityContext, id, false, hardDelete);
|
||||
PolicyCache.getInstance().invalidatePolicy(id);
|
||||
return response;
|
||||
return delete(uriInfo, securityContext, id, false, hardDelete);
|
||||
}
|
||||
|
||||
@DELETE
|
||||
|
@ -323,9 +323,7 @@ public class RoleResource extends EntityResource<Role, RoleRepository> {
|
||||
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateRole createRole)
|
||||
throws IOException {
|
||||
Role role = getRole(createRole, securityContext.getUserPrincipal().getName());
|
||||
Response response = createOrUpdate(uriInfo, securityContext, role);
|
||||
RoleCache.getInstance().invalidateRole(role.getId());
|
||||
return response;
|
||||
return createOrUpdate(uriInfo, securityContext, role);
|
||||
}
|
||||
|
||||
@PATCH
|
||||
@ -351,10 +349,7 @@ public class RoleResource extends EntityResource<Role, RoleRepository> {
|
||||
}))
|
||||
JsonPatch patch)
|
||||
throws IOException {
|
||||
Response response = patchInternal(uriInfo, securityContext, id, patch);
|
||||
Role role = (Role) response.getEntity();
|
||||
RoleCache.getInstance().invalidateRole(role.getId());
|
||||
return response;
|
||||
return patchInternal(uriInfo, securityContext, id, patch);
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@ -379,9 +374,7 @@ public class RoleResource extends EntityResource<Role, RoleRepository> {
|
||||
throws IOException {
|
||||
// A role has a strong relationship with a policy. Recursively delete the policy that the role contains, to avoid
|
||||
// leaving a dangling policy without a role.
|
||||
Response response = delete(uriInfo, securityContext, id, true, hardDelete);
|
||||
RoleCache.getInstance().invalidateRole(id);
|
||||
return response;
|
||||
return delete(uriInfo, securityContext, id, true, hardDelete);
|
||||
}
|
||||
|
||||
@DELETE
|
||||
|
@ -27,7 +27,7 @@ public class ResourceContext implements ResourceContextInterface {
|
||||
@NonNull private EntityRepository<? extends EntityInterface> entityRepository;
|
||||
private UUID id;
|
||||
private String name;
|
||||
@Getter private EntityInterface entity; // Will be lazily initialized
|
||||
private EntityInterface entity; // Will be lazily initialized
|
||||
|
||||
// Builder class added for getting around javadoc errors. This class will be filled in by lombok.
|
||||
public static class ResourceContextBuilder {}
|
||||
@ -41,7 +41,7 @@ public class ResourceContext implements ResourceContextInterface {
|
||||
@Override
|
||||
public List<TagLabel> getTags() throws IOException {
|
||||
resolveEntity();
|
||||
return entity == null ? Collections.EMPTY_LIST : Entity.getEntityTags(getResource(), entity);
|
||||
return entity == null ? Collections.emptyList() : Entity.getEntityTags(getResource(), entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -223,7 +223,7 @@ public class SubjectContext {
|
||||
this.user = user;
|
||||
|
||||
// Iterate over policies in user role
|
||||
if (user.getRoles() != null) {
|
||||
if (!listOrEmpty(user.getRoles()).isEmpty()) {
|
||||
iterators.add(new RolePolicyIterator(Entity.USER, user.getName(), user.getRoles()));
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,6 @@ import static org.openmetadata.common.utils.CommonUtil.listOrEmpty;
|
||||
import static org.openmetadata.csv.EntityCsvTest.assertSummary;
|
||||
import static org.openmetadata.schema.type.MetadataOperation.EDIT_ALL;
|
||||
import static org.openmetadata.schema.type.MetadataOperation.EDIT_TESTS;
|
||||
import static org.openmetadata.schema.type.MetadataOperation.VIEW_ALL;
|
||||
import static org.openmetadata.service.Entity.ADMIN_USER_NAME;
|
||||
import static org.openmetadata.service.Entity.FIELD_DELETED;
|
||||
import static org.openmetadata.service.Entity.FIELD_EXTENSION;
|
||||
@ -40,7 +39,6 @@ import static org.openmetadata.service.Entity.FIELD_TAGS;
|
||||
import static org.openmetadata.service.exception.CatalogExceptionMessage.ENTITY_ALREADY_EXISTS;
|
||||
import static org.openmetadata.service.exception.CatalogExceptionMessage.entityIsNotEmpty;
|
||||
import static org.openmetadata.service.exception.CatalogExceptionMessage.entityNotFound;
|
||||
import static org.openmetadata.service.exception.CatalogExceptionMessage.permissionDenied;
|
||||
import static org.openmetadata.service.exception.CatalogExceptionMessage.permissionNotAllowed;
|
||||
import static org.openmetadata.service.exception.CatalogExceptionMessage.readOnlyAttribute;
|
||||
import static org.openmetadata.service.security.SecurityUtil.authHeaders;
|
||||
@ -1616,61 +1614,6 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr
|
||||
"Invalid entity invalidEntity in query param entityDeleted");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Execution(ExecutionMode.CONCURRENT)
|
||||
protected void testTeamOnlyPolicy(TestInfo test) throws HttpResponseException {
|
||||
testTeamOnlyPolicy(test, VIEW_ALL);
|
||||
}
|
||||
|
||||
protected void testTeamOnlyPolicy(TestInfo test, MetadataOperation disallowedOperation) throws HttpResponseException {
|
||||
if (!supportsOwner) {
|
||||
return;
|
||||
}
|
||||
// TEAM2 allows operations on its entities to users only with in that team due to team only policy attached to it
|
||||
// Create an entity owned by TEAM21
|
||||
K createRequest = createRequest("teamOnlyPolicyTest", "", "", TEAM21.getEntityReference());
|
||||
T entity = createEntity(createRequest, ADMIN_AUTH_HEADERS);
|
||||
UserResourceTest userResourceTest = new UserResourceTest();
|
||||
User userInTeam21 =
|
||||
userResourceTest.createEntity(
|
||||
userResourceTest.createRequest(test, 21).withTeams(List.of(TEAM21.getId())), ADMIN_AUTH_HEADERS);
|
||||
User userInTeam2 =
|
||||
userResourceTest.createEntity(
|
||||
userResourceTest.createRequest(test, 2).withTeams(List.of(TEAM2.getId())), ADMIN_AUTH_HEADERS);
|
||||
User userInTeam11 =
|
||||
userResourceTest.createEntity(
|
||||
userResourceTest.createRequest(test, 11).withTeams(List.of(TEAM11.getId())), ADMIN_AUTH_HEADERS);
|
||||
User userInTeam1 =
|
||||
userResourceTest.createEntity(
|
||||
userResourceTest.createRequest(test, 1).withTeams(List.of(TEAM1.getId())), ADMIN_AUTH_HEADERS);
|
||||
|
||||
// users in team21 and team2 have all the operations allowed
|
||||
T getEntity = getEntity(entity.getId(), authHeaders(userInTeam21.getName()));
|
||||
assertEquals(getEntity.getId(), entity.getId());
|
||||
getEntity = getEntity(entity.getId(), authHeaders(userInTeam2.getName()));
|
||||
assertEquals(getEntity.getId(), entity.getId());
|
||||
|
||||
// users in team11 and team12 have all the operations denied due to Team2 team only policy
|
||||
assertResponse(
|
||||
() -> getEntity(entity.getId(), authHeaders(userInTeam11.getName())),
|
||||
FORBIDDEN,
|
||||
permissionDenied(
|
||||
userInTeam11.getName(),
|
||||
disallowedOperation,
|
||||
null,
|
||||
TEAM_ONLY_POLICY.getName(),
|
||||
TEAM_ONLY_POLICY_RULES.get(0).getName()));
|
||||
assertResponse(
|
||||
() -> getEntity(entity.getId(), authHeaders(userInTeam1.getName())),
|
||||
FORBIDDEN,
|
||||
permissionDenied(
|
||||
userInTeam1.getName(),
|
||||
disallowedOperation,
|
||||
null,
|
||||
TEAM_ONLY_POLICY.getName(),
|
||||
TEAM_ONLY_POLICY_RULES.get(0).getName()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Execution(ExecutionMode.CONCURRENT)
|
||||
void delete_systemEntity() throws IOException {
|
||||
|
@ -8,7 +8,6 @@ import static javax.ws.rs.core.Response.Status.OK;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.openmetadata.schema.type.MetadataOperation.EDIT_TESTS;
|
||||
import static org.openmetadata.schema.type.MetadataOperation.VIEW_TESTS;
|
||||
import static org.openmetadata.service.Entity.ADMIN_USER_NAME;
|
||||
import static org.openmetadata.service.exception.CatalogExceptionMessage.permissionNotAllowed;
|
||||
import static org.openmetadata.service.security.SecurityUtil.authHeaders;
|
||||
@ -26,7 +25,6 @@ import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.util.*;
|
||||
import javax.ws.rs.client.WebTarget;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.http.client.HttpResponseException;
|
||||
import org.junit.jupiter.api.MethodOrderer;
|
||||
@ -130,26 +128,6 @@ public class TestCaseResourceTest extends EntityResourceTest<TestCase, CreateTes
|
||||
patchEntityAndCheckAuthorization(entity, USER2.getName(), EDIT_TESTS, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Test
|
||||
@SneakyThrows
|
||||
protected void testTeamOnlyPolicy(TestInfo test) {
|
||||
// Testcase's are authorized based on the ownership of the entity to which testcases are attached to
|
||||
// Change the TABLE1 ownership to Team21 and then change it back to USER1
|
||||
// Set the owner for the entity
|
||||
TableResourceTest tableResourceTest = new TableResourceTest();
|
||||
String originalJson = JsonUtils.pojoToJson(TEST_TABLE1);
|
||||
TEST_TABLE1.setOwner(TEAM21.getEntityReference());
|
||||
TEST_TABLE1 = tableResourceTest.patchEntity(TEST_TABLE1.getId(), originalJson, TEST_TABLE1, ADMIN_AUTH_HEADERS);
|
||||
|
||||
super.testTeamOnlyPolicy(test, VIEW_TESTS);
|
||||
|
||||
// Revert the ownership back
|
||||
originalJson = JsonUtils.pojoToJson(TEST_TABLE1);
|
||||
TEST_TABLE1.setOwner(USER1_REF);
|
||||
TEST_TABLE1 = tableResourceTest.patchEntity(TEST_TABLE1.getId(), originalJson, TEST_TABLE1, ADMIN_AUTH_HEADERS);
|
||||
}
|
||||
|
||||
@Test
|
||||
void post_testWithoutRequiredFields_4xx(TestInfo test) {
|
||||
// name is required field
|
||||
|
@ -13,16 +13,20 @@
|
||||
|
||||
package org.openmetadata.service.resources.policies;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
import static javax.ws.rs.core.Response.Status.BAD_REQUEST;
|
||||
import static javax.ws.rs.core.Response.Status.FORBIDDEN;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.openmetadata.common.utils.CommonUtil.listOf;
|
||||
import static org.openmetadata.schema.api.teams.CreateTeam.TeamType.DEPARTMENT;
|
||||
import static org.openmetadata.schema.entity.policies.accessControl.Rule.Effect.ALLOW;
|
||||
import static org.openmetadata.schema.entity.policies.accessControl.Rule.Effect.DENY;
|
||||
import static org.openmetadata.schema.type.MetadataOperation.EDIT_ALL;
|
||||
import static org.openmetadata.schema.type.MetadataOperation.VIEW_ALL;
|
||||
import static org.openmetadata.service.Entity.ALL_RESOURCES;
|
||||
import static org.openmetadata.service.Entity.FIELD_DESCRIPTION;
|
||||
import static org.openmetadata.service.security.SecurityUtil.authHeaders;
|
||||
import static org.openmetadata.service.util.EntityUtil.fieldAdded;
|
||||
import static org.openmetadata.service.util.EntityUtil.fieldDeleted;
|
||||
import static org.openmetadata.service.util.EntityUtil.fieldUpdated;
|
||||
@ -34,6 +38,7 @@ import static org.openmetadata.service.util.TestUtils.assertListNull;
|
||||
import static org.openmetadata.service.util.TestUtils.assertResponse;
|
||||
import static org.openmetadata.service.util.TestUtils.assertResponseContains;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
@ -48,15 +53,19 @@ import org.apache.http.client.HttpResponseException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestInfo;
|
||||
import org.openmetadata.schema.api.data.CreateLocation;
|
||||
import org.openmetadata.schema.api.data.CreateTable;
|
||||
import org.openmetadata.schema.api.policies.CreatePolicy;
|
||||
import org.openmetadata.schema.api.teams.CreateRole;
|
||||
import org.openmetadata.schema.api.teams.CreateTeam;
|
||||
import org.openmetadata.schema.api.teams.CreateUser;
|
||||
import org.openmetadata.schema.entity.data.Location;
|
||||
import org.openmetadata.schema.entity.data.Table;
|
||||
import org.openmetadata.schema.entity.policies.Policy;
|
||||
import org.openmetadata.schema.entity.policies.accessControl.Rule;
|
||||
import org.openmetadata.schema.entity.policies.accessControl.Rule.Effect;
|
||||
import org.openmetadata.schema.entity.teams.Role;
|
||||
import org.openmetadata.schema.entity.teams.Team;
|
||||
import org.openmetadata.schema.entity.teams.User;
|
||||
import org.openmetadata.schema.type.ChangeDescription;
|
||||
import org.openmetadata.schema.type.EntityReference;
|
||||
import org.openmetadata.schema.type.Function;
|
||||
@ -67,11 +76,13 @@ import org.openmetadata.service.FunctionList;
|
||||
import org.openmetadata.service.exception.CatalogExceptionMessage;
|
||||
import org.openmetadata.service.resources.CollectionRegistry;
|
||||
import org.openmetadata.service.resources.EntityResourceTest;
|
||||
import org.openmetadata.service.resources.databases.TableResourceTest;
|
||||
import org.openmetadata.service.resources.locations.LocationResourceTest;
|
||||
import org.openmetadata.service.resources.policies.PolicyResource.PolicyList;
|
||||
import org.openmetadata.service.resources.policies.PolicyResource.ResourceDescriptorList;
|
||||
import org.openmetadata.service.resources.teams.RoleResourceTest;
|
||||
import org.openmetadata.service.resources.teams.TeamResourceTest;
|
||||
import org.openmetadata.service.resources.teams.UserResourceTest;
|
||||
import org.openmetadata.service.security.policyevaluator.RuleEvaluator;
|
||||
import org.openmetadata.service.util.EntityUtil;
|
||||
import org.openmetadata.service.util.JsonUtils;
|
||||
@ -79,6 +90,8 @@ import org.openmetadata.service.util.TestUtils;
|
||||
|
||||
@Slf4j
|
||||
public class PolicyResourceTest extends EntityResourceTest<Policy, CreatePolicy> {
|
||||
public static TableResourceTest tableTest = new TableResourceTest();
|
||||
public static TeamResourceTest teamTest = new TeamResourceTest();
|
||||
|
||||
public PolicyResourceTest() {
|
||||
super(
|
||||
@ -381,12 +394,11 @@ public class PolicyResourceTest extends EntityResourceTest<Policy, CreatePolicy>
|
||||
policies.add(createEntity(create, ADMIN_AUTH_HEADERS));
|
||||
}
|
||||
|
||||
TeamResourceTest teamResourceTest = new TeamResourceTest();
|
||||
List<Team> teams = new ArrayList<>();
|
||||
for (int i = 0; i < 3; i++) {
|
||||
// Team X has Policy X
|
||||
CreateTeam createTeam = teamResourceTest.createRequest(test, i).withPolicies(List.of(policies.get(i).getId()));
|
||||
teams.add(teamResourceTest.createEntity(createTeam, ADMIN_AUTH_HEADERS));
|
||||
CreateTeam createTeam = teamTest.createRequest(test, i).withPolicies(List.of(policies.get(i).getId()));
|
||||
teams.add(teamTest.createEntity(createTeam, ADMIN_AUTH_HEADERS));
|
||||
}
|
||||
|
||||
// Create a role with all the policies
|
||||
@ -410,6 +422,132 @@ public class PolicyResourceTest extends EntityResourceTest<Policy, CreatePolicy>
|
||||
assertEquals(expectedFunctions, actualFunctions);
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_roles_policies_scenarios() throws HttpResponseException, JsonProcessingException {
|
||||
//
|
||||
// Create a team hierarchy:
|
||||
// - Organization has Team1 with user1 and Team2 with user2
|
||||
// - Team1 has Team11 with user11 and table11, and Team12 with user12 and table12
|
||||
// - Team2 has Team21 with user21 and Team22 with user22
|
||||
// - Team2 has DATA_STEWARD_ROLE which is inherited by user2, user21, and user22
|
||||
//
|
||||
CreateTeam createTeam = teamTest.createRequest("rolesPoliciesTeam1").withTeamType(DEPARTMENT);
|
||||
Team team1 = teamTest.createEntity(createTeam, ADMIN_AUTH_HEADERS);
|
||||
createTeam =
|
||||
teamTest
|
||||
.createRequest("rolesPoliciesTeam2")
|
||||
.withTeamType(DEPARTMENT)
|
||||
.withDefaultRoles(listOf(DATA_STEWARD_ROLE.getId()));
|
||||
Team team2 = teamTest.createEntity(createTeam, ADMIN_AUTH_HEADERS);
|
||||
createTeam = teamTest.createRequest("rolesPoliciesTeam11").withParents(listOf(team1.getId()));
|
||||
Team team11 = teamTest.createEntity(createTeam, ADMIN_AUTH_HEADERS);
|
||||
createTeam = teamTest.createRequest("rolesPoliciesTeam12").withParents(listOf(team1.getId()));
|
||||
Team team12 = teamTest.createEntity(createTeam, ADMIN_AUTH_HEADERS);
|
||||
createTeam = teamTest.createRequest("rolesPoliciesTeam21").withParents(listOf(team2.getId()));
|
||||
Team team21 = teamTest.createEntity(createTeam, ADMIN_AUTH_HEADERS);
|
||||
createTeam = teamTest.createRequest("rolesPoliciesTeam22").withParents(listOf(team2.getId()));
|
||||
Team team22 = teamTest.createEntity(createTeam, ADMIN_AUTH_HEADERS);
|
||||
|
||||
// Create users - Team2 has default role DataSteward
|
||||
UserResourceTest userTest = new UserResourceTest();
|
||||
CreateUser createUser = userTest.createRequest("rolesAndPoliciesUser1").withTeams(listOf(team1.getId()));
|
||||
User user1 = userTest.createEntity(createUser, ADMIN_AUTH_HEADERS);
|
||||
createUser = userTest.createRequest("rolesAndPoliciesUser2").withTeams(listOf(team2.getId()));
|
||||
User user2 = userTest.createEntity(createUser, ADMIN_AUTH_HEADERS);
|
||||
createUser = userTest.createRequest("rolesAndPoliciesUser11").withTeams(listOf(team11.getId()));
|
||||
User user11 = userTest.createEntity(createUser, ADMIN_AUTH_HEADERS);
|
||||
createUser = userTest.createRequest("rolesAndPoliciesUser12").withTeams(listOf(team12.getId()));
|
||||
User user12 = userTest.createEntity(createUser, ADMIN_AUTH_HEADERS);
|
||||
createUser = userTest.createRequest("rolesAndPoliciesUser21").withTeams(listOf(team21.getId()));
|
||||
User user21 = userTest.createEntity(createUser, ADMIN_AUTH_HEADERS);
|
||||
createUser = userTest.createRequest("rolesAndPoliciesUser22").withTeams(listOf(team22.getId()));
|
||||
User user22 = userTest.createEntity(createUser, ADMIN_AUTH_HEADERS);
|
||||
|
||||
// Create resources - table11 has PII sensitive tags
|
||||
CreateTable createTable =
|
||||
tableTest
|
||||
.createRequest("rolesAndPoliciesTable11")
|
||||
.withOwner(team11.getEntityReference())
|
||||
.withTags(listOf(PII_SENSITIVE_TAG_LABEL));
|
||||
Table table11 = tableTest.createEntity(createTable, ADMIN_AUTH_HEADERS);
|
||||
|
||||
// table12 does not have PII
|
||||
createTable = tableTest.createRequest("rolesAndPoliciesTable12").withOwner(team12.getEntityReference());
|
||||
createTable.getColumns().forEach(c -> c.withTags(null)); // Clear all the tag labels
|
||||
Table table12 = tableTest.createEntity(createTable, ADMIN_AUTH_HEADERS);
|
||||
|
||||
// Create policies
|
||||
Policy denyAllPIIAccess = createPolicy("disallowAllPIIAccess", "matchAnyTag('PII.Sensitive')");
|
||||
Policy denyPIIAccessExceptTeam11 =
|
||||
createPolicy("denyPIIAccessExceptTeam11", "matchAnyTag('PII.Sensitive') && !inAnyTeam('rolesPoliciesTeam11')");
|
||||
Policy denyPIIAccessExceptTeam1 =
|
||||
createPolicy("denyPIIAccessExceptTeam1", "matchAnyTag('PII.Sensitive') && !inAnyTeam('rolesPoliciesTeam1')");
|
||||
Policy denyPIIAccessExceptRole =
|
||||
createPolicy("denyPIIAccessExceptRole", "matchAnyTag('PII.Sensitive') && !hasAnyRole('DataSteward')");
|
||||
|
||||
// Array made of team, policy to attach to the team, allowed users list, denied users list, entity being accessed
|
||||
Object[][] scenarios = {
|
||||
// 0 - TEAM_ONLY_POLICY attached to team11. Only user11 in team11 has access
|
||||
{team11, TEAM_ONLY_POLICY, listOf(user11), listOf(user1, user2, user12, user21, user22), table11},
|
||||
// 1 - TEAM_ONLY_POLICY attached to team1. All the users under team1 have access
|
||||
{team1, TEAM_ONLY_POLICY, listOf(user1, user11, user12), listOf(user2, user21, user22), table11},
|
||||
// 2 - denyPIIAccess attached to team1. No users can access table11 that has PII
|
||||
{team1, denyAllPIIAccess, emptyList(), listOf(user1, user2, user11, user12, user21, user22), table11},
|
||||
// 3 - denyPIIAccess attached to team1. All users can access table12 that has no PII
|
||||
{team1, denyAllPIIAccess, listOf(user1, user11, user12, user2, user21, user22), emptyList(), table12},
|
||||
// 4 - denyPIIAccessExceptTeam11 attached to team1. Only Team11 users can access table11 with PII
|
||||
{team1, denyPIIAccessExceptTeam11, listOf(user11), listOf(user1, user2, user12, user21, user22), table11},
|
||||
// 5 - denyPIIAccessExceptTeam11 attached to team1. All users can access table12 that has no PII
|
||||
{team1, denyPIIAccessExceptTeam11, listOf(user1, user11, user12, user2, user21, user22), emptyList(), table12},
|
||||
// 6 - denyPIIAccessExceptTeam11 attached to team11. Only Team11 users can access table11 with PII
|
||||
{team11, denyPIIAccessExceptTeam11, listOf(user11), listOf(user1, user2, user12, user21, user22), table11},
|
||||
// 7 - denyPIIAccessExceptTeam11 attached to team11. All users can access table12 that has no PII
|
||||
{team11, denyPIIAccessExceptTeam11, listOf(user1, user11, user12, user2, user21, user22), emptyList(), table12},
|
||||
// 8 - denyPIIAccessExceptTeam1 attached to team1. Only Team1 users can access table11 with PII
|
||||
{team1, denyPIIAccessExceptTeam1, listOf(user1, user11, user12), listOf(user2, user21, user22), table11},
|
||||
// 9 - denyPIIAccessExceptTeam1 attached to team1. All users can access table12 that has no PII
|
||||
{team1, denyPIIAccessExceptTeam1, listOf(user1, user11, user12, user2, user21, user22), emptyList(), table12},
|
||||
// 10 - denyPIIAccessExceptRole attached to team1. Only user2, user21 and user22 with DataStewardRole can access
|
||||
{team1, denyPIIAccessExceptRole, listOf(user2, user21, user22), listOf(user1, user11, user12), table11},
|
||||
// 11- denyPIIAccessExceptRole attached to team1. All users can access table12 that has no PII
|
||||
{team1, denyPIIAccessExceptTeam1, listOf(user1, user11, user12, user2, user21, user22), emptyList(), table12},
|
||||
};
|
||||
for (int i = 0; i < scenarios.length; i++) {
|
||||
Object[] scenario = scenarios[i];
|
||||
testScenario(i, scenario);
|
||||
}
|
||||
}
|
||||
|
||||
private Policy createPolicy(String name, String condition) throws HttpResponseException {
|
||||
Rule rule =
|
||||
new Rule()
|
||||
.withName(name)
|
||||
.withResources(listOf(ALL_RESOURCES))
|
||||
.withOperations(listOf(MetadataOperation.ALL))
|
||||
.withEffect(DENY)
|
||||
.withCondition(condition);
|
||||
CreatePolicy createPolicy = createRequest(name).withRules(listOf(rule));
|
||||
return createEntity(createPolicy, ADMIN_AUTH_HEADERS);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void testScenario(int index, Object[] scenario) throws HttpResponseException, JsonProcessingException {
|
||||
Team team = (Team) scenario[0];
|
||||
Policy policy = (Policy) scenario[1];
|
||||
List<User> allowedUsers = (List<User>) scenario[2];
|
||||
List<User> disallowedUsers = (List<User>) scenario[3];
|
||||
Table table = (Table) scenario[4];
|
||||
addTeamPolicy(team, policy);
|
||||
LOG.info(
|
||||
"Testing scenario at {} with team:{} policy:{} table:{}",
|
||||
index,
|
||||
team.getName(),
|
||||
policy.getName(),
|
||||
table.getName());
|
||||
checkAccess(allowedUsers, disallowedUsers, table);
|
||||
removeTeamPolicy(team);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Policy validateGetWithDifferentFields(Policy policy, boolean byName) throws HttpResponseException {
|
||||
String fields = "";
|
||||
@ -465,4 +603,28 @@ public class PolicyResourceTest extends EntityResourceTest<Policy, CreatePolicy>
|
||||
String name, List<String> resources, List<MetadataOperation> operations, Effect effect) {
|
||||
return new Rule().withName(name).withResources(resources).withOperations(operations).withEffect(effect);
|
||||
}
|
||||
|
||||
private void addTeamPolicy(Team team, Policy policy) throws JsonProcessingException, HttpResponseException {
|
||||
String json = JsonUtils.pojoToJson(team);
|
||||
team.setPolicies(listOf(policy.getEntityReference()));
|
||||
teamTest.patchEntity(team.getId(), json, team, ADMIN_AUTH_HEADERS);
|
||||
}
|
||||
|
||||
private void removeTeamPolicy(Team team) throws JsonProcessingException, HttpResponseException {
|
||||
String json = JsonUtils.pojoToJson(team);
|
||||
team.setPolicies(null);
|
||||
teamTest.patchEntity(team.getId(), json, team, ADMIN_AUTH_HEADERS);
|
||||
}
|
||||
|
||||
private void checkAccess(List<User> allowedUsers, List<User> deniedUsers, Table table) throws HttpResponseException {
|
||||
for (User allowed : allowedUsers) {
|
||||
LOG.info("Expecting access allowed for user:{}", allowed.getName());
|
||||
assertNotNull(tableTest.getEntity(table.getId(), "", authHeaders(allowed.getName())));
|
||||
}
|
||||
for (User deniedUser : deniedUsers) {
|
||||
LOG.info("Expecting access denied for user:{}", deniedUser.getName());
|
||||
assertResponseContains(
|
||||
() -> tableTest.getEntity(table.getId(), "", authHeaders(deniedUser.getName())), FORBIDDEN, "denied");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user