Repository: incubator-ranger Updated Branches: refs/heads/master 054a973df -> d69fc28d2
RANGER-278 Add validation for service create/update/delete operations Signed-off-by: Madhan Neethiraj <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/incubator-ranger/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ranger/commit/d69fc28d Tree: http://git-wip-us.apache.org/repos/asf/incubator-ranger/tree/d69fc28d Diff: http://git-wip-us.apache.org/repos/asf/incubator-ranger/diff/d69fc28d Branch: refs/heads/master Commit: d69fc28d2fbd5efe3741819cc8010e56ed5b9fa8 Parents: 054a973 Author: Alok Lal <[email protected]> Authored: Tue Feb 24 13:22:15 2015 -0800 Committer: Madhan Neethiraj <[email protected]> Committed: Tue Mar 3 14:40:23 2015 -0800 ---------------------------------------------------------------------- pom.xml | 30 +-- ranger-util/pom.xml | 1 - security-admin/pom.xml | 1 - .../org/apache/ranger/biz/ServiceDBStore.java | 19 ++ .../ranger/rest/RangerServiceValidator.java | 188 +++++++++++++ .../org/apache/ranger/rest/RangerValidator.java | 162 ++++++++++++ .../ranger/rest/RangerValidatorFactory.java | 29 ++ .../org/apache/ranger/rest/ServiceREST.java | 12 + .../ranger/rest/ValidationFailureDetails.java | 91 +++++++ .../rest/ValidationFailureDetailsBuilder.java | 64 +++++ .../ranger/rest/TestRangerServiceValidator.java | 262 +++++++++++++++++++ .../rest/TestServiceRESTForValidation.java | 129 +++++++++ .../ranger/rest/TestServiceValidator.java | 202 ++++++++++++++ .../apache/ranger/rest/ValidationTestUtils.java | 57 ++++ .../process/LdapUserGroupBuilder.java | 1 - 15 files changed, 1217 insertions(+), 31 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d69fc28d/pom.xml ---------------------------------------------------------------------- diff --git a/pom.xml b/pom.xml index b2a955d..93cba79 100644 --- a/pom.xml +++ b/pom.xml @@ -166,6 +166,7 @@ <velocity.version>1.7</velocity.version> <powermock.version>1.5.6</powermock.version> <aspectj.version>1.8.2</aspectj.version> + <findbugs.plugin.version>3.0.0</findbugs.plugin.version> <distMgmtStagingId>apache.staging.https</distMgmtStagingId> <distMgmtStagingName>Apache Release Distribution Repository</distMgmtStagingName> <distMgmtStagingUrl>https://repository.apache.org/service/local/staging/deploy/maven2</distMgmtStagingUrl> @@ -389,34 +390,6 @@ <artifactId>maven-release-plugin</artifactId> <version>2.5</version> </plugin> - <!--This plugin's configuration is used to store Eclipse - m2e settings only. It has no influence on the Maven build itself. - --> - <plugin> - <groupId>org.eclipse.m2e</groupId> - <artifactId>lifecycle-mapping</artifactId> - <version>1.0.0</version> - <configuration> - <lifecycleMappingMetadata> - <pluginExecutions> - <pluginExecution> - <pluginExecutionFilter> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-antrun-plugin</artifactId> - <versionRange>[1.0,)</versionRange> - <goals> - <goal>run</goal> - </goals> - </pluginExecutionFilter> - <action> - <execute /> - </action> - </pluginExecution> - </pluginExecutions> - </lifecycleMappingMetadata> - </configuration> - </plugin> - </plugins> </pluginManagement> @@ -496,6 +469,7 @@ <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>findbugs-maven-plugin</artifactId> + <version>${findbugs.plugin.version}</version> <!-- <configuration> <excludeFilterFile>${basedir}/dev-support/findbugsExcludeFile.xml http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d69fc28d/ranger-util/pom.xml ---------------------------------------------------------------------- diff --git a/ranger-util/pom.xml b/ranger-util/pom.xml index 047008a..fabbf2c 100644 --- a/ranger-util/pom.xml +++ b/ranger-util/pom.xml @@ -26,7 +26,6 @@ <version>0.4.0</version> </parent> <artifactId>ranger-util</artifactId> - <version>0.4.0</version> <name>ranger-util</name> <description>Common Utilities of Ranger</description> <dependencies> http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d69fc28d/security-admin/pom.xml ---------------------------------------------------------------------- diff --git a/security-admin/pom.xml b/security-admin/pom.xml index 6d313b6..ce754ab 100644 --- a/security-admin/pom.xml +++ b/security-admin/pom.xml @@ -18,7 +18,6 @@ <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <artifactId>security-admin-web</artifactId> - <version>0.4.0</version> <name>Security Admin Web Application</name> <description>security-admin-tool java web application</description> <packaging>war</packaging> http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d69fc28d/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java ---------------------------------------------------------------------- diff --git a/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java b/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java index 0cb1707..9c59933 100644 --- a/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java +++ b/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java @@ -1,3 +1,22 @@ +/* + * 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.biz; import java.util.ArrayList; http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d69fc28d/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 new file mode 100644 index 0000000..08184c7 --- /dev/null +++ b/security-admin/src/main/java/org/apache/ranger/rest/RangerServiceValidator.java @@ -0,0 +1,188 @@ +/* + * 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.rest; + +import java.util.Set; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.ranger.plugin.model.RangerService; +import org.apache.ranger.plugin.model.RangerServiceDef; +import org.apache.ranger.plugin.store.ServiceStore; + +import com.google.common.collect.Sets; + +public class RangerServiceValidator extends RangerValidator { + + private static final Log LOG = LogFactory.getLog(RangerServiceValidator.class); + + public RangerServiceValidator(ServiceStore store, Action action) { + super(store, action); + } + + public void validate(RangerService service) throws Exception { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerValidator.validate(" + service + ")"); + } + + if (isValid(service)) { + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerValidator.validate(" + service + "): valid"); + } + } else { + String message = getFailureMessage(); + LOG.debug("<== RangerValidator.validate(" + service + "): invalid, reason[" + message + "]"); + throw new Exception(message); + } + } + + public void validate(long id) throws Exception { + if (isValid(id)) { + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerValidator.validate(" + id + "): valid"); + } + } else { + String message = getFailureMessage(); + LOG.debug("<== RangerValidator.validate(" + id + "): invalid, reason[" + message + "]"); + throw new Exception(message); + } + } + + boolean isValid(Long id) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerServiceValidator.isValid(" + id + ")"); + } + + if (_action != Action.DELETE) { + addFailure(new ValidationFailureDetailsBuilder() + .isAnInternalError() + .becauseOf("isValid(Long) is only supported for DELETE") + .build()); + } else if (id == null) { + addFailure(new ValidationFailureDetailsBuilder() + .field("id") + .isMissing() + .build()); + } else { + boolean found = false; + try { + if (_store.getService(id) != null) { + found = true; + } + } catch (Exception e) { + LOG.debug("Encountred exception while retrieving service from service store!", e); + } + if (!found) { + addFailure(new ValidationFailureDetailsBuilder() + .field("id") + .isSemanticallyIncorrect() + .becauseOf("no service found for id[" + id + "]") + .build()); + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerServiceValidator.isValid(" + id + "): " + _valid); + } + return _valid; + } + + boolean isValid(RangerService service) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerServiceValidator.isValid(" + service + ")"); + } + + if (service == null) { + String message = "service object passed in was null"; + LOG.debug(message); + addFailure(new ValidationFailureDetailsBuilder() + .field("service") + .isMissing() + .becauseOf(message) + .build()); + } else { + String name = service.getName(); + String type = service.getType(); + boolean nameSpecified = StringUtils.isNotBlank(name); + boolean typeSpecified = StringUtils.isNotBlank(type); + RangerService existingService = null; + RangerServiceDef serviceDef = null; + if (!nameSpecified) { + String message = "service name was null/empty/blank"; + LOG.debug(message); + addFailure(new ValidationFailureDetailsBuilder() + .field("name") + .isMissing() + .becauseOf(message) + .build()); + } else { + existingService = getService(name); + if (existingService != null && _action == Action.CREATE) { + addFailure(new ValidationFailureDetailsBuilder() + .field("name") + .isSemanticallyIncorrect() + .becauseOf("service with the same name already exists") + .build()); + } else if (existingService == null && _action == Action.UPDATE) { + addFailure(new ValidationFailureDetailsBuilder() + .field("name") + .isSemanticallyIncorrect() + .becauseOf("service with the same name doesn't exist") + .build()); + } + } + if (!typeSpecified) { + addFailure(new ValidationFailureDetailsBuilder() + .field("type") + .isMissing() + .becauseOf("service def was null/empty/blank") + .build()); + } else { + serviceDef = getServiceDef(type); + if (serviceDef == null) { + addFailure(new ValidationFailureDetailsBuilder() + .field("type") + .isSemanticallyIncorrect() + .becauseOf("service def not found") + .build()); + } + } + if (nameSpecified && serviceDef != null) { + Set<String> reqiredParameters = getRequiredParameters(serviceDef); + Set<String> inputParameters = getServiceConfigParameters(service); + Set<String> missingParameters = Sets.difference(reqiredParameters, inputParameters); + if (!missingParameters.isEmpty()) { + addFailure(new ValidationFailureDetailsBuilder() + .field("configuration") + .subField(missingParameters.iterator().next()) // we return any one parameter! + .isMissing() + .becauseOf("required configuration parameter is missing") + .build()); + } + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerServiceValidator.isValid(" + service + "): " + _valid); + } + return _valid; + } +} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d69fc28d/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 new file mode 100644 index 0000000..3f25266 --- /dev/null +++ b/security-admin/src/main/java/org/apache/ranger/rest/RangerValidator.java @@ -0,0 +1,162 @@ +/* + * 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.rest; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.ranger.plugin.model.RangerService; +import org.apache.ranger.plugin.model.RangerServiceDef; +import org.apache.ranger.plugin.model.RangerServiceDef.RangerServiceConfigDef; +import org.apache.ranger.plugin.store.ServiceStore; + +public abstract class RangerValidator { + + private static final Log LOG = LogFactory.getLog(RangerValidator.class); + + ServiceStore _store; + boolean _valid = true; + List<ValidationFailureDetails> _failures; + Action _action; + + public enum Action { + CREATE, UPDATE, DELETE; + }; + + protected RangerValidator(ServiceStore store, Action action) { + if (store == null) { + throw new IllegalArgumentException("ServiceValidator(): store is null!"); + } + _store = store; + if (action == null) { + throw new IllegalArgumentException("ServiceValidator(): action is null!"); + } + _action = action; + } + + protected List<ValidationFailureDetails> getFailures() { + if (_valid) { + LOG.warn("getFailureDetails: called while _valid == true"); + } + return _failures; + } + + String getFailureMessage() { + if (_valid) { + LOG.warn("getFailureDetails: called while validator is true!"); + } + if (_failures == null) { + LOG.warn("getFailureDetails: called while list of failures is null!"); + return null; + } + StringBuilder builder = new StringBuilder(); + for (ValidationFailureDetails aFailure : _failures) { + builder.append(aFailure.toString()); + builder.append(";"); + } + return builder.toString(); + } + + void addFailure(ValidationFailureDetails aFailure) { + if (_failures == null) { + _failures = new ArrayList<ValidationFailureDetails>(); + } + _failures.add(aFailure); + _valid = false; + } + + Set<String> getServiceConfigParameters(RangerService service) { + if (service == null || service.getConfigs() == null) { + return new HashSet<String>(); + } else { + return service.getConfigs().keySet(); + } + } + + Set<String> getRequiredParameters(RangerServiceDef serviceDef) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerServiceValidator.getRequiredParameters(" + serviceDef + ")"); + } + + Set<String> result; + if (serviceDef == null) { + result = Collections.emptySet(); + } else { + List<RangerServiceConfigDef> configs = serviceDef.getConfigs(); + if (CollectionUtils.isEmpty(configs)) { + result = Collections.emptySet(); + } else { + result = new HashSet<String>(configs.size()); // at worse all of the config items are required! + for (RangerServiceConfigDef configDef : configs) { + if (configDef.getMandatory()) { + result.add(configDef.getName()); + } + } + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerServiceValidator.getRequiredParameters(" + serviceDef + "): " + result); + } + return result; + } + + RangerServiceDef getServiceDef(String type) { + + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerServiceValidator.getServiceDef(" + type + ")"); + } + RangerServiceDef result = null; + try { + result = _store.getServiceDefByName(type); + } catch (Exception e) { + LOG.debug("Encountred exception while retrieving service definition from service store!", e); + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerServiceValidator.getServiceDef(" + type + "): " + result); + } + return result; + } + + RangerService getService(String name) { + + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerServiceValidator.getService(" + name + ")"); + } + RangerService result = null; + try { + result = _store.getServiceByName(name); + } catch (Exception e) { + LOG.debug("Encountred exception while retrieving service from service store!", e); + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerServiceValidator.getService(" + name + "): " + result); + } + return result; + } +} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d69fc28d/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 new file mode 100644 index 0000000..6c75a2f --- /dev/null +++ b/security-admin/src/main/java/org/apache/ranger/rest/RangerValidatorFactory.java @@ -0,0 +1,29 @@ +/* + * 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.rest; + +import org.apache.ranger.plugin.store.ServiceStore; +import org.apache.ranger.rest.RangerValidator.Action; + +public class RangerValidatorFactory { + RangerServiceValidator getServiceValidator(ServiceStore store, Action action) { + return new RangerServiceValidator(store, action); + } +} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d69fc28d/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 b90a3df..ab09bf6 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 @@ -59,6 +59,7 @@ import org.apache.ranger.plugin.service.ResourceLookupContext; import org.apache.ranger.plugin.util.GrantRevokeRequest; import org.apache.ranger.plugin.util.SearchFilter; import org.apache.ranger.plugin.util.ServicePolicies; +import org.apache.ranger.rest.RangerValidator.Action; import org.apache.ranger.view.VXResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; @@ -92,6 +93,10 @@ public class ServiceREST { @Autowired ServiceDBStore svcStore; + + // this indirection for validation via a factory exists only for testability + // TODO move the instantiation to DI framework? + RangerValidatorFactory validatorFactory = new RangerValidatorFactory(); public ServiceREST() { } @@ -269,6 +274,9 @@ public class ServiceREST { RangerService ret = null; try { + RangerServiceValidator validator = validatorFactory.getServiceValidator(svcStore, Action.CREATE); + validator.validate(service); + ret = svcStore.createService(service); } catch(Exception excp) { LOG.error("createService(" + service + ") failed", excp); @@ -295,6 +303,8 @@ public class ServiceREST { RangerService ret = null; try { + RangerServiceValidator validator = validatorFactory.getServiceValidator(svcStore, Action.UPDATE); + validator.validate(service); ret = svcStore.updateService(service); } catch(Exception excp) { LOG.error("updateService(" + service + ") failed", excp); @@ -319,6 +329,8 @@ public class ServiceREST { } try { + RangerServiceValidator validator = validatorFactory.getServiceValidator(svcStore, Action.DELETE); + validator.validate(id); svcStore.deleteService(id); } catch(Exception excp) { LOG.error("deleteService(" + id + ") failed", excp); http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d69fc28d/security-admin/src/main/java/org/apache/ranger/rest/ValidationFailureDetails.java ---------------------------------------------------------------------- diff --git a/security-admin/src/main/java/org/apache/ranger/rest/ValidationFailureDetails.java b/security-admin/src/main/java/org/apache/ranger/rest/ValidationFailureDetails.java new file mode 100644 index 0000000..8ceeba1 --- /dev/null +++ b/security-admin/src/main/java/org/apache/ranger/rest/ValidationFailureDetails.java @@ -0,0 +1,91 @@ +/* + * 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.rest; + +import java.util.Objects; + +public class ValidationFailureDetails { + + final String _fieldName; + final String _subFieldName; + final boolean _missing; + final boolean _semanticError; + final boolean _internalError; + final String _reason; + + public ValidationFailureDetails(String fieldName, String subFieldName, boolean missing, boolean semanticError, boolean internalError, String reason) { + _missing = missing; + _semanticError = semanticError; + _internalError = internalError; + _fieldName = fieldName; + _subFieldName = subFieldName; + _reason = reason; + } + + public String getFieldName() { + return _fieldName; + } + + public boolean isMissingRequiredValue() { + return _missing; + } + + public boolean isSemanticallyIncorrect() { + return _semanticError; + } + + String getType() { + if (_missing) return "missing"; + if (_semanticError) return "semantically incorrect"; + if (_internalError) return "internal error"; + return ""; + } + + public String getSubFieldName() { + return _subFieldName; + } + + @Override + public String toString() { + return String.format("Field[%s]%s is %s: reason[%s]", + _fieldName, + _subFieldName == null ? "" : ", subField[" + _subFieldName + "]", + getType(), _reason); + } + + @Override + public int hashCode() { + return Objects.hash(_fieldName, _subFieldName, _missing, _semanticError, _internalError, _reason); + } + + @Override + public boolean equals(Object obj) { + if (obj == null || !(obj instanceof ValidationFailureDetails)) { + return false; + } + ValidationFailureDetails that = (ValidationFailureDetails)obj; + return Objects.equals(_fieldName, that._fieldName) && + Objects.equals(_subFieldName, that._subFieldName) && + Objects.equals(_reason, that._reason) && + _internalError == that._internalError && + _missing == that._missing && + _semanticError == that._semanticError; + } +} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d69fc28d/security-admin/src/main/java/org/apache/ranger/rest/ValidationFailureDetailsBuilder.java ---------------------------------------------------------------------- diff --git a/security-admin/src/main/java/org/apache/ranger/rest/ValidationFailureDetailsBuilder.java b/security-admin/src/main/java/org/apache/ranger/rest/ValidationFailureDetailsBuilder.java new file mode 100644 index 0000000..b85215d --- /dev/null +++ b/security-admin/src/main/java/org/apache/ranger/rest/ValidationFailureDetailsBuilder.java @@ -0,0 +1,64 @@ +/* + * 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.rest; + +public class ValidationFailureDetailsBuilder { + private String _fieldName; + private boolean _missing; + private boolean _semanticError; + private String _reason; + private String _subFieldName; + private boolean _internalError; + + ValidationFailureDetailsBuilder becauseOf(String aReason) { + _reason = aReason; + return this; + } + + ValidationFailureDetailsBuilder isMissing() { + _missing = true; + return this; + } + + ValidationFailureDetailsBuilder isSemanticallyIncorrect() { + _semanticError = true; + return this; + } + + ValidationFailureDetailsBuilder field(String fieldName) { + _fieldName = fieldName; + return this; + } + + ValidationFailureDetails build() { + return new ValidationFailureDetails(_fieldName, _subFieldName, _missing, _semanticError, _internalError, _reason); + } + + ValidationFailureDetailsBuilder subField(String missingParameter) { + _subFieldName = missingParameter; + return this; + } + + ValidationFailureDetailsBuilder isAnInternalError() { + _internalError = true; + return this; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d69fc28d/security-admin/src/test/java/org/apache/ranger/rest/TestRangerServiceValidator.java ---------------------------------------------------------------------- diff --git a/security-admin/src/test/java/org/apache/ranger/rest/TestRangerServiceValidator.java b/security-admin/src/test/java/org/apache/ranger/rest/TestRangerServiceValidator.java new file mode 100644 index 0000000..3bbb123 --- /dev/null +++ b/security-admin/src/test/java/org/apache/ranger/rest/TestRangerServiceValidator.java @@ -0,0 +1,262 @@ +/* + * 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.rest; + +import static org.junit.Assert.assertFalse; +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 java.util.List; +import java.util.Map; + +import org.apache.ranger.plugin.model.RangerService; +import org.apache.ranger.plugin.model.RangerServiceDef; +import org.apache.ranger.plugin.model.RangerServiceDef.RangerServiceConfigDef; +import org.apache.ranger.plugin.store.ServiceStore; +import org.apache.ranger.rest.RangerValidator.Action; +import org.junit.Before; +import org.junit.Test; + +public class TestRangerServiceValidator { + + final Action[] cud = new Action[] { Action.CREATE, Action.UPDATE, Action.DELETE }; + final Action[] cu = new Action[] { Action.CREATE, Action.UPDATE }; + final Action[] ud = new Action[] { Action.UPDATE, Action.DELETE }; + + @Before + public void before() { + _store = mock(ServiceStore.class); + _action = Action.CREATE; // by default we set action to create + _validator = new RangerServiceValidator(_store, _action); + } + + @Test + public void testIsValid_failures() throws Exception { + RangerService service = mock(RangerService.class); + List<ValidationFailureDetails> failures; + // create/update/delete: null, empty of blank name renders a service invalid + for (Action action : cud) { + _validator = new RangerServiceValidator(_store, action); + when(service.getName()).thenReturn(null); + assertFalse(_validator.isValid(service)); + // let's verify the sort of error information that is returned (for one of these) + failures = _validator.getFailures(); + // assert that among the failure reason is one about field name being missing. + boolean found = false; + for (ValidationFailureDetails f : failures) { + if ("name".equals(f.getFieldName()) && + f._internalError == false && + f._missing == true && + f._semanticError == false) { + found = true; + } + } + assertTrue("Matching failure located", found); + // let's assert behavior for other flavors of this condition, too. + when(service.getName()).thenReturn(""); + assertFalse(_validator.isValid(service)); + when(service.getName()).thenReturn(" "); // spaces + assertFalse(_validator.isValid(service)); + } + + // Create/update: null, empty or blank type is also invalid + for (Action action : cu) { + _validator = new RangerServiceValidator(_store, action); + when(service.getName()).thenReturn("aName"); + when(service.getType()).thenReturn(null); + assertFalse(_validator.isValid(service)); + when(service.getType()).thenReturn(""); + assertFalse(_validator.isValid(service)); + when(service.getType()).thenReturn(" "); // a tab + assertFalse(_validator.isValid(service)); + // let's verify the error information returned (for the last scenario) + failures = _validator.getFailures(); + boolean found = false; + for (ValidationFailureDetails f : failures) { + if ("type".equals(f._fieldName) && + f._missing == true && + f._semanticError == false) { + found = true; + } + } + assertTrue("Matching failure located", found); + } + + // Create/update: if non-empty, the type should also exist! + for (Action action : cu) { + _validator = new RangerServiceValidator(_store, action); + when(service.getName()).thenReturn("aName"); + when(service.getType()).thenReturn("aType"); + when(_store.getServiceDefByName("aType")).thenReturn(null); + assertFalse(_validator.isValid(service)); + // let's verify the error information returned (for the last scenario) + failures = _validator.getFailures(); + boolean found = false; + for (ValidationFailureDetails f : failures) { + if ("type".equals(f._fieldName) && + f._missing == false && + f._semanticError == true) { + found = true; + } + } + assertTrue("Matching failure located", found); + } + + // Create: if service already exists then that such a service should be considered invalid by create + when(service.getName()).thenReturn("aName"); + when(service.getType()).thenReturn("aType"); + RangerServiceDef serviceDef = mock(RangerServiceDef.class); + when(_store.getServiceDefByName("aType")).thenReturn(serviceDef); + // test both when service exists and when it doesn't -- the result is opposite for the two cases + RangerService existingService = mock(RangerService.class); + when(_store.getServiceByName("aName")).thenReturn(existingService); + + _validator = new RangerServiceValidator(_store, Action.CREATE); + assertFalse(_validator.isValid(service)); + + // check the error returned: it is a semantic error about service's name + failures = _validator.getFailures(); + boolean found = false; + for (ValidationFailureDetails f : failures) { + if ("name".equals(f._fieldName) && + f._missing == false && + f._semanticError == true) { + found = true; + } + } + assertTrue("Matching failure located", found); + + // Update: Exact inverse is true, i.e. service must exist! + when(_store.getServiceByName("anotherName")).thenReturn(null); + when(service.getName()).thenReturn("anotherName"); + + _validator = new RangerServiceValidator(_store, Action.UPDATE); + assertFalse(_validator.isValid(service)); + // check the error returned: it is a semantic error about service's name + failures = _validator.getFailures(); + found = false; + for (ValidationFailureDetails f : failures) { + if ("name".equals(f._fieldName) && + f._missing == false && + f._semanticError == true) { + found = true; + } + } + assertTrue("Matching failure located", found); + } + + @Test + public void test_isValid_missingRequiredParameter() throws Exception { + // Create/Update: simulate a condition where required parameters are missing + Object[][] input = new Object[][] { + { "param1", true }, + { "param2", true }, + { "param3", false }, + { "param4", false }, + }; + List<RangerServiceConfigDef> configDefs = _utils.createServiceConditionDefs(input); + RangerServiceDef serviceDef = mock(RangerServiceDef.class); + when(serviceDef.getConfigs()).thenReturn(configDefs); + // wire this service def into store + when(_store.getServiceDefByName("aType")).thenReturn(serviceDef); + // create a service with some require parameters missing + RangerService service = mock(RangerService.class); + when(service.getType()).thenReturn("aType"); + when(service.getName()).thenReturn("aName"); + // required parameters param2 is missing + String[] params = new String[] { "param1", "param3", "param4", "param5" }; + Map<String, String> paramMap = _utils.createMap(params); + when(service.getConfigs()).thenReturn(paramMap); + // service does not exist in the store + when(_store.getServiceByName("aService")).thenReturn(null); + for (Action action : cu) { + // it should be invalid + _validator = new RangerServiceValidator(_store, action); + assertFalse(_validator.isValid(service)); + // check the error message + List<ValidationFailureDetails> failures = _validator.getFailures(); + boolean found = false; + for (ValidationFailureDetails f : failures) { + if ("configuration".equals(f.getFieldName()) && + "param2".equals(f._subFieldName) && + f._missing == true && + f._internalError == false && + f._semanticError == false) { + found = true; + } + } + assertTrue(found); + } + } + + @Test + public void test_isValid_happyPath() throws Exception { + // create a service def with some required parameters + Object[][] serviceDefInput = new Object[][] { + { "param1", true }, + { "param2", true }, + { "param3", false }, + { "param4", false }, + { "param5", true }, + }; + List<RangerServiceConfigDef> configDefs = _utils.createServiceConditionDefs(serviceDefInput); + RangerServiceDef serviceDef = mock(RangerServiceDef.class); + when(serviceDef.getConfigs()).thenReturn(configDefs); + // create a service with some parameters on it + RangerService service = mock(RangerService.class); + when(service.getName()).thenReturn("aName"); + when(service.getType()).thenReturn("aType"); + // contains an extra parameter (param6) and one optional is missing(param4) + String[] configs = new String[] { "param1", "param2", "param3", "param5", "param6" }; + Map<String, String> configMap = _utils.createMap(configs); + when(service.getConfigs()).thenReturn(configMap); + // wire then into the store + try { + // service does not exists + when(_store.getServiceByName("aName")).thenReturn(null); + // service def exists + when(_store.getServiceDefByName("aType")).thenReturn(serviceDef); + } catch (Exception e) { + e.printStackTrace(); + fail("Unexpected error encountered while mocking!"); + } + _validator = new RangerServiceValidator(_store, Action.CREATE); + assertTrue(_validator.isValid(service)); + // for update to work the only additional requirement is that service should exist + RangerService existingService = mock(RangerService.class); + when(_store.getServiceByName("aName")).thenReturn(existingService); + _validator = new RangerServiceValidator(_store, Action.UPDATE); + assertTrue(_validator.isValid(service)); + } + + ValidationFailureDetails getFailure(List<ValidationFailureDetails> failures) { + if (failures == null || failures.size() == 0) { + return null; + } else { + return failures.iterator().next(); + } + } + private ServiceStore _store; + private RangerServiceValidator _validator; + private Action _action; + private ValidationTestUtils _utils = new ValidationTestUtils(); +} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d69fc28d/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 new file mode 100644 index 0000000..483e914 --- /dev/null +++ b/security-admin/src/test/java/org/apache/ranger/rest/TestServiceRESTForValidation.java @@ -0,0 +1,129 @@ +/* + * 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.rest; + +import static org.junit.Assert.fail; +import static org.mockito.Matchers.anyBoolean; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import javax.ws.rs.WebApplicationException; + +import org.apache.ranger.biz.ServiceDBStore; +import org.apache.ranger.common.RESTErrorUtil; +import org.apache.ranger.plugin.model.RangerService; +import org.apache.ranger.rest.RangerValidator.Action; +import org.junit.Before; +import org.junit.Test; + +public class TestServiceRESTForValidation { + + @Before + public void setUp() throws Exception { + _serviceRest = new ServiceREST(); + // inject out store in it + _store = mock(ServiceDBStore.class); + _serviceRest.svcStore = _store; + // and our validator factory + _action = Action.CREATE; + _factory = mock(RangerValidatorFactory.class); + _validator = mock(RangerServiceValidator.class); + when(_factory.getServiceValidator(_store, _action)).thenReturn(_validator); + _serviceRest.validatorFactory = _factory; + // and other things that are needed for service rest to work correctly + _restErrorUtil = mock(RESTErrorUtil.class); + WebApplicationException webApplicationException = new WebApplicationException(); + when(_restErrorUtil.createRESTException(anyInt(), anyString(), anyBoolean())).thenReturn(webApplicationException); + _serviceRest.restErrorUtil = _restErrorUtil; + // other object of use in multiple tests + _service = mock(RangerService.class); + _exception = new Exception(); + } + + @Test + public final void testCreateService_happyPath() throws Exception { + // creation should succeed if neither validator nor dbstore throw exception + when(_store.createService(_service)).thenReturn(null); // return value isn't important + // by default validator mock would not throw exception! + try { + _serviceRest.createService(_service); + // validator must be excercised + verify(_validator).validate(_service); + // db store would also have been excercised but that is not the focus of this test!! + } catch (Throwable t) { + t.printStackTrace(); + fail("Unexpected exception thrown!"); + } + } + + @Test + public final void testCreateService_failureStore() throws Exception { + // creation should fail if either validator or dbstore throw exception + // first have only the dbstore throw and exception + when(_store.createService(_service)).thenThrow(_exception); + // by default validator mock would not throw exception! + try { + _serviceRest.createService(_service); + fail("Should have thrown an exception!"); + } catch (WebApplicationException t) { + // expected exception - confirm that validator was excercised + verify(_validator).validate(_service); + } catch (Throwable t) { + fail("Unexpected exception thrown!"); + } + } + + @Test + public final void testCreateService_failureValidator() throws Exception { + // creation should fail if either validator or dbstore throw exception + // Now we only have the + doThrow(_exception).when(_validator).validate(_service); + // by default validator mock would not throw exception! + try { + _serviceRest.createService(_service); + fail("Should have thrown an exception!"); + } catch (WebApplicationException t) { + /* + * Expected exception - but we still need to validate two things: + * - That validator was exercised; accidentally call to validator should not get bypassed. + * - That dbstore was NOT exercised; we expect validator failure to short circuit that + */ + verify(_validator).validate(_service); + // And that db store was never called! We don't expect call to go to it if validator throws exception. + verify(_store, never()).createService(_service); + } catch (Throwable t) { + fail("Unexpected exception thrown!"); + } + } + + RangerValidatorFactory _factory; + RangerServiceValidator _validator; + ServiceDBStore _store; + Action _action; + ServiceREST _serviceRest; + RangerService _service; + Exception _exception; + RESTErrorUtil _restErrorUtil; +} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d69fc28d/security-admin/src/test/java/org/apache/ranger/rest/TestServiceValidator.java ---------------------------------------------------------------------- diff --git a/security-admin/src/test/java/org/apache/ranger/rest/TestServiceValidator.java b/security-admin/src/test/java/org/apache/ranger/rest/TestServiceValidator.java new file mode 100644 index 0000000..a1879c4 --- /dev/null +++ b/security-admin/src/test/java/org/apache/ranger/rest/TestServiceValidator.java @@ -0,0 +1,202 @@ +/* + * 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.rest; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.ranger.plugin.model.RangerService; +import org.apache.ranger.plugin.model.RangerServiceDef; +import org.apache.ranger.plugin.model.RangerServiceDef.RangerServiceConfigDef; +import org.apache.ranger.plugin.store.ServiceStore; +import org.apache.ranger.rest.RangerValidator.Action; +import org.junit.Before; +import org.junit.Test; + +public class TestServiceValidator { + + static class TestRangerValidator extends RangerValidator { + + public TestRangerValidator(ServiceStore store, Action action) { + super(store, action); + } + + boolean isValid(String behavior) { + if (behavior.equals("valid")) { + _valid = true; + } else { + _valid = false; + if (behavior.equals("reason")) { + _failures = new ArrayList<ValidationFailureDetails>(); + _failures.add(new ValidationFailureDetails("", "", false, false, false, "")); + } + } + return _valid; + } + } + + @Before + public void before() { + _store = mock(ServiceStore.class); + _validator = new TestRangerValidator(_store, Action.CREATE); + } + + @Test + public void test_ctor_firewalling() { + try { + // service store can't be null during construction + new TestRangerValidator(null, Action.CREATE); + fail("Should have thrown exception!"); + } catch (IllegalArgumentException e) { + // expected exception + } + try { + // action can't be null + new TestRangerValidator(_store, null); + fail("Should have thrown exception!"); + } catch (IllegalArgumentException e) { + // expected exception + } + } + + public void test_getFailures_firewalling() { + // it is illegal to query validator for reason without first having it check something! + try { + _validator.getFailures(); + fail("Should have thrown exception!"); + } catch (IllegalStateException e) { + // expected exception. + } + + try { + // we know this call will fail + _validator.isValid("invalid"); + _validator.getFailures(); + } catch (Throwable t) { + t.printStackTrace(); + fail("Unexpected exception!"); + } + } + + @Test + public void test_getServiceConfigParameters() { + // reasonable protection against null values + Set<String> parameters = _validator.getServiceConfigParameters(null); + assertNotNull(parameters); + assertTrue(parameters.isEmpty()); + + RangerService service = mock(RangerService.class); + when(service.getConfigs()).thenReturn(null); + parameters = _validator.getServiceConfigParameters(service); + assertNotNull(parameters); + assertTrue(parameters.isEmpty()); + + when(service.getConfigs()).thenReturn(new HashMap<String, String>()); + parameters = _validator.getServiceConfigParameters(service); + assertNotNull(parameters); + assertTrue(parameters.isEmpty()); + + String[] keys = new String[] { "a", "b", "c" }; + Map<String, String> map = _utils.createMap(keys); + when(service.getConfigs()).thenReturn(map); + parameters = _validator.getServiceConfigParameters(service); + for (String key: keys) { + assertTrue("key", parameters.contains(key)); + } + } + + @Test + public void test_getRequiredParameters() { + // reasonable protection against null things + Set<String> parameters = _validator.getRequiredParameters(null); + assertNotNull(parameters); + assertTrue(parameters.isEmpty()); + + RangerServiceDef serviceDef = mock(RangerServiceDef.class); + when(serviceDef.getConfigs()).thenReturn(null); + parameters = _validator.getRequiredParameters(null); + assertNotNull(parameters); + assertTrue(parameters.isEmpty()); + + List<RangerServiceConfigDef> configs = new ArrayList<RangerServiceDef.RangerServiceConfigDef>(); + when(serviceDef.getConfigs()).thenReturn(configs); + parameters = _validator.getRequiredParameters(null); + assertNotNull(parameters); + assertTrue(parameters.isEmpty()); + + Object[][] input = new Object[][] { + { "param1", false }, + { "param2", true }, + { "param3", true }, + { "param4", false }, + }; + configs = _utils.createServiceConditionDefs(input); + when(serviceDef.getConfigs()).thenReturn(configs); + parameters = _validator.getRequiredParameters(serviceDef); + assertTrue("result does not contain: param2", parameters.contains("param2")); + assertTrue("result does not contain: param3", parameters.contains("param3")); + } + + @Test + public void test_getServiceDef() { + try { + // if service store returns null or throws an exception then service is deemed invalid + when(_store.getServiceDefByName("return null")).thenReturn(null); + when(_store.getServiceDefByName("throw")).thenThrow(new Exception()); + RangerServiceDef serviceDef = mock(RangerServiceDef.class); + when(_store.getServiceDefByName("good-service")).thenReturn(serviceDef); + } catch (Exception e) { + e.printStackTrace(); + fail("Unexpected exception during mocking!"); + } + + assertNull(_validator.getServiceDef("return null")); + assertNull(_validator.getServiceDef("throw")); + assertFalse(_validator.getServiceDef("good-service") == null); + } + + @Test + public void test_getService() { + try { + // if service store returns null or throws an exception then service is deemed invalid + when(_store.getServiceByName("return null")).thenReturn(null); + when(_store.getServiceByName("throw")).thenThrow(new Exception()); + RangerService service = mock(RangerService.class); + when(_store.getServiceByName("good-service")).thenReturn(service); + } catch (Exception e) { + e.printStackTrace(); + fail("Unexpected exception during mocking!"); + } + + assertNull(_validator.getService("return null")); + assertNull(_validator.getService("throw")); + assertFalse(_validator.getService("good-service") == null); + } + + private TestRangerValidator _validator; + private ServiceStore _store; + private ValidationTestUtils _utils = new ValidationTestUtils(); +} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d69fc28d/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 new file mode 100644 index 0000000..0925aa1 --- /dev/null +++ b/security-admin/src/test/java/org/apache/ranger/rest/ValidationTestUtils.java @@ -0,0 +1,57 @@ +/* + * 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.rest; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.ranger.plugin.model.RangerServiceDef; +import org.apache.ranger.plugin.model.RangerServiceDef.RangerServiceConfigDef; + +public class ValidationTestUtils { + + Map<String, String> createMap(String[] keys) { + Map<String, String> result = new HashMap<String, String>(); + for (String key : keys) { + result.put(key, "valueof-" + key); + } + return result; + } + + // helper methods for tests + List<RangerServiceConfigDef> createServiceConditionDefs(Object[][] input) { + List<RangerServiceConfigDef> result = new ArrayList<RangerServiceDef.RangerServiceConfigDef>(); + + for (Object data[] : input) { + RangerServiceConfigDef aConfigDef = mock(RangerServiceConfigDef.class); + when(aConfigDef.getName()).thenReturn((String)data[0]); + when(aConfigDef.getMandatory()).thenReturn((boolean)data[1]); + result.add(aConfigDef); + } + + return result; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d69fc28d/ugsync/src/main/java/org/apache/ranger/ldapusersync/process/LdapUserGroupBuilder.java ---------------------------------------------------------------------- diff --git a/ugsync/src/main/java/org/apache/ranger/ldapusersync/process/LdapUserGroupBuilder.java b/ugsync/src/main/java/org/apache/ranger/ldapusersync/process/LdapUserGroupBuilder.java index f2fbf02..b6bb811 100644 --- a/ugsync/src/main/java/org/apache/ranger/ldapusersync/process/LdapUserGroupBuilder.java +++ b/ugsync/src/main/java/org/apache/ranger/ldapusersync/process/LdapUserGroupBuilder.java @@ -39,7 +39,6 @@ import javax.naming.ldap.LdapContext; import javax.naming.ldap.PagedResultsControl; import javax.naming.ldap.PagedResultsResponseControl; -import com.sun.jndi.toolkit.dir.SearchFilter; import org.apache.log4j.Logger; import org.apache.ranger.unixusersync.config.UserGroupSyncConfig; import org.apache.ranger.usergroupsync.UserGroupSink;
