summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tutorials/tutorial-xacml-application/src/main/java/org/onap/policy/tutorial/tutorial/TutorialRequest.java127
-rw-r--r--tutorials/tutorial-xacml-application/src/main/java/org/onap/policy/tutorial/tutorial/TutorialResponse.java30
-rw-r--r--tutorials/tutorial-xacml-application/src/main/java/org/onap/policy/tutorial/tutorial/TutorialResponsePermission.java28
-rw-r--r--tutorials/tutorial-xacml-application/src/main/java/org/onap/policy/tutorial/tutorial/TutorialTranslator.java80
-rw-r--r--tutorials/tutorial-xacml-application/src/test/java/org/onap/policy/tutorial/tutorial/TutorialApplicationTest.java90
-rw-r--r--tutorials/tutorial-xacml-application/src/test/resources/tutorial-decision-multi-request.json53
6 files changed, 380 insertions, 28 deletions
diff --git a/tutorials/tutorial-xacml-application/src/main/java/org/onap/policy/tutorial/tutorial/TutorialRequest.java b/tutorials/tutorial-xacml-application/src/main/java/org/onap/policy/tutorial/tutorial/TutorialRequest.java
index 356480bc..cda1b436 100644
--- a/tutorials/tutorial-xacml-application/src/main/java/org/onap/policy/tutorial/tutorial/TutorialRequest.java
+++ b/tutorials/tutorial-xacml-application/src/main/java/org/onap/policy/tutorial/tutorial/TutorialRequest.java
@@ -18,10 +18,23 @@
package org.onap.policy.tutorial.tutorial;
+import com.att.research.xacml.api.DataTypeException;
+import com.att.research.xacml.api.Identifier;
+import com.att.research.xacml.api.Request;
+import com.att.research.xacml.api.XACML3;
+import com.att.research.xacml.std.IdentifierImpl;
+import com.att.research.xacml.std.StdAttributeValue;
+import com.att.research.xacml.std.StdMutableAttribute;
+import com.att.research.xacml.std.StdMutableRequest;
+import com.att.research.xacml.std.StdMutableRequestAttributes;
+import com.att.research.xacml.std.StdMutableRequestReference;
+import com.att.research.xacml.std.StdRequestAttributesReference;
+import com.att.research.xacml.std.annotations.RequestParser;
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.List;
import java.util.Map;
import java.util.Map.Entry;
import lombok.Getter;
@@ -34,6 +47,15 @@ import org.onap.policy.models.decisions.concepts.DecisionRequest;
@ToString
@XACMLRequest(ReturnPolicyIdList = true)
public class TutorialRequest {
+ public static final Identifier ATTRIBUTE_ID_MULTIID = new IdentifierImpl("urn:org:onap:tutorial-multi-id");
+ public static final Identifier ATTRIBUTE_ID_USER = new IdentifierImpl("urn:org:onap:tutorial-user");
+ public static final Identifier ATTRIBUTE_ID_ENTITY = new IdentifierImpl("urn:org:onap:tutorial-entity");
+ public static final Identifier ATTRIBUTE_ID_PERMISSION = new IdentifierImpl("urn:org:onap:tutorial-permission");
+ //
+ // For use with a multi request
+ //
+ private static final StdRequestAttributesReference refSubjects = new StdRequestAttributesReference("subjects1");
+ private static final StdRequestAttributesReference refActions = new StdRequestAttributesReference("actions1");
//
// Excluding from results to demonstrate control as to which attributes can be returned.
//
@@ -46,7 +68,7 @@ public class TutorialRequest {
@XACMLSubject(attributeId = "urn:org:onap:onap-instance", includeInResults = false)
private String onapInstance;
- @XACMLAction()
+ @XACMLAction
private String action;
//
@@ -65,9 +87,13 @@ public class TutorialRequest {
* createRequest.
*
* @param decisionRequest Incoming
- * @return TutorialRequest object
+ * @return Request XACML Request object
+ * @throws DataTypeException DataTypeException
+ * @throws IllegalAccessException IllegalAccessException
*/
- public static TutorialRequest createRequest(DecisionRequest decisionRequest) {
+ @SuppressWarnings("unchecked")
+ public static Request createRequest(DecisionRequest decisionRequest)
+ throws IllegalAccessException, DataTypeException {
//
// Create our object
//
@@ -86,6 +112,18 @@ public class TutorialRequest {
// Add the resource attributes
//
Map<String, Object> resources = decisionRequest.getResource();
+ //
+ // Check if this is a multi-request
+ //
+ if (resources.containsKey("users")) {
+ //
+ // Setup the multi-request
+ //
+ return buildMultiRequest(request, (List<Object>) resources.get("users"));
+ }
+ //
+ // Continue as a single request
+ //
for (Entry<String, Object> entrySet : resources.entrySet()) {
if ("user".equals(entrySet.getKey())) {
request.user = entrySet.getValue().toString();
@@ -98,6 +136,87 @@ public class TutorialRequest {
}
}
- return request;
+ return RequestParser.parseRequest(request);
+ }
+
+ @SuppressWarnings("unchecked")
+ protected static Request buildMultiRequest(TutorialRequest existingRequest, List<Object> users)
+ throws IllegalAccessException, DataTypeException {
+ //
+ // Create a single request absorbing the existing attributes, we will copy
+ // them over and assign them an ID.
+ //
+ StdMutableRequest singleRequest = new StdMutableRequest(RequestParser.parseRequest(existingRequest));
+ //
+ // Copy the attributes and assign ID's
+ //
+ StdMutableRequest multiRequest = addMultiRequestIds(singleRequest);
+ //
+ // Iterate and add in the requests
+ //
+ users.forEach(user -> addUser(multiRequest, (Map<String, Object>) user));
+ //
+ // Done
+ //
+ return multiRequest;
+ }
+
+ protected static StdMutableRequest addMultiRequestIds(StdMutableRequest singleRequest) {
+ StdMutableRequest multiRequest = new StdMutableRequest();
+ singleRequest.getRequestAttributes().forEach(attributes -> {
+ StdMutableRequestAttributes newAttributes = new StdMutableRequestAttributes();
+ if (attributes.getCategory().equals(XACML3.ID_SUBJECT_CATEGORY_ACCESS_SUBJECT)) {
+ newAttributes.setCategory(XACML3.ID_SUBJECT_CATEGORY_ACCESS_SUBJECT);
+ newAttributes.setXmlId(refSubjects.getReferenceId());
+ } else if (attributes.getCategory().equals(XACML3.ID_ATTRIBUTE_CATEGORY_ACTION)) {
+ newAttributes.setCategory(XACML3.ID_ATTRIBUTE_CATEGORY_ACTION);
+ newAttributes.setXmlId(refActions.getReferenceId());
+ }
+ attributes.getAttributes().forEach(newAttributes::add);
+ multiRequest.add(newAttributes);
+ });
+ return multiRequest;
+ }
+
+ protected static void addUser(StdMutableRequest multiRequest, Map<String, Object> user) {
+ StdMutableRequestAttributes attributes = new StdMutableRequestAttributes();
+ attributes.setCategory(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
+ for (Entry<String, Object> entrySet : user.entrySet()) {
+ StdAttributeValue<String> value =
+ new StdAttributeValue<>(XACML3.ID_DATATYPE_STRING, entrySet.getValue().toString());
+ StdMutableAttribute attribute = new StdMutableAttribute();
+ attribute.setCategory(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
+ attribute.setIncludeInResults(true);
+ attribute.addValue(value);
+ if ("multiId".equals(entrySet.getKey())) {
+ attributes.setXmlId(entrySet.getValue().toString());
+ attribute.setAttributeId(ATTRIBUTE_ID_MULTIID);
+ } else if ("user".equals(entrySet.getKey())) {
+ attribute.setAttributeId(ATTRIBUTE_ID_USER);
+ } else if ("entity".equals(entrySet.getKey())) {
+ attribute.setAttributeId(ATTRIBUTE_ID_ENTITY);
+ } else if ("permission".equals(entrySet.getKey())) {
+ attribute.setAttributeId(ATTRIBUTE_ID_PERMISSION);
+ } else {
+ throw new IllegalArgumentException("Unknown request attribute given");
+ }
+ attributes.add(attribute);
+ }
+ //
+ // Add the attributes to the Multi-Request
+ //
+ multiRequest.add(attributes);
+ //
+ // Create the references
+ //
+ StdRequestAttributesReference attributesReference = new StdRequestAttributesReference(attributes.getXmlId());
+ StdMutableRequestReference reference = new StdMutableRequestReference();
+ reference.add(refSubjects);
+ reference.add(refActions);
+ reference.add(attributesReference);
+ //
+ // Add the reference to this request
+ //
+ multiRequest.add(reference);
}
}
diff --git a/tutorials/tutorial-xacml-application/src/main/java/org/onap/policy/tutorial/tutorial/TutorialResponse.java b/tutorials/tutorial-xacml-application/src/main/java/org/onap/policy/tutorial/tutorial/TutorialResponse.java
new file mode 100644
index 00000000..7ef6362b
--- /dev/null
+++ b/tutorials/tutorial-xacml-application/src/main/java/org/onap/policy/tutorial/tutorial/TutorialResponse.java
@@ -0,0 +1,30 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.tutorial.tutorial;
+
+import java.util.List;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.onap.policy.models.decisions.concepts.DecisionResponse;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class TutorialResponse extends DecisionResponse {
+ private List<TutorialResponsePermission> permissions;
+}
diff --git a/tutorials/tutorial-xacml-application/src/main/java/org/onap/policy/tutorial/tutorial/TutorialResponsePermission.java b/tutorials/tutorial-xacml-application/src/main/java/org/onap/policy/tutorial/tutorial/TutorialResponsePermission.java
new file mode 100644
index 00000000..5dd03cfb
--- /dev/null
+++ b/tutorials/tutorial-xacml-application/src/main/java/org/onap/policy/tutorial/tutorial/TutorialResponsePermission.java
@@ -0,0 +1,28 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.tutorial.tutorial;
+
+import java.util.Map;
+import lombok.Data;
+
+@Data
+public class TutorialResponsePermission {
+ private String status;
+ private Map<String, Object> attributes;
+}
diff --git a/tutorials/tutorial-xacml-application/src/main/java/org/onap/policy/tutorial/tutorial/TutorialTranslator.java b/tutorials/tutorial-xacml-application/src/main/java/org/onap/policy/tutorial/tutorial/TutorialTranslator.java
index 31bb1037..327a507a 100644
--- a/tutorials/tutorial-xacml-application/src/main/java/org/onap/policy/tutorial/tutorial/TutorialTranslator.java
+++ b/tutorials/tutorial-xacml-application/src/main/java/org/onap/policy/tutorial/tutorial/TutorialTranslator.java
@@ -28,7 +28,7 @@ import com.att.research.xacml.api.Response;
import com.att.research.xacml.api.Result;
import com.att.research.xacml.api.XACML3;
import com.att.research.xacml.std.IdentifierImpl;
-import com.att.research.xacml.std.annotations.RequestParser;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
@@ -93,9 +93,9 @@ public class TutorialTranslator extends StdBaseTranslator {
//
// For simplicity, let's just match on the action "authorize" and the user
//
- var matchAction = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
- XACML3.ID_FUNCTION_STRING_EQUAL, "authorize", XACML3.ID_DATATYPE_STRING,
- XACML3.ID_ACTION_ACTION_ID, XACML3.ID_ATTRIBUTE_CATEGORY_ACTION);
+ var matchAction =
+ ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(XACML3.ID_FUNCTION_STRING_EQUAL, "authorize",
+ XACML3.ID_DATATYPE_STRING, XACML3.ID_ACTION_ACTION_ID, XACML3.ID_ATTRIBUTE_CATEGORY_ACTION);
Map<String, Object> props = toscaPolicy.getProperties();
var user = props.get("user").toString();
var matchUser = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(XACML3.ID_FUNCTION_STRING_EQUAL, user,
@@ -119,9 +119,9 @@ public class TutorialTranslator extends StdBaseTranslator {
((Map<String, String>) permission).get("entity"), XACML3.ID_DATATYPE_STRING, ID_TUTORIAL_ENTITY,
XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
- var matchPermission = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
- XACML3.ID_FUNCTION_STRING_EQUAL, ((Map<String, String>) permission).get("permission"),
- XACML3.ID_DATATYPE_STRING, ID_TUTORIAL_PERM, XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
+ var matchPermission = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(XACML3.ID_FUNCTION_STRING_EQUAL,
+ ((Map<String, String>) permission).get("permission"), XACML3.ID_DATATYPE_STRING, ID_TUTORIAL_PERM,
+ XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
anyOf = new AnyOfType();
anyOf.getAllOf().add(ToscaPolicyTranslatorUtils.buildAllOf(matchEntity, matchPermission));
target = new TargetType();
@@ -147,7 +147,7 @@ public class TutorialTranslator extends StdBaseTranslator {
@Override
public Request convertRequest(DecisionRequest request) {
try {
- return RequestParser.parseRequest(TutorialRequest.createRequest(request));
+ return TutorialRequest.createRequest(request);
} catch (IllegalArgumentException | IllegalAccessException | DataTypeException e) {
// Empty
}
@@ -156,15 +156,59 @@ public class TutorialTranslator extends StdBaseTranslator {
@Override
public DecisionResponse convertResponse(Response xacmlResponse) {
+ //
+ // Single or Multi?
+ //
+ if (xacmlResponse.getResults().size() > 1) {
+ return convertMultiResponse(xacmlResponse);
+ } else {
+ return convertSingleResponse(xacmlResponse.getResults().iterator().next());
+ }
+ }
+
+ protected DecisionResponse convertSingleResponse(Result xacmlResult) {
var decisionResponse = new DecisionResponse();
//
// Setup policies
//
decisionResponse.setPolicies(new HashMap<>());
//
- // Iterate through all the results
+ // Check the result
+ //
+ if (xacmlResult.getDecision() == Decision.PERMIT) {
+ //
+ // This tutorial will simply set the status to Permit
+ //
+ decisionResponse.setStatus(Decision.PERMIT.toString());
+ } else {
+ //
+ // This tutorial will simply set the status to Deny
+ //
+ decisionResponse.setStatus(Decision.DENY.toString());
+ }
+ //
+ // Add attributes use the default scanAttributes. Note that one
+ // could override that method and return the structure as desired.
+ // The attributes returned by default method are in the format
+ // of XACML syntax. It may be more desirable to map them back to
+ // the original request name-value.
+ //
+ if (booleanReturnAttributes) {
+ scanAttributes(xacmlResult.getAttributes(), decisionResponse);
+ }
+ return decisionResponse;
+ }
+
+ protected DecisionResponse convertMultiResponse(Response xacmlResponse) {
+ TutorialResponse decisionResponse = new TutorialResponse();
//
+ // Setup policies
+ //
+ decisionResponse.setPolicies(new HashMap<>());
+ decisionResponse.setStatus("multi");
+ List<TutorialResponsePermission> permissions = new ArrayList<>();
for (Result xacmlResult : xacmlResponse.getResults()) {
+ TutorialResponsePermission permission = new TutorialResponsePermission();
//
// Check the result
//
@@ -172,12 +216,12 @@ public class TutorialTranslator extends StdBaseTranslator {
//
// This tutorial will simply set the status to Permit
//
- decisionResponse.setStatus(Decision.PERMIT.toString());
+ permission.setStatus(Decision.PERMIT.toString());
} else {
//
// This tutorial will simply set the status to Deny
//
- decisionResponse.setStatus(Decision.DENY.toString());
+ permission.setStatus(Decision.DENY.toString());
}
//
// Add attributes use the default scanAttributes. Note that one
@@ -187,10 +231,22 @@ public class TutorialTranslator extends StdBaseTranslator {
// the original request name-value.
//
if (booleanReturnAttributes) {
+ //
+ // Call existing method
+ //
scanAttributes(xacmlResult.getAttributes(), decisionResponse);
+ //
+ // Move from overall response to the individual permission
+ //
+ permission.setAttributes(decisionResponse.getAttributes());
+ decisionResponse.setAttributes(null);
}
+ //
+ // Add it
+ //
+ permissions.add(permission);
}
-
+ decisionResponse.setPermissions(permissions);
return decisionResponse;
}
diff --git a/tutorials/tutorial-xacml-application/src/test/java/org/onap/policy/tutorial/tutorial/TutorialApplicationTest.java b/tutorials/tutorial-xacml-application/src/test/java/org/onap/policy/tutorial/tutorial/TutorialApplicationTest.java
index 66001260..a6f0e944 100644
--- a/tutorials/tutorial-xacml-application/src/test/java/org/onap/policy/tutorial/tutorial/TutorialApplicationTest.java
+++ b/tutorials/tutorial-xacml-application/src/test/java/org/onap/policy/tutorial/tutorial/TutorialApplicationTest.java
@@ -25,6 +25,7 @@ import com.att.research.xacml.api.Response;
import com.att.research.xacml.api.XACML3;
import java.io.File;
import java.io.IOException;
+import java.util.Map;
import java.util.Properties;
import java.util.ServiceLoader;
import org.apache.commons.lang3.tuple.Pair;
@@ -65,8 +66,8 @@ public class TutorialApplicationTest {
// Setup our temporary folder
//
XacmlPolicyUtils.FileCreator myCreator = (String filename) -> policyFolder.newFile(filename);
- propertiesFile = XacmlPolicyUtils.copyXacmlPropertiesContents("src/test/resources/xacml.properties",
- properties, myCreator);
+ propertiesFile = XacmlPolicyUtils.copyXacmlPropertiesContents("src/test/resources/xacml.properties", properties,
+ myCreator);
//
// Load XacmlApplicationServiceProvider service
//
@@ -88,21 +89,20 @@ public class TutorialApplicationTest {
// we just built for it.
//
service.initialize(propertiesFile.toPath().getParent(), null);
- }
-
- @Test
- public void test() throws CoderException, XacmlApplicationException, IOException {
//
// Now load the tutorial policies.
//
TestUtils.loadPolicies("src/test/resources/tutorial-policies.yaml", service);
+ }
+
+ @Test
+ public void testSingleDecision() throws CoderException, XacmlApplicationException, IOException {
//
// Load a Decision request
//
- DecisionRequest decisionRequest = gson.decode(
- TextFileUtils
- .getTextFileAsString("src/test/resources/tutorial-decision-request.json"),
- DecisionRequest.class);
+ DecisionRequest decisionRequest =
+ gson.decode(TextFileUtils.getTextFileAsString("src/test/resources/tutorial-decision-request.json"),
+ DecisionRequest.class);
LOGGER.info("{}", gson.encode(decisionRequest, true));
//
// Test a decision - should start with a permit
@@ -114,7 +114,7 @@ public class TutorialApplicationTest {
// Check that there are attributes
//
assertThat(decision.getLeft().getAttributes()).isNotNull().hasSize(1)
- .containsKey(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE.stringValue());
+ .containsKey(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE.stringValue());
//
// This should be a deny
//
@@ -127,7 +127,73 @@ public class TutorialApplicationTest {
// Check that there are attributes
//
assertThat(decision.getLeft().getAttributes()).isNotNull().hasSize(1)
- .containsKey(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE.stringValue());
+ .containsKey(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE.stringValue());
}
+
+ @Test
+ public void testMultiDecision() throws CoderException, XacmlApplicationException, IOException {
+ //
+ // Load a Decision request
+ //
+ DecisionRequest decisionRequest = gson.decode(
+ TextFileUtils.getTextFileAsString("src/test/resources/tutorial-decision-multi-request.json"),
+ DecisionRequest.class);
+ LOGGER.info("{}", gson.encode(decisionRequest, true));
+ //
+ // Test a decision - should start with a permit
+ //
+ Pair<DecisionResponse, Response> decision = service.makeDecision(decisionRequest, null);
+ LOGGER.info("{}", gson.encode(decision.getLeft(), true));
+ assertEquals("multi", decision.getLeft().getStatus());
+ //
+ // Check that there no attributes for the overall response
+ //
+ assertThat(decision.getLeft().getAttributes()).isNull();
+ //
+ // Check that there are 7 decisions with attributes
+ //
+ assertThat(decision.getLeft()).isInstanceOf(TutorialResponse.class);
+ TutorialResponse tutorialResponse = (TutorialResponse) decision.getLeft();
+ assertThat(tutorialResponse.getPermissions()).hasSize(7);
+ tutorialResponse.getPermissions().forEach(p -> checkPermission(p));
+ }
+
+ private void checkPermission(TutorialResponsePermission permission) {
+ assertThat(permission.getAttributes()).hasSize(1);
+ Object resourceAttributes = permission.getAttributes().get(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE.stringValue());
+ assertThat(resourceAttributes).isNotNull().isInstanceOf(Map.class);
+ @SuppressWarnings("unchecked")
+ String multiId = ((Map<String, String>) resourceAttributes).get("urn:org:onap:tutorial-multi-id").toString();
+ assertThat(Integer.parseInt(multiId)).isBetween(1, 7);
+ switch (multiId) {
+ case "1":
+ assertThat(permission.getStatus()).isEqualTo("Permit");
+ return;
+ case "2":
+ assertThat(permission.getStatus()).isEqualTo("Permit");
+ return;
+ case "3":
+ assertThat(permission.getStatus()).isEqualTo("Deny");
+ return;
+ case "4":
+ assertThat(permission.getStatus()).isEqualTo("Permit");
+ return;
+ case "5":
+ assertThat(permission.getStatus()).isEqualTo("Deny");
+ return;
+ case "6":
+ assertThat(permission.getStatus()).isEqualTo("Deny");
+ return;
+ case "7":
+ assertThat(permission.getStatus()).isEqualTo("Deny");
+ return;
+ default:
+ //
+ // Should not get here as we check the value range in line 168.
+ // But CodeStyle wants a default.
+ //
+ break;
+ }
+ }
}
diff --git a/tutorials/tutorial-xacml-application/src/test/resources/tutorial-decision-multi-request.json b/tutorials/tutorial-xacml-application/src/test/resources/tutorial-decision-multi-request.json
new file mode 100644
index 00000000..9a7425d5
--- /dev/null
+++ b/tutorials/tutorial-xacml-application/src/test/resources/tutorial-decision-multi-request.json
@@ -0,0 +1,53 @@
+{
+ "ONAPName": "TutorialPEP",
+ "ONAPComponent": "TutorialPEPComponent",
+ "ONAPInstance": "TutorialPEPInstance",
+ "requestId": "unique-request-id-tutorial",
+ "action": "authorize",
+ "resource": {
+ "users": [
+ {
+ "multiId": 1,
+ "user": "demo",
+ "entity": "foo",
+ "permission" : "write"
+ },
+ {
+ "multiId": 2,
+ "user": "demo",
+ "entity": "foo",
+ "permission" : "read"
+ },
+ {
+ "multiId": 3,
+ "user": "audit",
+ "entity": "foo",
+ "permission" : "write"
+ },
+ {
+ "multiId": 4,
+ "user": "audit",
+ "entity": "foo",
+ "permission" : "read"
+ },
+ {
+ "multiId": 5,
+ "user": "demo",
+ "entity": "bar",
+ "permission" : "read"
+ },
+ {
+ "multiId": 6,
+ "user": "demo",
+ "entity": "bar",
+ "permission" : "admin"
+ },
+ {
+ "multiId": 7,
+ "user": "ceo",
+ "entity": "bar",
+ "permission" : "read"
+ }
+ ]
+ }
+}