2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights reserved.
4 * ================================================================================
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 * ============LICENSE_END=========================================================
19 package org.onap.policy.tutorial.policyenforcement;
21 import java.util.Arrays;
22 import java.util.Collections;
23 import java.util.HashMap;
25 import java.util.Map.Entry;
26 import java.util.Scanner;
27 import javax.ws.rs.client.Entity;
28 import javax.ws.rs.core.MediaType;
29 import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
30 import org.onap.policy.common.endpoints.event.comm.TopicEndpointManager;
31 import org.onap.policy.common.endpoints.event.comm.TopicListener;
32 import org.onap.policy.common.endpoints.event.comm.bus.internal.BusTopicParams;
33 import org.onap.policy.common.endpoints.http.client.HttpClient;
34 import org.onap.policy.common.endpoints.http.client.HttpClientConfigException;
35 import org.onap.policy.common.endpoints.http.client.HttpClientFactoryInstance;
36 import org.onap.policy.common.endpoints.parameters.TopicParameterGroup;
37 import org.onap.policy.common.endpoints.parameters.TopicParameters;
38 import org.onap.policy.common.utils.coder.CoderException;
39 import org.onap.policy.common.utils.coder.StandardCoder;
40 import org.onap.policy.models.decisions.concepts.DecisionRequest;
41 import org.onap.policy.models.decisions.concepts.DecisionResponse;
42 import org.onap.policy.models.pap.concepts.PolicyNotification;
43 import org.onap.policy.models.pap.concepts.PolicyStatus;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
47 public class App extends Thread implements TopicListener {
48 private static Logger logger = LoggerFactory.getLogger(App.class);
49 private static final String MY_POLICYTYPEID = "onap.policies.monitoring.MyAnalytic";
50 private String xacmlPdpHost;
51 private String xacmlPdpPort;
52 private DecisionRequest decisionRequest = new DecisionRequest();
53 private Integer requestId = 1;
54 private HttpClient client = null;
59 * @param args Command line arguments
61 public App(String[] args) {
62 xacmlPdpHost = args[0];
63 xacmlPdpPort = args[1];
65 var params = new TopicParameters();
66 params.setTopicCommInfrastructure("dmaap");
67 params.setFetchLimit(1);
68 params.setFetchTimeout(5000);
69 params.setTopic("POLICY-NOTIFICATION");
70 params.setServers(Arrays.asList(args[2] + ":" + args[3]));
71 var topicParams = new TopicParameterGroup();
72 topicParams.setTopicSources(Arrays.asList(params));
74 TopicEndpointManager.getManager().addTopics(topicParams);
75 TopicEndpointManager.getManager().getDmaapTopicSource("POLICY-NOTIFICATION").register(this);
77 decisionRequest.setOnapComponent("myComponent");
78 decisionRequest.setOnapName("myName");
79 decisionRequest.setOnapInstance("myInstanceId");
80 decisionRequest.setAction("configure");
81 Map<String, Object> resources = new HashMap<>();
82 resources.put("policy-type", MY_POLICYTYPEID);
83 decisionRequest.setResource(resources);
87 * Thread run method that creates a connection and gets an initial Decision on which policy(s)
88 * we should be enforcing.
89 * Then sits waiting for the user to enter q or Q from the keyboard to quit. While waiting,
90 * listen on Dmaap topic for notification that the policy has changed.
94 logger.info("running - type q to stdin to quit");
96 client = HttpClientFactoryInstance.getClientFactory().build(BusTopicParams.builder()
97 .clientName("myClientName").useHttps(true).allowSelfSignedCerts(true)
98 .hostname(xacmlPdpHost).port(Integer.parseInt(xacmlPdpPort))
99 .userName("healthcheck").password("zb!XztG34").basePath("policy/pdpx/v1")
101 .serializationProvider("org.onap.policy.common.gson.GsonMessageBodyHandler")
103 } catch (NumberFormatException | HttpClientConfigException e) {
104 logger.error("Could not create Http client", e);
108 Map<String, Object> policies = getDecision(client, this.decisionRequest);
109 if (policies.isEmpty()) {
110 logger.info("Not enforcing any policies to start");
112 for (Entry<String, Object> entrySet : policies.entrySet()) {
113 logger.info("Enforcing: {}", entrySet.getKey());
116 TopicEndpointManager.getManager().start();
118 @SuppressWarnings("resource") // never close System.in
119 var input = new Scanner(System.in);
120 while (!Thread.currentThread().isInterrupted()) {
121 String quit = input.nextLine();
122 if ("q".equalsIgnoreCase(quit)) {
123 logger.info("quiting");
128 TopicEndpointManager.getManager().shutdown();
133 * This method is called when a topic event is received.
136 public void onTopicEvent(CommInfrastructure infra, String topic, String event) {
137 logger.info("onTopicEvent {}", event);
138 if (scanForPolicyType(event)) {
139 Map<String, Object> newPolicies = getDecision(client, this.decisionRequest);
140 if (newPolicies.isEmpty()) {
141 logger.info("Not enforcing any policies");
143 for (Entry<String, Object> entrySet : newPolicies.entrySet()) {
144 logger.info("Now Enforcing: {}", entrySet.getKey());
150 * Helper method that parses a DMaap message event for POLICY-NOTIFICATION
151 * looking for our supported policy type to enforce.
153 * @param msg Dmaap Message
154 * @return true if MY_POLICYTYPEID is in the message
156 private boolean scanForPolicyType(String msg) {
157 var gson = new StandardCoder();
159 PolicyNotification notification = gson.decode(msg, PolicyNotification.class);
160 for (PolicyStatus added : notification.getAdded()) {
161 if (MY_POLICYTYPEID.equals(added.getPolicyTypeId())) {
165 for (PolicyStatus deleted : notification.getDeleted()) {
166 if (MY_POLICYTYPEID.equals(deleted.getPolicyTypeId())) {
170 } catch (CoderException e) {
171 logger.error("StandardCoder failed to parse PolicyNotification", e);
178 * Helper method that calls the XACML PDP Decision API to get a Decision
179 * as to which policy we should be enforcing.
181 * @param client HttpClient to use to make REST call
182 * @param decisionRequest DecisionRequest object to send
183 * @return The Map of policies that was in the DecisionResponse object
185 private Map<String, Object> getDecision(HttpClient client, DecisionRequest decisionRequest) {
186 decisionRequest.setRequestId(requestId.toString());
189 Entity<DecisionRequest> entityRequest =
190 Entity.entity(decisionRequest, MediaType.APPLICATION_JSON);
191 var response = client.post("/decision", entityRequest, Collections.emptyMap());
193 if (response.getStatus() != 200) {
195 "Decision API failed - is the IP/port correct? {}", response.getStatus());
196 return Collections.emptyMap();
199 var decisionResponse = HttpClient.getBody(response, DecisionResponse.class);
201 return decisionResponse.getPolicies();
205 * Our Main application entry point.
207 * @param args command line arguments
209 public static void main(String[] args) {
210 logger.info("Hello Welcome to ONAP Enforcement Tutorial!");
212 var app = new App(args);
218 } catch (InterruptedException e) {
219 Thread.currentThread().interrupt();
220 logger.warn("Thread interrupted");
223 logger.info("Tutorial ended");