Repository: atlas
Updated Branches:
  refs/heads/master 80f556a70 -> eb895a62f


ATLAS-2765: updated authorization model to scrub search-results (clear 
entity-attributes, classifications) for entities the user doesn't have read 
access to


Project: http://git-wip-us.apache.org/repos/asf/atlas/repo
Commit: http://git-wip-us.apache.org/repos/asf/atlas/commit/eb895a62
Tree: http://git-wip-us.apache.org/repos/asf/atlas/tree/eb895a62
Diff: http://git-wip-us.apache.org/repos/asf/atlas/diff/eb895a62

Branch: refs/heads/master
Commit: eb895a62fde263ecf84da3a476594ca75a23022b
Parents: 80f556a
Author: Madhan Neethiraj <mad...@apache.org>
Authored: Fri Jun 22 21:32:18 2018 -0700
Committer: Madhan Neethiraj <mad...@apache.org>
Committed: Sat Jun 23 21:02:09 2018 -0700

----------------------------------------------------------------------
 .../authorize/AtlasAuthorizationUtils.java      | 17 ++++++
 .../apache/atlas/authorize/AtlasAuthorizer.java | 38 ++++++++++++++
 .../atlas/authorize/AtlasNoneAuthorizer.java    |  4 ++
 .../AtlasSearchResultScrubRequest.java          | 54 ++++++++++++++++++++
 .../authorize/simple/AtlasSimpleAuthorizer.java | 50 ++++++++++++++++++
 .../atlas/discovery/EntityDiscoveryService.java | 16 ++++++
 .../apache/atlas/glossary/GlossaryService.java  |  6 ++-
 .../store/graph/v2/AtlasEntityStoreV2.java      |  4 +-
 8 files changed, 186 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/atlas/blob/eb895a62/authorization/src/main/java/org/apache/atlas/authorize/AtlasAuthorizationUtils.java
----------------------------------------------------------------------
diff --git 
a/authorization/src/main/java/org/apache/atlas/authorize/AtlasAuthorizationUtils.java
 
b/authorization/src/main/java/org/apache/atlas/authorize/AtlasAuthorizationUtils.java
index cc5db2f..a0d78eb 100644
--- 
a/authorization/src/main/java/org/apache/atlas/authorize/AtlasAuthorizationUtils.java
+++ 
b/authorization/src/main/java/org/apache/atlas/authorize/AtlasAuthorizationUtils.java
@@ -62,6 +62,23 @@ public class AtlasAuthorizationUtils {
         }
     }
 
