ATLAS-3898: authorization updates to require TYPE_READ permission for type-def read
Signed-off-by: Madhan Neethiraj <madhan@apache.org>
This commit is contained in:
parent
41eebcf4cf
commit
f077bbbf3b
|
|
@ -199,6 +199,28 @@ public class AtlasAuthorizationUtils {
|
|||
return ret;
|
||||
}
|
||||
|
||||
public static void filterTypesDef(AtlasTypesDefFilterRequest request) {
|
||||
MetricRecorder metric = RequestContext.get().startMetricRecord("filterTypesDef");
|
||||
String userName = getCurrentUserName();
|
||||
|
||||
if (StringUtils.isNotEmpty(userName) && !RequestContext.get().isImportInProgress()) {
|
||||
try {
|
||||
AtlasAuthorizer authorizer = AtlasAuthorizerFactory.getAtlasAuthorizer();
|
||||
|
||||
request.setUser(getCurrentUserName(), getCurrentUserGroups());
|
||||
request.setClientIPAddress(RequestContext.get().getClientIPAddress());
|
||||
request.setForwardedAddresses(RequestContext.get().getForwardedAddresses());
|
||||
request.setRemoteIPAddress(RequestContext.get().getClientIPAddress());
|
||||
|
||||
authorizer.filterTypesDef(request);
|
||||
} catch (AtlasAuthorizationException e) {
|
||||
LOG.error("Unable to obtain AtlasAuthorizer", e);
|
||||
}
|
||||
}
|
||||
|
||||
RequestContext.get().endMetricRecord(metric);
|
||||
}
|
||||
|
||||
public static List<String> getForwardedAddressesFromRequest(HttpServletRequest httpServletRequest){
|
||||
String ipAddress = httpServletRequest.getHeader("X-FORWARDED-FOR");
|
||||
String[] forwardedAddresses = null ;
|
||||
|
|
|
|||
|
|
@ -101,4 +101,8 @@ public interface AtlasAuthorizer {
|
|||
entity.getMeaningNames().clear();
|
||||
}
|
||||
}
|
||||
|
||||
default
|
||||
void filterTypesDef(AtlasTypesDefFilterRequest request) throws AtlasAuthorizationException {
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,9 @@ public enum AtlasPrivilege {
|
|||
|
||||
ENTITY_ADD_LABEL("entity-add-label"),
|
||||
ENTITY_REMOVE_LABEL("entity-remove-label"),
|
||||
ENTITY_UPDATE_BUSINESS_METADATA("entity-update-business-metadata");
|
||||
ENTITY_UPDATE_BUSINESS_METADATA("entity-update-business-metadata"),
|
||||
|
||||
TYPE_READ("type-read");
|
||||
|
||||
private final String type;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,50 @@
|
|||
/**
|
||||
* 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.typedef.AtlasTypesDef;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class AtlasTypesDefFilterRequest extends AtlasAccessRequest {
|
||||
private final AtlasTypesDef typesDef;
|
||||
|
||||
|
||||
public AtlasTypesDefFilterRequest(AtlasTypesDef typesDef) {
|
||||
super(AtlasPrivilege.TYPE_READ);
|
||||
|
||||
this.typesDef = typesDef;
|
||||
}
|
||||
|
||||
public AtlasTypesDefFilterRequest(AtlasTypesDef typesDef, String userName, Set<String> usergroups) {
|
||||
super(AtlasPrivilege.TYPE_READ, userName, usergroups);
|
||||
|
||||
this.typesDef = typesDef;
|
||||
}
|
||||
|
||||
public AtlasTypesDef getTypesDef() {
|
||||
return typesDef;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AtlasTypesDefFilterRequest[typesDef=" + typesDef + ", action=" + getAction() + ", accessTime=" + getAccessTime() +
|
||||
", user=" + getUser() + ", userGroups=" + getUserGroups() + ", clientIPAddress=" + getClientIPAddress() +
|
||||
", forwardedAddresses=" + getForwardedAddresses() + ", remoteIPAddress=" + getRemoteIPAddress() + "]";
|
||||
}
|
||||
}
|
||||
|
|
@ -23,6 +23,7 @@ import java.io.InputStream;
|
|||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.atlas.ApplicationProperties;
|
||||
|
|
@ -32,6 +33,8 @@ 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.model.typedef.AtlasBaseTypeDef;
|
||||
import org.apache.atlas.model.typedef.AtlasTypesDef;
|
||||
import org.apache.atlas.utils.AtlasJson;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.collections.MapUtils;
|
||||
|
|
@ -39,6 +42,11 @@ import org.apache.commons.lang.StringUtils;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static org.apache.atlas.authorize.AtlasPrivilege.TYPE_CREATE;
|
||||
import static org.apache.atlas.authorize.AtlasPrivilege.TYPE_DELETE;
|
||||
import static org.apache.atlas.authorize.AtlasPrivilege.TYPE_READ;
|
||||
import static org.apache.atlas.authorize.AtlasPrivilege.TYPE_UPDATE;
|
||||
|
||||
|
||||
public final class AtlasSimpleAuthorizer implements AtlasAuthorizer {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AtlasSimpleAuthorizer.class);
|
||||
|
|
@ -61,6 +69,8 @@ public final class AtlasSimpleAuthorizer implements AtlasAuthorizer {
|
|||
inputStream = ApplicationProperties.getFileAsInputStream(ApplicationProperties.get(), "atlas.authorizer.simple.authz.policy.file", "atlas-simple-authz-policy.json");
|
||||
|
||||
authzPolicy = AtlasJson.fromJson(inputStream, AtlasSimpleAuthzPolicy.class);
|
||||
|
||||
addImpliedTypeReadPrivilege(authzPolicy);
|
||||
} catch (IOException | AtlasException e) {
|
||||
LOG.error("SimpleAtlasAuthorizer.init(): initialization failed", e);
|
||||
|
||||
|
|
@ -313,6 +323,18 @@ public final class AtlasSimpleAuthorizer implements AtlasAuthorizer {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void filterTypesDef(AtlasTypesDefFilterRequest request) throws AtlasAuthorizationException {
|
||||
AtlasTypesDef typesDef = request.getTypesDef();
|
||||
|
||||
filterTypes(request, typesDef.getEnumDefs());
|
||||
filterTypes(request, typesDef.getStructDefs());
|
||||
filterTypes(request, typesDef.getEntityDefs());
|
||||
filterTypes(request, typesDef.getClassificationDefs());
|
||||
filterTypes(request, typesDef.getRelationshipDefs());
|
||||
filterTypes(request, typesDef.getBusinessMetadataDefs());
|
||||
}
|
||||
|
||||
private Set<String> getRoles(String userName, Set<String> userGroups) {
|
||||
Set<String> ret = new HashSet<>();
|
||||
|
||||
|
|
@ -467,6 +489,46 @@ public final class AtlasSimpleAuthorizer implements AtlasAuthorizer {
|
|||
private boolean isBusinessMetadataMatch(AtlasEntityAccessRequest request, AtlasEntityPermission permission) {
|
||||
return AtlasPrivilege.ENTITY_UPDATE_BUSINESS_METADATA.equals(request.getAction()) ? isMatch(request.getBusinessMetadata(), permission.getBusinessMetadata()) : true;
|
||||
}
|
||||
|
||||
private void filterTypes(AtlasAccessRequest request, List<? extends AtlasBaseTypeDef> typeDefs)throws AtlasAuthorizationException {
|
||||
if (typeDefs != null) {
|
||||
for (ListIterator<? extends AtlasBaseTypeDef> iter = typeDefs.listIterator(); iter.hasNext();) {
|
||||
AtlasBaseTypeDef typeDef = iter.next();
|
||||
AtlasTypeAccessRequest typeRequest = new AtlasTypeAccessRequest(request.getAction(), typeDef, request.getUser(), request.getUserGroups());
|
||||
|
||||
typeRequest.setClientIPAddress(request.getClientIPAddress());
|
||||
typeRequest.setForwardedAddresses(request.getForwardedAddresses());
|
||||
typeRequest.setRemoteIPAddress(request.getRemoteIPAddress());
|
||||
|
||||
if (!isAccessAllowed(typeRequest)) {
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add TYPE_READ privilege, if at least one of the following is granted: TYPE_CREATE, TYPE_UPDATE, TYPE_DELETE
|
||||
private void addImpliedTypeReadPrivilege(AtlasSimpleAuthzPolicy policy) {
|
||||
if (policy != null && policy.getRoles() != null) {
|
||||
for (AtlasAuthzRole role : policy.getRoles().values()) {
|
||||
if (role.getTypePermissions() == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (AtlasTypePermission permission : role.getTypePermissions()) {
|
||||
List<String> privileges = permission.getPrivileges();
|
||||
|
||||
if (CollectionUtils.isEmpty(privileges) || privileges.contains(TYPE_READ.name())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (privileges.contains(TYPE_CREATE.name()) || privileges.contains(TYPE_UPDATE.name()) || privileges.contains(TYPE_DELETE.name())) {
|
||||
privileges.add(TYPE_READ.name());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,10 @@ package org.apache.atlas.repository.store.graph;
|
|||
import org.apache.atlas.AtlasErrorCode;
|
||||
import org.apache.atlas.GraphTransactionInterceptor;
|
||||
import org.apache.atlas.annotation.GraphTransaction;
|
||||
import org.apache.atlas.authorize.AtlasAuthorizationUtils;
|
||||
import org.apache.atlas.authorize.AtlasPrivilege;
|
||||
import org.apache.atlas.authorize.AtlasTypeAccessRequest;
|
||||
import org.apache.atlas.authorize.AtlasTypesDefFilterRequest;
|
||||
import org.apache.atlas.exception.AtlasBaseException;
|
||||
import org.apache.atlas.listener.ChangedTypeDefs;
|
||||
import org.apache.atlas.listener.TypeDefChangeListener;
|
||||
|
|
@ -120,6 +124,9 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore {
|
|||
if (ret == null) {
|
||||
throw new AtlasBaseException(AtlasErrorCode.TYPE_NAME_NOT_FOUND, name);
|
||||
}
|
||||
|
||||
AtlasAuthorizationUtils.verifyAccess(new AtlasTypeAccessRequest(AtlasPrivilege.TYPE_READ, ret), "read type ", name);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -129,6 +136,9 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore {
|
|||
if (ret == null) {
|
||||
throw new AtlasBaseException(AtlasErrorCode.TYPE_GUID_NOT_FOUND, guid);
|
||||
}
|
||||
|
||||
AtlasAuthorizationUtils.verifyAccess(new AtlasTypeAccessRequest(AtlasPrivilege.TYPE_READ, ret), "read type ", ret.getName());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -160,6 +170,8 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore {
|
|||
throw new AtlasBaseException(AtlasErrorCode.TYPE_NAME_NOT_FOUND, name);
|
||||
}
|
||||
|
||||
AtlasAuthorizationUtils.verifyAccess(new AtlasTypeAccessRequest(AtlasPrivilege.TYPE_READ, ret), "read type ", name);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -171,6 +183,8 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore {
|
|||
throw new AtlasBaseException(AtlasErrorCode.TYPE_GUID_NOT_FOUND, guid);
|
||||
}
|
||||
|
||||
AtlasAuthorizationUtils.verifyAccess(new AtlasTypeAccessRequest(AtlasPrivilege.TYPE_READ, ret), "read type ", ret.getName());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -182,6 +196,8 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore {
|
|||
throw new AtlasBaseException(AtlasErrorCode.TYPE_NAME_NOT_FOUND, name);
|
||||
}
|
||||
|
||||
AtlasAuthorizationUtils.verifyAccess(new AtlasTypeAccessRequest(AtlasPrivilege.TYPE_READ, ret), "read type ", name);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -193,6 +209,8 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore {
|
|||
throw new AtlasBaseException(AtlasErrorCode.TYPE_GUID_NOT_FOUND, guid);
|
||||
}
|
||||
|
||||
AtlasAuthorizationUtils.verifyAccess(new AtlasTypeAccessRequest(AtlasPrivilege.TYPE_READ, ret), "read type ", ret.getName());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -204,6 +222,8 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore {
|
|||
throw new AtlasBaseException(AtlasErrorCode.TYPE_NAME_NOT_FOUND, name);
|
||||
}
|
||||
|
||||
AtlasAuthorizationUtils.verifyAccess(new AtlasTypeAccessRequest(AtlasPrivilege.TYPE_READ, ret), "read type ", name);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -215,6 +235,8 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore {
|
|||
throw new AtlasBaseException(AtlasErrorCode.TYPE_GUID_NOT_FOUND, guid);
|
||||
}
|
||||
|
||||
AtlasAuthorizationUtils.verifyAccess(new AtlasTypeAccessRequest(AtlasPrivilege.TYPE_READ, ret), "read type ", ret.getName());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -250,6 +272,8 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore {
|
|||
}
|
||||
}
|
||||
|
||||
AtlasAuthorizationUtils.verifyAccess(new AtlasTypeAccessRequest(AtlasPrivilege.TYPE_READ, ret), "read type ", name);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -261,6 +285,8 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore {
|
|||
throw new AtlasBaseException(AtlasErrorCode.TYPE_GUID_NOT_FOUND, guid);
|
||||
}
|
||||
|
||||
AtlasAuthorizationUtils.verifyAccess(new AtlasTypeAccessRequest(AtlasPrivilege.TYPE_READ, ret), "read type ", ret.getName());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -298,6 +324,8 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore {
|
|||
}
|
||||
}
|
||||
|
||||
AtlasAuthorizationUtils.verifyAccess(new AtlasTypeAccessRequest(AtlasPrivilege.TYPE_READ, ret), "read type ", name);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -309,6 +337,8 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore {
|
|||
throw new AtlasBaseException(AtlasErrorCode.TYPE_GUID_NOT_FOUND, guid);
|
||||
}
|
||||
|
||||
AtlasAuthorizationUtils.verifyAccess(new AtlasTypeAccessRequest(AtlasPrivilege.TYPE_READ, ret), "read type ", ret.getName());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -722,6 +752,8 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore {
|
|||
}
|
||||
}
|
||||
|
||||
AtlasAuthorizationUtils.filterTypesDef(new AtlasTypesDefFilterRequest(typesDef));
|
||||
|
||||
return typesDef;
|
||||
}
|
||||
|
||||
|
|
@ -771,6 +803,11 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore {
|
|||
default:
|
||||
throw new AtlasBaseException(AtlasErrorCode.SYSTEM_TYPE, type.getTypeCategory().name());
|
||||
}
|
||||
|
||||
if (ret != null) {
|
||||
AtlasAuthorizationUtils.verifyAccess(new AtlasTypeAccessRequest(AtlasPrivilege.TYPE_READ, ret), "read type ", ret.getName());
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue