ATLAS-2765: updated authorization model to scrub search-results (clear entity-attributes, classifications) for entities the user doesn't have read access to
This commit is contained in:
parent
80f556a704
commit
eb895a62fd
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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() + "]";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue