aboutsummaryrefslogtreecommitdiffstats
path: root/tutorials/tutorial-enforcement
diff options
context:
space:
mode:
Diffstat (limited to 'tutorials/tutorial-enforcement')
-rw-r--r--tutorials/tutorial-enforcement/README.md20
-rw-r--r--tutorials/tutorial-enforcement/pom.xml56
-rw-r--r--tutorials/tutorial-enforcement/src/main/docker/README.txt36
-rw-r--r--tutorials/tutorial-enforcement/src/main/docker/config/db/db.conf20
-rw-r--r--tutorials/tutorial-enforcement/src/main/docker/config/db/db.sh26
-rw-r--r--tutorials/tutorial-enforcement/src/main/docker/config/sim/simParameters.json15
-rw-r--r--tutorials/tutorial-enforcement/src/main/docker/docker-compose.yml105
-rw-r--r--tutorials/tutorial-enforcement/src/main/java/org/onap/policy/tutorial/policyenforcement/App.java227
-rw-r--r--tutorials/tutorial-enforcement/src/test/resources/MyAnalytic.yaml16
-rw-r--r--tutorials/tutorial-enforcement/src/test/resources/MyPolicies.yaml14
-rw-r--r--tutorials/tutorial-enforcement/src/test/resources/postman/Policy Enforcement Tutorial.postman_collection.json597
11 files changed, 1132 insertions, 0 deletions
diff --git a/tutorials/tutorial-enforcement/README.md b/tutorials/tutorial-enforcement/README.md
new file mode 100644
index 00000000..23321fd2
--- /dev/null
+++ b/tutorials/tutorial-enforcement/README.md
@@ -0,0 +1,20 @@
+Copyright 2020 AT&T Intellectual Property. All rights reserved.
+This file is licensed under the CREATIVE COMMONS ATTRIBUTION 4.0 INTERNATIONAL LICENSE
+Full license text at https://creativecommons.org/licenses/by/4.0/legalcode
+
+The Policy Enforcement Tutorial can be built:
+
+mvn clean install
+
+Be sure to start the Policy Framework application components if you are not testing this in a lab. See
+src/main/docker/README.txt for details to run local instances of the components.
+
+You can run the application via code by running the App.main method with command line argument with IP then Port
+of the XACML PDP, followed by the IP then Port of Dmaap.
+
+App.main(new String[] {"0.0.0.0", "6969", "0.0.0.0", "3904"});
+
+or from Eclipse by right-clicking App.java and selecting "Run As" and select "Java Application". Edit the
+configuration by adding these command line arguments: "0.0.0.0" "6969" "0.0.0.0" "3904"
+
+Quit the application by typing 'q' into stdin.
diff --git a/tutorials/tutorial-enforcement/pom.xml b/tutorials/tutorial-enforcement/pom.xml
new file mode 100644
index 00000000..d4065a53
--- /dev/null
+++ b/tutorials/tutorial-enforcement/pom.xml
@@ -0,0 +1,56 @@
+<!--
+ ============LICENSE_START=======================================================
+ ONAP Policy Engine - XACML PDP
+ ================================================================================
+ Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ Modifications Copyright (C) 2020 Bell Canada.
+ ================================================================================
+ 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=========================================================
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.policy.xacml-pdp</groupId>
+ <artifactId>xacml-tutorials</artifactId>
+ <version>2.3.4-SNAPSHOT</version>
+ </parent>
+
+ <groupId>org.onap.policy.tutorial</groupId>
+ <artifactId>tutorial-xacml-enforcement</artifactId>
+ <packaging>jar</packaging>
+
+ <name>tutorial-xacml-enforcement</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.policy.models</groupId>
+ <artifactId>policy-models-decisions</artifactId>
+ <version>${policy.models.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.policy.models</groupId>
+ <artifactId>policy-models-pap</artifactId>
+ <version>${policy.models.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.policy.common</groupId>
+ <artifactId>policy-endpoints</artifactId>
+ <version>${policy.common.version}</version>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/tutorials/tutorial-enforcement/src/main/docker/README.txt b/tutorials/tutorial-enforcement/src/main/docker/README.txt
new file mode 100644
index 00000000..eed0a74a
--- /dev/null
+++ b/tutorials/tutorial-enforcement/src/main/docker/README.txt
@@ -0,0 +1,36 @@
+docker-compose -f docker-compose.yml run --rm start_dependencies
+
+docker-compose -f docker-compose.yml run --rm start_all
+
+
+curl -X POST http://0.0.0.0:3904/events/POLICY-PDP-PAP
+
+Should return JSON similar to this:
+{"serverTimeMs":0,"count":0}
+
+
+curl -k -u 'healthcheck:zb!XztG34' 'https://0.0.0.0:6969/policy/pdpx/v1/healthcheck'
+
+Should return JSON similar to this:
+{"name":"Policy Xacml PDP","url":"self","healthy":true,"code":200,"message":"alive"}
+
+
+curl -k -u 'healthcheck:zb!XztG34' 'https://0.0.0.0:6767/policy/api/v1/healthcheck'
+Should return JSON similar to this:
+{
+ "name": "Policy API",
+ "url": "policy-api",
+ "healthy": true,
+ "code": 200,
+ "message": "alive"
+}
+
+curl -k -u 'healthcheck:zb!XztG34' 'https://0.0.0.0:6868/policy/pap/v1/healthcheck'
+{
+ "name": "Policy PAP",
+ "url": "policy-pap",
+ "healthy": true,
+ "code": 200,
+ "message": "alive"
+}
+
diff --git a/tutorials/tutorial-enforcement/src/main/docker/config/db/db.conf b/tutorials/tutorial-enforcement/src/main/docker/config/db/db.conf
new file mode 100644
index 00000000..42f35844
--- /dev/null
+++ b/tutorials/tutorial-enforcement/src/main/docker/config/db/db.conf
@@ -0,0 +1,20 @@
+# ============LICENSE_START=======================================================
+# Copyright (C) 2020 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+MYSQL_ROOT_PASSWORD=secret
+MYSQL_USER=policy_user
+MYSQL_PASSWORD=policy_user \ No newline at end of file
diff --git a/tutorials/tutorial-enforcement/src/main/docker/config/db/db.sh b/tutorials/tutorial-enforcement/src/main/docker/config/db/db.sh
new file mode 100644
index 00000000..499764df
--- /dev/null
+++ b/tutorials/tutorial-enforcement/src/main/docker/config/db/db.sh
@@ -0,0 +1,26 @@
+#!/bin/bash -xv
+# ============LICENSE_START=======================================================
+# Copyright (C) 2020 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+
+for db in policyadmin operationshistory
+do
+ mysql -uroot -p"${MYSQL_ROOT_PASSWORD}" --execute "CREATE DATABASE IF NOT EXISTS ${db};"
+ mysql -uroot -p"${MYSQL_ROOT_PASSWORD}" --execute "GRANT ALL PRIVILEGES ON \`${db}\`.* TO '${MYSQL_USER}'@'%' ;"
+done
+
+mysql -uroot -p"${MYSQL_ROOT_PASSWORD}" --execute "FLUSH PRIVILEGES;"
diff --git a/tutorials/tutorial-enforcement/src/main/docker/config/sim/simParameters.json b/tutorials/tutorial-enforcement/src/main/docker/config/sim/simParameters.json
new file mode 100644
index 00000000..bd435201
--- /dev/null
+++ b/tutorials/tutorial-enforcement/src/main/docker/config/sim/simParameters.json
@@ -0,0 +1,15 @@
+{
+ "dmaapProvider": {
+ "name": "DMaaP simulator",
+ "topicSweepSec": 300
+ },
+ "restServers": [
+ {
+ "name": "DMaaP simulator",
+ "providerClass": "org.onap.policy.models.sim.dmaap.rest.DmaapSimRestControllerV1",
+ "host": "0.0.0.0",
+ "port": 3904,
+ "https": false
+ }
+ ]
+} \ No newline at end of file
diff --git a/tutorials/tutorial-enforcement/src/main/docker/docker-compose.yml b/tutorials/tutorial-enforcement/src/main/docker/docker-compose.yml
new file mode 100644
index 00000000..bf55d0ff
--- /dev/null
+++ b/tutorials/tutorial-enforcement/src/main/docker/docker-compose.yml
@@ -0,0 +1,105 @@
+# ============LICENSE_START=======================================================
+# Copyright (C) 2020 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+version: '2'
+services:
+ mariadb:
+ image: mariadb:10.2.14
+ container_name: mariadb
+ hostname: mariadb
+ command: ['--lower-case-table-names=1', '--wait_timeout=28800']
+ env_file: config/db/db.conf
+ volumes:
+ - ./config/db:/docker-entrypoint-initdb.d
+ expose:
+ - 3306
+ message-router:
+ image: nexus3.onap.org:10001/onap/policy-models-simulator:latest
+ container_name: dmaap-simulator
+ hostname: dmaap-simulator
+ volumes:
+ - ./config/sim:/opt/app/policy/simulators/etc/mounted:ro
+ ports:
+ - "3904:3904"
+ expose:
+ - 3904
+ pap:
+ # Released Guilin image
+ image: nexus3.onap.org:10001/onap/policy-pap:2.3.3
+ container_name: policy-pap
+ depends_on:
+ - mariadb
+ - message-router
+ hostname: policy-pap
+ ports:
+ - "6868:6969"
+ expose:
+ - 6868
+ api:
+ # Released Guilin image
+ image: nexus3.onap.org:10001/onap/policy-api:2.3.3
+ container_name: policy-api
+ depends_on:
+ - mariadb
+ hostname: policy-api
+ ports:
+ - "6767:6969"
+ expose:
+ - 6767
+ xacml-pdp:
+ # Released Guilin image
+ image: nexus3.onap.org:10001/onap/policy-xacml-pdp:2.3.3
+ container_name: policy-xacml-pdp
+ depends_on:
+ - mariadb
+ - message-router
+ - pap
+ hostname: policy-xacml-pdp
+ ports:
+ - "6969:6969"
+ expose:
+ - 6969
+ start_dependencies:
+ image: dadarek/wait-for-dependencies
+ environment:
+ TIMEOUT_LENGTH: 60
+ container_name: policy-wait
+ depends_on:
+ - mariadb
+ - message-router
+ hostname: policy-wait
+ command:
+ mariadb:3306
+ message-router:3904
+ start_all:
+ image: dadarek/wait-for-dependencies
+ environment:
+ TIMEOUT_LENGTH: 60
+ container_name: policy-wait-all
+ depends_on:
+ - mariadb
+ - message-router
+ - api
+ - pap
+ - xacml-pdp
+ hostname: policy-wait-all
+ command:
+ mariadb:3306
+ message-router:3904
+ api:6969
+ pap:6969
+ xacml-pdp:6969
diff --git a/tutorials/tutorial-enforcement/src/main/java/org/onap/policy/tutorial/policyenforcement/App.java b/tutorials/tutorial-enforcement/src/main/java/org/onap/policy/tutorial/policyenforcement/App.java
new file mode 100644
index 00000000..764b3bdf
--- /dev/null
+++ b/tutorials/tutorial-enforcement/src/main/java/org/onap/policy/tutorial/policyenforcement/App.java
@@ -0,0 +1,227 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 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.policyenforcement;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Scanner;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
+import org.onap.policy.common.endpoints.event.comm.TopicEndpointManager;
+import org.onap.policy.common.endpoints.event.comm.TopicListener;
+import org.onap.policy.common.endpoints.event.comm.bus.internal.BusTopicParams;
+import org.onap.policy.common.endpoints.http.client.HttpClient;
+import org.onap.policy.common.endpoints.http.client.HttpClientConfigException;
+import org.onap.policy.common.endpoints.http.client.HttpClientFactoryInstance;
+import org.onap.policy.common.endpoints.parameters.TopicParameterGroup;
+import org.onap.policy.common.endpoints.parameters.TopicParameters;
+import org.onap.policy.common.utils.coder.CoderException;
+import org.onap.policy.common.utils.coder.StandardCoder;
+import org.onap.policy.models.decisions.concepts.DecisionRequest;
+import org.onap.policy.models.decisions.concepts.DecisionResponse;
+import org.onap.policy.models.pap.concepts.PolicyNotification;
+import org.onap.policy.models.pap.concepts.PolicyStatus;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class App extends Thread implements TopicListener {
+ private static Logger logger = LoggerFactory.getLogger(App.class);
+ private static final String MY_POLICYTYPEID = "onap.policies.monitoring.MyAnalytic";
+ private String xacmlPdpHost;
+ private String xacmlPdpPort;
+ private DecisionRequest decisionRequest = new DecisionRequest();
+ private Integer requestId = 1;
+ private HttpClient client = null;
+
+ /**
+ * Constructor.
+ *
+ * @param args Command line arguments
+ */
+ public App(String[] args) {
+ xacmlPdpHost = args[0];
+ xacmlPdpPort = args[1];
+
+ TopicParameters params = new TopicParameters();
+ params.setTopicCommInfrastructure("dmaap");
+ params.setFetchLimit(1);
+ params.setFetchTimeout(5000);
+ params.setTopic("POLICY-NOTIFICATION");
+ params.setServers(Arrays.asList(args[2] + ":" + args[3]));
+ TopicParameterGroup topicParams = new TopicParameterGroup();
+ topicParams.setTopicSources(Arrays.asList(params));
+
+ TopicEndpointManager.getManager().addTopics(topicParams);
+ TopicEndpointManager.getManager().getDmaapTopicSource("POLICY-NOTIFICATION").register(this);
+
+ decisionRequest.setOnapComponent("myComponent");
+ decisionRequest.setOnapName("myName");
+ decisionRequest.setOnapInstance("myInstanceId");
+ decisionRequest.setAction("configure");
+ Map<String, Object> resources = new HashMap<>();
+ resources.put("policy-type", MY_POLICYTYPEID);
+ decisionRequest.setResource(resources);
+ }
+
+ /**
+ * Thread run method that creates a connection and gets an initial Decision on which policy(s)
+ * we should be enforcing.
+ * Then sits waiting for the user to enter q or Q from the keyboard to quit. While waiting,
+ * listen on Dmaap topic for notification that the policy has changed.
+ */
+ @Override
+ public void run() {
+ logger.info("running - type q to stdin to quit");
+ try {
+ client = HttpClientFactoryInstance.getClientFactory().build(BusTopicParams.builder()
+ .clientName("myClientName").useHttps(true).allowSelfSignedCerts(true)
+ .hostname(xacmlPdpHost).port(Integer.parseInt(xacmlPdpPort))
+ .userName("healthcheck").password("zb!XztG34").basePath("policy/pdpx/v1")
+ .managed(true)
+ .serializationProvider("org.onap.policy.common.gson.GsonMessageBodyHandler")
+ .build());
+ } catch (NumberFormatException | HttpClientConfigException e) {
+ logger.error("Could not create Http client", e);
+ return;
+ }
+
+ Map<String, Object> policies = getDecision(client, this.decisionRequest);
+ if (policies.isEmpty()) {
+ logger.info("Not enforcing any policies to start");
+ }
+ for (Entry<String, Object> entrySet : policies.entrySet()) {
+ logger.info("Enforcing: {}", entrySet.getKey());
+ }
+
+ TopicEndpointManager.getManager().start();
+
+ @SuppressWarnings("resource") // never close System.in
+ Scanner input = new Scanner(System.in);
+ while (!Thread.currentThread().isInterrupted()) {
+ String quit = input.nextLine();
+ if ("q".equalsIgnoreCase(quit)) {
+ logger.info("quiting");
+ break;
+ }
+ }
+
+ TopicEndpointManager.getManager().shutdown();
+
+ }
+
+ /**
+ * This method is called when a topic event is received.
+ */
+ @Override
+ public void onTopicEvent(CommInfrastructure infra, String topic, String event) {
+ logger.info("onTopicEvent {}", event);
+ if (scanForPolicyType(event)) {
+ Map<String, Object> newPolicies = getDecision(client, this.decisionRequest);
+ if (newPolicies.isEmpty()) {
+ logger.info("Not enforcing any policies");
+ }
+ for (Entry<String, Object> entrySet : newPolicies.entrySet()) {
+ logger.info("Now Enforcing: {}", entrySet.getKey());
+ }
+ }
+ }
+
+ /**
+ * Helper method that parses a DMaap message event for POLICY-NOTIFICATION
+ * looking for our supported policy type to enforce.
+ *
+ * @param msg Dmaap Message
+ * @return true if MY_POLICYTYPEID is in the message
+ */
+ private boolean scanForPolicyType(String msg) {
+ StandardCoder gson = new StandardCoder();
+ try {
+ PolicyNotification notification = gson.decode(msg, PolicyNotification.class);
+ for (PolicyStatus added : notification.getAdded()) {
+ if (MY_POLICYTYPEID.equals(added.getPolicyTypeId())) {
+ return true;
+ }
+ }
+ for (PolicyStatus deleted : notification.getDeleted()) {
+ if (MY_POLICYTYPEID.equals(deleted.getPolicyTypeId())) {
+ return true;
+ }
+ }
+ } catch (CoderException e) {
+ logger.error("StandardCoder failed to parse PolicyNotification", e);
+ }
+ return false;
+ }
+
+
+ /**
+ * Helper method that calls the XACML PDP Decision API to get a Decision
+ * as to which policy we should be enforcing.
+ *
+ * @param client HttpClient to use to make REST call
+ * @param decisionRequest DecisionRequest object to send
+ * @return The Map of policies that was in the DecisionResponse object
+ */
+ private Map<String, Object> getDecision(HttpClient client, DecisionRequest decisionRequest) {
+ decisionRequest.setRequestId(requestId.toString());
+ requestId++;
+
+ Entity<DecisionRequest> entityRequest =
+ Entity.entity(decisionRequest, MediaType.APPLICATION_JSON);
+ Response response = client.post("/decision", entityRequest, Collections.emptyMap());
+
+ if (response.getStatus() != 200) {
+ logger.error(
+ "Decision API failed - is the IP/port correct? {}", response.getStatus());
+ return Collections.emptyMap();
+ }
+
+ DecisionResponse decisionResponse = HttpClient.getBody(response, DecisionResponse.class);
+
+ return decisionResponse.getPolicies();
+ }
+
+ /**
+ * Our Main application entry point.
+ *
+ * @param args command line arguments
+ */
+ public static void main(String[] args) {
+ logger.info("Hello Welcome to ONAP Enforcement Tutorial!");
+
+ App app = new App(args);
+
+ app.start();
+
+ try {
+ app.join();
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ logger.warn("Thread interrupted");
+ }
+
+ logger.info("Tutorial ended");
+ }
+
+}
diff --git a/tutorials/tutorial-enforcement/src/test/resources/MyAnalytic.yaml b/tutorials/tutorial-enforcement/src/test/resources/MyAnalytic.yaml
new file mode 100644
index 00000000..23cf3c60
--- /dev/null
+++ b/tutorials/tutorial-enforcement/src/test/resources/MyAnalytic.yaml
@@ -0,0 +1,16 @@
+tosca_definitions_version: tosca_simple_yaml_1_1_0
+policy_types:
+ onap.policies.Monitoring:
+ derived_from: tosca.policies.Root
+ version: 1.0.0
+ name: onap.policies.Monitoring
+ description: a base policy type for all policies that govern monitoring provisioning
+ onap.policies.monitoring.MyAnalytic:
+ derived_from: onap.policies.Monitoring
+ type_version: 1.0.0
+ version: 1.0.0
+ description: Example analytic
+ properties:
+ myProperty:
+ type: string
+ required: true \ No newline at end of file
diff --git a/tutorials/tutorial-enforcement/src/test/resources/MyPolicies.yaml b/tutorials/tutorial-enforcement/src/test/resources/MyPolicies.yaml
new file mode 100644
index 00000000..00c5ef91
--- /dev/null
+++ b/tutorials/tutorial-enforcement/src/test/resources/MyPolicies.yaml
@@ -0,0 +1,14 @@
+tosca_definitions_version: tosca_simple_yaml_1_1_0
+topology_template:
+ policies:
+ -
+ policy1:
+ type: onap.policies.monitoring.MyAnalytic
+ type_version: 1.0.0
+ version: 1.0.0
+ name: policy1
+ metadata:
+ policy-id: policy1
+ policy-version: 1.0.0
+ properties:
+ myProperty: value1 \ No newline at end of file
diff --git a/tutorials/tutorial-enforcement/src/test/resources/postman/Policy Enforcement Tutorial.postman_collection.json b/tutorials/tutorial-enforcement/src/test/resources/postman/Policy Enforcement Tutorial.postman_collection.json
new file mode 100644
index 00000000..85de39be
--- /dev/null
+++ b/tutorials/tutorial-enforcement/src/test/resources/postman/Policy Enforcement Tutorial.postman_collection.json
@@ -0,0 +1,597 @@
+{
+ "info": {
+ "_postman_id": "f00b4c77-8f4b-423f-a132-2bcdd4adf598",
+ "name": "Policy Enforcement Tutorial",
+ "description": "Collection of Postman API calls to support the Policy Enforcement Tutorial",
+ "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
+ },
+ "item": [
+ {
+ "name": "Api Healthcheck",
+ "request": {
+ "auth": {
+ "type": "basic",
+ "basic": [
+ {
+ "key": "password",
+ "value": "zb!XztG34",
+ "type": "string"
+ },
+ {
+ "key": "username",
+ "value": "healthcheck",
+ "type": "string"
+ }
+ ]
+ },
+ "method": "GET",
+ "header": [
+ {
+ "key": "Content-Type",
+ "type": "text",
+ "value": "application/json"
+ },
+ {
+ "key": "Accept",
+ "type": "text",
+ "value": "application/json"
+ }
+ ],
+ "url": {
+ "raw": "https://0.0.0.0:6767/policy/api/v1/healthcheck",
+ "protocol": "https",
+ "host": [
+ "0",
+ "0",
+ "0",
+ "0"
+ ],
+ "port": "6767",
+ "path": [
+ "policy",
+ "api",
+ "v1",
+ "healthcheck"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Create MyAnalytic Policy Type",
+ "request": {
+ "auth": {
+ "type": "basic",
+ "basic": [
+ {
+ "key": "password",
+ "value": "zb!XztG34",
+ "type": "string"
+ },
+ {
+ "key": "username",
+ "value": "healthcheck",
+ "type": "string"
+ }
+ ]
+ },
+ "method": "POST",
+ "header": [
+ {
+ "key": "Accept",
+ "type": "text",
+ "value": "application/yaml"
+ },
+ {
+ "key": "Content-Type",
+ "type": "text",
+ "value": "application/yaml"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "tosca_definitions_version: tosca_simple_yaml_1_1_0\npolicy_types:\n onap.policies.Monitoring:\n derived_from: tosca.policies.Root\n version: 1.0.0\n name: onap.policies.Monitoring\n description: a base policy type for all policies that govern monitoring provisioning\n onap.policies.monitoring.MyAnalytic:\n derived_from: onap.policies.Monitoring\n type_version: 1.0.0\n version: 1.0.0\n description: Example analytic\n properties:\n myProperty:\n type: string\n required: true"
+ },
+ "url": {
+ "raw": "https://0.0.0.0:6767/policy/api/v1/policytypes",
+ "protocol": "https",
+ "host": [
+ "0",
+ "0",
+ "0",
+ "0"
+ ],
+ "port": "6767",
+ "path": [
+ "policy",
+ "api",
+ "v1",
+ "policytypes"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Create policy1 MyAnalytic Policy",
+ "request": {
+ "auth": {
+ "type": "basic",
+ "basic": [
+ {
+ "key": "password",
+ "value": "zb!XztG34",
+ "type": "string"
+ },
+ {
+ "key": "username",
+ "value": "healthcheck",
+ "type": "string"
+ }
+ ]
+ },
+ "method": "POST",
+ "header": [
+ {
+ "key": "Accept",
+ "type": "text",
+ "value": "application/yaml"
+ },
+ {
+ "key": "Content-Type",
+ "type": "text",
+ "value": "application/yaml"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "tosca_definitions_version: tosca_simple_yaml_1_1_0\ntopology_template:\n policies:\n -\n policy1:\n type: onap.policies.monitoring.MyAnalytic\n type_version: 1.0.0\n version: 1.0.0\n name: policy1\n metadata:\n policy-id: policy1\n policy-version: 1.0.0\n properties:\n myProperty: value1\n "
+ },
+ "url": {
+ "raw": "https://0.0.0.0:6767/policy/api/v1/policytypes/onap.policies.monitoring.MyAnalytic/versions/1.0.0/policies",
+ "protocol": "https",
+ "host": [
+ "0",
+ "0",
+ "0",
+ "0"
+ ],
+ "port": "6767",
+ "path": [
+ "policy",
+ "api",
+ "v1",
+ "policytypes",
+ "onap.policies.monitoring.MyAnalytic",
+ "versions",
+ "1.0.0",
+ "policies"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "PAP Healthcheck",
+ "request": {
+ "auth": {
+ "type": "basic",
+ "basic": [
+ {
+ "key": "password",
+ "value": "zb!XztG34",
+ "type": "string"
+ },
+ {
+ "key": "username",
+ "value": "healthcheck",
+ "type": "string"
+ }
+ ]
+ },
+ "method": "GET",
+ "header": [
+ {
+ "key": "Content-Type",
+ "type": "text",
+ "value": "application/json"
+ },
+ {
+ "key": "Accept",
+ "type": "text",
+ "value": "application/json"
+ }
+ ],
+ "url": {
+ "raw": "https://0.0.0.0:6868/policy/pap/v1/healthcheck",
+ "protocol": "https",
+ "host": [
+ "0",
+ "0",
+ "0",
+ "0"
+ ],
+ "port": "6868",
+ "path": [
+ "policy",
+ "pap",
+ "v1",
+ "healthcheck"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "PAP Get PDPs",
+ "request": {
+ "auth": {
+ "type": "basic",
+ "basic": [
+ {
+ "key": "password",
+ "value": "zb!XztG34",
+ "type": "string"
+ },
+ {
+ "key": "username",
+ "value": "healthcheck",
+ "type": "string"
+ }
+ ]
+ },
+ "method": "GET",
+ "header": [
+ {
+ "key": "Accept",
+ "type": "text",
+ "value": "application/json"
+ },
+ {
+ "key": "Content-Type",
+ "type": "text",
+ "value": "application/json"
+ }
+ ],
+ "url": {
+ "raw": "https://0.0.0.0:6868/policy/pap/v1/pdps",
+ "protocol": "https",
+ "host": [
+ "0",
+ "0",
+ "0",
+ "0"
+ ],
+ "port": "6868",
+ "path": [
+ "policy",
+ "pap",
+ "v1",
+ "pdps"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Simple Deploy Policy - policy1",
+ "request": {
+ "auth": {
+ "type": "basic",
+ "basic": [
+ {
+ "key": "password",
+ "value": "zb!XztG34",
+ "type": "string"
+ },
+ {
+ "key": "username",
+ "value": "healthcheck",
+ "type": "string"
+ }
+ ]
+ },
+ "method": "POST",
+ "header": [
+ {
+ "key": "Content-Type",
+ "type": "text",
+ "value": "application/json"
+ },
+ {
+ "key": "Accept",
+ "type": "text",
+ "value": "application/json"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\r\n \"policies\" : [\r\n {\r\n \"policy-id\": \"policy1\",\r\n \"policy-version\": \"1.0.0\"\r\n }\r\n ]\r\n}"
+ },
+ "url": {
+ "raw": "{https://0.0.0.0:6868/policy/pap/v1/pdps/policies",
+ "protocol": "{https",
+ "host": [
+ "0",
+ "0",
+ "0",
+ "0"
+ ],
+ "port": "6868",
+ "path": [
+ "policy",
+ "pap",
+ "v1",
+ "pdps",
+ "policies"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Xacml Healthcheck",
+ "request": {
+ "auth": {
+ "type": "basic",
+ "basic": [
+ {
+ "key": "password",
+ "value": "zb!XztG34",
+ "type": "string"
+ },
+ {
+ "key": "username",
+ "value": "healthcheck",
+ "type": "string"
+ }
+ ]
+ },
+ "method": "GET",
+ "header": [
+ {
+ "key": "Content-Type",
+ "type": "text",
+ "value": "application/json"
+ },
+ {
+ "key": "Accept",
+ "type": "text",
+ "value": "application/json"
+ }
+ ],
+ "url": {
+ "raw": "https://0.0.0.0:6969/policy/pdpx/v1/healthcheck",
+ "protocol": "https",
+ "host": [
+ "0",
+ "0",
+ "0",
+ "0"
+ ],
+ "port": "6969",
+ "path": [
+ "policy",
+ "pdpx",
+ "v1",
+ "healthcheck"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Xacml Statistics",
+ "request": {
+ "auth": {
+ "type": "basic",
+ "basic": [
+ {
+ "key": "password",
+ "value": "zb!XztG34",
+ "type": "string"
+ },
+ {
+ "key": "username",
+ "value": "healthcheck",
+ "type": "string"
+ }
+ ]
+ },
+ "method": "GET",
+ "header": [
+ {
+ "key": "Content-Type",
+ "type": "text",
+ "value": "application/json"
+ },
+ {
+ "key": "Accept",
+ "type": "text",
+ "value": "application/json"
+ }
+ ],
+ "url": {
+ "raw": "https://0.0.0.0:6969/policy/pdpx/v1/healthcheck",
+ "protocol": "https",
+ "host": [
+ "0",
+ "0",
+ "0",
+ "0"
+ ],
+ "port": "6969",
+ "path": [
+ "policy",
+ "pdpx",
+ "v1",
+ "healthcheck"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Xacml Decision - MyAnalytic policy-type",
+ "request": {
+ "auth": {
+ "type": "basic",
+ "basic": [
+ {
+ "key": "password",
+ "value": "zb!XztG34",
+ "type": "string"
+ },
+ {
+ "key": "username",
+ "value": "healthcheck",
+ "type": "string"
+ }
+ ]
+ },
+ "method": "POST",
+ "header": [
+ {
+ "key": "Content-Type",
+ "type": "text",
+ "value": "application/json"
+ },
+ {
+ "key": "Accept",
+ "type": "text",
+ "value": "application/json"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"ONAPName\": \"myName\",\n \"ONAPComponent\": \"myComponent\",\n \"ONAPInstance\": \"myInstanceId\",\n \"requestId\": \"1\",\n \"action\": \"configure\",\n \"resource\": {\n \"policy-type\": \"onap.policies.monitoring.MyAnalytic\"\n }\n}"
+ },
+ "url": {
+ "raw": "https://0.0.0.0:6969/policy/pdpx/v1/decision",
+ "protocol": "https",
+ "host": [
+ "0",
+ "0",
+ "0",
+ "0"
+ ],
+ "port": "6969",
+ "path": [
+ "policy",
+ "pdpx",
+ "v1",
+ "decision"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Dmaap Simulator - Policy Update Notification",
+ "request": {
+ "auth": {
+ "type": "noauth"
+ },
+ "method": "POST",
+ "header": [
+ {
+ "key": "Content-Type",
+ "type": "text",
+ "value": "application/json"
+ },
+ {
+ "key": "Accept",
+ "type": "text",
+ "value": "application/json"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"messageName\": \"PDP_STATE_CHANGE\",\n \"requestId\": \"05d08a05-e182-46fa-a6d1-5500e52cd3e5\",\n \"timestampMs\": \"1576598570797\", \n \"name\": \"PamelaDragosh.local\",\n \"pdpGroup\": \"defaultGroup\",\n \"pdpSubgroup\":\"XacmlPdpGroup\",\n \"state\":\"ACTIVE\"\n}"
+ },
+ "url": {
+ "raw": "http://localhost:3904/events/POLICY-PDP-PAP",
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "3904",
+ "path": [
+ "events",
+ "POLICY-PDP-PAP"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Simple Undeploy Policy Copy",
+ "request": {
+ "auth": {
+ "type": "basic",
+ "basic": [
+ {
+ "key": "password",
+ "value": "zb!XztG34",
+ "type": "string"
+ },
+ {
+ "key": "username",
+ "value": "healthcheck",
+ "type": "string"
+ }
+ ]
+ },
+ "method": "DELETE",
+ "header": [
+ {
+ "key": "Accept",
+ "value": "application/json",
+ "type": "text"
+ },
+ {
+ "key": "Content-Type",
+ "value": "application/json",
+ "type": "text"
+ }
+ ],
+ "url": {
+ "raw": "https://0.0.0.0:6868/policy/pap/v1/pdps/policies/onap.policies.monitoring.MyAnalytic",
+ "protocol": "https",
+ "host": [
+ "0",
+ "0",
+ "0",
+ "0"
+ ],
+ "port": "6868",
+ "path": [
+ "policy",
+ "pap",
+ "v1",
+ "pdps",
+ "policies",
+ "onap.policies.monitoring.MyAnalytic"
+ ]
+ }
+ },
+ "response": []
+ }
+ ],
+ "auth": {
+ "type": "basic",
+ "basic": [
+ {
+ "key": "password",
+ "value": "",
+ "type": "string"
+ },
+ {
+ "key": "username",
+ "value": "",
+ "type": "string"
+ }
+ ]
+ },
+ "protocolProfileBehavior": {}
+} \ No newline at end of file