You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by ma...@apache.org on 2021/09/21 15:13:47 UTC
[ranger] branch ranger-2.2 updated: RANGER-3420: resource matcher
updated to support quoted resource names
This is an automated email from the ASF dual-hosted git repository.
madhan pushed a commit to branch ranger-2.2
in repository https://gitbox.apache.org/repos/asf/ranger.git
The following commit(s) were added to refs/heads/ranger-2.2 by this push:
new 259f508 RANGER-3420: resource matcher updated to support quoted resource names
259f508 is described below
commit 259f50847f0e8720184362ad25604fe9fe301fd6
Author: Madhan Neethiraj <ma...@apache.org>
AuthorDate: Mon Sep 20 01:16:13 2021 -0700
RANGER-3420: resource matcher updated to support quoted resource names
(cherry picked from commit 3af1378c0570bafc3618fc75683ec4ee8f4daadd)
---
.../RangerAbstractResourceMatcher.java | 118 ++-
.../plugin/resourcematcher/ResourceMatcher.java | 11 +
.../TestDefaultPolicyResourceMatcher.java | 7 +
.../test_defaultpolicyresourcematcher_quoted.json | 1035 ++++++++++++++++++++
4 files changed, 1161 insertions(+), 10 deletions(-)
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerAbstractResourceMatcher.java b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerAbstractResourceMatcher.java
index 4754539..7841838 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerAbstractResourceMatcher.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerAbstractResourceMatcher.java
@@ -40,8 +40,10 @@ public abstract class RangerAbstractResourceMatcher implements RangerResourceMat
public final static String WILDCARD_ASTERISK = "*";
- public final static String OPTION_IGNORE_CASE = "ignoreCase";
- public final static String OPTION_WILD_CARD = "wildCard";
+ public final static String OPTION_IGNORE_CASE = "ignoreCase";
+ public final static String OPTION_QUOTED_CASE_SENSITIVE = "quotedCaseSensitive";
+ public final static String OPTION_QUOTE_CHARS = "quoteChars";
+ public final static String OPTION_WILD_CARD = "wildCard";
public final static String OPTION_REPLACE_TOKENS = "replaceTokens";
public final static String OPTION_TOKEN_DELIMITER_START = "tokenDelimiterStart";
public final static String OPTION_TOKEN_DELIMITER_END = "tokenDelimiterEnd";
@@ -52,6 +54,8 @@ public abstract class RangerAbstractResourceMatcher implements RangerResourceMat
protected RangerPolicyResource policyResource;
protected boolean optIgnoreCase;
+ protected boolean optQuotedCaseSensitive;
+ protected String optQuoteChars = "\"";
protected boolean optWildCard;
protected List<String> policyValues;
@@ -83,8 +87,10 @@ public abstract class RangerAbstractResourceMatcher implements RangerResourceMat
Map<String, String> options = resourceDef != null ? resourceDef.getMatcherOptions() : null;
- optIgnoreCase = getOptionIgnoreCase(options);
- optWildCard = getOptionWildCard(options);
+ optIgnoreCase = getOptionIgnoreCase(options);
+ optQuotedCaseSensitive = getOptionQuotedCaseSensitive(options);
+ optQuoteChars = getOptionQuoteChars(options);
+ optWildCard = getOptionWildCard(options);
policyValues = new ArrayList<>();
policyIsExcludes = policyResource != null && policyResource.getIsExcludes();
@@ -143,6 +149,14 @@ public abstract class RangerAbstractResourceMatcher implements RangerResourceMat
return ServiceDefUtil.getBooleanOption(options, OPTION_IGNORE_CASE, true);
}
+ public static boolean getOptionQuotedCaseSensitive(Map<String, String> options) {
+ return ServiceDefUtil.getBooleanOption(options, OPTION_QUOTED_CASE_SENSITIVE, false);
+ }
+
+ public static String getOptionQuoteChars(Map<String, String> options) {
+ return ServiceDefUtil.getOption(options, OPTION_QUOTE_CHARS, "\"");
+ }
+
public static boolean getOptionWildCard(Map<String, String> options) {
return ServiceDefUtil.getBooleanOption(options, OPTION_WILD_CARD, true);
}
@@ -208,7 +222,7 @@ public abstract class RangerAbstractResourceMatcher implements RangerResourceMat
if(isMatchAny) {
ret = StringUtils.isEmpty(resource) || StringUtils.containsOnly(resource, WILDCARD_ASTERISK);
} else {
- ret = optIgnoreCase ? StringUtils.equalsIgnoreCase(resource, policyValue) : StringUtils.equals(resource, policyValue);
+ ret = optIgnoreCase && !(optQuotedCaseSensitive && ResourceMatcher.startsWithAnyChar(resource, optQuoteChars)) ? StringUtils.equalsIgnoreCase(resource, policyValue) : StringUtils.equals(resource, policyValue);
}
if(policyIsExcludes) {
@@ -246,6 +260,8 @@ public abstract class RangerAbstractResourceMatcher implements RangerResourceMat
}
sb.append("} ");
sb.append("optIgnoreCase={").append(optIgnoreCase).append("} ");
+ sb.append("optQuotedCaseSensitive={").append(optQuotedCaseSensitive).append("} ");
+ sb.append("optQuoteChars={").append(optQuoteChars).append("} ");
sb.append("optWildCard={").append(optWildCard).append("} ");
sb.append("policyValues={");
@@ -346,17 +362,17 @@ public abstract class RangerAbstractResourceMatcher implements RangerResourceMat
}
if (needWildcardMatch) { // test?, test*a*, test*a*b, *test*a
- ret = optIgnoreCase ? new CaseInsensitiveWildcardMatcher(policyValue) : new CaseSensitiveWildcardMatcher(policyValue);
+ ret = optIgnoreCase ? (optQuotedCaseSensitive ? new QuotedCaseSensitiveWildcardMatcher(policyValue, optQuoteChars) : new CaseInsensitiveWildcardMatcher(policyValue)) : new CaseSensitiveWildcardMatcher(policyValue);
} else if (wildcardStartIdx == -1) { // test, testa, testab
- ret = optIgnoreCase ? new CaseInsensitiveStringMatcher(policyValue) : new CaseSensitiveStringMatcher(policyValue);
+ ret = optIgnoreCase ? (optQuotedCaseSensitive ? new QuotedCaseSensitiveStringMatcher(policyValue, optQuoteChars) : new CaseInsensitiveStringMatcher(policyValue)) : new CaseSensitiveStringMatcher(policyValue);
} else if (wildcardStartIdx == 0) { // *test, **test, *testa, *testab
String matchStr = policyValue.substring(wildcardEndIdx + 1);
- ret = optIgnoreCase ? new CaseInsensitiveEndsWithMatcher(matchStr) : new CaseSensitiveEndsWithMatcher(matchStr);
+ ret = optIgnoreCase ? (optQuotedCaseSensitive ? new QuotedCaseSensitiveEndsWithMatcher(matchStr, optQuoteChars) : new CaseInsensitiveEndsWithMatcher(matchStr)) : new CaseSensitiveEndsWithMatcher(matchStr);
} else if (wildcardEndIdx != (len - 1)) { // test*a, test*ab
- ret = optIgnoreCase ? new CaseInsensitiveWildcardMatcher(policyValue) : new CaseSensitiveWildcardMatcher(policyValue);
+ ret = optIgnoreCase ? (optQuotedCaseSensitive ? new QuotedCaseSensitiveWildcardMatcher(policyValue, optQuoteChars) : new CaseInsensitiveWildcardMatcher(policyValue)) : new CaseSensitiveWildcardMatcher(policyValue);
} else { // test*, test**, testa*, testab*
String matchStr = policyValue.substring(0, wildcardStartIdx);
- ret = optIgnoreCase ? new CaseInsensitiveStartsWithMatcher(matchStr) : new CaseSensitiveStartsWithMatcher(matchStr);
+ ret = optIgnoreCase ? (optQuotedCaseSensitive ? new QuotedCaseSensitiveStartsWithMatcher(matchStr, optQuoteChars) : new CaseInsensitiveStartsWithMatcher(matchStr)) : new CaseSensitiveStartsWithMatcher(matchStr);
}
if(optReplaceTokens) {
@@ -389,6 +405,27 @@ final class CaseInsensitiveStringMatcher extends ResourceMatcher {
int getPriority() {return 2 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0); }
}
+final class QuotedCaseSensitiveStringMatcher extends ResourceMatcher {
+ private final String quoteChars;
+
+ QuotedCaseSensitiveStringMatcher(String value, String quoteChars) {
+ super(value);
+
+ this.quoteChars = quoteChars;
+ }
+
+ @Override
+ boolean isMatch(String resourceValue, Map<String, Object> evalContext) {
+ if (startsWithAnyChar(resourceValue, quoteChars)) {
+ return StringUtils.equals(resourceValue, getExpandedValue(evalContext));
+ } else {
+ return StringUtils.equalsIgnoreCase(resourceValue, getExpandedValue(evalContext));
+ }
+ }
+
+ int getPriority() {return 2 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0); }
+}
+
final class CaseSensitiveStartsWithMatcher extends ResourceMatcher {
CaseSensitiveStartsWithMatcher(String value) {
super(value);
@@ -411,6 +448,27 @@ final class CaseInsensitiveStartsWithMatcher extends ResourceMatcher {
int getPriority() { return 4 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0); }
}
+final class QuotedCaseSensitiveStartsWithMatcher extends ResourceMatcher {
+ private final String quoteChars;
+
+ QuotedCaseSensitiveStartsWithMatcher(String value, String quoteChars) {
+ super(value);
+
+ this.quoteChars = quoteChars;
+ }
+
+ @Override
+ boolean isMatch(String resourceValue, Map<String, Object> evalContext) {
+ if (startsWithAnyChar(resourceValue, quoteChars)) {
+ return StringUtils.startsWith(resourceValue, getExpandedValue(evalContext));
+ } else {
+ return StringUtils.startsWithIgnoreCase(resourceValue, getExpandedValue(evalContext));
+ }
+ }
+
+ int getPriority() { return 4 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0); }
+}
+
final class CaseSensitiveEndsWithMatcher extends ResourceMatcher {
CaseSensitiveEndsWithMatcher(String value) {
super(value);
@@ -435,6 +493,27 @@ final class CaseInsensitiveEndsWithMatcher extends ResourceMatcher {
int getPriority() { return 4 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0); }
}
+final class QuotedCaseSensitiveEndsWithMatcher extends ResourceMatcher {
+ private final String quoteChars;
+
+ QuotedCaseSensitiveEndsWithMatcher(String value, String quoteChars) {
+ super(value);
+
+ this.quoteChars = quoteChars;
+ }
+
+ @Override
+ boolean isMatch(String resourceValue, Map<String, Object> evalContext) {
+ if (startsWithAnyChar(resourceValue, quoteChars)) {
+ return StringUtils.endsWith(resourceValue, getExpandedValue(evalContext));
+ } else {
+ return StringUtils.endsWithIgnoreCase(resourceValue, getExpandedValue(evalContext));
+ }
+ }
+
+ int getPriority() { return 4 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0); }
+}
+
final class CaseSensitiveWildcardMatcher extends ResourceMatcher {
CaseSensitiveWildcardMatcher(String value) {
super(value);
@@ -460,6 +539,25 @@ final class CaseInsensitiveWildcardMatcher extends ResourceMatcher {
int getPriority() {return 6 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0); }
}
+final class QuotedCaseSensitiveWildcardMatcher extends ResourceMatcher {
+ private final String quoteChars;
+
+ QuotedCaseSensitiveWildcardMatcher(String value, String quoteChars) {
+ super(value);
+
+ this.quoteChars = quoteChars;
+ }
+
+ @Override
+ boolean isMatch(String resourceValue, Map<String, Object> evalContext) {
+ IOCase caseSensitivity = startsWithAnyChar(resourceValue, quoteChars) ? IOCase.SENSITIVE : IOCase.INSENSITIVE;
+
+ return FilenameUtils.wildcardMatch(resourceValue, getExpandedValue(evalContext), caseSensitivity);
+ }
+
+ int getPriority() {return 6 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0); }
+}
+
final class ResourceMatcherWrapper {
private final boolean needsDynamicEval;
private final List<ResourceMatcher> resourceMatchers;
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/ResourceMatcher.java b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/ResourceMatcher.java
index 35856a9..6d8e293 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/ResourceMatcher.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/ResourceMatcher.java
@@ -19,6 +19,7 @@
package org.apache.ranger.plugin.resourcematcher;
+import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ranger.plugin.util.StringTokenReplacer;
@@ -92,6 +93,16 @@ abstract class ResourceMatcher {
return ret;
}
+ public static boolean startsWithAnyChar(String value, String startChars) {
+ boolean ret = false;
+
+ if (value != null && value.length() > 0 && startChars != null) {
+ ret = StringUtils.contains(startChars, value.charAt(0));
+ }
+
+ return ret;
+ }
+
public static class PriorityComparator implements Comparator<ResourceMatcher>, Serializable {
@Override
public int compare(ResourceMatcher me, ResourceMatcher other) {
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/resourcematcher/TestDefaultPolicyResourceMatcher.java b/agents-common/src/test/java/org/apache/ranger/plugin/resourcematcher/TestDefaultPolicyResourceMatcher.java
index 8ea7105..2b432a1 100644
--- a/agents-common/src/test/java/org/apache/ranger/plugin/resourcematcher/TestDefaultPolicyResourceMatcher.java
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/resourcematcher/TestDefaultPolicyResourceMatcher.java
@@ -97,6 +97,13 @@ public class TestDefaultPolicyResourceMatcher {
}
@Test
+ public void testDefaultPolicyResourceMatcherQuoted() throws Exception {
+ String[] tests = {"/resourcematcher/test_defaultpolicyresourcematcher_quoted.json"};
+
+ runTestsFromResourceFiles(tests, null);
+ }
+
+ @Test
public void testDefaultPolicyResourceMatcher_ResourceSpecific() throws Exception {
String[] tests = { "/resourcematcher/test_defaultpolicyresourcematcher.json" };
diff --git a/agents-common/src/test/resources/resourcematcher/test_defaultpolicyresourcematcher_quoted.json b/agents-common/src/test/resources/resourcematcher/test_defaultpolicyresourcematcher_quoted.json
new file mode 100644
index 0000000..cebfb72
--- /dev/null
+++ b/agents-common/src/test/resources/resourcematcher/test_defaultpolicyresourcematcher_quoted.json
@@ -0,0 +1,1035 @@
+{
+ "serviceDef": {
+ "name": "quoted",
+ "id": 3,
+ "resources": [
+ {
+ "name": "database",
+ "level": 1,
+ "mandatory": true,
+ "lookupSupported": true,
+ "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher",
+ "matcherOptions": {
+ "wildCard": true,
+ "ignoreCase": true,
+ "quotedCaseSensitive": true,
+ "quoteChars": "\""
+ },
+ "label": "Quoted Database",
+ "description": "Quoted Database",
+ "isExcludes": true
+ },
+ {
+ "name": "table",
+ "level": 2,
+ "parent": "database",
+ "mandatory": true,
+ "lookupSupported": true,
+ "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher",
+ "matcherOptions": {
+ "wildCard": true,
+ "ignoreCase": true,
+ "quotedCaseSensitive": true,
+ "quoteChars": "\""
+ },
+ "label": "Quoted Table",
+ "description": "Quoted Table",
+ "isExcludes": true
+ },
+ {
+ "name": "column",
+ "level": 3,
+ "parent": "table",
+ "mandatory": true,
+ "lookupSupported": true,
+ "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher",
+ "matcherOptions": {
+ "wildCard": true,
+ "ignoreCase": true,
+ "quotedCaseSensitive": true,
+ "quoteChars": "\""
+ },
+ "label": "Quoted Column",
+ "description": "Quoted Column",
+ "isExcludes": true
+ }
+ ],
+ "accessTypes": [
+ {
+ "name": "select",
+ "label": "Select"
+ },
+ {
+ "name": "update",
+ "label": "Update"
+ },
+ {
+ "name": "create",
+ "label": "Create"
+ },
+ {
+ "name": "drop",
+ "label": "Drop"
+ },
+ {
+ "name": "alter",
+ "label": "Alter"
+ },
+ {
+ "name": "index",
+ "label": "Index"
+ },
+ {
+ "name": "lock",
+ "label": "Lock"
+ },
+ {
+ "name": "all",
+ "label": "All"
+ }
+ ]
+ },
+ "testCases": [
+ {
+ "name": "Quoted values in policy: database=\"Test*:table=\"teSt*:column=*",
+ "policyResources": {
+ "database": {"values": [ "\"Test*"] },
+ "table": {"values": ["\"teSt*"]},
+ "column": {"values": ["*"]}
+ },
+ "tests": [
+ {
+ "name": "MATCH for exact '\"TestDB.\"teStTbl.ssn'",
+ "type": "exactMatch",
+ "resource": {
+ "elements": {"database": "\"TestDB", "table":"\"teStTbl", "column":"ssn"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for exact '\"TestDB.\"teStTbl.\"ssn'",
+ "type": "exactMatch",
+ "resource": {
+ "elements": {"database": "\"TestDB", "table":"\"teStTbl", "column":"\"ssn"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "No MATCH for unquoted 'TestDB.\"teStTbl.ssn'",
+ "type": "exactMatch",
+ "resource": {
+ "elements": {"database": "TestDB", "table":"\"teStTbl", "column":"SSN"}
+ },
+ "evalContext": {},
+ "result": false
+ }
+ ,
+ {
+ "name": "No MATCH for unquoted 'TestDB.teStTbl.ssn'",
+ "type": "exactMatch",
+ "resource": {
+ "elements": {"database": "\"TestDB", "table":"teStTbl", "column":"ssn"}
+ },
+ "evalContext": {},
+ "result": false
+ }
+ ,
+ {
+ "name": "MATCH for parent with wildcards '\"TestDB.\"teStTbl'",
+ "type": "selfAndAllDescendants",
+ "resource": {
+ "elements": {"database": "\"TestDB","table": "\"teStTbl"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for parent with wildcards '\"TestDB'",
+ "type": "selfAndAllDescendants",
+ "resource": {
+ "elements": {"database": "\"TestDB"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ]
+ },
+ {
+ "name": "Quoted values in resource: database=Test*:table=teSt*:column=*",
+ "policyResources": {
+ "database": {"values": [ "Test*"] },
+ "table": {"values": ["teSt*"]},
+ "column": {"values": ["*"]}
+ },
+ "tests": [
+ {
+ "name": "No MATCH for quoted '\"TestDB.\"teStTbl.ssn'",
+ "type": "exactMatch",
+ "resource": {
+ "elements": {"database": "\"TestDB", "table":"\"teStTbl", "column":"ssn"}
+ },
+ "evalContext": {},
+ "result": false
+ }
+ ,
+ {
+ "name": "No MATCH for exact '\"TestDB.\"teStTbl.\"ssn'",
+ "type": "exactMatch",
+ "resource": {
+ "elements": {"database": "\"TestDB", "table":"\"teStTbl", "column":"\"ssn"}
+ },
+ "evalContext": {},
+ "result": false
+ }
+ ,
+ {
+ "name": "MATCH for unquoted 'testdb.testtbl.ssn'",
+ "type": "exactMatch",
+ "resource": {
+ "elements": {"database": "testdb", "table":"testtbl", "column":"SSN"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for unquoted 'TestDB.teStTbl.ssn'",
+ "type": "exactMatch",
+ "resource": {
+ "elements": {"database": "TestDB", "table":"teStTbl", "column":"ssn"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for parent with wildcards 'TestDB.teStTbl'",
+ "type": "selfAndAllDescendants",
+ "resource": {
+ "elements": {"database": "TestDB","table": "teStTbl"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for parent with wildcards 'TestDB'",
+ "type": "selfAndAllDescendants",
+ "resource": {
+ "elements": {"database": "TestDB"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ]
+ },
+ {
+ "name": "database=*, isExclude=true:table=*, isExcludes=true",
+ "policyResources": {
+ "database": {"values": ["*"], "isExcludes": true},
+ "table": {"values": ["*"], "isExcludes": true}
+ },
+ "tests": [
+ {
+ "name": "NO MATCH for invalid resource level",
+ "type": "anyMatch",
+ "resource" : {
+ "elements" : { "database":"finance", "invalid-resource-name":"any"}
+ },
+ "evalContext": {},
+ "result" : false
+ }
+ ,
+ {
+ "name": "No MATCH for parent 'finance.tax.ssn'",
+ "type": "anyMatch",
+ "resource": {
+ "elements": {"database": "finance", "table":"tax", "column":"ssn"}
+ },
+ "evalContext": {},
+ "result": false
+ }
+ ,
+ {
+ "name": "No MATCH for exact 'finance:tax'",
+ "type": "anyMatch",
+ "resource": {
+ "elements": {"database": "finance","table": "tax"}
+ },
+ "evalContext": {},
+ "result": false
+ }
+ ,
+ {
+ "name": "No MATCH for parent with wildcards 'finance'",
+ "type": "anyMatch",
+ "resource": {
+ "elements": {"database": "finance"}
+ },
+ "evalContext": {},
+ "result": false
+ }
+ ,
+ {
+ "name": "No MATCH for any ''",
+ "type": "anyMatch",
+ "resource": {
+ "elements": {}
+ },
+ "evalContext": {},
+ "result": false
+ }
+ ]
+ },
+ {
+ "name": "database=*:table=tax, isExcludes=true",
+ "policyResources": {
+ "database": {"values": ["*"]},
+ "table": {"values": ["tax"], "isExcludes": true}
+ },
+ "tests": [
+ {
+ "name": "NO MATCH for invalid resource level",
+ "type": "anyMatch",
+ "resource" : {
+ "elements" : { "database":"finance", "invalid-resource-name":"any"}
+ },
+ "evalContext": {},
+ "result" : false
+ }
+ ,
+ {
+ "name": "No MATCH for parent 'finance.tax.ssn'",
+ "type": "anyMatch",
+ "resource": {
+ "elements": {"database": "finance", "table":"tax", "column":"ssn"}
+ },
+ "evalContext": {},
+ "result": false
+ }
+ ,
+ {
+ "name": "No MATCH for exact 'finance:tax'",
+ "type": "anyMatch",
+ "resource": {
+ "elements": {"database": "finance","table": "tax"}
+ },
+ "evalContext": {},
+ "result": false
+ }
+ ,
+ {
+ "name": "MATCH for parent with wildcards 'finance'",
+ "type": "selfAndAllDescendants",
+ "resource": {
+ "elements": {"database": "finance"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for child ''",
+ "type": "descendantMatch",
+ "resource": {
+ "elements": {}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ]
+ },
+ {
+ "name": "database=*:table=*",
+ "policyResources": {
+ "database": {"values": ["*"]},
+ "table": {"values": ["*"]}
+ },
+ "tests": [
+ {
+ "name": "NO MATCH for invalid resource level",
+ "type": "anyMatch",
+ "resource" : {
+ "elements" : { "database":"finance", "invalid-resource-name":"any"}
+ },
+ "evalContext": {},
+ "result" : false
+ }
+ ,
+ {
+ "name": "MATCH for parent 'finance.tax.ssn'",
+ "type": "ancestorMatch",
+ "resource": {
+ "elements": {"database": "finance", "table":"tax", "column":"ssn"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for exact 'finance:tax'",
+ "type": "exactMatch",
+ "resource": {
+ "elements": {"database": "finance","table": "tax"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for parent with wildcards 'finance'",
+ "type": "selfAndAllDescendants",
+ "resource": {
+ "elements": {"database": "finance"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for parent with wildcards ''",
+ "type": "selfAndAllDescendants",
+ "resource": {
+ "elements": {}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ]
+ },
+ {
+ "name": "database=finance:table=tax",
+ "policyResources": {
+ "database": {"values": ["finance"]},
+ "table": {"values": ["tax"]}
+ },
+ "tests": [
+ {
+ "name": "MATCH for parent 'finance.tax.ssn'",
+ "type": "ancestorMatch",
+ "resource": {
+ "elements": {"database": "finance", "table":"tax", "column":"ssn"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for exact 'finance:tax'",
+ "type": "exactMatch",
+ "resource": {
+ "elements": {"database": "finance","table": "tax"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for child 'finance'",
+ "type": "descendantMatch",
+ "resource": {
+ "elements": {"database": "finance"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for child ''",
+ "type": "descendantMatch",
+ "resource": {
+ "elements": {}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ]
+ },
+ {
+ "name": "database=*:table=tax",
+ "policyResources": {
+ "database": {"values": ["*"]},
+ "table": {"values": ["tax"]}
+ },
+ "tests": [
+ {
+ "name": "MATCH for parent 'finance.tax.ssn'",
+ "type": "ancestorMatch",
+ "resource": {
+ "elements": {"database": "finance", "table":"tax", "column":"ssn"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for exact 'finance:tax'",
+ "type": "exactMatch",
+ "resource": {
+ "elements": {"database": "finance","table": "tax"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for child 'finance'",
+ "type": "descendantMatch",
+ "resource": {
+ "elements": {"database": "finance"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for child ''",
+ "type": "descendantMatch",
+ "resource": {
+ "elements": {}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ]
+ },
+ {
+ "name": "database=finance:table=*",
+ "policyResources": {
+ "database": {"values": ["finance"]},
+ "table": {"values": ["*"]}
+ },
+ "tests": [
+ {
+ "name": "MATCH for parent 'finance.tax.ssn'",
+ "type": "ancestorMatch",
+ "resource": {
+ "elements": {"database": "finance", "table":"tax", "column":"ssn"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for exact 'finance:tax'",
+ "type": "exactMatch",
+ "resource": {
+ "elements": {"database": "finance","table": "tax"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for parent with wildcards 'finance'",
+ "type": "selfAndAllDescendants",
+ "resource": {
+ "elements": {"database": "finance"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for child ''",
+ "type": "descendantMatch",
+ "resource": {
+ "elements": {}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ]
+ },
+ {
+ "name": "database=finance",
+ "policyResources": {
+ "database": {"values": ["finance"]}
+ },
+ "tests": [
+ {
+ "name": "MATCH for parent 'finance.tax.ssn'",
+ "type": "ancestorMatch",
+ "resource": {
+ "elements": {"database": "finance", "table":"tax", "column":"ssn"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for parent 'finance:tax'",
+ "type": "ancestorMatch",
+ "resource": {
+ "elements": {"database": "finance","table": "tax"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for exact 'finance'",
+ "type": "exactMatch",
+ "resource": {
+ "elements": {"database": "finance"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for child ''",
+ "type": "descendantMatch",
+ "resource": {
+ "elements": {}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ]
+ },
+ {
+ "name": "database=*",
+ "policyResources": {
+ "database": {"values": ["*"]}
+ },
+ "tests": [
+ {
+ "name": "NO MATCH for invalid resource level",
+ "type": "anyMatch",
+ "resource" : {
+ "elements" : { "database":"finance", "invalid-resource-name":"any"}
+ },
+ "evalContext": {},
+ "result" : false
+ }
+ ,
+ {
+ "name": "MATCH for parent 'finance.tax.ssn'",
+ "type": "ancestorMatch",
+ "resource": {
+ "elements": {"database": "finance", "table":"tax", "column":"ssn"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for parent 'finance:tax'",
+ "type": "ancestorMatch",
+ "resource": {
+ "elements": {"database": "finance","table": "tax"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for exact 'finance'",
+ "type": "exactMatch",
+ "resource": {
+ "elements": {"database": "finance"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for parent with wildcards ''",
+ "type": "selfAndAllDescendants",
+ "resource": {
+ "elements": {}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ]
+ },
+ {
+ "name": "database=*:table=*:column=*",
+ "policyResources": {
+ "database": {"values": [ "*"] },
+ "table": {"values": ["*"]},
+ "column": {"values": ["*"]}
+ },
+ "tests": [
+ {
+ "name": "MATCH for exact 'finance.tax.ssn'",
+ "type": "exactMatch",
+ "resource": {
+ "elements": {"database": "finance", "table":"tax", "column":"ssn"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for parent with wildcards 'finance:tax'",
+ "type": "selfAndAllDescendants",
+ "resource": {
+ "elements": {"database": "finance","table": "tax"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for parent with wildcards 'finance'",
+ "type": "selfAndAllDescendants",
+ "resource": {
+ "elements": {"database": "finance"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for parent with wildcards ''",
+ "type": "selfAndAllDescendants",
+ "resource": {
+ "elements": {}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "NO MATCH for any 'finance::ssn'",
+ "type": "anyMatch",
+ "resource": {
+ "elements": {
+ "database": "finance","column":"ssn"
+ }
+ },
+ "evalContext": {},
+ "result": false
+ }
+ ]
+ }
+ ,
+ {
+ "name": "database=finance:table=tax:column=ssn",
+ "policyResources": {
+ "database": {"values": [ "finance"] },
+ "table": {"values": ["tax"]},
+ "column": {"values": ["ssn"]}
+ },
+ "tests": [
+ {
+ "name": "MATCH for exact 'finance.tax.ssn'",
+ "type": "exactMatch",
+ "resource": {
+ "elements": {"database": "finance", "table":"tax", "column":"ssn"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for child 'finance:tax'",
+ "type": "descendantMatch",
+ "resource": {
+ "elements": {"database": "finance","table": "tax"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for child 'finance'",
+ "type": "descendantMatch",
+ "resource": {
+ "elements": {"database": "finance"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for child ''",
+ "type": "descendantMatch",
+ "resource": {
+ "elements": {}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ]
+ }
+ ,
+
+ {
+ "name": "database=*:table=*:column=ssn",
+ "policyResources": {
+ "database": {"values": [ "*"] },
+ "table": {"values": ["*"]},
+ "column": {"values": ["ssn"]}
+ },
+ "tests": [
+ {
+ "name": "MATCH for exact 'finance.tax.ssn'",
+ "type": "exactMatch",
+ "resource": {
+ "elements": {"database": "finance", "table":"tax", "column":"ssn"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for child 'finance:tax'",
+ "type": "descendantMatch",
+ "resource": {
+ "elements": {"database": "finance","table": "tax"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for child 'finance'",
+ "type": "descendantMatch",
+ "resource": {
+ "elements": {"database": "finance"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ]
+ }
+ ,
+
+ {
+ "name": "database=finance:table=*:column=*",
+ "policyResources": {
+ "database": {"values": [ "finance"] },
+ "table": {"values": ["*"]},
+ "column": {"values": ["*"]}
+ },
+ "tests": [
+ {
+ "name": "MATCH for exact 'finance.tax.ssn'",
+ "type": "exactMatch",
+ "resource": {
+ "elements": {"database": "finance", "table":"tax", "column":"ssn"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for parent with wildcards 'finance:tax'",
+ "type": "selfAndAllDescendants",
+ "resource": {
+ "elements": {"database": "finance","table": "tax"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for parent with wildcards 'finance'",
+ "type": "selfAndAllDescendants",
+ "resource": {
+ "elements": {"database": "finance"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ]
+ }
+ ,
+
+ {
+ "name": "database=*:table=tax:column=*",
+ "policyResources": {
+ "database": {"values": [ "*"] },
+ "table": {"values": ["tax"]},
+ "column": {"values": ["*"]}
+ },
+ "tests": [
+ {
+ "name": "MATCH for exact 'finance.tax.ssn'",
+ "type": "exactMatch",
+ "resource": {
+ "elements": {"database": "finance", "table":"tax", "column":"ssn"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for parent with wildcards 'finance:tax'",
+ "type": "selfAndAllDescendants",
+ "resource": {
+ "elements": {"database": "finance","table": "tax"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for parent with wildcards 'finance'",
+ "type": "selfAndAllDescendants",
+ "resource": {
+ "elements": {"database": "finance"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ]
+ }
+ ,
+ {
+ "name": "database=*:table=tax:column=ssn",
+ "policyResources": {
+ "database": {"values": [ "*"] },
+ "table": {"values": ["tax"]},
+ "column": {"values": ["ssn"]}
+ },
+ "tests": [
+ {
+ "name": "MATCH for exact 'finance.tax.ssn'",
+ "type": "exactMatch",
+ "resource": {
+ "elements": {"database": "finance", "table":"tax", "column":"ssn"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for child 'finance:tax'",
+ "type": "descendantMatch",
+ "resource": {
+ "elements": {"database": "finance","table": "tax"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for child 'finance'",
+ "type": "descendantMatch",
+ "resource": {
+ "elements": {"database": "finance"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ]
+ }
+ ,
+ {
+ "name": "database=finance:table=*:column=ssn",
+ "policyResources": {
+ "database": {"values": [ "finance"] },
+ "table": {"values": ["*"]},
+ "column": {"values": ["ssn"]}
+ },
+ "tests": [
+ {
+ "name": "MATCH for exact 'finance.tax.ssn'",
+ "type": "exactMatch",
+ "resource": {
+ "elements": {"database": "finance", "table":"tax", "column":"ssn"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for child 'finance:tax'",
+ "type": "descendantMatch",
+ "resource": {
+ "elements": {"database": "finance","table": "tax"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for child 'finance'",
+ "type": "descendantMatch",
+ "resource": {
+ "elements": {"database": "finance"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ]
+ }
+ ,
+ {
+ "name": "database=finance:table=tax:column=*",
+ "policyResources": {
+ "database": {"values": [ "finance"] },
+ "table": {"values": ["tax"]},
+ "column": {"values": ["*"]}
+ },
+ "tests": [
+ {
+ "name": "MATCH for exact 'finance.tax.ssn'",
+ "type": "exactMatch",
+ "resource": {
+ "elements": {"database": "finance", "table":"tax", "column":"ssn"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for parent with wildcards 'finance:tax'",
+ "type": "selfAndAllDescendants",
+ "resource": {
+ "elements": {"database": "finance","table": "tax"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for child 'finance'",
+ "type": "descendantMatch",
+ "resource": {
+ "elements": {"database": "finance"}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ]
+ }
+ ,
+ {
+ "name": "empty policyresources",
+ "policyResources": {
+ },
+ "tests": [
+ {
+ "name": "MATCH for exact ''",
+ "type": "exactMatch",
+ "resource": {
+ "elements": {}
+ },
+ "evalContext": {},
+ "result": true
+ }
+ ,
+ {
+ "name": "MATCH for parent 'default'",
+ "type": "anyMatch",
+ "resource": {
+ "elements": {"database": "default"}
+ },
+ "evalContext": {},
+ "result": false
+ }
+ ]
+ }
+ ]
+}