From d2daf7ef5d003b5c5ae6a7083ccf676cc87a1d7b Mon Sep 17 00:00:00 2001 From: Pamela Dragosh Date: Wed, 27 Mar 2019 06:40:18 -0400 Subject: Adding guard PIP Adding the PIP support into the translator to setup the count attribute as an attribute generated by PIP and not sent by calling application. Added JUnit for OperationsHistoryPipEngine. Issue-ID: POLICY-1471 Change-Id: I71773ee8ea0e6c02873506d973a604899383d4b5 Signed-off-by: Pamela Dragosh --- .../guard/LegacyGuardPolicyRequest.java | 4 +- .../application/guard/LegacyGuardTranslator.java | 39 ++-- .../src/main/resources/META-INF/persistence.xml | 33 ++++ .../application/guard/GuardPdpApplicationTest.java | 205 ++++++++++++++------- .../src/test/resources/META-INF/createtest.sql | 16 ++ .../src/test/resources/META-INF/persistence.xml | 41 +++++ .../vDNS.policy.guard.frequency.output.tosca.yaml | 6 +- .../vDNS.policy.guard.minmax.output.tosca.yaml | 4 +- .../guard/src/test/resources/xacml.properties | 14 ++ 9 files changed, 268 insertions(+), 94 deletions(-) create mode 100644 applications/guard/src/main/resources/META-INF/persistence.xml create mode 100644 applications/guard/src/test/resources/META-INF/createtest.sql create mode 100644 applications/guard/src/test/resources/META-INF/persistence.xml (limited to 'applications/guard/src') diff --git a/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/LegacyGuardPolicyRequest.java b/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/LegacyGuardPolicyRequest.java index 0b5b5675..7346dded 100644 --- a/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/LegacyGuardPolicyRequest.java +++ b/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/LegacyGuardPolicyRequest.java @@ -138,8 +138,8 @@ public class LegacyGuardPolicyRequest { if (guard.containsKey("clname")) { request.clnameId = guard.get("clname").toString(); } - if (guard.containsKey("targets")) { - request.targetId = guard.get("targets").toString(); + if (guard.containsKey("target")) { + request.targetId = guard.get("target").toString(); } if (guard.containsKey("vfCount")) { request.vfCount = Integer.decode(guard.get("vfCount").toString()); diff --git a/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/LegacyGuardTranslator.java b/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/LegacyGuardTranslator.java index 81340b4d..48861d86 100644 --- a/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/LegacyGuardTranslator.java +++ b/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/LegacyGuardTranslator.java @@ -398,23 +398,16 @@ public class LegacyGuardTranslator implements ToscaPolicyTranslator { // Now combine into an And // ApplyType applyAnd = new ApplyType(); - applyAnd.setDescription("return true if all the apply's are true."); + applyAnd.setDescription("return true if time range and count checks are true."); applyAnd.setFunctionId(XACML3.ID_FUNCTION_AND.stringValue()); applyAnd.getExpression().add(new ObjectFactory().createApply(timeRange)); applyAnd.getExpression().add(new ObjectFactory().createApply(countCheck)); - // - // And create an outer negation of the And - // - ApplyType applyNot = new ApplyType(); - applyNot.setDescription("Negate the and"); - applyNot.setFunctionId(XACML3.ID_FUNCTION_NOT.stringValue()); - applyNot.getExpression().add(new ObjectFactory().createApply(applyAnd)); // // Create our condition // final ConditionType condition = new ConditionType(); - condition.setExpression(new ObjectFactory().createApply(applyNot)); + condition.setExpression(new ObjectFactory().createApply(applyAnd)); // // Now we can create our rule @@ -617,8 +610,8 @@ public class LegacyGuardTranslator implements ToscaPolicyTranslator { // // Right now I am faking the count value by re-using the request-id field // - //String issuer = "org:onap:xacml:guard:historydb:tw:" + timeWindow + ":" + timeUnits; - //designator.setIssuer(issuer); + String issuer = ToscaDictionary.GUARD_ISSUER + ":tw:" + timeWindow + ":" + timeUnits; + designator.setIssuer(issuer); AttributeValueType valueLimit = new AttributeValueType(); valueLimit.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue()); @@ -636,13 +629,13 @@ public class LegacyGuardTranslator implements ToscaPolicyTranslator { applyOneAndOnly.setFunctionId(XACML3.ID_FUNCTION_INTEGER_ONE_AND_ONLY.stringValue()); applyOneAndOnly.getExpression().add(factory.createAttributeDesignator(designator)); - ApplyType applyGreaterThanEqual = new ApplyType(); - applyGreaterThanEqual.setDescription("return true if current count is greater than or equal."); - applyGreaterThanEqual.setFunctionId(XACML3.ID_FUNCTION_INTEGER_GREATER_THAN_OR_EQUAL.stringValue()); - applyGreaterThanEqual.getExpression().add(factory.createApply(applyOneAndOnly)); - applyGreaterThanEqual.getExpression().add(factory.createAttributeValue(valueLimit)); + ApplyType applyLessThan = new ApplyType(); + applyLessThan.setDescription("return true if current count is less than."); + applyLessThan.setFunctionId(XACML3.ID_FUNCTION_INTEGER_LESS_THAN.stringValue()); + applyLessThan.getExpression().add(factory.createApply(applyOneAndOnly)); + applyLessThan.getExpression().add(factory.createAttributeValue(valueLimit)); - return applyGreaterThanEqual; + return applyLessThan; } private static ApplyType generateMinCheck(Integer min) { @@ -706,13 +699,13 @@ public class LegacyGuardTranslator implements ToscaPolicyTranslator { applyOneAndOnly.setFunctionId(XACML3.ID_FUNCTION_INTEGER_ONE_AND_ONLY.stringValue()); applyOneAndOnly.getExpression().add(factory.createAttributeDesignator(designator)); - ApplyType applyGreaterThanEqual = new ApplyType(); - applyGreaterThanEqual.setDescription("return true if current count is less than or equal."); - applyGreaterThanEqual.setFunctionId(XACML3.ID_FUNCTION_INTEGER_LESS_THAN_OR_EQUAL.stringValue()); - applyGreaterThanEqual.getExpression().add(factory.createApply(applyOneAndOnly)); - applyGreaterThanEqual.getExpression().add(factory.createAttributeValue(valueLimit)); + ApplyType applyLessThanEqual = new ApplyType(); + applyLessThanEqual.setDescription("return true if current count is less than or equal."); + applyLessThanEqual.setFunctionId(XACML3.ID_FUNCTION_INTEGER_LESS_THAN_OR_EQUAL.stringValue()); + applyLessThanEqual.getExpression().add(factory.createApply(applyOneAndOnly)); + applyLessThanEqual.getExpression().add(factory.createAttributeValue(valueLimit)); - return applyGreaterThanEqual; + return applyLessThanEqual; } private static AdviceExpressionsType generateRequestIdAdvice() { diff --git a/applications/guard/src/main/resources/META-INF/persistence.xml b/applications/guard/src/main/resources/META-INF/persistence.xml new file mode 100644 index 00000000..8d481a59 --- /dev/null +++ b/applications/guard/src/main/resources/META-INF/persistence.xml @@ -0,0 +1,33 @@ + + + + + + + org.eclipse.persistence.jpa.PersistenceProvider + + + + + + + + \ No newline at end of file diff --git a/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/GuardPdpApplicationTest.java b/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/GuardPdpApplicationTest.java index 981afee7..0e5d8593 100644 --- a/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/GuardPdpApplicationTest.java +++ b/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/GuardPdpApplicationTest.java @@ -29,6 +29,8 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; +import java.sql.Date; +import java.time.Instant; import java.util.HashMap; import java.util.Iterator; import java.util.Map; @@ -36,6 +38,11 @@ import java.util.Properties; import java.util.ServiceLoader; import java.util.UUID; +import javax.persistence.EntityManager; +import javax.persistence.Persistence; + +import org.junit.AfterClass; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.FixMethodOrder; @@ -47,6 +54,7 @@ import org.onap.policy.common.utils.coder.StandardCoder; import org.onap.policy.common.utils.resources.TextFileUtils; import org.onap.policy.models.decisions.concepts.DecisionRequest; import org.onap.policy.models.decisions.concepts.DecisionResponse; +import org.onap.policy.pdp.xacml.application.common.OnapOperationsHistoryDbao; import org.onap.policy.pdp.xacml.application.common.XacmlApplicationServiceProvider; import org.onap.policy.pdp.xacml.application.common.XacmlPolicyUtils; import org.slf4j.Logger; @@ -60,10 +68,13 @@ public class GuardPdpApplicationTest { private static Properties properties = new Properties(); private static File propertiesFile; private static XacmlApplicationServiceProvider service; - private static DecisionRequest requestGuardPermit; - private static DecisionRequest requestGuardDeny; - private static DecisionRequest requestGuardDeny2; + private static DecisionRequest requestVfCount1; + private static DecisionRequest requestVfCount3; + private static DecisionRequest requestVfCount6; private static StandardCoder gson = new StandardCoder(); + private static EntityManager em; + private static final String DENY = "Deny"; + private static final String PERMIT = "Permit"; @ClassRule public static final TemporaryFolder policyFolder = new TemporaryFolder(); @@ -115,30 +126,79 @@ public class GuardPdpApplicationTest { // we just built for it. // service.initialize(propertiesFile.toPath().getParent()); - } - - @Test - public void test1Basics() throws CoderException, IOException { - LOGGER.info("**************** Running test1 ****************"); // - // Load Single Decision Request + // Load Decision Requests // - requestGuardPermit = gson.decode( + requestVfCount1 = gson.decode( + TextFileUtils.getTextFileAsString( + "../../main/src/test/resources/decisions/decision.guard.vfCount.1.input.json"), + DecisionRequest.class); + requestVfCount3 = gson.decode( + TextFileUtils.getTextFileAsString( + "../../main/src/test/resources/decisions/decision.guard.vfCount.3.input.json"), + DecisionRequest.class); + requestVfCount6 = gson.decode( TextFileUtils.getTextFileAsString( - "../../main/src/test/resources/decisions/decision.guard.shouldpermit.input.json"), + "../../main/src/test/resources/decisions/decision.guard.vfCount.6.input.json"), DecisionRequest.class); // - // Load Single Decision Request + // Create EntityManager for manipulating DB + // + em = Persistence.createEntityManagerFactory( + GuardPdpApplicationTest.properties.getProperty("historydb.persistenceunit"), properties) + .createEntityManager(); + } + + /** + * Clears the database before each test. + * + */ + @Before + public void startClean() throws Exception { + em.getTransaction().begin(); + em.createQuery("DELETE FROM OnapOperationsHistoryDbao").executeUpdate(); + em.getTransaction().commit(); + } + + /** + * Check that decision matches expectation. + * + * @param expected from the response + * @param response received + * + **/ + public void checkDecision(String expected, DecisionResponse response) throws CoderException { + LOGGER.info("Looking for {} Decision", expected); + assertThat(response).isNotNull(); + assertThat(response.getStatus()).isNotNull(); + assertThat(response.getStatus()).isEqualTo(expected); + // + // Dump it out as Json + // + LOGGER.info(gson.encode(response)); + } + + /** + * Request a decision and check that it matches expectation. + * + * @param request to send to Xacml PDP + * @param expected from the response + * + **/ + public void requestAndCheckDecision(DecisionRequest request, String expected) throws CoderException { + // + // Ask for a decision // - requestGuardDeny = gson.decode(TextFileUtils.getTextFileAsString( - "../../main/src/test/resources/decisions/decision.guard.shoulddeny.input.json"), - DecisionRequest.class); + DecisionResponse response = service.makeDecision(request); // - // Load Single Decision Request + // Check decision // - requestGuardDeny2 = gson.decode(TextFileUtils.getTextFileAsString( - "../../main/src/test/resources/decisions/decision.guard.shoulddeny.input2.json"), - DecisionRequest.class); + checkDecision(expected, response); + } + + @Test + public void test1Basics() throws CoderException, IOException { + LOGGER.info("**************** Running test1 ****************"); // // Make sure there's an application name // @@ -164,16 +224,9 @@ public class GuardPdpApplicationTest { } @Test - public void test2NoPolicies() { + public void test2NoPolicies() throws CoderException { LOGGER.info("**************** Running test2 ****************"); - // - // Ask for a decision - // - DecisionResponse response = service.makeDecision(requestGuardPermit); - LOGGER.info("Decision {}", response); - - assertThat(response).isNotNull(); - assertThat(response.getStatus()).isEqualTo("Permit"); + requestAndCheckDecision(requestVfCount1,PERMIT); } @Test @@ -196,30 +249,25 @@ public class GuardPdpApplicationTest { service.loadPolicies(toscaObject); } // - // Ask for a decision - should get permit + // Zero recent actions: should get permit // - DecisionResponse response = service.makeDecision(requestGuardPermit); - LOGGER.info("Looking for Permit Decision {}", response); - - assertThat(response).isNotNull(); - assertThat(response.getStatus()).isNotNull(); - assertThat(response.getStatus()).isEqualTo("Permit"); + requestAndCheckDecision(requestVfCount1,PERMIT); // - // Dump it out as Json + // Add entry into operations history DB // - LOGGER.info(gson.encode(response)); + insertOperationEvent(requestVfCount1); // - // Ask for a decision - should get deny + // Only one recent actions: should get permit // - response = service.makeDecision(requestGuardDeny); - LOGGER.info("Looking for Deny Decision {}", response); - assertThat(response).isNotNull(); - assertThat(response.getStatus()).isNotNull(); - assertThat(response.getStatus()).isEqualTo("Deny"); + requestAndCheckDecision(requestVfCount1,PERMIT); // - // Dump it out as Json + // Add entry into operations history DB // - LOGGER.info(gson.encode(response)); + insertOperationEvent(requestVfCount1); + // + // Two recent actions, more than specified limit of 2: should get deny + // + requestAndCheckDecision(requestVfCount1,DENY); } @Test @@ -240,32 +288,32 @@ public class GuardPdpApplicationTest { // Load the policies // service.loadPolicies(toscaObject); - // - // Ask for a decision - should get permit - // } - DecisionResponse response = service.makeDecision(requestGuardPermit); - LOGGER.info("Looking for Permit Decision {}", response); - - assertThat(response).isNotNull(); - assertThat(response.getStatus()).isNotNull(); - assertThat(response.getStatus()).isEqualTo("Permit"); // - // Dump it out as Json + // vfcount=1 below min of 2: should get a Deny // - LOGGER.info(gson.encode(response)); + requestAndCheckDecision(requestVfCount1, DENY); // - // Ask for a decision - should get deny + // vfcount=3 between min of 2 and max of 5: should get a Permit // - response = service.makeDecision(requestGuardDeny); - LOGGER.info("Looking for Deny Decision {}", response); - assertThat(response).isNotNull(); - assertThat(response.getStatus()).isNotNull(); - assertThat(response.getStatus()).isEqualTo("Deny"); + requestAndCheckDecision(requestVfCount3, PERMIT); // - // Dump it out as Json + // vfcount=6 above max of 5: should get a Deny // - LOGGER.info(gson.encode(response)); + requestAndCheckDecision(requestVfCount6,DENY); + // + // Add two entry into operations history DB + // + insertOperationEvent(requestVfCount1); + insertOperationEvent(requestVfCount1); + // + // vfcount=3 between min of 2 and max of 5, but 2 recent actions is above frequency limit: should get a Deny + // + requestAndCheckDecision(requestVfCount3, DENY); + // + // vfcount=6 above max of 5: should get a Deny + // + requestAndCheckDecision(requestVfCount6, DENY); } @Test @@ -324,4 +372,33 @@ public class GuardPdpApplicationTest { assertThat(response.getStatus()).isEqualTo("Deny"); } } + + @SuppressWarnings("unchecked") + private void insertOperationEvent(DecisionRequest request) { + // + // Get the properties + // + Map properties = (Map) request.getResource().get("guard"); + assertThat(properties).isNotNull(); + // + // Add an entry + // + OnapOperationsHistoryDbao newEntry = new OnapOperationsHistoryDbao(); + newEntry.setActor(properties.get("actor").toString()); + newEntry.setOperation(properties.get("recipe").toString()); + newEntry.setClName(properties.get("clname").toString()); + newEntry.setOutcome("SUCCESS"); + newEntry.setStarttime(Date.from(Instant.now().minusMillis(20000))); + newEntry.setEndtime(Date.from(Instant.now())); + newEntry.setRequestId(UUID.randomUUID().toString()); + newEntry.setTarget(properties.get("target").toString()); + em.getTransaction().begin(); + em.persist(newEntry); + em.getTransaction().commit(); + } + + @AfterClass + public static void cleanup() throws Exception { + em.close(); + } } diff --git a/applications/guard/src/test/resources/META-INF/createtest.sql b/applications/guard/src/test/resources/META-INF/createtest.sql new file mode 100644 index 00000000..c7389f33 --- /dev/null +++ b/applications/guard/src/test/resources/META-INF/createtest.sql @@ -0,0 +1,16 @@ +# +# Create the operations history table +# +CREATE TABLE `operationshistory` + ( + `id` bigint not null, + `closedLoopName` varchar(255) not null, + `requestId` varchar(50) not null, + `subrequestId` varchar(50) not null, + `actor` varchar(50) not null, + `operation` varchar(50) not null, + `target` varchar(50) not null, + `starttime` timestamp not null, + `outcome` varchar(50) not null, + `message` varchar(255) not null, + `endtime` timestamp not null); diff --git a/applications/guard/src/test/resources/META-INF/persistence.xml b/applications/guard/src/test/resources/META-INF/persistence.xml new file mode 100644 index 00000000..de399c48 --- /dev/null +++ b/applications/guard/src/test/resources/META-INF/persistence.xml @@ -0,0 +1,41 @@ + + + + + + + org.eclipse.persistence.jpa.PersistenceProvider + org.onap.policy.pdp.xacml.application.common.OnapOperationsHistoryDbao + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/applications/guard/src/test/resources/vDNS.policy.guard.frequency.output.tosca.yaml b/applications/guard/src/test/resources/vDNS.policy.guard.frequency.output.tosca.yaml index a0552d42..fd414e13 100644 --- a/applications/guard/src/test/resources/vDNS.policy.guard.frequency.output.tosca.yaml +++ b/applications/guard/src/test/resources/vDNS.policy.guard.frequency.output.tosca.yaml @@ -7,14 +7,14 @@ topology_template: version: 1.0.0 metadata: policy-id: guard.frequency.scaleout - policy-version: 1 + policy-version: 1 properties: actor: SO recipe: VF Module Create targets: .* clname: ControlLoop-vDNS-6f37f56d-a87d-4b85-b6a9-cc953cf779b3 - limit: 1 + limit: 2 timeWindow: 10 timeUnits: minute - guardActiveStart: 00:00:01-05:00 + guardActiveStart: 00:00:00-05:00 guardActiveEnd: 23:59:59-05:00 diff --git a/applications/guard/src/test/resources/vDNS.policy.guard.minmax.output.tosca.yaml b/applications/guard/src/test/resources/vDNS.policy.guard.minmax.output.tosca.yaml index 97282a6f..88d2186e 100644 --- a/applications/guard/src/test/resources/vDNS.policy.guard.minmax.output.tosca.yaml +++ b/applications/guard/src/test/resources/vDNS.policy.guard.minmax.output.tosca.yaml @@ -13,7 +13,7 @@ topology_template: recipe: VF Module Create targets: .* clname: ControlLoop-vDNS-6f37f56d-a87d-4b85-b6a9-cc953cf779b3 - min: 1 + min: 2 max: 5 - guardActiveStart: 00:00:01-05:00 + guardActiveStart: 00:00:00-05:00 guardActiveEnd: 23:59:59-05:00 diff --git a/applications/guard/src/test/resources/xacml.properties b/applications/guard/src/test/resources/xacml.properties index 9bd7bfb8..d429a32e 100644 --- a/applications/guard/src/test/resources/xacml.properties +++ b/applications/guard/src/test/resources/xacml.properties @@ -24,6 +24,20 @@ xacml.att.policyFinderFactory=org.onap.policy.pdp.xacml.application.common.OnapP # xacml.att.policyFinderFactory.combineRootPolicies=urn:oasis:names:tc:xacml:3.0:policy-combining-algorithm:permit-unless-deny +xacml.pip.engines=historydb + +# +# PIP Engine Definition +# +historydb.classname=org.onap.policy.pdp.xacml.application.common.OnapOperationsHistoryPipEngine +historydb.issuer=urn:org:onap:xacml:guard:historydb +historydb.name=operationHistoryDB +historydb.description=Returns operation counts based on time window + +# +# Database persistence for PIP +# +historydb.persistenceunit=OperationsHistoryPUTest # Policies to load # -- cgit 1.2.3-korg