Support for kafka within xacml tutorial
[policy/xacml-pdp.git] / tutorials / tutorial-xacml-application / src / main / java / org / onap / policy / tutorial / tutorial / TutorialTranslator.java
1 /*-
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
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
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=========================================================
18  */
19
20 package org.onap.policy.tutorial.tutorial;
21
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;
36 import java.util.Map;
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;
49
50 public class TutorialTranslator extends StdBaseTranslator {
51
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");
57
58     /**
59      * Constructor will set up some defaults.
60      */
61     public TutorialTranslator() {
62         //
63         // For demonstration purposes, this tutorial will have
64         // the original attributes returned in the request.
65         //
66         this.booleanReturnAttributes = true;
67         this.booleanReturnSingleValueAttributesAsCollection = false;
68     }
69
70     /**
71      * Convert Policy from TOSCA to XACML.
72      */
73     @SuppressWarnings("unchecked")
74     @Override
75     public PolicyType convertPolicy(ToscaPolicy toscaPolicy) {
76         //
77         // Here is our policy with a version and default combining algo
78         //
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")));
82         //
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.
87         //
88         // In this case, we will only produce XACML rules for permissions. If no permission
89         // combo exists, then the default is to deny.
90         //
91         newPolicyType.setRuleCombiningAlgId(XACML3.ID_RULE_DENY_UNLESS_PERMIT.stringValue());
92         //
93         // Create the target for the Policy.
94         //
95         // For simplicity, let's just match on the action "authorize" and the user
96         //
97         var matchAction =
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();
105         //
106         // Create AllOf (AND) of just Policy ID
107         //
108         anyOf.getAllOf().add(ToscaPolicyTranslatorUtils.buildAllOf(matchAction, matchUser));
109         var target = new TargetType();
110         target.getAnyOf().add(anyOf);
111         newPolicyType.setTarget(target);
112         //
113         // Now add the rule for each permission
114         //
115         var ruleNumber = 0;
116         List<Object> permissions = (List<Object>) props.get("permissions");
117         for (Object permission : permissions) {
118
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);
122
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);
130
131             var rule = new RuleType();
132             rule.setDescription("Default is to PERMIT if the policy matches.");
133             rule.setRuleId(newPolicyType.getPolicyId() + ":rule" + ruleNumber);
134
135             rule.setEffect(EffectType.PERMIT);
136             rule.setTarget(target);
137
138             newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(rule);
139
140             ruleNumber++;
141         }
142         return newPolicyType;
143     }
144
145     /**
146      * Convert ONAP DecisionRequest to XACML Request.
147      */
148     @Override
149     public Request convertRequest(DecisionRequest request) {
150         try {
151             return TutorialRequest.createRequest(request);
152         } catch (IllegalArgumentException | IllegalAccessException | DataTypeException e) {
153             // Empty
154         }
155         return null;
156     }
157
158     @Override
159     public DecisionResponse convertResponse(Response xacmlResponse) {
160         //
161         // Single or Multi?
162         //
163         if (xacmlResponse.getResults().size() > 1) {
164             return convertMultiResponse(xacmlResponse);
165         } else {
166             return convertSingleResponse(xacmlResponse.getResults().iterator().next());
167         }
168     }
169
170     protected DecisionResponse convertSingleResponse(Result xacmlResult) {
171         var decisionResponse = new DecisionResponse();
172         //
173         // Setup policies
174         //
175         decisionResponse.setPolicies(new HashMap<>());
176         //
177         // Check the result
178         //
179         if (xacmlResult.getDecision() == Decision.PERMIT) {
180             //
181             // This tutorial will simply set the status to Permit
182             //
183             decisionResponse.setStatus(Decision.PERMIT.toString());
184         } else {
185             //
186             // This tutorial will simply set the status to Deny
187             //
188             decisionResponse.setStatus(Decision.DENY.toString());
189         }
190         //
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.
196         //
197         if (booleanReturnAttributes) {
198             scanAttributes(xacmlResult.getAttributes(), decisionResponse);
199         }
200         return decisionResponse;
201     }
202
203     protected DecisionResponse convertMultiResponse(Response xacmlResponse) {
204         TutorialResponse decisionResponse = new TutorialResponse();
205         //
206         // Setup policies
207         //
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();
213             //
214             // Check the result
215             //
216             if (xacmlResult.getDecision() == Decision.PERMIT) {
217                 //
218                 // This tutorial will simply set the status to Permit
219                 //
220                 permission.setStatus(Decision.PERMIT.toString());
221             } else {
222                 //
223                 // This tutorial will simply set the status to Deny
224                 //
225                 permission.setStatus(Decision.DENY.toString());
226             }
227             //
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.
233             //
234             if (booleanReturnAttributes) {
235                 //
236                 // Call existing method
237                 //
238                 scanAttributes(xacmlResult.getAttributes(), decisionResponse);
239                 //
240                 // Move from overall response to the individual permission
241                 //
242                 permission.setAttributes(decisionResponse.getAttributes());
243                 decisionResponse.setAttributes(null);
244             }
245             //
246             // Add it
247             //
248             permissions.add(permission);
249         }
250         decisionResponse.setPermissions(permissions);
251         return decisionResponse;
252     }
253
254     @Override
255     protected void scanObligations(Collection<Obligation> obligations, DecisionResponse decisionResponse) {
256         //
257         // No obligations in this tutorial yet.
258         //
259     }
260
261     @Override
262     protected void scanAdvice(Collection<Advice> advice, DecisionResponse decisionResponse) {
263         //
264         // No advice in this tutorial yet.
265         //
266     }
267
268 }