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 2015/03/13 00:27:08 UTC
incubator-ranger git commit: RANGER-299 Service def validations;
RANGER-304 validation does several checks in case-insensitive manner
Repository: incubator-ranger
Updated Branches:
refs/heads/master 4d1abc89c -> 6e9f2a3b5
RANGER-299 Service def validations; RANGER-304 validation does several checks in case-insensitive manner
Conflicts:
security-admin/src/main/java/org/apache/ranger/rest/RangerServiceValidator.java
Signed-off-by: Madhan Neethiraj <ma...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/incubator-ranger/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ranger/commit/6e9f2a3b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ranger/tree/6e9f2a3b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ranger/diff/6e9f2a3b
Branch: refs/heads/master
Commit: 6e9f2a3b5a9cc2a04927ca6a99f8c3ec93f1891b
Parents: 4d1abc8
Author: Alok Lal <al...@hortonworks.com>
Authored: Thu Mar 5 14:55:18 2015 -0800
Committer: Madhan Neethiraj <ma...@apache.org>
Committed: Thu Mar 12 16:13:03 2015 -0700
----------------------------------------------------------------------
.../ranger/rest/RangerPolicyValidator.java | 26 +-
.../ranger/rest/RangerServiceDefValidator.java | 365 +++++++++++++++++++
.../ranger/rest/RangerServiceValidator.java | 31 +-
.../org/apache/ranger/rest/RangerValidator.java | 73 +++-
.../ranger/rest/RangerValidatorFactory.java | 4 +
.../org/apache/ranger/rest/ServiceREST.java | 6 +
.../ranger/rest/TestRangerPolicyValidator.java | 15 +-
.../rest/TestRangerServiceDefValidator.java | 353 ++++++++++++++++++
.../apache/ranger/rest/TestRangerValidator.java | 162 +++++++-
.../rest/TestServiceRESTForValidation.java | 133 ++++++-
.../apache/ranger/rest/ValidationTestUtils.java | 60 +++
11 files changed, 1167 insertions(+), 61 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/6e9f2a3b/security-admin/src/main/java/org/apache/ranger/rest/RangerPolicyValidator.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/rest/RangerPolicyValidator.java b/security-admin/src/main/java/org/apache/ranger/rest/RangerPolicyValidator.java
index 941bb21..281b32d 100644
--- a/security-admin/src/main/java/org/apache/ranger/rest/RangerPolicyValidator.java
+++ b/security-admin/src/main/java/org/apache/ranger/rest/RangerPolicyValidator.java
@@ -29,7 +29,7 @@ public class RangerPolicyValidator extends RangerValidator {
public void validate(RangerPolicy policy, Action action) throws Exception {
if(LOG.isDebugEnabled()) {
- LOG.debug(String.format("==> RangerValidator.validate(%s, %s)", policy, action));
+ LOG.debug(String.format("==> RangerPolicyValidator.validate(%s, %s)", policy, action));
}
List<ValidationFailureDetails> failures = new ArrayList<ValidationFailureDetails>();
@@ -42,7 +42,7 @@ public class RangerPolicyValidator extends RangerValidator {
}
} finally {
if(LOG.isDebugEnabled()) {
- LOG.debug(String.format("<== RangerValidator.validate(%s, %s): %s, reason[%s]", policy, action, valid, message));
+ LOG.debug(String.format("<== RangerPolicyValidator.validate(%s, %s): %s, reason[%s]", policy, action, valid, message));
}
}
}
@@ -151,7 +151,7 @@ public class RangerPolicyValidator extends RangerValidator {
failures.add(new ValidationFailureDetailsBuilder()
.field("id/name")
.isSemanticallyIncorrect()
- .becauseOf("id/name conflict: policy already exists with name[" + policyName + "], its id is[" + policies.iterator().next().getId() + "]")
+ .becauseOf("id/name conflict: another policy already exists with name[" + policyName + "], its id is[" + policies.iterator().next().getId() + "]")
.build());
valid = false;
}
@@ -396,17 +396,15 @@ public class RangerPolicyValidator extends RangerValidator {
.becauseOf("policy items access type's name was null/empty/blank")
.build());
valid = false;
- } else {
- if (!accessTypes.contains(accessType)) {
- String message = String.format("access type[%s] not among valid types for service[%s]", accessType, accessTypes);
- LOG.debug(message);
- failures.add(new ValidationFailureDetailsBuilder()
- .field("policy item access type")
- .isSemanticallyIncorrect()
- .becauseOf(message)
- .build());
- valid = false;
- }
+ } else if (!accessTypes.contains(accessType.toLowerCase())) {
+ String message = String.format("access type[%s] not among valid types for service[%s]", accessType, accessTypes);
+ LOG.debug(message);
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("policy item access type")
+ .isSemanticallyIncorrect()
+ .becauseOf(message)
+ .build());
+ valid = false;
}
Boolean isAllowed = access.getIsAllowed();
// it can be null (which is treated as allowed) but not false
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/6e9f2a3b/security-admin/src/main/java/org/apache/ranger/rest/RangerServiceDefValidator.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/rest/RangerServiceDefValidator.java b/security-admin/src/main/java/org/apache/ranger/rest/RangerServiceDefValidator.java
new file mode 100644
index 0000000..a84f68a
--- /dev/null
+++ b/security-admin/src/main/java/org/apache/ranger/rest/RangerServiceDefValidator.java
@@ -0,0 +1,365 @@
+package org.apache.ranger.rest;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumElementDef;
+import org.apache.ranger.plugin.store.ServiceStore;
+
+import com.google.common.collect.Sets;
+
+public class RangerServiceDefValidator extends RangerValidator {
+
+ private static final Log LOG = LogFactory.getLog(RangerServiceDefValidator.class);
+
+ public RangerServiceDefValidator(ServiceStore store) {
+ super(store);
+ }
+
+ public void validate(final RangerServiceDef serviceDef, final Action action) throws Exception {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug(String.format("==> RangerServiceDefValidator.validate(%s, %s)", serviceDef, action));
+ }
+
+ List<ValidationFailureDetails> failures = new ArrayList<ValidationFailureDetails>();
+ boolean valid = isValid(serviceDef, action, failures);
+ String message = "";
+ try {
+ if (!valid) {
+ message = serializeFailures(failures);
+ throw new Exception(message);
+ }
+ } finally {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug(String.format("<== RangerServiceDefValidator.validate(%s, %s): %s, reason[%s]", serviceDef, action, valid, message));
+ }
+ }
+ }
+
+ boolean isValid(final Long id, final Action action, final List<ValidationFailureDetails> failures) {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("==> RangerServiceDefValidator.isValid(" + id + ")");
+ }
+
+ boolean valid = true;
+ if (action != Action.DELETE) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .isAnInternalError()
+ .becauseOf("unsupported action[" + action + "]; isValid(Long) is only supported for DELETE")
+ .build());
+ valid = false;
+ } else if (id == null) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("id")
+ .isMissing()
+ .build());
+ valid = false;
+ } else if (getServiceDef(id) == null) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("id")
+ .isSemanticallyIncorrect()
+ .becauseOf("no service def found for id[" + id + "]")
+ .build());
+ valid = false;
+ }
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("<== RangerServiceDefValidator.isValid(" + id + "): " + valid);
+ }
+ return valid;
+ }
+
+ boolean isValid(final RangerServiceDef serviceDef, final Action action, final List<ValidationFailureDetails> failures) {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("==> RangerServiceDefValidator.isValid(" + serviceDef + ")");
+ }
+
+ if (!(action == Action.CREATE || action == Action.UPDATE)) {
+ throw new IllegalArgumentException("isValid(RangerServiceDef, ...) is only supported for CREATE/UPDATE");
+ }
+ boolean valid = true;
+ if (serviceDef == null) {
+ String message = "service def object passed in was null";
+ LOG.debug(message);
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("service def")
+ .isMissing()
+ .becauseOf(message)
+ .build());
+ valid = false;
+ } else {
+ Long id = serviceDef.getId();
+ if (action == Action.UPDATE) { // id is ignored for CREATE
+ if (id == null) {
+ String message = "service def id was null/empty/blank";
+ LOG.debug(message);
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("id")
+ .isMissing()
+ .becauseOf(message)
+ .build());
+ valid = false;
+ } else if (getServiceDef(id) == null) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("id")
+ .isSemanticallyIncorrect()
+ .becauseOf("no service def exists with id[" + id +"]")
+ .build());
+ valid = false;
+ }
+ }
+ // validate the service def name
+ String name = serviceDef.getName();
+ boolean nameSpecified = StringUtils.isNotBlank(name);
+ if (!nameSpecified) {
+ String message = "service def name[" + name + "] was null/empty/blank";
+ LOG.debug(message);
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("name")
+ .isMissing()
+ .becauseOf(message)
+ .build());
+ valid = false;
+ } else {
+ RangerServiceDef otherServiceDef = getServiceDef(name);
+ if (otherServiceDef != null && action == Action.CREATE) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("name")
+ .isSemanticallyIncorrect()
+ .becauseOf("service def with the name[" + name + "] already exists")
+ .build());
+ valid = false;
+ } else if (otherServiceDef != null && otherServiceDef.getId() !=null && otherServiceDef.getId() != id) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("id/name")
+ .isSemanticallyIncorrect()
+ .becauseOf("id/name conflict: another service def already exists with name[" + name + "], its id is [" + otherServiceDef.getId() + "]")
+ .build());
+ valid = false;
+ }
+ }
+ if (CollectionUtils.isEmpty(serviceDef.getAccessTypes())) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("access types")
+ .isMissing()
+ .becauseOf("access types collection was null/empty")
+ .build());
+ valid = false;
+ } else {
+ valid = isValidAccessTypes(serviceDef.getAccessTypes(), failures) && valid;
+ }
+ if (CollectionUtils.isEmpty(serviceDef.getEnums())) {
+ LOG.debug("No enums specified on the service def. Ok!");
+ } else {
+ valid = isValidEnums(serviceDef.getEnums(), failures) && valid;
+ }
+ }
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("<== RangerServiceDefValidator.isValid(" + serviceDef + "): " + valid);
+ }
+ return valid;
+ }
+
+ boolean isValidAccessTypes(final List<RangerAccessTypeDef> accessTypeDefs, final List<ValidationFailureDetails> failures) {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug(String.format("==> RangerServiceDefValidator.isValidAccessTypes(%s, %s)", accessTypeDefs, failures));
+ }
+
+ boolean valid = true;
+ if (CollectionUtils.isEmpty(accessTypeDefs)) {
+ LOG.debug("access type def collection is empty/null");
+ } else {
+ List<RangerAccessTypeDef> defsWithImpliedGrants = new ArrayList<RangerAccessTypeDef>();
+ Set<String> accessNames = new HashSet<String>();
+ for (RangerAccessTypeDef def : accessTypeDefs) {
+ String name = def.getName();
+ // name can't be null/empty/blank
+ if (StringUtils.isBlank(name)) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("access type name")
+ .isMissing()
+ .becauseOf("access type name[" + name + "] is null/empty")
+ .build());
+ valid = false;
+ } else if (accessNames.contains(name.toLowerCase())) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("access type name")
+ .subField(name)
+ .isSemanticallyIncorrect()
+ .becauseOf("duplicate access type names in access types collection: [" + name + "]")
+ .build());
+ valid = false;
+ } else {
+ accessNames.add(name.toLowerCase()); // we have a new unique access type
+ }
+ if (CollectionUtils.isNotEmpty(def.getImpliedGrants())) {
+ defsWithImpliedGrants.add(def);
+ }
+ }
+ // validate implied grants
+ for (RangerAccessTypeDef def : defsWithImpliedGrants) {
+ Collection<String> impliedGrants = getImpliedGrants(def);
+ Set<String> unknownAccessTypes = Sets.difference(Sets.newHashSet(impliedGrants), accessNames);
+ if (!unknownAccessTypes.isEmpty()) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("implied grants")
+ .subField(unknownAccessTypes.iterator().next()) // we return just on item here. Message has all unknow items
+ .isSemanticallyIncorrect()
+ .becauseOf("implied grant[" + impliedGrants + "] contains an unknown access types[" + unknownAccessTypes + "]")
+ .build());
+ valid = false;
+ }
+ // implied grant should not imply itself!
+ String name = def.getName(); // note: this name could be null/blank/empty!
+ if (impliedGrants.contains(name)) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("implied grants")
+ .subField(name)
+ .isSemanticallyIncorrect()
+ .becauseOf("implied grants list [" + impliedGrants + "] for access type[" + name + "] contains itself")
+ .build());
+ valid = false;
+ }
+ }
+ }
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug(String.format("<== RangerServiceDefValidator.isValidAccessTypes(%s, %s): %s", accessTypeDefs, failures, valid));
+ }
+ return valid;
+ }
+
+ boolean isValidEnums(List<RangerEnumDef> enumDefs, List<ValidationFailureDetails> failures) {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug(String.format("==> RangerServiceDefValidator.isValidEnums(%s, %s)", enumDefs, failures));
+ }
+
+ boolean valid = true;
+ if (CollectionUtils.isEmpty(enumDefs)) {
+ LOG.debug("enum def collection passed in was null/empty");
+ } else {
+ Set<String> enumNames = new HashSet<String>();
+ for (RangerEnumDef enumDef : enumDefs) {
+ if (enumDef == null) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("enum def")
+ .isMissing()
+ .becauseOf("An enum def in enums collection is null")
+ .build());
+ valid = false;
+ } else {
+ // enum-names must non-blank and be unique to a service definition
+ String enumName = enumDef.getName();
+ if (StringUtils.isBlank(enumName)) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("enum def name")
+ .isMissing()
+ .becauseOf("enum name [" + enumName + "] is null/empty")
+ .build());
+ valid = false;
+ } else if (enumNames.contains(enumName.toLowerCase())) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("enum def name")
+ .subField(enumName)
+ .isSemanticallyIncorrect()
+ .becauseOf("dumplicate enum name [" + enumName + "] found")
+ .build());
+ valid = false;
+ } else {
+ enumNames.add(enumName.toLowerCase());
+ }
+ // enum must contain at least one valid value and those values should be non-blank and distinct
+ if (CollectionUtils.isEmpty(enumDef.getElements())) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("enum values")
+ .subField(enumName)
+ .isMissing()
+ .becauseOf("enum [" + enumName + "] does not have any elements")
+ .build());
+ valid = false;
+ } else {
+ valid = isValidEnumElements(enumDef.getElements(), failures, enumName) && valid;
+ // default index should be valid
+ int defaultIndex = getEnumDefaultIndex(enumDef);
+ if (defaultIndex < 0 || defaultIndex >= enumDef.getElements().size()) { // max index is one less than the size of the elements list
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("enum default index")
+ .subField(enumName)
+ .isSemanticallyIncorrect()
+ .becauseOf("default index[" + defaultIndex + "] for enum [" + enumName + "] is invalid")
+ .build());
+ valid = false;
+ }
+ }
+ }
+ }
+ }
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug(String.format("<== RangerServiceDefValidator.isValidEnums(%s, %s): %s", enumDefs, failures, valid));
+ }
+ return valid;
+ }
+
+ boolean isValidEnumElements(List<RangerEnumElementDef> enumElementsDefs, List<ValidationFailureDetails> failures, String enumName) {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug(String.format("==> RangerServiceDefValidator.isValidEnums(%s, %s)", enumElementsDefs, failures));
+ }
+
+ boolean valid = true;
+ if (CollectionUtils.isEmpty(enumElementsDefs)) {
+ LOG.debug("Enum elements list passed in was null/empty!");
+ } else {
+ // enum element names should be valid and distinct
+ Set<String> elementNames = new HashSet<String>();
+ for (RangerEnumElementDef elementDef : enumElementsDefs) {
+ if (elementDef == null) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("enum element")
+ .subField(enumName)
+ .isMissing()
+ .becauseOf("An enum element in enum element collection of enum [" + enumName + "] is null")
+ .build());
+ valid = false;
+ } else {
+ String elementName = elementDef.getName();
+ if (StringUtils.isBlank(elementName)) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("enum element name")
+ .subField(enumName)
+ .isMissing()
+ .becauseOf("Name of an element of enum [" + enumName + "] is null/empty[" + elementName + "]")
+ .build());
+ valid = false;
+ } else if (elementNames.contains(elementName.toLowerCase())) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("enum element name")
+ .subField(enumName)
+ .isSemanticallyIncorrect()
+ .becauseOf("dumplicate enum element name [" + elementName + "] found for enum[" + enumName + "]")
+ .build());
+ valid = false;
+ } else {
+ elementNames.add(elementName.toLowerCase());
+ }
+ }
+ }
+ }
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug(String.format("<== RangerServiceDefValidator.isValidEnums(%s, %s): %s", enumElementsDefs, failures, valid));
+ }
+ return valid;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/6e9f2a3b/security-admin/src/main/java/org/apache/ranger/rest/RangerServiceValidator.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/rest/RangerServiceValidator.java b/security-admin/src/main/java/org/apache/ranger/rest/RangerServiceValidator.java
index 11e2682..8e02f25 100644
--- a/security-admin/src/main/java/org/apache/ranger/rest/RangerServiceValidator.java
+++ b/security-admin/src/main/java/org/apache/ranger/rest/RangerServiceValidator.java
@@ -42,18 +42,21 @@ public class RangerServiceValidator extends RangerValidator {
public void validate(RangerService service, Action action) throws Exception {
if(LOG.isDebugEnabled()) {
- LOG.debug("==> RangerValidator.validate(" + service + ")");
+ LOG.debug(String.format("==> RangerServiceValidator.validate(%s, %s)", service, action));
}
List<ValidationFailureDetails> failures = new ArrayList<ValidationFailureDetails>();
- if (isValid(service, action, failures)) {
+ boolean valid = isValid(service, action, failures);
+ String message = "";
+ try {
+ if (!valid) {
+ message = serializeFailures(failures);
+ throw new Exception(message);
+ }
+ } finally {
if(LOG.isDebugEnabled()) {
- LOG.debug("<== RangerValidator.validate(" + service + "): valid");
+ LOG.debug(String.format("<== RangerServiceValidator.validate(%s, %s): %s, reason[%s]", service, action, valid, message));
}
- } else {
- String message = serializeFailures(failures);
- LOG.debug("<== RangerValidator.validate(" + service + "): invalid, reason[" + message + "]");
- throw new Exception(message);
}
}
@@ -66,7 +69,7 @@ public class RangerServiceValidator extends RangerValidator {
if (action != Action.DELETE) {
failures.add(new ValidationFailureDetailsBuilder()
.isAnInternalError()
- .becauseOf("isValid(Long) is only supported for DELETE")
+ .becauseOf("unsupported action[" + action + "]; isValid(Long) is only supported for DELETE")
.build());
valid = false;
} else if (id == null) {
@@ -133,7 +136,7 @@ public class RangerServiceValidator extends RangerValidator {
boolean nameSpecified = StringUtils.isNotBlank(name);
RangerServiceDef serviceDef = null;
if (!nameSpecified) {
- String message = "service name was null/empty/blank[" + name + "]";
+ String message = "service name[" + name + "] was null/empty/blank";
LOG.debug(message);
failures.add(new ValidationFailureDetailsBuilder()
.field("name")
@@ -147,14 +150,14 @@ public class RangerServiceValidator extends RangerValidator {
failures.add(new ValidationFailureDetailsBuilder()
.field("name")
.isSemanticallyIncorrect()
- .becauseOf("service already exists with name[" + name + "]")
+ .becauseOf("service with the name[" + name + "] already exists")
.build());
valid = false;
} else if (otherService != null && otherService.getId() !=null && otherService.getId() != id) {
failures.add(new ValidationFailureDetailsBuilder()
.field("id/name")
.isSemanticallyIncorrect()
- .becauseOf("id/name conflict: service already exists with name[" + name + "], its id is [" + otherService.getId() + "]")
+ .becauseOf("id/name conflict: another service already exists with name[" + name + "], its id is [" + otherService.getId() + "]")
.build());
valid = false;
}
@@ -165,7 +168,7 @@ public class RangerServiceValidator extends RangerValidator {
failures.add(new ValidationFailureDetailsBuilder()
.field("type")
.isMissing()
- .becauseOf("service def was null/empty/blank")
+ .becauseOf("service def [" + type + "] was null/empty/blank")
.build());
valid = false;
} else {
@@ -174,7 +177,7 @@ public class RangerServiceValidator extends RangerValidator {
failures.add(new ValidationFailureDetailsBuilder()
.field("type")
.isSemanticallyIncorrect()
- .becauseOf("service def not found for type[" + type + "]")
+ .becauseOf("service def named[" + type + "] not found")
.build());
valid = false;
}
@@ -188,7 +191,7 @@ public class RangerServiceValidator extends RangerValidator {
.field("configuration")
.subField(missingParameters.iterator().next()) // we return any one parameter!
.isMissing()
- .becauseOf("required configuration parameter is missing")
+ .becauseOf("required configuration parameter is missing; missing parameters: " + missingParameters)
.build());
valid = false;
}
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/6e9f2a3b/security-admin/src/main/java/org/apache/ranger/rest/RangerValidator.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/rest/RangerValidator.java b/security-admin/src/main/java/org/apache/ranger/rest/RangerValidator.java
index b6948dc..cec40fd 100644
--- a/security-admin/src/main/java/org/apache/ranger/rest/RangerValidator.java
+++ b/security-admin/src/main/java/org/apache/ranger/rest/RangerValidator.java
@@ -21,6 +21,7 @@ package org.apache.ranger.rest;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -36,6 +37,7 @@ import org.apache.ranger.plugin.model.RangerPolicy;
import org.apache.ranger.plugin.model.RangerService;
import org.apache.ranger.plugin.model.RangerServiceDef;
import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumDef;
import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
import org.apache.ranger.plugin.model.RangerServiceDef.RangerServiceConfigDef;
import org.apache.ranger.plugin.store.ServiceStore;
@@ -149,6 +151,24 @@ public abstract class RangerValidator {
return result;
}
+ RangerServiceDef getServiceDef(Long id) {
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("==> RangerValidator.getServiceDef(" + id + ")");
+ }
+ RangerServiceDef result = null;
+ try {
+ result = _store.getServiceDef(id);
+ } catch (Exception e) {
+ LOG.debug("Encountred exception while retrieving service def from service store!", e);
+ }
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("<== RangerValidator.getServiceDef(" + id + "): " + result);
+ }
+ return result;
+ }
+
RangerServiceDef getServiceDef(String type) {
if(LOG.isDebugEnabled()) {
@@ -262,7 +282,7 @@ public abstract class RangerValidator {
if (StringUtils.isBlank(accessType)) {
LOG.warn("Access type def name was null/empty/blank!");
} else {
- accessTypes.add(accessType);
+ accessTypes.add(accessType.toLowerCase());
}
}
}
@@ -299,6 +319,11 @@ public abstract class RangerValidator {
return isEnabled;
}
+ /**
+ * Returns names of resource types set to lower-case to allow for case-insensitive comparison.
+ * @param serviceDef
+ * @return
+ */
Set<String> getMandatoryResourceNames(RangerServiceDef serviceDef) {
if(LOG.isDebugEnabled()) {
LOG.debug("==> RangerValidator.getMandatoryResourceNames(" + serviceDef + ")");
@@ -320,7 +345,7 @@ public abstract class RangerValidator {
if (StringUtils.isBlank(resourceName)) {
LOG.warn("Resource def name was null/empty/blank!");
} else {
- resourceNames.add(resourceName);
+ resourceNames.add(resourceName.toLowerCase());
}
}
}
@@ -352,7 +377,7 @@ public abstract class RangerValidator {
if (StringUtils.isBlank(resourceName)) {
LOG.warn("Resource def name was null/empty/blank!");
} else {
- resourceNames.add(resourceName);
+ resourceNames.add(resourceName.toLowerCase());
}
}
}
@@ -364,11 +389,20 @@ public abstract class RangerValidator {
return resourceNames;
}
+ /**
+ * Returns the resource-types defined on the policy converted to lowe-case
+ * @param policy
+ * @return
+ */
Set<String> getPolicyResources(RangerPolicy policy) {
if (policy == null || policy.getResources() == null || policy.getResources().isEmpty()) {
return new HashSet<String>();
} else {
- return policy.getResources().keySet();
+ Set<String> result = new HashSet<String>();
+ for (String name : policy.getResources().keySet()) {
+ result.add(name.toLowerCase());
+ }
+ return result;
}
}
@@ -395,4 +429,35 @@ public abstract class RangerValidator {
return result;
}
}
+
+ int getEnumDefaultIndex(RangerEnumDef enumDef) {
+ int index;
+ if (enumDef == null) {
+ index = -1;
+ } else if (enumDef.getDefaultIndex() == null) {
+ index = 0;
+ } else {
+ index = enumDef.getDefaultIndex();
+ }
+ return index;
+ }
+
+ Collection<String> getImpliedGrants(RangerAccessTypeDef def) {
+ if (def == null) {
+ return null;
+ } else if (CollectionUtils.isEmpty(def.getImpliedGrants())) {
+ return new ArrayList<String>();
+ } else {
+ List<String> result = new ArrayList<String>(def.getImpliedGrants().size());
+ for (String name : def.getImpliedGrants()) {
+ if (StringUtils.isBlank(name)) {
+ result.add(name); // could be null!
+ } else {
+ result.add(name.toLowerCase());
+ }
+ }
+ return result;
+ }
+ }
+
}
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/6e9f2a3b/security-admin/src/main/java/org/apache/ranger/rest/RangerValidatorFactory.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/rest/RangerValidatorFactory.java b/security-admin/src/main/java/org/apache/ranger/rest/RangerValidatorFactory.java
index 01b0a7e..025595d 100644
--- a/security-admin/src/main/java/org/apache/ranger/rest/RangerValidatorFactory.java
+++ b/security-admin/src/main/java/org/apache/ranger/rest/RangerValidatorFactory.java
@@ -30,4 +30,8 @@ public class RangerValidatorFactory {
public RangerPolicyValidator getPolicyValidator(ServiceDBStore store) {
return new RangerPolicyValidator(store);
}
+
+ public RangerServiceDefValidator getServiceDefValidator(ServiceDBStore store) {
+ return new RangerServiceDefValidator(store);
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/6e9f2a3b/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java b/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java
index be52892..8f41288 100644
--- a/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java
+++ b/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java
@@ -119,6 +119,8 @@ public class ServiceREST {
RangerServiceDef ret = null;
try {
+ RangerServiceDefValidator validator = validatorFactory.getServiceDefValidator(svcStore);
+ validator.validate(serviceDef, Action.CREATE);
ret = svcStore.createServiceDef(serviceDef);
} catch(Exception excp) {
LOG.error("createServiceDef(" + serviceDef + ") failed", excp);
@@ -145,6 +147,8 @@ public class ServiceREST {
RangerServiceDef ret = null;
try {
+ RangerServiceDefValidator validator = validatorFactory.getServiceDefValidator(svcStore);
+ validator.validate(serviceDef, Action.UPDATE);
ret = svcStore.updateServiceDef(serviceDef);
} catch(Exception excp) {
LOG.error("updateServiceDef(" + serviceDef + ") failed", excp);
@@ -169,6 +173,8 @@ public class ServiceREST {
}
try {
+ RangerServiceDefValidator validator = validatorFactory.getServiceDefValidator(svcStore);
+ validator.validate(id, Action.DELETE);
svcStore.deleteServiceDef(id);
} catch(Exception excp) {
LOG.error("deleteServiceDef(" + id + ") failed", excp);
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/6e9f2a3b/security-admin/src/test/java/org/apache/ranger/rest/TestRangerPolicyValidator.java
----------------------------------------------------------------------
diff --git a/security-admin/src/test/java/org/apache/ranger/rest/TestRangerPolicyValidator.java b/security-admin/src/test/java/org/apache/ranger/rest/TestRangerPolicyValidator.java
index 4e15753..c3fdf30 100644
--- a/security-admin/src/test/java/org/apache/ranger/rest/TestRangerPolicyValidator.java
+++ b/security-admin/src/test/java/org/apache/ranger/rest/TestRangerPolicyValidator.java
@@ -45,20 +45,20 @@ public class TestRangerPolicyValidator {
"groups", new String[] {"group1", "group2"},
"accesses", new String[] { "r", "w" },
"isAllowed", new Boolean[] { true, true }),
- ImmutableMap.of( // no users
+ ImmutableMap.of( // no users, access type different case
"groups", new String[] {"group3", "group4"},
- "accesses", new String[]{"w", "x"},
+ "accesses", new String[]{"W", "x"},
"isAllowed", new Boolean[] { true, true }),
ImmutableMap.of( // no groups
"users", new String[] {"user3" ," user4"},
"accesses", new String[] { "r", "x" },
"isAllowed", new Boolean[] { true, true }),
- ImmutableMap.of( // isallowed on access types is null
+ ImmutableMap.of( // isallowed on access types is null, case is different from that in definition
"users", new String[] {"user7" ," user6"},
"accesses", new String[] { "a" },
"isAllowed", new Boolean[] { null, null })
};
- String[] accessTypes = new String[] { "r", "w", "x", "a" };
+ String[] accessTypes = new String[] { "r", "w", "x", "A" }; // mix of lower and upper case
String[] accessTypes_bad = new String[] { "r", "w", "xx", }; // two missing (x, a), one new that isn't on bad (xx)
final Object[][] resourceDefData = new Object[][] {
@@ -69,7 +69,8 @@ public class TestRangerPolicyValidator {
final Map<String, String[]> policyResourceMap_good = ImmutableMap.of(
"db", new String[] { "db1", "db2" },
- "tbl", new String[] { "tbl1", "tbl2" } );
+ "TBL", new String[] { "tbl1", "tbl2" } ); // case should not matter
+
final Map<String, String[]> policyResourceMap_bad = ImmutableMap.of(
"db", new String[] { "db1", "db2" }, // mandatory "tbl" missing
"col", new String[] { "col12", "col 1" }, // wrong format of value for "col"
@@ -424,9 +425,9 @@ public class TestRangerPolicyValidator {
public void test_isValidPolicyItemAccess_happyPath() {
RangerPolicyItemAccess access = mock(RangerPolicyItemAccess.class);
- when(access.getType()).thenReturn("anAccess"); // valid
+ when(access.getType()).thenReturn("an-Access"); // valid
- Set<String> validAccesses = Sets.newHashSet(new String[] { "anAccess", "anotherAccess" });
+ Set<String> validAccesses = Sets.newHashSet(new String[] { "an-access", "another-access" }); // valid accesses should be lower-cased
// both null or true access types are the same and valid
for (Boolean allowed : new Boolean[] { null, true } ) {
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/6e9f2a3b/security-admin/src/test/java/org/apache/ranger/rest/TestRangerServiceDefValidator.java
----------------------------------------------------------------------
diff --git a/security-admin/src/test/java/org/apache/ranger/rest/TestRangerServiceDefValidator.java b/security-admin/src/test/java/org/apache/ranger/rest/TestRangerServiceDefValidator.java
new file mode 100644
index 0000000..b621673
--- /dev/null
+++ b/security-admin/src/test/java/org/apache/ranger/rest/TestRangerServiceDefValidator.java
@@ -0,0 +1,353 @@
+package org.apache.ranger.rest;
+
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumElementDef;
+import org.apache.ranger.plugin.store.ServiceStore;
+import org.apache.ranger.rest.RangerValidator.Action;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.collect.ImmutableMap;
+
+public class TestRangerServiceDefValidator {
+
+ @Before
+ public void setUp() throws Exception {
+ _store = mock(ServiceStore.class);
+ _validator = new RangerServiceDefValidator(_store);
+ _failures = new ArrayList<ValidationFailureDetails>();
+ _serviceDef = mock(RangerServiceDef.class);
+ }
+
+ final Action[] cu = new Action[] { Action.CREATE, Action.UPDATE };
+
+ final Object[][] accessTypes_good = new Object[][] {
+ { "read", null }, // ok, null implied grants
+ { "write", new String[] { } }, // ok, empty implied grants
+ { "admin", new String[] { "READ", "write" } } // ok, admin access implies read/write, access types are case-insensitive
+ };
+
+ final Map<String, String[]> enums_good = ImmutableMap.of(
+ "authentication-type", new String[] { "simple", "kerberos" },
+ "time-unit", new String[] { "day", "hour", "minute" }
+ );
+
+ @Test
+ public final void test_isValid_happyPath_create() throws Exception {
+
+ // setup access types with implied access and couple of enums
+ List<RangerAccessTypeDef> accessTypeDefs = _utils.createAccessTypeDefs(accessTypes_good);
+ when(_serviceDef.getAccessTypes()).thenReturn(accessTypeDefs);
+ List<RangerEnumDef> enumDefs = _utils.createEnumDefs(enums_good);
+ when(_serviceDef.getEnums()).thenReturn(enumDefs);
+
+ // create: id is not relevant, name should not conflict
+ when(_serviceDef.getId()).thenReturn(null); // id is not relevant for create
+ when(_serviceDef.getName()).thenReturn("aServiceDef"); // service has a name
+ when(_store.getServiceDefByName("aServiceDef")).thenReturn(null); // no name collision
+ assertTrue(_validator.isValid(_serviceDef, Action.CREATE, _failures));
+ assertTrue(_failures.isEmpty());
+
+ // update: id should match existing service, name should not point to different service def
+ when(_serviceDef.getId()).thenReturn(5L);
+ RangerServiceDef existingServiceDef = mock(RangerServiceDef.class);
+ when(_store.getServiceDef(5L)).thenReturn(existingServiceDef);
+ assertTrue(_validator.isValid(_serviceDef, Action.UPDATE, _failures));
+ assertTrue(_failures.isEmpty());
+
+ // update: if name points to a service that it's id should be the same
+ RangerServiceDef anotherExistingServiceDef = mock(RangerServiceDef.class);
+ when(anotherExistingServiceDef.getId()).thenReturn(5L);
+ when(_store.getServiceDefByName("aServiceDef")).thenReturn(anotherExistingServiceDef);
+ assertTrue(_validator.isValid(_serviceDef, Action.UPDATE, _failures));
+ assertTrue(_failures.isEmpty());
+ }
+
+ @Test
+ public final void testIsValid_Long_failures() throws Exception {
+ Long id = null;
+ // passing in wrong action type
+ boolean result = _validator.isValid((Long)null, Action.CREATE, _failures);
+ assertFalse(result);
+ _utils.checkFailureForInternalError(_failures);
+ // passing in null id is an error
+ _failures.clear(); assertFalse(_validator.isValid((Long)null, Action.DELETE, _failures));
+ _utils.checkFailureForMissingValue(_failures, "id");
+ // a service def with that id should exist, else it is an error
+ id = 3L;
+ when(_store.getServiceDef(id)).thenReturn(null);
+ _failures.clear(); assertFalse(_validator.isValid(id, Action.DELETE, _failures));
+ _utils.checkFailureForSemanticError(_failures, "id");
+ // happypath
+ when(_store.getServiceDef(id)).thenReturn(_serviceDef);
+ _failures.clear(); assertTrue(_validator.isValid(id, Action.DELETE, _failures));
+ assertTrue(_failures.isEmpty());
+ }
+
+ @Test
+ public final void testIsValid_failures_name() throws Exception {
+ // null service def and bad service def name
+ for (Action action : cu) {
+ // passing in null service def is an error
+ assertFalse(_validator.isValid((RangerServiceDef)null, action, _failures));
+ _utils.checkFailureForMissingValue(_failures, "service def");
+ // name should be valid
+ for (String name : new String[] { null, "", " " }) {
+ when(_serviceDef.getName()).thenReturn(name);
+ _failures.clear(); assertFalse(_validator.isValid(_serviceDef, action, _failures));
+ _utils.checkFailureForMissingValue(_failures, "name");
+ }
+ }
+ }
+
+ @Test
+ public final void testIsValid_failures_id() throws Exception {
+ // id is required for update
+ when(_serviceDef.getId()).thenReturn(null);
+ assertFalse(_validator.isValid(_serviceDef, Action.UPDATE, _failures));
+ _utils.checkFailureForMissingValue(_failures, "id");
+
+ // update: service should exist for the passed in id
+ Long id = 7L;
+ when(_serviceDef.getId()).thenReturn(id);
+ when(_store.getServiceDef(id)).thenReturn(null);
+ assertFalse(_validator.isValid(_serviceDef, Action.UPDATE, _failures));
+ _utils.checkFailureForSemanticError(_failures, "id");
+
+ when(_store.getServiceDef(id)).thenThrow(new Exception());
+ assertFalse(_validator.isValid(_serviceDef, Action.UPDATE, _failures));
+ _utils.checkFailureForSemanticError(_failures, "id");
+ }
+
+ @Test
+ public final void testIsValid_failures_nameId_create() throws Exception {
+ // service shouldn't exist with the name
+ RangerServiceDef existingServiceDef = mock(RangerServiceDef.class);
+ when(_store.getServiceDefByName("existing-service")).thenReturn(existingServiceDef);
+ when(_serviceDef.getName()).thenReturn("existing-service");
+ _failures.clear(); assertFalse(_validator.isValid(_serviceDef, Action.CREATE, _failures));
+ _utils.checkFailureForSemanticError(_failures, "name");
+ }
+
+ @Test
+ public final void testIsValid_failures_nameId_update() throws Exception {
+
+ // update: if service exists with the same name then it can't point to a different service
+ Long id = 7L;
+ when(_serviceDef.getId()).thenReturn(id);
+ RangerServiceDef existingServiceDef = mock(RangerServiceDef.class);
+ when(existingServiceDef.getId()).thenReturn(id);
+ when(_store.getServiceDef(id)).thenReturn(existingServiceDef);
+
+ String name = "aServiceDef";
+ when(_serviceDef.getName()).thenReturn(name);
+ RangerServiceDef anotherExistingServiceDef = mock(RangerServiceDef.class);
+ Long anotherId = 49L;
+ when(anotherExistingServiceDef.getId()).thenReturn(anotherId);
+ when(_store.getServiceDefByName(name)).thenReturn(anotherExistingServiceDef);
+
+ assertFalse(_validator.isValid(_serviceDef, Action.UPDATE, _failures));
+ _utils.checkFailureForSemanticError(_failures, "id/name");
+ }
+
+ final Object[][] accessTypes_bad_unknownType = new Object[][] {
+ { "read", null }, // ok, null implied grants
+ { "write", new String[] { } }, // ok, empty implied grants
+ { "admin", new String[] { "ReaD", "execute" } } // non-existent access type (execute), read is good (case should not matter)
+ };
+
+ final Object[][] accessTypes_bad_selfReference = new Object[][] {
+ { "read", null }, // ok, null implied grants
+ { "write", new String[] { } }, // ok, empty implied grants
+ { "admin", new String[] { "write", "admin" } } // non-existent access type (execute)
+ };
+
+ @Test
+ public final void test_isValidAccessTypes_happyPath() {
+ List<RangerAccessTypeDef> input = _utils.createAccessTypeDefs(accessTypes_good);
+ assertTrue(_validator.isValidAccessTypes(input, _failures));
+ assertTrue(_failures.isEmpty());
+ }
+
+ @Test
+ public final void test_isValidAccessTypes_failures() {
+ // sending in empty null access type defs is ok
+ assertTrue(_validator.isValidAccessTypes(null, _failures));
+ assertTrue(_failures.isEmpty());
+
+ List<RangerAccessTypeDef> input = new ArrayList<RangerAccessTypeDef>();
+ _failures.clear(); assertTrue(_validator.isValidAccessTypes(input, _failures));
+ assertTrue(_failures.isEmpty());
+
+ // null/empty access types
+ List<RangerAccessTypeDef> accessTypeDefs = _utils.createAccessTypeDefs(new String[] { null, "", " " });
+ _failures.clear(); assertFalse(_validator.isValidAccessTypes(accessTypeDefs, _failures));
+ _utils.checkFailureForMissingValue(_failures, "access type name");
+
+ // duplicate access types
+ accessTypeDefs = _utils.createAccessTypeDefs(new String[] { "read", "write", "execute", "read" } );
+ _failures.clear(); assertFalse(_validator.isValidAccessTypes(accessTypeDefs, _failures));
+ _utils.checkFailureForSemanticError(_failures, "access type name", "read");
+
+ // duplicate access types - case-insensitive
+ accessTypeDefs = _utils.createAccessTypeDefs(new String[] { "read", "write", "execute", "READ" } );
+ _failures.clear(); assertFalse(_validator.isValidAccessTypes(accessTypeDefs, _failures));
+ _utils.checkFailureForSemanticError(_failures, "access type name", "READ");
+
+ // unknown access type in implied grants list
+ accessTypeDefs = _utils.createAccessTypeDefs(accessTypes_bad_unknownType);
+ _failures.clear(); assertFalse(_validator.isValidAccessTypes(accessTypeDefs, _failures));
+ _utils.checkFailureForSemanticError(_failures, "implied grants", "execute");
+
+ // access type with implied grant referring to itself
+ accessTypeDefs = _utils.createAccessTypeDefs(accessTypes_bad_selfReference);
+ _failures.clear(); assertFalse(_validator.isValidAccessTypes(accessTypeDefs, _failures));
+ _utils.checkFailureForSemanticError(_failures, "implied grants", "admin");
+ }
+
+ final Map<String, String[]> enums_bad_enumName_null = ImmutableMap.of(
+ "authentication-type", new String[] { "simple", "kerberos" },
+ "time-unit", new String[] { "day", "hour", "minute" },
+ "null", new String[] { "foo", "bar", "tar" } // null enum-name -- "null" is a special value that leads to a null enum name
+ );
+
+ final Map<String, String[]> enums_bad_enumName_blank = ImmutableMap.of(
+ "authentication-type", new String[] { "simple", "kerberos" },
+ "time-unit", new String[] { "day", "hour", "minute" },
+ " ", new String[] { "foo", "bar", "tar" } // enum name is all spaces
+ );
+
+ final Map<String, String[]> enums_bad_Elements_empty = ImmutableMap.of(
+ "authentication-type", new String[] { "simple", "kerberos" },
+ "time-unit", new String[] { "day", "hour", "minute" },
+ "anEnum", new String[] { } // enum elements collection is empty
+ );
+
+ final Map<String, String[]> enums_bad_enumName_duplicate_exact = ImmutableMap.of(
+ "authentication-type", new String[] { "simple", "kerberos" },
+ "time-unit", new String[] { "day", "hour", "minute" }
+ );
+
+ final Map<String, String[]> enums_bad_enumName_duplicate_differentCase = ImmutableMap.of(
+ "authentication-type", new String[] { "simple", "kerberos" },
+ "time-unit", new String[] { "day", "hour", "minute" },
+ "Authentication-Type", new String[] { } // duplicate enum-name different in case
+ );
+
+ @Test
+ public final void test_isValidEnums_happyPath() {
+ List<RangerEnumDef> input = _utils.createEnumDefs(enums_good);
+ assertTrue(_validator.isValidEnums(input, _failures));
+ assertTrue(_failures.isEmpty());
+ }
+
+ @Test
+ public final void test_isValidEnums_failures() {
+ // null elements in enum def list are a failure
+ List<RangerEnumDef> input = _utils.createEnumDefs(enums_good);
+ input.add(null);
+ assertFalse(_validator.isValidEnums(input, _failures));
+ _utils.checkFailureForMissingValue(_failures, "enum def");
+
+ // enum names should be valid
+ input = _utils.createEnumDefs(enums_bad_enumName_null);
+ _failures.clear(); assertFalse(_validator.isValidEnums(input, _failures));
+ _utils.checkFailureForMissingValue(_failures, "enum def name");
+
+ input = _utils.createEnumDefs(enums_bad_enumName_blank);
+ _failures.clear(); assertFalse(_validator.isValidEnums(input, _failures));
+ _utils.checkFailureForMissingValue(_failures, "enum def name");
+
+ // enum elements collection should not be null or empty
+ input = _utils.createEnumDefs(enums_good);
+ RangerEnumDef anEnumDef = mock(RangerEnumDef.class);
+ when(anEnumDef.getName()).thenReturn("anEnum");
+ when(anEnumDef.getElements()).thenReturn(null);
+ input.add(anEnumDef);
+ _failures.clear(); assertFalse(_validator.isValidEnums(input, _failures));
+ _utils.checkFailureForMissingValue(_failures, "enum values", "anEnum");
+
+ input = _utils.createEnumDefs(enums_bad_Elements_empty);
+ _failures.clear(); assertFalse(_validator.isValidEnums(input, _failures));
+ _utils.checkFailureForMissingValue(_failures, "enum values", "anEnum");
+
+ // enum names should be distinct -- exact match
+ input = _utils.createEnumDefs(enums_good);
+ // add an element with same name as the first element
+ String name = input.iterator().next().getName();
+ when(anEnumDef.getName()).thenReturn(name);
+ List<RangerEnumElementDef> elementDefs = _utils.createEnumElementDefs(new String[] {"val1", "val2"});
+ when(anEnumDef.getElements()).thenReturn(elementDefs);
+ input.add(anEnumDef);
+ _failures.clear(); assertFalse(_validator.isValidEnums(input, _failures));
+ _utils.checkFailureForSemanticError(_failures, "enum def name", name);
+
+ // enum names should be distinct -- case insensitive
+ input = _utils.createEnumDefs(enums_bad_enumName_duplicate_differentCase);
+ _failures.clear(); assertFalse(_validator.isValidEnums(input, _failures));
+ _utils.checkFailureForSemanticError(_failures, "enum def name", "Authentication-Type");
+
+ // enum default index should be right
+ input = _utils.createEnumDefs(enums_good);
+ // set the index of 1st on to be less than 0
+ when(input.iterator().next().getDefaultIndex()).thenReturn(-1);
+ _failures.clear(); assertFalse(_validator.isValidEnums(input, _failures));
+ _utils.checkFailureForSemanticError(_failures, "enum default index", "authentication-type");
+ // set the index to be more than number of elements
+ when(input.iterator().next().getDefaultIndex()).thenReturn(2);
+ _failures.clear(); assertFalse(_validator.isValidEnums(input, _failures));
+ _utils.checkFailureForSemanticError(_failures, "enum default index", "authentication-type");
+ }
+
+ @Test
+ public final void test_isValidEnumElements_happyPath() {
+ List<RangerEnumElementDef> input = _utils.createEnumElementDefs(new String[] { "simple", "kerberos" });
+ assertTrue(_validator.isValidEnumElements(input, _failures, "anEnum"));
+ assertTrue(_failures.isEmpty());
+ }
+
+ @Test
+ public final void test_isValidEnumElements_failures() {
+ // enum element collection should not have nulls in it
+ List<RangerEnumElementDef> input = _utils.createEnumElementDefs(new String[] { "simple", "kerberos" });
+ input.add(null);
+ assertFalse(_validator.isValidEnumElements(input, _failures, "anEnum"));
+ _utils.checkFailureForMissingValue(_failures, "enum element", "anEnum");
+
+ // element names can't be null/empty
+ input = _utils.createEnumElementDefs(new String[] { "simple", "kerberos", null });
+ _failures.clear(); assertFalse(_validator.isValidEnumElements(input, _failures, "anEnum"));
+ _utils.checkFailureForMissingValue(_failures, "enum element name", "anEnum");
+
+ input = _utils.createEnumElementDefs(new String[] { "simple", "kerberos", " " }); // two tabs
+ _failures.clear(); assertFalse(_validator.isValidEnumElements(input, _failures, "anEnum"));
+ _utils.checkFailureForMissingValue(_failures, "enum element name", "anEnum");
+
+ // element names should be distinct - case insensitive
+ input = _utils.createEnumElementDefs(new String[] { "simple", "kerberos", "kerberos" }); // duplicate name - exact match
+ _failures.clear(); assertFalse(_validator.isValidEnumElements(input, _failures, "anEnum"));
+ _utils.checkFailureForSemanticError(_failures, "enum element name", "anEnum");
+
+ input = _utils.createEnumElementDefs(new String[] { "simple", "kerberos", "kErbErOs" }); // duplicate name - different case
+ _failures.clear(); assertFalse(_validator.isValidEnumElements(input, _failures, "anEnum"));
+ _utils.checkFailureForSemanticError(_failures, "enum element name", "anEnum");
+ }
+
+ private ValidationTestUtils _utils = new ValidationTestUtils();
+ RangerServiceDef _serviceDef;
+ List<ValidationFailureDetails> _failures;
+ ServiceStore _store;
+ RangerServiceDefValidator _validator;
+}
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/6e9f2a3b/security-admin/src/test/java/org/apache/ranger/rest/TestRangerValidator.java
----------------------------------------------------------------------
diff --git a/security-admin/src/test/java/org/apache/ranger/rest/TestRangerValidator.java b/security-admin/src/test/java/org/apache/ranger/rest/TestRangerValidator.java
index d3ee6d6..7da6672 100644
--- a/security-admin/src/test/java/org/apache/ranger/rest/TestRangerValidator.java
+++ b/security-admin/src/test/java/org/apache/ranger/rest/TestRangerValidator.java
@@ -26,26 +26,32 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.*;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.ranger.plugin.model.RangerPolicy;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
import org.apache.ranger.plugin.model.RangerService;
import org.apache.ranger.plugin.model.RangerServiceDef;
import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumDef;
import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
import org.apache.ranger.plugin.model.RangerServiceDef.RangerServiceConfigDef;
import org.apache.ranger.plugin.store.ServiceStore;
+import org.apache.ranger.plugin.util.SearchFilter;
import org.apache.ranger.rest.RangerValidator.Action;
import org.junit.Before;
import org.junit.Test;
+import com.google.common.collect.Maps;
+
public class TestRangerValidator {
static class RangerValidatorForTest extends RangerValidator {
@@ -238,13 +244,14 @@ public class TestRangerValidator {
assertTrue(accessTypes.isEmpty());
// access type defs with null empty blank names are skipped, spaces within names are preserved
- String[] names = new String[] { null, "", "a", " ", "b ", " ", " c" };
+ String[] names = new String[] { null, "", "a", " ", "b ", " ", " C", " D " };
accessTypeDefs.addAll(_utils.createAccessTypeDefs(names));
accessTypes = _validator.getAccessTypes(serviceDef);
- assertEquals(3, accessTypes.size());
+ assertEquals(4, accessTypes.size());
assertTrue(accessTypes.contains("a"));
assertTrue(accessTypes.contains("b "));
assertTrue(accessTypes.contains(" c"));
+ assertTrue(accessTypes.contains(" d "));
}
@Test
@@ -270,22 +277,24 @@ public class TestRangerValidator {
// access type defs with null empty blank names are skipped, spaces within names are preserved
Object[][] data = {
- { "a", true }, // all good
- null, // this should put a null element in the resource def!
- { "b", null }, // mandatory field is null, i.e. false
- { "c", false }, // mandatory field false
- { "d", true }, // all good
+ { "a", true }, // all good
+ null, // this should put a null element in the resource def!
+ { "b", null }, // mandatory field is null, i.e. false
+ { "c", false }, // non-mandatory field false - upper case
+ { "D", true }, // resource specified in upper case
+ { "E", false }, // all good
};
resourceDefs.addAll(_utils.createResourceDefs(data));
accessTypes = _validator.getMandatoryResourceNames(serviceDef);
assertEquals(2, accessTypes.size());
assertTrue(accessTypes.contains("a"));
- assertTrue(accessTypes.contains("d"));
+ assertTrue(accessTypes.contains("d")); // name should come back lower case
accessTypes = _validator.getAllResourceNames(serviceDef);
- assertEquals(4, accessTypes.size());
+ assertEquals(5, accessTypes.size());
assertTrue(accessTypes.contains("b"));
assertTrue(accessTypes.contains("c"));
+ assertTrue(accessTypes.contains("e"));
}
@Test
@@ -327,6 +336,137 @@ public class TestRangerValidator {
assertEquals("regex3", regExMap.get("f"));
}
+ @Test
+ public void test_getPolicyResources() {
+
+ Set<String> result;
+ RangerPolicy policy = null;
+ // null policy
+ result = _validator.getPolicyResources(null);
+ assertTrue(result != null);
+ assertTrue(result.isEmpty());
+ // null resource map
+ policy = mock(RangerPolicy.class);
+ when(policy.getResources()).thenReturn(null);
+ result = _validator.getPolicyResources(null);
+ assertTrue(result != null);
+ assertTrue(result.isEmpty());
+ // empty resource map
+ Map<String, RangerPolicyResource> input = Maps.newHashMap();
+ when(policy.getResources()).thenReturn(input);
+ result = _validator.getPolicyResources(policy);
+ assertTrue(result != null);
+ assertTrue(result.isEmpty());
+ // known resource map
+ input.put("r1", mock(RangerPolicyResource.class));
+ input.put("R2", mock(RangerPolicyResource.class));
+ result = _validator.getPolicyResources(policy);
+ assertEquals(2, result.size());
+ assertTrue("r1", result.contains("r1"));
+ assertTrue("R2", result.contains("r2")); // result should lowercase the resource-names
+ }
+
+ @Test
+ public void test_getIsAuditEnabled() {
+ // null policy
+ RangerPolicy policy = null;
+ boolean result = _validator.getIsAuditEnabled(policy);
+ assertFalse(result);
+ // null isAuditEnabled Boolean is supposed to be TRUE!!
+ policy = mock(RangerPolicy.class);
+ when(policy.getIsAuditEnabled()).thenReturn(null);
+ result = _validator.getIsAuditEnabled(policy);
+ assertTrue(result);
+ // non-null value
+ when(policy.getIsAuditEnabled()).thenReturn(Boolean.FALSE);
+ result = _validator.getIsAuditEnabled(policy);
+ assertFalse(result);
+
+ when(policy.getIsAuditEnabled()).thenReturn(Boolean.TRUE);
+ result = _validator.getIsAuditEnabled(policy);
+ assertTrue(result);
+ }
+
+ @Test
+ public void test_getPolicies() throws Exception {
+
+ // returns null when store returns null
+ String policyName = "aPolicy";
+ String serviceName = "aService";
+ SearchFilter filter = new SearchFilter();
+ filter.setParam(SearchFilter.POLICY_NAME, policyName);
+ filter.setParam(SearchFilter.SERVICE_NAME, serviceName);
+
+ when(_store.getPolicies(filter)).thenReturn(null);
+ List<RangerPolicy> result = _validator.getPolicies(policyName, serviceName);
+ // validate store is queried with both parameters
+ verify(_store).getPolicies(filter);
+ assertNull(result);
+
+ // returns null if store throws an exception
+ when(_store.getPolicies(filter)).thenThrow(new Exception());
+ result = _validator.getPolicies(policyName, serviceName);
+ assertNull(result);
+ }
+
+ @Test
+ public void test_getServiceDef_byId() throws Exception {
+ // if service store returns null or throws an exception then service is deemed invalid
+ when(_store.getServiceDef(1L)).thenReturn(null);
+ when(_store.getServiceDef(2L)).thenThrow(new Exception());
+ RangerServiceDef serviceDef = mock(RangerServiceDef.class);
+ when(_store.getServiceDef(3L)).thenReturn(serviceDef);
+
+ assertNull(_validator.getServiceDef(1L));
+ assertNull(_validator.getServiceDef(2L));
+ assertTrue(_validator.getServiceDef(3L) != null);
+ }
+
+ @Test
+ public void test_getEnumDefaultIndex() {
+ RangerEnumDef enumDef = mock(RangerEnumDef.class);
+ assertEquals(-1, _validator.getEnumDefaultIndex(null));
+ when(enumDef.getDefaultIndex()).thenReturn(null);
+ assertEquals(0, _validator.getEnumDefaultIndex(enumDef));
+ when(enumDef.getDefaultIndex()).thenReturn(-5);
+ assertEquals(-5, _validator.getEnumDefaultIndex(enumDef));
+ }
+
+ @Test
+ public void test_getImpliedGrants() {
+
+ // passing in null gets back a null
+ Collection<String> result = _validator.getImpliedGrants(null);
+ assertNull(result);
+
+ // null or empty implied grant collection gets back an empty collection
+ RangerAccessTypeDef accessTypeDef = mock(RangerAccessTypeDef.class);
+ when(accessTypeDef.getImpliedGrants()).thenReturn(null);
+ result = _validator.getImpliedGrants(accessTypeDef);
+ assertTrue(result.isEmpty());
+
+ List<String> impliedGrants = new ArrayList<String>();
+ when(accessTypeDef.getImpliedGrants()).thenReturn(impliedGrants);
+ result = _validator.getImpliedGrants(accessTypeDef);
+ assertTrue(result.isEmpty());
+
+ // null/empty values come back as is
+ impliedGrants = Arrays.asList(new String[] { null, "", " ", " " });
+ when(accessTypeDef.getImpliedGrants()).thenReturn(impliedGrants);
+ result = _validator.getImpliedGrants(accessTypeDef);
+ assertEquals(4, result.size());
+
+ // non-empty values get lower cased
+ impliedGrants = Arrays.asList(new String[] { "a", "B", "C ", " d " });
+ when(accessTypeDef.getImpliedGrants()).thenReturn(impliedGrants);
+ result = _validator.getImpliedGrants(accessTypeDef);
+ assertEquals(4, result.size());
+ assertTrue(result.contains("a"));
+ assertTrue(result.contains("b"));
+ assertTrue(result.contains("c "));
+ assertTrue(result.contains(" d "));
+ }
+
private RangerValidatorForTest _validator;
private ServiceStore _store;
private ValidationTestUtils _utils = new ValidationTestUtils();
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/6e9f2a3b/security-admin/src/test/java/org/apache/ranger/rest/TestServiceRESTForValidation.java
----------------------------------------------------------------------
diff --git a/security-admin/src/test/java/org/apache/ranger/rest/TestServiceRESTForValidation.java b/security-admin/src/test/java/org/apache/ranger/rest/TestServiceRESTForValidation.java
index da15ffa..d112b83 100644
--- a/security-admin/src/test/java/org/apache/ranger/rest/TestServiceRESTForValidation.java
+++ b/security-admin/src/test/java/org/apache/ranger/rest/TestServiceRESTForValidation.java
@@ -37,6 +37,7 @@ import org.apache.ranger.biz.ServiceDBStore;
import org.apache.ranger.common.RESTErrorUtil;
import org.apache.ranger.plugin.model.RangerPolicy;
import org.apache.ranger.plugin.model.RangerService;
+import org.apache.ranger.plugin.model.RangerServiceDef;
import org.apache.ranger.rest.RangerValidator.Action;
import org.junit.Before;
import org.junit.Test;
@@ -51,6 +52,7 @@ public class TestServiceRESTForValidation {
// inject out store in it
_store = mock(ServiceDBStore.class);
_serviceRest.svcStore = _store;
+
// and our validator factory
_factory = mock(RangerValidatorFactory.class);
_serviceValidator = mock(RangerServiceValidator.class);
@@ -58,6 +60,9 @@ public class TestServiceRESTForValidation {
_policyValidator = mock(RangerPolicyValidator.class);
when(_factory.getPolicyValidator(_store)).thenReturn(_policyValidator);
_serviceRest.validatorFactory = _factory;
+ _serviceDefValidator = mock(RangerServiceDefValidator.class);
+ when(_factory.getServiceDefValidator(_store)).thenReturn(_serviceDefValidator);
+
// and other things that are needed for service rest to work correctly
_restErrorUtil = mock(RESTErrorUtil.class);
WebApplicationException webApplicationException = new WebApplicationException();
@@ -85,7 +90,7 @@ public class TestServiceRESTForValidation {
//
_serviceRest.updateService(_service);
verify(_serviceValidator).validate(_service, Action.UPDATE);
-
+
_serviceRest.deleteService(3L);
verify(_serviceValidator).validate(3L, Action.DELETE);
} catch (Throwable t) {
@@ -93,7 +98,7 @@ public class TestServiceRESTForValidation {
fail("Unexpected exception thrown!");
}
}
-
+
@Test
public final void testService_storeFailure() throws Exception {
/*
@@ -283,14 +288,120 @@ public class TestServiceRESTForValidation {
fail("Unexpected exception!");
}
}
+
+ @Test
+ public final void testServiceDef_happyPath() throws Exception {
+ /*
+ * Creation should succeed if neither validator nor dbstore throw exception.
+ * - by default mocks return null for unspecified methods, so no additional mocking needed.
+ * - We just assert that validator is called with right set of arguments.
+ * - db store would also have been excercised but that is not the focus of this test, so we don't assert about it!!
+ */
+ try {
+ _serviceRest.createServiceDef(_serviceDef);
+ verify(_serviceDefValidator).validate(_serviceDef, Action.CREATE);
+ //
+ _serviceRest.updateServiceDef(_serviceDef);
+ verify(_serviceDefValidator).validate(_serviceDef, Action.UPDATE);
+
+ _serviceRest.deleteServiceDef(3L);
+ verify(_serviceDefValidator).validate(3L, Action.DELETE);
+ } catch (Throwable t) {
+ t.printStackTrace();
+ fail("Unexpected exception thrown!");
+ }
+ }
- RangerValidatorFactory _factory;
- RangerServiceValidator _serviceValidator;
- RangerPolicyValidator _policyValidator;
- ServiceDBStore _store;
- ServiceREST _serviceRest;
- RangerService _service;
- RangerPolicy _policy;
- Exception _exception;
- RESTErrorUtil _restErrorUtil;
+ @Test
+ public void testServiveDef_validatorFailure() throws Exception {
+
+ doThrow(_exception).when(_serviceDefValidator).validate(_serviceDef, Action.CREATE);
+ try {
+ _serviceRest.createServiceDef(_serviceDef);
+ fail("Should have thrown exception!");
+ } catch (WebApplicationException t) {
+ verify(_serviceDefValidator).validate(_serviceDef, Action.CREATE);
+ verify(_store, never()).createServiceDef(_serviceDef);
+ } catch (Throwable t) {
+ LOG.debug(t);
+ fail("Unexpected exception!");
+ }
+
+ doThrow(_exception).when(_serviceDefValidator).validate(_serviceDef, Action.UPDATE);
+ try {
+ _serviceRest.updateServiceDef(_serviceDef);
+ fail("Should have thrown exception!");
+ } catch (WebApplicationException t) {
+ verify(_serviceDefValidator).validate(_serviceDef, Action.UPDATE);
+ verify(_store, never()).updateServiceDef(_serviceDef);
+ } catch (Throwable t) {
+ LOG.debug(t);
+ fail("Unexpected exception!");
+ }
+
+ doThrow(_exception).when(_serviceDefValidator).validate(4L, Action.DELETE);
+ try {
+ _serviceRest.deleteServiceDef(4L);
+ fail("Should have thrown exception!");
+ } catch (WebApplicationException t) {
+ verify(_serviceDefValidator).validate(4L, Action.DELETE);
+ verify(_store, never()).deleteServiceDef(4L);
+ } catch (Throwable t) {
+ LOG.debug(t);
+ fail("Unexpected exception!");
+ }
+ }
+
+ @Test
+ public void testServiceDef_storeFailure() throws Exception {
+ doThrow(_exception).when(_store).createServiceDef(_serviceDef);
+ try {
+ _serviceRest.createServiceDef(_serviceDef);
+ fail("Should have thrown exception!");
+ } catch (WebApplicationException e) {
+ verify(_serviceDefValidator).validate(_serviceDef, Action.CREATE);
+ verify(_store).createServiceDef(_serviceDef);
+ } catch (Throwable t) {
+ LOG.debug(t);
+ fail("Unexpected exception!");
+ }
+
+ doThrow(_exception).when(_store).updateServiceDef(_serviceDef);
+ try {
+ _serviceRest.updateServiceDef(_serviceDef);
+ fail("Should have thrown exception!");
+ } catch (WebApplicationException e) {
+ verify(_serviceDefValidator).validate(_serviceDef, Action.UPDATE);
+ verify(_store).updateServiceDef(_serviceDef);
+ } catch (Throwable t) {
+ LOG.debug(t);
+ fail("Unexpected exception!");
+ }
+
+ doThrow(_exception).when(_store).deleteServiceDef(5L);
+ try {
+ _serviceRest.deleteServiceDef(5L);
+ fail("Should have thrown exception!");
+ } catch (WebApplicationException e) {
+ verify(_serviceDefValidator).validate(5L, Action.DELETE);
+ verify(_store).deleteServiceDef(5L);
+ } catch (Throwable t) {
+ LOG.debug(t);
+ fail("Unexpected exception!");
+ }
+ }
+
+ private RangerValidatorFactory _factory;
+ private RangerServiceValidator _serviceValidator;
+ private RangerPolicyValidator _policyValidator;
+ private RangerServiceDefValidator _serviceDefValidator;
+
+ private ServiceDBStore _store;
+ private ServiceREST _serviceRest;
+ private Exception _exception;
+ private RESTErrorUtil _restErrorUtil;
+
+ private RangerService _service;
+ private RangerPolicy _policy;
+ private RangerServiceDef _serviceDef;
}
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/6e9f2a3b/security-admin/src/test/java/org/apache/ranger/rest/ValidationTestUtils.java
----------------------------------------------------------------------
diff --git a/security-admin/src/test/java/org/apache/ranger/rest/ValidationTestUtils.java b/security-admin/src/test/java/org/apache/ranger/rest/ValidationTestUtils.java
index b734763..6c71502 100644
--- a/security-admin/src/test/java/org/apache/ranger/rest/ValidationTestUtils.java
+++ b/security-admin/src/test/java/org/apache/ranger/rest/ValidationTestUtils.java
@@ -37,6 +37,8 @@ import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemAccess;
import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
import org.apache.ranger.plugin.model.RangerServiceDef;
import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumElementDef;
import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
import org.apache.ranger.plugin.model.RangerServiceDef.RangerServiceConfigDef;
@@ -119,6 +121,30 @@ public class ValidationTestUtils {
return defs;
}
+
+ List<RangerAccessTypeDef> createAccessTypeDefs(Object[][] data) {
+ if (data == null) {
+ return null;
+ }
+ List<RangerAccessTypeDef> result = new ArrayList<RangerAccessTypeDef>();
+ if (data.length == 0) {
+ return result;
+ }
+ for (Object[] entry : data) {
+ String accessType = (String)entry[0];
+ String[] impliedAccessArray = (String[])entry[1];
+ List<String> impliedAccesses = null;
+ if (impliedAccessArray != null) {
+ impliedAccesses = Arrays.asList(impliedAccessArray);
+ }
+ RangerAccessTypeDef aTypeDef = mock(RangerAccessTypeDef.class);
+ when(aTypeDef.getName()).thenReturn(accessType);
+ when(aTypeDef.getImpliedGrants()).thenReturn(impliedAccesses);
+ result.add(aTypeDef);
+ }
+ return result;
+ }
+
RangerServiceDef createServiceDefWithAccessTypes(String[] accesses) {
RangerServiceDef serviceDef = mock(RangerServiceDef.class);
List<RangerAccessTypeDef> accessTypeDefs = new ArrayList<RangerServiceDef.RangerAccessTypeDef>();
@@ -249,4 +275,38 @@ public class ValidationTestUtils {
}
return resourceMap;
}
+
+ List<RangerEnumElementDef> createEnumElementDefs(String[] input) {
+ if (input == null) {
+ return null;
+ }
+ List<RangerEnumElementDef> output = new ArrayList<RangerEnumElementDef>();
+ for (String elementName : input) {
+ RangerEnumElementDef aDef = mock(RangerEnumElementDef.class);
+ when(aDef.getName()).thenReturn(elementName);
+ output.add(aDef);
+ }
+ return output;
+ }
+
+ List<RangerEnumDef> createEnumDefs(Map<String, String[]> input) {
+ if (input == null) {
+ return null;
+ }
+ List<RangerEnumDef> defs = new ArrayList<RangerEnumDef>();
+ for (Map.Entry<String, String[]> entry : input.entrySet()) {
+ RangerEnumDef enumDef = mock(RangerEnumDef.class);
+ String enumName = entry.getKey();
+ if ("null".equals(enumName)) { // special handling to process null hint in enum-name
+ enumName = null;
+ }
+ when(enumDef.getName()).thenReturn(enumName);
+ List<RangerEnumElementDef> elements = createEnumElementDefs(entry.getValue());
+ when(enumDef.getElements()).thenReturn(elements);
+ // by default set default index to last element
+ when(enumDef.getDefaultIndex()).thenReturn(elements.size() - 1);
+ defs.add(enumDef);
+ }
+ return defs;
+ }
}