This is an automated email from the ASF dual-hosted git repository.

madhan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/atlas.git


The following commit(s) were added to refs/heads/master by this push:
     new 8fe3edd  ATLAS-3622: added authorization for add/remove of labels, 
update of namespace attributes
8fe3edd is described below

commit 8fe3edd2a7d480408ec3d43762cfb43887d5fa19
Author: Madhan Neethiraj <mad...@apache.org>
AuthorDate: Sun Feb 16 17:15:34 2020 -0800

    ATLAS-3622: added authorization for add/remove of labels, update of 
namespace attributes
---
 .../atlas/authorize/AtlasEntityAccessRequest.java  | 101 +++++++++++++++++--
 .../org/apache/atlas/authorize/AtlasPrivilege.java |   7 +-
 .../authorize/simple/AtlasSimpleAuthorizer.java    |  13 ++-
 .../authorize/simple/AtlasSimpleAuthzPolicy.java   |  24 +++++
 .../main/resources/atlas-simple-authz-policy.json  |  14 ++-
 .../simple/AtlasSimpleAuthorizerTest.java          |  67 ++++++++++++
 .../test/resources/atlas-simple-authz-policy.json  |  14 ++-
 .../store/graph/v2/AtlasEntityStoreV2.java         | 112 ++++++++++++++++++++-
 .../store/graph/v2/EntityGraphMapper.java          |   2 +-
 .../store/graph/v2/EntityGraphRetriever.java       |  53 ++++++----
 10 files changed, 366 insertions(+), 41 deletions(-)

diff --git 
a/authorization/src/main/java/org/apache/atlas/authorize/AtlasEntityAccessRequest.java
 