+    public static void scrubSearchResults(AtlasSearchResultScrubRequest 
request) throws AtlasBaseException {
+        String userName = getCurrentUserName();
+
+        if (StringUtils.isNotEmpty(userName)) {
+            try {
+                AtlasAuthorizer authorizer = 
AtlasAuthorizerFactory.getAtlasAuthorizer();
+
+                request.setUser(userName, getCurrentUserGroups());
+                
request.setClientIPAddress(RequestContext.get().getClientIPAddress());
+
+                authorizer.scrubSearchResults(request);
+            } catch (AtlasAuthorizationException e) {
+                LOG.error("Unable to obtain AtlasAuthorizer", e);
+            }
+        }
+    }
+
     public static boolean isAccessAllowed(AtlasAdminAccessRequest request) {
         boolean ret      = false;
         String  userName = getCurrentUserName();

http://git-wip-us.apache.org/repos/asf/atlas/blob/eb895a62/authorization/src/main/java/org/apache/atlas/authorize/AtlasAuthorizer.java
----------------------------------------------------------------------
diff --git 
a/authorization/src/main/java/org/apache/atlas/authorize/AtlasAuthorizer.java 
b/authorization/src/main/java/org/apache/atlas/authorize/AtlasAuthorizer.java
index 285e0f6..563485e 100644
--- 
a/authorization/src/main/java/org/apache/atlas/authorize/AtlasAuthorizer.java
+++ 
b/authorization/src/main/java/org/apache/atlas/authorize/AtlasAuthorizer.java
@@ -19,6 +19,8 @@
 package org.apache.atlas.authorize;
 
 
+import org.apache.atlas.model.instance.AtlasEntityHeader;
+
 public interface AtlasAuthorizer {
     /**
      * initialization of authorizer implementation
@@ -55,4 +57,40 @@ public interface AtlasAuthorizer {
      * @throws AtlasAuthorizationException
      */
     boolean isAccessAllowed(AtlasTypeAccessRequest request) throws 
AtlasAuthorizationException;
+
+
+    /**
+     * scrub search-results to handle entities for which the user doesn't have 
access
+     * @param request
+     * @return
+     * @throws AtlasAuthorizationException
+     */
+    default
+    void scrubSearchResults(AtlasSearchResultScrubRequest request) throws 
AtlasAuthorizationException {
+    }
+
+    default
+    void scrubEntityHeader(AtlasEntityHeader entity) {
+        entity.setGuid("-1");
+
+        if(entity.getAttributes() != null) {
+            entity.getAttributes().clear();
+        }
+
+        if(entity.getClassifications() != null) {
+            entity.getClassifications().clear();
+        }
+
+        if(entity.getClassificationNames() != null) {
+            entity.getClassificationNames().clear();
+        }
+
+        if(entity.getMeanings() != null) {
+            entity.getMeanings().clear();
+        }
+
+        if(entity.getMeaningNames() != null) {
+            entity.getMeaningNames().clear();
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/atlas/blob/eb895a62/authorization/src/main/java/org/apache/atlas/authorize/AtlasNoneAuthorizer.java
----------------------------------------------------------------------
diff --git 
a/authorization/src/main/java/org/apache/atlas/authorize/AtlasNoneAuthorizer.java
 
b/authorization/src/main/java/org/apache/atlas/authorize/AtlasNoneAuthorizer.java
index 06ae600..9f8f7ac 100644
--- 
a/authorization/src/main/java/org/apache/atlas/authorize/AtlasNoneAuthorizer.java
+++ 
b/authorization/src/main/java/org/apache/atlas/authorize/AtlasNoneAuthorizer.java
@@ -44,4 +44,8 @@ public class AtlasNoneAuthorizer implements AtlasAuthorizer {
     public boolean isAccessAllowed(AtlasTypeAccessRequest request) throws 
AtlasAuthorizationException {
         return true;
     }
+
+    public void scrubSearchResults(AtlasSearchResultScrubRequest request) 
throws AtlasAuthorizationException {
+
+    }
 }

http://git-wip-us.apache.org/repos/asf/atlas/blob/eb895a62/authorization/src/main/java/org/apache/atlas/authorize/AtlasSearchResultScrubRequest.java
----------------------------------------------------------------------
diff --git 
a/authorization/src/main/java/org/apache/atlas/authorize/AtlasSearchResultScrubRequest.java
 
b/authorization/src/main/java/org/apache/atlas/authorize/AtlasSearchResultScrubRequest.java
new file mode 100644
index 0000000..c908b28
--- /dev/null
+++ 
b/authorization/src/main/java/org/apache/atlas/authorize/AtlasSearchResultScrubRequest.java
@@ -0,0 +1,54 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.atlas.authorize;
+
+import org.apache.atlas.model.discovery.AtlasSearchResult;
+import org.apache.atlas.type.AtlasTypeRegistry;
+
+import java.util.Set;
+
+public class AtlasSearchResultScrubRequest extends AtlasAccessRequest {
+    private final AtlasTypeRegistry typeRegistry;
+    private final AtlasSearchResult searchResult;
+
+
+    public AtlasSearchResultScrubRequest(AtlasTypeRegistry typeRegistry, 
AtlasSearchResult searchResult) {
+        this(typeRegistry, searchResult, null, null);
+    }
+
+    public AtlasSearchResultScrubRequest(AtlasTypeRegistry typeRegistry, 
AtlasSearchResult searchResult, String userName, Set<String> userGroups) {
+        super(AtlasPrivilege.ENTITY_READ, userName, userGroups);
+
+        this.typeRegistry = typeRegistry;
+        this.searchResult = searchResult;
+    }
+
+    public AtlasTypeRegistry getTypeRegistry() { return typeRegistry; }
+
+    public AtlasSearchResult getSearchResult() {
+        return searchResult;
+    }
+
+    @Override
+    public String toString() {
+        return "AtlasSearchResultScrubRequest[searchResult=" + searchResult + 
", action=" + getAction() + ", accessTime=" + getAccessTime() + ", user=" + 
getUser() +
+                                         ", userGroups=" + getUserGroups() + 
", clientIPAddress=" + getClientIPAddress() + "]";
+    }
+}
+
+

http://git-wip-us.apache.org/repos/asf/atlas/blob/eb895a62/authorization/src/main/java/org/apache/atlas/authorize/simple/AtlasSimpleAuthorizer.java
----------------------------------------------------------------------
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 fd58858..47c44cc 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
@@ -31,10 +31,16 @@ import org.apache.atlas.authorize.AtlasAdminAccessRequest;
 import org.apache.atlas.authorize.AtlasAuthorizer;
 import org.apache.atlas.authorize.AtlasAuthorizationException;
 import org.apache.atlas.authorize.AtlasEntityAccessRequest;
+import org.apache.atlas.authorize.AtlasPrivilege;
+import org.apache.atlas.authorize.AtlasSearchResultScrubRequest;
 import org.apache.atlas.authorize.AtlasTypeAccessRequest;
 import org.apache.atlas.authorize.simple.AtlasSimpleAuthzPolicy.*;
+import org.apache.atlas.model.discovery.AtlasSearchResult;
+import org.apache.atlas.model.discovery.AtlasSearchResult.AtlasFullTextResult;
+import org.apache.atlas.model.instance.AtlasEntityHeader;
 import org.apache.atlas.utils.AtlasJson;
 import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -219,6 +225,38 @@ public final class AtlasSimpleAuthorizer implements 
AtlasAuthorizer {
         return ret;
     }
 
+    @Override
+    public void scrubSearchResults(AtlasSearchResultScrubRequest request) 
throws AtlasAuthorizationException {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> SimpleAtlasAuthorizer.scrubSearchResults({})", 
request);
+        }
+
+        final AtlasSearchResult result = request.getSearchResult();
+
+        if (CollectionUtils.isNotEmpty(result.getEntities())) {
+            for (AtlasEntityHeader entity : result.getEntities()) {
+                checkAccessAndScrub(entity, request);
+            }
+        }
+
+        if (CollectionUtils.isNotEmpty(result.getFullTextResult())) {
+            for (AtlasFullTextResult fullTextResult : 
result.getFullTextResult()) {
+                if (fullTextResult != null) {
+                    checkAccessAndScrub(fullTextResult.getEntity(), request);
+                }
+            }
+        }
+
+        if (MapUtils.isNotEmpty(result.getReferredEntities())) {
+            for (AtlasEntityHeader entity : 
result.getReferredEntities().values()) {
+                checkAccessAndScrub(entity, request);
+            }
+        }
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("<== SimpleAtlasAuthorizer.scrubSearchResults({}): {}", 
request, result);
+        }
+    }
 
     private Set<String> getRoles(String userName, Set<String> userGroups) {
         Set<String> ret = new HashSet<>();
@@ -341,6 +379,18 @@ public final class AtlasSimpleAuthorizer implements 
AtlasAuthorizer {
 
         return ret;
     }
+
+    private void checkAccessAndScrub(AtlasEntityHeader entity, 
AtlasSearchResultScrubRequest request) throws AtlasAuthorizationException {
+        if (entity != null && request != null) {
+            final AtlasEntityAccessRequest entityAccessRequest = new 
AtlasEntityAccessRequest(request.getTypeRegistry(), AtlasPrivilege.ENTITY_READ, 
entity, request.getUser(), request.getUserGroups());
+
+            
entityAccessRequest.setClientIPAddress(request.getClientIPAddress());
+
+            if (!isAccessAllowed(entityAccessRequest)) {
+                scrubEntityHeader(entity);
+            }
+        }
+    }
 }
 
 

http://git-wip-us.apache.org/repos/asf/atlas/blob/eb895a62/repository/src/main/java/org/apache/atlas/discovery/EntityDiscoveryService.java
----------------------------------------------------------------------
diff --git 
a/repository/src/main/java/org/apache/atlas/discovery/EntityDiscoveryService.java
 
b/repository/src/main/java/org/apache/atlas/discovery/EntityDiscoveryService.java
index 9d0cc9d..2378d6b 100644
--- 
a/repository/src/main/java/org/apache/atlas/discovery/EntityDiscoveryService.java
+++ 
b/repository/src/main/java/org/apache/atlas/discovery/EntityDiscoveryService.java
@@ -23,6 +23,8 @@ import org.apache.atlas.AtlasErrorCode;
 import org.apache.atlas.AtlasException;
 import org.apache.atlas.SortOrder;
 import org.apache.atlas.annotation.GraphTransaction;
+import org.apache.atlas.authorize.AtlasAuthorizationUtils;
+import org.apache.atlas.authorize.AtlasSearchResultScrubRequest;
 import org.apache.atlas.exception.AtlasBaseException;
 import org.apache.atlas.model.discovery.AtlasSearchResult;
 import org.apache.atlas.model.discovery.AtlasSearchResult.AtlasFullTextResult;
@@ -167,6 +169,8 @@ public class EntityDiscoveryService implements 
AtlasDiscoveryService {
             }
         }
 
