From: Pamela Dragosh Date: Mon, 26 Oct 2020 13:59:09 +0000 (-0400) Subject: Submit Policy Tutorials X-Git-Url: https://gerrit.onap.org/r/gitweb?a=commitdiff_plain;h=c9c871660267ab9a43406cfd02e356309cf7a558;p=policy%2Fxacml-pdp.git Submit Policy Tutorials So app developers can more easily download and test client code etc. Issue-ID: POLICY-2876 Change-Id: I360cd0d637150cd0c2353c6284803f4438e96556 Signed-off-by: Pamela Dragosh (cherry picked from commit f0bd7f421948415b1c2f05cb39674f57f72218e0) --- diff --git a/pom.xml b/pom.xml index 53e215a8..82889ffd 100644 --- a/pom.xml +++ b/pom.xml @@ -51,6 +51,7 @@ packages testsuites xacml-test + tutorials diff --git a/tutorials/pom.xml b/tutorials/pom.xml new file mode 100644 index 00000000..66a1892e --- /dev/null +++ b/tutorials/pom.xml @@ -0,0 +1,47 @@ + + + + 4.0.0 + + org.onap.policy.xacml-pdp + policy-xacml-pdp + 2.3.4-SNAPSHOT + + + xacml-tutorials + pom + + ${project.artifactId} + This sub-module holds the XACML PDP Application Tutorials. + + + + true + + + + tutorial-xacml-application + tutorial-enforcement + + + 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 @@ + + + + 4.0.0 + + + org.onap.policy.xacml-pdp + xacml-tutorials + 2.3.4-SNAPSHOT + + + org.onap.policy.tutorial + tutorial-xacml-enforcement + jar + + tutorial-xacml-enforcement + + + + org.onap.policy.models + policy-models-decisions + ${policy.models.version} + + + org.onap.policy.models + policy-models-pap + ${policy.models.version} + + + org.onap.policy.common + policy-endpoints + ${policy.common.version} + + + + 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 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 policies = getDecision(client, this.decisionRequest); + if (policies.isEmpty()) { + logger.info("Not enforcing any policies to start"); + } + for (Entry 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 newPolicies = getDecision(client, this.decisionRequest); + if (newPolicies.isEmpty()) { + logger.info("Not enforcing any policies"); + } + for (Entry 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 getDecision(HttpClient client, DecisionRequest decisionRequest) { + decisionRequest.setRequestId(requestId.toString()); + requestId++; + + Entity 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 diff --git a/tutorials/tutorial-xacml-application/pom.xml b/tutorials/tutorial-xacml-application/pom.xml new file mode 100644 index 00000000..aa776a8d --- /dev/null +++ b/tutorials/tutorial-xacml-application/pom.xml @@ -0,0 +1,101 @@ + + + + 4.0.0 + + + org.onap.policy.xacml-pdp + xacml-tutorials + 2.3.4-SNAPSHOT + + + org.onap.policy.tutorial.xacml-application + tutorial-xacml-application + jar + + tutorial-xacml-application + + + + true + + + + + org.onap.policy.xacml-pdp.applications + common + ${project.version} + + + org.onap.policy.xacml-pdp + xacml-test + ${project.version} + test + + + + + + docker + + + + io.fabric8 + docker-maven-plugin + + true + + + onap/policy-xacml-tutorial + xacml-pdp + + ${project.basedir}/src/main/docker + + artifact-with-dependencies + + + + + + + + clean-images + pre-clean + + remove + + + + generate-images + package + + build + + + + + + + + + diff --git a/tutorials/tutorial-xacml-application/postman/PolicyApplicationTutorial.postman_collection.json b/tutorials/tutorial-xacml-application/postman/PolicyApplicationTutorial.postman_collection.json new file mode 100644 index 00000000..dbb1e0d1 --- /dev/null +++ b/tutorials/tutorial-xacml-application/postman/PolicyApplicationTutorial.postman_collection.json @@ -0,0 +1,738 @@ +{ + "info": { + "_postman_id": "20eb42db-f0a7-4b65-8ccd-c3a5f56cb526", + "name": "Policy Application 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": "{{POLICY-API-URL}}/policy/api/v1/healthcheck", + "host": [ + "{{POLICY-API-URL}}" + ], + "path": [ + "policy", + "api", + "v1", + "healthcheck" + ] + } + }, + "response": [ + ] + }, + { + "name": "Create Authorization 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.Authorization:\n derived_from: tosca.policies.Root\n version: 1.0.0\n description: Example tutorial policy type for doing user authorization\n properties:\n user:\n type: string\n required: true\n description: The unique user name\n permissions:\n type: list\n required: true\n description: A list of resource permissions\n entry_schema:\n type: onap.datatypes.Tutorial\ndata_types:\n onap.datatypes.Tutorial:\n derived_from: tosca.datatypes.Root\n version: 1.0.0\n properties:\n entity:\n type: string\n required: true\n description: The resource\n permission:\n type: string\n required: true\n description: The permission level\n constraints:\n - valid_values: [read, write, delete]\n", + "options": { + "raw": { + "language": "text" + } + } + }, + "url": { + "raw": "{{POLICY-API-URL}}/policy/api/v1/policytypes", + "host": [ + "{{POLICY-API-URL}}" + ], + "path": [ + "policy", + "api", + "v1", + "policytypes" + ] + } + }, + "response": [ + ] + }, + { + "name": "Create policies", + "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 onap.policy.tutorial.demo:\n type: onap.policies.Authorization\n type_version: 1.0.0\n version: 1.0.0\n metadata:\n policy-id: onap.policy.tutorial.demo\n policy-version: 1\n properties:\n user: demo\n permissions:\n -\n entity: foo\n permission: read\n -\n entity: foo\n permission: write\n -\n onap.policy.tutorial.audit:\n type: onap.policies.Authorization\n version: 1.0.0\n type_version: 1.0.0\n metadata:\n policy-id: onap.policy.tutorial.bar\n policy-version: 1\n properties:\n user: audit\n permissions:\n -\n entity: foo\n permission: read\n", + "options": { + "raw": { + "language": "text" + } + } + }, + "url": { + "raw": "{{POLICY-API-URL}}/policy/api/v1/policytypes/onap.policies.Authorization/versions/1.0.0/policies", + "host": [ + "{{POLICY-API-URL}}" + ], + "path": [ + "policy", + "api", + "v1", + "policytypes", + "onap.policies.Authorization", + "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": "{{POLICY-PAP-URL}}/policy/pap/v1/healthcheck", + "host": [ + "{{POLICY-PAP-URL}}" + ], + "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": "{{POLICY-PAP-URL}}/policy/pap/v1/pdps", + "host": [ + "{{POLICY-PAP-URL}}" + ], + "path": [ + "policy", + "pap", + "v1", + "pdps" + ] + } + }, + "response": [ + ] + }, + { + "name": "PdpGroup State Change PASSIVE", + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "zb!XztG34", + "type": "string" + }, + { + "key": "username", + "value": "healthcheck", + "type": "string" + } + ] + }, + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + }, + { + "key": "Accept", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{POLICY-PAP-URL}}/policy/pap/v1/pdps/groups/defaultGroup?state=PASSIVE", + "host": [ + "{{POLICY-PAP-URL}}" + ], + "path": [ + "policy", + "pap", + "v1", + "pdps", + "groups", + "defaultGroup" + ], + "query": [ + { + "key": "state", + "value": "PASSIVE" + } + ] + }, + "description": "This is an API to change the current state of a PdpGroup (example - \"defaultGroup\") resulting in changing state of all the PDP instances registered with the PdpGroup. As of now, the allowed states are ACTIVE and PASSIVE." + }, + "response": [ + ] + }, + { + "name": "Delete PdpGroup", + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "zb!XztG34", + "type": "string" + }, + { + "key": "username", + "value": "healthcheck", + "type": "string" + } + ] + }, + "method": "DELETE", + "header": [ + { + "key": "Accept", + "type": "text", + "value": "application/json" + }, + { + "key": "Content-Type", + "type": "text", + "value": "application/json" + } + ], + "url": { + "raw": "{{POLICY-PAP-URL}}/policy/pap/v1/pdps/groups/defaultGroup", + "host": [ + "{{POLICY-PAP-URL}}" + ], + "path": [ + "policy", + "pap", + "v1", + "pdps", + "groups", + "defaultGroup" + ] + }, + "description": "This is an API to delete a specific PdpGroup (example - \"SampleGroup\") currently available in Policy DB, resulting in removing all the PDP instances registered with the group." + }, + "response": [ + ] + }, + { + "name": "Create/Update PdpGroup", + "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 \"groups\": [\n {\n \"name\": \"defaultGroup\",\n \"pdpGroupState\": \"ACTIVE\",\n \"properties\": {},\n \"pdpSubgroups\": [\n {\n \"pdpType\": \"xacml\",\n \"desiredInstanceCount\": 1,\n \"properties\": {},\n \"supportedPolicyTypes\": [\n {\n \"name\": \"onap.policies.Authorization\",\n \"version\": \"1.0.0\"\n }\n ],\n \"policies\": []\n }\n ]\n }\n ]\n}" + }, + "url": { + "raw": "{{POLICY-PAP-URL}}/policy/pap/v1/pdps/groups/batch", + "host": [ + "{{POLICY-PAP-URL}}" + ], + "path": [ + "policy", + "pap", + "v1", + "pdps", + "groups", + "batch" + ] + }, + "description": "This is a generic API to create/update PdpGroups in Policy DB. However, the supportedPolicyTypes field of PdpSubGroup cannot be changed once created." + }, + "response": [ + ] + }, + { + "name": "Simple Deploy Policy - onap.policy.tutorial.demo", + "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\": \"onap.policy.tutorial.demo\",\r\n \"policy-version\": \"1.0.0\"\r\n },\r\n {\r\n \"policy-id\": \"onap.policy.tutorial.audit\",\r\n \"policy-version\": \"1.0.0\"\r\n }\r\n ]\r\n}" + }, + "url": { + "raw": "{{POLICY-PAP-URL}}/policy/pap/v1/pdps/policies", + "host": [ + "{{POLICY-PAP-URL}}" + ], + "path": [ + "policy", + "pap", + "v1", + "pdps", + "policies" + ] + } + }, + "response": [ + ] + }, + { + "name": "Dmaap Simulator - Policy Update Notification", + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "auth": { + "type": "noauth" + }, + "method": "GET", + "header": [ + { + "key": "Content-Type", + "type": "text", + "value": "application/json" + }, + { + "key": "Accept", + "type": "text", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{DMAAP-URL}}/events/POLICY-NOTIFICATION/group/id?timeout=5000", + "host": [ + "{{DMAAP-URL}}" + ], + "path": [ + "events", + "POLICY-NOTIFICATION", + "group", + "id" + ], + "query": [ + { + "key": "timeout", + "value": "5000" + } + ] + } + }, + "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": "{{POLICY-XACML-URL}}/policy/pdpx/v1/healthcheck", + "host": [ + "{{POLICY-XACML-URL}}" + ], + "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": "{{POLICY-XACML-URL}}/policy/pdpx/v1/statistics", + "host": [ + "{{POLICY-XACML-URL}}" + ], + "path": [ + "policy", + "pdpx", + "v1", + "statistics" + ] + } + }, + "response": [ + ] + }, + { + "name": "Xacml Decision - Authorization 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\": \"TutorialPEP\",\n \"ONAPComponent\": \"TutorialPEPComponent\",\n \"ONAPInstance\": \"TutorialPEPInstance\",\n \"requestId\": \"unique-request-id-tutorial\",\n \"action\": \"authorize\",\n \"resource\": {\n \"user\": \"audit\",\n \"entity\": \"foo\",\n \"permission\" : \"read\"\n }\n}" + }, + "url": { + "raw": "{{POLICY-XACML-URL}}/policy/pdpx/v1/decision", + "host": [ + "{{POLICY-XACML-URL}}" + ], + "path": [ + "policy", + "pdpx", + "v1", + "decision" + ] + } + }, + "response": [ + ] + }, + { + "name": "Simple Undeploy Policy", + "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": "{{POLICY-PAP-URL}}/policy/pap/v1/pdps/policies/onap.policy.tutorial.demo", + "host": [ + "{{POLICY-PAP-URL}}" + ], + "path": [ + "policy", + "pap", + "v1", + "pdps", + "policies", + "onap.policy.tutorial.demo" + ] + } + }, + "response": [ + ] + } + ], + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "", + "type": "string" + }, + { + "key": "username", + "value": "", + "type": "string" + } + ] + }, + "protocolProfileBehavior": { + } +} diff --git a/tutorials/tutorial-xacml-application/src/main/docker/Dockerfile b/tutorials/tutorial-xacml-application/src/main/docker/Dockerfile new file mode 100644 index 00000000..26106512 --- /dev/null +++ b/tutorials/tutorial-xacml-application/src/main/docker/Dockerfile @@ -0,0 +1,7 @@ +FROM onap/policy-xacml-pdp + +ADD maven/${project.build.finalName}.jar /opt/app/policy/pdpx/lib/${project.build.finalName}.jar + +RUN mkdir -p /opt/app/policy/pdpx/apps/tutorial + +COPY --chown=policy:policy xacml.properties /opt/app/policy/pdpx/apps/tutorial \ No newline at end of file diff --git a/tutorials/tutorial-xacml-application/src/main/docker/README.txt b/tutorials/tutorial-xacml-application/src/main/docker/README.txt new file mode 100644 index 00000000..a29a44b2 --- /dev/null +++ b/tutorials/tutorial-xacml-application/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' +Should return JSON similar to this: +{ + "name": "Policy PAP", + "url": "policy-pap", + "healthy": true, + "code": 200, + "message": "alive" +} \ No newline at end of file diff --git a/tutorials/tutorial-xacml-application/src/main/docker/config/db/db.conf b/tutorials/tutorial-xacml-application/src/main/docker/config/db/db.conf new file mode 100644 index 00000000..42f35844 --- /dev/null +++ b/tutorials/tutorial-xacml-application/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-xacml-application/src/main/docker/config/db/db.sh b/tutorials/tutorial-xacml-application/src/main/docker/config/db/db.sh new file mode 100644 index 00000000..499764df --- /dev/null +++ b/tutorials/tutorial-xacml-application/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-xacml-application/src/main/docker/config/sim/simParameters.json b/tutorials/tutorial-xacml-application/src/main/docker/config/sim/simParameters.json new file mode 100644 index 00000000..bd435201 --- /dev/null +++ b/tutorials/tutorial-xacml-application/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-xacml-application/src/main/docker/docker-compose.yml b/tutorials/tutorial-xacml-application/src/main/docker/docker-compose.yml new file mode 100644 index 00000000..2809f646 --- /dev/null +++ b/tutorials/tutorial-xacml-application/src/main/docker/docker-compose.yml @@ -0,0 +1,106 @@ +# ============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 + api: + # Guilin released images + 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 + pap: + # Guilin released images + image: nexus3.onap.org:10001/onap/policy-pap:2.3.3 + container_name: policy-pap + depends_on: + - mariadb + - message-router + - api + hostname: policy-pap + ports: + - "6868:6969" + expose: + - 6868 + xacml-pdp: + image: onap/policy-xacml-tutorial + container_name: policy-xacml-pdp + depends_on: + - mariadb + - message-router + - api + - 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-xacml-application/src/main/docker/xacml.properties b/tutorials/tutorial-xacml-application/src/main/docker/xacml.properties new file mode 100644 index 00000000..277b098e --- /dev/null +++ b/tutorials/tutorial-xacml-application/src/main/docker/xacml.properties @@ -0,0 +1,31 @@ +# +# Properties that the embedded PDP engine uses to configure and load +# +# Standard API Factories +# +xacml.dataTypeFactory=com.att.research.xacml.std.StdDataTypeFactory +xacml.pdpEngineFactory=com.att.research.xacmlatt.pdp.ATTPDPEngineFactory +xacml.pepEngineFactory=com.att.research.xacml.std.pep.StdEngineFactory +xacml.pipFinderFactory=com.att.research.xacml.std.pip.StdPIPFinderFactory +xacml.traceEngineFactory=com.att.research.xacml.std.trace.LoggingTraceEngineFactory +# +# AT&T PDP Implementation Factories +# +xacml.att.evaluationContextFactory=com.att.research.xacmlatt.pdp.std.StdEvaluationContextFactory +xacml.att.combiningAlgorithmFactory=com.att.research.xacmlatt.pdp.std.StdCombiningAlgorithmFactory +xacml.att.functionDefinitionFactory=com.att.research.xacmlatt.pdp.std.StdFunctionDefinitionFactory +# +# ONAP PDP Implementation Factories +# +xacml.att.policyFinderFactory=org.onap.policy.pdp.xacml.application.common.OnapPolicyFinderFactory + +# +# Use a root combining algorithm +# +xacml.att.policyFinderFactory.combineRootPolicies=urn:oasis:names:tc:xacml:3.0:policy-combining-algorithm:deny-overrides + +# +# Policies to load +# +xacml.rootPolicies= +xacml.referencedPolicies= \ No newline at end of file diff --git a/tutorials/tutorial-xacml-application/src/main/java/org/onap/policy/tutorial/tutorial/TutorialApplication.java b/tutorials/tutorial-xacml-application/src/main/java/org/onap/policy/tutorial/tutorial/TutorialApplication.java new file mode 100644 index 00000000..3c76494b --- /dev/null +++ b/tutorials/tutorial-xacml-application/src/main/java/org/onap/policy/tutorial/tutorial/TutorialApplication.java @@ -0,0 +1,58 @@ +/*- + * ============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.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 actionDecisionsSupported() { + return Arrays.asList("authorize"); + } + + @Override + public synchronized List supportedPolicyTypes() { + return Arrays.asList(supportedPolicyType); + } + + @Override + public boolean canSupportPolicyType(ToscaPolicyTypeIdentifier policyTypeId) { + return supportedPolicyType.equals(policyTypeId); + } + + @Override + protected ToscaPolicyTranslator getTranslator(String type) { + return translator; + } + +} 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 new file mode 100644 index 00000000..4bb94cd7 --- /dev/null +++ b/tutorials/tutorial-xacml-application/src/main/java/org/onap/policy/tutorial/tutorial/TutorialRequest.java @@ -0,0 +1,97 @@ +/*- + * ============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.tutorial; + +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 resources = decisionRequest.getResource(); + for (Entry 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; + } +} 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 new file mode 100644 index 00000000..7a6b5d8a --- /dev/null +++ b/tutorials/tutorial-xacml-application/src/main/java/org/onap/policy/tutorial/tutorial/TutorialTranslator.java @@ -0,0 +1,168 @@ +/*- + * ============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.tutorial; + +import com.att.research.xacml.api.DataTypeException; +import com.att.research.xacml.api.Decision; +import com.att.research.xacml.api.Identifier; +import com.att.research.xacml.api.Request; +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.List; +import java.util.Map; +import oasis.names.tc.xacml._3_0.core.schema.wd_17.AnyOfType; +import oasis.names.tc.xacml._3_0.core.schema.wd_17.EffectType; +import oasis.names.tc.xacml._3_0.core.schema.wd_17.MatchType; +import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType; +import oasis.names.tc.xacml._3_0.core.schema.wd_17.RuleType; +import oasis.names.tc.xacml._3_0.core.schema.wd_17.TargetType; +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.ToscaDictionary; +import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException; +import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslator; +import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslatorUtils; + +public class TutorialTranslator implements ToscaPolicyTranslator { + + private static final Identifier ID_TUTORIAL_USER = new IdentifierImpl(ToscaDictionary.ID_URN_ONAP, "tutorial-user"); + private static final Identifier ID_TUTORIAL_ENTITY = + new IdentifierImpl(ToscaDictionary.ID_URN_ONAP, "tutorial-entity"); + private static final Identifier ID_TUTORIAL_PERM = + new IdentifierImpl(ToscaDictionary.ID_URN_ONAP, "tutorial-permission"); + + /** + * Convert Policy from TOSCA to XACML. + */ + @SuppressWarnings("unchecked") + public PolicyType convertPolicy(ToscaPolicy toscaPolicy) throws ToscaPolicyConversionException { + // + // Here is our policy with a version and default combining algo + // + PolicyType newPolicyType = new PolicyType(); + newPolicyType.setPolicyId(toscaPolicy.getMetadata().get("policy-id")); + newPolicyType.setVersion(toscaPolicy.getMetadata().get("policy-version")); + // + // When choosing the rule combining algorithm, be sure to be mindful of the + // setting xacml.att.policyFinderFactory.combineRootPolicies in the + // xacml.properties file. As that choice for ALL the policies together may have + // an impact on the decision rendered from each individual policy. + // + // In this case, we will only produce XACML rules for permissions. If no permission + // combo exists, then the default is to deny. + // + newPolicyType.setRuleCombiningAlgId(XACML3.ID_RULE_DENY_UNLESS_PERMIT.stringValue()); + // + // Create the target for the Policy. + // + // For simplicity, let's just match on the action "authorize" and the user + // + MatchType matchAction = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator( + XACML3.ID_FUNCTION_STRING_EQUAL, "authorize", XACML3.ID_DATATYPE_STRING, + XACML3.ID_ACTION_ACTION_ID, XACML3.ID_ATTRIBUTE_CATEGORY_ACTION); + Map props = toscaPolicy.getProperties(); + String user = props.get("user").toString(); + MatchType matchUser = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(XACML3.ID_FUNCTION_STRING_EQUAL, user, + XACML3.ID_DATATYPE_STRING, ID_TUTORIAL_USER, XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE); + AnyOfType anyOf = new AnyOfType(); + // + // Create AllOf (AND) of just Policy Id + // + anyOf.getAllOf().add(ToscaPolicyTranslatorUtils.buildAllOf(matchAction, matchUser)); + TargetType target = new TargetType(); + target.getAnyOf().add(anyOf); + newPolicyType.setTarget(target); + // + // Now add the rule for each permission + // + int ruleNumber = 0; + List permissions = (List) props.get("permissions"); + for (Object permission : permissions) { + + MatchType matchEntity = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(XACML3.ID_FUNCTION_STRING_EQUAL, + ((Map) permission).get("entity"), XACML3.ID_DATATYPE_STRING, ID_TUTORIAL_ENTITY, + XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE); + + MatchType matchPermission = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator( + XACML3.ID_FUNCTION_STRING_EQUAL, ((Map) 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(); + target.getAnyOf().add(anyOf); + + RuleType rule = new RuleType(); + rule.setDescription("Default is to PERMIT if the policy matches."); + rule.setRuleId(newPolicyType.getPolicyId() + ":rule" + ruleNumber); + + rule.setEffect(EffectType.PERMIT); + rule.setTarget(target); + + newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(rule); + + ruleNumber++; + } + return newPolicyType; + } + + /** + * Convert ONAP DecisionRequest to XACML Request. + */ + public Request convertRequest(DecisionRequest request) { + try { + return RequestParser.parseRequest(TutorialRequest.createRequest(request)); + } catch (IllegalArgumentException | IllegalAccessException | DataTypeException e) { + // Empty + } + return null; + } + + /** + * Convert XACML Response to ONAP DecisionResponse. + */ + public DecisionResponse convertResponse(Response xacmlResponse) { + DecisionResponse decisionResponse = new DecisionResponse(); + // + // Iterate through all the results + // + for (Result xacmlResult : xacmlResponse.getResults()) { + // + // Check the result + // + if (xacmlResult.getDecision() == Decision.PERMIT) { + // + // Just simply return a Permit response + // + decisionResponse.setStatus(Decision.PERMIT.toString()); + } else { + // + // Just simply return a Deny response + // + decisionResponse.setStatus(Decision.DENY.toString()); + } + } + + return decisionResponse; + } + +} diff --git a/tutorials/tutorial-xacml-application/src/main/resources/META-INF/services/org.onap.policy.pdp.xacml.application.common.XacmlApplicationServiceProvider b/tutorials/tutorial-xacml-application/src/main/resources/META-INF/services/org.onap.policy.pdp.xacml.application.common.XacmlApplicationServiceProvider new file mode 100644 index 00000000..942cc596 --- /dev/null +++ b/tutorials/tutorial-xacml-application/src/main/resources/META-INF/services/org.onap.policy.pdp.xacml.application.common.XacmlApplicationServiceProvider @@ -0,0 +1 @@ +org.onap.policy.tutorial.tutorial.TutorialApplication \ No newline at end of file diff --git a/tutorials/tutorial-xacml-application/src/main/resources/xacml.properties b/tutorials/tutorial-xacml-application/src/main/resources/xacml.properties new file mode 100644 index 00000000..277b098e --- /dev/null +++ b/tutorials/tutorial-xacml-application/src/main/resources/xacml.properties @@ -0,0 +1,31 @@ +# +# Properties that the embedded PDP engine uses to configure and load +# +# Standard API Factories +# +xacml.dataTypeFactory=com.att.research.xacml.std.StdDataTypeFactory +xacml.pdpEngineFactory=com.att.research.xacmlatt.pdp.ATTPDPEngineFactory +xacml.pepEngineFactory=com.att.research.xacml.std.pep.StdEngineFactory +xacml.pipFinderFactory=com.att.research.xacml.std.pip.StdPIPFinderFactory +xacml.traceEngineFactory=com.att.research.xacml.std.trace.LoggingTraceEngineFactory +# +# AT&T PDP Implementation Factories +# +xacml.att.evaluationContextFactory=com.att.research.xacmlatt.pdp.std.StdEvaluationContextFactory +xacml.att.combiningAlgorithmFactory=com.att.research.xacmlatt.pdp.std.StdCombiningAlgorithmFactory +xacml.att.functionDefinitionFactory=com.att.research.xacmlatt.pdp.std.StdFunctionDefinitionFactory +# +# ONAP PDP Implementation Factories +# +xacml.att.policyFinderFactory=org.onap.policy.pdp.xacml.application.common.OnapPolicyFinderFactory + +# +# Use a root combining algorithm +# +xacml.att.policyFinderFactory.combineRootPolicies=urn:oasis:names:tc:xacml:3.0:policy-combining-algorithm:deny-overrides + +# +# Policies to load +# +xacml.rootPolicies= +xacml.referencedPolicies= \ No newline at end of file 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 new file mode 100644 index 00000000..28d25ee8 --- /dev/null +++ b/tutorials/tutorial-xacml-application/src/test/java/org/onap/policy/tutorial/tutorial/TutorialApplicationTest.java @@ -0,0 +1,120 @@ +/*- + * ============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.tutorial; + +import static org.junit.Assert.assertEquals; + +import com.att.research.xacml.api.Response; +import java.io.File; +import java.io.IOException; +import java.util.Properties; +import java.util.ServiceLoader; +import org.apache.commons.lang3.tuple.Pair; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.onap.policy.common.endpoints.parameters.RestServerParameters; +import org.onap.policy.common.utils.coder.CoderException; +import org.onap.policy.common.utils.coder.StandardCoder; +import org.onap.policy.common.utils.resources.TextFileUtils; +import org.onap.policy.models.decisions.concepts.DecisionRequest; +import org.onap.policy.models.decisions.concepts.DecisionResponse; +import org.onap.policy.pdp.xacml.application.common.XacmlApplicationException; +import org.onap.policy.pdp.xacml.application.common.XacmlApplicationServiceProvider; +import org.onap.policy.pdp.xacml.application.common.XacmlPolicyUtils; +import org.onap.policy.pdp.xacml.xacmltest.TestUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TutorialApplicationTest { + private static final Logger LOGGER = LoggerFactory.getLogger(TutorialApplicationTest.class); + private static Properties properties = new Properties(); + private static File propertiesFile; + private static XacmlApplicationServiceProvider service; + private static StandardCoder gson = new StandardCoder(); + + @ClassRule + public static final TemporaryFolder policyFolder = new TemporaryFolder(); + + /** + * setup the tests. + * + * @throws Exception Should not have exceptions thrown. + */ + @BeforeClass + public static void setup() throws Exception { + // + // Setup our temporary folder + // + XacmlPolicyUtils.FileCreator myCreator = (String filename) -> policyFolder.newFile(filename); + propertiesFile = XacmlPolicyUtils.copyXacmlPropertiesContents("src/test/resources/xacml.properties", + properties, myCreator); + // + // Load XacmlApplicationServiceProvider service + // + ServiceLoader applicationLoader = + ServiceLoader.load(XacmlApplicationServiceProvider.class); + // + // Look for our class instance and save it + // + for (XacmlApplicationServiceProvider application : applicationLoader) { + // + // Is it our service? + // + if (application instanceof TutorialApplication) { + service = application; + } + } + // + // Tell the application to initialize based on the properties file + // we just built for it. + // + service.initialize(propertiesFile.toPath().getParent(), new RestServerParameters()); + } + + @Test + public void test() throws CoderException, XacmlApplicationException, IOException { + // + // Now load the tutorial policies. + // + TestUtils.loadPolicies("src/test/resources/tutorial-policies.yaml", service); + // + // Load a Decision request + // + DecisionRequest decisionRequest = gson.decode( + TextFileUtils + .getTextFileAsString("src/test/resources/tutorial-decision-request.json"), + DecisionRequest.class); + // + // Test a decision - should start with a permit + // + Pair decision = service.makeDecision(decisionRequest, null); + LOGGER.info(decision.getLeft().toString()); + assertEquals("Permit", decision.getLeft().getStatus()); + // + // This should be a deny + // + decisionRequest.getResource().put("user", "audit"); + decision = service.makeDecision(decisionRequest, null); + LOGGER.info(decision.getLeft().toString()); + assertEquals("Deny", decision.getLeft().getStatus()); + } + +} diff --git a/tutorials/tutorial-xacml-application/src/test/resources/tutorial-decision-request.json b/tutorials/tutorial-xacml-application/src/test/resources/tutorial-decision-request.json new file mode 100644 index 00000000..f3a7f9a2 --- /dev/null +++ b/tutorials/tutorial-xacml-application/src/test/resources/tutorial-decision-request.json @@ -0,0 +1,12 @@ +{ + "ONAPName": "TutorialPEP", + "ONAPComponent": "TutorialPEPComponent", + "ONAPInstance": "TutorialPEPInstance", + "requestId": "unique-request-id-tutorial", + "action": "authorize", + "resource": { + "user": "demo", + "entity": "foo", + "permission" : "write" + } +} diff --git a/tutorials/tutorial-xacml-application/src/test/resources/tutorial-policies.yaml b/tutorials/tutorial-xacml-application/src/test/resources/tutorial-policies.yaml new file mode 100644 index 00000000..fa353653 --- /dev/null +++ b/tutorials/tutorial-xacml-application/src/test/resources/tutorial-policies.yaml @@ -0,0 +1,34 @@ +tosca_definitions_version: tosca_simple_yaml_1_1_0 +topology_template: + policies: + - + onap.policy.tutorial.demo: + type: onap.policies.Authorization + type_version: 1.0.0 + version: 1.0.0 + metadata: + policy-id: onap.policy.tutorial.demo + policy-version: 1 + properties: + user: demo + permissions: + - + entity: foo + permission: read + - + entity: foo + permission: write + - + onap.policy.tutorial.audit: + type: onap.policies.Authorization + version: 1.0.0 + type_version: 1.0.0 + metadata: + policy-id: onap.policy.tutorial.bar + policy-version: 1 + properties: + user: audit + permissions: + - + entity: foo + permission: read diff --git a/tutorials/tutorial-xacml-application/src/test/resources/tutorial-policy-type.yaml b/tutorials/tutorial-xacml-application/src/test/resources/tutorial-policy-type.yaml new file mode 100644 index 00000000..7948bd28 --- /dev/null +++ b/tutorials/tutorial-xacml-application/src/test/resources/tutorial-policy-type.yaml @@ -0,0 +1,32 @@ +tosca_definitions_version: tosca_simple_yaml_1_1_0 +policy_types: + onap.policies.Authorization: + derived_from: tosca.policies.Root + version: 1.0.0 + description: Example tutorial policy type for doing user authorization + properties: + user: + type: string + required: true + description: The unique user name + permissions: + type: list + required: true + description: A list of resource permissions + entry_schema: + type: onap.datatypes.Tutorial +data_types: + onap.datatypes.Tutorial: + derived_from: tosca.datatypes.Root + version: 1.0.0 + properties: + entity: + type: string + required: true + description: The resource + permission: + type: string + required: true + description: The permission level + constraints: + - valid_values: [read, write, delete] diff --git a/tutorials/tutorial-xacml-application/src/test/resources/xacml.properties b/tutorials/tutorial-xacml-application/src/test/resources/xacml.properties new file mode 100644 index 00000000..277b098e --- /dev/null +++ b/tutorials/tutorial-xacml-application/src/test/resources/xacml.properties @@ -0,0 +1,31 @@ +# +# Properties that the embedded PDP engine uses to configure and load +# +# Standard API Factories +# +xacml.dataTypeFactory=com.att.research.xacml.std.StdDataTypeFactory +xacml.pdpEngineFactory=com.att.research.xacmlatt.pdp.ATTPDPEngineFactory +xacml.pepEngineFactory=com.att.research.xacml.std.pep.StdEngineFactory +xacml.pipFinderFactory=com.att.research.xacml.std.pip.StdPIPFinderFactory +xacml.traceEngineFactory=com.att.research.xacml.std.trace.LoggingTraceEngineFactory +# +# AT&T PDP Implementation Factories +# +xacml.att.evaluationContextFactory=com.att.research.xacmlatt.pdp.std.StdEvaluationContextFactory +xacml.att.combiningAlgorithmFactory=com.att.research.xacmlatt.pdp.std.StdCombiningAlgorithmFactory +xacml.att.functionDefinitionFactory=com.att.research.xacmlatt.pdp.std.StdFunctionDefinitionFactory +# +# ONAP PDP Implementation Factories +# +xacml.att.policyFinderFactory=org.onap.policy.pdp.xacml.application.common.OnapPolicyFinderFactory + +# +# Use a root combining algorithm +# +xacml.att.policyFinderFactory.combineRootPolicies=urn:oasis:names:tc:xacml:3.0:policy-combining-algorithm:deny-overrides + +# +# Policies to load +# +xacml.rootPolicies= +xacml.referencedPolicies= \ No newline at end of file