XACML pdp support for clc. 14/102514/5
authorpramod.jamkhedkar <pramod@research.att.com>
Thu, 27 Feb 2020 17:55:59 +0000 (12:55 -0500)
committerpramod.jamkhedkar <pramod@research.att.com>
Fri, 28 Feb 2020 16:47:41 +0000 (11:47 -0500)
Added policies for SON and PCI to support each blocking the other, with test cases and appropriate requests

Issue-ID: POLICY-2163
Change-Id: I8153f9cd973a7cd6824fcd6c9787628a74148d46
Signed-off-by: pramod.jamkhedkar <pramod@research.att.com>
applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/CoordinationGuardTranslator.java
applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/SonCoordinationTest.java [new file with mode: 0644]
applications/guard/src/test/resources/requests/coordination.cl.vPci.node.1.json [new file with mode: 0644]
applications/guard/src/test/resources/requests/coordination.cl.vSonh.node.1.json [new file with mode: 0644]
applications/guard/src/test/resources/test.policy.guard.coordination.vPciBlocksVsonh.tosca.yaml [new file with mode: 0644]
applications/guard/src/test/resources/test.policy.guard.coordination.vSonhBlocksVpci.tosca.yaml [new file with mode: 0644]

index eb86486..60fac49 100644 (file)
@@ -2,7 +2,7 @@
  * ============LICENSE_START=======================================================
  * ONAP
  * ================================================================================
- * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * 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.
@@ -94,12 +94,20 @@ public class CoordinationGuardTranslator implements ToscaPolicyTranslator {
         }
     }
 
+    /**
+     * This function is not used for CLC instead
+     * the one in LegacyGuardTranslator is used.
+     */
     @Override
     public Request convertRequest(DecisionRequest request) {
         LOGGER.info("this convertRequest shouldn't be used");
         return null;
     }
 