+        scrubSearchResults(ret);
+
         return ret;
     }
 
@@ -183,6 +187,8 @@ public class EntityDiscoveryService implements 
AtlasDiscoveryService {
         }
         ret.setFullTextResult(getIndexQueryResults(idxQuery, params, 
excludeDeletedEntities));
 
+        scrubSearchResults(ret);
+
         return ret;
     }
 
@@ -408,6 +414,8 @@ public class EntityDiscoveryService implements 
AtlasDiscoveryService {
             }
         }
 
+        scrubSearchResults(ret);
+
         return ret;
     }
 
@@ -504,6 +512,8 @@ public class EntityDiscoveryService implements 
AtlasDiscoveryService {
             searchTracker.remove(searchID);
         }
 
+        scrubSearchResults(ret);
+
         return ret;
     }
 
@@ -612,6 +622,8 @@ public class EntityDiscoveryService implements 
AtlasDiscoveryService {
             graph.releaseGremlinScriptEngine(scriptEngine);
         }
 
+        scrubSearchResults(ret);
+
         return ret;
     }
 
@@ -929,4 +941,8 @@ public class EntityDiscoveryService implements 
AtlasDiscoveryService {
             throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "invalid 
data");
         }
     }
+
+    private void scrubSearchResults(AtlasSearchResult result) throws 
AtlasBaseException {
+        AtlasAuthorizationUtils.scrubSearchResults(new 
AtlasSearchResultScrubRequest(typeRegistry, result));
+    }
 }

