2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights reserved.
4 * Modifications Copyright (C) 2024 Nordix Foundation.
5 * ================================================================================
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 * ============LICENSE_END=========================================================
20 package org.onap.policy.tutorial.tutorial;
22 import com.att.research.xacml.api.Advice;
23 import com.att.research.xacml.api.DataTypeException;
24 import com.att.research.xacml.api.Decision;
25 import com.att.research.xacml.api.Identifier;
26 import com.att.research.xacml.api.Obligation;
27 import com.att.research.xacml.api.Request;
28 import com.att.research.xacml.api.Response;
29 import com.att.research.xacml.api.Result;
30 import com.att.research.xacml.api.XACML3;
31 import com.att.research.xacml.std.IdentifierImpl;
32 import java.util.ArrayList;
33 import java.util.Collection;
34 import java.util.HashMap;
35 import java.util.List;
37 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AnyOfType;
38 import oasis.names.tc.xacml._3_0.core.schema.wd_17.EffectType;
39 import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType;
40 import oasis.names.tc.xacml._3_0.core.schema.wd_17.RuleType;
41 import oasis.names.tc.xacml._3_0.core.schema.wd_17.TargetType;
42 import org.onap.policy.models.decisions.concepts.DecisionRequest;
43 import org.onap.policy.models.decisions.concepts.DecisionResponse;
44 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
45 import org.onap.policy.pdp.xacml.application.common.ToscaDictionary;
46 import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException;
47 import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslatorUtils;
48 import org.onap.policy.pdp.xacml.application.common.std.StdBaseTranslator;
50 public class TutorialTranslator extends StdBaseTranslator {
52 private static final Identifier ID_TUTORIAL_USER = new IdentifierImpl(ToscaDictionary.ID_URN_ONAP, "tutorial-user");
53 private static final Identifier ID_TUTORIAL_ENTITY =
54 new IdentifierImpl(ToscaDictionary.ID_URN_ONAP, "tutorial-entity");
55 private static final Identifier ID_TUTORIAL_PERM =
56 new IdentifierImpl(ToscaDictionary.ID_URN_ONAP, "tutorial-permission");
59 * Constructor will set up some defaults.
61 public TutorialTranslator() {
63 // For demonstration purposes, this tutorial will have
64 // the original attributes returned in the request.
66 this.booleanReturnAttributes = true;
67 this.booleanReturnSingleValueAttributesAsCollection = false;
71 * Convert Policy from TOSCA to XACML.
73 @SuppressWarnings("unchecked")
75 public PolicyType convertPolicy(ToscaPolicy toscaPolicy) {
77 // Here is our policy with a version and default combining algo
79 var newPolicyType = new PolicyType();
80 newPolicyType.setPolicyId(String.valueOf(toscaPolicy.getMetadata().get("policy-id")));
81 newPolicyType.setVersion(String.valueOf(toscaPolicy.getMetadata().get("policy-version")));
83 // When choosing the rule combining algorithm, be sure to be mindful of the
84 // setting xacml.att.policyFinderFactory.combineRootPolicies in the
85 // xacml.properties file. As that choice for ALL the policies together may have
86 // an impact on the decision rendered from each individual policy.
88 // In this case, we will only produce XACML rules for permissions. If no permission
89 // combo exists, then the default is to deny.
91 newPolicyType.setRuleCombiningAlgId(XACML3.ID_RULE_DENY_UNLESS_PERMIT.stringValue());
93 // Create the target for the Policy.
95 // For simplicity, let's just match on the action "authorize" and the user
98 ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(XACML3.ID_FUNCTION_STRING_EQUAL, "authorize",
99 XACML3.ID_DATATYPE_STRING, XACML3.ID_ACTION_ACTION_ID, XACML3.ID_ATTRIBUTE_CATEGORY_ACTION);
100 Map<String, Object> props = toscaPolicy.getProperties();
101 var user = props.get("user").toString();
102 var matchUser = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(XACML3.ID_FUNCTION_STRING_EQUAL, user,
103 XACML3.ID_DATATYPE_STRING, ID_TUTORIAL_USER, XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
104 var anyOf = new AnyOfType();
106 // Create AllOf (AND) of just Policy ID
108 anyOf.getAllOf().add(ToscaPolicyTranslatorUtils.buildAllOf(matchAction, matchUser));
109 var target = new TargetType();
110 target.getAnyOf().add(anyOf);
111 newPolicyType.setTarget(target);
113 // Now add the rule for each permission
116 List<Object> permissions = (List<Object>) props.get("permissions");
117 for (Object permission : permissions) {
119 var matchEntity = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(XACML3.ID_FUNCTION_STRING_EQUAL,
120 ((Map<String, String>) permission).get("entity"), XACML3.ID_DATATYPE_STRING, ID_TUTORIAL_ENTITY,
121 XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
123 var matchPermission = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(XACML3.ID_FUNCTION_STRING_EQUAL,
124 ((Map<String, String>) permission).get("permission"), XACML3.ID_DATATYPE_STRING, ID_TUTORIAL_PERM,
125 XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
126 anyOf = new AnyOfType();
127 anyOf.getAllOf().add(ToscaPolicyTranslatorUtils.buildAllOf(matchEntity, matchPermission));
128 target = new TargetType();
129 target.getAnyOf().add(anyOf);
131 var rule = new RuleType();
132 rule.setDescription("Default is to PERMIT if the policy matches.");
133 rule.setRuleId(newPolicyType.getPolicyId() + ":rule" + ruleNumber);
135 rule.setEffect(EffectType.PERMIT);
136 rule.setTarget(target);
138 newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(rule);
142 return newPolicyType;
146 * Convert ONAP DecisionRequest to XACML Request.
149 public Request convertRequest(DecisionRequest request) {
151 return TutorialRequest.createRequest(request);
152 } catch (IllegalArgumentException | IllegalAccessException | DataTypeException e) {
159 public DecisionResponse convertResponse(Response xacmlResponse) {
163 if (xacmlResponse.getResults().size() > 1) {
164 return convertMultiResponse(xacmlResponse);
166 return convertSingleResponse(xacmlResponse.getResults().iterator().next());
170 protected DecisionResponse convertSingleResponse(Result xacmlResult) {
171 var decisionResponse = new DecisionResponse();
175 decisionResponse.setPolicies(new HashMap<>());
179 if (xacmlResult.getDecision() == Decision.PERMIT) {
181 // This tutorial will simply set the status to Permit
183 decisionResponse.setStatus(Decision.PERMIT.toString());
186 // This tutorial will simply set the status to Deny
188 decisionResponse.setStatus(Decision.DENY.toString());
191 // Add attributes use the default scanAttributes. Note that one
192 // could override that method and return the structure as desired.
193 // The attributes returned by default method are in the format
194 // of XACML syntax. It may be more desirable to map them back to
195 // the original request name-value.
197 if (booleanReturnAttributes) {
198 scanAttributes(xacmlResult.getAttributes(), decisionResponse);
200 return decisionResponse;
203 protected DecisionResponse convertMultiResponse(Response xacmlResponse) {
204 TutorialResponse decisionResponse = new TutorialResponse();
208 decisionResponse.setPolicies(new HashMap<>());
209 decisionResponse.setStatus("multi");
210 List<TutorialResponsePermission> permissions = new ArrayList<>();
211 for (Result xacmlResult : xacmlResponse.getResults()) {
212 TutorialResponsePermission permission = new TutorialResponsePermission();
216 if (xacmlResult.getDecision() == Decision.PERMIT) {
218 // This tutorial will simply set the status to Permit
220 permission.setStatus(Decision.PERMIT.toString());
223 // This tutorial will simply set the status to Deny
225 permission.setStatus(Decision.DENY.toString());
228 // Add attributes use the default scanAttributes. Note that one
229 // could override that method and return the structure as desired.
230 // The attributes returned by default method are in the format
231 // of XACML syntax. It may be more desirable to map them back to
232 // the original request name-value.
234 if (booleanReturnAttributes) {
236 // Call existing method
238 scanAttributes(xacmlResult.getAttributes(), decisionResponse);
240 // Move from overall response to the individual permission
242 permission.setAttributes(decisionResponse.getAttributes());
243 decisionResponse.setAttributes(null);
248 permissions.add(permission);
250 decisionResponse.setPermissions(permissions);
251 return decisionResponse;
255 protected void scanObligations(Collection<Obligation> obligations, DecisionResponse decisionResponse) {
257 // No obligations in this tutorial yet.
262 protected void scanAdvice(Collection<Advice> advice, DecisionResponse decisionResponse) {
264 // No advice in this tutorial yet.