+    /**
+     * This function is not used for CLC instead
+     * the one in LegacyGuardTranslator is used.
+     */
     @Override
     public DecisionResponse convertResponse(Response xacmlResponse) {
         LOGGER.info("this convertResponse shouldn't be used");
@@ -112,13 +120,15 @@ public class CoordinationGuardTranslator implements ToscaPolicyTranslator {
      * @param directiveFilename yaml directive file to load
      * @return the CoordinationDirective
      */
-    public static CoordinationDirective loadCoordinationDirectiveFromFile(String directiveFilename) {
+    public static CoordinationDirective loadCoordinationDirectiveFromFile(
+        String directiveFilename) {
         try (InputStream is = new FileInputStream(new File(directiveFilename))) {
             String contents = IOUtils.toString(is, StandardCharsets.UTF_8);
             //
             // Read the yaml into our Java Object
             //
-            CoordinationDirective obj = new StandardYamlCoder().decode(contents, CoordinationDirective.class);
+            CoordinationDirective obj =
+                new StandardYamlCoder().decode(contents, CoordinationDirective.class);
             LOGGER.debug(contents);
             return obj;
         } catch (IOException | CoderException e) {
@@ -135,11 +145,12 @@ public class CoordinationGuardTranslator implements ToscaPolicyTranslator {
      * @return the generated Xacml policy
      */
     public static String generateXacmlFromCoordinationDirective(CoordinationDirective cd,
-                                                                String protoDir) throws ToscaPolicyConversionException {
+        String protoDir) throws ToscaPolicyConversionException {
         /*
          * Determine file names
          */
-        String xacmlProtoFilename = protoDir + File.separator + cd.getCoordinationFunction() + ".xml";
+        String xacmlProtoFilename =
+            protoDir + File.separator + cd.getCoordinationFunction() + ".xml";
         LOGGER.debug("xacmlProtoFilename={}", xacmlProtoFilename);
         /*
          * Values to be used for placeholders
@@ -156,8 +167,8 @@ public class CoordinationGuardTranslator implements ToscaPolicyTranslator {
                 .map(s -> s.replace("CONTROL_LOOP_TWO", cLTwo))
                 .collect(Collectors.joining(XacmlPolicyUtils.LINE_SEPARATOR));
         } catch (IOException e) {
-            throw new
-                ToscaPolicyConversionException("Error while generating XACML policy for coordination directive", e);
+            throw new ToscaPolicyConversionException(
+                "Error while generating XACML policy for coordination directive", e);
         }
     }
 
diff --git a/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/SonCoordinationTest.java b/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/SonCoordinationTest.java
new file mode 100644 (file)
index 0000000..e840bb7
--- /dev/null
@@ -0,0 +1,290 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.xacml.pdp.application.guard;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import com.att.research.xacml.api.Response;
+import java.io.File;
+import java.io.IOException;
+import java.sql.Date;
+import java.time.Instant;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+import java.util.ServiceLoader;
+import java.util.UUID;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Persistence;
+
+import org.apache.commons.lang3.tuple.Pair;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.junit.runners.MethodSorters;
+import org.onap.policy.common.endpoints.parameters.RestServerParameters;
+import org.onap.policy.common.utils.coder.CoderException;
+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.XacmlApplicationException;
+import org.onap.policy.pdp.xacml.application.common.XacmlApplicationServiceProvider;
+import org.onap.policy.pdp.xacml.application.common.XacmlPolicyUtils;
+import org.onap.policy.pdp.xacml.application.common.operationshistory.CountRecentOperationsPip;
+import org.onap.policy.pdp.xacml.application.common.operationshistory.Dbao;
+import org.onap.policy.pdp.xacml.xacmltest.TestUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class SonCoordinationTest {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(CoordinationTest.class);
+    private static Properties properties = new Properties();
+    private static File propertiesFile;
+    private static RestServerParameters clientParams = new RestServerParameters();
+    private static XacmlApplicationServiceProvider service;
+    private static DecisionRequest requestVpciNode1;
+    private static DecisionRequest requestVsonhNode1;
+    private static StandardCoder gson = new StandardCoder();
+    private static EntityManager em;
+    private static final String DENY = "Deny";
+    private static final String PERMIT = "Permit";
+    private static final String OPEN = "Success";
+    private static final String CLOSE = "Closed";
+
+    @ClassRule
+    public static final TemporaryFolder policyFolder = new TemporaryFolder();
+
+    /**
+     * Copies the xacml.properties and policies files into
+     * temporary folder and loads the service provider saving
+     * instance of provider off for other tests to use.
+     */
+    @BeforeClass
+    public static void setup() throws Exception {
+        LOGGER.info("Setting up class");
+        //
+        // Setup our temporary folder
+        //
+        XacmlPolicyUtils.FileCreator myCreator =
+            (String filename) -> policyFolder.newFile(filename);
+        propertiesFile = XacmlPolicyUtils.copyXacmlPropertiesContents(
+            "src/test/resources/xacml.properties", properties, myCreator);
+        //
+        // Load service
+        //
+        ServiceLoader<XacmlApplicationServiceProvider> applicationLoader =
+            ServiceLoader.load(XacmlApplicationServiceProvider.class);
+        //
+        // Find the guard service application and save for use in all the tests
+        //
+        StringBuilder strDump =
+            new StringBuilder("Loaded applications:" + XacmlPolicyUtils.LINE_SEPARATOR);
+        Iterator<XacmlApplicationServiceProvider> iterator = applicationLoader.iterator();
+        while (iterator.hasNext()) {
+            XacmlApplicationServiceProvider application = iterator.next();
+            //
+            // Is it our service?
+            //
+            if (application instanceof GuardPdpApplication) {
+                //
+                // Should be the first and only one
+                //
+                assertThat(service).isNull();
+                service = application;
+            }
+            strDump.append(application.applicationName());
+            strDump.append(" supports ");
+            strDump.append(application.supportedPolicyTypes());
+            strDump.append(XacmlPolicyUtils.LINE_SEPARATOR);
+        }
+        LOGGER.info("{}", strDump);
+        //
+        // Tell it to initialize based on the properties file
+        // we just built for it.
+        //
+        service.initialize(propertiesFile.toPath().getParent(), clientParams);
+        //
+        // Load Decision Requests
+        //
+        requestVpciNode1 = gson.decode(
+            TextFileUtils.getTextFileAsString(
+                "src/test/resources/requests/coordination.cl.vPci.node.1.json"),
+            DecisionRequest.class);
+        requestVsonhNode1 = gson.decode(
+            TextFileUtils.getTextFileAsString(
+                "src/test/resources/requests/coordination.cl.vSonh.node.1.json"),
+            DecisionRequest.class);
+        String persistenceUnit = CountRecentOperationsPip.ISSUER_NAME + ".persistenceunit";
+        em = Persistence
+            .createEntityManagerFactory(SonCoordinationTest.properties.getProperty(persistenceUnit),
+                properties)
+            .createEntityManager();
+    }
+
+    /**
+     * Clears the database before each test.
+     *
+     */
+    @Before
+    public void startClean() throws Exception {
+        em.getTransaction().begin();
+        em.createQuery("DELETE FROM Dbao").executeUpdate();
+        em.getTransaction().commit();
+    }
+
+    /**
+     * Close the entity manager.
+     */
+    @AfterClass
+    public static void cleanup() throws Exception {
+        if (em != null) {
+            em.close();
+        }
+    }
+
+    /**
+     * 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
+        //
+        Pair<DecisionResponse, Response> decision = service.makeDecision(request, null);
+        //
+        // Check decision
+        //
+        checkDecision(expected, decision.getKey());
+    }
+
+    @Test
+    public void test1() throws CoderException, IOException, XacmlApplicationException {
+        LOGGER.info("**************** Running vPci and vSonh Control Loops ****************");
+        //
+        // Now load the test coordination policy - make sure
+        // the pdp can support it and have it load
+        // into the PDP.
+        //
+        TestUtils.loadPolicies(
+            "src/test/resources/test.policy.guard.coordination.vPciBlocksVsonh.tosca.yaml",
+            service);
+        TestUtils.loadPolicies(
+            "src/test/resources/test.policy.guard.coordination.vSonhBlocksVpci.tosca.yaml",
+            service);
+        //
+        // vSonh doesn't have open action: vPci should get permit
+        //
+        requestAndCheckDecision(requestVpciNode1, PERMIT);
+        //
+        // vPci doesn't have open action: vSonh should get permit
+        //
+        requestAndCheckDecision(requestVsonhNode1, PERMIT);
+        //
+        // Open vSonh on node1
+        //
+        insertOperationEvent(requestVsonhNode1, OPEN);
+        //
+        // Under current coordination policy vPci should get a deny
+        //
+        requestAndCheckDecision(requestVpciNode1, DENY);
+        //
+        // Open vPci on node1
+        //
+        insertOperationEvent(requestVpciNode1, OPEN);
+        //
+        // Under current coordination policy vSonh should get a deny
+        //
+        requestAndCheckDecision(requestVsonhNode1, DENY);
+        //
+        // Close vSonh on node1
+        //
+        insertOperationEvent(requestVsonhNode1, CLOSE);
+        //
+        // With vSonh closed on node 1, vPci now should get a permit
+        //
+        requestAndCheckDecision(requestVpciNode1, PERMIT);
+        //
+        // Close cl1 on node1
+        //
+        insertOperationEvent(requestVpciNode1, CLOSE);
+        //
+        // With vPci closed on node 1, vSonh now should get a permit
+        //
+        requestAndCheckDecision(requestVsonhNode1, PERMIT);
+    }
+
+    @SuppressWarnings("unchecked")
+    private void insertOperationEvent(DecisionRequest request, String outcome) {
+        //
+        // Get the properties
+        //
+        Map<String, Object> properties = (Map<String, Object>) request.getResource().get("guard");
+        //
+        // Add an entry
+        //
+        Dbao newEntry = new Dbao();
+        newEntry.setActor(properties.get("actor").toString());
+        newEntry.setOperation(properties.get("recipe").toString());
+        newEntry.setClosedLoopName(properties.get("clname").toString());
+        newEntry.setOutcome(outcome);
+        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();
+    }
+
+}
diff --git a/applications/guard/src/test/resources/requests/coordination.cl.vPci.node.1.json b/applications/guard/src/test/resources/requests/coordination.cl.vPci.node.1.json
new file mode 100644 (file)
index 0000000..22e710b
--- /dev/null
@@ -0,0 +1,15 @@
+{
+    "ONAPName": "Policy",
+    "ONAPComponent": "drools-pdp",
+    "ONAPInstance": "usecase-template",
+    "requestId": "unique-request-id-47",
+    "action": "guard",
+    "resource": {
+        "guard": {
+            "actor": "SDNR",
+            "recipe": "ModifyConfig",
+            "clname": "ControlLoop-vPCI-fb41f388-a5f2-11e8-98d0-529269fb1459",
+            "target": "node1"
+        }
+    }
+}
diff --git a/applications/guard/src/test/resources/requests/coordination.cl.vSonh.node.1.json b/applications/guard/src/test/resources/requests/coordination.cl.vSonh.node.1.json
new file mode 100644 (file)
index 0000000..5846da3
--- /dev/null
@@ -0,0 +1,15 @@
+{
+    "ONAPName": "Policy",
+    "ONAPComponent": "drools-pdp",
+    "ONAPInstance": "usecase-template",
+    "requestId": "unique-request-id-47",
+    "action": "guard",
+    "resource": {
+        "guard": {
+            "actor": "SDNR",
+            "recipe": "ModifyConfigANR",
+            "clname": "ControlLoop-vSONH-7d4baf04-8875-4d1f-946d-06b874048b61",
+            "target": "node1"
+        }
+    }
+}
diff --git a/applications/guard/src/test/resources/test.policy.guard.coordination.vPciBlocksVsonh.tosca.yaml b/applications/guard/src/test/resources/test.policy.guard.coordination.vPciBlocksVsonh.tosca.yaml
new file mode 100644 (file)
index 0000000..d8ccec6
--- /dev/null
@@ -0,0 +1,14 @@
+tosca_definitions_version: tosca_simple_yaml_1_0_0
+topology_template:
+  policies:
+    -
+      guard.coordination.firstBlocksSecond.test:
+        type: onap.policies.controlloop.guard.coordination.FirstBlocksSecond
+        version: 1.0.0
+        metadata:
+          policy-id : guard.coordination.firstBlocksSecond.test
+          policy-version: 1
+        properties:
+          controlLoop:
+            - ControlLoop-vPCI-fb41f388-a5f2-11e8-98d0-529269fb1459
+            - ControlLoop-vSONH-7d4baf04-8875-4d1f-946d-06b874048b61
diff --git a/applications/guard/src/test/resources/test.policy.guard.coordination.vSonhBlocksVpci.tosca.yaml b/applications/guard/src/test/resources/test.policy.guard.coordination.vSonhBlocksVpci.tosca.yaml
new file mode 100644 (file)
index 0000000..5859d5e
--- /dev/null
@@ -0,0 +1,14 @@
+tosca_definitions_version: tosca_simple_yaml_1_0_0
+topology_template:
+  policies:
+    -
+      guard.coordination.firstBlocksSecond.test:
+        type: onap.policies.controlloop.guard.coordination.FirstBlocksSecond
+        version: 1.0.0
+        metadata:
+          policy-id : guard.coordination.firstBlocksSecond.test
+          policy-version: 1
+        properties:
+          controlLoop:
+            - ControlLoop-vSONH-7d4baf04-8875-4d1f-946d-06b874048b61
+            - ControlLoop-vPCI-fb41f388-a5f2-11e8-98d0-529269fb1459