http://git-wip-us.apache.org/repos/asf/atlas/blob/eb895a62/repository/src/main/java/org/apache/atlas/glossary/GlossaryService.java
----------------------------------------------------------------------
diff --git 
a/repository/src/main/java/org/apache/atlas/glossary/GlossaryService.java 
b/repository/src/main/java/org/apache/atlas/glossary/GlossaryService.java
index fb26598..9229d2d 100644
--- a/repository/src/main/java/org/apache/atlas/glossary/GlossaryService.java
+++ b/repository/src/main/java/org/apache/atlas/glossary/GlossaryService.java
@@ -1026,13 +1026,17 @@ public class GlossaryService {
         Map<String, AtlasGlossaryTerm> termMap = new HashMap<>();
         dataAccess.load(terms).iterator().forEachRemaining(t -> 
termMap.put(t.getGuid(), t));
 
-        termHeaders.forEach(t -> 
t.setDisplayText(termMap.get(t.getTermGuid()).getName()));
+        termHeaders.forEach(t -> 
t.setDisplayText(getDisplayText(termMap.get(t.getTermGuid()))));
     }
 
     private boolean isNameInvalid(String name) {
         return StringUtils.containsAny(name, invalidNameChars);
     }
 
+    private String getDisplayText(AtlasGlossaryTerm term) {
+        return term != null ? term.getName() : null;
+    }
+
     static class PaginationHelper<T> {
         private int     pageStart;
         private int     pageEnd;

http://git-wip-us.apache.org/repos/asf/atlas/blob/eb895a62/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasEntityStoreV2.java
----------------------------------------------------------------------
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 40593be..1b709e4 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
@@ -525,7 +525,7 @@ public class AtlasEntityStoreV2 implements AtlasEntityStore 
{
 
         AtlasEntityHeader entityHeader = 
entityRetriever.toAtlasEntityHeaderWithClassifications(guid);
 
-        AtlasAuthorizationUtils.verifyAccess(new 
AtlasEntityAccessRequest(typeRegistry, 
AtlasPrivilege.ENTITY_READ_CLASSIFICATION, entityHeader), "get classifications: 
guid=", guid);
+        AtlasAuthorizationUtils.verifyAccess(new 
AtlasEntityAccessRequest(typeRegistry, AtlasPrivilege.ENTITY_READ, 
entityHeader), "get classifications: guid=", guid);
 
         return entityHeader.getClassifications();
     }
@@ -541,7 +541,7 @@ public class AtlasEntityStoreV2 implements AtlasEntityStore 
{
         AtlasEntityHeader   entityHeader = 
entityRetriever.toAtlasEntityHeaderWithClassifications(guid);
 
         if (CollectionUtils.isNotEmpty(entityHeader.getClassifications())) {
-            AtlasAuthorizationUtils.verifyAccess(new 
AtlasEntityAccessRequest(typeRegistry, 
AtlasPrivilege.ENTITY_READ_CLASSIFICATION, entityHeader), "get classification: 
guid=", guid, ", classification=", classificationName);
+            AtlasAuthorizationUtils.verifyAccess(new 
AtlasEntityAccessRequest(typeRegistry, AtlasPrivilege.ENTITY_READ, 
entityHeader), "get classification: guid=", guid, ", classification=", 
classificationName);
 
             for (AtlasClassification classification : 
entityHeader.getClassifications()) {
                 if 
(!StringUtils.equalsIgnoreCase(classification.getTypeName(), 
classificationName)) {

Reply via email to