This is an automated email from the ASF dual-hosted git repository.
madhan pushed a commit to branch ranger-2.8
in repository https://gitbox.apache.org/repos/asf/ranger.git
The following commit(s) were added to refs/heads/ranger-2.8 by this push:
new ed998c827 RANGER-5367: simplify resource-name parsing (#699)
ed998c827 is described below
commit ed998c827db2feed98462c529f127b822daad59f
Author: Madhan Neethiraj <[email protected]>
AuthorDate: Mon Oct 13 15:09:55 2025 -0700
RANGER-5367: simplify resource-name parsing (#699)
(cherry picked from commit 073bd9fb43f8a3f3f55353cf90c5ad691db24651)
---
.../ranger/plugin/model/RangerServiceDef.java | 24 +-
.../model/validation/RangerServiceDefHelper.java | 27 +-
.../validation/TestRangerServiceDefHelper.java | 26 +-
.../ranger/authz/api/RangerAuthzApiErrorCode.java | 6 +-
.../authz/util/RangerResourceNameParser.java | 216 +++++++++++
.../ranger/authz/util/RangerResourceTemplate.java | 192 ----------
.../ranger/authz/api/TestAuthzApiErrorCode.java | 8 +-
.../ranger/authz/api/TestAuthzException.java | 10 +-
.../authz/util/TestRangerResourceNameParser.java | 406 +++++++++++++++++++++
.../ranger/authz/util/TestResourceTemplate.java | 250 -------------
10 files changed, 649 insertions(+), 516 deletions(-)
diff --git
a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerServiceDef.java
b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerServiceDef.java
index d5955bd20..eeabde089 100644
---
a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerServiceDef.java
+++
b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerServiceDef.java
@@ -1380,7 +1380,6 @@ public static class RangerResourceDef implements
java.io.Serializable {
private String rbKeyValidationMessage = null;
private Set<String> accessTypeRestrictions = null;
private Boolean isValidLeaf = null;
- private String rrnTemplate; // resource-name
template. Examples: {database}.{table}.{column},
{container}@{storageaccount}/{relativepath}
public RangerResourceDef() {
this(null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null);
@@ -1408,7 +1407,6 @@ public RangerResourceDef(RangerResourceDef other) {
setRbKeyValidationMessage(other.getRbKeyValidationMessage());
setAccessTypeRestrictions(other.getAccessTypeRestrictions());
setIsValidLeaf(other.getIsValidLeaf());
- setRrnTemplate(other.getRrnTemplate());
}
public RangerResourceDef(Long itemId, String name, String type,
Integer level, String parent, Boolean mandatory, Boolean lookupSupported,
Boolean recursiveSupported, Boolean excludesSupported, String matcher,
Map<String, String> matcherOptions, String validationRegEx, String
validationMessage, String uiHint, String label, String description, String
rbKeyLabel, String rbKeyDescription, String rbKeyValidationMessage, Set<String>
accessTypeRestrictions, Boolean isValidLeaf) {
@@ -1712,15 +1710,7 @@ public void setAccessTypeRestrictions(Set<String>
accessTypeRestrictions) {
public Boolean getIsValidLeaf() { return isValidLeaf; }
public void setIsValidLeaf(Boolean isValidLeaf) {
- this.isValidLeaf = isValidLeaf;
- }
-
- public String getRrnTemplate() {
- return rrnTemplate;
- }
-
- public void setRrnTemplate(String rrnTemplate) {
- this.rrnTemplate = rrnTemplate;
+ this.isValidLeaf = isValidLeaf;
}
public void dedupStrings(Map<String, String> strTbl) {
@@ -1738,7 +1728,6 @@ public void dedupStrings(Map<String, String> strTbl) {
rbKeyDescription =
StringUtil.dedupString(rbKeyDescription, strTbl);
rbKeyValidationMessage =
StringUtil.dedupString(rbKeyValidationMessage, strTbl);
accessTypeRestrictions =
StringUtil.dedupStringsSet(accessTypeRestrictions, strTbl);
- rrnTemplate =
StringUtil.dedupString(rrnTemplate, strTbl);
}
@Override
@@ -1773,7 +1762,6 @@ public StringBuilder toString(StringBuilder sb) {
sb.append("rbKeyValidationMessage={").append(rbKeyValidationMessage).append("}
");
sb.append("accessTypeRestrictions={").append(accessTypeRestrictions == null ?
"null" : accessTypeRestrictions.toString()).append("} ");
sb.append("isValidLeaf={").append(isValidLeaf == null ?
"null" : isValidLeaf.toString()).append("} ");
- sb.append("rrnTemplate={").append(rrnTemplate == null ?
"null" : rrnTemplate).append("} ");
sb.append("}");
return sb;
@@ -1836,9 +1824,6 @@ public int hashCode() {
result = prime
* result
+ ((isValidLeaf == null) ? 0 :
isValidLeaf.hashCode());
- result = prime
- * result
- + ((rrnTemplate == null) ? 0 :
rrnTemplate.hashCode());
return result;
}
@@ -1952,12 +1937,7 @@ public boolean equals(Object obj) {
return false;
} else if (!isValidLeaf.equals(other.isValidLeaf))
return false;
- if (rrnTemplate == null) {
- if (other.rrnTemplate != null)
- return false;
- } else if (!rrnTemplate.equals(other.rrnTemplate))
- return false;
- return true;
+ return true;
}
}
diff --git
a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceDefHelper.java
b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceDefHelper.java
index 0e74d26eb..868f6d7b9 100644
---
a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceDefHelper.java
+++
b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceDefHelper.java
@@ -49,10 +49,7 @@
public class RangerServiceDefHelper {
private static final Logger LOG =
LoggerFactory.getLogger(RangerServiceDefHelper.class);
- public static final String RRN_RESOURCE_PREFIX = "{";
- public static final String RRN_RESOURCE_SUFFIX = "}";
- public static final String RRN_RESOURCE_SEP = ".";
- public static final String RRN_PATH_RESOURCE_SEP = "/";
+ public static final String RRN_RESOURCE_SEP = "/";
static final Map<String, Delegate> _Cache = new ConcurrentHashMap<>();
final Delegate _delegate;
@@ -454,13 +451,7 @@ public Delegate(RangerServiceDef serviceDef, boolean
checkForCycles) {
_orderedResourceNames =
buildSortedResourceNames();
for (RangerResourceDef resourceDef :
serviceDef.getResources()) {
- if
(StringUtils.isBlank(resourceDef.getRrnTemplate())) {
-
resourceDef.setRrnTemplate(getDefaultRrnTemplate(resourceDef));
-
- LOG.debug("No rrnTemplate was
defined for resource {}.{}. It is now set to default: {}", _serviceName,
resourceDef.getName(), resourceDef.getRrnTemplate());
- }
-
-
this.rrnTemplates.put(resourceDef.getName(), resourceDef.getRrnTemplate());
+
this.rrnTemplates.put(resourceDef.getName(),
getDefaultRrnTemplate(resourceDef));
}
} else {
_orderedResourceNames = new ArrayList<>();
@@ -860,11 +851,11 @@ private List<String> buildSortedResourceNames() {
}
// create default resource-name template for the resource-def,
like:
- // database:{database}
- // table:{database}.{table}
- // column:{database}.{table}.{column}
- // path:{bucket}/{path}
- // key:{volume}.{bucket}/{key}
+ // database:database
+ // table:database/table
+ // column:database/table/column
+ // path:bucket/path
+ // key:volume/bucket/key
private String getDefaultRrnTemplate(RangerResourceDef
resourceDef) {
List<RangerResourceDef> path = new ArrayList<>();
@@ -878,10 +869,10 @@ private String getDefaultRrnTemplate(RangerResourceDef
resourceDef) {
RangerResourceDef res = path.get(i);
if (i > 0) {
-
sb.append(StringUtils.equalsIgnoreCase(res.getType(), "path") ?
RRN_PATH_RESOURCE_SEP : RRN_RESOURCE_SEP);
+ sb.append(RRN_RESOURCE_SEP);
}
-
sb.append(RRN_RESOURCE_PREFIX).append(res.getName()).append(RRN_RESOURCE_SUFFIX);
+ sb.append(res.getName());
}
return sb.toString();
diff --git
a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceDefHelper.java
b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceDefHelper.java
index af371c520..1f716df42 100644
---
a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceDefHelper.java
+++
b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceDefHelper.java
@@ -327,19 +327,12 @@ public void testRrnTemplateHive() {
RangerServiceDef svcDef =
JsonUtils.jsonToObject(reader, RangerServiceDef.class);
RangerServiceDefHelper svcDefHelper = new
RangerServiceDefHelper(svcDef);
- String rrnDatabase = svcDefHelper.getRrnTemplate("database");
- String rrnTable = svcDefHelper.getRrnTemplate("table");
- String rrnColumn = svcDefHelper.getRrnTemplate("column");
- String rrnUdf = svcDefHelper.getRrnTemplate("udf");
- String rrnUrl = svcDefHelper.getRrnTemplate("url");
- String rrnUnknown =
svcDefHelper.getRrnTemplate("unknown-resource");
-
- assertEquals("{database}", rrnDatabase);
- assertEquals("{database}.{table}", rrnTable);
- assertEquals("{database}.{table}.{column}", rrnColumn);
- assertEquals("{database}.{udf}", rrnUdf);
- assertEquals("{url}", rrnUrl);
- assertNull(rrnUnknown);
+ assertEquals("database",
svcDefHelper.getRrnTemplate("database"));
+ assertEquals("database/table",
svcDefHelper.getRrnTemplate("table"));
+ assertEquals("database/table/column",
svcDefHelper.getRrnTemplate("column"));
+ assertEquals("database/udf",
svcDefHelper.getRrnTemplate("udf"));
+ assertEquals("url", svcDefHelper.getRrnTemplate("url"));
+ assertNull(svcDefHelper.getRrnTemplate("unknown-resource"));
}
@Test
@@ -348,11 +341,8 @@ public void testRrnTemplateS3() {
RangerServiceDef svcDef =
JsonUtils.jsonToObject(reader, RangerServiceDef.class);
RangerServiceDefHelper svcDefHelper = new
RangerServiceDefHelper(svcDef);
- String rrnBucket = svcDefHelper.getRrnTemplate("bucket");
- String rrnPath = svcDefHelper.getRrnTemplate("path");
-
- assertEquals("{bucket}", rrnBucket);
- assertEquals("{bucket}/{path}", rrnPath);
+ assertEquals("bucket", svcDefHelper.getRrnTemplate("bucket"));
+ assertEquals("bucket/path",
svcDefHelper.getRrnTemplate("path"));
}
RangerResourceDef createResourceDef(String name, String parent) {
diff --git
a/authz-api/src/main/java/org/apache/ranger/authz/api/RangerAuthzApiErrorCode.java
b/authz-api/src/main/java/org/apache/ranger/authz/api/RangerAuthzApiErrorCode.java
index f289e3f55..cc7881d27 100644
---
a/authz-api/src/main/java/org/apache/ranger/authz/api/RangerAuthzApiErrorCode.java
+++
b/authz-api/src/main/java/org/apache/ranger/authz/api/RangerAuthzApiErrorCode.java
@@ -35,13 +35,11 @@ public enum RangerAuthzApiErrorCode implements
RangerAuthzErrorCode {
INVALID_REQUEST_PERMISSION_NOT_FOUND(400, "00-011", "{0}: permission not
found"),
INVALID_REQUEST_PERMISSIONS_EMPTY(400, "00-012", "permissions is empty.
Nothing to authorize"),
INVALID_REQUEST_SERVICE_NAME_OR_TYPE_MANDATORY(400, "00-013", "service
name or service type is mandatory"),
- INVALID_RESOURCE_TEMPLATE_UNEXPECTED_MARKER_AT(400, "00-014", "invalid
resource template: {0}. Unexpected marker \"{1}\" at position {2}"),
+ INVALID_RESOURCE_TEMPLATE_EMPTY_VALUE(400, "00-014", "invalid resource
template - empty"),
INVALID_RESOURCE_TYPE_NOT_VALID(400, "00-015", "invalid resource \"{0}\" -
unknown type \"{1}\""),
INVALID_RESOURCE_EMPTY_VALUE(400, "00-016", "invalid resource - empty"),
- INVALID_RESOURCE_PREFIX_MISMATCH(400, "00-017", "invalid resource \"{0}\"
- prefix \"{1}\" not found"),
- INVALID_RESOURCE_SUFFIX_MISMATCH(400, "00-018", "invalid resource \"{0}\"
- suffix \"{1}\" not found"),
- INVALID_RESOURCE_VALUE(400, "00-019", "invalid resource \"{0}\" - does not
match template \"{1}\"");
+ INVALID_RESOURCE_VALUE(400, "00-017", "invalid resource \"{0}\" - does not
match template \"{1}\"");
private static final String ERROR_CODE_MODULE_PREFIX = "AUTHZ";
diff --git
a/authz-api/src/main/java/org/apache/ranger/authz/util/RangerResourceNameParser.java
b/authz-api/src/main/java/org/apache/ranger/authz/util/RangerResourceNameParser.java
new file mode 100644
index 000000000..5000a5a43
--- /dev/null
+++
b/authz-api/src/main/java/org/apache/ranger/authz/util/RangerResourceNameParser.java
@@ -0,0 +1,216 @@
+/*
+ * 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.ranger.authz.util;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+import static
org.apache.ranger.authz.api.RangerAuthzApiErrorCode.INVALID_RESOURCE_EMPTY_VALUE;
+import static
org.apache.ranger.authz.api.RangerAuthzApiErrorCode.INVALID_RESOURCE_TEMPLATE_EMPTY_VALUE;
+import static
org.apache.ranger.authz.api.RangerAuthzApiErrorCode.INVALID_RESOURCE_VALUE;
+
+public class RangerResourceNameParser {
+ private static final Logger LOG =
LoggerFactory.getLogger(RangerResourceNameParser.class);
+
+ public static final char ESCAPE_CHAR = '\\';
+ public static final char SEPARATOR_CHAR = '/';
+
+ private static final String SEPARATOR_STRING =
String.valueOf(SEPARATOR_CHAR);
+ private static final String ESCAPED_SEPARATOR = "\\\\" +
SEPARATOR_STRING;
+ private static final Pattern SEPARATOR_PATTERN =
Pattern.compile(SEPARATOR_STRING);
+ private static final String[] EMPTY_ARRAY = new String[0];
+
+ private final String template; // examples: database/table/column,
bucket/volume/path
+ private final String[] resources; // examples: [database, table, column],
[bucket, volume, path]
+
+ public RangerResourceNameParser(String template) throws
RangerAuthzException {
+ if (StringUtils.isBlank(template)) {
+ throw new
RangerAuthzException(INVALID_RESOURCE_TEMPLATE_EMPTY_VALUE);
+ }
+
+ this.template = template;
+ this.resources = template.split(SEPARATOR_STRING); // assumption: '/'
is not a valid character in resource names
+ }
+
+ public String getTemplate() {
+ return template;
+ }
+
+ public String getResourceType() {
+ return resources[resources.length - 1];
+ }
+
+ public int count() {
+ return resources.length;
+ }
+
+ public String resourceAt(int index) {
+ return resources[index];
+ }
+
+ public String[] parseToArray(final String resourceName) throws
RangerAuthzException {
+ if (StringUtils.isBlank(resourceName)) {
+ throw new RangerAuthzException(INVALID_RESOURCE_EMPTY_VALUE);
+ }
+
+ final String[] ret = new String[resources.length];
+ final int nameLen = resourceName.length();
+ final StringBuilder token = new StringBuilder();
+ int idxToken = 0;
+ boolean isLastToken = resources.length == 1;
+ boolean isInEscape = false;
+
+ for (int i = 0; i < nameLen; i++) {
+ char c = resourceName.charAt(i);
+
+ if (c == ESCAPE_CHAR) {
+ if (!isInEscape) {
+ isInEscape = true;
+
+ continue;
+ }
+ } else if (c == SEPARATOR_CHAR) {
+ if (!isInEscape) {
+ if (!isLastToken) { // for last token, '/' is not a
separator
+ ret[idxToken++] = token.toString();
+
+ token.setLength(0);
+
+ isLastToken = idxToken == (resources.length - 1);
+
+ continue;
+ }
+ }
+ }
+
+ token.append(c);
+
+ isInEscape = false;
+ }
+
+ ret[idxToken] = token.toString();
+
+ if (!isLastToken) {
+ throw new RangerAuthzException(INVALID_RESOURCE_VALUE,
resourceName, template);
+ }
+
+ LOG.debug("parseToArray(resource='{}', template='{}'): ret={}",
resourceName, template, ret);
+
+ return ret;
+ }
+
+ public Map<String, String> parseToMap(final String resourceName) throws
RangerAuthzException {
+ final String[] arr = parseToArray(resourceName);
+ final Map<String, String> ret = new HashMap<>(arr.length);
+
+ for (int i = 0; i < arr.length; i++) {
+ ret.put(resources[i], arr[i]);
+ }
+
+ LOG.debug("parseToMap(resourceName='{}', template='{}'): ret={}",
resourceName, template, ret);
+
+ return ret;
+ }
+
+ public String toResourceName(String[] values) {
+ StringBuilder ret = new StringBuilder();
+
+ if (values == null) {
+ values = EMPTY_ARRAY;
+ }
+
+ for (int i = 0; i < resources.length; i++) {
+ String value = values.length > i ? values[i] : null;
+ boolean isLast = i == (resources.length - 1);
+
+ if (value == null) {
+ value = "";
+ }
+
+ if (!isLast) { // escape '/' in all but the last resource
+ value = escapeIfNeeded(value);
+ }
+
+ if (i > 0) {
+ ret.append(SEPARATOR_CHAR);
+ }
+
+ ret.append(value);
+ }
+
+ LOG.debug("toResourceName(values={}, template='{}'): ret='{}'",
values, template, ret);
+
+ return ret.toString();
+ }
+
+ public String toResourceName(Map<String, String> values) {
+ StringBuilder ret = new StringBuilder();
+
+ if (values == null) {
+ values = Collections.emptyMap();
+ }
+
+ for (int i = 0; i < resources.length; i++) {
+ String value = values.get(resources[i]);
+ boolean isLast = i == (resources.length - 1);
+
+ if (value == null) {
+ value = "";
+ }
+
+ if (!isLast) { // escape '/' in all but the last resource
+ value = escapeIfNeeded(value);
+ }
+
+ if (i > 0) {
+ ret.append(SEPARATOR_CHAR);
+ }
+
+ ret.append(value);
+ }
+
+ LOG.debug("toResourceName(values={}, template='{}'): ret='{}'",
values, template, ret);
+
+ return ret.toString();
+ }
+
+ @Override
+ public String toString() {
+ return "RangerResourceTemplate{" +
+ "template=" + template +
+ ", resources='" + String.join(SEPARATOR_STRING, resources) +
"'" +
+ "}";
+ }
+
+ private String escapeIfNeeded(String value) {
+ if (value.contains(SEPARATOR_STRING)) {
+ return
SEPARATOR_PATTERN.matcher(value).replaceAll(ESCAPED_SEPARATOR);
+ } else {
+ return value;
+ }
+ }
+}
diff --git
a/authz-api/src/main/java/org/apache/ranger/authz/util/RangerResourceTemplate.java
b/authz-api/src/main/java/org/apache/ranger/authz/util/RangerResourceTemplate.java
deleted file mode 100644
index a32e9c6c5..000000000
---
a/authz-api/src/main/java/org/apache/ranger/authz/util/RangerResourceTemplate.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * 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.ranger.authz.util;
-
-import org.apache.ranger.authz.api.RangerAuthzException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import static
org.apache.ranger.authz.api.RangerAuthzApiErrorCode.INVALID_RESOURCE_EMPTY_VALUE;
-import static
org.apache.ranger.authz.api.RangerAuthzApiErrorCode.INVALID_RESOURCE_PREFIX_MISMATCH;
-import static
org.apache.ranger.authz.api.RangerAuthzApiErrorCode.INVALID_RESOURCE_SUFFIX_MISMATCH;
-import static
org.apache.ranger.authz.api.RangerAuthzApiErrorCode.INVALID_RESOURCE_TEMPLATE_UNEXPECTED_MARKER_AT;
-import static
org.apache.ranger.authz.api.RangerAuthzApiErrorCode.INVALID_RESOURCE_VALUE;
-
-public class RangerResourceTemplate {
- private static final Logger LOG =
LoggerFactory.getLogger(RangerResourceTemplate.class);
-
- private static final char RESOURCE_START_CHAR = '{';
- private static final char RESOURCE_END_CHAR = '}';
- private static final char ESCAPE_CHAR = '\\';
-
- private final String template; // examples:
{database}.{table}.{column}, ofs://{bucket}/{volume}/{path}
- private final String[] resources; // examples: [database, table, column],
[bucket, volume, path]
- private final String prefix; // examples: "",
"ofs://"
- private final String[] separators; // examples: [".", "."],
["/", "/"]
- private final String suffix;
-
- public RangerResourceTemplate(String template) throws RangerAuthzException
{
- List<String> resources = new ArrayList<>();
- List<String> separators = new ArrayList<>();
- String prefix = null;
- boolean isInEscape = false;
- boolean isInResource = false;
- StringBuilder currentToken = new StringBuilder();
-
- for (int i = 0; i < template.length(); i++) {
- char c = template.charAt(i);
-
- if (isInEscape) {
- currentToken.append(c);
-
- isInEscape = false;
- } else if (c == ESCAPE_CHAR) {
- isInEscape = true;
- } else if (c == RESOURCE_START_CHAR) {
- if (isInResource) {
- throw new
RangerAuthzException(INVALID_RESOURCE_TEMPLATE_UNEXPECTED_MARKER_AT, template,
RESOURCE_START_CHAR, i);
- }
-
- if (prefix == null) {
- prefix = currentToken.toString();
- } else {
- separators.add(currentToken.toString());
- }
-
- isInResource = true;
-
- currentToken.setLength(0);
- } else if (c == RESOURCE_END_CHAR) {
- if (!isInResource) {
- throw new
RangerAuthzException(INVALID_RESOURCE_TEMPLATE_UNEXPECTED_MARKER_AT, template,
RESOURCE_END_CHAR, i);
- }
-
- resources.add(currentToken.toString());
-
- isInResource = false;
-
- currentToken.setLength(0);
- } else {
- currentToken.append(c);
- }
- }
-
- this.template = template;
- this.resources = resources.toArray(new String[0]);
- this.separators = separators.toArray(new String[0]);
- this.prefix = prefix;
- this.suffix = currentToken.toString();
- }
-
- public String getTemplate() {
- return template;
- }
-
- public Map<String, String> parse(String resource) throws
RangerAuthzException {
- Map<String, String> ret = null;
-
- if (resource == null || resource.isEmpty()) {
- throw new RangerAuthzException(INVALID_RESOURCE_EMPTY_VALUE);
- } else if (!resource.startsWith(prefix)) {
- throw new RangerAuthzException(INVALID_RESOURCE_PREFIX_MISMATCH,
resource, prefix);
- } else if (!resource.endsWith(suffix)) {
- throw new RangerAuthzException(INVALID_RESOURCE_SUFFIX_MISMATCH,
resource, suffix);
- } else {
- ret = new HashMap<>();
-
- int tokenStartPos = prefix.length();
-
- for (int i = 0; i < this.separators.length; i++) {
- String sep = this.separators[i];
- int idxSep = resource.indexOf(sep, tokenStartPos);
-
- LOG.debug("Separator '{}' found at {}: tokenStartPos={}", sep,
idxSep, tokenStartPos);
-
- if (idxSep == -1) {
- ret = null;
-
- break;
- } else {
- String value = resource.substring(tokenStartPos, idxSep);
-
- ret.put(this.resources[i], value);
- }
-
- tokenStartPos = idxSep + sep.length();
- }
-
- if (ret != null && tokenStartPos != -1) {
- String name = this.resources[this.resources.length - 1];
- String value = resource.substring(tokenStartPos,
resource.length() - suffix.length());
-
- ret.put(name, value);
- }
- }
-
- if (ret == null || ret.size() != resources.length) {
- throw new RangerAuthzException(INVALID_RESOURCE_VALUE, resource,
template);
- }
-
- LOG.debug("parse(resource='{}', template='{}'): ret={}", resource,
template, ret);
-
- return ret;
- }
-
- public String formatResource(Map<String, String> resourceMap) {
- StringBuilder ret = new StringBuilder(prefix);
-
- for (int i = 0; i < resources.length; i++) {
- String name = resources[i];
- String value = resourceMap.get(name);
-
- if (value == null) {
- value = "";
- }
-
- ret.append(value);
-
- if (i < separators.length) {
- ret.append(separators[i]);
- }
- }
-
- ret.append(suffix);
-
- LOG.debug("createResource(resourceMap={}, template='{}'): ret='{}'",
resourceMap, template, ret);
-
- return ret.toString();
- }
-
- @Override
- public String toString() {
- return "RangerResourceTemplate{" +
- "template=" + template +
- ", resources='" + String.join(",", resources) + "'" +
- ", prefix='" + prefix + "'" +
- ", separators='" + String.join(",", separators) + "'" +
- ", suffix='" + suffix + "'" +
- "}";
- }
-}
diff --git
a/authz-api/src/test/java/org/apache/ranger/authz/api/TestAuthzApiErrorCode.java
b/authz-api/src/test/java/org/apache/ranger/authz/api/TestAuthzApiErrorCode.java
index 441f1c36f..77c92e783 100644
---
a/authz-api/src/test/java/org/apache/ranger/authz/api/TestAuthzApiErrorCode.java
+++
b/authz-api/src/test/java/org/apache/ranger/authz/api/TestAuthzApiErrorCode.java
@@ -36,7 +36,7 @@
import static
org.apache.ranger.authz.api.RangerAuthzApiErrorCode.INVALID_REQUEST_SERVICE_NOT_FOUND;
import static
org.apache.ranger.authz.api.RangerAuthzApiErrorCode.INVALID_REQUEST_SERVICE_TYPE_NOT_FOUND;
import static
org.apache.ranger.authz.api.RangerAuthzApiErrorCode.INVALID_REQUEST_USER_INFO_MISSING;
-import static
org.apache.ranger.authz.api.RangerAuthzApiErrorCode.INVALID_RESOURCE_TEMPLATE_UNEXPECTED_MARKER_AT;
+import static
org.apache.ranger.authz.api.RangerAuthzApiErrorCode.INVALID_RESOURCE_TEMPLATE_EMPTY_VALUE;
import static
org.apache.ranger.authz.model.RangerResourceInfo.ResourceMatchScope.SELF;
import static
org.apache.ranger.authz.model.RangerResourceInfo.ResourceMatchScope.SELF_OR_ANY_CHILD;
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -59,12 +59,10 @@ public void testAuthzApiErrorCodeMessages() {
assertEquals("AUTHZ-400-00-011: mypermission: permission not found",
INVALID_REQUEST_PERMISSION_NOT_FOUND.getFormattedMessage("mypermission"));
assertEquals("AUTHZ-400-00-012: permissions is empty. Nothing to
authorize", INVALID_REQUEST_PERMISSIONS_EMPTY.getFormattedMessage());
assertEquals("AUTHZ-400-00-013: service name or service type is
mandatory",
INVALID_REQUEST_SERVICE_NAME_OR_TYPE_MANDATORY.getFormattedMessage());
- assertEquals("AUTHZ-400-00-014: invalid resource template:
{database}.{table}}. Unexpected marker \"}\" at position 18",
INVALID_RESOURCE_TEMPLATE_UNEXPECTED_MARKER_AT.getFormattedMessage("{database}.{table}}",
"}", 18));
+ assertEquals("AUTHZ-400-00-014: invalid resource template - empty",
INVALID_RESOURCE_TEMPLATE_EMPTY_VALUE.getFormattedMessage());
assertEquals("AUTHZ-400-00-015: invalid resource \"mytype:myresource\"
- unknown type \"mytype\"",
RangerAuthzApiErrorCode.INVALID_RESOURCE_TYPE_NOT_VALID.getFormattedMessage("mytype:myresource",
"mytype"));
assertEquals("AUTHZ-400-00-016: invalid resource - empty",
RangerAuthzApiErrorCode.INVALID_RESOURCE_EMPTY_VALUE.getFormattedMessage());
- assertEquals("AUTHZ-400-00-017: invalid resource \"mytype:myresource\"
- prefix \"myprefix\" not found",
RangerAuthzApiErrorCode.INVALID_RESOURCE_PREFIX_MISMATCH.getFormattedMessage("mytype:myresource",
"myprefix"));
- assertEquals("AUTHZ-400-00-018: invalid resource \"mytype:myresource\"
- suffix \"mysuffix\" not found",
RangerAuthzApiErrorCode.INVALID_RESOURCE_SUFFIX_MISMATCH.getFormattedMessage("mytype:myresource",
"mysuffix"));
- assertEquals("AUTHZ-400-00-019: invalid resource \"mytype:myresource\"
- does not match template \"{res1}.{res2}\"",
RangerAuthzApiErrorCode.INVALID_RESOURCE_VALUE.getFormattedMessage("mytype:myresource",
"{res1}.{res2}"));
+ assertEquals("AUTHZ-400-00-017: invalid resource \"mytype:myresource\"
- does not match template \"{res1}/{res2}\"",
RangerAuthzApiErrorCode.INVALID_RESOURCE_VALUE.getFormattedMessage("mytype:myresource",
"{res1}/{res2}"));
}
}
diff --git
a/authz-api/src/test/java/org/apache/ranger/authz/api/TestAuthzException.java
b/authz-api/src/test/java/org/apache/ranger/authz/api/TestAuthzException.java
index 59529371a..5aabe3631 100644
---
a/authz-api/src/test/java/org/apache/ranger/authz/api/TestAuthzException.java
+++
b/authz-api/src/test/java/org/apache/ranger/authz/api/TestAuthzException.java
@@ -37,9 +37,7 @@
import static
org.apache.ranger.authz.api.RangerAuthzApiErrorCode.INVALID_REQUEST_SERVICE_TYPE_NOT_FOUND;
import static
org.apache.ranger.authz.api.RangerAuthzApiErrorCode.INVALID_REQUEST_USER_INFO_MISSING;
import static
org.apache.ranger.authz.api.RangerAuthzApiErrorCode.INVALID_RESOURCE_EMPTY_VALUE;
-import static
org.apache.ranger.authz.api.RangerAuthzApiErrorCode.INVALID_RESOURCE_PREFIX_MISMATCH;
-import static
org.apache.ranger.authz.api.RangerAuthzApiErrorCode.INVALID_RESOURCE_SUFFIX_MISMATCH;
-import static
org.apache.ranger.authz.api.RangerAuthzApiErrorCode.INVALID_RESOURCE_TEMPLATE_UNEXPECTED_MARKER_AT;
+import static
org.apache.ranger.authz.api.RangerAuthzApiErrorCode.INVALID_RESOURCE_TEMPLATE_EMPTY_VALUE;
import static
org.apache.ranger.authz.api.RangerAuthzApiErrorCode.INVALID_RESOURCE_TYPE_NOT_VALID;
import static
org.apache.ranger.authz.api.RangerAuthzApiErrorCode.INVALID_RESOURCE_VALUE;
import static
org.apache.ranger.authz.model.RangerResourceInfo.ResourceMatchScope.SELF;
@@ -64,12 +62,10 @@ public void testAuthzApiExceptionMessage() {
assertEquals("AUTHZ-400-00-011: mypermission: permission not found",
new RangerAuthzException(INVALID_REQUEST_PERMISSION_NOT_FOUND,
"mypermission").getMessage());
assertEquals("AUTHZ-400-00-012: permissions is empty. Nothing to
authorize", new
RangerAuthzException(INVALID_REQUEST_PERMISSIONS_EMPTY).getMessage());
assertEquals("AUTHZ-400-00-013: service name or service type is
mandatory", new
RangerAuthzException(INVALID_REQUEST_SERVICE_NAME_OR_TYPE_MANDATORY).getMessage());
- assertEquals("AUTHZ-400-00-014: invalid resource template:
{database}.{table}}. Unexpected marker \"}\" at position 18", new
RangerAuthzException(INVALID_RESOURCE_TEMPLATE_UNEXPECTED_MARKER_AT,
"{database}.{table}}", "}", 18).getMessage());
+ assertEquals("AUTHZ-400-00-014: invalid resource template - empty",
new RangerAuthzException(INVALID_RESOURCE_TEMPLATE_EMPTY_VALUE).getMessage());
assertEquals("AUTHZ-400-00-015: invalid resource \"mytype:myresource\"
- unknown type \"mytype\"", new
RangerAuthzException(INVALID_RESOURCE_TYPE_NOT_VALID, "mytype:myresource",
"mytype").getMessage());
assertEquals("AUTHZ-400-00-016: invalid resource - empty", new
RangerAuthzException(INVALID_RESOURCE_EMPTY_VALUE).getMessage());
- assertEquals("AUTHZ-400-00-017: invalid resource \"mytype:myresource\"
- prefix \"myprefix\" not found", new
RangerAuthzException(INVALID_RESOURCE_PREFIX_MISMATCH, "mytype:myresource",
"myprefix").getMessage());
- assertEquals("AUTHZ-400-00-018: invalid resource \"mytype:myresource\"
- suffix \"mysuffix\" not found", new
RangerAuthzException(INVALID_RESOURCE_SUFFIX_MISMATCH, "mytype:myresource",
"mysuffix").getMessage());
- assertEquals("AUTHZ-400-00-019: invalid resource \"mytype:myresource\"
- does not match template \"{res1}.{res2}\"", new
RangerAuthzException(INVALID_RESOURCE_VALUE, "mytype:myresource",
"{res1}.{res2}").getMessage());
+ assertEquals("AUTHZ-400-00-017: invalid resource \"mytype:myresource\"
- does not match template \"{res1}/{res2}\"", new
RangerAuthzException(INVALID_RESOURCE_VALUE, "mytype:myresource",
"{res1}/{res2}").getMessage());
}
}
diff --git
a/authz-api/src/test/java/org/apache/ranger/authz/util/TestRangerResourceNameParser.java
b/authz-api/src/test/java/org/apache/ranger/authz/util/TestRangerResourceNameParser.java
new file mode 100644
index 000000000..8c137203b
--- /dev/null
+++
b/authz-api/src/test/java/org/apache/ranger/authz/util/TestRangerResourceNameParser.java
@@ -0,0 +1,406 @@
+/*
+ * 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.ranger.authz.util;
+
+import org.apache.ranger.authz.api.RangerAuthzErrorCode;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.junit.jupiter.api.Test;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import static
org.apache.ranger.authz.api.RangerAuthzApiErrorCode.INVALID_RESOURCE_EMPTY_VALUE;
+import static
org.apache.ranger.authz.api.RangerAuthzApiErrorCode.INVALID_RESOURCE_TEMPLATE_EMPTY_VALUE;
+import static
org.apache.ranger.authz.api.RangerAuthzApiErrorCode.INVALID_RESOURCE_TYPE_NOT_VALID;
+import static
org.apache.ranger.authz.api.RangerAuthzApiErrorCode.INVALID_RESOURCE_VALUE;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrowsExactly;
+
+public class TestRangerResourceNameParser {
+ @Test
+ public void testValidTemplates() throws Exception {
+ Object[][] testData = {
+ {"database", "database", 1, "database"},
+ {"database/table", "table", 2, "database", "table"},
+ {"database/table/column", "column", 3, "database", "table",
"column"},
+ {"bucket", "bucket", 1, "bucket"},
+ {"bucket/path", "path", 2, "bucket", "path"},
+ {"storageaccount", "storageaccount", 1, "storageaccount"},
+ {"storageaccount/container", "container", 2, "storageaccount",
"container"},
+ {"storageaccount/container/relativepath", "relativepath", 3,
"storageaccount", "container", "relativepath"},
+ {"catalog", "catalog", 1, "catalog"},
+ {"catalog/schema", "schema", 2, "catalog", "schema"},
+ {"catalog/schema/table", "table", 3, "catalog", "schema",
"table"},
+ {"catalog/schema/table/column", "column", 4, "catalog",
"schema", "table", "column"},
+ {"catalog/schema/procedure", "procedure", 3, "catalog",
"schema", "procedure"},
+ {"catalog/schema/schemafunction", "schemafunction", 3,
"catalog", "schema", "schemafunction"},
+ {"catalog/sessionproperty", "sessionproperty", 2, "catalog",
"sessionproperty"},
+ };
+
+ for (Object[] test : testData) {
+ String template = (String) test[0];
+ String resourceType = (String) test[1];
+ int resourceCount = (Integer) test[2];
+ RangerResourceNameParser resourceTemplate = new
RangerResourceNameParser(template);
+
+ assertEquals(resourceType, resourceTemplate.getResourceType(),
template);
+ assertEquals(resourceCount, resourceTemplate.count(), template);
+ assertEquals(template, resourceTemplate.getTemplate(), template);
+
+ for (int i = 0; i < resourceCount; i++) {
+ assertEquals(test[i + 3], resourceTemplate.resourceAt(i),
template + " at " + i);
+ }
+ }
+ }
+
+ @Test
+ public void testInvalidTemplates() throws Exception {
+ String[] templates = {
+ null,
+ "",
+ " ",
+ };
+
+ for (String template : templates) {
+ RangerAuthzException excp =
assertThrowsExactly(RangerAuthzException.class, () -> new
RangerResourceNameParser(template), template);
+
+ assertEquals(INVALID_RESOURCE_TEMPLATE_EMPTY_VALUE.getCode(),
excp.getErrorCode().getCode(), template);
+ }
+ }
+
+ @Test
+ public void testParseHiveResources() throws Exception {
+ Map<String, RangerResourceNameParser> templates = getHiveTemplates();
+
+ TestData[] tests = {
+ new TestData("database:db1", "database", "db1"),
+ new TestData("database:db1/", "database", "db1/"),
+ new TestData("table:db1/tbl1", "database", "db1", "table",
"tbl1"),
+ new TestData("table:db\\/1/tbl1", "database", "db/1", "table",
"tbl1"), // escape '/' in database name "db/1"
+ new TestData("column:db1/tbl1/col1", "database", "db1",
"table", "tbl1", "column", "col1"),
+ new TestData("column:db1//col1", "database", "db1", "table",
"", "column", "col1"), // empty table name
+ new TestData("column:db1//", "database", "db1", "table", "",
"column", ""), // empty table and column names
+ new TestData("column://", "database", "", "table", "",
"column", ""), // empty database, table and column names
+ new TestData("udf:db1/myUDF", "database", "db1", "udf",
"myUDF"),
+ new TestData("url:s3a://mybucket/db1/tbl1", "url",
"s3a://mybucket/db1/tbl1"),
+ new TestData("hiveservice:server1", "hiveservice", "server1"),
+ new TestData("global:*", "global", "*"),
+ // invalid values
+ new TestData("db1/tbl1/col1",
INVALID_RESOURCE_TYPE_NOT_VALID), // no resource-type
+ new TestData(":db1/tbl1/col1",
INVALID_RESOURCE_TYPE_NOT_VALID), // empty resource-type
+ new TestData("invalidResourceType:db1/tbl1/col1",
INVALID_RESOURCE_TYPE_NOT_VALID), // unknown resource-type
+ new TestData("database:", INVALID_RESOURCE_EMPTY_VALUE),
+ new TestData("table:db1_tbl1", INVALID_RESOURCE_VALUE),
+ new TestData("column:db1_tbl1/col1", INVALID_RESOURCE_VALUE),
+ new TestData("udf:db1_myUDF", INVALID_RESOURCE_VALUE),
+ };
+
+ for (TestData test : tests) {
+ if (test.errorCode != null) {
+ RangerAuthzException excp =
assertThrowsExactly(RangerAuthzException.class, () -> parseToMap(test.resource,
templates), test.resource);
+
+ assertEquals(test.errorCode.getCode(),
excp.getErrorCode().getCode(), test.resource);
+ } else {
+ assertEquals(test.expected, parseToMap(test.resource,
templates), test.resource);
+ }
+ }
+ }
+
+ @Test
+ public void testParseS3Resources() throws Exception {
+ Map<String, RangerResourceNameParser> templates = getS3Templates();
+
+ TestData[] tests = {
+ new TestData("bucket:mybucket", "bucket", "mybucket"),
+ new TestData("path:mybucket/myfolder/myfile.txt", "bucket",
"mybucket", "path", "myfolder/myfile.txt"), // no escape needed for '/' in
the last resource
+ new TestData("path:mybucket/myfolder\\/myfile.txt", "bucket",
"mybucket", "path", "myfolder/myfile.txt"), // escape in the last resource
should be ignored
+ new TestData("path:mybucket/\\/myfolder/myfile.txt", "bucket",
"mybucket", "path", "/myfolder/myfile.txt"), // escape in the last resource
should be ignored
+ new TestData("path:mybucket/", "bucket", "mybucket", "path",
""),
+ // invalid values
+ new TestData("mybucket/myfolder/myfile.txt",
INVALID_RESOURCE_TYPE_NOT_VALID), // no resource-type
+ new TestData(":mybucket/myfolder/myfile.txt",
INVALID_RESOURCE_TYPE_NOT_VALID), // empty resource-type
+ new
TestData("invalidResourceType:mybucket/myfolder/myfile.txt",
INVALID_RESOURCE_TYPE_NOT_VALID), // unknown resource-type
+ new TestData("bucket:", INVALID_RESOURCE_EMPTY_VALUE),
+ new TestData("path:mybucket_myfolder_myfile.txt",
INVALID_RESOURCE_VALUE),
+ };
+
+ for (TestData test : tests) {
+ if (test.errorCode != null) {
+ RangerAuthzException excp =
assertThrowsExactly(RangerAuthzException.class, () -> parseToMap(test.resource,
templates), test.resource);
+
+ assertEquals(test.errorCode.getCode(),
excp.getErrorCode().getCode(), test.resource);
+ } else {
+ assertEquals(test.expected, parseToMap(test.resource,
templates), test.resource);
+ }
+ }
+ }
+
+ @Test
+ public void testParseAdlsGen2Resources() throws Exception {
+ Map<String, RangerResourceNameParser> templates =
getAdlsGen2Templates();
+
+ TestData[] tests = {
+ new TestData("container:myaccount/mycontainer",
"storageaccount", "myaccount", "container", "mycontainer"),
+ new
TestData("relativepath:myaccount/mycontainer/p1/p2/f1.txt", "storageaccount",
"myaccount", "container", "mycontainer", "relativepath", "p1/p2/f1.txt"),
+ };
+
+ for (TestData test : tests) {
+ if (test.errorCode != null) {
+ RangerAuthzException excp =
assertThrowsExactly(RangerAuthzException.class, () -> parseToMap(test.resource,
templates), test.resource);
+
+ assertEquals(test.errorCode.getCode(),
excp.getErrorCode().getCode(), test.resource);
+ } else {
+ assertEquals(test.expected, parseToMap(test.resource,
templates), test.resource);
+ }
+ }
+ }
+
+ @Test
+ public void testParseTrinoResources() throws Exception {
+ Map<String, RangerResourceNameParser> templates = getTrinoTemplates();
+
+ TestData[] tests = {
+ new TestData("catalog:mycatalog", "catalog", "mycatalog"),
+ new TestData("schema:mycatalog/myschema", "catalog",
"mycatalog", "schema", "myschema"),
+ new TestData("table:mycatalog/myschema/mytable", "catalog",
"mycatalog", "schema", "myschema", "table", "mytable"),
+ new TestData("column:mycatalog/myschema/mytable/mycolumn",
"catalog", "mycatalog", "schema", "myschema", "table", "mytable", "column",
"mycolumn"),
+ new TestData("trinouser:myuser", "trinouser", "myuser"),
+ new TestData("systemproperty:myproperty", "systemproperty",
"myproperty"),
+ new TestData("sessionproperty:mycatalog/mysessionproperty",
"catalog", "mycatalog", "sessionproperty", "mysessionproperty"),
+ new TestData("function:myfunction", "function", "myfunction"),
+ new TestData("procedure:mycatalog/myschema/myprocedure",
"catalog", "mycatalog", "schema", "myschema", "procedure", "myprocedure"),
+ new
TestData("schemafunction:mycatalog/myschema/myschemafunction", "catalog",
"mycatalog", "schema", "myschema", "schemafunction", "myschemafunction"),
+ new
TestData("queryid:12345-67890-abcdefg-hijklmnopqrs-tuvwxyz", "queryid",
"12345-67890-abcdefg-hijklmnopqrs-tuvwxyz"),
+ new TestData("sysinfo:systeminfo", "sysinfo", "systeminfo"),
+ new TestData("role:myrole", "role", "myrole"),
+ // invalid values
+ new TestData("mycatalog/myschema/mytable/mycolumn",
INVALID_RESOURCE_TYPE_NOT_VALID), // no resource-type
+ new TestData(":mycatalog/myschema/mytable/mycolumn",
INVALID_RESOURCE_TYPE_NOT_VALID), // empty resource-type
+ new
TestData("invalidResourceType:mycatalog/myschema/mytable/mycolumn",
INVALID_RESOURCE_TYPE_NOT_VALID), // unknown resource-type
+ new TestData("catalog:", INVALID_RESOURCE_EMPTY_VALUE),
+ new TestData("schema:mycatalog_myschema",
INVALID_RESOURCE_VALUE),
+ new TestData("table:mycatalog_myschema_mytable",
INVALID_RESOURCE_VALUE),
+ new TestData("column:mycatalog_myschema_mytable_mycolumn",
INVALID_RESOURCE_VALUE),
+ new TestData("trinouser:", INVALID_RESOURCE_EMPTY_VALUE),
+ new TestData("sessionproperty:mycatalog_mysessionproperty",
INVALID_RESOURCE_VALUE),
+ new TestData("procedure:mycatalog_myschema_myprocedure",
INVALID_RESOURCE_VALUE),
+ };
+
+ for (TestData test : tests) {
+ if (test.errorCode != null) {
+ RangerAuthzException excp =
assertThrowsExactly(RangerAuthzException.class, () -> parseToMap(test.resource,
templates), test.resource);
+
+ assertEquals(test.errorCode.getCode(),
excp.getErrorCode().getCode(), test.resource);
+ } else {
+ assertEquals(test.expected, parseToMap(test.resource,
templates), test.resource);
+ }
+ }
+ }
+
+ @Test
+ public void testResourceNameFromMapHive() throws Exception {
+ Map<String, RangerResourceNameParser> templates = getHiveTemplates();
+
+ assertEquals("db1",
templates.get("database").toResourceName(toMap("database", "db1")));
+ assertEquals("db1/tbl1",
templates.get("table").toResourceName(toMap("database", "db1", "table",
"tbl1")));
+ assertEquals("db1/tbl1/col1",
templates.get("column").toResourceName(toMap("database", "db1", "table",
"tbl1", "column", "col1")));
+ assertEquals("db1/myUDF",
templates.get("udf").toResourceName(toMap("database", "db1", "udf", "myUDF")));
+ assertEquals("s3a://mybucket/db1/tbl1",
templates.get("url").toResourceName(toMap("url", "s3a://mybucket/db1/tbl1")));
+ assertEquals("server1",
templates.get("hiveservice").toResourceName(toMap("hiveservice", "server1")));
+ assertEquals("*",
templates.get("global").toResourceName(toMap("global", "*")));
+ assertEquals("db1/tbl\\/1/col1",
templates.get("column").toResourceName(toMap("database", "db1", "table",
"tbl/1", "column", "col1")));
+ assertEquals("db1/tbl\\/1/col/1",
templates.get("column").toResourceName(toMap("database", "db1", "table",
"tbl/1", "column", "col/1")));
+
+ // validate missing entries in map
+ assertEquals("", templates.get("database").toResourceName((Map<String,
String>) null));
+ assertEquals("",
templates.get("database").toResourceName(Collections.emptyMap()));
+ assertEquals("/", templates.get("table").toResourceName((Map<String,
String>) null));
+ assertEquals("/",
templates.get("table").toResourceName(Collections.emptyMap()));
+ assertEquals("/tbl1",
templates.get("table").toResourceName(toMap("table", "tbl1"))); // missing
database name
+ assertEquals("db1/",
templates.get("table").toResourceName(toMap("database", "db1"))); // missing
table name
+ assertEquals("//", templates.get("column").toResourceName((Map<String,
String>) null)); // null map
+ assertEquals("//",
templates.get("column").toResourceName(Collections.emptyMap())); // empty map
+ assertEquals("/tbl1/col1",
templates.get("column").toResourceName(toMap("table", "tbl1", "column",
"col1"))); // missing database name
+ assertEquals("db1//col1",
templates.get("column").toResourceName(toMap("database", "db1", "column",
"col1"))); // missing table name
+ assertEquals("db1/tbl1/",
templates.get("column").toResourceName(toMap("database", "db1", "table",
"tbl1"))); // missing column name
+ assertEquals("//",
templates.get("column").toResourceName(toMap("database", null, "table",
null))); // all names null or missing
+
+ // validate unknown entries in map
+ assertEquals("db1",
templates.get("database").toResourceName(toMap("database", "db1", "unknown",
"ignore")));
+ }
+
+ @Test
+ public void testResourceNameFromMapS3() throws Exception {
+ Map<String, RangerResourceNameParser> templates = getS3Templates();
+
+ assertEquals("mybucket",
templates.get("bucket").toResourceName(toMap("bucket", "mybucket")));
+ assertEquals("mybucket/myfolder/myfile.txt",
templates.get("path").toResourceName(toMap("bucket", "mybucket", "path",
"myfolder/myfile.txt")));
+ assertEquals("mybucket//myfolder/myfile.txt",
templates.get("path").toResourceName(toMap("bucket", "mybucket", "path",
"/myfolder/myfile.txt")));
+ }
+
+ @Test
+ public void testResourceNameFromArrayHive() throws Exception {
+ Map<String, RangerResourceNameParser> templates = getHiveTemplates();
+
+ assertEquals("db1",
templates.get("database").toResourceName(toArray("db1")));
+ assertEquals("db1/tbl1",
templates.get("table").toResourceName(toArray("db1", "tbl1")));
+ assertEquals("db1/tbl1/col1",
templates.get("column").toResourceName(toArray("db1", "tbl1", "col1")));
+ assertEquals("db1/myUDF",
templates.get("udf").toResourceName(toArray("db1", "myUDF")));
+ assertEquals("s3a://mybucket/db1/tbl1",
templates.get("url").toResourceName(toArray("s3a://mybucket/db1/tbl1")));
+ assertEquals("server1",
templates.get("hiveservice").toResourceName(toArray("server1")));
+ assertEquals("*",
templates.get("global").toResourceName(toArray("*")));
+ assertEquals("db1/tbl\\/1/col1",
templates.get("column").toResourceName(toArray("db1", "tbl/1", "col1")));
+ assertEquals("db1/tbl\\/1/col/1",
templates.get("column").toResourceName(toArray("db1", "tbl/1", "col/1")));
+
+ // validate null or missing entries in array
+ assertEquals("", templates.get("database").toResourceName((Map<String,
String>) null));
+ assertEquals("",
templates.get("database").toResourceName(Collections.emptyMap()));
+ assertEquals("/", templates.get("table").toResourceName((Map<String,
String>) null));
+ assertEquals("/",
templates.get("table").toResourceName(Collections.emptyMap()));
+ assertEquals("/tbl1",
templates.get("table").toResourceName(toArray(null, "tbl1"))); // null database
name
+ assertEquals("db1/",
templates.get("table").toResourceName(toArray("db1"))); // missing table name
+ assertEquals("//", templates.get("column").toResourceName((String[])
null)); // null array
+ assertEquals("//", templates.get("column").toResourceName(new
String[0])); // empty array
+ assertEquals("/tbl1/col1",
templates.get("column").toResourceName(toArray(null, "tbl1", "col1"))); // null
database name
+ assertEquals("db1//col1",
templates.get("column").toResourceName(toArray("db1", null, "col1"))); // null
table name
+ assertEquals("db1/tbl1/",
templates.get("column").toResourceName(toArray("db1", "tbl1", null))); // null
column name
+ assertEquals("db1/tbl1/",
templates.get("column").toResourceName(toArray("db1", "tbl1"))); // missing
column name
+
+ // validate unknown entries in map
+ assertEquals("db1",
templates.get("database").toResourceName(toArray("db1", "ignore")));
+ }
+
+ @Test
+ public void testResourceNameFromArrayS3() throws Exception {
+ Map<String, RangerResourceNameParser> templates = getS3Templates();
+
+ assertEquals("mybucket",
templates.get("bucket").toResourceName(toArray("mybucket")));
+ assertEquals("mybucket/myfolder/myfile.txt",
templates.get("path").toResourceName(toArray("mybucket",
"myfolder/myfile.txt")));
+ assertEquals("mybucket//myfolder/myfile.txt",
templates.get("path").toResourceName(toArray("mybucket",
"/myfolder/myfile.txt")));
+ }
+
+ private static Map<String, RangerResourceNameParser> getHiveTemplates()
throws Exception {
+ Map<String, RangerResourceNameParser> ret = new HashMap<>();
+
+ ret.put("database", new RangerResourceNameParser("database"));
+ ret.put("table", new RangerResourceNameParser("database/table"));
+ ret.put("column", new
RangerResourceNameParser("database/table/column"));
+ ret.put("udf", new RangerResourceNameParser("database/udf"));
+ ret.put("url", new RangerResourceNameParser("url"));
+ ret.put("hiveservice", new RangerResourceNameParser("hiveservice"));
+ ret.put("global", new RangerResourceNameParser("global"));
+
+ return ret;
+ }
+
+ private static Map<String, RangerResourceNameParser> getS3Templates()
throws Exception {
+ Map<String, RangerResourceNameParser> ret = new HashMap<>();
+
+ ret.put("bucket", new RangerResourceNameParser("bucket"));
+ ret.put("path", new RangerResourceNameParser("bucket/path"));
+
+ return ret;
+ }
+
+ private static Map<String, RangerResourceNameParser>
getAdlsGen2Templates() throws Exception {
+ Map<String, RangerResourceNameParser> ret = new HashMap<>();
+
+ ret.put("container", new
RangerResourceNameParser("storageaccount/container"));
+ ret.put("relativepath", new
RangerResourceNameParser("storageaccount/container/relativepath"));
+
+ return ret;
+ }
+
+ private static Map<String, RangerResourceNameParser> getTrinoTemplates()
throws Exception {
+ Map<String, RangerResourceNameParser> ret = new HashMap<>();
+
+ ret.put("catalog", new RangerResourceNameParser("catalog"));
+ ret.put("schema", new RangerResourceNameParser("catalog/schema"));
+ ret.put("table", new RangerResourceNameParser("catalog/schema/table"));
+ ret.put("column", new
RangerResourceNameParser("catalog/schema/table/column"));
+ ret.put("trinouser", new RangerResourceNameParser("trinouser"));
+ ret.put("systemproperty", new
RangerResourceNameParser("systemproperty"));
+ ret.put("sessionproperty", new
RangerResourceNameParser("catalog/sessionproperty"));
+ ret.put("function", new RangerResourceNameParser("function"));
+ ret.put("procedure", new
RangerResourceNameParser("catalog/schema/procedure"));
+ ret.put("schemafunction", new
RangerResourceNameParser("catalog/schema/schemafunction"));
+ ret.put("queryid", new RangerResourceNameParser("queryid"));
+ ret.put("sysinfo", new RangerResourceNameParser("sysinfo"));
+ ret.put("role", new RangerResourceNameParser("role"));
+
+ return ret;
+ }
+
+ private Map<String, String> parseToMap(String resource, Map<String,
RangerResourceNameParser> templates) throws RangerAuthzException {
+ String[] resourceParts = resource.split(":", 2);
+ String resourceType = resourceParts.length > 0 ?
resourceParts[0] : null;
+ String resourceValue = resourceParts.length > 1 ?
resourceParts[1] : null;
+ RangerResourceNameParser template = templates.get(resourceType);
+
+ if (template == null) {
+ throw new RangerAuthzException(INVALID_RESOURCE_TYPE_NOT_VALID,
resourceType);
+ }
+
+ return template.parseToMap(resourceValue);
+ }
+
+ private static class TestData {
+ public final String resource;
+ public final Map<String, String> expected;
+ public final RangerAuthzErrorCode errorCode;
+
+ public TestData(String resource, String...values) {
+ this.resource = resource;
+
+ if (values.length > 1) {
+ this.expected = new HashMap<>();
+ this.errorCode = null;
+
+ for (int i = 1; i < values.length; i += 2) {
+ expected.put(values[i - 1], values[i]);
+ }
+ } else {
+ this.expected = null;
+ this.errorCode = null;
+ }
+ }
+
+ public TestData(String resource, RangerAuthzErrorCode errorCode) {
+ this.resource = resource;
+ this.expected = null;
+ this.errorCode = errorCode;
+ }
+ }
+
+ private static Map<String, String> toMap(String... values) {
+ Map<String, String> ret = new HashMap<>();
+
+ for (int i = 1; i < values.length; i += 2) {
+ ret.put(values[i - 1], values[i]);
+ }
+
+ return ret;
+ }
+
+ private static String[] toArray(String... values) {
+ return values;
+ }
+}
diff --git
a/authz-api/src/test/java/org/apache/ranger/authz/util/TestResourceTemplate.java
b/authz-api/src/test/java/org/apache/ranger/authz/util/TestResourceTemplate.java
deleted file mode 100644
index 704fd77e9..000000000
---
a/authz-api/src/test/java/org/apache/ranger/authz/util/TestResourceTemplate.java
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * 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.ranger.authz.util;
-
-import org.apache.ranger.authz.api.RangerAuthzErrorCode;
-import org.apache.ranger.authz.api.RangerAuthzException;
-import org.junit.jupiter.api.Test;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import static
org.apache.ranger.authz.api.RangerAuthzApiErrorCode.INVALID_RESOURCE_EMPTY_VALUE;
-import static
org.apache.ranger.authz.api.RangerAuthzApiErrorCode.INVALID_RESOURCE_TYPE_NOT_VALID;
-import static
org.apache.ranger.authz.api.RangerAuthzApiErrorCode.INVALID_RESOURCE_VALUE;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertThrowsExactly;
-
-public class TestResourceTemplate {
- @Test
- public void testHiveResources() throws Exception {
- Map<String, RangerResourceTemplate> templates = getHiveTemplates();
-
- TestData[] tests = {
- new TestData("database:db1", "database", "db1"),
- new TestData("table:db1.tbl1", "database", "db1", "table",
"tbl1"),
- new TestData("column:db1.tbl1.col1", "database", "db1",
"table", "tbl1", "column", "col1"),
- new TestData("udf:db1.myUDF", "database", "db1", "udf",
"myUDF"),
- new TestData("url:s3a://mybucket/db1/tbl1", "url",
"s3a://mybucket/db1/tbl1"),
- new TestData("hiveservice:server1", "hiveservice", "server1"),
- new TestData("global:*", "global", "*"),
- // invalid values
- new TestData("db1.tbl1.col1",
INVALID_RESOURCE_TYPE_NOT_VALID), // no resource-type
- new TestData(":db1.tbl1.col1",
INVALID_RESOURCE_TYPE_NOT_VALID), // empty resource-type
- new TestData("invalidResourceType:db1.tbl1.col1",
INVALID_RESOURCE_TYPE_NOT_VALID), // unknown resource-type
- new TestData("database:", INVALID_RESOURCE_EMPTY_VALUE),
- new TestData("table:db1_tbl1", INVALID_RESOURCE_VALUE),
- new TestData("column:db1_tbl1.col1", INVALID_RESOURCE_VALUE),
- new TestData("udf:db1_myUDF", INVALID_RESOURCE_VALUE),
- };
-
- for (TestData test : tests) {
- if (test.errorCode != null) {
- RangerAuthzException excp =
assertThrowsExactly(RangerAuthzException.class, () ->
getResourceAsMap(test.resource, templates), test.resource);
-
- assertEquals(test.errorCode.getCode(),
excp.getErrorCode().getCode(), test.resource);
- } else {
- assertEquals(test.expected, getResourceAsMap(test.resource,
templates), test.resource);
- }
- }
- }
-
- @Test
- public void testS3Resources() throws Exception {
- Map<String, RangerResourceTemplate> templates = getS3Templates();
-
- TestData[] tests = {
- new TestData("bucket:mybucket", "bucket", "mybucket"),
- new TestData("path:mybucket/myfolder/myfile.txt", "bucket",
"mybucket", "path", "myfolder/myfile.txt"),
- new TestData("path:mybucket/", "bucket", "mybucket", "path",
""),
- // invalid values
- new TestData("mybucket/myfolder/myfile.txt",
INVALID_RESOURCE_TYPE_NOT_VALID), // no resource-type
- new TestData(":mybucket/myfolder/myfile.txt",
INVALID_RESOURCE_TYPE_NOT_VALID), // empty resource-type
- new
TestData("invalidResourceType:mybucket/myfolder/myfile.txt",
INVALID_RESOURCE_TYPE_NOT_VALID), // unknown resource-type
- new TestData("bucket:", INVALID_RESOURCE_EMPTY_VALUE),
- new TestData("path:mybucket_myfolder_myfile.txt",
INVALID_RESOURCE_VALUE),
- };
-
- for (TestData test : tests) {
- if (test.errorCode != null) {
- RangerAuthzException excp =
assertThrowsExactly(RangerAuthzException.class, () ->
getResourceAsMap(test.resource, templates), test.resource);
-
- assertEquals(test.errorCode.getCode(),
excp.getErrorCode().getCode(), test.resource);
- } else {
- assertEquals(test.expected, getResourceAsMap(test.resource,
templates), test.resource);
- }
- }
- }
-
- @Test
- public void testAdlsGen2Resources() throws Exception {
- Map<String, RangerResourceTemplate> templates = getAdlsGen2Templates();
-
- TestData[] tests = {
- new TestData("container:mycontainer@myaccount",
"storageaccount", "myaccount", "container", "mycontainer"),
- new
TestData("relativepath:mycontainer@myaccount/p1/p2/f1.txt", "storageaccount",
"myaccount", "container", "mycontainer", "relativepath", "p1/p2/f1.txt"),
- };
-
- for (TestData test : tests) {
- if (test.errorCode != null) {
- RangerAuthzException excp =
assertThrowsExactly(RangerAuthzException.class, () ->
getResourceAsMap(test.resource, templates), test.resource);
-
- assertEquals(test.errorCode.getCode(),
excp.getErrorCode().getCode(), test.resource);
- } else {
- assertEquals(test.expected, getResourceAsMap(test.resource,
templates), test.resource);
- }
- }
- }
-
- @Test
- public void testTrinoResources() throws Exception {
- Map<String, RangerResourceTemplate> templates = getTrinoTemplates();
-
- TestData[] tests = {
- new TestData("catalog:mycatalog", "catalog", "mycatalog"),
- new TestData("schema:mycatalog.myschema", "catalog",
"mycatalog", "schema", "myschema"),
- new TestData("table:mycatalog.myschema.mytable", "catalog",
"mycatalog", "schema", "myschema", "table", "mytable"),
- new TestData("column:mycatalog.myschema.mytable.mycolumn",
"catalog", "mycatalog", "schema", "myschema", "table", "mytable", "column",
"mycolumn"),
- new TestData("trinouser:myuser", "trinouser", "myuser"),
- new TestData("systemproperty:myproperty", "systemproperty",
"myproperty"),
- new TestData("sessionproperty:mycatalog.mysessionproperty",
"catalog", "mycatalog", "sessionproperty", "mysessionproperty"),
- new TestData("function:myfunction", "function", "myfunction"),
- new TestData("procedure:mycatalog.myschema.myprocedure",
"catalog", "mycatalog", "schema", "myschema", "procedure", "myprocedure"),
- new
TestData("schemafunction:mycatalog.myschema.myschemafunction", "catalog",
"mycatalog", "schema", "myschema", "schemafunction", "myschemafunction"),
- new
TestData("queryid:12345-67890-abcdefg-hijklmnopqrs-tuvwxyz", "queryid",
"12345-67890-abcdefg-hijklmnopqrs-tuvwxyz"),
- new TestData("sysinfo:systeminfo", "sysinfo", "systeminfo"),
- new TestData("role:myrole", "role", "myrole"),
- // invalid values
- new TestData("mycatalog.myschema.mytable.mycolumn",
INVALID_RESOURCE_TYPE_NOT_VALID), // no resource-type
- new TestData(":mycatalog.myschema.mytable.mycolumn",
INVALID_RESOURCE_TYPE_NOT_VALID), // empty resource-type
- new
TestData("invalidResourceType:mycatalog.myschema.mytable.mycolumn",
INVALID_RESOURCE_TYPE_NOT_VALID), // unknown resource-type
- new TestData("catalog:", INVALID_RESOURCE_EMPTY_VALUE),
- new TestData("schema:mycatalog_myschema",
INVALID_RESOURCE_VALUE),
- new TestData("table:mycatalog_myschema_mytable",
INVALID_RESOURCE_VALUE),
- new TestData("column:mycatalog_myschema_mytable_mycolumn",
INVALID_RESOURCE_VALUE),
- new TestData("trinouser:", INVALID_RESOURCE_EMPTY_VALUE),
- new TestData("sessionproperty:mycatalog_mysessionproperty",
INVALID_RESOURCE_VALUE),
- new TestData("procedure:mycatalog_myschema_myprocedure",
INVALID_RESOURCE_VALUE),
- };
-
- for (TestData test : tests) {
- if (test.errorCode != null) {
- RangerAuthzException excp =
assertThrowsExactly(RangerAuthzException.class, () ->
getResourceAsMap(test.resource, templates), test.resource);
-
- assertEquals(test.errorCode.getCode(),
excp.getErrorCode().getCode(), test.resource);
- } else {
- assertEquals(test.expected, getResourceAsMap(test.resource,
templates), test.resource);
- }
- }
- }
-
- private static Map<String, RangerResourceTemplate> getHiveTemplates()
throws Exception {
- Map<String, RangerResourceTemplate> ret = new HashMap<>();
-
- ret.put("database", new RangerResourceTemplate("{database}"));
- ret.put("table", new RangerResourceTemplate("{database}.{table}"));
- ret.put("column", new
RangerResourceTemplate("{database}.{table}.{column}"));
- ret.put("udf", new RangerResourceTemplate("{database}.{udf}"));
- ret.put("url", new RangerResourceTemplate("{url}"));
- ret.put("hiveservice", new RangerResourceTemplate("{hiveservice}"));
- ret.put("global", new RangerResourceTemplate("{global}"));
-
- return ret;
- }
-
- private static Map<String, RangerResourceTemplate> getS3Templates() throws
Exception {
- Map<String, RangerResourceTemplate> ret = new HashMap<>();
-
- ret.put("bucket", new RangerResourceTemplate("{bucket}"));
- ret.put("path", new RangerResourceTemplate("{bucket}/{path}"));
-
- return ret;
- }
-
- private static Map<String, RangerResourceTemplate> getAdlsGen2Templates()
throws Exception {
- Map<String, RangerResourceTemplate> ret = new HashMap<>();
-
- ret.put("container", new
RangerResourceTemplate("{container}@{storageaccount}"));
- ret.put("relativepath", new
RangerResourceTemplate("{container}@{storageaccount}/{relativepath}"));
-
- return ret;
- }
-
- private static Map<String, RangerResourceTemplate> getTrinoTemplates()
throws Exception {
- Map<String, RangerResourceTemplate> ret = new HashMap<>();
-
- ret.put("catalog", new RangerResourceTemplate("{catalog}"));
- ret.put("schema", new RangerResourceTemplate("{catalog}.{schema}"));
- ret.put("table", new
RangerResourceTemplate("{catalog}.{schema}.{table}"));
- ret.put("column", new
RangerResourceTemplate("{catalog}.{schema}.{table}.{column}"));
- ret.put("trinouser", new RangerResourceTemplate("{trinouser}"));
- ret.put("systemproperty", new
RangerResourceTemplate("{systemproperty}"));
- ret.put("sessionproperty", new
RangerResourceTemplate("{catalog}.{sessionproperty}"));
- ret.put("function", new RangerResourceTemplate("{function}"));
- ret.put("procedure", new
RangerResourceTemplate("{catalog}.{schema}.{procedure}"));
- ret.put("schemafunction", new
RangerResourceTemplate("{catalog}.{schema}.{schemafunction}"));
- ret.put("queryid", new RangerResourceTemplate("{queryid}"));
- ret.put("sysinfo", new RangerResourceTemplate("{sysinfo}"));
- ret.put("role", new RangerResourceTemplate("{role}"));
-
- return ret;
- }
-
- private Map<String, String> getResourceAsMap(String resource, Map<String,
RangerResourceTemplate> templates) throws RangerAuthzException {
- String[] resourceParts = resource.split(":", 2);
- String resourceType = resourceParts.length > 0 ?
resourceParts[0] : null;
- String resourceValue = resourceParts.length > 1 ?
resourceParts[1] : null;
- RangerResourceTemplate template = templates.get(resourceType);
-
- if (template == null) {
- throw new RangerAuthzException(INVALID_RESOURCE_TYPE_NOT_VALID,
resourceType);
- }
-
- return template.parse(resourceValue);
- }
-
- private static class TestData {
- public final String resource;
- public final Map<String, String> expected;
- public final RangerAuthzErrorCode errorCode;
-
- public TestData(String resource, String...values) {
- this.resource = resource;
-
- if (values.length > 1) {
- this.expected = new HashMap<>();
- this.errorCode = null;
-
- for (int i = 1; i < values.length; i += 2) {
- expected.put(values[i - 1], values[i]);
- }
- } else {
- this.expected = null;
- this.errorCode = null;
- }
- }
-
- public TestData(String resource, RangerAuthzErrorCode errorCode) {
- this.resource = resource;
- this.expected = null;
- this.errorCode = errorCode;
- }
- }
-}