Skip to content

Commit

Permalink
Merge pull request #2270 from atlanhq/nb/1245
Browse files Browse the repository at this point in the history
[stag] GOV-1245 Fix: member user deleting a collection
  • Loading branch information
nikhilbonte21 authored Aug 21, 2023
2 parents 65e92b7 + c395d43 commit a0ad4bd
Show file tree
Hide file tree
Showing 10 changed files with 57 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,7 @@ public enum SupportedFileExtensions { XLSX, XLS, CSV }
public static final Set<String> SKIP_DELETE_AUTH_CHECK_TYPES = new HashSet<String>() {{
add(README_ENTITY_TYPE);
add(LINK_ENTITY_TYPE);
add(POLICY_ENTITY_TYPE);
}};

private Constants() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,17 @@ private void startInternal() {
private void loadBootstrapAuthPolicies() {
LOG.info("==> AuthPoliciesBootstrapper.loadBootstrapAuthPolicies()");

RequestContext.get().setPoliciesBootstrappingInProgress(true);
RequestContext.get().setSkipAuthorizationCheck(true);

String atlasHomeDir = System.getProperty("atlas.home");
String policiesDirName = (StringUtils.isEmpty(atlasHomeDir) ? "." : atlasHomeDir) + File.separator + "policies";
try {
String atlasHomeDir = System.getProperty("atlas.home");
String policiesDirName = (StringUtils.isEmpty(atlasHomeDir) ? "." : atlasHomeDir) + File.separator + "policies";

File topPoliciesDir = new File(policiesDirName);
loadPoliciesInFolder(topPoliciesDir);
File topPoliciesDir = new File(policiesDirName);
loadPoliciesInFolder(topPoliciesDir);
} finally {
RequestContext.get().setSkipAuthorizationCheck(false);
}

LOG.info("<== AuthPoliciesBootstrapper.loadBootstrapAuthPolicies()");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1437,7 +1437,7 @@ private EntityMutationResponse createOrUpdate(EntityStream entityStream, boolean
final EntityMutationContext context = preCreateOrUpdate(entityStream, entityGraphMapper, isPartialUpdate);

// Check if authorized to create entities
if (!RequestContext.get().isImportInProgress() && !RequestContext.get().isPoliciesBootstrappingInProgress()) {
if (!RequestContext.get().isImportInProgress() && !RequestContext.get().isSkipAuthorizationCheck()) {
for (AtlasEntity entity : context.getCreatedEntities()) {
if (!PreProcessor.skipInitialAuthCheckTypes.contains(entity.getTypeName())) {
AtlasAuthorizationUtils.verifyAccess(new AtlasEntityAccessRequest(typeRegistry, AtlasPrivilege.ENTITY_CREATE, new AtlasEntityHeader(entity)),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,13 @@
import org.apache.atlas.AtlasErrorCode;
import org.apache.atlas.RequestContext;
import org.apache.atlas.authorize.AtlasAuthorizationUtils;
import org.apache.atlas.authorize.AtlasEntityAccessRequest;
import org.apache.atlas.authorize.AtlasPrivilege;
import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.featureflag.FeatureFlagStore;
import org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityWithExtInfo;
import org.apache.atlas.model.instance.AtlasEntityHeader;
import org.apache.atlas.model.instance.AtlasObjectId;
import org.apache.atlas.model.instance.AtlasStruct;
import org.apache.atlas.model.instance.EntityMutations.EntityOperation;
Expand Down Expand Up @@ -52,6 +55,7 @@
import static org.apache.atlas.AtlasErrorCode.RESOURCE_NOT_FOUND;
import static org.apache.atlas.AtlasErrorCode.UNAUTHORIZED_CONNECTION_ADMIN;
import static org.apache.atlas.authorize.AtlasAuthorizationUtils.getCurrentUserName;
import static org.apache.atlas.authorize.AtlasAuthorizationUtils.verifyAccess;
import static org.apache.atlas.model.instance.EntityMutations.EntityOperation.CREATE;
import static org.apache.atlas.model.instance.EntityMutations.EntityOperation.UPDATE;
import static org.apache.atlas.repository.Constants.ATTR_ADMIN_ROLES;
Expand Down Expand Up @@ -223,6 +227,8 @@ public void processDelete(AtlasVertex vertex) throws AtlasBaseException {
try {
AtlasEntity policy = entityRetriever.toAtlasEntity(vertex);

authorizeDeleteAuthPolicy(policy);

if(!policy.getStatus().equals(AtlasEntity.Status.ACTIVE)) {
LOG.info("Policy with guid {} is already deleted/purged", policy.getGuid());
return;
Expand All @@ -238,6 +244,16 @@ public void processDelete(AtlasVertex vertex) throws AtlasBaseException {
}
}

private void authorizeDeleteAuthPolicy(AtlasEntity policy) throws AtlasBaseException {
if (!RequestContext.get().isSkipAuthorizationCheck()) {
AtlasEntityAccessRequest request = new AtlasEntityAccessRequest(typeRegistry, AtlasPrivilege.ENTITY_DELETE, new AtlasEntityHeader(policy));
verifyAccess(request, "delete entity: guid=" + policy.getGuid());
}
/* else,
* skip auth check
* */
}

private void validateConnectionAdmin(AtlasEntity policy) throws AtlasBaseException {
String subCategory = getPolicySubCategory(policy);
if (POLICY_SUB_CATEGORY_METADATA.equals(subCategory) || POLICY_SUB_CATEGORY_DATA.equals(subCategory)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ public void validate(AtlasEntity policy, AtlasEntity existingPolicy,

} else {
//only allow argo & backend
if (!RequestContext.get().isPoliciesBootstrappingInProgress()) {
if (!RequestContext.get().isSkipAuthorizationCheck()) {
String userName = RequestContext.getCurrentUser();
validateOperation (!ARGO_SERVICE_USER_NAME.equals(userName) && !BACKEND_SERVICE_USER_NAME.equals(userName),
"Create/Update AuthPolicy with policyCategory other than persona & purpose");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,12 +142,12 @@ private void processCreateConnection(AtlasStruct struct) throws AtlasBaseExcepti
AtlasEntitiesWithExtInfo policies = transformer.transform(connection);

try {
RequestContext.get().setPoliciesBootstrappingInProgress(true);
RequestContext.get().setSkipAuthorizationCheck(true);
EntityStream entityStream = new AtlasEntityStream(policies);
entityStore.createOrUpdate(entityStream, false);
LOG.info("Created bootstrap policies for connection {}", connection.getAttribute(QUALIFIED_NAME));
} finally {
RequestContext.get().setPoliciesBootstrappingInProgress(false);
RequestContext.get().setSkipAuthorizationCheck(false);
}

RequestContext.get().endMetricRecord(metricRecorder);
Expand Down Expand Up @@ -254,6 +254,7 @@ private List<AtlasEntityHeader> getConnectionPolicies(String guid, String roleNa
dsl.put("query", mapOf("bool", mapOf("must", mustClauseList)));

indexSearchParams.setDsl(dsl);
indexSearchParams.setSuppressLogs(true);

AtlasSearchResult result = discovery.directIndexSearch(indexSearchParams);
if (result != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
import org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.model.instance.AtlasEntityHeader;
import org.apache.atlas.model.instance.AtlasStruct;
import org.apache.atlas.model.instance.EntityMutationResponse;
import org.apache.atlas.model.instance.EntityMutations;
import org.apache.atlas.repository.graph.GraphHelper;
import org.apache.atlas.repository.graphdb.AtlasVertex;
import org.apache.atlas.repository.store.graph.AtlasEntityStore;
import org.apache.atlas.repository.store.graph.v2.AtlasEntityStream;
Expand Down Expand Up @@ -137,12 +137,12 @@ private void processCreate(AtlasStruct entity) throws AtlasBaseException {
AtlasEntity.AtlasEntitiesWithExtInfo policies = transformer.transform(collection);

try {
RequestContext.get().setPoliciesBootstrappingInProgress(true);
RequestContext.get().setSkipAuthorizationCheck(true);
EntityStream entityStream = new AtlasEntityStream(policies);
entityStore.createOrUpdate(entityStream, false);
LOG.info("Created bootstrap policies for collection {}", entity.getAttribute(QUALIFIED_NAME));
} finally {
RequestContext.get().setPoliciesBootstrappingInProgress(false);
RequestContext.get().setSkipAuthorizationCheck(false);
}
}
} finally {
Expand Down Expand Up @@ -170,26 +170,30 @@ public void processDelete(AtlasVertex vertex) throws AtlasBaseException {
AtlasPerfMetrics.MetricRecorder metricRecorder = RequestContext.get().startMetricRecord("processDeleteCollection");

try {
AtlasEntityHeader collection = entityRetriever.toAtlasEntityHeader(vertex);
AtlasEntity.Status collectionStatus = GraphHelper.getStatus(vertex);

if (!AtlasEntity.Status.ACTIVE.equals(collection.getStatus())) {
if (!AtlasEntity.Status.ACTIVE.equals(collectionStatus)) {
throw new AtlasBaseException("Collection is already deleted/purged");
}

if (ATLAS_AUTHORIZER_IMPL.equalsIgnoreCase(CURRENT_AUTHORIZER_IMPL)) {
String collectionGuid = GraphHelper.getGuid(vertex);

//delete collection policies
List<AtlasEntityHeader> policies = getCollectionPolicies(collection.getGuid());
EntityMutationResponse response = entityStore.deleteByIds(policies.stream().map(x -> x.getGuid()).collect(Collectors.toList()));
List<AtlasEntityHeader> policies = getCollectionPolicies(collectionGuid);
RequestContext.get().setSkipAuthorizationCheck(true);
entityStore.deleteByIds(policies.stream().map(x -> x.getGuid()).collect(Collectors.toList()));

//delete collection roles
String adminRoleName = String.format(COLL_ADMIN_ROLE_PATTERN, collection.getGuid());
String viewerRoleName = String.format(COLL_VIEWER_ROLE_PATTERN, collection.getGuid());
String adminRoleName = String.format(COLL_ADMIN_ROLE_PATTERN, collectionGuid);
String viewerRoleName = String.format(COLL_VIEWER_ROLE_PATTERN, collectionGuid);

keycloakStore.removeRoleByName(adminRoleName);
keycloakStore.removeRoleByName(viewerRoleName);
}
} finally {
RequestContext.get().endMetricRecord(metricRecorder);
RequestContext.get().setSkipAuthorizationCheck(false);
}
}

Expand Down Expand Up @@ -303,6 +307,7 @@ private List<AtlasEntityHeader> getCollectionPolicies(String guid) throws AtlasB
dsl.put("query", mapOf("bool", mapOf("must", mustClauseList)));

indexSearchParams.setDsl(dsl);
indexSearchParams.setSuppressLogs(true);

AtlasSearchResult result = discovery.directIndexSearch(indexSearchParams);
if (result != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ public final class AccessControlUtils {
public static final String POLICY_CATEGORY_PURPOSE = "purpose";
public static final String POLICY_CATEGORY_BOOTSTRAP = "bootstrap";

public static final String POLICY_SUB_CATEGORY_COLLECTION = "collection";

public static final String POLICY_RESOURCE_CATEGORY_PERSONA_CUSTOM = "CUSTOM";
public static final String POLICY_RESOURCE_CATEGORY_PERSONA_ENTITY = "ENTITY";
public static final String POLICY_RESOURCE_CATEGORY_PURPOSE = "TAG";
Expand Down
13 changes: 6 additions & 7 deletions server-api/src/main/java/org/apache/atlas/RequestContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ public class RequestContext {
private int maxAttempts = 1;
private int attemptCount = 1;
private boolean isImportInProgress = false;
private boolean isPoliciesBootstrappingInProgress = false;
private boolean isInNotificationProcessing = false;
private boolean isInTypePatching = false;
private boolean createShellEntityForNonExistingReference = false;
Expand All @@ -94,6 +93,7 @@ public class RequestContext {
private final Map<AtlasObjectId, Object> relationshipEndToVertexIdMap = new HashMap<>();
private boolean allowDuplicateDisplayName;
private MetricsRegistry metricsRegistry;
private boolean skipAuthorizationCheck = false;

private RequestContext() {
}
Expand Down Expand Up @@ -151,8 +151,7 @@ public void clearCache() {
this.relationshipEndToVertexIdMap.clear();
this.relationshipMutationMap.clear();
this.currentTask = null;

this.isPoliciesBootstrappingInProgress = false;
this.skipAuthorizationCheck = false;

if (metrics != null && !metrics.isEmpty()) {
METRICS.debug(metrics.toString());
Expand Down Expand Up @@ -411,12 +410,12 @@ public static int getActiveRequestsCount() {
return ACTIVE_REQUESTS.size();
}

public boolean isPoliciesBootstrappingInProgress() {
return isPoliciesBootstrappingInProgress;
public boolean isSkipAuthorizationCheck() {
return skipAuthorizationCheck;
}

public void setPoliciesBootstrappingInProgress(boolean policiesBootstrappingInProgress) {
isPoliciesBootstrappingInProgress = policiesBootstrappingInProgress;
public void setSkipAuthorizationCheck(boolean skipAuthorizationCheck) {
this.skipAuthorizationCheck = skipAuthorizationCheck;
}

public static long earliestActiveRequestTime() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,13 +109,13 @@ public EntityMutationResponse bootstrapConnections(AtlasEntity.AtlasEntitiesWith
}
AtlasEntity.AtlasEntitiesWithExtInfo policiesExtInfo = transformer.transform(entity);
try {
RequestContext.get().setPoliciesBootstrappingInProgress(true);
RequestContext.get().setSkipAuthorizationCheck(true);
EntityStream entityStream = new AtlasEntityStream(policiesExtInfo);
EntityMutationResponse policyResponse = entityStore.createOrUpdate(entityStream, false);
response.setMutatedEntities(policyResponse.getMutatedEntities());
LOG.info("Created bootstrap policies for connection");
} finally {
RequestContext.get().setPoliciesBootstrappingInProgress(false);
RequestContext.get().setSkipAuthorizationCheck(false);
}
}
}
Expand All @@ -142,14 +142,14 @@ public EntityMutationResponse bootstrapCollections(AtlasEntity.AtlasEntitiesWith
//create bootstrap policies
AtlasEntity.AtlasEntitiesWithExtInfo policies = transformer.transform(entity);
try {
RequestContext.get().setPoliciesBootstrappingInProgress(true);
RequestContext.get().setSkipAuthorizationCheck(true);

EntityStream entityStream = new AtlasEntityStream(policies);
EntityMutationResponse policyResponse = entityStore.createOrUpdate(entityStream, false);
response.setMutatedEntities(policyResponse.getMutatedEntities());
LOG.info("Created bootstrap policies for connection");
} finally {
RequestContext.get().setPoliciesBootstrappingInProgress(false);
RequestContext.get().setSkipAuthorizationCheck(false);
}
}
}
Expand Down

0 comments on commit a0ad4bd

Please sign in to comment.