From f0bd7f421948415b1c2f05cb39674f57f72218e0 Mon Sep 17 00:00:00 2001 From: Pamela Dragosh Date: Mon, 26 Oct 2020 09:59:09 -0400 Subject: 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 --- .../src/main/docker/README.txt | 36 ++++ .../src/main/docker/config/db/db.conf | 20 ++ .../src/main/docker/config/db/db.sh | 26 +++ .../src/main/docker/config/sim/simParameters.json | 15 ++ .../src/main/docker/docker-compose.yml | 105 ++++++++++ .../policy/tutorial/policyenforcement/App.java | 227 +++++++++++++++++++++ 6 files changed, 429 insertions(+) create mode 100644 tutorials/tutorial-enforcement/src/main/docker/README.txt create mode 100644 tutorials/tutorial-enforcement/src/main/docker/config/db/db.conf create mode 100644 tutorials/tutorial-enforcement/src/main/docker/config/db/db.sh create mode 100644 tutorials/tutorial-enforcement/src/main/docker/config/sim/simParameters.json create mode 100644 tutorials/tutorial-enforcement/src/main/docker/docker-compose.yml create mode 100644 tutorials/tutorial-enforcement/src/main/java/org/onap/policy/tutorial/policyenforcement/App.java (limited to 'tutorials/tutorial-enforcement/src/main') 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"); + } + +} -- cgit 1.2.3-korg