Skip to content

Commit

Permalink
RANGER-4529: script evaluator updated to reuse bindings for a request
Browse files Browse the repository at this point in the history
  • Loading branch information
mneethiraj committed Nov 18, 2023
1 parent 89fa061 commit b50feda
Show file tree
Hide file tree
Showing 9 changed files with 424 additions and 404 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,16 @@

package org.apache.ranger.plugin.conditionevaluator;

import org.apache.ranger.plugin.contextenricher.RangerTagForEval;
import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
import org.apache.ranger.plugin.policyengine.RangerRequestScriptEvaluator;
import org.apache.ranger.plugin.util.RangerAccessRequestUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

// Policy Condition to check if resource Tags does contain any of the policy Condition Tags

public class RangerAnyOfExpectedTagsPresentConditionEvaluator extends RangerAbstractConditionEvaluator {

private static final Logger LOG = LoggerFactory.getLogger(RangerAnyOfExpectedTagsPresentConditionEvaluator.class);
Expand Down Expand Up @@ -62,14 +61,17 @@ public boolean isMatched(RangerAccessRequest request) {
LOG.debug("==> RangerAnyOfExpectedTagsPresentConditionEvaluator.isMatched(" + request + ")");
}

boolean matched = false;

RangerRequestScriptEvaluator evaluator = new RangerRequestScriptEvaluator(request);
Set<String> resourceTags = evaluator.getAllTagTypes();
boolean matched = false;
Set<RangerTagForEval> resourceTags = RangerAccessRequestUtil.getRequestTagsFromContext(request.getContext());

if (resourceTags != null) {
// check if resource Tags does contain any of the policy Condition Tags
matched = (!Collections.disjoint(resourceTags, policyConditionTags));
for (RangerTagForEval tag : resourceTags) {
if (policyConditionTags.contains(tag.getType())) {
matched = true;
break;
}
}
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@

package org.apache.ranger.plugin.conditionevaluator;

import org.apache.ranger.plugin.contextenricher.RangerTagForEval;
import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
import org.apache.ranger.plugin.policyengine.RangerRequestScriptEvaluator;
import org.apache.ranger.plugin.util.RangerAccessRequestUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

Expand Down Expand Up @@ -62,13 +62,17 @@ public boolean isMatched(RangerAccessRequest request) {
LOG.debug("==> RangerNoneOfExpectedTagsPresentConditionEvaluator.isMatched(" + request + ")");
}

boolean matched = true;
RangerRequestScriptEvaluator evaluator = new RangerRequestScriptEvaluator(request);
Set<String> resourceTags = evaluator.getAllTagTypes();
boolean matched = true;
Set<RangerTagForEval> resourceTags = RangerAccessRequestUtil.getRequestTagsFromContext(request.getContext());

if (resourceTags != null) {
// check if resource Tags does not contain any tags in the policy condition
matched = (Collections.disjoint(resourceTags, policyConditionTags));
for (RangerTagForEval tag : resourceTags) {
if (policyConditionTags.contains(tag.getType())) {
matched = false;
break;
}
}
}

if(LOG.isDebugEnabled()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@
import java.util.List;
import java.util.Map;

import static org.apache.ranger.plugin.util.RangerCommonConstants.*;
import static org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_OPTION_ENABLE_JSON_CTX;


public class RangerScriptConditionEvaluator extends RangerAbstractConditionEvaluator {
private static final Logger LOG = LoggerFactory.getLogger(RangerScriptConditionEvaluator.class);
Expand Down Expand Up @@ -100,13 +101,13 @@ public boolean isMatched(RangerAccessRequest request) {
LOG.debug("RangerScriptConditionEvaluator.isMatched(): script={" + script + "}");
}

RangerRequestScriptEvaluator evaluator = new RangerRequestScriptEvaluator(request);

if (enableJsonCtx == null) { // if not specified in evaluatorOptions, set it on first call to isMatched()
enableJsonCtx = RangerRequestScriptEvaluator.needsJsonCtxEnabled(script);
}

evaluator.evaluateConditionScript(scriptEngine, script, enableJsonCtx);
RangerRequestScriptEvaluator evaluator = new RangerRequestScriptEvaluator(request, scriptEngine, enableJsonCtx);

evaluator.evaluateConditionScript(script);

result = evaluator.getResult();
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@
package org.apache.ranger.plugin.conditionevaluator;

import org.apache.commons.collections.CollectionUtils;
import org.apache.ranger.plugin.contextenricher.RangerTagForEval;
import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
import org.apache.ranger.plugin.policyengine.RangerRequestScriptEvaluator;
import org.apache.ranger.plugin.util.RangerAccessRequestUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -63,12 +64,21 @@ public boolean isMatched(RangerAccessRequest request) {

boolean matched = true;

if (CollectionUtils.isNotEmpty(policyConditionTags)) {
RangerRequestScriptEvaluator evaluator = new RangerRequestScriptEvaluator(request);
Set<String> resourceTags = evaluator.getAllTagTypes();
if (CollectionUtils.isNotEmpty(policyConditionTags)) {
Set<RangerTagForEval> resourceTags = RangerAccessRequestUtil.getRequestTagsFromContext(request.getContext());

// check if resource Tags atleast have to have all the tags in policy Condition
matched = resourceTags != null && resourceTags.containsAll(policyConditionTags);
if (CollectionUtils.isNotEmpty(resourceTags)) {
Set<String> tags = new HashSet<>(resourceTags.size());

for (RangerTagForEval tag : resourceTags) {
tags.add(tag.getType());
}

matched = tags.containsAll(policyConditionTags);
} else {
matched = false;
}
}

if(LOG.isDebugEnabled()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ public final class RangerRequestScriptEvaluator {
private static String[] dateFormatStrings = null;

private final RangerAccessRequest accessRequest;
private final ScriptEngine scriptEngine;
private final Bindings bindings;
private boolean initDone = false;
private Map<String, String> userAttrs = Collections.emptyMap();
private Map<String, Map<String, String>> groupAttrs = Collections.emptyMap();
Expand Down Expand Up @@ -179,84 +181,87 @@ public static String expandMacros(String script) {
return MACRO_PROCESSOR.expandMacros(script);
}

public RangerRequestScriptEvaluator(final RangerAccessRequest accessRequest) {
this.accessRequest = accessRequest.getReadOnlyCopy();
}

public Object evaluateScript(ScriptEngine scriptEngine, String script) {
script = expandMacros(script);

return evaluateScript(scriptEngine, script, needsJsonCtxEnabled(script));
public RangerRequestScriptEvaluator(RangerAccessRequest accessRequest, ScriptEngine scriptEngine) {
this(accessRequest, scriptEngine, true);
}

public Object evaluateConditionScript(ScriptEngine scriptEngine, String script, boolean enableJsonCtx) {
script = expandMacros(script);

Object ret = evaluateScript(scriptEngine, script, enableJsonCtx);

if (ret == null) {
ret = getResult();
}

if (ret instanceof Boolean) {
result = (Boolean) ret;
}

return ret;
}
public RangerRequestScriptEvaluator(RangerAccessRequest accessRequest, ScriptEngine scriptEngine, boolean enableJsonCtx) {
this.accessRequest = accessRequest.getReadOnlyCopy();
this.scriptEngine = scriptEngine;
this.bindings = scriptEngine.createBindings();

private Object evaluateScript(ScriptEngine scriptEngine, String script, boolean enableJsonCtx) {
Object ret = null;
Bindings bindings = scriptEngine.createBindings();
RangerTagForEval currentTag = this.getCurrentTag();
Map<String, String> tagAttribs = currentTag != null ? currentTag.getAttributes() : Collections.emptyMap();
boolean hasIncludes = StringUtils.contains(script, ".includes(");
boolean hasIntersects = StringUtils.contains(script, ".intersects(");
RangerTagForEval currentTag = this.getCurrentTag();
Map<String, String> tagAttribs = currentTag != null ? currentTag.getAttributes() : Collections.emptyMap();

bindings.put(SCRIPT_VAR_ctx, this);
bindings.put(SCRIPT_VAR_tag, currentTag);
bindings.put(SCRIPT_VAR_tagAttr, tagAttribs);

script = SCRIPT_SAFE_PREEXEC + script;
String preExecScript = "";

if (enableJsonCtx) {
bindings.put(SCRIPT_VAR__CTX_JSON, this.toJson());

script = SCRIPT_PREEXEC + script;
preExecScript += SCRIPT_PREEXEC;
}

if (hasIncludes) {
script = SCRIPT_POLYFILL_INCLUDES + script;
if (StringUtils.isNotBlank(preExecScript)) {
try {
scriptEngine.eval(preExecScript, bindings);
} catch (ScriptException excp) {
LOG.error("RangerRequestScriptEvaluator(): initialization failed", excp);
}
}
}

if (hasIntersects) {
script = SCRIPT_POLYFILL_INTERSECTS + script;
}
public Object evaluateScript(String script) {
script = expandMacros(script);

return evaluateScriptImpl(script);
}

if (JavaScriptEdits.hasDoubleBrackets(script)) {
script = JavaScriptEdits.replaceDoubleBrackets(script);
public Object evaluateConditionScript(String script) {
Object ret = evaluateScript(script);

if (ret == null) {
ret = getResult();
}

if (LOG.isDebugEnabled()) {
LOG.debug("RangerRequestScriptEvaluator.evaluateScript(): script={" + script + "}");
if (ret instanceof Boolean) {
result = (Boolean) ret;
}

return ret;
}

private Object evaluateScriptImpl(String script) {
Object ret = null;
RangerPerfTracer perf = null;

try {
long requestHash = accessRequest.hashCode();

if (RangerPerfTracer.isPerfTraceEnabled(PERF_POLICY_CONDITION_SCRIPT_EVAL)) {
perf = RangerPerfTracer.getPerfTracer(PERF_POLICY_CONDITION_SCRIPT_EVAL, "RangerRequestScriptEvaluator.evaluateScript(requestHash=" + requestHash + ")");
perf = RangerPerfTracer.getPerfTracer(PERF_POLICY_CONDITION_SCRIPT_EVAL, "RangerRequestScriptEvaluator.evaluateScript(requestHash=" + accessRequest.hashCode() + ")");
}

String preExec = SCRIPT_SAFE_PREEXEC;

if (script.contains(".includes(")) {
preExec += SCRIPT_POLYFILL_INCLUDES;
}

if (script.contains(".intersects(")) {
preExec += SCRIPT_POLYFILL_INTERSECTS;
}

ret = scriptEngine.eval(script, bindings);
if (JavaScriptEdits.hasDoubleBrackets(script)) {
script = JavaScriptEdits.replaceDoubleBrackets(script);
}

ret = scriptEngine.eval(preExec + script, bindings);
} catch (NullPointerException nullp) {
LOG.error("RangerRequestScriptEvaluator.evaluateScript(): eval called with NULL argument(s)", nullp);

} catch (ScriptException exception) {
LOG.error("RangerRequestScriptEvaluator.evaluateScript(): failed to evaluate script," +
" exception=" + exception);
} catch (ScriptException excp) {
LOG.error("RangerRequestScriptEvaluator.evaluateScript(): failed to evaluate script", excp);
} catch (Throwable t) {
LOG.error("RangerRequestScriptEvaluator.evaluateScript(): failed to evaluate script", t);
} finally {
Expand All @@ -269,10 +274,8 @@ private Object evaluateScript(ScriptEngine scriptEngine, String script, boolean
private String toJson() {
RangerPerfTracer perf = null;

long requestHash = accessRequest.hashCode();

if (RangerPerfTracer.isPerfTraceEnabled(PERF_POLICY_CONDITION_SCRIPT_TOJSON)) {
perf = RangerPerfTracer.getPerfTracer(PERF_POLICY_CONDITION_SCRIPT_TOJSON, "RangerRequestScriptEvaluator.toJson(requestHash=" + requestHash + ")");
perf = RangerPerfTracer.getPerfTracer(PERF_POLICY_CONDITION_SCRIPT_TOJSON, "RangerRequestScriptEvaluator.toJson(requestHash=" + accessRequest.hashCode() + ")");
}

Map<String, Object> ret = new HashMap<>();
Expand Down Expand Up @@ -1393,5 +1396,4 @@ public Map<String, Map<String, Object>> getAttributes() {
return ret;
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -175,13 +175,13 @@ public class RangerCommonConstants {
" Array.prototype, 'intersects', {\n" +
" value: function (x) {\n" +
" if (x == null) {return false;}\n" +
" var o = Object(this);\n" +
" var len = o.length >>> 0;\n" +
" if (len === 0) { return false; }\n" +
" var result = o.filter(function(n) { return x.indexOf(n) > -1;})\n" +
" return result.length != 0;\n" +
" var o = Object(this);\n" +
" var len = o.length >>> 0;\n" +
" if (len === 0) { return false; }\n" +
" var result = o.filter(function(n) { return x.indexOf(n) > -1;})\n" +
" return result.length != 0;\n" +
" }\n" +
" }\n" +
" )\n" +
" );\n" +
"}; ";
}
Original file line number Diff line number Diff line change
Expand Up @@ -98,14 +98,14 @@ public String resolveExpressions(RangerAccessRequest request) {
String ret = str;

if (hasTokens) {
RangerRequestScriptEvaluator scriptEvaluator = new RangerRequestScriptEvaluator(request);
ScriptEngine scriptEngine = ScriptEngineUtil.createScriptEngine(serviceType);
RangerRequestScriptEvaluator scriptEvaluator = new RangerRequestScriptEvaluator(request, scriptEngine, RangerRequestScriptEvaluator.needsJsonCtxEnabled(str));
StringBuffer sb = new StringBuffer();
Matcher matcher = PATTERN.matcher(str);

while (matcher.find()) {
String expr = matcher.group(REGEX_GROUP_EXPR);
String val = Objects.toString(scriptEvaluator.evaluateScript(scriptEngine, expr));
String val = Objects.toString(scriptEvaluator.evaluateScript(expr));

matcher.appendReplacement(sb, val);
}
Expand Down
Loading

0 comments on commit b50feda

Please sign in to comment.