Commit f077bbbf by nixonrodrigues Committed by Madhan Neethiraj

ATLAS-3898: authorization updates to require TYPE_READ permission for type-def read

parent 41eebcf4
...@@ -199,6 +199,28 @@ public class AtlasAuthorizationUtils { ...@@ -199,6 +199,28 @@ public class AtlasAuthorizationUtils {
return ret; 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){ public static List<String> getForwardedAddressesFromRequest(HttpServletRequest httpServletRequest){
String ipAddress = httpServletRequest.getHeader("X-FORWARDED-FOR"); String ipAddress = httpServletRequest.getHeader("X-FORWARDED-FOR");
String[] forwardedAddresses = null ; String[] forwardedAddresses = null ;
......
...@@ -101,4 +101,8 @@ public interface AtlasAuthorizer { ...@@ -101,4 +101,8 @@ public interface AtlasAuthorizer {
entity.getMeaningNames().clear(); entity.getMeaningNames().clear();
} }
} }
default
void filterTypesDef(AtlasTypesDefFilterRequest request) throws AtlasAuthorizationException {
}
} }
...@@ -42,7 +42,9 @@ public enum AtlasPrivilege { ...@@ -42,7 +42,9 @@ public enum AtlasPrivilege {
ENTITY_ADD_LABEL("entity-add-label"), ENTITY_ADD_LABEL("entity-add-label"),
ENTITY_REMOVE_LABEL("entity-remove-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; private final String type;
......
/**
* 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; ...@@ -23,6 +23,7 @@ import java.io.InputStream;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.ListIterator;
import java.util.Set; import java.util.Set;
import org.apache.atlas.ApplicationProperties; import org.apache.atlas.ApplicationProperties;
...@@ -32,6 +33,8 @@ import org.apache.atlas.authorize.simple.AtlasSimpleAuthzPolicy.*; ...@@ -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;
import org.apache.atlas.model.discovery.AtlasSearchResult.AtlasFullTextResult; import org.apache.atlas.model.discovery.AtlasSearchResult.AtlasFullTextResult;
import org.apache.atlas.model.instance.AtlasEntityHeader; 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.atlas.utils.AtlasJson;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils; import org.apache.commons.collections.MapUtils;
...@@ -39,6 +42,11 @@ import org.apache.commons.lang.StringUtils; ...@@ -39,6 +42,11 @@ import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; 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 { public final class AtlasSimpleAuthorizer implements AtlasAuthorizer {
private static final Logger LOG = LoggerFactory.getLogger(AtlasSimpleAuthorizer.class); private static final Logger LOG = LoggerFactory.getLogger(AtlasSimpleAuthorizer.class);
...@@ -61,6 +69,8 @@ public final class AtlasSimpleAuthorizer implements AtlasAuthorizer { ...@@ -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"); inputStream = ApplicationProperties.getFileAsInputStream(ApplicationProperties.get(), "atlas.authorizer.simple.authz.policy.file", "atlas-simple-authz-policy.json");
authzPolicy = AtlasJson.fromJson(inputStream, AtlasSimpleAuthzPolicy.class); authzPolicy = AtlasJson.fromJson(inputStream, AtlasSimpleAuthzPolicy.class);
addImpliedTypeReadPrivilege(authzPolicy);
} catch (IOException | AtlasException e) { } catch (IOException | AtlasException e) {
LOG.error("SimpleAtlasAuthorizer.init(): initialization failed", e); LOG.error("SimpleAtlasAuthorizer.init(): initialization failed", e);
...@@ -313,6 +323,18 @@ public final class AtlasSimpleAuthorizer implements AtlasAuthorizer { ...@@ -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) { private Set<String> getRoles(String userName, Set<String> userGroups) {
Set<String> ret = new HashSet<>(); Set<String> ret = new HashSet<>();
...@@ -467,6 +489,46 @@ public final class AtlasSimpleAuthorizer implements AtlasAuthorizer { ...@@ -467,6 +489,46 @@ public final class AtlasSimpleAuthorizer implements AtlasAuthorizer {
private boolean isBusinessMetadataMatch(AtlasEntityAccessRequest request, AtlasEntityPermission permission) { private boolean isBusinessMetadataMatch(AtlasEntityAccessRequest request, AtlasEntityPermission permission) {
return AtlasPrivilege.ENTITY_UPDATE_BUSINESS_METADATA.equals(request.getAction()) ? isMatch(request.getBusinessMetadata(), permission.getBusinessMetadata()) : true; 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; ...@@ -20,6 +20,10 @@ package org.apache.atlas.repository.store.graph;
import org.apache.atlas.AtlasErrorCode; import org.apache.atlas.AtlasErrorCode;
import org.apache.atlas.GraphTransactionInterceptor; import org.apache.atlas.GraphTransactionInterceptor;
import org.apache.atlas.annotation.GraphTransaction; 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.exception.AtlasBaseException;
import org.apache.atlas.listener.ChangedTypeDefs; import org.apache.atlas.listener.ChangedTypeDefs;
import org.apache.atlas.listener.TypeDefChangeListener; import org.apache.atlas.listener.TypeDefChangeListener;
...@@ -120,6 +124,9 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore { ...@@ -120,6 +124,9 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore {
if (ret == null) { if (ret == null) {
throw new AtlasBaseException(AtlasErrorCode.TYPE_NAME_NOT_FOUND, name); throw new AtlasBaseException(AtlasErrorCode.TYPE_NAME_NOT_FOUND, name);
} }
AtlasAuthorizationUtils.verifyAccess(new AtlasTypeAccessRequest(AtlasPrivilege.TYPE_READ, ret), "read type ", name);
return ret; return ret;
} }
...@@ -129,6 +136,9 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore { ...@@ -129,6 +136,9 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore {
if (ret == null) { if (ret == null) {
throw new AtlasBaseException(AtlasErrorCode.TYPE_GUID_NOT_FOUND, guid); throw new AtlasBaseException(AtlasErrorCode.TYPE_GUID_NOT_FOUND, guid);
} }
AtlasAuthorizationUtils.verifyAccess(new AtlasTypeAccessRequest(AtlasPrivilege.TYPE_READ, ret), "read type ", ret.getName());
return ret; return ret;
} }
...@@ -160,6 +170,8 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore { ...@@ -160,6 +170,8 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore {
throw new AtlasBaseException(AtlasErrorCode.TYPE_NAME_NOT_FOUND, name); throw new AtlasBaseException(AtlasErrorCode.TYPE_NAME_NOT_FOUND, name);
} }
AtlasAuthorizationUtils.verifyAccess(new AtlasTypeAccessRequest(AtlasPrivilege.TYPE_READ, ret), "read type ", name);
return ret; return ret;
} }
...@@ -171,6 +183,8 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore { ...@@ -171,6 +183,8 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore {
throw new AtlasBaseException(AtlasErrorCode.TYPE_GUID_NOT_FOUND, guid); throw new AtlasBaseException(AtlasErrorCode.TYPE_GUID_NOT_FOUND, guid);
} }
AtlasAuthorizationUtils.verifyAccess(new AtlasTypeAccessRequest(AtlasPrivilege.TYPE_READ, ret), "read type ", ret.getName());
return ret; return ret;
} }
...@@ -182,6 +196,8 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore { ...@@ -182,6 +196,8 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore {
throw new AtlasBaseException(AtlasErrorCode.TYPE_NAME_NOT_FOUND, name); throw new AtlasBaseException(AtlasErrorCode.TYPE_NAME_NOT_FOUND, name);
} }
AtlasAuthorizationUtils.verifyAccess(new AtlasTypeAccessRequest(AtlasPrivilege.TYPE_READ, ret), "read type ", name);
return ret; return ret;
} }
...@@ -193,6 +209,8 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore { ...@@ -193,6 +209,8 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore {
throw new AtlasBaseException(AtlasErrorCode.TYPE_GUID_NOT_FOUND, guid); throw new AtlasBaseException(AtlasErrorCode.TYPE_GUID_NOT_FOUND, guid);
} }
AtlasAuthorizationUtils.verifyAccess(new AtlasTypeAccessRequest(AtlasPrivilege.TYPE_READ, ret), "read type ", ret.getName());
return ret; return ret;
} }
...@@ -204,6 +222,8 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore { ...@@ -204,6 +222,8 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore {
throw new AtlasBaseException(AtlasErrorCode.TYPE_NAME_NOT_FOUND, name); throw new AtlasBaseException(AtlasErrorCode.TYPE_NAME_NOT_FOUND, name);
} }
AtlasAuthorizationUtils.verifyAccess(new AtlasTypeAccessRequest(AtlasPrivilege.TYPE_READ, ret), "read type ", name);
return ret; return ret;
} }
...@@ -215,6 +235,8 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore { ...@@ -215,6 +235,8 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore {
throw new AtlasBaseException(AtlasErrorCode.TYPE_GUID_NOT_FOUND, guid); throw new AtlasBaseException(AtlasErrorCode.TYPE_GUID_NOT_FOUND, guid);
} }
AtlasAuthorizationUtils.verifyAccess(new AtlasTypeAccessRequest(AtlasPrivilege.TYPE_READ, ret), "read type ", ret.getName());
return ret; return ret;
} }
...@@ -250,6 +272,8 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore { ...@@ -250,6 +272,8 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore {
} }
} }
AtlasAuthorizationUtils.verifyAccess(new AtlasTypeAccessRequest(AtlasPrivilege.TYPE_READ, ret), "read type ", name);
return ret; return ret;
} }
...@@ -261,6 +285,8 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore { ...@@ -261,6 +285,8 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore {
throw new AtlasBaseException(AtlasErrorCode.TYPE_GUID_NOT_FOUND, guid); throw new AtlasBaseException(AtlasErrorCode.TYPE_GUID_NOT_FOUND, guid);
} }
AtlasAuthorizationUtils.verifyAccess(new AtlasTypeAccessRequest(AtlasPrivilege.TYPE_READ, ret), "read type ", ret.getName());
return ret; return ret;
} }
...@@ -298,6 +324,8 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore { ...@@ -298,6 +324,8 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore {
} }
} }
AtlasAuthorizationUtils.verifyAccess(new AtlasTypeAccessRequest(AtlasPrivilege.TYPE_READ, ret), "read type ", name);
return ret; return ret;
} }
...@@ -309,6 +337,8 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore { ...@@ -309,6 +337,8 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore {
throw new AtlasBaseException(AtlasErrorCode.TYPE_GUID_NOT_FOUND, guid); throw new AtlasBaseException(AtlasErrorCode.TYPE_GUID_NOT_FOUND, guid);
} }
AtlasAuthorizationUtils.verifyAccess(new AtlasTypeAccessRequest(AtlasPrivilege.TYPE_READ, ret), "read type ", ret.getName());
return ret; return ret;
} }
...@@ -722,6 +752,8 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore { ...@@ -722,6 +752,8 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore {
} }
} }
AtlasAuthorizationUtils.filterTypesDef(new AtlasTypesDefFilterRequest(typesDef));
return typesDef; return typesDef;
} }
...@@ -771,6 +803,11 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore { ...@@ -771,6 +803,11 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore {
default: default:
throw new AtlasBaseException(AtlasErrorCode.SYSTEM_TYPE, type.getTypeCategory().name()); 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; return ret;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment