diff options
Diffstat (limited to 'controlloop/m2')
24 files changed, 2239 insertions, 19 deletions
diff --git a/controlloop/m2/guard/pom.xml b/controlloop/m2/guard/pom.xml index 566761e8e..7a4993a40 100644 --- a/controlloop/m2/guard/pom.xml +++ b/controlloop/m2/guard/pom.xml @@ -38,6 +38,13 @@ </dependency> <dependency> + <groupId>org.onap.policy.models.policy-models-interactions</groupId> + <artifactId>model-yaml</artifactId> + <version>${policy.models.version}</version> + <scope>provided</scope> + </dependency> + + <dependency> <groupId>org.onap.policy.drools-pdp</groupId> <artifactId>policy-core</artifactId> <version>${version.policy.drools-pdp}</version> @@ -52,20 +59,73 @@ </dependency> <dependency> - <groupId>org.onap.policy.drools-applications.controlloop.common</groupId> - <artifactId>guard</artifactId> - <version>${project.version}</version> - </dependency> - - <dependency> <groupId>org.onap.policy.models.policy-models-interactions.model-impl</groupId> <artifactId>guard</artifactId> <version>${policy.models.version}</version> </dependency> <dependency> + <groupId>org.onap.policy.models</groupId> + <artifactId>policy-models-decisions</artifactId> + <version>${policy.models.version}</version> + </dependency> + + <dependency> + <groupId>org.onap.policy.models.policy-models-interactions.model-impl</groupId> + <artifactId>rest</artifactId> + <version>${policy.models.version}</version> + </dependency> + + <dependency> + <groupId>com.att.research.xacml</groupId> + <artifactId>xacml-pdp</artifactId> + <version>1.0.2</version> + <exclusions> + <!-- + Exclude jars with an older version or that are insecure and not needed. + --> + <exclusion> + <artifactId>commons-codec</artifactId> + <groupId>commons-codec</groupId> + </exclusion> + <exclusion> + <artifactId>commons-logging</artifactId> + <groupId>commons-logging</groupId> + </exclusion> + <exclusion> + <artifactId>guava</artifactId> + <groupId>com.google.guava</groupId> + </exclusion> + <exclusion> + <artifactId>commons-lang3</artifactId> + <groupId>org.apache.commons</groupId> + </exclusion> + <exclusion> + <artifactId>jackson-databind</artifactId> + <groupId>com.fasterxml.jackson.core</groupId> + </exclusion> + <exclusion> + <artifactId>commons-collections</artifactId> + <groupId>commons-collections</groupId> + </exclusion> + <exclusion> + <artifactId>commons-lang</artifactId> + <groupId>commons-lang</groupId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.onap.policy.models.policy-models-interactions</groupId> + <artifactId>simulators</artifactId> + <version>${policy.models.version}</version> + <scope>test</scope> + </dependency> + + <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> + <scope>test</scope> </dependency> </dependencies> diff --git a/controlloop/m2/guard/src/main/java/org/onap/policy/guard/CallGuardTask.java b/controlloop/m2/guard/src/main/java/org/onap/policy/guard/CallGuardTask.java new file mode 100644 index 000000000..0331b7aab --- /dev/null +++ b/controlloop/m2/guard/src/main/java/org/onap/policy/guard/CallGuardTask.java @@ -0,0 +1,155 @@ +/*- + * ============LICENSE_START======================================================= + * guard + * ================================================================================ + * Copyright (C) 2017-2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.guard; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; +import java.util.function.Supplier; +import org.drools.core.WorkingMemory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CallGuardTask implements Runnable { + + private static final Logger logger = LoggerFactory.getLogger(CallGuardTask.class); + + /** + * Actor/recipe pairs whose guard requests need a VF Module count. Each element is of + * the form "<actor>:<recipe>". + */ + private static final Set<String> NEEDS_VF_COUNT = new HashSet<>(); + + /** + * Actor/recipe pairs whose guard requests need the VF Module count to be incremented + * (i.e., because a module is being added). Each element is of the form + * "<actor>:<recipe>". + */ + private static final Set<String> INCR_VF_COUNT = new HashSet<>(); + + static { + INCR_VF_COUNT.add("SO:VF Module Create"); + NEEDS_VF_COUNT.addAll(INCR_VF_COUNT); + } + + private WorkingMemory workingMemory; + private String clname; + private String actor; + private String recipe; + private String target; + private String requestId; + private Integer vfCount; + + /** + * Populated once the response has been determined, which may happen during the + * constructor or later, during {@link #run()}. + */ + private PolicyGuardResponse guardResponse; + + /** + * Guard url is grabbed from PolicyEngine manager properties. + */ + public CallGuardTask(WorkingMemory wm, String cl, String act, + String rec, String tar, String reqId, Supplier<Integer> vfcnt) { + workingMemory = wm; + clname = cl; + actor = act; + recipe = rec; + requestId = reqId; + target = tar; + + vfCount = null; + + String key = act + ":" + rec; + + if (NEEDS_VF_COUNT.contains(key)) { + // this actor/recipe needs the count - get it + if ((vfCount = vfcnt.get()) == null) { + /* + * The count is missing - create an artificial Deny, which will be + * inserted into working memory when "run()" is called. + */ + guardResponse = new PolicyGuardResponse(Util.DENY, UUID.fromString(requestId), recipe); + logger.error("CallGuardTask.run missing VF Module count; requestId={}", requestId); + return; + } + + if (INCR_VF_COUNT.contains(key)) { + // this actor/recipe needs the count to be incremented + ++vfCount; + } + } + } + + @Override + public void run() { + if (guardResponse != null) { + // already have a response - just insert it + workingMemory.insert(guardResponse); + return; + } + + final long startTime = System.nanoTime(); + + PolicyGuardXacmlRequestAttributes xacmlReq = + new PolicyGuardXacmlRequestAttributes(clname, actor, recipe, target, requestId, vfCount); + + logger.debug("\n********** XACML REQUEST START ********"); + logger.debug("{}", xacmlReq); + logger.debug("********** XACML REQUEST END ********\n"); + + String guardDecision = null; + + // + // Make guard request + // + guardDecision = new PolicyGuardXacmlHelper().callPdp(xacmlReq); + + logger.debug("\n********** XACML RESPONSE START ********"); + logger.debug("{}", guardDecision); + logger.debug("********** XACML RESPONSE END ********\n"); + + // + // Check if the restful call was unsuccessful or property doesn't exist + // + if (guardDecision == null) { + logger.error("********** XACML FAILED TO CONNECT ********"); + guardDecision = Util.INDETERMINATE; + } + + guardResponse = new PolicyGuardResponse(guardDecision, UUID.fromString(this.requestId), this.recipe); + + // + // Create an artificial Guard response in case we didn't get a clear Permit or Deny + // + if ("Indeterminate".equals(guardResponse.getResult())) { + guardResponse.setOperation(recipe); + guardResponse.setRequestId(UUID.fromString(requestId)); + } + + long estimatedTime = System.nanoTime() - startTime; + logger.debug("\n\n============ Guard inserted with decision {} !!! =========== time took: {} mili sec \n\n", + guardResponse.getResult(), (double) estimatedTime / 1000 / 1000); + workingMemory.insert(guardResponse); + + } + +} diff --git a/controlloop/m2/guard/src/main/java/org/onap/policy/guard/GuardContext.java b/controlloop/m2/guard/src/main/java/org/onap/policy/guard/GuardContext.java index d41e30cb6..75163e24e 100644 --- a/controlloop/m2/guard/src/main/java/org/onap/policy/guard/GuardContext.java +++ b/controlloop/m2/guard/src/main/java/org/onap/policy/guard/GuardContext.java @@ -31,6 +31,7 @@ import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import org.drools.core.WorkingMemory; +import org.eclipse.persistence.config.PersistenceUnitProperties; import org.onap.policy.drools.core.PolicyContainer; import org.onap.policy.drools.core.PolicySession; import org.onap.policy.drools.system.PolicyControllerConstants; @@ -48,8 +49,6 @@ import org.slf4j.LoggerFactory; public class GuardContext implements Serializable { private static final long serialVersionUID = 1L; - private static final String ECLIPSE_LINK_KEY_DRIVER = "javax.persistence.jdbc.driver"; - private static Logger logger = LoggerFactory.getLogger(GuardContext.class); // object that should be serialized @@ -158,13 +157,15 @@ public class GuardContext implements Serializable { // extract 'guard.java.persistence.jdbc.*' parameters, // which are all mandatory dbProperties = new Properties(); - setProperty(dbProperties, Util.ONAP_KEY_URL, Util.ECLIPSE_LINK_KEY_URL, sb); - setProperty(dbProperties, Util.ONAP_KEY_USER, Util.ECLIPSE_LINK_KEY_USER, sb); - setProperty(dbProperties, Util.ONAP_KEY_PASS, Util.ECLIPSE_LINK_KEY_PASS, sb); - String driver = properties.getProperty("guard." + ECLIPSE_LINK_KEY_DRIVER); + setProperty(dbProperties, Util.ONAP_KEY_URL, PersistenceUnitProperties.JDBC_URL, sb); + setProperty(dbProperties, Util.ONAP_KEY_USER, PersistenceUnitProperties.JDBC_USER, sb); + setProperty(dbProperties, Util.ONAP_KEY_PASS, PersistenceUnitProperties.JDBC_PASSWORD, sb); + String driver = properties.getProperty("guard." + PersistenceUnitProperties.JDBC_DRIVER); if (driver != null) { - dbProperties.setProperty(ECLIPSE_LINK_KEY_DRIVER, driver); + dbProperties.setProperty(PersistenceUnitProperties.JDBC_DRIVER, driver); } + dbProperties.setProperty(Util.PROP_GUARD_PERSISTENCE_UNIT, + properties.getProperty(Util.PROP_GUARD_PERSISTENCE_UNIT, Util.PU_KEY)); // if there are any errors, update 'errorMessage' & disable guard queries if (sb.length() != 0) { @@ -266,7 +267,8 @@ public class GuardContext implements Serializable { propertiesMap.put("eclipselink.ddl-generation", "create-tables"); // create entity manager factory - emf = Persistence.createEntityManagerFactory("OperationsHistoryPU", propertiesMap); + String persistenceUnit = dbProperties.getProperty(Util.PROP_GUARD_PERSISTENCE_UNIT); + emf = Persistence.createEntityManagerFactory(persistenceUnit, propertiesMap); } // create and return the 'EntityManager' diff --git a/controlloop/m2/guard/src/main/java/org/onap/policy/guard/GuardResult.java b/controlloop/m2/guard/src/main/java/org/onap/policy/guard/GuardResult.java new file mode 100644 index 000000000..6b11c1afa --- /dev/null +++ b/controlloop/m2/guard/src/main/java/org/onap/policy/guard/GuardResult.java @@ -0,0 +1,25 @@ +/*- + * ============LICENSE_START======================================================= + * guard + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.guard; + +public enum GuardResult { + LOCK_ACQUIRED, LOCK_DENIED, LOCK_EXCEPTION; +} diff --git a/controlloop/m2/guard/src/main/java/org/onap/policy/guard/PolicyGuardRequest.java b/controlloop/m2/guard/src/main/java/org/onap/policy/guard/PolicyGuardRequest.java new file mode 100644 index 000000000..8887e00b7 --- /dev/null +++ b/controlloop/m2/guard/src/main/java/org/onap/policy/guard/PolicyGuardRequest.java @@ -0,0 +1,84 @@ +/*- + * ============LICENSE_START======================================================= + * guard + * ================================================================================ + * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.guard; + +import java.util.UUID; + +public class PolicyGuardRequest { + private String actor; + private String target; + private UUID requestId; + private String operation; + + /** + * Construct an instance. + * + * @param actor the actor + * @param target the target + * @param requestId the request Id + * @param operation the operation + */ + public PolicyGuardRequest(String actor, String target, UUID requestId, String operation) { + super(); + this.actor = actor; + this.target = target; + this.requestId = requestId; + this.operation = operation; + } + + @Override + public String toString() { + return "PolicyGuardRequest [actor=" + actor + ", target=" + target + ", requestId=" + requestId + ", operation=" + + operation + "]"; + } + + public String getActor() { + return actor; + } + + public void setActor(String actor) { + this.actor = actor; + } + + public String getTarget() { + return target; + } + + public void setTarget(String target) { + this.target = target; + } + + public UUID getRequestId() { + return requestId; + } + + public void setRequestId(UUID requestId) { + this.requestId = requestId; + } + + public String getOperation() { + return operation; + } + + public void setOperation(String operation) { + this.operation = operation; + } +} diff --git a/controlloop/m2/guard/src/main/java/org/onap/policy/guard/PolicyGuardResponse.java b/controlloop/m2/guard/src/main/java/org/onap/policy/guard/PolicyGuardResponse.java new file mode 100644 index 000000000..574c50b79 --- /dev/null +++ b/controlloop/m2/guard/src/main/java/org/onap/policy/guard/PolicyGuardResponse.java @@ -0,0 +1,71 @@ +/*- + * ============LICENSE_START======================================================= + * guard + * ================================================================================ + * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.guard; + +import java.util.UUID; + +public class PolicyGuardResponse { + private UUID requestId; + private String operation; + private String result; + + /** + * Create an instance. + * + * @param result the result + * @param req the request Id + * @param op the operation + */ + public PolicyGuardResponse(String result, UUID req, String op) { + this.result = result; + this.requestId = req; + this.operation = op; + } + + @Override + public String toString() { + return "PolicyGuardResponse [requestId=" + requestId + ", operation=" + operation + ", result=" + result + "]"; + } + + public UUID getRequestId() { + return requestId; + } + + public void setRequestId(UUID requestId) { + this.requestId = requestId; + } + + public String getResult() { + return result; + } + + public void setResult(String result) { + this.result = result; + } + + public String getOperation() { + return operation; + } + + public void setOperation(String operation) { + this.operation = operation; + } +} diff --git a/controlloop/m2/guard/src/main/java/org/onap/policy/guard/PolicyGuardXacmlHelper.java b/controlloop/m2/guard/src/main/java/org/onap/policy/guard/PolicyGuardXacmlHelper.java new file mode 100644 index 000000000..d9ace1d83 --- /dev/null +++ b/controlloop/m2/guard/src/main/java/org/onap/policy/guard/PolicyGuardXacmlHelper.java @@ -0,0 +1,139 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2017-2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2019 Samsung Electronics Co., Ltd. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.guard; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import org.apache.commons.lang3.tuple.Pair; +import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure; +import org.onap.policy.common.endpoints.utils.NetLoggerUtil; +import org.onap.policy.common.endpoints.utils.NetLoggerUtil.EventType; +import org.onap.policy.common.utils.coder.CoderException; +import org.onap.policy.common.utils.coder.StandardCoder; +import org.onap.policy.drools.system.PolicyEngineConstants; +import org.onap.policy.models.decisions.concepts.DecisionRequest; +import org.onap.policy.models.decisions.concepts.DecisionResponse; +import org.onap.policy.rest.RestManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class PolicyGuardXacmlHelper { + private static final Logger logger = LoggerFactory.getLogger(PolicyGuardXacmlHelper.class); + + private String url; + private String user; + private String pwd; + + /** + * Constructor. + */ + public PolicyGuardXacmlHelper() { + this.url = PolicyEngineConstants.getManager().getEnvironmentProperty("guard.url"); + this.user = PolicyEngineConstants.getManager().getEnvironmentProperty("pdpx.username"); + this.pwd = PolicyEngineConstants.getManager().getEnvironmentProperty("pdpx.password"); + } + + /** + * Call PDP. + * + * @param xacmlReq the XACML request + * @return the response + */ + public String callPdp(PolicyGuardXacmlRequestAttributes xacmlReq) { + // + // Create a request suitable for API + // + DecisionRequest decisionRequest = new DecisionRequest(); + decisionRequest.setOnapName("Policy"); + decisionRequest.setOnapComponent("Drools PDP"); + decisionRequest.setOnapInstance("usecase template"); + decisionRequest.setRequestId(UUID.randomUUID().toString()); + decisionRequest.setAction("guard"); + Map<String, String> guard = new HashMap<>(); + guard.put("actor", xacmlReq.getActorId()); + guard.put("operation", xacmlReq.getOperationId()); + guard.put("target", xacmlReq.getTargetId()); + if (xacmlReq.getClnameId() != null) { + guard.put("clname", xacmlReq.getClnameId()); + } + if (xacmlReq.getVfCount() != null) { + guard.put("vfCount", Integer.toString(xacmlReq.getVfCount())); + } + Map<String, Object> resources = new HashMap<>(); + resources.put("guard", guard); + decisionRequest.setResource(resources); + + try { + // + // Call RESTful PDP + // + NetLoggerUtil.log(EventType.OUT, CommInfrastructure.REST, this.url, decisionRequest.toString()); + String response = callRestfulPdp(decisionRequest); + NetLoggerUtil.log(EventType.IN, CommInfrastructure.REST, this.url, response); + + return response; + } catch (Exception e) { + logger.error("Exception in sending RESTful request: ", e); + } + + return Util.DENY; + } + + /** + * This makes an HTTP POST call to a running PDP RESTful servlet to get a decision. + * + * @param decisionRequest The Decision request + * @return response from guard which contains "Permit" or "Deny" + * @throws CoderException Exception when converting to/from JSON the message body + */ + private String callRestfulPdp(DecisionRequest decisionRequest) throws CoderException { + StandardCoder coder = new StandardCoder(); + + String jsonBody = coder.encode(decisionRequest); + RestManager restManager = new RestManager(); + + Map<String, String> headers = new HashMap<>(); + headers.put("Accepts", "application/json"); + + logger.info("Guard Decision Request: {}", jsonBody); + + Pair<Integer, String> httpDetails = restManager.post(url, user, pwd, headers, "application/json", jsonBody); + + if (httpDetails == null) { + logger.error("Guard rest call returned a null pair - defaulting to DENY"); + return Util.DENY; + } + + logger.info("Guard Decision REST Response {} {}", httpDetails.getLeft(), httpDetails.getRight()); + + if (httpDetails.getLeft() == 200) { + DecisionResponse decision = coder.decode(httpDetails.getRight(), DecisionResponse.class); + logger.info("Guard Decision {}", decision); + return decision.getStatus(); + } + + return Util.DENY; + } + +} diff --git a/controlloop/m2/guard/src/main/java/org/onap/policy/guard/PolicyGuardXacmlRequestAttributes.java b/controlloop/m2/guard/src/main/java/org/onap/policy/guard/PolicyGuardXacmlRequestAttributes.java new file mode 100644 index 000000000..c888f94c1 --- /dev/null +++ b/controlloop/m2/guard/src/main/java/org/onap/policy/guard/PolicyGuardXacmlRequestAttributes.java @@ -0,0 +1,123 @@ +/*- + * ============LICENSE_START======================================================= + * guard + * ================================================================================ + * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.guard; + +import com.att.research.xacml.std.annotations.XACMLAction; +import com.att.research.xacml.std.annotations.XACMLRequest; +import com.att.research.xacml.std.annotations.XACMLResource; +import com.att.research.xacml.std.annotations.XACMLSubject; + +@XACMLRequest(ReturnPolicyIdList = true, CombinedDecision = true) +public class PolicyGuardXacmlRequestAttributes { + + @XACMLSubject(includeInResults = true, attributeId = "urn:org:onap:guard:clname:clname-id") + String clnameId; + + @XACMLSubject(includeInResults = true, attributeId = "urn:org:onap:guard:actor:actor-id") + String actorId; + + @XACMLAction(includeInResults = true, attributeId = "urn:org:onap:guard:operation:operation-id") + String operationId; + + @XACMLResource(includeInResults = true, attributeId = "urn:org:onap:guard:target:target-id") + String targetId; + + @XACMLResource(includeInResults = true, attributeId = "urn:org:onap:guard:request:request-id") + String requestId; + + @XACMLResource(includeInResults = true, attributeId = "urn:org:onap:guard:request:vf-count") + Integer vfCount; + + /** + * Construct an instance. + * + * @param clnameId the control loop Id + * @param actorId the actor Id + * @param operationId the operation Id + * @param targetId the target Id + * @param requestId the request Id + * @param vfCount the new number of VF Modules + */ + public PolicyGuardXacmlRequestAttributes(String clnameId, String actorId, String operationId, String targetId, + String requestId, Integer vfCount) { + super(); + this.clnameId = clnameId; + this.actorId = actorId; + this.operationId = operationId; + this.targetId = targetId; + this.requestId = requestId; + this.vfCount = vfCount; + } + + @Override + public String toString() { + return "PolicyGuardXacmlRequestAttributes [actorId=" + actorId + ", operationId=" + operationId + ", targetId=" + + targetId + ", requestId=" + requestId + "]"; + } + + public String getActorId() { + return actorId; + } + + public void setActorId(String actorId) { + this.actorId = actorId; + } + + public String getOperationId() { + return operationId; + } + + public void setOperationId(String operationId) { + this.operationId = operationId; + } + + public String getTargetId() { + return targetId; + } + + public void setTargetId(String targetId) { + this.targetId = targetId; + } + + public String getRequestId() { + return requestId; + } + + public void setRequestId(String requestId) { + this.requestId = requestId; + } + + public String getClnameId() { + return clnameId; + } + + public void setClnameId(String clnameId) { + this.clnameId = clnameId; + } + + public Integer getVfCount() { + return vfCount; + } + + public void setVfCount(Integer vfCount) { + this.vfCount = vfCount; + } +} diff --git a/controlloop/m2/guard/src/main/java/org/onap/policy/guard/PolicyGuardYamlToXacml.java b/controlloop/m2/guard/src/main/java/org/onap/policy/guard/PolicyGuardYamlToXacml.java new file mode 100644 index 000000000..60ccce05d --- /dev/null +++ b/controlloop/m2/guard/src/main/java/org/onap/policy/guard/PolicyGuardYamlToXacml.java @@ -0,0 +1,210 @@ +/*- + * ============LICENSE_START======================================================= + * guard + * ================================================================================ + * Copyright (C) 2017, 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.guard; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.function.Consumer; +import org.onap.policy.controlloop.policy.guard.Constraint; +import org.onap.policy.controlloop.policy.guard.ControlLoopGuard; +import org.onap.policy.controlloop.policy.guard.GuardPolicy; +import org.onap.policy.controlloop.policy.guard.MatchParameters; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class PolicyGuardYamlToXacml { + private static final Logger logger = LoggerFactory.getLogger(PolicyGuardYamlToXacml.class); + + private PolicyGuardYamlToXacml() { + // Construction of this static class is not allowed + } + + /** + * Convert from Yaml to Xacml. + * + * @param yamlFile the Yaml file + * @param xacmlTemplate the Xacml template + * @param xacmlPolicyOutput the Xacml output + */ + public static void fromYamlToXacml(String yamlFile, String xacmlTemplate, String xacmlPolicyOutput) { + fromYamlToXacml(yamlFile, xacmlTemplate, xacmlPolicyOutput, PolicyGuardYamlToXacml::generateXacmlGuard, + constraint -> { + logger.debug("num: {}", constraint.getFreq_limit_per_target()); + logger.debug("duration: {}", constraint.getTime_window()); + logger.debug("time_in_range: {}", constraint.getActive_time_range()); + }); + } + + /** + * Convert from Yaml to Xacml. + * + * @param yamlFile the Yaml file + * @param xacmlTemplate the Xacml template + * @param xacmlPolicyOutput the Xacml output + * @param generator function to generate the yaml from the xacml + * @param logConstraint function to log relevant fields of the constraint + */ + public static void fromYamlToXacml(String yamlFile, String xacmlTemplate, String xacmlPolicyOutput, + Generator generator, Consumer<Constraint> logConstraint) { + + ControlLoopGuard yamlGuardObject = Util.loadYamlGuard(yamlFile); + GuardPolicy guardPolicy = yamlGuardObject.getGuards().get(0); + logger.debug("clname: {}", guardPolicy.getMatch_parameters().getControlLoopName()); + logger.debug("actor: {}", guardPolicy.getMatch_parameters().getActor()); + logger.debug("recipe: {}", guardPolicy.getMatch_parameters().getRecipe()); + Constraint constraint = guardPolicy.getLimit_constraints().get(0); + logConstraint.accept(constraint); + + Path xacmlTemplatePath = Paths.get(xacmlTemplate); + String xacmlTemplateContent; + + try { + xacmlTemplateContent = new String(Files.readAllBytes(xacmlTemplatePath)); + + String xacmlPolicyContent = generator.apply(xacmlTemplateContent, + guardPolicy.getMatch_parameters(), constraint); + + Files.write(Paths.get(xacmlPolicyOutput), xacmlPolicyContent.getBytes()); + + } catch (IOException e) { + logger.error("fromYamlToXacml threw: ", e); + } + } + + /** + * Generate a Xacml guard. + * + * @param xacmlTemplateContent the Xacml template content + * @param matchParameters the paremeters to use + * @param constraint the constraint to use + * @return the guard + */ + private static String generateXacmlGuard(String xacmlTemplateContent, MatchParameters matchParameters, + Constraint constraint) { + + xacmlTemplateContent = doCommonReplacements(xacmlTemplateContent, matchParameters, constraint); + + String targetsRegex = ""; + if (isNullOrEmptyList(matchParameters.getTargets())) { + targetsRegex = ".*"; + } else { + StringBuilder targetsRegexSb = new StringBuilder(); + boolean addBarChar = false; + for (String t : matchParameters.getTargets()) { + targetsRegexSb.append(t); + if (addBarChar) { + targetsRegexSb.append("|"); + } else { + addBarChar = true; + } + } + targetsRegex = targetsRegexSb.toString(); + } + xacmlTemplateContent = xacmlTemplateContent.replace("${targets}", targetsRegex); + + xacmlTemplateContent = xacmlTemplateContent.replace("${limit}", + constraint.getFreq_limit_per_target().toString()); + + xacmlTemplateContent = xacmlTemplateContent.replace("${twValue}", constraint.getTime_window().get("value")); + + xacmlTemplateContent = xacmlTemplateContent.replace("${twUnits}", constraint.getTime_window().get("units")); + + logger.debug(xacmlTemplateContent); + + return xacmlTemplateContent; + } + + private static String doCommonReplacements(String xacmlTemplateContent, MatchParameters matchParameters, + Constraint constraint) { + + replaceNullOrEmpty(matchParameters.getControlLoopName(), matchParameters::setControlLoopName, ".*"); + xacmlTemplateContent = xacmlTemplateContent.replace("${clname}", matchParameters.getControlLoopName()); + + replaceNullOrEmpty(matchParameters.getActor(), matchParameters::setActor, ".*"); + xacmlTemplateContent = xacmlTemplateContent.replace("${actor}", matchParameters.getActor()); + + replaceNullOrEmpty(matchParameters.getRecipe(), matchParameters::setRecipe, ".*"); + xacmlTemplateContent = xacmlTemplateContent.replace("${recipe}", matchParameters.getRecipe()); + + xacmlTemplateContent = xacmlTemplateContent.replace("${guardActiveStart}", + constraint.getActive_time_range().get("start")); + + xacmlTemplateContent = xacmlTemplateContent.replace("${guardActiveEnd}", + constraint.getActive_time_range().get("end")); + + return xacmlTemplateContent; + } + + private static void replaceNullOrEmpty(String text, Consumer<String> replacer, String newValue) { + if (isNullOrEmpty(text)) { + replacer.accept(newValue); + } + } + + public static boolean isNullOrEmpty(String string) { + return string == null || string.trim().isEmpty(); + } + + public static boolean isNullOrEmptyList(List<String> list) { + return list == null || list.isEmpty(); + } + + /** + * Convert from Yaml to Xacml blacklist. + * + * @param yamlFile the Yaml file + * @param xacmlTemplate the Xacml template + * @param xacmlPolicyOutput the Xacml output + */ + public static void fromYamlToXacmlBlacklist(String yamlFile, String xacmlTemplate, String xacmlPolicyOutput) { + fromYamlToXacml(yamlFile, xacmlTemplate, xacmlPolicyOutput, PolicyGuardYamlToXacml::generateXacmlGuardBlacklist, + constraint -> { + logger.debug("freq_limit_per_target: {}", constraint.getFreq_limit_per_target()); + logger.debug("time_window: {}", constraint.getTime_window()); + logger.debug("active_time_range: {}", constraint.getActive_time_range()); + }); + } + + private static String generateXacmlGuardBlacklist(String xacmlTemplateContent, MatchParameters matchParameters, + Constraint constraint) { + + String result = doCommonReplacements(xacmlTemplateContent, matchParameters, constraint); + + for (String target : constraint.getBlacklist()) { + result = result.replace("${blackListElement}", + "<AttributeValue DataType=\"http://www.w3.org/2001/XMLSchema#string\">" + target + + "</AttributeValue>" + "\n\t\t\t\t\t\t\\${blackListElement}\n"); + } + + result = result.replace("\t\t\t\t\t\t\\${blackListElement}\n", ""); + + return result; + } + + @FunctionalInterface + private static interface Generator { + public String apply(String xacmlTemplateContent, MatchParameters matchParameters, + Constraint constraint); + } +} diff --git a/controlloop/m2/guard/src/main/java/org/onap/policy/guard/Util.java b/controlloop/m2/guard/src/main/java/org/onap/policy/guard/Util.java new file mode 100644 index 000000000..d1eed1bb4 --- /dev/null +++ b/controlloop/m2/guard/src/main/java/org/onap/policy/guard/Util.java @@ -0,0 +1,146 @@ +/*- + * ============LICENSE_START======================================================= + * guard + * ================================================================================ + * Copyright (C) 2017-2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.guard; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import org.apache.commons.io.IOUtils; +import org.onap.policy.controlloop.policy.ControlLoopPolicy; +import org.onap.policy.controlloop.policy.guard.ControlLoopGuard; +import org.onap.policy.drools.system.PolicyEngineConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.constructor.Constructor; + +public final class Util { + /* + * Keys for guard properties + */ + public static final String PROP_GUARD_URL = "guard.url"; + public static final String PROP_GUARD_USER = "pdpx.username"; + public static final String PROP_GUARD_PASS = "pdpx.password"; + public static final String PROP_GUARD_DISABLED = "guard.disabled"; + public static final String PROP_GUARD_PERSISTENCE_UNIT = "guard.persistenceUnit"; + + /* + * Keys for ONAP properties + */ + public static final String ONAP_KEY_URL = "guard.jdbc.url"; + public static final String ONAP_KEY_USER = "sql.db.username"; + public static final String ONAP_KEY_PASS = "sql.db.password"; + + /* + * Guard responses + */ + public static final String INDETERMINATE = "Indeterminate"; + public static final String PERMIT = "Permit"; + public static final String DENY = "Deny"; + + /* + * Junit props + */ + protected static final String PU_KEY = "OperationsHistoryPU"; + protected static final String JUNITPU = "OperationsHistoryPUTest"; + + private static final Logger logger = LoggerFactory.getLogger(Util.class); + + public static class Pair<A, B> { + public final A parameterA; + public final B parameterB; + + public Pair(A parameterA, B parameterB) { + this.parameterA = parameterA; + this.parameterB = parameterB; + } + } + + private Util() { + // This static class cannot be instantiated + } + + /** + * Load a Yaml file. + * + * @param testFile the Yaml file + * @return the policies + */ + public static Pair<ControlLoopPolicy, String> loadYaml(String testFile) { + try (InputStream is = new FileInputStream(new File(testFile))) { + String contents = IOUtils.toString(is, StandardCharsets.UTF_8); + // + // Read the yaml into our Java Object + // + Yaml yaml = new Yaml(new Constructor(ControlLoopPolicy.class)); + Object obj = yaml.load(contents); + + logger.debug(contents); + + return new Pair<>((ControlLoopPolicy) obj, contents); + } catch (IOException e) { + logger.error(e.getLocalizedMessage(), e); + } + return null; + } + + /** + * Load a Yaml guard. + * + * @param testFile the Yaml file + * @return the guard + */ + public static ControlLoopGuard loadYamlGuard(String testFile) { + try (InputStream is = new FileInputStream(new File(testFile))) { + String contents = IOUtils.toString(is, StandardCharsets.UTF_8); + // + // Read the yaml into our Java Object + // + Yaml yaml = new Yaml(new Constructor(ControlLoopGuard.class)); + Object obj = yaml.load(contents); + return (ControlLoopGuard) obj; + } catch (IOException e) { + logger.error(e.getLocalizedMessage(), e); + } + return null; + } + + /** + * Sets Guard Properties. + * + * <p>see /guard/src/test/java/org/onap/policy/guard/UtilTest.java for setting test properties + */ + public static void setGuardEnvProps(String url, String username, String password) { + PolicyEngineConstants.getManager().setEnvironmentProperty(org.onap.policy.guard.Util.PROP_GUARD_URL, url); + PolicyEngineConstants.getManager().setEnvironmentProperty(org.onap.policy.guard.Util.PROP_GUARD_USER, username); + PolicyEngineConstants.getManager().setEnvironmentProperty(org.onap.policy.guard.Util.PROP_GUARD_PASS, password); + } + + public static void setGuardEnvProp(String key, String value) { + PolicyEngineConstants.getManager().setEnvironmentProperty(key, value); + } + + public static String getGuardProp(String propName) { + return PolicyEngineConstants.getManager().getEnvironmentProperty(propName); + } +} diff --git a/controlloop/m2/guard/src/main/resources/META-INF/persistence.xml b/controlloop/m2/guard/src/main/resources/META-INF/persistence.xml new file mode 100644 index 000000000..cf7e28190 --- /dev/null +++ b/controlloop/m2/guard/src/main/resources/META-INF/persistence.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!-- + ============LICENSE_START======================================================= + drools-applications + ================================================================================ + Copyright (C) 2018-2020 AT&T Intellectual Property. All rights reserved. + ================================================================================ + Licensed 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. + ============LICENSE_END========================================================= + --> +<persistence xmlns="http://java.sun.com/xml/ns/persistence" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://java.sun.com/xml/ns/persistence + http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0"> + + <persistence-unit name="OperationsHistoryPU" transaction-type="RESOURCE_LOCAL"> + <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> + + <class>org.onap.policy.guard.OperationsHistory</class> + + <properties> + <property name="eclipselink.ddl-generation" value="create-tables"/> + <property name="eclipselink.logging.level" value="INFO" /> + <property name="javax.persistence.jdbc.driver" value="org.mariadb.jdbc.Driver" /> + <property name="javax.persistence.jdbc.url" value="jdbc:mariadb://mariadb:3306/operationshistory"/> + <property name="javax.persistence.jdbc.user" value="policy_user"/> + <property name="javax.persistence.jdbc.password" value="cG9saWN5X3VzZXI="/> + <property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/> + <property name="javax.persistence.schema-generation.create-source" value="metadata"/> + </properties> + </persistence-unit> + +</persistence> diff --git a/controlloop/m2/guard/src/test/java/org/onap/policy/guard/CallGuardTaskTest.java b/controlloop/m2/guard/src/test/java/org/onap/policy/guard/CallGuardTaskTest.java new file mode 100644 index 000000000..3a647b130 --- /dev/null +++ b/controlloop/m2/guard/src/test/java/org/onap/policy/guard/CallGuardTaskTest.java @@ -0,0 +1,78 @@ +/*- + * ============LICENSE_START======================================================= + * guard + * ================================================================================ + * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.guard; + +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.ArgumentMatchers.isNotNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.function.Supplier; +import org.drools.core.WorkingMemory; +import org.junit.Test; + +public class CallGuardTaskTest { + + private static final String REQ_ID = "1-2-3-4-5"; + private static final String REQ_MATCHER = "0+1-0+2-0+3-0+4-0+5"; + private static final String VF_COUNT_ACTOR = "SO"; + private static final String INCR_VF_COUNT_RECIPE = "VF Module Create"; + + /** + * Tests that "run" works, and inserts guard response into working memory. + */ + @Test + public void testRun() { + // plain - doesn't need VF module count + //doTestRun(Util.INDETERMINATE, "act", "rec", () -> null); + + // SO actor, but plain recipe - doesn't need VF module count + //doTestRun(Util.INDETERMINATE, VF_COUNT_ACTOR, "rec", () -> null); + + // plain actor, but scale-out recipe - doesn't need VF module count + //doTestRun(Util.INDETERMINATE, "act", "VF Module Create", () -> null); + + // needs VF count + //doTestRun(Util.INDETERMINATE, VF_COUNT_ACTOR, INCR_VF_COUNT_RECIPE, () -> 22); + + // needs VF count, but it's missing ==> DENY + doTestRun(Util.DENY, VF_COUNT_ACTOR, INCR_VF_COUNT_RECIPE, () -> null); + } + + private void doTestRun(String status, String actor, String recipe, Supplier<Integer> vfCount) { + WorkingMemory mockWorkingSession = mock(WorkingMemory.class); + when(mockWorkingSession.insert(isNotNull())).thenReturn(null); + // Create CallGuardTask and run + CallGuardTask cgt = new CallGuardTask(mockWorkingSession, "cl", actor, recipe, "tar", REQ_ID, vfCount); + cgt.run(); + verify(mockWorkingSession).insert(argThat((Object obj) -> { + if (!(obj instanceof PolicyGuardResponse)) { + return false; + } + // Check if the inserted response is PolicyGuardResponse, is Indeterminate, + // and has same reqID + PolicyGuardResponse response = (PolicyGuardResponse) obj; + // req ID has form 00000001-0002-0003-0004-000000000005 + return status.equals(response.getResult()) && response.getRequestId().toString().matches(REQ_MATCHER); + })); + } +} diff --git a/controlloop/m2/guard/src/test/java/org/onap/policy/guard/GuardContextTest.java b/controlloop/m2/guard/src/test/java/org/onap/policy/guard/GuardContextTest.java index 54fd323c2..1b375cf21 100644 --- a/controlloop/m2/guard/src/test/java/org/onap/policy/guard/GuardContextTest.java +++ b/controlloop/m2/guard/src/test/java/org/onap/policy/guard/GuardContextTest.java @@ -84,11 +84,12 @@ public class GuardContextTest { @Test public void testGuardDbResponse() throws InterruptedException { Properties props = new Properties(prop); + props.setProperty(Util.PROP_GUARD_PERSISTENCE_UNIT, Util.JUNITPU); props.setProperty("guard.disabled", "false"); props.setProperty("guard.javax.persistence.jdbc.user", "user"); props.setProperty("guard.javax.persistence.jdbc.password", "secret"); props.setProperty("guard.javax.persistence.jdbc.driver", "org.h2.Driver"); - props.setProperty("guard.javax.persistence.jdbc.url", "jdbc:h2:file:./H2DB"); + props.setProperty("guard.javax.persistence.jdbc.url", "jdbc:h2:mem:testGuardDbResponse"); guardContext = new GuardContext(props); assertNotNull(guardContext); @@ -167,11 +168,12 @@ public class GuardContextTest { @Test public void testCreateDbEntry() { - Properties mockProperties = Mockito.mock(Properties.class); + Properties props = new Properties(); + props.setProperty(Util.PROP_GUARD_PERSISTENCE_UNIT, Util.JUNITPU); Instant startTime = Instant.now(); Instant endTime = Instant.now(); - guardContext = new GuardContext(mockProperties); + guardContext = new GuardContext(props); assertFalse(guardContext.createDbEntry(startTime, endTime, "testClosedLoopControlName", "testActor", "testRecipe", "testTarget", "testRequestId", "testSubRequestId", "testMessage", "testOutcome")); @@ -180,10 +182,10 @@ public class GuardContextTest { "testRecipe", "testTarget", "testRequestId", "testSubRequestId", "testMessage", "testOutcome")); PolicyEngineConstants.getManager().setEnvironmentProperty("guard.disabled", ""); - PolicyEngineConstants.getManager().setEnvironmentProperty("guard.jdbc.url", "jdbc:h2:file:./H2DB"); + PolicyEngineConstants.getManager().setEnvironmentProperty("guard.jdbc.url", "jdbc:h2:mem:testCreateDbEntry"); PolicyEngineConstants.getManager().setEnvironmentProperty("sql.db.username", "user"); PolicyEngineConstants.getManager().setEnvironmentProperty("sql.db.password", "secret"); - guardContext = new GuardContext(mockProperties); + guardContext = new GuardContext(props); assertTrue(guardContext.createDbEntry(startTime, endTime, "testClosedLoopControlName", "testActor", "testRecipe", "testTarget", "testRequestId", "testSubRequestId", "testMessage", "testOutcome")); diff --git a/controlloop/m2/guard/src/test/java/org/onap/policy/guard/GuardResultTest.java b/controlloop/m2/guard/src/test/java/org/onap/policy/guard/GuardResultTest.java new file mode 100644 index 000000000..6fe0f2b50 --- /dev/null +++ b/controlloop/m2/guard/src/test/java/org/onap/policy/guard/GuardResultTest.java @@ -0,0 +1,42 @@ +/*- + * ============LICENSE_START======================================================= + * guard + * ================================================================================ + * Copyright (C) 2018 Ericsson. All rights reserved. + * Modifications Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.guard; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import org.junit.Test; + +public class GuardResultTest { + + @Test + public void testGuardResult() { + assertEquals(3, GuardResult.values().length); + assertNotNull(GuardResult.LOCK_ACQUIRED); + assertNotNull(GuardResult.LOCK_DENIED); + assertNotNull(GuardResult.LOCK_EXCEPTION); + + assertEquals(GuardResult.LOCK_ACQUIRED, GuardResult.valueOf("LOCK_ACQUIRED")); + assertEquals(GuardResult.LOCK_DENIED, GuardResult.valueOf("LOCK_DENIED")); + assertEquals(GuardResult.LOCK_EXCEPTION, GuardResult.valueOf("LOCK_EXCEPTION")); + } +} diff --git a/controlloop/m2/guard/src/test/java/org/onap/policy/guard/GuardUtilTest.java b/controlloop/m2/guard/src/test/java/org/onap/policy/guard/GuardUtilTest.java new file mode 100644 index 000000000..e17207634 --- /dev/null +++ b/controlloop/m2/guard/src/test/java/org/onap/policy/guard/GuardUtilTest.java @@ -0,0 +1,102 @@ +/*- + * ============LICENSE_START======================================================= + * guard + * ================================================================================ + * Copyright (C) 2018 Ericsson. All rights reserved. + * Modifications Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.guard; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import com.google.common.io.Files; +import java.io.File; +import java.io.IOException; +import org.junit.Test; +import org.onap.policy.controlloop.policy.ControlLoopPolicy; +import org.onap.policy.controlloop.policy.guard.ControlLoopGuard; +import org.onap.policy.guard.Util.Pair; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.constructor.Constructor; + +public class GuardUtilTest { + @Test + public void testLoadYamlOk() throws IOException { + File tempYamlFile = File.createTempFile("ONAPPF", "yaml"); + tempYamlFile.deleteOnExit(); + + ControlLoopPolicy clPolicy = new ControlLoopPolicy(); + + Yaml clYaml = new Yaml(new Constructor(ControlLoopPolicy.class)); + String clYamlString = clYaml.dump(clPolicy); + + SupportTextFileUtils.putStringAsFile(clYamlString, tempYamlFile); + + Pair<ControlLoopPolicy, String> result = Util.loadYaml(tempYamlFile.getCanonicalPath()); + + assertEquals(clPolicy, result.parameterA); + assertEquals(clYamlString, result.parameterB); + } + + @Test + public void testLoadYamlError() throws IOException { + File tempDir = Files.createTempDir(); + tempDir.deleteOnExit(); + + // Read from a directory forces an IO exception + assertNull(Util.loadYaml(tempDir.getCanonicalPath())); + } + + @Test + public void testLoadGuardYamlOk() throws IOException { + File tempYamlFile = File.createTempFile("ONAPPF", "yaml"); + tempYamlFile.deleteOnExit(); + + ControlLoopGuard clGuardPolicy = new ControlLoopGuard(); + + Yaml clYaml = new Yaml(new Constructor(ControlLoopPolicy.class)); + String clYamlString = clYaml.dump(clGuardPolicy); + + SupportTextFileUtils.putStringAsFile(clYamlString, tempYamlFile); + + ControlLoopGuard result = Util.loadYamlGuard(tempYamlFile.getCanonicalPath()); + + assertEquals(clGuardPolicy, result); + } + + @Test + public void testLoadGuardYamlError() throws IOException { + File tempDir = Files.createTempDir(); + tempDir.deleteOnExit(); + + // Read from a directory forces an IO exception + assertNull(Util.loadYamlGuard(tempDir.getCanonicalPath())); + } + + @Test + public void testMisc() { + Util.setGuardEnvProp("Actor", "Judy Garland"); + assertEquals("Judy Garland", Util.getGuardProp("Actor")); + + Util.setGuardEnvProps("http://somewhere.over.the.rainbow", "Dorothy", "Toto"); + + assertEquals("http://somewhere.over.the.rainbow", Util.getGuardProp(Util.PROP_GUARD_URL)); + assertEquals("Dorothy", Util.getGuardProp(Util.PROP_GUARD_USER)); + assertEquals("Toto", Util.getGuardProp(Util.PROP_GUARD_PASS)); + } +} diff --git a/controlloop/m2/guard/src/test/java/org/onap/policy/guard/PolicyGuardRequestTest.java b/controlloop/m2/guard/src/test/java/org/onap/policy/guard/PolicyGuardRequestTest.java new file mode 100644 index 000000000..cdc862acb --- /dev/null +++ b/controlloop/m2/guard/src/test/java/org/onap/policy/guard/PolicyGuardRequestTest.java @@ -0,0 +1,59 @@ +/*- + * ============LICENSE_START======================================================= + * guard + * ================================================================================ + * Copyright (C) 2018 Ericsson. All rights reserved. + * ================================================================================ + * Modifications Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.guard; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.util.UUID; +import org.junit.Test; + +public class PolicyGuardRequestTest { + + private static final String KANSAS = "Kansas"; + private static final String GET_BACK_HOME = "GetBackHome"; + private static final String DOROTHY = "Dorothy"; + + @Test + public void testPolicyGuardRequest() { + UUID requestId = UUID.randomUUID(); + + assertNotNull(new PolicyGuardRequest(null, null, null, null)); + + PolicyGuardRequest request = new PolicyGuardRequest(DOROTHY, KANSAS, requestId, GET_BACK_HOME); + + request.setRequestId(requestId); + assertEquals(requestId, request.getRequestId()); + + request.setActor(DOROTHY); + assertEquals(DOROTHY, request.getActor()); + + request.setTarget(KANSAS); + assertEquals(KANSAS, request.getTarget()); + + request.setOperation(GET_BACK_HOME); + assertEquals(GET_BACK_HOME, request.getOperation()); + + assertEquals("PolicyGuardRequest [actor=Dorothy", request.toString().substring(0, 33)); + } +} diff --git a/controlloop/m2/guard/src/test/java/org/onap/policy/guard/PolicyGuardResponseTest.java b/controlloop/m2/guard/src/test/java/org/onap/policy/guard/PolicyGuardResponseTest.java new file mode 100644 index 000000000..629555297 --- /dev/null +++ b/controlloop/m2/guard/src/test/java/org/onap/policy/guard/PolicyGuardResponseTest.java @@ -0,0 +1,55 @@ +/*- + * ============LICENSE_START======================================================= + * guard + * ================================================================================ + * Copyright (C) 2018 Ericsson. All rights reserved. + * ================================================================================ + * Modifications Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.guard; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.util.UUID; +import org.junit.Test; + +public class PolicyGuardResponseTest { + + private static final String GET_BACK_HOME = "GetBackHome"; + private static final String BACK_HOME = "BackHome"; + + @Test + public void testPolicyGuardResponse() { + UUID requestId = UUID.randomUUID(); + + assertNotNull(new PolicyGuardResponse(null, null, null)); + + PolicyGuardResponse response = new PolicyGuardResponse(BACK_HOME, requestId, GET_BACK_HOME); + + response.setRequestId(requestId); + assertEquals(requestId, response.getRequestId()); + + response.setResult(BACK_HOME); + assertEquals(BACK_HOME, response.getResult()); + + response.setOperation(GET_BACK_HOME); + assertEquals(GET_BACK_HOME, response.getOperation()); + + assertEquals("PolicyGuardResponse [requestId=", response.toString().substring(0, 31)); + } +} diff --git a/controlloop/m2/guard/src/test/java/org/onap/policy/guard/PolicyGuardXacmlHelperTest.java b/controlloop/m2/guard/src/test/java/org/onap/policy/guard/PolicyGuardXacmlHelperTest.java new file mode 100644 index 000000000..47af1fbc6 --- /dev/null +++ b/controlloop/m2/guard/src/test/java/org/onap/policy/guard/PolicyGuardXacmlHelperTest.java @@ -0,0 +1,150 @@ +/*- + * ============LICENSE_START======================================================= + * guard + * ================================================================================ + * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.guard; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.util.Properties; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.onap.policy.common.endpoints.http.server.HttpServletServerFactoryInstance; +import org.onap.policy.drools.system.PolicyEngineConstants; +import org.onap.policy.drools.utils.logging.LoggerUtil; + +public class PolicyGuardXacmlHelperTest { + + private static final String TARGET = "target"; + private static final String REQUEST_ID = "requestId"; + private static final String RECIPE = "recipe"; + private static final String GUARD_URL = "guard.url"; + private static final String ACTOR = "actor"; + private static final Integer VF_COUNT = 100; + + /** + * Set up test class. + */ + @BeforeClass + public static void setupSimulator() throws Exception { + LoggerUtil.setLevel("ROOT", "INFO"); + LoggerUtil.setLevel("org.eclipse.jetty", "WARN"); + + HttpServletServerFactoryInstance.getServerFactory().destroy(); + org.onap.policy.simulators.Util.buildGuardSim(); + + // + // Set guard properties + // + org.onap.policy.guard.Util.setGuardEnvProps("http://localhost:6669/policy/pdpx/v1/decision", "python", "test"); + } + + /** + * Shuts down simulator and performs 1 more test for the case where the connection fails. + */ + @AfterClass + public static void tearDownSimulator() { + HttpServletServerFactoryInstance.getServerFactory().destroy(); + + // Null/ Bad Connection Case + PolicyGuardXacmlRequestAttributes xacmlReq = new PolicyGuardXacmlRequestAttributes( + org.onap.policy.simulators.GuardSimulatorJaxRs.DENY_CLNAME, ACTOR, RECIPE, TARGET, + REQUEST_ID, VF_COUNT); + String rawDecision = new PolicyGuardXacmlHelper().callPdp(xacmlReq); + assertNotNull(rawDecision); + assertEquals(Util.DENY, rawDecision); + } + + @Test + public void testSimulator() { + PolicyGuardXacmlRequestAttributes request = new PolicyGuardXacmlRequestAttributes("clname_id", "actor_id", + "operation_id", "target_id", "request_id", VF_COUNT); + String xacmlResponse = new PolicyGuardXacmlHelper().callPdp(request); + assertNotNull(xacmlResponse); + } + + @Test + /* + * Tests PolicyGuardXacmlHelper.callPdp method to determine if it returns DENY, PERMIT, or + * INDETERMINATE as expected. + */ + public void testCallPdp() { + // Deny Case + PolicyGuardXacmlRequestAttributes xacmlReq = new PolicyGuardXacmlRequestAttributes( + org.onap.policy.simulators.GuardSimulatorJaxRs.DENY_CLNAME, ACTOR, RECIPE, TARGET, + REQUEST_ID, VF_COUNT); + String rawDecision = new PolicyGuardXacmlHelper().callPdp(xacmlReq); + assertNotNull(rawDecision); + assertEquals(Util.DENY, rawDecision); + + // Permit Case + xacmlReq = new PolicyGuardXacmlRequestAttributes("clname", ACTOR, RECIPE, TARGET, REQUEST_ID, VF_COUNT); + rawDecision = new PolicyGuardXacmlHelper().callPdp(xacmlReq); + assertNotNull(rawDecision); + assertEquals(Util.PERMIT, rawDecision); + + // Indeterminate case is in tearDown for efficiency + } + + @Test + public void testInit() { + final Properties savedEnvironment = (Properties) PolicyEngineConstants.getManager().getEnvironment().clone(); + + assertNotNull(new PolicyGuardXacmlHelper()); + + PolicyEngineConstants.getManager().getEnvironment().setProperty(GUARD_URL, + "http://localhost:6669/pdp/api/getDecision,Dorothy"); + assertNotNull(new PolicyGuardXacmlHelper()); + + PolicyEngineConstants.getManager().getEnvironment().setProperty(GUARD_URL, + "http://localhost:6669/pdp/api/getDecision,Dorothy,Toto"); + assertNotNull(new PolicyGuardXacmlHelper()); + + PolicyEngineConstants.getManager().getEnvironment().setProperty(GUARD_URL, + "http://localhost:6969/policy/pdpx/v1/decision"); + + PolicyEngineConstants.getManager().getEnvironment().setProperty("pdpx.timeout", "thisIsNotANumber"); + assertNotNull(new PolicyGuardXacmlHelper()); + + PolicyEngineConstants.getManager().getEnvironment().setProperty("pdpx.timeout", "1000"); + assertNotNull(new PolicyGuardXacmlHelper()); + + PolicyEngineConstants.getManager().getEnvironment().remove("pdpx.password"); + assertNotNull(new PolicyGuardXacmlHelper()); + + PolicyEngineConstants.getManager().getEnvironment().setProperty("pdpx.username", "python"); + assertNotNull(new PolicyGuardXacmlHelper()); + + PolicyEngineConstants.getManager().getEnvironment().setProperty(GUARD_URL, "///"); + assertNotNull(new PolicyGuardXacmlHelper()); + + PolicyEngineConstants.getManager().getEnvironment().setProperty("guard.disabled", ""); + assertNotNull(new PolicyGuardXacmlHelper()); + + PolicyEngineConstants.getManager().getEnvironment().setProperty("guard.disabled", "true"); + assertNotNull(new PolicyGuardXacmlHelper()); + + PolicyEngineConstants.getManager().getEnvironment().clear(); + assertNotNull(new PolicyGuardXacmlHelper()); + + PolicyEngineConstants.getManager().setEnvironment(savedEnvironment); + } +} diff --git a/controlloop/m2/guard/src/test/java/org/onap/policy/guard/PolicyGuardXacmlRequestAttributesTest.java b/controlloop/m2/guard/src/test/java/org/onap/policy/guard/PolicyGuardXacmlRequestAttributesTest.java new file mode 100644 index 000000000..3d49d99c1 --- /dev/null +++ b/controlloop/m2/guard/src/test/java/org/onap/policy/guard/PolicyGuardXacmlRequestAttributesTest.java @@ -0,0 +1,74 @@ +/*- + * ============LICENSE_START======================================================= + * guard + * ================================================================================ + * Copyright (C) 2018 Ericsson. All rights reserved. + * ================================================================================ + * Modifications Copyright (C) 2018-2020 AT&T. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.guard; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.util.UUID; +import org.junit.Test; + +public class PolicyGuardXacmlRequestAttributesTest { + + @Test + public void testPolicyGuardXacmlRequestAttributes() { + PolicyGuardXacmlRequestAttributes attributes = + new PolicyGuardXacmlRequestAttributes(null, null, null, null, null, null); + assertNotNull(attributes); + + UUID requestId = UUID.randomUUID(); + attributes.setRequestId(requestId.toString()); + assertEquals(requestId.toString(), attributes.getRequestId()); + + UUID operationId = UUID.randomUUID(); + attributes.setOperationId(operationId.toString()); + assertEquals(operationId.toString(), attributes.getOperationId()); + + UUID actorId = UUID.randomUUID(); + attributes.setActorId(actorId.toString()); + assertEquals(actorId.toString(), attributes.getActorId()); + + UUID targetId = UUID.randomUUID(); + attributes.setTargetId(targetId.toString()); + assertEquals(targetId.toString(), attributes.getTargetId()); + + attributes.setTargetId(targetId.toString()); + assertEquals(targetId.toString(), attributes.getTargetId()); + + UUID controlLoopId = UUID.randomUUID(); + attributes.setClnameId(controlLoopId.toString()); + assertEquals(controlLoopId.toString(), attributes.getClnameId()); + + attributes.setClnameId(null); + assertEquals(null, attributes.getClnameId()); + + Integer vfCount = 20; + attributes.setVfCount(vfCount); + assertEquals(vfCount, attributes.getVfCount()); + + attributes.setVfCount(null); + assertEquals(null, attributes.getVfCount()); + + assertEquals("PolicyGuardXacmlRequestAttributes [actorId=", attributes.toString().substring(0, 43)); + } +} diff --git a/controlloop/m2/guard/src/test/java/org/onap/policy/guard/PolicyGuardYamlToXacmlTest.java b/controlloop/m2/guard/src/test/java/org/onap/policy/guard/PolicyGuardYamlToXacmlTest.java new file mode 100644 index 000000000..a8110ed04 --- /dev/null +++ b/controlloop/m2/guard/src/test/java/org/onap/policy/guard/PolicyGuardYamlToXacmlTest.java @@ -0,0 +1,248 @@ +/*- + * ============LICENSE_START======================================================= + * guard + * ================================================================================ + * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.guard; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import org.junit.Before; +import org.junit.Test; +import org.onap.policy.controlloop.policy.guard.Constraint; +import org.onap.policy.controlloop.policy.guard.ControlLoopGuard; +import org.onap.policy.controlloop.policy.guard.GuardPolicy; +import org.onap.policy.controlloop.policy.guard.MatchParameters; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.constructor.Constructor; + +public class PolicyGuardYamlToXacmlTest { + private static final String SOME_START_TIME = "someStartTime"; + private static final String SOME_END_TIME = "someEndTime"; + private static final String HOURS = "hours"; + private static final String TARGET2 = "WickedWitchOfTheWest"; + private static final String TARGET1 = "Wizard"; + private static final String ONAPPF_FILE = "ONAPPF"; + private static final String RECIPE = "GoToOz"; + private static final String TEXT1 = "WestWitches"; + private static final String TEXT2 = "EastWitches"; + private static final String OUT_XACML = ".out.xacml"; + private ControlLoopGuard clGuard; + + /** + * Set up test cases. + */ + @Before + public void createControlLoopGuard() { + clGuard = new ControlLoopGuard(); + MatchParameters matchParameters = new MatchParameters(); + matchParameters.setControlLoopName("WizardOfOz"); + matchParameters.setActor("Dorothy"); + matchParameters.setRecipe(RECIPE); + List<String> targets = new ArrayList<>(); + targets.add(TARGET1); + targets.add(TARGET2); + matchParameters.setTargets(targets); + GuardPolicy guardPolicy = new GuardPolicy(); + guardPolicy.setMatch_parameters(matchParameters); + Constraint limitConstraint = new Constraint(); + limitConstraint.setFreq_limit_per_target(5); + Map<String, String> timeWindow = new HashMap<>(); + timeWindow.put("value", "10"); + timeWindow.put("units", HOURS); + limitConstraint.setTime_window(timeWindow); + Map<String, String> activeTimeRange = new HashMap<>(); + activeTimeRange.put("start", SOME_START_TIME); + activeTimeRange.put("end", SOME_END_TIME); + limitConstraint.setActive_time_range(activeTimeRange); + LinkedList<Constraint> limitConstraints = new LinkedList<>(); + limitConstraints.add(limitConstraint); + guardPolicy.setLimit_constraints(limitConstraints); + LinkedList<GuardPolicy> guardList = new LinkedList<>(); + guardList.add(guardPolicy); + clGuard.setGuards(guardList); + } + + @Test + public void testGenerateXacmlGuardFull() throws IOException { + File tempYamlFile = File.createTempFile(ONAPPF_FILE, "yaml"); + tempYamlFile.deleteOnExit(); + + File tempXacmlTemplateFile = new File("src/test/resources/frequency_limiter_template.xml"); + + File tempXacmlOutputFile = File.createTempFile(ONAPPF_FILE, OUT_XACML); + tempXacmlOutputFile.deleteOnExit(); + + Yaml clYaml = new Yaml(new Constructor(ControlLoopGuard.class)); + String clYamlString = clYaml.dump(clGuard); + + SupportTextFileUtils.putStringAsFile(clYamlString, tempYamlFile); + PolicyGuardYamlToXacml.fromYamlToXacml(tempYamlFile.getCanonicalPath(), + tempXacmlTemplateFile.getCanonicalPath(), tempXacmlOutputFile.getCanonicalPath()); + + String result = SupportTextFileUtils.getTextFileAsString(tempXacmlOutputFile.getCanonicalPath()); + + // Assert no mote "${}" are left + assertFalse(result.contains("${")); + assertFalse(result.contains("}")); + // Assert all substitutions are made + assertTrue(result.contains("cl")); + assertTrue(result.contains("actor")); + assertTrue(result.contains(RECIPE)); + assertTrue(result.contains(TARGET1)); + assertTrue(result.contains(TARGET2)); + assertTrue(result.contains("10")); + assertTrue(result.contains(HOURS)); + assertTrue(result.contains(SOME_START_TIME)); + assertTrue(result.contains(SOME_END_TIME)); + } + + @Test + public void testGenerateXacmlGuardPartial() throws IOException { + final File tempYamlFile = File.createTempFile(ONAPPF_FILE, "yaml"); + tempYamlFile.deleteOnExit(); + + final File tempXacmlTemplateFile = new File("src/test/resources/frequency_limiter_template.xml"); + + final File tempXacmlOutputFile = File.createTempFile(ONAPPF_FILE, OUT_XACML); + tempXacmlOutputFile.deleteOnExit(); + + MatchParameters matchParameters = clGuard.getGuards().get(0).getMatch_parameters(); + matchParameters.setControlLoopName(null); + matchParameters.setActor(null); + matchParameters.setRecipe(null); + matchParameters.setTargets(null); + + Yaml clYaml = new Yaml(new Constructor(ControlLoopGuard.class)); + String clYamlString = clYaml.dump(clGuard); + + SupportTextFileUtils.putStringAsFile(clYamlString, tempYamlFile); + PolicyGuardYamlToXacml.fromYamlToXacml(tempYamlFile.getCanonicalPath(), + tempXacmlTemplateFile.getCanonicalPath(), tempXacmlOutputFile.getCanonicalPath()); + + String result = SupportTextFileUtils.getTextFileAsString(tempXacmlOutputFile.getCanonicalPath()); + + // Assert no mote "${}" are left + assertFalse(result.contains("${")); + assertFalse(result.contains("}")); + // Assert all substitutions are made + assertTrue(result.contains("cl")); + assertTrue(result.contains("actor")); + assertFalse(result.contains(RECIPE)); + assertFalse(result.contains(TARGET1)); + assertFalse(result.contains(TARGET2)); + assertTrue(result.contains("10")); + assertTrue(result.contains(HOURS)); + assertTrue(result.contains(SOME_START_TIME)); + assertTrue(result.contains(SOME_END_TIME)); + } + + @Test + public void testIsNullOrEmpty() { + assertTrue(PolicyGuardYamlToXacml.isNullOrEmpty("")); + assertTrue(PolicyGuardYamlToXacml.isNullOrEmpty(null)); + assertFalse(PolicyGuardYamlToXacml.isNullOrEmpty("hello")); + } + + @Test + public void testIsNullOrEmptyList() { + List<String> list = new ArrayList<>(); + assertTrue(PolicyGuardYamlToXacml.isNullOrEmptyList(null)); + assertTrue(PolicyGuardYamlToXacml.isNullOrEmptyList(list)); + + list.add("hello"); + assertFalse(PolicyGuardYamlToXacml.isNullOrEmptyList(list)); + } + + @Test + public void testGenerateXacmlGuardBlacklist() throws IOException { + final File tempYamlFile = File.createTempFile(ONAPPF_FILE, "yaml"); + tempYamlFile.deleteOnExit(); + + final File tempXacmlTemplateFile = new File("src/test/resources/blacklist_template.xml"); + + final File tempXacmlOutputFile = File.createTempFile(ONAPPF_FILE, OUT_XACML); + tempXacmlOutputFile.deleteOnExit(); + + List<String> blacklist = new ArrayList<>(); + blacklist.add(TEXT1); + blacklist.add(TEXT2); + clGuard.getGuards().get(0).getLimit_constraints().get(0).setBlacklist(blacklist); + + Yaml clYaml = new Yaml(new Constructor(ControlLoopGuard.class)); + String clYamlString = clYaml.dump(clGuard); + + SupportTextFileUtils.putStringAsFile(clYamlString, tempYamlFile); + PolicyGuardYamlToXacml.fromYamlToXacmlBlacklist(tempYamlFile.getCanonicalPath(), + tempXacmlTemplateFile.getCanonicalPath(), tempXacmlOutputFile.getCanonicalPath()); + + String result = SupportTextFileUtils.getTextFileAsString(tempXacmlOutputFile.getCanonicalPath()); + // Assert no mote "${}" are left + assertFalse(result.contains("${")); + assertFalse(result.contains("}")); + // Assert all substitutions are made + assertTrue(result.contains(TEXT1)); + assertTrue(result.contains(TEXT2)); + } + + @Test + public void testGenerateXacmlGuardBlacklistPartial() throws IOException { + final File tempYamlFile = File.createTempFile(ONAPPF_FILE, "yaml"); + tempYamlFile.deleteOnExit(); + + final File tempXacmlTemplateFile = new File("src/test/resources/blacklist_template.xml"); + + final File tempXacmlOutputFile = File.createTempFile(ONAPPF_FILE, OUT_XACML); + tempXacmlOutputFile.deleteOnExit(); + + List<String> blacklist = new ArrayList<>(); + blacklist.add(TEXT1); + blacklist.add(TEXT2); + GuardPolicy guardPolicy = clGuard.getGuards().get(0); + guardPolicy.getLimit_constraints().get(0).setBlacklist(blacklist); + + MatchParameters matchParameters = guardPolicy.getMatch_parameters(); + matchParameters.setControlLoopName(null); + matchParameters.setActor(null); + matchParameters.setRecipe(null); + matchParameters.setTargets(null); + + Yaml clYaml = new Yaml(new Constructor(ControlLoopGuard.class)); + String clYamlString = clYaml.dump(clGuard); + + SupportTextFileUtils.putStringAsFile(clYamlString, tempYamlFile); + PolicyGuardYamlToXacml.fromYamlToXacmlBlacklist(tempYamlFile.getCanonicalPath(), + tempXacmlTemplateFile.getCanonicalPath(), tempXacmlOutputFile.getCanonicalPath()); + + String result = SupportTextFileUtils.getTextFileAsString(tempXacmlOutputFile.getCanonicalPath()); + // Assert no mote "${}" are left + assertFalse(result.contains("${")); + assertFalse(result.contains("}")); + // Assert all substitutions are made + assertTrue(result.contains(TEXT1)); + assertTrue(result.contains(TEXT2)); + } +} diff --git a/controlloop/m2/guard/src/test/java/org/onap/policy/guard/SupportTextFileUtils.java b/controlloop/m2/guard/src/test/java/org/onap/policy/guard/SupportTextFileUtils.java new file mode 100644 index 000000000..98c33c761 --- /dev/null +++ b/controlloop/m2/guard/src/test/java/org/onap/policy/guard/SupportTextFileUtils.java @@ -0,0 +1,65 @@ +/*- + * ============LICENSE_START======================================================= + * guard + * ================================================================================ + * Copyright (C) 2018 Ericsson. All rights reserved. + * Modifications Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.guard; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import org.drools.core.util.IoUtils; + +/** + * The Class TextFileUtils is class that provides useful functions for handling text files. + * Functions to read and wrtie text files to strings and strings are provided. + * + * @author Liam Fallon (liam.fallon@ericsson.com) + */ +public class SupportTextFileUtils { + + private SupportTextFileUtils() { + // do nothing + } + + /** + * Method to return the contents of a text file as a string. + * + * @param textFilePath The path to the file as a string + * @return A string containing the contents of the file + * @throws IOException on errors reading text from the file + */ + public static String getTextFileAsString(final String textFilePath) { + return IoUtils.readFileAsString(new File(textFilePath)); + } + + /** + * Method to write contents of a string to a text file. + * + * @param outString The string to write + * @param textFile The file to write the string to + * @throws IOException on errors reading text from the file + */ + public static void putStringAsFile(final String outString, final File textFile) throws IOException { + try (final FileOutputStream textFileOutputStream = new FileOutputStream(textFile)) { + textFileOutputStream.write(outString.getBytes(StandardCharsets.UTF_8)); + } + } +} diff --git a/controlloop/m2/guard/src/test/resources/META-INF/persistence.xml b/controlloop/m2/guard/src/test/resources/META-INF/persistence.xml new file mode 100644 index 000000000..8e8be4ed2 --- /dev/null +++ b/controlloop/m2/guard/src/test/resources/META-INF/persistence.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ============LICENSE_START======================================================= + drools-applications + ================================================================================ + Copyright (C) 2018-2020 AT&T Intellectual Property. All rights reserved. + ================================================================================ + Licensed 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. + ============LICENSE_END========================================================= + --> +<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence persistence_1_0.xsd" version="1.0"> + + <!-- In-mem DB for junit --> + <persistence-unit name="OperationsHistoryPUTest" + transaction-type="RESOURCE_LOCAL"> + <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> + + <class>org.onap.policy.guard.OperationsHistory</class> + + <properties> + <property name="eclipselink.ddl-generation" value="create-tables" /> + <property name="eclipselink.logging.level" value="FINE" /> + <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/> + <property name="javax.persistence.jdbc.driver" value="org.h2.Driver" /> + <property name="javax.persistence.jdbc.url" value="jdbc:h2:mem:testdb;DATABASE_TO_UPPER=FALSE" /> + <property name="javax.persistence.jdbc.user" value="policy" /> + <property name="javax.persistence.jdbc.password" value="P01icY" /> + <property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/> + <property name="javax.persistence.schema-generation.create-source" value="metadata"/> + </properties> + </persistence-unit> + +</persistence> diff --git a/controlloop/m2/guard/src/test/resources/blacklist_template.xml b/controlloop/m2/guard/src/test/resources/blacklist_template.xml new file mode 100644 index 000000000..1563e4a7d --- /dev/null +++ b/controlloop/m2/guard/src/test/resources/blacklist_template.xml @@ -0,0 +1,117 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<!-- + ============LICENSE_START======================================================= + drools-applications + ================================================================================ + Copyright (C) 2018-2019 AT&T Intellectual Property. All rights reserved. + ================================================================================ + Licensed 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. + ============LICENSE_END========================================================= + --> +<Policy xmlns="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17" + PolicyId="urn:com:att:xacml:policy:id:25e12b06-11d5-4895-b2a2-6f6c594de069" + Version="1" + RuleCombiningAlgId="urn:oasis:names:tc:xacml:3.0:rule-combining-algorithm:permit-unless-deny"> + <Description>Policy for frequency limiter.</Description> + <Target> + <AnyOf> + <AllOf> + <Match + MatchId="urn:oasis:names:tc:xacml:1.0:function:string-regexp-match"> + <!-- <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">.*</AttributeValue>--> + <AttributeValue + DataType="http://www.w3.org/2001/XMLSchema#string">${clname}</AttributeValue> + <AttributeDesignator + Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject" + AttributeId="urn:org:onap:guard:clname:clname-id" + DataType="http://www.w3.org/2001/XMLSchema#string" + MustBePresent="false" /> + </Match> + + <!-- <Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">--> + <Match + MatchId="urn:oasis:names:tc:xacml:1.0:function:string-regexp-match"> + <AttributeValue + DataType="http://www.w3.org/2001/XMLSchema#string">${actor}</AttributeValue> + <AttributeDesignator + Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject" + AttributeId="urn:org:onap:guard:actor:actor-id" + DataType="http://www.w3.org/2001/XMLSchema#string" + MustBePresent="false" /> + </Match> + <Match + MatchId="urn:oasis:names:tc:xacml:1.0:function:string-regexp-match"> + <AttributeValue + DataType="http://www.w3.org/2001/XMLSchema#string">${recipe}</AttributeValue> + <AttributeDesignator + Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action" + AttributeId="urn:org:onap:guard:operation:operation-id" + DataType="http://www.w3.org/2001/XMLSchema#string" + MustBePresent="false" /> + </Match> + </AllOf> + </AnyOf> + </Target> + <Rule + RuleId="urn:com:att:xacml:rule:id:e1e8c5c0-e2ba-47d5-9289-6c015305ed21" + Effect="Deny"> + <Description>DENY - only if target is in black list and guard is + active.</Description> + <Condition> + <Apply + FunctionId="urn:oasis:names:tc:xacml:1.0:function:and"> + <VariableReference + VariableId="isGuardActive" /> + <VariableReference + VariableId="isInBlackList" /> + </Apply> + </Condition> + </Rule> + <VariableDefinition VariableId="isInBlackList"> + <Apply + FunctionId="urn:oasis:names:tc:xacml:3.0:function:any-of"> + <Function + FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-equal" /> + <Apply + FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-one-and-only"> + <AttributeDesignator + Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource" + AttributeId="urn:org:onap:guard:target:target-id" + DataType="http://www.w3.org/2001/XMLSchema#string" + MustBePresent="false" /> + </Apply> + <Apply + FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-bag"> + ${blackListElement} + <!-- <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">vserver.vserver-name</AttributeValue>--> + </Apply> + </Apply> + </VariableDefinition> + <VariableDefinition VariableId="isGuardActive"> + <Apply + FunctionId="urn:oasis:names:tc:xacml:2.0:function:time-in-range"> + <Apply + FunctionId="urn:oasis:names:tc:xacml:1.0:function:time-one-and-only"> + <AttributeDesignator + AttributeId="urn:oasis:names:tc:xacml:1.0:environment:current-time" + DataType="http://www.w3.org/2001/XMLSchema#time" + Category="urn:oasis:names:tc:xacml:3.0:attribute-category:environment" + MustBePresent="false" /> + </Apply> + <AttributeValue + DataType="http://www.w3.org/2001/XMLSchema#time">${guardActiveStart}</AttributeValue> + <AttributeValue + DataType="http://www.w3.org/2001/XMLSchema#time">${guardActiveEnd}</AttributeValue> + </Apply> + </VariableDefinition> +</Policy> diff --git a/controlloop/m2/guard/src/test/resources/frequency_limiter_template.xml b/controlloop/m2/guard/src/test/resources/frequency_limiter_template.xml new file mode 100644 index 000000000..d26432f86 --- /dev/null +++ b/controlloop/m2/guard/src/test/resources/frequency_limiter_template.xml @@ -0,0 +1,127 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<!-- + ============LICENSE_START======================================================= + drools-applications + ================================================================================ + Copyright (C) 2018-2019 AT&T Intellectual Property. All rights reserved. + ================================================================================ + Licensed 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. + ============LICENSE_END========================================================= + --> +<Policy xmlns="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17" + PolicyId="urn:com:att:xacml:policy:id:25e12b06-11d5-4895-b2a2-6f6c594de069" + Version="1" + RuleCombiningAlgId="urn:oasis:names:tc:xacml:3.0:rule-combining-algorithm:permit-unless-deny"> + <Description>Policy for frequency limiter.</Description> + <Target> + <AnyOf> + <AllOf> + + <Match + MatchId="urn:oasis:names:tc:xacml:1.0:function:string-regexp-match"> + <!-- <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">.*</AttributeValue>--> + <AttributeValue + DataType="http://www.w3.org/2001/XMLSchema#string">${clname}</AttributeValue> + <AttributeDesignator + Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject" + AttributeId="urn:org:onap:guard:clname:clname-id" + DataType="http://www.w3.org/2001/XMLSchema#string" + MustBePresent="false" /> + </Match> + + <!-- <Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">--> + <Match + MatchId="urn:oasis:names:tc:xacml:1.0:function:string-regexp-match"> + <AttributeValue + DataType="http://www.w3.org/2001/XMLSchema#string">${actor}</AttributeValue> + <AttributeDesignator + Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject" + AttributeId="urn:org:onap:guard:actor:actor-id" + DataType="http://www.w3.org/2001/XMLSchema#string" + MustBePresent="false" /> + </Match> + <Match + MatchId="urn:oasis:names:tc:xacml:1.0:function:string-regexp-match"> + <AttributeValue + DataType="http://www.w3.org/2001/XMLSchema#string">${recipe}</AttributeValue> + <AttributeDesignator + Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action" + AttributeId="urn:org:onap:guard:operation:operation-id" + DataType="http://www.w3.org/2001/XMLSchema#string" + MustBePresent="false" /> + </Match> + + <Match + MatchId="urn:oasis:names:tc:xacml:1.0:function:string-regexp-match"> + <AttributeValue + DataType="http://www.w3.org/2001/XMLSchema#string">${targets}</AttributeValue> + <AttributeDesignator + Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource" + AttributeId="urn:org:onap:guard:target:target-id" + DataType="http://www.w3.org/2001/XMLSchema#string" + MustBePresent="false" /> + </Match> + + </AllOf> + </AnyOf> + </Target> + <Rule + RuleId="urn:com:att:xacml:rule:id:e1e8c5c0-e2ba-47d5-9289-6c015305ed21" + Effect="Deny"> + <Description>DENY - only if number of operations performed in + the past is larger than the limit and the Guard is active.</Description> + <Condition> + <Apply + FunctionId="urn:oasis:names:tc:xacml:1.0:function:and"> + <VariableReference + VariableId="isGuardActive" /> + <VariableReference + VariableId="isHistoryGreaterThanLimit" /> + </Apply> + </Condition> + </Rule> + <VariableDefinition VariableId="isGuardActive"> + <Apply + FunctionId="urn:oasis:names:tc:xacml:2.0:function:time-in-range"> + <Apply + FunctionId="urn:oasis:names:tc:xacml:1.0:function:time-one-and-only"> + <AttributeDesignator + AttributeId="urn:oasis:names:tc:xacml:1.0:environment:current-time" + DataType="http://www.w3.org/2001/XMLSchema#time" + Category="urn:oasis:names:tc:xacml:3.0:attribute-category:environment" + MustBePresent="false" /> + </Apply> + <AttributeValue + DataType="http://www.w3.org/2001/XMLSchema#time">${guardActiveStart}</AttributeValue> + <AttributeValue + DataType="http://www.w3.org/2001/XMLSchema#time">${guardActiveEnd}</AttributeValue> + </Apply> + </VariableDefinition> + <VariableDefinition + VariableId="isHistoryGreaterThanLimit"> + <Apply + FunctionId="urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal"> + <Apply + FunctionId="urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only"> + <AttributeDesignator + Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource" + AttributeId="com:att:research:xacml:test:sql:resource:operations:count" + DataType="http://www.w3.org/2001/XMLSchema#integer" + Issuer="com:att:research:xacml:guard:historydb:tw:${twValue}:${twUnits}" + MustBePresent="false" /> + </Apply> + <AttributeValue + DataType="http://www.w3.org/2001/XMLSchema#integer">${limit}</AttributeValue> + </Apply> + </VariableDefinition> +</Policy> |