2  * ============LICENSE_START=======================================================
 
   4  * ================================================================================
 
   5  * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
 
   6  * ================================================================================
 
   7  * Licensed under the Apache License, Version 2.0 (the "License");
 
   8  * you may not use this file except in compliance with the License.
 
   9  * You may obtain a copy of the License at
 
  11  *      http://www.apache.org/licenses/LICENSE-2.0
 
  13  * Unless required by applicable law or agreed to in writing, software
 
  14  * distributed under the License is distributed on an "AS IS" BASIS,
 
  15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
  16  * See the License for the specific language governing permissions and
 
  17  * limitations under the License.
 
  19  * SPDX-License-Identifier: Apache-2.0
 
  20  * ============LICENSE_END=========================================================
 
  23 package org.onap.policy.xacml.pdp.application.guard;
 
  25 import static org.assertj.core.api.Assertions.assertThat;
 
  26 import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
 
  28 import com.att.research.xacml.api.Decision;
 
  29 import com.att.research.xacml.api.Request;
 
  30 import com.att.research.xacml.api.XACML3;
 
  31 import com.att.research.xacml.std.StdMutableResponse;
 
  32 import com.att.research.xacml.std.StdMutableResult;
 
  33 import com.att.research.xacml.std.StdStatus;
 
  34 import com.att.research.xacml.std.StdStatusCode;
 
  35 import com.att.research.xacml.util.XACMLPolicyWriter;
 
  36 import java.io.ByteArrayOutputStream;
 
  38 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AllOfType;
 
  39 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AnyOfType;
 
  40 import oasis.names.tc.xacml._3_0.core.schema.wd_17.MatchType;
 
  41 import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType;
 
  42 import oasis.names.tc.xacml._3_0.core.schema.wd_17.RuleType;
 
  43 import org.junit.Test;
 
  44 import org.onap.policy.common.utils.coder.StandardCoder;
 
  45 import org.onap.policy.common.utils.coder.StandardYamlCoder;
 
  46 import org.onap.policy.common.utils.resources.ResourceUtils;
 
  47 import org.onap.policy.common.utils.resources.TextFileUtils;
 
  48 import org.onap.policy.models.decisions.concepts.DecisionRequest;
 
  49 import org.onap.policy.models.decisions.concepts.DecisionResponse;
 
  50 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
 
  51 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
 
  52 import org.onap.policy.models.tosca.simple.concepts.JpaToscaServiceTemplate;
 
  53 import org.onap.policy.pdp.xacml.application.common.ToscaDictionary;
 
  54 import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException;
 
  55 import org.slf4j.Logger;
 
  56 import org.slf4j.LoggerFactory;
 
  58 public class GuardTranslatorTest {
 
  59     private static final Logger LOGGER = LoggerFactory.getLogger(GuardTranslatorTest.class);
 
  60     private static final StandardYamlCoder yamlCoder = new StandardYamlCoder();
 
  61     private static StandardCoder gson = new StandardCoder();
 
  63     private GuardTranslator translator = new GuardTranslator();
 
  66     public void testRequest() throws Exception {
 
  67         DecisionRequest decisionRequest = gson.decode(
 
  68                 TextFileUtils.getTextFileAsString(
 
  69                         "src/test/resources/requests/guard.vfCount.json"),
 
  70                         DecisionRequest.class);
 
  71         Request xacmlRequest = translator.convertRequest(decisionRequest);
 
  73         assertThat(xacmlRequest).isNotNull();
 
  77     public void testResponse() {
 
  78         StdStatus status = new StdStatus(StdStatusCode.STATUS_CODE_OK);
 
  79         StdMutableResult result = new StdMutableResult(Decision.PERMIT, status);
 
  80         StdMutableResponse response = new StdMutableResponse(result);
 
  82         DecisionResponse decisionResponse = translator.convertResponse(response);
 
  83         assertThat(decisionResponse).isNotNull();
 
  84         assertThat(decisionResponse.getStatus()).isEqualTo(Decision.PERMIT.toString());
 
  86         result = new StdMutableResult(Decision.DENY, status);
 
  87         response = new StdMutableResponse(result);
 
  88         decisionResponse = translator.convertResponse(response);
 
  89         assertThat(decisionResponse).isNotNull();
 
  90         assertThat(decisionResponse.getStatus()).isEqualTo(Decision.DENY.toString());
 
  92         result = new StdMutableResult(Decision.INDETERMINATE, status);
 
  93         response = new StdMutableResponse(result);
 
  94         decisionResponse = translator.convertResponse(response);
 
  95         assertThat(decisionResponse).isNotNull();
 
  96         assertThat(decisionResponse.getStatus()).isEqualTo(Decision.PERMIT.toString());
 
 101     public void testBadPolicies() throws Exception {
 
 102         String policyYaml = ResourceUtils.getResourceAsString("src/test/resources/test-bad-policies.yaml");
 
 104         // Serialize it into a class
 
 106         ToscaServiceTemplate serviceTemplate = yamlCoder.decode(policyYaml, ToscaServiceTemplate.class);
 
 108         // Make sure all the fields are setup properly
 
 110         JpaToscaServiceTemplate jtst = new JpaToscaServiceTemplate();
 
 111         jtst.fromAuthorative(serviceTemplate);
 
 112         ToscaServiceTemplate completedJtst = jtst.toAuthorative();
 
 116         for (Map<String, ToscaPolicy> policies : completedJtst.getToscaTopologyTemplate().getPolicies()) {
 
 117             for (ToscaPolicy policy : policies.values()) {
 
 118                 LOGGER.info("Testing policy " + policy.getName());
 
 119                 if ("frequency-missing-properties".equals(policy.getName())) {
 
 120                     assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
 
 121                         translator.convertPolicy(policy)
 
 122                     ).withMessageContaining("Missing property limit");
 
 123                 } else if ("frequency-timewindow".equals(policy.getName())) {
 
 124                     assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
 
 125                         translator.convertPolicy(policy)
 
 126                     ).withMessageContaining("timeWindow is not an integer");
 
 127                 } else if ("minmax-notarget".equals(policy.getName())) {
 
 128                     assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
 
 129                         translator.convertPolicy(policy)
 
 130                     ).withMessageContaining("Missing target field in minmax policy");
 
 131                 } else if ("minmax-nominmax".equals(policy.getName())) {
 
 132                     assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
 
 133                         translator.convertPolicy(policy)
 
 134                     ).withMessageContaining("Missing min or max field in minmax policy");
 
 135                 } else if ("blacklist-noblacklist".equals(policy.getName())) {
 
 136                     assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
 
 137                         translator.convertPolicy(policy)
 
 138                     ).withMessageContaining("Missing blacklist");
 
 139                 } else if ("filter-noalgorithm".equals(policy.getName())) {
 
 140                     assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
 
 141                         translator.convertPolicy(policy)
 
 142                     ).withMessageContaining("Missing algorithm");
 
 143                 } else if ("filter-badalgorithm".equals(policy.getName())) {
 
 144                     assertThatExceptionOfType(ToscaPolicyConversionException.class)
 
 145                             .isThrownBy(() -> translator.convertPolicy(policy))
 
 146                             .withMessageContaining(
 
 147                                 "Unexpected value for algorithm, should be whitelist-overrides or blacklist-overrides");
 
 148                 } else if ("filter-nofilter".equals(policy.getName())) {
 
 149                     assertThatExceptionOfType(ToscaPolicyConversionException.class)
 
 150                             .isThrownBy(() -> translator.convertPolicy(policy))
 
 151                             .withMessageContaining("Missing filters");
 
 152                 } else if ("filter-nocollection".equals(policy.getName())) {
 
 153                     assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
 
 154                         translator.convertPolicy(policy)
 
 155                     ).withMessageContaining("Filters is not a collection");
 
 156                 } else if ("filter-noarray".equals(policy.getName())) {
 
 157                     assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
 
 158                         translator.convertPolicy(policy)
 
 159                     ).withMessageContaining("Filters is not a collection");
 
 160                 } else if ("filter-missingfield".equals(policy.getName())) {
 
 161                     assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
 
 162                         translator.convertPolicy(policy)
 
 163                     ).withMessageContaining("Missing \'field\' from filter");
 
 164                 } else if ("filter-badfield".equals(policy.getName())) {
 
 165                     assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
 
 166                         translator.convertPolicy(policy)
 
 167                     ).withMessageContaining("Unexpected value for field in filter");
 
 168                 } else if ("filter-missingfilter".equals(policy.getName())) {
 
 169                     assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
 
 170                         translator.convertPolicy(policy)
 
 171                     ).withMessageContaining("Missing \'filter\' from filter");
 
 172                 } else if ("filter-missingfunction".equals(policy.getName())) {
 
 173                     assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
 
 174                         translator.convertPolicy(policy)
 
 175                     ).withMessageContaining("Missing \'function\' from filter");
 
 176                 } else if ("filter-badfunction".equals(policy.getName())) {
 
 177                     assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
 
 178                         translator.convertPolicy(policy)
 
 179                     ).withMessageContaining("Unexpected value for function in filter");
 
 180                 } else if ("filter-missingblacklist".equals(policy.getName())) {
 
 181                     assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
 
 182                         translator.convertPolicy(policy)
 
 183                     ).withMessageContaining("Missing \'blacklist\' from filter");
 
 184                 } else if ("filter-badblacklist".equals(policy.getName())) {
 
 185                     assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
 
 186                         translator.convertPolicy(policy)
 
 187                     ).withMessageContaining("Unexpected value for blacklist in filter");
 
 194     public void testPolicyConversion() throws Exception {
 
 195         String policyYaml = ResourceUtils.getResourceAsString("src/test/resources/test-policies.yaml");
 
 197         // Serialize it into a class
 
 199         ToscaServiceTemplate serviceTemplate = yamlCoder.decode(policyYaml, ToscaServiceTemplate.class);
 
 201         // Make sure all the fields are setup properly
 
 203         JpaToscaServiceTemplate jtst = new JpaToscaServiceTemplate();
 
 204         jtst.fromAuthorative(serviceTemplate);
 
 205         ToscaServiceTemplate completedJtst = jtst.toAuthorative();
 
 209         for (Map<String, ToscaPolicy> policies : completedJtst.getToscaTopologyTemplate().getPolicies()) {
 
 210             for (ToscaPolicy policy : policies.values()) {
 
 212                 // Convert the policy
 
 214                 if ("onap.policies.controlloop.guard.common.Unknown".equals(policy.getType())) {
 
 215                     assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
 
 216                         translator.convertPolicy(policy));
 
 219                 PolicyType xacmlPolicy = (PolicyType) translator.convertPolicy(policy);
 
 220                 assertThat(xacmlPolicy).isNotNull();
 
 224                 ByteArrayOutputStream os = new ByteArrayOutputStream();
 
 225                 XACMLPolicyWriter.writePolicyFile(os, xacmlPolicy);
 
 226                 LOGGER.info(os.toString());
 
 228                 // Validate the policy
 
 230                 assertThat(xacmlPolicy.getPolicyId()).isEqualTo(policy.getName());
 
 231                 assertThat(xacmlPolicy.getVersion()).isEqualTo(policy.getVersion());
 
 232                 assertThat(xacmlPolicy.getRuleCombiningAlgId()).isNotNull();
 
 233                 validateCommon(policy, xacmlPolicy);
 
 235                 // Validate each policy type
 
 237                 if (GuardTranslator.POLICYTYPE_FREQUENCY.equals(policy.getType())) {
 
 238                     validateFrequency(policy, xacmlPolicy);
 
 239                 } else if (GuardTranslator.POLICYTYPE_MINMAX.equals(policy.getType())) {
 
 240                     validateMinMax(policy, xacmlPolicy);
 
 241                 } else if (GuardTranslator.POLICYTYPE_BLACKLIST.equals(policy.getType())) {
 
 242                     validateBlacklist(policy, xacmlPolicy);
 
 243                 } else if (GuardTranslator.POLICYTYPE_FILTER.equals(policy.getType())) {
 
 244                     validateFilter(policy, xacmlPolicy);
 
 250     private void validateCommon(ToscaPolicy policy, PolicyType xacmlPolicy) {
 
 251         boolean foundActor = false;
 
 252         boolean foundOperation = false;
 
 253         boolean foundTarget = false;
 
 254         boolean foundControlLoop = false;
 
 255         boolean foundTimeRange = false;
 
 257         assertThat(xacmlPolicy.getTarget()).isNotNull();
 
 258         assertThat(xacmlPolicy.getTarget().getAnyOf()).isNotEmpty();
 
 259         for (AnyOfType anyOf : xacmlPolicy.getTarget().getAnyOf()) {
 
 260             assertThat(anyOf.getAllOf()).isNotEmpty();
 
 261             for (AllOfType allOf : anyOf.getAllOf()) {
 
 262                 assertThat(allOf.getMatch()).isNotEmpty();
 
 263                 for (MatchType match : allOf.getMatch()) {
 
 265                     // These fields are required
 
 267                     if (ToscaDictionary.ID_RESOURCE_GUARD_ACTOR.toString().equals(
 
 268                             match.getAttributeDesignator().getAttributeId())) {
 
 269                         assertThat(match.getAttributeValue().getContent()).isNotNull();
 
 271                     } else if (ToscaDictionary.ID_RESOURCE_GUARD_RECIPE.toString().equals(
 
 272                             match.getAttributeDesignator().getAttributeId())) {
 
 273                         assertThat(match.getAttributeValue().getContent()).isNotNull();
 
 274                         foundOperation = true;
 
 277                         // These fields are optional
 
 279                         if (ToscaDictionary.ID_RESOURCE_GUARD_TARGETID.toString().equals(
 
 280                                 match.getAttributeDesignator().getAttributeId())) {
 
 281                             assertThat(policy.getProperties()).containsKey("target");
 
 284                         if (ToscaDictionary.ID_RESOURCE_GUARD_CLNAME.toString().equals(
 
 285                                 match.getAttributeDesignator().getAttributeId())) {
 
 286                             assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_CONTROLLOOP);
 
 287                             foundControlLoop = true;
 
 289                         if (XACML3.ID_ENVIRONMENT_CURRENT_TIME.toString().equals(
 
 290                                 match.getAttributeDesignator().getAttributeId())) {
 
 291                             assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_TIMERANGE);
 
 292                             foundTimeRange = true;
 
 298         assertThat(foundActor && foundOperation).isTrue();
 
 299         if (policy.getProperties().containsKey("target")) {
 
 300             assertThat(foundTarget).isTrue();
 
 302         if (policy.getProperties().containsKey(GuardTranslator.FIELD_CONTROLLOOP)) {
 
 303             assertThat(foundControlLoop).isTrue();
 
 305         if (policy.getProperties().containsKey(GuardTranslator.FIELD_TIMERANGE)) {
 
 306             assertThat(foundTimeRange).isTrue();
 
 310     private void validateFrequency(ToscaPolicy policy, PolicyType xacmlPolicy) {
 
 311         for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) {
 
 312             if (! (rule instanceof RuleType)) {
 
 315             assertThat(((RuleType) rule).getCondition()).isNotNull();
 
 316             assertThat(((RuleType) rule).getCondition().getExpression()).isNotNull();
 
 320     private void validateMinMax(ToscaPolicy policy, PolicyType xacmlPolicy) {
 
 321         boolean foundTarget = false;
 
 322         boolean foundMinOrMax = false;
 
 323         for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) {
 
 324             if (! (rule instanceof RuleType)) {
 
 327             for (AnyOfType anyOf : ((RuleType) rule).getTarget().getAnyOf()) {
 
 328                 assertThat(anyOf.getAllOf()).isNotEmpty();
 
 329                 for (AllOfType allOf : anyOf.getAllOf()) {
 
 330                     assertThat(allOf.getMatch()).isNotEmpty();
 
 331                     for (MatchType match : allOf.getMatch()) {
 
 332                         if (ToscaDictionary.ID_RESOURCE_GUARD_TARGETID.toString().equals(
 
 333                                 match.getAttributeDesignator().getAttributeId())) {
 
 334                             assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_TARGET);
 
 336                         } else if (ToscaDictionary.ID_RESOURCE_GUARD_VFCOUNT.toString().equals(
 
 337                                 match.getAttributeDesignator().getAttributeId())) {
 
 338                             assertThat(policy.getProperties().keySet()).containsAnyOf(GuardTranslator.FIELD_MIN,
 
 339                                     GuardTranslator.FIELD_MAX);
 
 340                             foundMinOrMax = true;
 
 346         assertThat(foundTarget && foundMinOrMax).isTrue();
 
 349     private void validateBlacklist(ToscaPolicy policy, PolicyType xacmlPolicy) {
 
 350         boolean foundBlacklist = false;
 
 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                                 .isEqualTo(ToscaDictionary.ID_RESOURCE_GUARD_TARGETID.toString());
 
 365                         assertThat(match.getAttributeValue().getContent()).containsAnyOf("vnf1", "vnf2");
 
 367                         // This just checks that policy did have a blacklist in it.
 
 369                         assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_BLACKLIST);
 
 370                         foundBlacklist = true;
 
 375         assertThat(foundBlacklist).isTrue();
 
 378     private void validateFilter(ToscaPolicy policy, PolicyType xacmlPolicy) {
 
 379         assertThat(xacmlPolicy.getRuleCombiningAlgId()).endsWith("-overrides");
 
 380         for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) {
 
 381             if (! (rule instanceof RuleType)) {
 
 384             assertThat(((RuleType) rule).getTarget()).isNotNull();
 
 385             assertThat(((RuleType) rule).getTarget().getAnyOf()).hasSize(1);
 
 386             for (AnyOfType anyOf : ((RuleType) rule).getTarget().getAnyOf()) {
 
 387                 assertThat(anyOf.getAllOf()).isNotEmpty();
 
 388                 for (AllOfType allOf : anyOf.getAllOf()) {
 
 389                     assertThat(allOf.getMatch()).isNotEmpty();
 
 390                     assertThat(allOf.getMatch()).hasSize(1);
 
 391                     for (MatchType match : allOf.getMatch()) {
 
 392                         assertThat(match.getAttributeDesignator().getAttributeId())
 
 393                             .startsWith(GuardPolicyRequest.PREFIX_RESOURCE_ATTRIBUTE_ID);