aboutsummaryrefslogtreecommitdiffstats
path: root/docs/xacml/xacml-tutorial.rst
blob: e27533533422285f6dc9cd336d39a2aacb410c47 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
.. This work is licensed under a Creative Commons Attribution 4.0 International License.

.. _xacmltutorial-label:

Policy XACML - Custom Application Tutorial
##########################################

.. toctree::
   :maxdepth: 3

This tutorial shows how to build a XACML application for a Policy Type. Please be sure to clone the
policy repositories before going through the tutorial. See :ref:`policy-development-tools-label` for details.

Design a Policy Type
********************
Follow :ref:`TOSCA Policy Primer <tosca-label>` for more information. For the tutorial, we will use
this example Policy Type in which an ONAP PEP client would like to enforce an action **authorize**
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>`_.

.. literalinclude:: tutorial/tutorial-policy-type.yaml
  :language: yaml
  :caption: Example Tutorial Policy Type
  :linenos:

We would expect then to be able to create the following policies to allow the demo user to Read/Write
an entity called foo, while the audit user can only read the entity called foo. Neither user has Delete
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>`_.

.. literalinclude:: tutorial/tutorial-policies.yaml
  :language: yaml
  :caption: Example Policies Derived From Tutorial Policy Type
  :linenos:

Design Decision Request and expected Decision Response
******************************************************
For the PEP (Policy Enforcement Point) client applications that call the Decision API, you need
to design how the Decision API Request resource fields will be sent via the PEP.

.. literalinclude:: tutorial/tutorial-decision-request.json
  :language: JSON
  :caption: Example Decision Request
  :linenos:

For simplicity, this tutorial expects only a *Permit* or *Deny* in the Decision Response. However, one could
customize the Decision Response object and send back whatever information is desired.

.. literalinclude:: tutorial/tutorial-decision-response.json
  :language: JSON
  :caption: Example Decision Response
  :linenos:

Create A Maven Project
**********************
Use whatever tool or environment to create your application project. This tutorial assumes you use Maven to build it.

Add Dependencies Into Application pom.xml
*****************************************

Here we import the XACML PDP Application common dependency which has the interfaces we need to implement. In addition,
we are importing a testing dependency that has common code for producing a JUnit test.

.. code-block:: java
  :caption: pom.xml dependencies

    <dependency>
      <groupId>org.onap.policy.xacml-pdp.applications</groupId>
      <artifactId>common</artifactId>
      <version>2.3.3</version>
    </dependency>
    <dependency>
      <groupId>org.onap.policy.xacml-pdp</groupId>
      <artifactId>xacml-test</artifactId>
      <version>2.3.3</version>
      <scope>test</scope>
    </dependency>

Create META-INF to expose Java Service
**************************************
The ONAP XACML PDP Engine will not be able to find the tutorial application unless it has
a property file located in src/main/resources/META-INF/services that contains a property file
declaring the class that implements the service.

The name of the file must match **org.onap.policy.pdp.xacml.application.common.XacmlApplicationServiceProvider**
and the contents of the file is one line **org.onap.policy.tutorial.tutorial.TutorialApplication**.

.. code-block:: java
  :caption: META-INF/services/org.onap.policy.pdp.xacml.application.common.XacmlApplicationServiceProvider

    org.onap.policy.tutorial.tutorial.TutorialApplication


Create A Java Class That Extends **StdXacmlApplicationServiceProvider**
***********************************************************************
You could implement **XacmlApplicationServiceProvider** if you wish, but
for simplicity if you just extend **StdXacmlApplicationServiceProvider** you
will get a lot of implementation done for your application up front. All
that needs to be implemented is providing a custom translator.

.. code-block:: java
  :caption: Custom Tutorial Application Service Provider
  :emphasize-lines: 6

  package org.onap.policy.tutorial.tutorial;

  import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslator;
  import org.onap.policy.pdp.xacml.application.common.std.StdXacmlApplicationServiceProvider;

  public class TutorialApplication extends StdXacmlApplicationServiceProvider {

        @Override
        protected ToscaPolicyTranslator getTranslator(String type) {
                // TODO Auto-generated method stub
                return null;
        }

  }

Override Methods for Tutorial
*****************************
Override these methods to differentiate Tutorial from other applications so that the XACML PDP
Engine can determine how to route policy types and policies to the application.

