Document multi-cluster support
[policy/parent.git] / docs / xacml / xacml-tutorial.rst
1 .. This work is licensed under a Creative Commons Attribution 4.0 International License.
2
3 .. _xacmltutorial-label:
4
5 Policy XACML - Custom Application Tutorial
6 ##########################################
7
8 .. toctree::
9    :maxdepth: 3
10
11 This tutorial shows how to build a XACML application for a Policy Type. Please be sure to clone the
12 policy repositories before going through the tutorial. See :ref:`policy-development-tools-label` for details.
13
14 Design a Policy Type
15 ********************
16 Follow :ref:`TOSCA Policy Primer <tosca-label>` for more information. For the tutorial, we will use
17 this example Policy Type in which an ONAP PEP client would like to enforce an action **authorize**
18 for a *user* to execute a *permission* on an *entity*. `See here for latest Tutorial Policy Type <https://github.com/onap/policy-xacml-pdp/blob/master/tutorials/tutorial-xacml-application/src/test/resources/tutorial-policy-type.yaml>`_.
19
20 .. literalinclude:: tutorial/tutorial-policy-type.yaml
21   :language: yaml
22   :caption: Example Tutorial Policy Type
23   :linenos:
24
25 We would expect then to be able to create the following policies to allow the demo user to Read/Write
26 an entity called foo, while the audit user can only read the entity called foo. Neither user has Delete
27 permission. `See here for latest Tutorial Policies <https://github.com/onap/policy-xacml-pdp/blob/master/tutorials/tutorial-xacml-application/src/test/resources/tutorial-policies.yaml>`_.
28
29 .. literalinclude:: tutorial/tutorial-policies.yaml
30   :language: yaml
31   :caption: Example Policies Derived From Tutorial Policy Type
32   :linenos:
33
34 Design Decision Request and expected Decision Response
35 ******************************************************
36 For the PEP (Policy Enforcement Point) client applications that call the Decision API, you need
37 to design how the Decision API Request resource fields will be sent via the PEP.
38
39 .. literalinclude:: tutorial/tutorial-decision-request.json
40   :language: JSON
41   :caption: Example Decision Request
42   :linenos:
43
44 For simplicity, this tutorial expects only a *Permit* or *Deny* in the Decision Response. However, one could
45 customize the Decision Response object and send back whatever information is desired.
46
47 .. literalinclude:: tutorial/tutorial-decision-response.json
48   :language: JSON
49   :caption: Example Decision Response
50   :linenos:
51
52 Create A Maven Project
53 **********************
54 Use whatever tool or environment to create your application project. This tutorial assumes you use Maven to build it.
55
56 Add Dependencies Into Application pom.xml
57 *****************************************
58
59 Here we import the XACML PDP Application common dependency which has the interfaces we need to implement. In addition,
60 we are importing a testing dependency that has common code for producing a JUnit test.
61
62 .. code-block:: java
63   :caption: pom.xml dependencies
64
65     <dependency>
66       <groupId>org.onap.policy.xacml-pdp.applications</groupId>
67       <artifactId>common</artifactId>
68       <version>2.3.3</version>
69     </dependency>
70     <dependency>
71       <groupId>org.onap.policy.xacml-pdp</groupId>
72       <artifactId>xacml-test</artifactId>
73       <version>2.3.3</version>
74       <scope>test</scope>
75     </dependency>
76
77 Create META-INF to expose Java Service
78 **************************************
79 The ONAP XACML PDP Engine will not be able to find the tutorial application unless it has
80 a property file located in src/main/resources/META-INF/services that contains a property file
81 declaring the class that implements the service.
82
83 The name of the file must match **org.onap.policy.pdp.xacml.application.common.XacmlApplicationServiceProvider**
84 and the contents of the file is one line **org.onap.policy.tutorial.tutorial.TutorialApplication**.
85
86 .. code-block:: java
87   :caption: META-INF/services/org.onap.policy.pdp.xacml.application.common.XacmlApplicationServiceProvider
88
89     org.onap.policy.tutorial.tutorial.TutorialApplication
90
91
92 Create A Java Class That Extends **StdXacmlApplicationServiceProvider**
93 ***********************************************************************
94 You could implement **XacmlApplicationServiceProvider** if you wish, but
95 for simplicity if you just extend **StdXacmlApplicationServiceProvider** you
96 will get a lot of implementation done for your application up front. All
97 that needs to be implemented is providing a custom translator.
98
99 .. code-block:: java
100   :caption: Custom Tutorial Application Service Provider
101   :emphasize-lines: 6
102
103   package org.onap.policy.tutorial.tutorial;
104
105   import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslator;
106   import org.onap.policy.pdp.xacml.application.common.std.StdXacmlApplicationServiceProvider;
107
108   public class TutorialApplication extends StdXacmlApplicationServiceProvider {
109
110         @Override
111         protected ToscaPolicyTranslator getTranslator(String type) {
112                 // TODO Auto-generated method stub
113                 return null;
114         }
115
116   }
117
118 Override Methods for Tutorial
119 *****************************
120 Override these methods to differentiate Tutorial from other applications so that the XACML PDP
121 Engine can determine how to route policy types and policies to the application.
122
123 .. code-block:: java
124   :caption: Custom Tutorial Application Service Provider
125
126   package org.onap.policy.tutorial.tutorial;
127
128   import java.util.Arrays;
129   import java.util.List;
130
131   import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier;
132   import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslator;
133   import org.onap.policy.pdp.xacml.application.common.std.StdXacmlApplicationServiceProvider;
134
135   public class TutorialApplication extends StdXacmlApplicationServiceProvider {
136         
137     private final ToscaPolicyTypeIdentifier supportedPolicyType = new ToscaPolicyTypeIdentifier();
138
139     @Override
140     public String applicationName() {
141         return "tutorial";
142     }
143
144     @Override
145     public List<String> actionDecisionsSupported() {
146         return Arrays.asList("authorize");
147     }
148
149     @Override
150     public synchronized List<ToscaPolicyTypeIdentifier> supportedPolicyTypes() {
151         return Arrays.asList(supportedPolicyType);
152     }
153
154     @Override
155     public boolean canSupportPolicyType(ToscaPolicyTypeIdentifier policyTypeId) {
156         return supportedPolicyType.equals(policyTypeId);
157     }
158
159     @Override
160         protected ToscaPolicyTranslator getTranslator(String type) {
161         // TODO Auto-generated method stub
162         return null;
163     }
164
165   }
166
167 Create A Translation Class that extends the ToscaPolicyTranslator Class
168 ***********************************************************************
169 Please be sure to review the existing translators in the policy/xacml-pdp repo to see if they could
170 be re-used for your policy type. For the tutorial, we will create our own translator.
171
172 The custom translator is not only responsible for translating Policies derived from the Tutorial
173 Policy Type, but also for translating Decision API Requests/Responses to/from the appropriate XACML
174 requests/response objects the XACML engine understands.  
175
176 .. code-block:: java
177   :caption: Custom Tutorial Translator Class
178
179   package org.onap.policy.tutorial.tutorial;
180
181   import org.onap.policy.models.decisions.concepts.DecisionRequest;
182   import org.onap.policy.models.decisions.concepts.DecisionResponse;
183   import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
184   import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException;
185   import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslator;
186
187   import com.att.research.xacml.api.Request;
188   import com.att.research.xacml.api.Response;
189
190   import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType;
191
192   public class TutorialTranslator implements ToscaPolicyTranslator {
193
194     public PolicyType convertPolicy(ToscaPolicy toscaPolicy) throws ToscaPolicyConversionException {
195         // TODO Auto-generated method stub
196         return null;
197     }
198
199     public Request convertRequest(DecisionRequest request) {
200         // TODO Auto-generated method stub
201         return null;
202     }
203
204     public DecisionResponse convertResponse(Response xacmlResponse) {
205         // TODO Auto-generated method stub
206         return null;
207     }
208
209   }
210
211 Implement the TutorialTranslator Methods
212 ****************************************
213 This is the part where knowledge of the XACML OASIS 3.0 specification is required. Please refer to
214 that specification on the many ways to design a XACML Policy.
215
216 For the tutorial, we will build code that translates the TOSCA Policy into one XACML Policy that matches
217 on the user and action. It will then have one or more rules for each entity and permission combination. The
218 default combining algorithm for the XACML Rules are to "Deny Unless Permit".
219
220 `See the tutorial example for details on how the translator is implemented <https://github.com/onap/policy-xacml-pdp/blob/master/tutorials/tutorial-xacml-application/src/main/java/org/onap/policy/tutorial/tutorial/TutorialTranslator.java>`_. Note that in the Tutorial Translator, it also shows how a developer could extend the translator to return or act upon obligations, advice and attributes.
221
222 .. Note::
223   There are many ways to build the policy based on the attributes. How to do so is a matter of experience and
224   fine tuning using the many options for combining algorithms, target and/or condition matching and the rich set of
225   functions available.
226
227 Use the TutorialTranslator in the TutorialApplication
228 *****************************************************
229 Be sure to go back to the TutorialApplication and create an instance of the translator to return to the
230 StdXacmlApplicationServiceProvider. The StdXacmlApplicationServiceProvider uses the translator to convert
231 a policy when a new policy is deployed to the ONAP XACML PDP Engine. `See the Tutorial Application Example <https://github.com/onap/policy-xacml-pdp/blob/master/tutorials/tutorial-xacml-application/src/main/java/org/onap/policy/tutorial/tutorial/TutorialApplication.java>`_.
232
233 .. code-block:: java
234   :caption: Final TutorialApplication Class
235   :linenos:
236   :emphasize-lines: 38
237
238     package org.onap.policy.tutorial.tutorial;
239
240     import java.util.Arrays;
241     import java.util.List;
242     import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier;
243     import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslator;
244     import org.onap.policy.pdp.xacml.application.common.std.StdXacmlApplicationServiceProvider;
245     
246     public class TutorialApplication extends StdXacmlApplicationServiceProvider {
247     
248         private final ToscaPolicyTypeIdentifier supportedPolicyType =
249                 new ToscaPolicyTypeIdentifier("onap.policies.Authorization", "1.0.0");
250         private final TutorialTranslator translator = new TutorialTranslator();
251     
252         @Override
253         public String applicationName() {
254             return "tutorial";
255         }
256     
257         @Override
258         public List<String> actionDecisionsSupported() {
259             return Arrays.asList("authorize");
260         }
261     
262         @Override
263         public synchronized List<ToscaPolicyTypeIdentifier> supportedPolicyTypes() {
264             return Arrays.asList(supportedPolicyType);
265         }
266     
267         @Override
268         public boolean canSupportPolicyType(ToscaPolicyTypeIdentifier policyTypeId) {
269             return supportedPolicyType.equals(policyTypeId);
270         }
271     
272         @Override
273         protected ToscaPolicyTranslator getTranslator(String type) {
274             return translator;
275         }
276     
277     }
278
279 Create a XACML Request from ONAP Decision Request
280 *************************************************
281 The easiest way to do this is to use the annotations feature from XACML PDP library to create an example XACML
282 request. Then create an instance and simply populate it from an incoming ONAP Decision Request.
283
284 .. code-block:: java
285   :caption: Final TutorialApplication Class
286   :linenos:
287     import com.att.research.xacml.std.annotations.XACMLAction;
288     import com.att.research.xacml.std.annotations.XACMLRequest;
289     import com.att.research.xacml.std.annotations.XACMLResource;
290     import com.att.research.xacml.std.annotations.XACMLSubject;
291     import java.util.Map;
292     import java.util.Map.Entry;
293     import lombok.Getter;
294     import lombok.Setter;
295     import lombok.ToString;
296     import org.onap.policy.models.decisions.concepts.DecisionRequest;
297     
298     @Getter
299     @Setter
300     @ToString
301     @XACMLRequest(ReturnPolicyIdList = true)
302     public class TutorialRequest {
303         @XACMLSubject(includeInResults = true)
304         private String onapName;
305
306         @XACMLSubject(attributeId = "urn:org:onap:onap-component", includeInResults = true)
307         private String onapComponent;
308
309         @XACMLSubject(attributeId = "urn:org:onap:onap-instance", includeInResults = true)
310         private String onapInstance;
311
312         @XACMLAction()
313         private String action;
314
315         @XACMLResource(attributeId = "urn:org:onap:tutorial-user", includeInResults = true)
316         private String user;
317
318         @XACMLResource(attributeId = "urn:org:onap:tutorial-entity", includeInResults = true)
319         private String entity;
320
321         @XACMLResource(attributeId = "urn:org:onap:tutorial-permission", includeInResults = true)
322         private String permission;
323
324         /**
325          * createRequest.
326          *
327          * @param decisionRequest Incoming
328          * @return TutorialRequest object
329          */
330         public static TutorialRequest createRequest(DecisionRequest decisionRequest) {
331             //
332             // Create our object
333             //
334             TutorialRequest request = new TutorialRequest();
335             //
336             // Add the subject attributes
337             //
338             request.onapName = decisionRequest.getOnapName();
339             request.onapComponent = decisionRequest.getOnapComponent();
340             request.onapInstance = decisionRequest.getOnapInstance();
341             //
342             // Add the action attribute
343             //
344             request.action = decisionRequest.getAction();
345             //
346             // Add the resource attributes
347             //
348             Map<String, Object> resources = decisionRequest.getResource();
349             for (Entry<String, Object> entrySet : resources.entrySet()) {
350                 if ("user".equals(entrySet.getKey())) {
351                     request.user = entrySet.getValue().toString();
352                 }
353                 if ("entity".equals(entrySet.getKey())) {
354                     request.entity = entrySet.getValue().toString();
355                 }
356                 if ("permission".equals(entrySet.getKey())) {
357                     request.permission = entrySet.getValue().toString();
358                 }
359             }
360
361             return request;
362         }
363     }
364
365 `See the Tutorial Request <https://github.com/onap/policy-xacml-pdp/blob/master/tutorials/tutorial-xacml-application/src/main/java/org/onap/policy/tutorial/tutorial/TutorialRequest.java>`_
366
367 Create a JUnit and use the TestUtils.java class in xacml-test dependency
368 ************************************************************************
369 Be sure to create a JUnit that will test your translator and application code. You can utilize a TestUtils.java
370 class from the policy/xamcl-pdp repo's xacml-test submodule to use some utility methods for building the JUnit test.
371
372 Build the code and run the JUnit test. Its easiest to run it via a terminal command line using maven commands.
373
374 .. code-block:: bash
375    :caption: Running Maven Commands
376    :linenos:
377
378    > mvn clean install
379
380 Building Docker Image
381 *********************
382 To build a docker image that incorporates your application with the XACML PDP Engine. The XACML PDP Engine
383 must be able to *find* your Java.Service in the classpath. This is easy to do, just create a jar file for your application
384 and copy into the same directory used to startup the XACML PDP.
385
386 Here is a Dockerfile as an example:
387
388 .. code-block:: bash
389   :caption: Dockerfile
390   :linenos:
391
392     FROM onap/policy-xacml-pdp
393
394     ADD maven/${project.build.finalName}.jar /opt/app/policy/pdpx/lib/${project.build.finalName}.jar
395
396     RUN mkdir -p /opt/app/policy/pdpx/apps/tutorial
397
398     COPY --chown=policy:policy xacml.properties /opt/app/policy/pdpx/apps/tutorial
399
400 Download Tutorial Application Example
401 *************************************
402
403 If you clone the XACML-PDP repo, the tutorial is included for local testing without building your own.
404
405 `Tutorial code located in xacml-pdp repo <https://github.com/onap/policy-xacml-pdp/tree/master/tutorials/tutorial-xacml-application>`_
406
407 There is an example Docker compose script that you can use to run the Policy Framework components locally and test the tutorial out.
408
409 `Docker compose script <https://github.com/onap/policy-xacml-pdp/blob/master/tutorials/tutorial-xacml-application/src/main/docker/docker-compose.yml>`_
410
411 In addition, there is a POSTMAN collection available for setting up and running tests against a
412 running instance of ONAP Policy Components (api, pap, dmaap-simulator, tutorial-xacml-pdp).
413
414 `POSTMAN collection for testing <https://github.com/onap/policy-xacml-pdp/blob/master/tutorials/tutorial-xacml-application/postman/PolicyApplicationTutorial.postman_collection.json>`_