b/authorization/src/main/java/org/apache/atlas/authorize/AtlasEntityAccessRequest.java
index 951e5c9..f2e4838 100644
--- 
a/authorization/src/main/java/org/apache/atlas/authorize/AtlasEntityAccessRequest.java
+++ 
b/authorization/src/main/java/org/apache/atlas/authorize/AtlasEntityAccessRequest.java
@@ -28,45 +28,53 @@ public class AtlasEntityAccessRequest extends 
AtlasAccessRequest {
     private final AtlasEntityHeader   entity;
     private final String              entityId;
     private final AtlasClassification classification;
+    private final String              label;
+    private final String              namespaceName;
     private final String              attributeName;
     private final AtlasTypeRegistry   typeRegistry;
     private final Set<String>         entityClassifications;
 
 
     public AtlasEntityAccessRequest(AtlasTypeRegistry typeRegistry, 
AtlasPrivilege action) {
-        this(typeRegistry, action, null, null, null, null, null);
+        this(typeRegistry, action, null, null, null, null, null, null, null);
     }
 
     public AtlasEntityAccessRequest(AtlasTypeRegistry typeRegistry, 
AtlasPrivilege action, AtlasEntityHeader entity) {
-        this(typeRegistry, action, entity, null, null, null, null);
+        this(typeRegistry, action, entity, null, null, null, null, null, null);
     }
 
     public AtlasEntityAccessRequest(AtlasTypeRegistry typeRegistry, 
AtlasPrivilege action, AtlasEntityHeader entity, AtlasClassification 
classification) {
-        this(typeRegistry, action, entity, classification, null, null, null);
+        this(typeRegistry, action, entity, classification, null, null, null, 
null, null);
     }
 
     public AtlasEntityAccessRequest(AtlasTypeRegistry typeRegistry, 
AtlasPrivilege action, AtlasEntityHeader entity, String attributeName) {
-        this(typeRegistry, action, entity, null, attributeName, null, null);
+        this(typeRegistry, action, entity, null, attributeName, null, null, 
null, null);
     }
 
     public AtlasEntityAccessRequest(AtlasTypeRegistry typeRegistry, 
AtlasPrivilege action, AtlasEntityHeader entity, String userName, Set<String> 
userGroups) {
-        this(typeRegistry, action, entity, null, null, userName, userGroups);
+        this(typeRegistry, action, entity, null, null, null, null, userName, 
userGroups);
     }
 
     public AtlasEntityAccessRequest(AtlasTypeRegistry typeRegistry, 
AtlasPrivilege action, AtlasEntityHeader entity, AtlasClassification 
classification, String userName, Set<String> userGroups) {
-        this(typeRegistry, action, entity, classification, null, userName, 
userGroups);
+        this(typeRegistry, action, entity, classification, null, null, null, 
userName, userGroups);
     }
 
     public AtlasEntityAccessRequest(AtlasTypeRegistry typeRegistry, 
AtlasPrivilege action, AtlasEntityHeader entity, String attributeName, String 
userName, Set<String> userGroups) {
-        this(typeRegistry, action, entity, null, attributeName, userName, 
userGroups);
+        this(typeRegistry, action, entity, null, attributeName, null, null, 
userName, userGroups);
     }
 
     public AtlasEntityAccessRequest(AtlasTypeRegistry typeRegistry, 
AtlasPrivilege action, AtlasEntityHeader entity, AtlasClassification 
classification, String attributeName, String userName, Set<String> userGroups) {
+        this(typeRegistry, action, entity, classification, attributeName, 
null, null, userName, userGroups);
+    }
+
+    public AtlasEntityAccessRequest(AtlasTypeRegistry typeRegistry, 
AtlasPrivilege action, AtlasEntityHeader entity, AtlasClassification 
classification, String attributeName, String label, String namespaceName, 
String userName, Set<String> userGroups) {
         super(action, userName, userGroups);
 
         this.entity                = entity;
         this.entityId              = super.getEntityId(entity, typeRegistry);
         this.classification        = classification;
+        this.label                 = label;
+        this.namespaceName         = namespaceName;
         this.attributeName         = attributeName;
         this.typeRegistry          = typeRegistry;
         this.entityClassifications = super.getClassificationNames(entity);
@@ -84,6 +92,14 @@ public class AtlasEntityAccessRequest extends 
AtlasAccessRequest {
         return classification;
     }
 
+    public String getLabel() {
+        return label;
+    }
+
+    public String getNamespaceName() {
+        return namespaceName;
+    }
+
     public String getAttributeName() {
         return attributeName;
     }
@@ -106,11 +122,80 @@ public class AtlasEntityAccessRequest extends 
AtlasAccessRequest {
 
     @Override
     public String toString() {
-        return "AtlasEntityAccessRequest[entity=" + entity + ", 
classification=" + classification + ", attributeName=" + attributeName +
+        return "AtlasEntityAccessRequest[entity=" + entity + ", 
classification=" + classification + ", label=" + label + ", namespaceName=" + 
namespaceName + ", attributeName=" + attributeName +
                 ", action=" + getAction() + ", accessTime=" + getAccessTime() 
+ ", user=" + getUser() +
                 ", userGroups=" + getUserGroups() + ", clientIPAddress=" + 
getClientIPAddress() +
                 ", forwardedAddresses=" + getForwardedAddresses() + ", 
remoteIPAddress=" + getRemoteIPAddress() + "]";
     }
+
+    public static class AtlasEntityAccessRequestBuilder {
+        private final AtlasTypeRegistry   typeRegistry;
+        private final AtlasPrivilege      action;
+        private       String              userName;
+        private       Set<String>         userGroups;
+        private       AtlasEntityHeader   entity;
+        private       AtlasClassification classification;
+        private       String              label;
+        private       String              namespaceName;
+        private       String              attributeName;
+
+        public AtlasEntityAccessRequestBuilder(AtlasTypeRegistry typeRegistry, 
AtlasPrivilege action) {
+            this.typeRegistry = typeRegistry;
+            this.action       = action;
+        }
+
+        public AtlasEntityAccessRequestBuilder(AtlasTypeRegistry typeRegistry, 
AtlasPrivilege action, AtlasEntityHeader entity) {
+            this.typeRegistry = typeRegistry;
+            this.action       = action;
+            this.entity       = entity;
+        }
+
+        public AtlasEntityAccessRequestBuilder setUserName(String userName) {
+            this.userName = userName;
+
+            return this;
+        }
+
+        public AtlasEntityAccessRequestBuilder setUserGroups(Set<String> 
userGroups) {
+            this.userGroups = userGroups;
+
+            return this;
+        }
+
+        public AtlasEntityAccessRequestBuilder setEntity(AtlasEntityHeader 
entity) {
+            this.entity = entity;
+
+            return this;
+        }
+
+        public AtlasEntityAccessRequestBuilder 
setClassification(AtlasClassification classification) {
+            this.classification = classification;
+
+            return this;
+        }
+
+        public AtlasEntityAccessRequestBuilder setLabel(String label) {
+            this.label = label;
+
+            return this;
+        }
+
+        public AtlasEntityAccessRequestBuilder setNamespaceName(String 
namespaceName) {
+            this.namespaceName = namespaceName;
+
+            return this;
+        }
+
+        public AtlasEntityAccessRequestBuilder setAttributeName(String 
attributeName) {
+            this.attributeName = attributeName;
+
+            return this;
+        }
+
+        public AtlasEntityAccessRequest build() {
+            return new AtlasEntityAccessRequest(typeRegistry, action, entity, 
classification, attributeName, label, namespaceName, userName, userGroups);
+        }
+    }
 }
 
 
diff --git 
a/authorization/src/main/java/org/apache/atlas/authorize/AtlasPrivilege.java 
b/authorization/src/main/java/org/apache/atlas/authorize/AtlasPrivilege.java
index 38b68fa..7d81e22 100644
--- a/authorization/src/main/java/org/apache/atlas/authorize/AtlasPrivilege.java
+++ b/authorization/src/main/java/org/apache/atlas/authorize/AtlasPrivilege.java
@@ -37,7 +37,12 @@ public enum AtlasPrivilege {
      RELATIONSHIP_ADD("add-relationship"),
      RELATIONSHIP_UPDATE("update-relationship"),
      RELATIONSHIP_REMOVE("remove-relationship"),
-     ADMIN_PURGE("admin-purge");
+
+     ADMIN_PURGE("admin-purge"),
+
+     ENTITY_ADD_LABEL("entity-add-label"),
+     ENTITY_REMOVE_LABEL("entity-remove-label"),
+     ENTITY_UPDATE_NAMESPACE("entity-update-namespace");
 
      private final String type;
 
diff --git 
a/authorization/src/main/java/org/apache/atlas/authorize/simple/AtlasSimpleAuthorizer.java
 
b/authorization/src/main/java/org/apache/atlas/authorize/simple/AtlasSimpleAuthorizer.java
index e210958..5f0c7b2 100644
--- 
a/authorization/src/main/java/org/apache/atlas/authorize/simple/AtlasSimpleAuthorizer.java
+++ 
b/authorization/src/main/java/org/apache/atlas/authorize/simple/AtlasSimpleAuthorizer.java
@@ -238,8 +238,9 @@ public final class AtlasSimpleAuthorizer implements 
AtlasAuthorizer {
 
             if (permissions != null) {
                 for (AtlasEntityPermission permission : permissions) {
-                    // match entity-type/entity-id/attribute
-                    if (isMatchAny(entityTypes, permission.getEntityTypes()) 
&& isMatch(entityId, permission.getEntityIds()) && isMatch(attribute, 
permission.getAttributes())) {
+                    // match entity-type/entity-id/lable/namespace/attribute
+                    if (isMatchAny(entityTypes, permission.getEntityTypes()) 
&& isMatch(entityId, permission.getEntityIds()) && isMatch(attribute, 
permission.getAttributes())
+                         && isLabelMatch(request, permission) && 
isNamespaceMatch(request, permission)) {
                         // match permission/classification
                         if (!hasEntityAccess) {
                             if (isMatch(action, permission.getPrivileges()) && 
isMatch(classification, permission.getClassifications())) {
@@ -458,6 +459,14 @@ public final class AtlasSimpleAuthorizer implements 
AtlasAuthorizer {
             }
         }
     }
+
+    private boolean isLabelMatch(AtlasEntityAccessRequest request, 
AtlasEntityPermission permission) {
+        return (AtlasPrivilege.ENTITY_ADD_LABEL.equals(request.getAction()) || 
AtlasPrivilege.ENTITY_REMOVE_LABEL.equals(request.getAction())) ? 
isMatch(request.getLabel(), permission.getLabels()) : true;
+    }
+
+    private boolean isNamespaceMatch(AtlasEntityAccessRequest request, 
AtlasEntityPermission permission) {
+        return 
AtlasPrivilege.ENTITY_UPDATE_NAMESPACE.equals(request.getAction()) ? 
isMatch(request.getNamespaceName(), permission.getNamespaces()) : true;
+    }
 }
 
 
diff --git 
a/authorization/src/main/java/org/apache/atlas/authorize/simple/AtlasSimpleAuthzPolicy.java
 
b/authorization/src/main/java/org/apache/atlas/authorize/simple/AtlasSimpleAuthzPolicy.java
index 485d4e8..899e386 100644
--- 
a/authorization/src/main/java/org/apache/atlas/authorize/simple/AtlasSimpleAuthzPolicy.java
+++ 
b/authorization/src/main/java/org/apache/atlas/authorize/simple/AtlasSimpleAuthzPolicy.java
@@ -209,16 +209,24 @@ public class AtlasSimpleAuthzPolicy implements 
Serializable {
         private List<String> entityTypes;     // name of entity-type, 
wildcards supported
         private List<String> entityIds;       // value of entity-unique 
attribute, wildcards supported
         private List<String> classifications; // name of classification-type, 
wildcards supported
+        private List<String> labels;          // labels, wildcards supported
+        private List<String> namespaces;      // name of namespace-type, 
wildcards supported
         private List<String> attributes;      // name of entity-attribute, 
wildcards supported
 
         public AtlasEntityPermission() {
         }
 
         public AtlasEntityPermission(List<String> privileges, List<String> 
entityTypes, List<String> entityIds, List<String> classifications, List<String> 
attributes) {
+            this(privileges, entityTypes, entityIds, classifications, 
attributes, null, null);
+        }
+
+        public AtlasEntityPermission(List<String> privileges, List<String> 
entityTypes, List<String> entityIds, List<String> classifications, List<String> 
labels, List<String> namespaces, List<String> attributes) {
             this.privileges      = privileges;
             this.entityTypes     = entityTypes;
             this.entityIds       = entityIds;
             this.classifications = classifications;
+            this.labels          = labels;
+            this.namespaces      = namespaces;
             this.attributes      = attributes;
         }
 
@@ -254,6 +262,22 @@ public class AtlasSimpleAuthzPolicy implements 
Serializable {
             this.classifications = classifications;
         }
 
+        public List<String> getLabels() {
+            return labels;
+        }
+
+        public void setLabels(List<String> labels) {
+            this.namespaces = labels;
+        }
+
+        public List<String> getNamespaces() {
+            return namespaces;
+        }
+
+        public void setNamespaces(List<String> namespaces) {
+            this.namespaces = namespaces;
+        }
+
         public List<String> getAttributes() {
             return attributes;
         }
diff --git a/authorization/src/main/resources/atlas-simple-authz-policy.json 
b/authorization/src/main/resources/atlas-simple-authz-policy.json
index 0a5f0fa..bd08a6f 100644
--- a/authorization/src/main/resources/atlas-simple-authz-policy.json
+++ b/authorization/src/main/resources/atlas-simple-authz-policy.json
@@ -18,7 +18,9 @@
           "privileges":      [ ".*" ],
           "entityTypes":     [ ".*" ],
           "entityIds":       [ ".*" ],
-          "classifications": [ ".*" ]
+          "classifications": [ ".*" ],
+          "labels":          [ ".*" ],
+          "namespaces":      [ ".*" ]
         }
       ],
       "relationshipPermissions": [
@@ -41,7 +43,9 @@
           "privileges":      [ "entity-read", "entity-read-classification" ],
           "entityTypes":     [ ".*" ],
           "entityIds":       [ ".*" ],
-          "classifications": [ ".*" ]
+          "classifications": [ ".*" ],
+          "labels":          [ ".*" ],
+          "namespaces":      [ ".*" ]
         }
       ]
     },
@@ -49,10 +53,12 @@
     "DATA_STEWARD": {
       "entityPermissions": [
         {
-          "privileges":      [ "entity-read", "entity-create", 
"entity-update", "entity-read-classification", "entity-add-classification", 
"entity-update-classification", "entity-remove-classification" ],
+          "privileges":      [ "entity-read", "entity-create", 
"entity-update", "entity-read-classification", "entity-add-classification", 
"entity-update-classification", "entity-remove-classification", 
"entity-add-label", "entity-remove-label", "entity-update-namespace" ],
           "entityTypes":     [ ".*" ],
           "entityIds":       [ ".*" ],
-          "classifications": [ ".*" ]
+          "classifications": [ ".*" ],
+          "labels":          [ ".*" ],
+          "namespaces":      [ ".*" ]
         }
       ],
       "relationshipPermissions": [
diff --git 
a/authorization/src/test/java/org/apache/atlas/authorize/simple/AtlasSimpleAuthorizerTest.java
 
b/authorization/src/test/java/org/apache/atlas/authorize/simple/AtlasSimpleAuthorizerTest.java
index 16c8c8c..e585e93 100644
--- 
a/authorization/src/test/java/org/apache/atlas/authorize/simple/AtlasSimpleAuthorizerTest.java
+++ 
b/authorization/src/test/java/org/apache/atlas/authorize/simple/AtlasSimpleAuthorizerTest.java
@@ -29,6 +29,10 @@ import java.util.Collections;
 public class AtlasSimpleAuthorizerTest {
     private static Logger LOG = 
LoggerFactory.getLogger(AtlasSimpleAuthorizerTest.class);
 
+    private static final String USER_DATA_SCIENTIST = "dataScientist1";
+    private static final String USER_DATA_STEWARD   = "dataSteward1";
+
+
     private String          originalConf;
     private AtlasAuthorizer authorizer;
 
@@ -104,4 +108,67 @@ public class AtlasSimpleAuthorizerTest {
             AssertJUnit.fail();
         }
     }
+
+    @Test(enabled = true)
+    public void testLabels() {
+        try {
+            AtlasEntityAccessRequest request = new 
AtlasEntityAccessRequest(null, AtlasPrivilege.ENTITY_ADD_LABEL);
+
+            request.setUser(USER_DATA_SCIENTIST, Collections.emptySet());
+
+            boolean isAccessAllowed = authorizer.isAccessAllowed(request);
+
+            AssertJUnit.assertEquals("user " + USER_DATA_SCIENTIST + " 
shouldn't be allowed to add label", false, isAccessAllowed);
+
+
+            request.setUser(USER_DATA_STEWARD, Collections.emptySet());
+
+            isAccessAllowed = authorizer.isAccessAllowed(request);
+
+            AssertJUnit.assertEquals("user " + USER_DATA_STEWARD + " should be 
allowed to add label", true, isAccessAllowed);
+
+
+            request = new AtlasEntityAccessRequest(null, 
AtlasPrivilege.ENTITY_REMOVE_LABEL);
+
+            request.setUser(USER_DATA_SCIENTIST, Collections.emptySet());
+
+            isAccessAllowed = authorizer.isAccessAllowed(request);
+
+            AssertJUnit.assertEquals("user " + USER_DATA_SCIENTIST + " 
shouldn't be allowed to remove label", false, isAccessAllowed);
+
+
+            request.setUser(USER_DATA_STEWARD, Collections.emptySet());
+
+            isAccessAllowed = authorizer.isAccessAllowed(request);
+
+            AssertJUnit.assertEquals("user " + USER_DATA_STEWARD + " should be 
allowed to remove label", true, isAccessAllowed);
+        } catch (AtlasAuthorizationException e) {
+            LOG.error("Exception in AtlasSimpleAuthorizerTest", e);
+
+            AssertJUnit.fail();
+        }
+    }
+
+    @Test(enabled = true)
+    public void testNamespaces() {
+        try {
+            AtlasEntityAccessRequest request = new 
AtlasEntityAccessRequest(null, AtlasPrivilege.ENTITY_UPDATE_NAMESPACE);
+
+            request.setUser(USER_DATA_SCIENTIST, Collections.emptySet());
+
+            boolean isAccessAllowed = authorizer.isAccessAllowed(request);
+
+            AssertJUnit.assertEquals("user " + USER_DATA_SCIENTIST + " 
shouldn't be allowed to update namespace", false, isAccessAllowed);
+
+            request.setUser(USER_DATA_STEWARD, Collections.emptySet());
+
+            isAccessAllowed = authorizer.isAccessAllowed(request);
+
+            AssertJUnit.assertEquals("user " + USER_DATA_STEWARD + " should be 
allowed to update namespace", true, isAccessAllowed);
+        } catch (AtlasAuthorizationException e) {
+            LOG.error("Exception in AtlasSimpleAuthorizerTest", e);
+
+            AssertJUnit.fail();
+        }
+    }
 }
diff --git a/authorization/src/test/resources/atlas-simple-authz-policy.json 
b/authorization/src/test/resources/atlas-simple-authz-policy.json
index 5743de1..379d42b 100644
--- a/authorization/src/test/resources/atlas-simple-authz-policy.json
+++ b/authorization/src/test/resources/atlas-simple-authz-policy.json
@@ -43,7 +43,9 @@
           "privileges":      [ "entity-read", "entity-read-classification" ],
           "entityTypes":     [ ".*" ],
           "entityIds":       [ ".*" ],
-          "classifications": [ ".*" ]
+          "classifications": [ ".*" ],
+          "labels":          [ ".*" ],
+          "namespaces":      [ ".*" ]
         }
       ]
     },
@@ -51,10 +53,12 @@
     "DATA_STEWARD": {
       "entityPermissions": [
         {
-          "privileges":      [ "entity-read", "entity-create", 
"entity-update", "entity-read-classification", "entity-add-classification", 
"entity-update-classification", "entity-remove-classification" ],
+          "privileges":      [ "entity-read", "entity-create", 
"entity-update", "entity-read-classification", "entity-add-classification", 
"entity-update-classification", "entity-remove-classification", 
"entity-add-label", "entity-remove-label", "entity-update-namespace" ],
           "entityTypes":     [ ".*" ],
           "entityIds":       [ ".*" ],
-          "classifications": [ ".*" ]
+          "classifications": [ ".*" ],
+          "labels":          [ ".*" ],
+          "namespaces":      [ ".*" ]
         }
       ]
     }
@@ -62,7 +66,9 @@
 
   "userRoles": {
     "admin": [ "ROLE_ADMIN" ],
-    "rangertagsync": [ "DATA_SCIENTIST" ]
+    "rangertagsync": [ "DATA_SCIENTIST" ],
+    "dataScientist1": [ "DATA_SCIENTIST"],
+    "dataSteward1": [ "DATA_STEWARD"]
   },
 
   "groupRoles": {
diff --git 
a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasEntityStoreV2.java
 
b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasEntityStoreV2.java
index c536f3b..30f5e5a 100644
--- 
a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasEntityStoreV2.java
+++ 
b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasEntityStoreV2.java
@@ -25,6 +25,7 @@ import org.apache.atlas.annotation.GraphTransaction;
 import org.apache.atlas.authorize.AtlasAdminAccessRequest;
 import org.apache.atlas.authorize.AtlasAuthorizationUtils;
 import org.apache.atlas.authorize.AtlasEntityAccessRequest;
+import 
org.apache.atlas.authorize.AtlasEntityAccessRequest.AtlasEntityAccessRequestBuilder;
 import org.apache.atlas.authorize.AtlasPrivilege;
 import org.apache.atlas.exception.AtlasBaseException;
 import org.apache.atlas.model.TypeCategory;
@@ -66,6 +67,7 @@ import javax.inject.Inject;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -834,14 +836,44 @@ public class AtlasEntityStoreV2 implements 
AtlasEntityStore {
             throw new AtlasBaseException(AtlasErrorCode.INVALID_PARAMETERS, 
"guid is null/empty");
         }
 
+        if (MapUtils.isEmpty(entityNamespaces)) {
+            throw new AtlasBaseException(AtlasErrorCode.INVALID_PARAMETERS, 
"entityNamespaces is null/empty");
+        }
+
         AtlasVertex entityVertex = AtlasGraphUtilsV2.findByGuid(guid);
 
         if (entityVertex == null) {
             throw new 
AtlasBaseException(AtlasErrorCode.INSTANCE_GUID_NOT_FOUND, guid);
         }
 
-        String          typeName   = getTypeName(entityVertex);
-        AtlasEntityType entityType = 
typeRegistry.getEntityTypeByName(typeName);
+        String                           typeName       = 
getTypeName(entityVertex);
+        AtlasEntityType                  entityType     = 
typeRegistry.getEntityTypeByName(typeName);
+        AtlasEntityHeader                entityHeader   = 
entityRetriever.toAtlasEntityHeaderWithClassifications(entityVertex);
+        Map<String, Map<String, Object>> currNamespaces = 
entityRetriever.getEntityNamespaces(entityVertex);
+        Set<String>                      updatedNsNames = new HashSet<>();
+
+        for (String nsName : entityType.getNamespaceAttributes().keySet()) {
+            Map<String, Object> nsAttrs     = entityNamespaces.get(nsName);
+            Map<String, Object> currNsAttrs = currNamespaces != null ? 
currNamespaces.get(nsName) : null;
+
+            if (nsAttrs == null && !isOverwrite) {
+                continue;
+            } else if (MapUtils.isEmpty(nsAttrs) && 
MapUtils.isEmpty(currNsAttrs)) { // no change
+                continue;
+            } else if (Objects.equals(nsAttrs, currNsAttrs)) { // no change
+                continue;
+            }
+
+            updatedNsNames.add(nsName);
+        }
+
+        AtlasEntityAccessRequestBuilder  requestBuilder = new 
AtlasEntityAccessRequestBuilder(typeRegistry, 
AtlasPrivilege.ENTITY_UPDATE_NAMESPACE, entityHeader);
+
+        for (String nsName : updatedNsNames) {
+            requestBuilder.setNamespaceName(nsName);
+
+            AtlasAuthorizationUtils.verifyAccess(requestBuilder.build(), 
"add/update namespace: guid=", guid, ", namespace=", nsName);
+        }
 
         validateNamespaceAttributes(entityVertex, entityType, 
entityNamespaces, isOverwrite);
 
@@ -867,14 +899,27 @@ public class AtlasEntityStoreV2 implements 
AtlasEntityStore {
             throw new AtlasBaseException(AtlasErrorCode.INVALID_PARAMETERS, 
"guid is null/empty");
         }
 
+        if (MapUtils.isEmpty(entityNamespaces)) {
+            throw new AtlasBaseException(AtlasErrorCode.INVALID_PARAMETERS, 
"entityNamespaces is null/empty");
+        }
+
         AtlasVertex entityVertex = AtlasGraphUtilsV2.findByGuid(guid);
 
         if (entityVertex == null) {
             throw new 
AtlasBaseException(AtlasErrorCode.INSTANCE_GUID_NOT_FOUND, guid);
         }
 
-        String          typeName   = getTypeName(entityVertex);
-        AtlasEntityType entityType = 
typeRegistry.getEntityTypeByName(typeName);
+        String                          typeName       = 
getTypeName(entityVertex);
+        AtlasEntityType                 entityType     = 
typeRegistry.getEntityTypeByName(typeName);
+        AtlasEntityHeader               entityHeader   = 
entityRetriever.toAtlasEntityHeaderWithClassifications(entityVertex);
+
+        AtlasEntityAccessRequestBuilder requestBuilder = new 
AtlasEntityAccessRequestBuilder(typeRegistry, 
AtlasPrivilege.ENTITY_UPDATE_NAMESPACE, entityHeader);
+
+        for (String nsName : entityNamespaces.keySet()) {
+            requestBuilder.setNamespaceName(nsName);
+
+            AtlasAuthorizationUtils.verifyAccess(requestBuilder.build(), 
"remove namespace: guid=", guid, ", namespace=", nsName);
+        }
 
         entityGraphMapper.removeNamespaceAttributes(entityVertex, entityType, 
entityNamespaces);
 
@@ -902,6 +947,39 @@ public class AtlasEntityStoreV2 implements 
AtlasEntityStore {
 
         validateLabels(labels);
 
+        AtlasEntityHeader entityHeader  = 
entityRetriever.toAtlasEntityHeaderWithClassifications(entityVertex);
+        Set<String>       addedLabels   = Collections.emptySet();
+        Set<String>       removedLabels = Collections.emptySet();
+
+        if (CollectionUtils.isEmpty(entityHeader.getLabels())) {
+            addedLabels = labels;
+        } else if (CollectionUtils.isEmpty(labels)) {
+            removedLabels = entityHeader.getLabels();
+        } else {
+            addedLabels   = new 
HashSet<String>(CollectionUtils.subtract(labels, entityHeader.getLabels()));
+            removedLabels = new 
HashSet<String>(CollectionUtils.subtract(entityHeader.getLabels(), labels));
+        }
+
+        if (addedLabels != null) {
+            AtlasEntityAccessRequestBuilder requestBuilder = new 
AtlasEntityAccessRequestBuilder(typeRegistry, AtlasPrivilege.ENTITY_ADD_LABEL, 
entityHeader);
+
+            for (String label : addedLabels) {
+                requestBuilder.setLabel(label);
+
+                AtlasAuthorizationUtils.verifyAccess(requestBuilder.build(), 
"add label: guid=", guid, ", label=", label);
+            }
+        }
+
+        if (removedLabels != null) {
+            AtlasEntityAccessRequestBuilder requestBuilder = new 
AtlasEntityAccessRequestBuilder(typeRegistry, 
AtlasPrivilege.ENTITY_REMOVE_LABEL, entityHeader);
+
+            for (String label : removedLabels) {
+                requestBuilder.setLabel(label);
+
+                AtlasAuthorizationUtils.verifyAccess(requestBuilder.build(), 
"remove label: guid=", guid, ", label=", label);
+            }
+        }
+
         entityGraphMapper.setLabels(entityVertex, labels);
 
         if (LOG.isDebugEnabled()) {
@@ -920,12 +998,25 @@ public class AtlasEntityStoreV2 implements 
AtlasEntityStore {
             throw new AtlasBaseException(AtlasErrorCode.INVALID_PARAMETERS, 
"guid is null/empty");
         }
 
+        if (CollectionUtils.isEmpty(labels)) {
+            throw new AtlasBaseException(AtlasErrorCode.INVALID_PARAMETERS, 
"labels is null/empty");
+        }
+
         AtlasVertex entityVertex = AtlasGraphUtilsV2.findByGuid(guid);
 
         if (entityVertex == null) {
             throw new 
AtlasBaseException(AtlasErrorCode.INSTANCE_GUID_NOT_FOUND, guid);
         }
 
+        AtlasEntityHeader               entityHeader   = 
entityRetriever.toAtlasEntityHeaderWithClassifications(entityVertex);
+        AtlasEntityAccessRequestBuilder requestBuilder = new 
AtlasEntityAccessRequestBuilder(typeRegistry, 
AtlasPrivilege.ENTITY_REMOVE_LABEL, entityHeader);
+
+        for (String label : labels) {
+            requestBuilder.setLabel(label);
+
+            AtlasAuthorizationUtils.verifyAccess(requestBuilder.build(), 
"remove label: guid=", guid, ", label=", label);
+        }
+
         validateLabels(labels);
 
         entityGraphMapper.removeLabels(entityVertex, labels);
@@ -946,12 +1037,25 @@ public class AtlasEntityStoreV2 implements 
AtlasEntityStore {
             throw new AtlasBaseException(AtlasErrorCode.INVALID_PARAMETERS, 
"guid is null/empty");
         }
 
+        if (CollectionUtils.isEmpty(labels)) {
+            throw new AtlasBaseException(AtlasErrorCode.INVALID_PARAMETERS, 
"labels is null/empty");
+        }
+
         AtlasVertex entityVertex = AtlasGraphUtilsV2.findByGuid(guid);
 
         if (entityVertex == null) {
             throw new 
AtlasBaseException(AtlasErrorCode.INSTANCE_GUID_NOT_FOUND, guid);
         }
 
+        AtlasEntityHeader               entityHeader   = 
entityRetriever.toAtlasEntityHeaderWithClassifications(entityVertex);
+        AtlasEntityAccessRequestBuilder requestBuilder = new 
AtlasEntityAccessRequestBuilder(typeRegistry, AtlasPrivilege.ENTITY_ADD_LABEL, 
entityHeader);
+
+        for (String label : labels) {
+            requestBuilder.setLabel(label);
+
+            AtlasAuthorizationUtils.verifyAccess(requestBuilder.build(), 
"add/update label: guid=", guid, ", label=", label);
+        }
+
         validateLabels(labels);
 
         entityGraphMapper.addLabels(entityVertex, labels);
diff --git 
a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/EntityGraphMapper.java
 
b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/EntityGraphMapper.java
index 7461931..2f3aad0 100644
--- 
a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/EntityGraphMapper.java
+++ 
b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/EntityGraphMapper.java
@@ -353,7 +353,7 @@ public class EntityGraphMapper {
             removedLabels = null;
         } else if (CollectionUtils.isEmpty(labels)) {
             addedLabels   = null;
-            removedLabels = labels;
+            removedLabels = currentLabels;
         } else {
             addedLabels   = new 
HashSet<String>(CollectionUtils.subtract(labels, currentLabels));
             removedLabels = new 
HashSet<String>(CollectionUtils.subtract(currentLabels, labels));
diff --git 
a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/EntityGraphRetriever.java
 
b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/EntityGraphRetriever.java
index 3c22d9a..7533ebc 100644
--- 
a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/EntityGraphRetriever.java
+++ 
b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/EntityGraphRetriever.java
@@ -221,6 +221,41 @@ public class EntityGraphRetriever {
         return ret;
     }
 
+    public Map<String, Map<String, Object>> getEntityNamespaces(AtlasVertex 
entityVertex) throws AtlasBaseException {
+        Map<String, Map<String, Object>>                  ret                  
= null;
+        String                                            entityTypeName       
= getTypeName(entityVertex);
+        AtlasEntityType                                   entityType           
= typeRegistry.getEntityTypeByName(entityTypeName);
+        Map<String, Map<String, AtlasNamespaceAttribute>> entityTypeNamespaces 
= entityType != null ? entityType.getNamespaceAttributes() : null;
+
+        if (MapUtils.isNotEmpty(entityTypeNamespaces)) {
+            for (Map.Entry<String, Map<String, AtlasNamespaceAttribute>> entry 
: entityTypeNamespaces.entrySet()) {
+                String                               nsName        = 
entry.getKey();
+                Map<String, AtlasNamespaceAttribute> nsAttributes  = 
entry.getValue();
+                Map<String, Object>                  entityNsAttrs = null;
+
+                for (AtlasNamespaceAttribute nsAttribute : 
nsAttributes.values()) {
+                    Object nsAttrValue = mapVertexToAttribute(entityVertex, 
nsAttribute, null, false, false);
+
+                    if (nsAttrValue != null) {
+                        if (ret == null) {
+                            ret = new HashMap<>();
+                        }
+
+                        if (entityNsAttrs == null) {
+                            entityNsAttrs = new HashMap<>();
+
+                            ret.put(nsName, entityNsAttrs);
+                        }
+
+                        entityNsAttrs.put(nsAttribute.getName(), nsAttrValue);
+                    }
+                }
+            }
+        }
+
+        return ret;
+    }
+
     public Object getEntityAttribute(AtlasVertex entityVertex, AtlasAttribute 
attribute) {
         Object ret = null;
 
@@ -770,23 +805,7 @@ public class EntityGraphRetriever {
     }
 
     private void mapNamespaceAttributes(AtlasVertex entityVertex, AtlasEntity 
entity) throws AtlasBaseException {
-        AtlasEntityType                                   entityType           
= typeRegistry.getEntityTypeByName(entity.getTypeName());
-        Map<String, Map<String, AtlasNamespaceAttribute>> entityTypeNamespaces 
= entityType != null ? entityType.getNamespaceAttributes() : null;
-
-        if (MapUtils.isNotEmpty(entityTypeNamespaces)) {
-            for (Map.Entry<String, Map<String, AtlasNamespaceAttribute>> entry 
: entityTypeNamespaces.entrySet()) {
-                String                               nsName       = 
entry.getKey();
-                Map<String, AtlasNamespaceAttribute> nsAttributes = 
entry.getValue();
-
-                for (AtlasNamespaceAttribute nsAttribute : 
nsAttributes.values()) {
-                    Object nsAttrValue = mapVertexToAttribute(entityVertex, 
nsAttribute, null, false, false);
-
-                    if (nsAttrValue != null) {
-                        entity.setNamespaceAttribute(nsName, 
nsAttribute.getName(), nsAttrValue);
-                    }
-                }
-            }
-        }
+        entity.setNamespaceAttributes(getEntityNamespaces(entityVertex));
     }
 
     public List<AtlasClassification> getAllClassifications(AtlasVertex 
entityVertex) throws AtlasBaseException {

Reply via email to