.. code-block:: java
  :caption: Custom Tutorial Application Service Provider

  package org.onap.policy.tutorial.tutorial;

  import java.util.Arrays;
  import java.util.List;

  import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier;
  import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslator;
  import org.onap.policy.pdp.xacml.application.common.std.StdXacmlApplicationServiceProvider;

  public class TutorialApplication extends StdXacmlApplicationServiceProvider {
	
    private final ToscaPolicyTypeIdentifier supportedPolicyType = new ToscaPolicyTypeIdentifier();

    @Override
    public String applicationName() {
        return "tutorial";
    }

    @Override
    public List<String> actionDecisionsSupported() {
        return Arrays.asList("authorize");
    }

    @Override
    public synchronized List<ToscaPolicyTypeIdentifier> supportedPolicyTypes() {
        return Arrays.asList(supportedPolicyType);
    }

    @Override
    public boolean canSupportPolicyType(ToscaPolicyTypeIdentifier policyTypeId) {
    	return supportedPolicyType.equals(policyTypeId);
    }

    @Override
        protected ToscaPolicyTranslator getTranslator(String type) {
        // TODO Auto-generated method stub
        return null;
    }

  }

Create A Translation Class that extends the ToscaPolicyTranslator Class
***********************************************************************
Please be sure to review the existing translators in the policy/xacml-pdp repo to see if they could
be re-used for your policy type. For the tutorial, we will create our own translator.

The custom translator is not only responsible for translating Policies derived from the Tutorial
Policy Type, but also for translating Decision API Requests/Responses to/from the appropriate XACML
requests/response objects the XACML engine understands.  

.. code-block:: java
  :caption: Custom Tutorial Translator Class

  package org.onap.policy.tutorial.tutorial;

  import org.onap.policy.models.decisions.concepts.DecisionRequest;
  import org.onap.policy.models.decisions.concepts.DecisionResponse;
  import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
  import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException;
  import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslator;

  import com.att.research.xacml.api.Request;
  import com.att.research.xacml.api.Response;

  import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType;

  public class TutorialTranslator implements ToscaPolicyTranslator {

    public PolicyType convertPolicy(ToscaPolicy toscaPolicy) throws ToscaPolicyConversionException {
        // TODO Auto-generated method stub
        return null;
    }

    public Request convertRequest(DecisionRequest request) {
        // TODO Auto-generated method stub
        return null;
    }

    public DecisionResponse convertResponse(Response xacmlResponse) {
        // TODO Auto-generated method stub
        return null;
    }

  }

Implement the TutorialTranslator Methods
****************************************
This is the part where knowledge of the XACML OASIS 3.0 specification is required. Please refer to
that specification on the many ways to design a XACML Policy.

For the tutorial, we will build code that translates the TOSCA Policy into one XACML Policy that matches
on the user and action. It will then have one or more rules for each entity and permission combination. The
default combining algorithm for the XACML Rules are to "Deny Unless Permit".

`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.

.. Note::
  There are many ways to build the policy based on the attributes. How to do so is a matter of experience and
  fine tuning using the many options for combining algorithms, target and/or condition matching and the rich set of
  functions available.

Use the TutorialTranslator in the TutorialApplication
*****************************************************
Be sure to go back to the TutorialApplication and create an instance of the translator to return to the
StdXacmlApplicationServiceProvider. The StdXacmlApplicationServiceProvider uses the translator to convert
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>`_.

.. code-block:: java
  :caption: Final TutorialApplication Class
  :linenos:
  :emphasize-lines: 38

    package org.onap.policy.tutorial.tutorial;

    import java.util.Arrays;
    import java.util.List;
    import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier;
    import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslator;
    import org.onap.policy.pdp.xacml.application.common.std.StdXacmlApplicationServiceProvider;
    
    public class TutorialApplication extends StdXacmlApplicationServiceProvider {
    
        private final ToscaPolicyTypeIdentifier supportedPolicyType =
                new ToscaPolicyTypeIdentifier("onap.policies.Authorization", "1.0.0");
        private final TutorialTranslator translator = new TutorialTranslator();
    
        @Override
        public String applicationName() {
            return "tutorial";
        }
    
        @Override
        public List<String> actionDecisionsSupported() {
            return Arrays.asList("authorize");
        }
    
        @Override
        public synchronized List<ToscaPolicyTypeIdentifier> supportedPolicyTypes() {
            return Arrays.asList(supportedPolicyType);
        }
    
        @Override
        public boolean canSupportPolicyType(ToscaPolicyTypeIdentifier policyTypeId) {
            return supportedPolicyType.equals(policyTypeId);
        }
    
        @Override
        protected ToscaPolicyTranslator getTranslator(String type) {
            return translator;
        }
    
    }

