diff options
9 files changed, 932 insertions, 81 deletions
diff --git a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/XacmlPolicyUtils.java b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/XacmlPolicyUtils.java index c12aae2c..6f2a9f0e 100644 --- a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/XacmlPolicyUtils.java +++ b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/XacmlPolicyUtils.java @@ -52,6 +52,9 @@ import org.slf4j.LoggerFactory; public class XacmlPolicyUtils { private static final Logger LOGGER = LoggerFactory.getLogger(XacmlPolicyUtils.class); + + public static final String XACML_PROPERTY_FILE = "xacml.properties"; + private static final String DOT_FILE_SUFFIX = ".file"; private static final String NOT_FOUND_MESSAGE = "NOT FOUND"; @@ -403,7 +406,7 @@ public class XacmlPolicyUtils { * @return Path to rootPath/xacml.properties file */ public static Path getPropertiesPath(Path rootPath) { - return Paths.get(rootPath.toAbsolutePath().toString(), "xacml.properties"); + return Paths.get(rootPath.toAbsolutePath().toString(), XACML_PROPERTY_FILE); } @FunctionalInterface @@ -434,7 +437,7 @@ public class XacmlPolicyUtils { // // Now we create a new xacml.properties in the temporary folder location // - File propertiesFile = creator.createAFile("xacml.properties"); + File propertiesFile = creator.createAFile(XACML_PROPERTY_FILE); // // Iterate through any root policies defined // diff --git a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdCombinedPolicyRequest.java b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdCombinedPolicyRequest.java index 1acf741a..d7cf3f2d 100644 --- a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdCombinedPolicyRequest.java +++ b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdCombinedPolicyRequest.java @@ -43,6 +43,9 @@ import org.onap.policy.models.decisions.concepts.DecisionRequest; @XACMLRequest(ReturnPolicyIdList = true) public class StdCombinedPolicyRequest { + public static final String POLICY_TYPE_KEY = "policy-type"; + public static final String POLICY_ID_KEY = "policy-id"; + @XACMLSubject(includeInResults = true) private String onapName; @@ -92,7 +95,7 @@ public class StdCombinedPolicyRequest { // Map<String, Object> resources = decisionRequest.getResource(); for (Entry<String, Object> entrySet : resources.entrySet()) { - if ("policy-id".equals(entrySet.getKey())) { + if (POLICY_ID_KEY.equals(entrySet.getKey())) { if (entrySet.getValue() instanceof Collection) { addPolicyIds(request, (Collection) entrySet.getValue()); } else if (entrySet.getValue() instanceof String) { @@ -100,7 +103,7 @@ public class StdCombinedPolicyRequest { } continue; } - if ("policy-type".equals(entrySet.getKey())) { + if (POLICY_TYPE_KEY.equals(entrySet.getKey())) { if (entrySet.getValue() instanceof Collection) { addPolicyTypes(request, (Collection) entrySet.getValue()); } else if (entrySet.getValue() instanceof String) { diff --git a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchablePolicyRequest.java b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchablePolicyRequest.java index 086d21db..0e5edf84 100644 --- a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchablePolicyRequest.java +++ b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchablePolicyRequest.java @@ -44,6 +44,9 @@ import org.onap.policy.models.decisions.concepts.DecisionRequest; @XACMLRequest(ReturnPolicyIdList = true) public class StdMatchablePolicyRequest { + public static final String POLICY_TYPE_KEY = "policyType"; + public static final String POLICY_SCOPE_KEY = "policyScope"; + @XACMLSubject(includeInResults = true) private String onapName; @@ -103,7 +106,7 @@ public class StdMatchablePolicyRequest { // Its possible we may have to load the policy type model // and use that to find the fields that are matchable. // - if ("policyScope".equals(entrySet.getKey())) { + if (POLICY_SCOPE_KEY.equals(entrySet.getKey())) { if (entrySet.getValue() instanceof Collection) { addPolicyScopes(request, (Collection) entrySet.getValue()); } else if (entrySet.getValue() instanceof String) { @@ -111,7 +114,7 @@ public class StdMatchablePolicyRequest { } continue; } - if ("policyType".equals(entrySet.getKey())) { + if (POLICY_TYPE_KEY.equals(entrySet.getKey())) { if (entrySet.getValue() instanceof Collection) { addPolicyTypes(request, (Collection) entrySet.getValue()); } diff --git a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdOnapPip.java b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdOnapPip.java index 5336d572..c511a9ad 100644 --- a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdOnapPip.java +++ b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdOnapPip.java @@ -22,6 +22,7 @@ package org.onap.policy.pdp.xacml.application.common.std; import com.att.research.xacml.api.Attribute; import com.att.research.xacml.api.AttributeValue; +import com.att.research.xacml.api.DataTypeException; import com.att.research.xacml.api.Identifier; import com.att.research.xacml.api.XACML3; import com.att.research.xacml.api.pip.PIPException; @@ -104,16 +105,12 @@ public abstract class StdOnapPip extends StdConfigurableEngine { try { pipResponse = pipFinder.getMatchingAttributes(pipRequest, this); if (pipResponse.getStatus() != null && !pipResponse.getStatus().isOk()) { - if (logger.isInfoEnabled()) { - logger.info("get attribute error retrieving {}: {}", pipRequest.getAttributeId().stringValue(), - pipResponse.getStatus()); - } + logger.info("get attribute error retrieving {}: {}", pipRequest.getAttributeId().stringValue(), + pipResponse.getStatus()); pipResponse = null; } if (pipResponse != null && pipResponse.getAttributes().isEmpty()) { - if (logger.isInfoEnabled()) { - logger.info("No value for {}", pipRequest.getAttributeId().stringValue()); - } + logger.info("No value for {}", pipRequest.getAttributeId().stringValue()); pipResponse = null; } } catch (PIPException ex) { @@ -125,12 +122,10 @@ public abstract class StdOnapPip extends StdConfigurableEngine { protected String findFirstAttributeValue(PIPResponse pipResponse) { for (Attribute attribute: pipResponse.getAttributes()) { Iterator<AttributeValue<String>> iterAttributeValues = attribute.findValues(DataTypes.DT_STRING); - if (iterAttributeValues != null) { - while (iterAttributeValues.hasNext()) { - String value = iterAttributeValues.next().getValue(); - if (value != null) { - return value; - } + while (iterAttributeValues.hasNext()) { + String value = iterAttributeValues.next().getValue(); + if (value != null) { + return value; } } } @@ -141,7 +136,7 @@ public abstract class StdOnapPip extends StdConfigurableEngine { Identifier attributeId, int value, PIPRequest pipRequest) { AttributeValue<BigInteger> attributeValue = null; try { - attributeValue = DataTypes.DT_INTEGER.createAttributeValue(value); + attributeValue = makeInteger(value); } catch (Exception e) { logger.error("Failed to convert {} to integer {}", value, e); } @@ -155,7 +150,7 @@ public abstract class StdOnapPip extends StdConfigurableEngine { Identifier attributeId, long value, PIPRequest pipRequest) { AttributeValue<BigInteger> attributeValue = null; try { - attributeValue = DataTypes.DT_INTEGER.createAttributeValue(value); + attributeValue = makeLong(value); } catch (Exception e) { logger.error("Failed to convert {} to long {}", value, e); } @@ -169,7 +164,7 @@ public abstract class StdOnapPip extends StdConfigurableEngine { String value, PIPRequest pipRequest) { AttributeValue<String> attributeValue = null; try { - attributeValue = DataTypes.DT_STRING.createAttributeValue(value); + attributeValue = makeString(value); } catch (Exception ex) { logger.error("Failed to convert {} to an AttributeValue<String>", value, ex); } @@ -179,4 +174,18 @@ public abstract class StdOnapPip extends StdConfigurableEngine { } } + // these may be overridden by junit tests + + protected AttributeValue<BigInteger> makeInteger(int value) throws DataTypeException { + return DataTypes.DT_INTEGER.createAttributeValue(value); + } + + protected AttributeValue<BigInteger> makeLong(long value) throws DataTypeException { + return DataTypes.DT_INTEGER.createAttributeValue(value); + } + + protected AttributeValue<String> makeString(String value) throws DataTypeException { + return DataTypes.DT_STRING.createAttributeValue(value); + } + } diff --git a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdXacmlApplicationServiceProvider.java b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdXacmlApplicationServiceProvider.java index 1dd30ec4..89299567 100644 --- a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdXacmlApplicationServiceProvider.java +++ b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdXacmlApplicationServiceProvider.java @@ -29,21 +29,15 @@ import com.att.research.xacml.api.pdp.PDPEngineFactory; import com.att.research.xacml.api.pdp.PDPException; import com.att.research.xacml.util.FactoryException; import com.att.research.xacml.util.XACMLPolicyWriter; - import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; - import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType; - import org.apache.commons.lang3.tuple.Pair; import org.onap.policy.models.decisions.concepts.DecisionRequest; import org.onap.policy.models.decisions.concepts.DecisionResponse; @@ -87,29 +81,13 @@ public abstract class StdXacmlApplicationServiceProvider implements XacmlApplica this.pathForData = pathForData; LOGGER.info("New Path is {}", this.pathForData.toAbsolutePath()); // - // Ensure properties exist - // - Path propertiesPath = XacmlPolicyUtils.getPropertiesPath(pathForData); - if (! propertiesPath.toFile().exists()) { - LOGGER.info("Copying src/main/resources/xacml.properties to path"); - // - // Properties do not exist, by default we will copy ours over - // from src/main/resources - // - try { - Files.copy(Paths.get("src/main/resources/xacml.properties"), propertiesPath); - } catch (IOException e) { - throw new XacmlApplicationException("Failed to copy xacml.propertis", e); - } - } - // // Look for and load the properties object // try { pdpProperties = XacmlPolicyUtils.loadXacmlProperties(XacmlPolicyUtils.getPropertiesPath(pathForData)); LOGGER.info("{}", pdpProperties); } catch (IOException e) { - throw new XacmlApplicationException("Failed to load xacml.propertis", e); + throw new XacmlApplicationException("Failed to load " + XacmlPolicyUtils.XACML_PROPERTY_FILE, e); } // // Create an engine @@ -277,41 +255,6 @@ public abstract class StdXacmlApplicationServiceProvider implements XacmlApplica } /** - * Load properties from given file. - * - * @throws IOException If unable to read file - */ - protected synchronized Properties loadXacmlProperties() throws IOException { - LOGGER.info("Loading xacml properties {}", pathForData); - try (InputStream is = Files.newInputStream(pathForData)) { - Properties properties = new Properties(); - properties.load(is); - return properties; - } - } - - /** - * Stores the XACML Properties to the given file location. - * - * @throws IOException If unable to store the file. - */ - protected synchronized void storeXacmlProperties() throws IOException { - try (OutputStream os = Files.newOutputStream(pathForData)) { - String strComments = "#"; - pdpProperties.store(os, strComments); - } - } - - /** - * Appends 'xacml.properties' to a root Path object - * - * @return Path to rootPath/xacml.properties file - */ - protected synchronized Path getPropertiesPath() { - return Paths.get(pathForData.toAbsolutePath().toString(), "xacml.properties"); - } - - /** * Creates an instance of PDP engine given the Properties object. */ protected synchronized void createEngine(Properties properties) { @@ -319,7 +262,7 @@ public abstract class StdXacmlApplicationServiceProvider implements XacmlApplica // Now initialize the XACML PDP Engine // try { - PDPEngineFactory factory = PDPEngineFactory.newInstance(); + PDPEngineFactory factory = getPdpEngineFactory(); PDPEngine engine = factory.newEngine(properties); if (engine != null) { this.pdpEngine = engine; @@ -358,4 +301,9 @@ public abstract class StdXacmlApplicationServiceProvider implements XacmlApplica return response; } + // these may be overridden by junit tests + + protected PDPEngineFactory getPdpEngineFactory() throws FactoryException { + return PDPEngineFactory.newInstance(); + } } diff --git a/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdCombinedPolicyRequestTest.java b/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdCombinedPolicyRequestTest.java new file mode 100644 index 00000000..7d7d0e6b --- /dev/null +++ b/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdCombinedPolicyRequestTest.java @@ -0,0 +1,121 @@ +/*- + * ============LICENSE_START======================================================= + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.pdp.xacml.application.common.std; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.when; + +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.TreeMap; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.onap.policy.models.decisions.concepts.DecisionRequest; + +public class StdCombinedPolicyRequestTest { + private static final String ACTION = "my-action"; + private static final String ONAP_NAME = "my-name"; + private static final String ONAP_INSTANCE = "my-instance"; + private static final String ONAP_COMPONENT = "my-component"; + private static final String POLICY_ID = "my-policy"; + private static final String POLICY_TYPE = "my-type"; + + @Mock + private DecisionRequest decreq; + + private Map<String, Object> resources; + + private StdCombinedPolicyRequest stdreq; + + /** + * Initializes objects. + */ + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + resources = new TreeMap<>(); + + when(decreq.getResource()).thenReturn(resources); + when(decreq.getAction()).thenReturn(ACTION); + when(decreq.getOnapComponent()).thenReturn(ONAP_COMPONENT); + when(decreq.getOnapInstance()).thenReturn(ONAP_INSTANCE); + when(decreq.getOnapName()).thenReturn(ONAP_NAME); + } + + @Test + public void testCreateInstance() { + resources.put(StdCombinedPolicyRequest.POLICY_ID_KEY, 100); + resources.put(StdCombinedPolicyRequest.POLICY_TYPE_KEY, 101); + + stdreq = StdCombinedPolicyRequest.createInstance(decreq); + + assertNotNull(stdreq); + + assertEquals(ACTION, stdreq.getAction()); + assertEquals(ONAP_COMPONENT, stdreq.getOnapComponent()); + assertEquals(ONAP_INSTANCE, stdreq.getOnapInstance()); + assertEquals(ONAP_NAME, stdreq.getOnapName()); + + assertTrue(stdreq.getResource().isEmpty()); + assertTrue(stdreq.getResourcePolicyType().isEmpty()); + } + + @Test + public void testCreateInstance_StringValues() { + resources.put(StdCombinedPolicyRequest.POLICY_ID_KEY, POLICY_ID); + resources.put(StdCombinedPolicyRequest.POLICY_ID_KEY + "-x", "unused value"); + resources.put(StdCombinedPolicyRequest.POLICY_TYPE_KEY, POLICY_TYPE); + + stdreq = StdCombinedPolicyRequest.createInstance(decreq); + + Collection<String> res = stdreq.getResource(); + assertFalse(res.isEmpty()); + assertEquals(POLICY_ID, res.iterator().next()); + + res = stdreq.getResourcePolicyType(); + assertFalse(res.isEmpty()); + assertEquals(POLICY_TYPE, res.iterator().next()); + } + + @Test + public void testCreateInstance_Collections() { + resources.put(StdCombinedPolicyRequest.POLICY_ID_KEY, Collections.singleton(POLICY_ID)); + resources.put(StdCombinedPolicyRequest.POLICY_TYPE_KEY, Collections.singleton(POLICY_TYPE)); + + stdreq = StdCombinedPolicyRequest.createInstance(decreq); + + Collection<String> res = stdreq.getResource(); + assertFalse(res.isEmpty()); + assertEquals(POLICY_ID, res.iterator().next()); + + res = stdreq.getResourcePolicyType(); + assertFalse(res.isEmpty()); + assertEquals(POLICY_TYPE, res.iterator().next()); + } + +} diff --git a/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchablePolicyRequestTest.java b/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchablePolicyRequestTest.java new file mode 100644 index 00000000..00c86f25 --- /dev/null +++ b/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchablePolicyRequestTest.java @@ -0,0 +1,121 @@ +/*- + * ============LICENSE_START======================================================= + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.pdp.xacml.application.common.std; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.when; + +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.TreeMap; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.onap.policy.models.decisions.concepts.DecisionRequest; + +public class StdMatchablePolicyRequestTest { + private static final String ACTION = "my-action"; + private static final String ONAP_NAME = "my-name"; + private static final String ONAP_INSTANCE = "my-instance"; + private static final String ONAP_COMPONENT = "my-component"; + private static final String POLICY_SCOPE = "my-scope"; + private static final String POLICY_TYPE = "my-type"; + + @Mock + private DecisionRequest decreq; + + private Map<String, Object> resources; + + private StdMatchablePolicyRequest stdreq; + + /** + * Initializes objects. + */ + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + resources = new TreeMap<>(); + + when(decreq.getResource()).thenReturn(resources); + when(decreq.getAction()).thenReturn(ACTION); + when(decreq.getOnapComponent()).thenReturn(ONAP_COMPONENT); + when(decreq.getOnapInstance()).thenReturn(ONAP_INSTANCE); + when(decreq.getOnapName()).thenReturn(ONAP_NAME); + } + + @Test + public void testCreateInstance() { + resources.put(StdMatchablePolicyRequest.POLICY_SCOPE_KEY, 100); + resources.put(StdMatchablePolicyRequest.POLICY_TYPE_KEY, 101); + + stdreq = StdMatchablePolicyRequest.createInstance(decreq); + + assertNotNull(stdreq); + + assertEquals(ACTION, stdreq.getAction()); + assertEquals(ONAP_COMPONENT, stdreq.getOnapComponent()); + assertEquals(ONAP_INSTANCE, stdreq.getOnapInstance()); + assertEquals(ONAP_NAME, stdreq.getOnapName()); + + assertTrue(stdreq.getPolicyScopes().isEmpty()); + assertTrue(stdreq.getPolicyTypes().isEmpty()); + } + + @Test + public void testCreateInstance_StringValues() { + resources.put(StdMatchablePolicyRequest.POLICY_SCOPE_KEY, POLICY_SCOPE); + resources.put(StdMatchablePolicyRequest.POLICY_SCOPE_KEY + "-x", "unused value"); + resources.put(StdMatchablePolicyRequest.POLICY_TYPE_KEY, POLICY_TYPE); + + stdreq = StdMatchablePolicyRequest.createInstance(decreq); + + Collection<String> res = stdreq.getPolicyScopes(); + assertFalse(res.isEmpty()); + assertEquals(POLICY_SCOPE, res.iterator().next()); + + res = stdreq.getPolicyTypes(); + assertFalse(res.isEmpty()); + assertEquals(POLICY_TYPE, res.iterator().next()); + } + + @Test + public void testCreateInstance_Collections() { + resources.put(StdMatchablePolicyRequest.POLICY_SCOPE_KEY, Collections.singleton(POLICY_SCOPE)); + resources.put(StdMatchablePolicyRequest.POLICY_TYPE_KEY, Collections.singleton(POLICY_TYPE)); + + stdreq = StdMatchablePolicyRequest.createInstance(decreq); + + Collection<String> res = stdreq.getPolicyScopes(); + assertFalse(res.isEmpty()); + assertEquals(POLICY_SCOPE, res.iterator().next()); + + res = stdreq.getPolicyTypes(); + assertFalse(res.isEmpty()); + assertEquals(POLICY_TYPE, res.iterator().next()); + } + +} diff --git a/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdOnapPipTest.java b/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdOnapPipTest.java new file mode 100644 index 00000000..1a9901b5 --- /dev/null +++ b/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdOnapPipTest.java @@ -0,0 +1,314 @@ +/*- + * ============LICENSE_START======================================================= + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.pdp.xacml.application.common.std; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.att.research.xacml.api.Attribute; +import com.att.research.xacml.api.AttributeValue; +import com.att.research.xacml.api.DataTypeException; +import com.att.research.xacml.api.Identifier; +import com.att.research.xacml.api.Status; +import com.att.research.xacml.api.XACML3; +import com.att.research.xacml.api.pip.PIPException; +import com.att.research.xacml.api.pip.PIPFinder; +import com.att.research.xacml.api.pip.PIPRequest; +import com.att.research.xacml.api.pip.PIPResponse; +import com.att.research.xacml.std.datatypes.DataTypes; +import com.att.research.xacml.std.pip.StdMutablePIPResponse; +import java.math.BigInteger; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.Properties; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.onap.policy.pdp.xacml.application.common.ToscaDictionary; + +public class StdOnapPipTest { + private static final String EXPECTED_EXCEPTION = "expected exception"; + private static final String MY_ID = "my-id"; + private static final String ISSUER = "my-issuer"; + private static final String STRING_VALUE = "my-value"; + + private static final int INT_VALUE = 100; + private static final long LONG_VALUE = 200L; + + private static final Identifier CATEGORY = XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE; + private static final Identifier ATTRIBUTE_ID = ToscaDictionary.ID_RESOURCE_GUARD_ACTOR; + + @Mock + private PIPRequest request; + + @Mock + private PIPFinder finder; + + private StdMutablePIPResponse resp; + + private StdOnapPip pip; + + /** + * Initializes objects, including the PIP. + * + * @throws PIPException if an error occurs + */ + @Before + public void setUp() throws PIPException { + MockitoAnnotations.initMocks(this); + + resp = new StdMutablePIPResponse(); + + when(request.getIssuer()).thenReturn(ISSUER); + when(request.getAttributeId()).thenReturn(ATTRIBUTE_ID); + + pip = new MyPip(); + + when(finder.getMatchingAttributes(request, pip)).thenReturn(resp); + } + + @Test + public void testAttributesProvided() { + assertTrue(pip.attributesProvided().isEmpty()); + } + + @Test + public void testConfigureStringProperties() throws PIPException { + Properties props = new Properties(); + pip.configure(MY_ID, props); + + assertEquals(MY_ID, pip.getName()); + assertSame(props, pip.properties); + } + + @Test + public void testGetAttributePipFinderPipRequest_NullResponse() { + assertNull(pip.getAttribute(finder, request)); + } + + @Test + public void testGetAttributePipFinderPipRequest() { + pip.addStringAttribute(resp, CATEGORY, CATEGORY, STRING_VALUE, request); + + assertEquals(STRING_VALUE, pip.getAttribute(finder, request)); + } + + @Test + public void testGetAttributePipRequestPipFinder_NoStatus() { + resp.setStatus(null); + pip.addStringAttribute(resp, CATEGORY, CATEGORY, STRING_VALUE, request); + + assertSame(resp, pip.getAttribute(request, finder)); + } + + @Test + public void testGetAttributePipRequestPipFinder_StatusNotOk() { + Status status = mock(Status.class); + when(status.isOk()).thenReturn(false); + resp.setStatus(status); + + pip.addStringAttribute(resp, CATEGORY, CATEGORY, STRING_VALUE, request); + + assertNull(pip.getAttribute(request, finder)); + } + + @Test + public void testGetAttributePipRequestPipFinder_StatusOk() { + Status status = mock(Status.class); + when(status.isOk()).thenReturn(true); + resp.setStatus(status); + + pip.addStringAttribute(resp, CATEGORY, CATEGORY, STRING_VALUE, request); + + assertSame(resp, pip.getAttribute(request, finder)); + } + + @Test + public void testGetAttributePipRequestPipFinder_NoAttributes() { + assertNull(pip.getAttribute(request, finder)); + } + + @Test + public void testGetAttributePipRequestPipFinder_Ex() throws PIPException { + when(finder.getMatchingAttributes(request, pip)).thenThrow(new PIPException(EXPECTED_EXCEPTION)); + + pip.addStringAttribute(resp, CATEGORY, CATEGORY, STRING_VALUE, request); + + assertNull(pip.getAttribute(request, finder)); + } + + @Test + public void testFindFirstAttributeValue_NoAttributes() { + assertNull(pip.findFirstAttributeValue(resp)); + } + + @Test + public void testFindFirstAttributeValue_NullAttributeValue() { + pip.addIntegerAttribute(resp, CATEGORY, ATTRIBUTE_ID, INT_VALUE, request); + + assertNull(pip.findFirstAttributeValue(resp)); + } + + @Test + public void testFindFirstAttributeValue_NullValues() { + pip.addStringAttribute(resp, CATEGORY, ATTRIBUTE_ID, null, request); + pip.addStringAttribute(resp, CATEGORY, ATTRIBUTE_ID, STRING_VALUE, request); + pip.addStringAttribute(resp, CATEGORY, ATTRIBUTE_ID, null, request); + + assertEquals(STRING_VALUE, pip.findFirstAttributeValue(resp)); + } + + @Test + public void testAddIntegerAttribute() { + pip.addIntegerAttribute(resp, CATEGORY, ATTRIBUTE_ID, INT_VALUE, request); + assertEquals(1, resp.getAttributes().size()); + + Attribute attr = resp.getAttributes().iterator().next(); + assertEquals(ISSUER, attr.getIssuer()); + assertEquals(CATEGORY, attr.getCategory()); + assertEquals(ATTRIBUTE_ID, attr.getAttributeId()); + + Iterator<AttributeValue<BigInteger>> attrValues = attr.findValues(DataTypes.DT_INTEGER); + assertTrue(attrValues.hasNext()); + assertEquals(INT_VALUE, attrValues.next().getValue().intValue()); + } + + @Test + public void testAddIntegerAttribute_Ex() { + pip = new MyPip() { + @Override + protected AttributeValue<BigInteger> makeInteger(int value) throws DataTypeException { + throw new RuntimeException(EXPECTED_EXCEPTION); + } + }; + pip.addIntegerAttribute(resp, CATEGORY, ATTRIBUTE_ID, INT_VALUE, request); + assertEquals(0, resp.getAttributes().size()); + } + + @Test + public void testAddIntegerAttribute_Null() { + pip = new MyPip() { + @Override + protected AttributeValue<BigInteger> makeInteger(int value) throws DataTypeException { + return null; + } + }; + pip.addIntegerAttribute(resp, CATEGORY, ATTRIBUTE_ID, INT_VALUE, request); + assertEquals(0, resp.getAttributes().size()); + } + + @Test + public void testAddLongAttribute() { + pip.addLongAttribute(resp, CATEGORY, ATTRIBUTE_ID, LONG_VALUE, request); + assertEquals(1, resp.getAttributes().size()); + + Attribute attr = resp.getAttributes().iterator().next(); + assertEquals(ISSUER, attr.getIssuer()); + assertEquals(CATEGORY, attr.getCategory()); + assertEquals(ATTRIBUTE_ID, attr.getAttributeId()); + + Iterator<AttributeValue<BigInteger>> attrValues = attr.findValues(DataTypes.DT_INTEGER); + assertTrue(attrValues.hasNext()); + assertEquals(LONG_VALUE, attrValues.next().getValue().longValue()); + } + + @Test + public void testAddLongAttribute_Ex() { + pip = new MyPip() { + @Override + protected AttributeValue<BigInteger> makeLong(long value) throws DataTypeException { + throw new RuntimeException(EXPECTED_EXCEPTION); + } + }; + pip.addLongAttribute(resp, CATEGORY, ATTRIBUTE_ID, LONG_VALUE, request); + assertEquals(0, resp.getAttributes().size()); + } + + @Test + public void testAddLongAttribute_NullAttrValue() { + pip = new MyPip() { + @Override + protected AttributeValue<BigInteger> makeLong(long value) throws DataTypeException { + return null; + } + }; + pip.addLongAttribute(resp, CATEGORY, ATTRIBUTE_ID, LONG_VALUE, request); + assertEquals(0, resp.getAttributes().size()); + } + + @Test + public void testAddStringAttribute() { + pip.addStringAttribute(resp, CATEGORY, ATTRIBUTE_ID, STRING_VALUE, request); + assertEquals(1, resp.getAttributes().size()); + + Attribute attr = resp.getAttributes().iterator().next(); + assertEquals(ISSUER, attr.getIssuer()); + assertEquals(CATEGORY, attr.getCategory()); + assertEquals(ATTRIBUTE_ID, attr.getAttributeId()); + + Iterator<AttributeValue<String>> attrValues = attr.findValues(DataTypes.DT_STRING); + assertTrue(attrValues.hasNext()); + assertEquals(STRING_VALUE, attrValues.next().getValue()); + } + + @Test + public void testAddStringAttribute_Ex() { + pip = new MyPip() { + @Override + protected AttributeValue<String> makeString(String value) throws DataTypeException { + throw new RuntimeException(EXPECTED_EXCEPTION); + } + }; + pip.addStringAttribute(resp, CATEGORY, ATTRIBUTE_ID, STRING_VALUE, request); + assertEquals(0, resp.getAttributes().size()); + } + + @Test + public void testAddStringAttribute_NullAttrValue() { + pip = new MyPip() { + @Override + protected AttributeValue<String> makeString(String value) throws DataTypeException { + return null; + } + }; + pip.addStringAttribute(resp, CATEGORY, ATTRIBUTE_ID, STRING_VALUE, request); + assertEquals(0, resp.getAttributes().size()); + } + + private class MyPip extends StdOnapPip { + + @Override + public Collection<PIPRequest> attributesRequired() { + return Collections.emptyList(); + } + + @Override + public PIPResponse getAttributes(PIPRequest pipRequest, PIPFinder pipFinder) throws PIPException { + return null; + } + } +} diff --git a/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdXacmlApplicationServiceProviderTest.java b/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdXacmlApplicationServiceProviderTest.java new file mode 100644 index 00000000..8f44dedb --- /dev/null +++ b/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdXacmlApplicationServiceProviderTest.java @@ -0,0 +1,329 @@ +/*- + * ============LICENSE_START======================================================= + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.pdp.xacml.application.common.std; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.att.research.xacml.api.Request; +import com.att.research.xacml.api.Response; +import com.att.research.xacml.api.pdp.PDPEngine; +import com.att.research.xacml.api.pdp.PDPEngineFactory; +import com.att.research.xacml.api.pdp.PDPException; +import com.att.research.xacml.util.FactoryException; +import com.att.research.xacml.util.XACMLProperties; +import com.google.common.io.Files; +import java.io.File; +import java.nio.file.Path; +import java.util.HashSet; +import java.util.Properties; +import java.util.Set; +import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType; +import org.apache.commons.lang3.tuple.Pair; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.onap.policy.models.decisions.concepts.DecisionRequest; +import org.onap.policy.models.decisions.concepts.DecisionResponse; +import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; +import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException; +import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslator; +import org.onap.policy.pdp.xacml.application.common.XacmlApplicationException; +import org.onap.policy.pdp.xacml.application.common.XacmlPolicyUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class StdXacmlApplicationServiceProviderTest { + private static final Logger logger = LoggerFactory.getLogger(StdXacmlApplicationServiceProviderTest.class); + + private static final String TEMP_DIR_NAME = "src/test/resources/temp"; + private static File TEMP_DIR = new File(TEMP_DIR_NAME); + private static Path TEMP_PATH = TEMP_DIR.toPath(); + private static File SOURCE_PROP_FILE = new File("src/test/resources/test.properties"); + private static File PROP_FILE = new File(TEMP_DIR, XacmlPolicyUtils.XACML_PROPERTY_FILE); + private static final String EXPECTED_EXCEPTION = "expected exception"; + private static final String POLICY_NAME = "my-name"; + private static final String POLICY_VERSION = "1.2.3"; + private static final String POLICY_TYPE = "my-type"; + + @Mock + private ToscaPolicyTranslator trans; + + @Mock + private PDPEngineFactory engineFactory; + + @Mock + private PDPEngine engine; + + @Mock + private Request req; + + @Mock + private Response resp; + + private ToscaPolicy policy; + private PolicyType internalPolicy; + + private StdXacmlApplicationServiceProvider prov; + + /** + * Creates the temp directory. + */ + @BeforeClass + public static void setUpBeforeClass() { + assertTrue(TEMP_DIR.mkdir()); + } + + /** + * Deletes the temp directory and its contents. + */ + @AfterClass + public static void tearDownAfterClass() { + for (File file : TEMP_DIR.listFiles()) { + if (!file.delete()) { + logger.warn("cannot delete: {}", file); + } + } + + if (!TEMP_DIR.delete()) { + logger.warn("cannot delete: {}", TEMP_DIR); + } + } + + /** + * Initializes objects, including the provider. + * + * @throws Exception if an error occurs + */ + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + + policy = new ToscaPolicy(); + policy.setType(POLICY_TYPE); + policy.setName(POLICY_NAME); + policy.setVersion(POLICY_VERSION); + + internalPolicy = new PolicyType(); + internalPolicy.setPolicyId(POLICY_NAME); + internalPolicy.setVersion(POLICY_VERSION); + + when(engineFactory.newEngine(any())).thenReturn(engine); + + when(engine.decide(req)).thenReturn(resp); + + when(trans.convertPolicy(policy)).thenReturn(internalPolicy); + + prov = new MyProv(); + + Files.copy(SOURCE_PROP_FILE, PROP_FILE); + } + + @Test + public void testApplicationName() { + assertNotNull(prov.applicationName()); + } + + @Test + public void testActionDecisionsSupported() { + assertTrue(prov.actionDecisionsSupported().isEmpty()); + } + + @Test + public void testInitialize_testGetXxx() throws XacmlApplicationException { + prov.initialize(TEMP_PATH); + + assertEquals(TEMP_PATH, prov.getDataPath()); + assertNotNull(prov.getEngine()); + + Properties props = prov.getProperties(); + assertEquals("rootstart", props.getProperty("xacml.rootPolicies")); + } + + @Test + public void testInitialize_Ex() throws XacmlApplicationException { + assertThatThrownBy(() -> prov.initialize(new File(TEMP_DIR_NAME + "-nonExistent").toPath())) + .isInstanceOf(XacmlApplicationException.class).hasMessage("Failed to load xacml.properties"); + } + + @Test + public void testSupportedPolicyTypes() { + assertThatThrownBy(() -> prov.supportedPolicyTypes()).isInstanceOf(UnsupportedOperationException.class); + } + + @Test + public void testCanSupportPolicyType() { + assertThatThrownBy(() -> prov.canSupportPolicyType(null)).isInstanceOf(UnsupportedOperationException.class); + } + + @Test + public void testLoadPolicy_ConversionError() throws ToscaPolicyConversionException { + when(trans.convertPolicy(policy)).thenReturn(null); + + assertFalse(prov.loadPolicy(policy)); + } + + @Test + public void testLoadPolicy_testUnloadPolicy() throws Exception { + prov.initialize(TEMP_PATH); + PROP_FILE.delete(); + + final Set<String> set = XACMLProperties.getRootPolicyIDs(prov.getProperties()); + + assertTrue(prov.loadPolicy(policy)); + + // policy file should have been created + File policyFile = new File(TEMP_DIR, "my-name_1.2.3.xml"); + assertTrue(policyFile.exists()); + + // new property file should have been created + assertTrue(PROP_FILE.exists()); + + // should have re-created the engine + verify(engineFactory, times(2)).newEngine(any()); + + final Set<String> set2 = XACMLProperties.getRootPolicyIDs(prov.getProperties()); + assertEquals(set.size() + 1, set2.size()); + + Set<String> set3 = new HashSet<>(set2); + set3.removeAll(set); + assertEquals("[root1]", set3.toString()); + + + /* + * Prepare for unload. + */ + PROP_FILE.delete(); + + assertTrue(prov.unloadPolicy(policy)); + + // policy file should have been removed + assertFalse(policyFile.exists()); + + // new property file should have been created + assertTrue(PROP_FILE.exists()); + + // should have re-created the engine + verify(engineFactory, times(3)).newEngine(any()); + + set3 = XACMLProperties.getRootPolicyIDs(prov.getProperties()); + assertEquals(set.toString(), set3.toString()); + } + + @Test + public void testUnloadPolicy_NotDeployed() throws Exception { + prov.initialize(TEMP_PATH); + + assertFalse(prov.unloadPolicy(policy)); + + // no additional calls + verify(engineFactory, times(1)).newEngine(any()); + } + + @Test + public void testMakeDecision() { + prov.createEngine(null); + + DecisionRequest decreq = mock(DecisionRequest.class); + when(trans.convertRequest(decreq)).thenReturn(req); + + DecisionResponse decresp = mock(DecisionResponse.class); + when(trans.convertResponse(resp)).thenReturn(decresp); + + Pair<DecisionResponse, Response> result = prov.makeDecision(decreq); + assertSame(decresp, result.getKey()); + assertSame(resp, result.getValue()); + + verify(trans).convertRequest(decreq); + verify(trans).convertResponse(resp); + } + + @Test + public void testGetTranslator() { + assertSame(trans, prov.getTranslator()); + } + + @Test + public void testCreateEngine() throws FactoryException { + // success + prov.createEngine(null); + assertSame(engine, prov.getEngine()); + + // null - should be unchanged + when(engineFactory.newEngine(any())).thenReturn(null); + prov.createEngine(null); + assertSame(engine, prov.getEngine()); + + // exception - should be unchanged + when(engineFactory.newEngine(any())).thenThrow(new FactoryException(EXPECTED_EXCEPTION)); + prov.createEngine(null); + assertSame(engine, prov.getEngine()); + } + + @Test + public void testXacmlDecision() throws PDPException { + prov.createEngine(null); + + // success + assertSame(resp, prov.xacmlDecision(req)); + + // exception + when(engine.decide(req)).thenThrow(new PDPException(EXPECTED_EXCEPTION)); + assertNull(prov.xacmlDecision(req)); + } + + @Test + public void testGetPdpEngineFactory() throws XacmlApplicationException { + // use the real engine factory + engineFactory = null; + + prov = new MyProv(); + prov.initialize(TEMP_PATH); + + assertNotNull(prov.getEngine()); + } + + private class MyProv extends StdXacmlApplicationServiceProvider { + + @Override + protected ToscaPolicyTranslator getTranslator(String type) { + return trans; + } + + @Override + protected PDPEngineFactory getPdpEngineFactory() throws FactoryException { + return (engineFactory != null ? engineFactory : super.getPdpEngineFactory()); + } + } +} |