Skip to content

Commit

Permalink
added_list_values_support_similar_to_contains_adminUser
Browse files Browse the repository at this point in the history
  • Loading branch information
nikhilbonte21 committed Mar 8, 2024
1 parent 2fa7ac3 commit c07ddd7
Show file tree
Hide file tree
Showing 8 changed files with 284 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,10 @@ Set<List<RangerResourceDef>> getHierarchies(DirectedGraph graph, Map<String, Ran
}
}

if (sinks.contains("entityAttr")) {
hierarchies.add(Lists.newArrayList("entityAttr"));
}

return convertHierarchies(hierarchies, resourceMap);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -714,43 +714,45 @@ private List<RangerPolicyEvaluator> getLikelyMatchPolicyEvaluators(Map<String, R
Set<RangerPolicyEvaluator> serviceResourceMatchersForResource = trie.getEvaluatorsForResource(resource.getValue(resourceName), request.getResourceMatchingScope());
Set<RangerPolicyEvaluator> inheritedResourceMatchers = trie.getInheritedEvaluators();

if (smallestList != null) {
if (CollectionUtils.isEmpty(inheritedResourceMatchers) && CollectionUtils.isEmpty(serviceResourceMatchersForResource)) {
smallestList = null;
} else if (CollectionUtils.isEmpty(inheritedResourceMatchers)) {
smallestList.retainAll(serviceResourceMatchersForResource);
} else if (CollectionUtils.isEmpty(serviceResourceMatchersForResource)) {
smallestList.retainAll(inheritedResourceMatchers);
} else {
Set<RangerPolicyEvaluator> smaller, bigger;
if (serviceResourceMatchersForResource.size() < inheritedResourceMatchers.size()) {
smaller = serviceResourceMatchersForResource;
bigger = inheritedResourceMatchers;
} else {
smaller = inheritedResourceMatchers;
bigger = serviceResourceMatchersForResource;
}
Set<RangerPolicyEvaluator> tmp = new HashSet<>();
if (smallestList.size() < smaller.size()) {
smallestList.stream().filter(smaller::contains).forEach(tmp::add);
smallestList.stream().filter(bigger::contains).forEach(tmp::add);
if (serviceResourceMatchersForResource != null) {
if (smallestList != null) {
if (CollectionUtils.isEmpty(inheritedResourceMatchers) && CollectionUtils.isEmpty(serviceResourceMatchersForResource)) {
smallestList = null;
} else if (CollectionUtils.isEmpty(inheritedResourceMatchers)) {
smallestList.retainAll(serviceResourceMatchersForResource);
} else if (CollectionUtils.isEmpty(serviceResourceMatchersForResource)) {
smallestList.retainAll(inheritedResourceMatchers);
} else {
smaller.stream().filter(smallestList::contains).forEach(tmp::add);
if (smallestList.size() < bigger.size()) {
Set<RangerPolicyEvaluator> smaller, bigger;
if (serviceResourceMatchersForResource.size() < inheritedResourceMatchers.size()) {
smaller = serviceResourceMatchersForResource;
bigger = inheritedResourceMatchers;
} else {
smaller = inheritedResourceMatchers;
bigger = serviceResourceMatchersForResource;
}
Set<RangerPolicyEvaluator> tmp = new HashSet<>();
if (smallestList.size() < smaller.size()) {
smallestList.stream().filter(smaller::contains).forEach(tmp::add);
smallestList.stream().filter(bigger::contains).forEach(tmp::add);
} else {
bigger.stream().filter(smallestList::contains).forEach(tmp::add);
smaller.stream().filter(smallestList::contains).forEach(tmp::add);
if (smallestList.size() < bigger.size()) {
smallestList.stream().filter(bigger::contains).forEach(tmp::add);
} else {
bigger.stream().filter(smallestList::contains).forEach(tmp::add);
}
}
smallestList = tmp;
}
smallestList = tmp;
}
} else {
if (CollectionUtils.isEmpty(inheritedResourceMatchers) || CollectionUtils.isEmpty(serviceResourceMatchersForResource)) {
Set<RangerPolicyEvaluator> tmp = CollectionUtils.isEmpty(inheritedResourceMatchers) ? serviceResourceMatchersForResource : inheritedResourceMatchers;
smallestList = resourceKeys.size() == 1 || CollectionUtils.isEmpty(tmp) ? tmp : new HashSet<>(tmp);
} else {
smallestList = new HashSet<>(serviceResourceMatchersForResource);
smallestList.addAll(inheritedResourceMatchers);
if (CollectionUtils.isEmpty(inheritedResourceMatchers) || CollectionUtils.isEmpty(serviceResourceMatchersForResource)) {
Set<RangerPolicyEvaluator> tmp = CollectionUtils.isEmpty(inheritedResourceMatchers) ? serviceResourceMatchersForResource : inheritedResourceMatchers;
smallestList = resourceKeys.size() == 1 || CollectionUtils.isEmpty(tmp) ? tmp : new HashSet<>(tmp);
} else {
smallestList = new HashSet<>(serviceResourceMatchersForResource);
smallestList.addAll(inheritedResourceMatchers);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,12 @@ private TrieNode<T> buildTrie(RangerResourceDef resourceDef, List<T> evaluators,
ret.addWildcardEvaluator(evaluator);
} else {
if (CollectionUtils.isNotEmpty(policyResource.getValues())) {
boolean isEntityAttrs = resourceDef.getName().equals("entityAttr");
for (String resource : policyResource.getValues()) {
if (isEntityAttrs && !resource.equals("*")) {
resource = resource.split(":")[1];
}

if (!isMultiThreaded) {
insert(ret, resource, policyResource.getIsRecursive(), evaluator);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ public void setPolicyResources(Map<String, RangerPolicyResource> policyResources
@Override
public void setPolicyResources(Map<String, RangerPolicyResource> policyResources, String policyType) {
this.policyResources = policyResources;
if (this.policyResources.keySet().contains("entity-type") && !this.policyResources.keySet().contains("entityAttr")) {
this.policyResources.put("entityAttr", new RangerPolicyResource("*"));
}
this.policyType = policyType;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
/*
* 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.plugin.resourcematcher;


import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;


public class RangerEntityResourceMatcher extends RangerAbstractResourceMatcher {
private static final Log LOG = LogFactory.getLog(RangerEntityResourceMatcher.class);

@Override
public void init() {
if(LOG.isDebugEnabled()) {
LOG.debug("==> RangerAbstractResourceMatcher.init()");
}

Map<String, String> options = resourceDef != null ? resourceDef.getMatcherOptions() : null;

optIgnoreCase = getOptionIgnoreCase(options);
optQuotedCaseSensitive = getOptionQuotedCaseSensitive(options);
optQuoteChars = getOptionQuoteChars(options);
optWildCard = getOptionWildCard(options);

policyValues = new ArrayList<>();
policyIsExcludes = policyResource != null && policyResource.getIsExcludes();

if (policyResource != null && policyResource.getValues() != null) {
for (String policyValue : policyResource.getValues()) {
if (StringUtils.isEmpty(policyValue)) {
continue;
}
policyValues.add(policyValue);
}
}

optReplaceTokens = getOptionReplaceTokens(options);

if(optReplaceTokens) {
startDelimiterChar = getOptionDelimiterStart(options);
endDelimiterChar = getOptionDelimiterEnd(options);
escapeChar = getOptionDelimiterEscape(options);
tokenPrefix = getOptionDelimiterPrefix(options);

if(escapeChar == startDelimiterChar || escapeChar == endDelimiterChar ||
tokenPrefix.indexOf(escapeChar) != -1 || tokenPrefix.indexOf(startDelimiterChar) != -1 ||
tokenPrefix.indexOf(endDelimiterChar) != -1) {
String resouceName = resourceDef == null ? "" : resourceDef.getName();

String msg = "Invalid token-replacement parameters for resource '" + resouceName + "': { ";
msg += (OPTION_TOKEN_DELIMITER_START + "='" + startDelimiterChar + "'; ");
msg += (OPTION_TOKEN_DELIMITER_END + "='" + endDelimiterChar + "'; ");
msg += (OPTION_TOKEN_DELIMITER_ESCAPE + "='" + escapeChar + "'; ");
msg += (OPTION_TOKEN_DELIMITER_PREFIX + "='" + tokenPrefix + "' }. ");
msg += "Token replacement disabled";

LOG.error(msg);

optReplaceTokens = false;
}
}

resourceMatchers = buildResourceMatchers();
isMatchAny = resourceMatchers == null || CollectionUtils.isEmpty(resourceMatchers.getResourceMatchers());

if(LOG.isDebugEnabled()) {
LOG.debug("<== RangerAbstractResourceMatcher.init()");
}
}

protected ResourceMatcherWrapper buildResourceMatchers() {
List<ResourceMatcher> resourceMatchers = new ArrayList<>();
boolean needsDynamicEval = false;

for (String policyValue : policyValues) {
ResourceMatcher matcher = getMatcher(policyValue);

if (matcher != null) {
if (matcher.isMatchAny()) {
resourceMatchers.clear();
break;
}
if (!needsDynamicEval && matcher.getNeedsDynamicEval()) {
needsDynamicEval = true;
}
resourceMatchers.add(matcher);
}
}

Collections.sort(resourceMatchers, new ResourceMatcher.PriorityComparator());

return CollectionUtils.isNotEmpty(resourceMatchers) ?
new ResourceMatcherWrapper(needsDynamicEval, resourceMatchers) : null;
}

@Override
public boolean isMatch(Object resource, Map<String, Object> evalContext) {
if(LOG.isDebugEnabled()) {
LOG.debug("==> RangerDefaultResourceMatcher.isMatch(" + resource + ", " + evalContext + ")");
}

boolean ret = false;
boolean allValuesRequested = isAllValuesRequested(resource);

if(allValuesRequested || isMatchAny) {
ret = isMatchAny;
} else {
int resourceMatcherCount = resourceMatchers.getResourceMatchers().size();
int matchedResourceMatcherCount = 0;

for (ResourceMatcher resourceMatcher : resourceMatchers.getResourceMatchers()) {
Object value = ((Map<?, ?>) resource).get(resourceMatcher.attrName);

if (value instanceof String) {
boolean result = resourceMatcher.isMatch((String) value, evalContext);
if (result) {
matchedResourceMatcherCount++;
}
} else if (value instanceof Collection) {
Collection<String> collValue = (Collection<String>) value;

/*ret = resourceMatcher.isMatchAny(collValue, evalContext);
if (ret) {
break;
}*/

boolean result = resourceMatcher.isMatchAny(collValue, evalContext);
if (result) {
matchedResourceMatcherCount++;
}
}
}

if (matchedResourceMatcherCount == resourceMatcherCount) {
ret = true; //all resources for entityAttr matched
}
}

ret = applyExcludes(allValuesRequested, ret);

if(LOG.isDebugEnabled()) {
LOG.debug("<== RangerDefaultResourceMatcher.isMatch(" + resource + ", " + evalContext + "): " + ret);
}

return ret;
}

ResourceMatcher getMatcher(String policyValueRaw) {
final ResourceMatcher ret;

if (policyValueRaw.equals("*")){
return super.getMatcher(policyValueRaw);
}

String[] splitted = policyValueRaw.split(":");
String attrName = splitted[0];
String policyValue = splitted[1];

switch (attrName) {
case "certificateStatus":
ret = super.getMatcher(policyValue); break;



default:
ret = super.getMatcher(policyValue);
}
ret.attrName = attrName;

return ret;
}

public StringBuilder toString(StringBuilder sb) {
sb.append("RangerDefaultResourceMatcher={");

super.toString(sb);

sb.append("}");

return sb;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ abstract class ResourceMatcher {
private static final Log LOG = LogFactory.getLog(ResourceMatcher.class);

protected final String value;
protected String attrName;
protected StringTokenReplacer tokenReplacer;

static final int DYNAMIC_EVALUATION_PENALTY = 8;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,26 @@
"entity-update-classification",
"entity-remove-classification"
]
},
{
"itemId": 17,
"name": "entityAttr",
"type": "string",
"level": 40,
"parent": "entity",
"mandatory": false,
"isValidLeaf": true,
"lookupSupported": true,
"recursiveSupported": true,
"excludesSupported": true,
"matcher": "org.apache.atlas.plugin.resourcematcher.RangerEntityResourceMatcher",
"matcherOptions": {
"wildCard": "true",
"ignoreCase": "false"
},
"label": "Entity",
"description": "Entity",
"accessTypeRestrictions": ["entity-read", "entity-create", "entity-update", "entity-delete"]
}
],
"accessTypes": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import static org.apache.atlas.authorization.atlas.authorizer.RangerAtlasAuthorizerUtil.*;
import static org.apache.atlas.authorize.AtlasAuthorizationUtils.getCurrentUserGroups;
Expand Down Expand Up @@ -667,6 +668,15 @@ private boolean isAccessAllowed(AtlasEntityAccessRequest request, RangerAtlasAud

rangerResource.setValue(RESOURCE_ENTITY_TYPE, entityTypes);
rangerResource.setValue(RESOURCE_ENTITY_ID, entityId);
//Set<String> attributes = request.getEntity().getAttributes().entrySet().stream().map(x -> x.getKey() + ":" + x.getValue()).collect(Collectors.toSet());
//rangerResource.setValue("entityAttr", attributes);

rangerResource.setValue("entityAttr", request.getEntity().getAttributes());

//rangerResource.setValue("certificateStatus", request.getEntity().getAttribute("certificateStatus"));
//rangerResource.setValue("__typeName", request.getEntity().getTypeName());
//rangerResource.setValue("adminUsers", request.getEntity().getAttribute("adminUsers"));
//rangerResource.setValue("connectionQualifiedName", "connectionQualifiedName:" + (String) request.getEntity().getAttribute("connectionQualifiedName"));
rangerResource.setOwnerUser(ownerUser);
rangerRequest.setAccessType(action);
rangerRequest.setAction(action);
Expand Down

0 comments on commit c07ddd7

Please sign in to comment.