Create a XACML Request from ONAP Decision Request
*************************************************
The easiest way to do this is to use the annotations feature from XACML PDP library to create an example XACML
request. Then create an instance and simply populate it from an incoming ONAP Decision Request.

.. code-block:: java
 :caption: Final TutorialApplication Class

    import com.att.research.xacml.std.annotations.XACMLAction;
    import com.att.research.xacml.std.annotations.XACMLRequest;
    import com.att.research.xacml.std.annotations.XACMLResource;
    import com.att.research.xacml.std.annotations.XACMLSubject;
    import java.util.Map;
    import java.util.Map.Entry;
    import lombok.Getter;
    import lombok.Setter;
    import lombok.ToString;
    import org.onap.policy.models.decisions.concepts.DecisionRequest;
    
    @Getter
    @Setter
    @ToString
    @XACMLRequest(ReturnPolicyIdList = true)
    public class TutorialRequest {
        @XACMLSubject(includeInResults = true)
        private String onapName;

        @XACMLSubject(attributeId = "urn:org:onap:onap-component", includeInResults = true)
        private String onapComponent;

        @XACMLSubject(attributeId = "urn:org:onap:onap-instance", includeInResults = true)
        private String onapInstance;

        @XACMLAction()
        private String action;

        @XACMLResource(attributeId = "urn:org:onap:tutorial-user", includeInResults = true)
        private String user;

        @XACMLResource(attributeId = "urn:org:onap:tutorial-entity", includeInResults = true)
        private String entity;

        @XACMLResource(attributeId = "urn:org:onap:tutorial-permission", includeInResults = true)
        private String permission;

        /**
         * createRequest.
         *
         * @param decisionRequest Incoming
         * @return TutorialRequest object
         */
        public static TutorialRequest createRequest(DecisionRequest decisionRequest) {
            //
            // Create our object
            //
            TutorialRequest request = new TutorialRequest();
            //
            // Add the subject attributes
            //
            request.onapName = decisionRequest.getOnapName();
            request.onapComponent = decisionRequest.getOnapComponent();
            request.onapInstance = decisionRequest.getOnapInstance();
            //
            // Add the action attribute
            //
            request.action = decisionRequest.getAction();
            //
            // Add the resource attributes
            //
            Map<String, Object> resources = decisionRequest.getResource();
            for (Entry<String, Object> entrySet : resources.entrySet()) {
                if ("user".equals(entrySet.getKey())) {
                    request.user = entrySet.getValue().toString();
                }
                if ("entity".equals(entrySet.getKey())) {
                    request.entity = entrySet.getValue().toString();
                }
                if ("permission".equals(entrySet.getKey())) {
                    request.permission = entrySet.getValue().toString();
                }
            }

            return request;
        }
    }

`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>`_

Create a JUnit and use the TestUtils.java class in xacml-test dependency
************************************************************************
Be sure to create a JUnit that will test your translator and application code. You can utilize a TestUtils.java
class from the policy/xamcl-pdp repo's xacml-test submodule to use some utility methods for building the JUnit test.

Build the code and run the JUnit test. Its easiest to run it via a terminal command line using maven commands.

.. code-block:: bash
   :caption: Running Maven Commands
   :linenos:

   > mvn clean install


Download Tutorial Application Example
*************************************

If you clone the XACML-PDP repo, the tutorial is included for local testing without building your own.

`Tutorial code located in xacml-pdp repo <https://github.com/onap/policy-xacml-pdp/tree/master/tutorials/tutorial-xacml-application>`_

There are instructions on the repo to run the Policy Framework components locally and test the tutorial out using Docker.

`Docker Instructions <https://github.com/onap/policy-xacml-pdp/tree/master/tutorials/tutorial-xacml-application/src/main/docker>`_

In addition, there is a POSTMAN collection available for setting up and running tests against a
running instance of ONAP Policy Components (api, pap, dmaap-simulator, tutorial-xacml-pdp).

`POSTMAN collection for testing <https://github.com/onap/policy-xacml-pdp/blob/master/tutorials/tutorial-xacml-application/postman/PolicyApplicationTutorial.postman_collection.json>`_