2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2019 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.pdp.xacml.application.common.std;
25 import com.att.research.xacml.api.AttributeAssignment;
26 import com.att.research.xacml.api.Decision;
27 import com.att.research.xacml.api.Obligation;
28 import com.att.research.xacml.api.Request;
29 import com.att.research.xacml.api.Response;
30 import com.att.research.xacml.api.Result;
31 import com.att.research.xacml.api.XACML3;
32 import com.google.gson.Gson;
33 import java.util.Collection;
34 import java.util.HashMap;
36 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AnyOfType;
37 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ApplyType;
38 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeAssignmentExpressionType;
39 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeDesignatorType;
40 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeValueType;
41 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ConditionType;
42 import oasis.names.tc.xacml._3_0.core.schema.wd_17.EffectType;
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.ObjectFactory;
45 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObligationExpressionType;
46 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObligationExpressionsType;
47 import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicySetType;
48 import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType;
49 import oasis.names.tc.xacml._3_0.core.schema.wd_17.RuleType;
50 import org.onap.policy.models.decisions.concepts.DecisionRequest;
51 import org.onap.policy.models.decisions.concepts.DecisionResponse;
52 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
53 import org.onap.policy.pdp.xacml.application.common.ToscaDictionary;
54 import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException;
55 import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslator;
56 import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslatorUtils;
57 import org.onap.policy.pdp.xacml.application.common.XacmlPolicyUtils;
58 import org.slf4j.Logger;
59 import org.slf4j.LoggerFactory;
61 public class StdBaseTranslator implements ToscaPolicyTranslator {
62 private static final Logger LOGGER = LoggerFactory.getLogger(StdBaseTranslator.class);
63 private static Gson gson = new Gson();
65 public static final String POLICY_ID = "policy-id";
66 public static final String POLICY_VERSION = "policy-version";
69 public PolicyType convertPolicy(ToscaPolicy toscaPolicy) throws ToscaPolicyConversionException {
70 throw new ToscaPolicyConversionException("Please override converPolicy");
74 public Request convertRequest(DecisionRequest request) {
79 public DecisionResponse convertResponse(Response xacmlResponse) {
80 LOGGER.info("Converting Response {}", xacmlResponse);
81 DecisionResponse decisionResponse = new DecisionResponse();
85 decisionResponse.setPolicies(new HashMap<>());
87 // Iterate through all the results
89 for (Result xacmlResult : xacmlResponse.getResults()) {
93 if (xacmlResult.getDecision() == Decision.PERMIT) {
95 // Go through obligations
97 scanObligations(xacmlResult.getObligations(), decisionResponse);
98 } else if (xacmlResult.getDecision() == Decision.DENY
99 || xacmlResult.getDecision() == Decision.INDETERMINATE) {
101 // TODO we have to return an ErrorResponse object instead
103 decisionResponse.setStatus("A better error message");
107 return decisionResponse;
111 * scanObligations - scans the list of obligations and make appropriate method calls to process
114 * @param obligations Collection of obligation objects
115 * @param decisionResponse DecisionResponse object used to store any results from obligations.
117 protected void scanObligations(Collection<Obligation> obligations, DecisionResponse decisionResponse) {
118 for (Obligation obligation : obligations) {
119 LOGGER.info("Obligation: {}", obligation);
120 for (AttributeAssignment assignment : obligation.getAttributeAssignments()) {
121 LOGGER.info("Attribute Assignment: {}", assignment);
122 processObligationAttribute(assignment, decisionResponse);
128 * processObligationAttribute - processes an individual obligation attribute assignment object.
130 * @param assignment AttributeAssignment object
131 * @param decisionResponse DecisionResponse object used to store any results from attribute assignment.
133 @SuppressWarnings("unchecked")
134 protected void processObligationAttribute(AttributeAssignment assignment, DecisionResponse decisionResponse) {
136 // We care about the content attribute
138 if (ToscaDictionary.ID_OBLIGATION_POLICY_MONITORING_CONTENTS
139 .equals(assignment.getAttributeId())) {
141 // The contents are in Json form
143 Object stringContents = assignment.getAttributeValue().getValue();
144 LOGGER.info("DCAE contents: {}{}", XacmlPolicyUtils.LINE_SEPARATOR, stringContents);
146 // Let's parse it into a map using Gson
148 Map<String, Object> result;
149 result = gson.fromJson(stringContents.toString(), Map.class);
151 // Find the metadata section
153 Map<String, Object> metadata = (Map<String, Object>) result.get("metadata");
154 if (metadata != null) {
155 decisionResponse.getPolicies().put(metadata.get(POLICY_ID).toString(), result);
157 LOGGER.error("Missing metadata section in policy contained in obligation.");
163 * From the TOSCA metadata section, pull in values that are needed into the XACML policy.
165 * @param policy Policy Object to store the metadata
166 * @param map The Metadata TOSCA Map
167 * @return Same Policy Object
168 * @throws ToscaPolicyConversionException If there is something missing from the metadata
170 protected PolicyType fillMetadataSection(PolicyType policy,
171 Map<String, String> map) throws ToscaPolicyConversionException {
173 // Ensure the policy-id exists - we don't use it here. It
174 // is saved in the TOSCA Policy Name field.
176 if (! map.containsKey(POLICY_ID)) {
177 throw new ToscaPolicyConversionException(policy.getPolicyId() + " missing metadata " + POLICY_ID);
180 // Ensure the policy-version exists
182 if (! map.containsKey(POLICY_VERSION)) {
183 throw new ToscaPolicyConversionException(policy.getPolicyId() + " missing metadata "
187 // Add in the Policy Version
189 policy.setVersion(map.get(POLICY_VERSION));
194 * addObligation - general code to add a json policy as an obligation. Probably could just
195 * return the obligation only instead of adding it directly to a rule/policy/policyset.
196 * But this is fine for now.
198 * @param <T> RuleType, PolicyType, PolicySetType object
199 * @param ruleOrPolicy Incoming RuleType, PolicyType, PolicySetType object
200 * @param jsonPolicy JSON String representation of policy.
201 * @return Return the Incoming RuleType, PolicyType, PolicySetType object for convenience.
203 protected <T> T addObligation(T ruleOrPolicy, String jsonPolicy) {
205 // Creating obligation for returning policy
207 LOGGER.info("Obligation Policy {}{}", XacmlPolicyUtils.LINE_SEPARATOR, jsonPolicy);
209 // Create an AttributeValue for it
211 AttributeValueType value = new AttributeValueType();
212 value.setDataType(ToscaDictionary.ID_OBLIGATION_POLICY_MONITORING_DATATYPE.stringValue());
213 value.getContent().add(jsonPolicy);
215 // Create our AttributeAssignmentExpression where we will
216 // store the contents of the policy in JSON format.
218 AttributeAssignmentExpressionType expressionType = new AttributeAssignmentExpressionType();
219 expressionType.setAttributeId(ToscaDictionary.ID_OBLIGATION_POLICY_MONITORING_CONTENTS.stringValue());
220 ObjectFactory factory = new ObjectFactory();
221 expressionType.setExpression(factory.createAttributeValue(value));
223 // Create an ObligationExpression for it
225 ObligationExpressionType obligation = new ObligationExpressionType();
226 obligation.setFulfillOn(EffectType.PERMIT);
227 obligation.setObligationId(ToscaDictionary.ID_OBLIGATION_REST_BODY.stringValue());
228 obligation.getAttributeAssignmentExpression().add(expressionType);
230 // Now we can add it into the rule/policy/policyset
232 ObligationExpressionsType obligations = new ObligationExpressionsType();
233 obligations.getObligationExpression().add(obligation);
234 if (ruleOrPolicy instanceof RuleType) {
235 ((RuleType) ruleOrPolicy).setObligationExpressions(obligations);
236 } else if (ruleOrPolicy instanceof PolicyType) {
237 ((PolicyType) ruleOrPolicy).setObligationExpressions(obligations);
238 } else if (ruleOrPolicy instanceof PolicySetType) {
239 ((PolicySetType) ruleOrPolicy).setObligationExpressions(obligations);
242 // Return as a convenience
248 * generateAnyOfForPolicyType - Creates a specific AnyOfType that includes the check
249 * to match on a specific TOSCA Policy Type.
251 * @param type String represenatation of TOSCA Policy Type (eg. "onap.policies.Foo")
252 * @return AnyOfType object
254 protected AnyOfType generateAnyOfForPolicyType(String type) {
256 // Create the match for the policy type
258 MatchType match = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
259 XACML3.ID_FUNCTION_STRING_EQUAL,
261 XACML3.ID_DATATYPE_STRING,
262 ToscaDictionary.ID_RESOURCE_POLICY_TYPE,
263 XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
265 // Add it to an AnyOfType object
267 AnyOfType anyOf = new AnyOfType();
268 anyOf.getAllOf().add(ToscaPolicyTranslatorUtils.buildAllOf(match));
270 // Return new AnyOfType
276 * generateConditionForPolicyType - create a ConditionType XACML object
277 * that is able to determine if a request specifies a specific policy type
278 * that the policy is created from, only then is the rule applied. If the
279 * request doesn't even care about the policy type (eg it is missing) then
280 * return the rule should not apply.
282 * @param type PolicyType (eg. onap.policies.Foo
283 * @return ConditionType object
285 protected ConditionType generateConditionForPolicyType(String type) {
287 // Create an ApplyType that checks if the request contains the
288 // policy-type attribute
290 AttributeDesignatorType designator = new AttributeDesignatorType();
291 designator.setAttributeId(ToscaDictionary.ID_RESOURCE_POLICY_TYPE.stringValue());
292 designator.setCategory(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE.stringValue());
293 designator.setDataType(XACML3.ID_DATATYPE_STRING.stringValue());
295 ApplyType applyBagSize = new ApplyType();
296 applyBagSize.setDescription("Get the size of policy-type attributes");
297 applyBagSize.setFunctionId(XACML3.ID_FUNCTION_STRING_BAG_SIZE.stringValue());
299 AttributeValueType valueZero = new AttributeValueType();
300 valueZero.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue());
301 valueZero.getContent().add("0"); // Yes really - represent as a string
303 ObjectFactory factory = new ObjectFactory();
304 applyBagSize.getExpression().add(factory.createAttributeDesignator(designator));
306 ApplyType applyGreaterThan = new ApplyType();
307 applyGreaterThan.setDescription("Does the policy-type attribute exist?");
308 applyGreaterThan.setFunctionId(XACML3.ID_FUNCTION_INTEGER_EQUAL.stringValue());
310 applyGreaterThan.getExpression().add(factory.createApply(applyBagSize));
311 applyGreaterThan.getExpression().add(factory.createAttributeValue(valueZero));
314 // Create an apply type that checks the actual value
316 AttributeValueType value = new AttributeValueType();
317 value.setDataType(XACML3.ID_DATATYPE_STRING.stringValue());
318 value.getContent().add(type);
321 // Create string-is-in apply - which determines if the policy-type
322 // is in the request bag of resources for policy-type
324 ApplyType applyIsIn = new ApplyType();
325 applyIsIn.setDescription("Is this policy-type in the list?");
326 applyIsIn.setFunctionId(XACML3.ID_FUNCTION_STRING_IS_IN.stringValue());
327 applyIsIn.getExpression().add(factory.createAttributeValue(value));
328 applyIsIn.getExpression().add(factory.createAttributeDesignator(designator));
331 // Create our outer apply
333 ApplyType applyOr = new ApplyType();
334 applyOr.setDescription("IF exists and is equal");
335 applyOr.setFunctionId(XACML3.ID_FUNCTION_OR.stringValue());
337 applyOr.getExpression().add(factory.createApply(applyGreaterThan));
338 applyOr.getExpression().add(factory.createApply(applyIsIn));
341 // Finally create the condition
343 ConditionType condition = new ConditionType();
345 condition.setExpression(factory.createApply(applyOr));