2  * ============LICENSE_START=======================================================
 
   4  * ================================================================================
 
   5  * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
 
   6  * Modifications Copyright (C) 2020 Nordix Foundation.
 
   7  * ================================================================================
 
   8  * Licensed under the Apache License, Version 2.0 (the "License");
 
   9  * you may not use this file except in compliance with the License.
 
  10  * You may obtain a copy of the License at
 
  12  *      http://www.apache.org/licenses/LICENSE-2.0
 
  14  * Unless required by applicable law or agreed to in writing, software
 
  15  * distributed under the License is distributed on an "AS IS" BASIS,
 
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
  17  * See the License for the specific language governing permissions and
 
  18  * limitations under the License.
 
  20  * SPDX-License-Identifier: Apache-2.0
 
  21  * ============LICENSE_END=========================================================
 
  24 package org.onap.policy.xacml.pdp.application.guard;
 
  26 import static org.assertj.core.api.Assertions.assertThat;
 
  27 import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
 
  29 import com.att.research.xacml.api.Decision;
 
  30 import com.att.research.xacml.api.Request;
 
  31 import com.att.research.xacml.api.XACML3;
 
  32 import com.att.research.xacml.std.StdMutableResponse;
 
  33 import com.att.research.xacml.std.StdMutableResult;
 
  34 import com.att.research.xacml.std.StdStatus;
 
  35 import com.att.research.xacml.std.StdStatusCode;
 
  36 import com.att.research.xacml.util.XACMLPolicyWriter;
 
  37 import java.io.ByteArrayOutputStream;
 
  38 import java.util.HashMap;
 
  39 import java.util.LinkedHashMap;
 
  41 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AllOfType;
 
  42 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AnyOfType;
 
  43 import oasis.names.tc.xacml._3_0.core.schema.wd_17.MatchType;
 
  44 import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType;
 
  45 import oasis.names.tc.xacml._3_0.core.schema.wd_17.RuleType;
 
  46 import org.junit.Test;
 
  47 import org.onap.policy.common.utils.coder.StandardCoder;
 
  48 import org.onap.policy.common.utils.coder.StandardYamlCoder;
 
  49 import org.onap.policy.common.utils.resources.ResourceUtils;
 
  50 import org.onap.policy.common.utils.resources.TextFileUtils;
 
  51 import org.onap.policy.models.decisions.concepts.DecisionRequest;
 
  52 import org.onap.policy.models.decisions.concepts.DecisionResponse;
 
  53 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
 
  54 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
 
  55 import org.onap.policy.models.tosca.simple.concepts.JpaToscaServiceTemplate;
 
  56 import org.onap.policy.pdp.xacml.application.common.ToscaDictionary;
 
  57 import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException;
 
  58 import org.slf4j.Logger;
 
  59 import org.slf4j.LoggerFactory;
 
  61 public class GuardTranslatorTest {
 
  62     private static final Logger LOGGER = LoggerFactory.getLogger(GuardTranslatorTest.class);
 
  63     private static final StandardYamlCoder yamlCoder = new StandardYamlCoder();
 
  64     private static StandardCoder gson = new StandardCoder();
 
  66     private GuardTranslator translator = new GuardTranslator();
 
  69     public void testRequest() throws Exception {
 
  70         DecisionRequest decisionRequest = gson.decode(
 
  71                 TextFileUtils.getTextFileAsString(
 
  72                         "src/test/resources/requests/guard.vfCount.json"),
 
  73                         DecisionRequest.class);
 
  74         Request xacmlRequest = translator.convertRequest(decisionRequest);
 
  76         assertThat(xacmlRequest).isNotNull();
 
  80     public void testResponse() {
 
  81         StdStatus status = new StdStatus(StdStatusCode.STATUS_CODE_OK);
 
  82         StdMutableResult result = new StdMutableResult(Decision.PERMIT, status);
 
  83         StdMutableResponse response = new StdMutableResponse(result);
 
  85         DecisionResponse decisionResponse = translator.convertResponse(response);
 
  86         assertThat(decisionResponse).isNotNull();
 
  87         assertThat(decisionResponse.getStatus()).isEqualTo(Decision.PERMIT.toString());
 
  89         result = new StdMutableResult(Decision.DENY, status);
 
  90         response = new StdMutableResponse(result);
 
  91         decisionResponse = translator.convertResponse(response);
 
  92         assertThat(decisionResponse).isNotNull();
 
  93         assertThat(decisionResponse.getStatus()).isEqualTo(Decision.DENY.toString());
 
  95         result = new StdMutableResult(Decision.INDETERMINATE, status);
 
  96         response = new StdMutableResponse(result);
 
  97         decisionResponse = translator.convertResponse(response);
 
  98         assertThat(decisionResponse).isNotNull();
 
  99         assertThat(decisionResponse.getStatus()).isEqualTo(Decision.PERMIT.toString());
 
 104     public void testBadPolicies() throws Exception {
 
 105         String policyYaml = ResourceUtils.getResourceAsString("src/test/resources/test-bad-policies.yaml");
 
 107         // Serialize it into a class
 
 109         ToscaServiceTemplate serviceTemplate = yamlCoder.decode(policyYaml, ToscaServiceTemplate.class);
 
 111         // Make sure all the fields are setup properly
 
 113         JpaToscaServiceTemplate jtst = new JpaToscaServiceTemplate();
 
 114         jtst.fromAuthorative(serviceTemplate);
 
 115         final ToscaServiceTemplate completedJtst = jtst.toAuthorative();
 
 117         // Expected message for given policy name
 
 119         final Map<String, String> name2message = new HashMap<>();
 
 120         name2message.put("frequency-missing-properties", "Missing property limit");
 
 121         name2message.put("frequency-timewindow", "timeWindow is not an integer");
 
 122         name2message.put("minmax-notarget", "Missing target field in minmax policy");
 
 123         name2message.put("minmax-nominmax", "Missing min or max field in minmax policy");
 
 124         name2message.put("blacklist-noblacklist", "Missing blacklist");
 
 125         name2message.put("filter-noalgorithm", "Missing algorithm");
 
 126         name2message.put("filter-badalgorithm",
 
 127                             "Unexpected value for algorithm, should be whitelist-overrides or blacklist-overrides");
 
 128         name2message.put("filter-nofilter", "Missing filters");
 
 129         name2message.put("filter-nocollection", "Filters is not a collection");
 
 130         name2message.put("filter-noarray", "Filters is not a collection");
 
 131         name2message.put("filter-missingfield", "Missing \'field\' from filter");
 
 132         name2message.put("filter-badfield", "Unexpected value for field in filter");
 
 133         name2message.put("filter-missingfilter", "Missing \'filter\' from filter");
 
 134         name2message.put("filter-missingfunction", "Missing \'function\' from filter");
 
 135         name2message.put("filter-badfunction", "Unexpected value for function in filter");
 
 136         name2message.put("filter-missingblacklist", "Missing \'blacklist\' from filter");
 
 137         name2message.put("filter-badblacklist", "Unexpected value for blacklist in filter");
 
 141         for (Map<String, ToscaPolicy> policies : completedJtst.getToscaTopologyTemplate().getPolicies()) {
 
 142             for (ToscaPolicy policy : policies.values()) {
 
 143                 LOGGER.info("Testing policy " + policy.getName());
 
 144                 String expectedMsg = name2message.get(policy.getName());
 
 145                 assertThat(expectedMsg).as(policy.getName()).isNotNull();
 
 147                 assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
 
 148                     translator.convertPolicy(policy)
 
 149                 ).withMessageContaining(expectedMsg);
 
 155     public void testPolicyConversion() throws Exception {
 
 156         String policyYaml = ResourceUtils.getResourceAsString("src/test/resources/test-policies.yaml");
 
 158         // Serialize it into a class
 
 160         ToscaServiceTemplate serviceTemplate = yamlCoder.decode(policyYaml, ToscaServiceTemplate.class);
 
 162         // Make sure all the fields are setup properly
 
 164         JpaToscaServiceTemplate jtst = new JpaToscaServiceTemplate();
 
 165         jtst.fromAuthorative(serviceTemplate);
 
 166         ToscaServiceTemplate completedJtst = jtst.toAuthorative();
 
 170         for (Map<String, ToscaPolicy> policies : completedJtst.getToscaTopologyTemplate().getPolicies()) {
 
 171             for (ToscaPolicy policy : policies.values()) {
 
 173                 // Convert the policy
 
 175                 if ("onap.policies.controlloop.guard.common.Unknown".equals(policy.getType())) {
 
 176                     assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
 
 177                         translator.convertPolicy(policy));
 
 180                 PolicyType xacmlPolicy = (PolicyType) translator.convertPolicy(policy);
 
 181                 assertThat(xacmlPolicy).isNotNull();
 
 185                 ByteArrayOutputStream os = new ByteArrayOutputStream();
 
 186                 XACMLPolicyWriter.writePolicyFile(os, xacmlPolicy);
 
 187                 LOGGER.info(os.toString());
 
 189                 // Validate the policy
 
 191                 assertThat(xacmlPolicy.getPolicyId()).isEqualTo(policy.getName());
 
 192                 assertThat(xacmlPolicy.getVersion()).isEqualTo(policy.getVersion());
 
 193                 assertThat(xacmlPolicy.getRuleCombiningAlgId()).isNotNull();
 
 194                 validateCommon(policy, xacmlPolicy);
 
 196                 // Validate each policy type
 
 198                 if (GuardTranslator.POLICYTYPE_FREQUENCY.equals(policy.getType())) {
 
 199                     validateFrequency(policy, xacmlPolicy);
 
 200                 } else if (GuardTranslator.POLICYTYPE_MINMAX.equals(policy.getType())) {
 
 201                     validateMinMax(policy, xacmlPolicy);
 
 202                 } else if (GuardTranslator.POLICYTYPE_BLACKLIST.equals(policy.getType())) {
 
 203                     validateBlacklist(policy, xacmlPolicy);
 
 204                 } else if (GuardTranslator.POLICYTYPE_FILTER.equals(policy.getType())) {
 
 205                     validateFilter(policy, xacmlPolicy);
 
 210         ToscaPolicy testPol = completedJtst.getToscaTopologyTemplate().getPolicies().get(0).values().iterator().next();
 
 212         testPol.setProperties(new LinkedHashMap<>());
 
 213         assertThatExceptionOfType(ToscaPolicyConversionException.class)
 
 214                 .isThrownBy(() -> translator.convertPolicy(testPol));
 
 216         testPol.setProperties(null);
 
 217         assertThatExceptionOfType(ToscaPolicyConversionException.class)
 
 218                 .isThrownBy(() -> translator.convertPolicy(testPol));
 
 221     private void validateCommon(ToscaPolicy policy, PolicyType xacmlPolicy) {
 
 222         boolean foundActor = false;
 
 223         boolean foundOperation = false;
 
 224         boolean foundTarget = false;
 
 225         boolean foundControlLoop = false;
 
 226         boolean foundTimeRange = false;
 
 228         assertThat(xacmlPolicy.getTarget()).isNotNull();
 
 229         assertThat(xacmlPolicy.getTarget().getAnyOf()).isNotEmpty();
 
 230         for (AnyOfType anyOf : xacmlPolicy.getTarget().getAnyOf()) {
 
 231             assertThat(anyOf.getAllOf()).isNotEmpty();
 
 232             for (AllOfType allOf : anyOf.getAllOf()) {
 
 233                 assertThat(allOf.getMatch()).isNotEmpty();
 
 234                 for (MatchType match : allOf.getMatch()) {
 
 236                     // These fields are required
 
 238                     if (ToscaDictionary.ID_RESOURCE_GUARD_ACTOR.toString().equals(
 
 239                             match.getAttributeDesignator().getAttributeId())) {
 
 240                         assertThat(match.getAttributeValue().getContent()).isNotNull();
 
 242                     } else if (ToscaDictionary.ID_RESOURCE_GUARD_RECIPE.toString().equals(
 
 243                             match.getAttributeDesignator().getAttributeId())) {
 
 244                         assertThat(match.getAttributeValue().getContent()).isNotNull();
 
 245                         foundOperation = true;
 
 248                         // These fields are optional
 
 250                         if (ToscaDictionary.ID_RESOURCE_GUARD_TARGETID.toString().equals(
 
 251                                 match.getAttributeDesignator().getAttributeId())) {
 
 252                             assertThat(policy.getProperties()).containsKey("target");
 
 255                         if (ToscaDictionary.ID_RESOURCE_GUARD_CLNAME.toString().equals(
 
 256                                 match.getAttributeDesignator().getAttributeId())) {
 
 257                             assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_CONTROLLOOP);
 
 258                             foundControlLoop = true;
 
 260                         if (XACML3.ID_ENVIRONMENT_CURRENT_TIME.toString().equals(
 
 261                                 match.getAttributeDesignator().getAttributeId())) {
 
 262                             assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_TIMERANGE);
 
 263                             foundTimeRange = true;
 
 269         assertThat(foundActor && foundOperation).isTrue();
 
 270         if (policy.getProperties().containsKey("target")) {
 
 271             assertThat(foundTarget).isTrue();
 
 273         if (policy.getProperties().containsKey(GuardTranslator.FIELD_CONTROLLOOP)) {
 
 274             assertThat(foundControlLoop).isTrue();
 
 276         if (policy.getProperties().containsKey(GuardTranslator.FIELD_TIMERANGE)) {
 
 277             assertThat(foundTimeRange).isTrue();
 
 281     private void validateFrequency(ToscaPolicy policy, PolicyType xacmlPolicy) {
 
 282         for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) {
 
 283             if (! (rule instanceof RuleType)) {
 
 286             assertThat(((RuleType) rule).getCondition()).isNotNull();
 
 287             assertThat(((RuleType) rule).getCondition().getExpression()).isNotNull();
 
 291     private void validateMinMax(ToscaPolicy policy, PolicyType xacmlPolicy) {
 
 292         boolean foundTarget = false;
 
 293         boolean foundMinOrMax = false;
 
 294         for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) {
 
 295             if (! (rule instanceof RuleType)) {
 
 298             for (AnyOfType anyOf : ((RuleType) rule).getTarget().getAnyOf()) {
 
 299                 assertThat(anyOf.getAllOf()).isNotEmpty();
 
 300                 for (AllOfType allOf : anyOf.getAllOf()) {
 
 301                     assertThat(allOf.getMatch()).isNotEmpty();
 
 302                     for (MatchType match : allOf.getMatch()) {
 
 303                         if (ToscaDictionary.ID_RESOURCE_GUARD_TARGETID.toString().equals(
 
 304                                 match.getAttributeDesignator().getAttributeId())) {
 
 305                             assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_TARGET);
 
 307                         } else if (ToscaDictionary.ID_RESOURCE_GUARD_VFCOUNT.toString().equals(
 
 308                                 match.getAttributeDesignator().getAttributeId())) {
 
 309                             assertThat(policy.getProperties().keySet()).containsAnyOf(GuardTranslator.FIELD_MIN,
 
 310                                     GuardTranslator.FIELD_MAX);
 
 311                             foundMinOrMax = true;
 
 317         assertThat(foundTarget && foundMinOrMax).isTrue();
 
 320     private void validateBlacklist(ToscaPolicy policy, PolicyType xacmlPolicy) {
 
 321         boolean foundBlacklist = false;
 
 322         for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) {
 
 323             if (! (rule instanceof RuleType)) {
 
 326             assertThat(((RuleType) rule).getTarget()).isNotNull();
 
 327             assertThat(((RuleType) rule).getTarget().getAnyOf()).hasSize(1);
 
 328             for (AnyOfType anyOf : ((RuleType) rule).getTarget().getAnyOf()) {
 
 329                 assertThat(anyOf.getAllOf()).isNotEmpty();
 
 330                 for (AllOfType allOf : anyOf.getAllOf()) {
 
 331                     assertThat(allOf.getMatch()).isNotEmpty();
 
 332                     assertThat(allOf.getMatch()).hasSize(1);
 
 333                     for (MatchType match : allOf.getMatch()) {
 
 334                         assertThat(match.getAttributeDesignator().getAttributeId())
 
 335                                 .isEqualTo(ToscaDictionary.ID_RESOURCE_GUARD_TARGETID.toString());
 
 336                         assertThat(match.getAttributeValue().getContent()).containsAnyOf("vnf1", "vnf2");
 
 338                         // This just checks that policy did have a blacklist in it.
 
 340                         assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_BLACKLIST);
 
 341                         foundBlacklist = true;
 
 346         assertThat(foundBlacklist).isTrue();
 
 349     private void validateFilter(ToscaPolicy policy, PolicyType xacmlPolicy) {
 
 350         assertThat(xacmlPolicy.getRuleCombiningAlgId()).endsWith("-overrides");
 
 351         for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) {
 
 352             if (! (rule instanceof RuleType)) {
 
 355             assertThat(((RuleType) rule).getTarget()).isNotNull();
 
 356             assertThat(((RuleType) rule).getTarget().getAnyOf()).hasSize(1);
 
 357             for (AnyOfType anyOf : ((RuleType) rule).getTarget().getAnyOf()) {
 
 358                 assertThat(anyOf.getAllOf()).isNotEmpty();
 
 359                 for (AllOfType allOf : anyOf.getAllOf()) {
 
 360                     assertThat(allOf.getMatch()).isNotEmpty();
 
 361                     assertThat(allOf.getMatch()).hasSize(1);
 
 362                     for (MatchType match : allOf.getMatch()) {
 
 363                         assertThat(match.getAttributeDesignator().getAttributeId())
 
 364                             .startsWith(GuardPolicyRequest.PREFIX_RESOURCE_ATTRIBUTE_ID);