2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved.
6 * Modified Copyright (C) 2018 Samsung Electronics Co., Ltd.
7 * Modifications Copyright (C) 2019 Bell Canada
8 * ================================================================================
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 * ============LICENSE_END=========================================================
23 package org.onap.policy.admin;
25 import com.att.research.xacml.util.XACMLProperties;
26 import com.fasterxml.jackson.databind.DeserializationFeature;
27 import com.fasterxml.jackson.databind.JsonNode;
28 import com.fasterxml.jackson.databind.ObjectMapper;
29 import com.fasterxml.jackson.databind.SerializationFeature;
31 import java.io.ByteArrayInputStream;
33 import java.io.IOException;
34 import java.io.InputStream;
35 import java.io.OutputStream;
36 import java.io.PrintWriter;
37 import java.net.HttpURLConnection;
39 import java.nio.charset.StandardCharsets;
40 import java.util.ArrayList;
41 import java.util.Base64;
42 import java.util.List;
44 import javax.servlet.http.HttpServletRequest;
45 import javax.servlet.http.HttpServletResponse;
47 import org.apache.commons.fileupload.FileItem;
48 import org.apache.commons.fileupload.disk.DiskFileItemFactory;
49 import org.apache.commons.fileupload.servlet.ServletFileUpload;
50 import org.apache.commons.io.IOUtils;
51 import org.json.JSONObject;
52 import org.onap.policy.common.logging.flexlogger.FlexLogger;
53 import org.onap.policy.common.logging.flexlogger.Logger;
54 import org.onap.policy.controller.CreateClosedLoopFaultController;
55 import org.onap.policy.controller.CreateDcaeMicroServiceController;
56 import org.onap.policy.controller.CreateFirewallController;
57 import org.onap.policy.controller.CreateOptimizationController;
58 import org.onap.policy.controller.PolicyController;
59 import org.onap.policy.rest.XACMLRestProperties;
60 import org.onap.policy.rest.adapter.PolicyRestAdapter;
61 import org.onap.policy.rest.dao.CommonClassDao;
62 import org.onap.policy.rest.jpa.PolicyVersion;
63 import org.onap.policy.utils.PeCryptoUtils;
64 import org.onap.policy.utils.PolicyUtils;
65 import org.onap.policy.xacml.api.XACMLErrorConstants;
66 import org.onap.portalsdk.core.controller.RestrictedBaseController;
67 import org.onap.portalsdk.core.web.support.UserUtils;
68 import org.springframework.beans.factory.annotation.Autowired;
69 import org.springframework.http.HttpEntity;
70 import org.springframework.http.HttpHeaders;
71 import org.springframework.http.HttpMethod;
72 import org.springframework.http.HttpStatus;
73 import org.springframework.http.ResponseEntity;
74 import org.springframework.web.bind.annotation.RequestMapping;
75 import org.springframework.web.bind.annotation.RequestMethod;
76 import org.springframework.web.bind.annotation.RestController;
77 import org.springframework.web.client.HttpClientErrorException;
78 import org.springframework.web.client.RestTemplate;
79 import org.springframework.web.servlet.ModelAndView;
83 public class PolicyRestController extends RestrictedBaseController {
85 private static final Logger policyLogger = FlexLogger.getLogger(PolicyRestController.class);
87 private static final String MODEL = "model";
88 private static final String IMPORT_DICTIONARY = "import_dictionary";
89 private static final String FILE = "file";
90 private static final String TYPE = "type";
91 private static final String PATH = "path";
92 private static final String NAME = "name";
93 private static final String CLOSED_LOOP_FAULT = "ClosedLoop_Fault";
94 private static final String FIREWALL_CONFIG = "Firewall Config";
95 private static final String MICRO_SERVICE = "Micro Service";
96 private static final String OPTIMIZATION = "Optimization";
97 private static final String POLICY_NAME = "policyName";
98 private static final String SUCCESS = "success";
99 private static final String XML = ".xml";
100 private static final String UTF_8 = "UTF-8";
101 private static final String DATA = "data";
102 private static final String USER_ID = "UserId: ";
103 private static final String BASIC = "Basic ";
104 private static final String AUTHORIZATION = "Authorization";
105 private static final String CONTENT_TYPE = "Content-Type";
106 private static final String ONAP = "/onap";
108 private static CommonClassDao commonClassDao;
110 public PolicyRestController() {
111 // default constructor
115 private PolicyRestController(CommonClassDao commonClassDao) {
116 PolicyRestController.commonClassDao = commonClassDao;
119 public static CommonClassDao getCommonClassDao() {
120 return commonClassDao;
123 public static void setCommonClassDao(CommonClassDao commonClassDao) {
124 PolicyRestController.commonClassDao = commonClassDao;
127 @RequestMapping(value = {"/policycreation/save_policy"}, method = {RequestMethod.POST})
128 public void policyCreationController(HttpServletRequest request, HttpServletResponse response) {
129 String userId = UserUtils.getUserSession(request).getOrgUserId();
130 ObjectMapper mapper = new ObjectMapper();
131 mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
133 updateAndSendToPAP(request, response, userId, mapper);
134 } catch (Exception e) {
135 policyLogger.error("Exception Occured while saving policy", e);
139 private void updateAndSendToPAP(HttpServletRequest request, HttpServletResponse response, String userId,
140 ObjectMapper mapper) throws IOException {
141 JsonNode root = mapper.readTree(request.getReader());
143 "****************************************Logging UserID while Create/Update Policy**************************************************");
144 policyLogger.info(USER_ID + userId + "Policy Data Object: "
145 + root.get(PolicyController.getPolicydata()).get("policy").toString());
147 "***********************************************************************************************************************************");
149 PolicyRestAdapter policyData = mapper.readValue(
150 root.get(PolicyController.getPolicydata()).get("policy").toString(), PolicyRestAdapter.class);
151 modifyPolicyData(root, policyData);
153 if (policyData.getConfigPolicyType() != null) {
154 if (CLOSED_LOOP_FAULT.equalsIgnoreCase(policyData.getConfigPolicyType())) {
155 policyData = new CreateClosedLoopFaultController().setDataToPolicyRestAdapter(policyData, root);
156 } else if (FIREWALL_CONFIG.equalsIgnoreCase(policyData.getConfigPolicyType())) {
157 policyData = new CreateFirewallController().setDataToPolicyRestAdapter(policyData);
158 } else if (MICRO_SERVICE.equalsIgnoreCase(policyData.getConfigPolicyType())) {
159 policyData = new CreateDcaeMicroServiceController().setDataToPolicyRestAdapter(policyData, root);
160 } else if (OPTIMIZATION.equalsIgnoreCase(policyData.getConfigPolicyType())) {
161 policyData = new CreateOptimizationController().setDataToPolicyRestAdapter(policyData, root);
165 policyData.setUserId(userId);
168 String body = PolicyUtils.objectToJsonString(policyData);
169 String uri = request.getRequestURI();
170 ResponseEntity<?> responseEntity = sendToPAP(body, uri, HttpMethod.POST);
171 if (responseEntity != null && responseEntity.getBody().equals(HttpServletResponse.SC_CONFLICT)) {
172 result = "PolicyExists";
173 } else if (responseEntity != null) {
174 result = responseEntity.getBody().toString();
175 String policyName = responseEntity.getHeaders().get(POLICY_NAME).get(0);
176 if (policyData.isEditPolicy() && SUCCESS.equalsIgnoreCase(result)) {
177 PolicyNotificationMail email = new PolicyNotificationMail();
178 String mode = "EditPolicy";
179 String watchPolicyName = policyName.replace(XML, "");
180 String version = watchPolicyName.substring(watchPolicyName.lastIndexOf('.') + 1);
182 watchPolicyName.substring(0, watchPolicyName.lastIndexOf('.')).replace(".", File.separator);
183 String policyVersionName = watchPolicyName.replace(".", File.separator);
184 watchPolicyName = watchPolicyName + "." + version + XML;
185 PolicyVersion entityItem = new PolicyVersion();
186 entityItem.setPolicyName(policyVersionName);
187 entityItem.setActiveVersion(Integer.parseInt(version));
188 entityItem.setModifiedBy(userId);
189 email.sendMail(entityItem, watchPolicyName, mode, commonClassDao);
192 result = "Response is null from PAP";
195 response.setCharacterEncoding(PolicyController.getCharacterencoding());
196 response.setContentType(PolicyController.getContenttype());
197 request.setCharacterEncoding(PolicyController.getCharacterencoding());
199 PrintWriter out = response.getWriter();
200 String responseString = mapper.writeValueAsString(result);
201 JSONObject j = new JSONObject("{policyData: " + responseString + "}");
202 out.write(j.toString());
205 private void modifyPolicyData(JsonNode root, PolicyRestAdapter policyData) {
206 if (FILE.equals(root.get(PolicyController.getPolicydata()).get(MODEL).get(TYPE).toString().replace("\"", ""))) {
207 policyData.setEditPolicy(true);
209 if (root.get(PolicyController.getPolicydata()).get(MODEL).get(PATH).size() != 0) {
211 for (int i = 0; i < root.get(PolicyController.getPolicydata()).get(MODEL).get(PATH).size(); i++) {
212 dirName = dirName.replace("\"", "") + root.get(PolicyController.getPolicydata()).get(MODEL).get(PATH)
213 .get(i).toString().replace("\"", "") + File.separator;
215 if (policyData.isEditPolicy()) {
216 policyData.setDomainDir(dirName.substring(0, dirName.lastIndexOf(File.separator)));
218 policyData.setDomainDir(dirName
219 + root.get(PolicyController.getPolicydata()).get(MODEL).get(NAME).toString().replace("\"", ""));
222 String domain = root.get(PolicyController.getPolicydata()).get(MODEL).get(NAME).toString();
223 if (domain.contains("/")) {
224 domain = domain.substring(0, domain.lastIndexOf('/')).replace("/", File.separator);
226 domain = domain.replace("\"", "");
227 policyData.setDomainDir(domain);
231 private ResponseEntity<?> sendToPAP(String body, String requestURI, HttpMethod method) {
232 String papUrl = PolicyController.getPapUrl();
233 String papID = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_USERID);
234 String papPass = PeCryptoUtils.decrypt(XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_PASS));
235 Base64.Encoder encoder = Base64.getEncoder();
236 String encoding = encoder.encodeToString((papID + ":" + papPass).getBytes(StandardCharsets.UTF_8));
237 HttpHeaders headers = new HttpHeaders();
238 headers.set(AUTHORIZATION, BASIC + encoding);
239 headers.set(CONTENT_TYPE, PolicyController.getContenttype());
241 RestTemplate restTemplate = new RestTemplate();
242 HttpEntity<?> requestEntity = new HttpEntity<>(body, headers);
243 ResponseEntity<?> result = null;
244 HttpClientErrorException exception = null;
245 String uri = requestURI;
246 if (uri.startsWith("/")) {
247 uri = uri.substring(uri.indexOf('/') + 1);
249 uri = "onap" + uri.substring(uri.indexOf('/'));
251 result = restTemplate.exchange(papUrl + uri, method, requestEntity, String.class);
252 } catch (Exception e) {
253 policyLogger.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Error while connecting to " + papUrl, e);
254 exception = new HttpClientErrorException(HttpStatus.INTERNAL_SERVER_ERROR, e.getMessage());
255 if ("409 Conflict".equals(e.getMessage())) {
256 return ResponseEntity.ok(HttpServletResponse.SC_CONFLICT);
259 if (exception != null && exception.getStatusCode() != null) {
260 if (exception.getStatusCode().equals(HttpStatus.UNAUTHORIZED)) {
261 String message = XACMLErrorConstants.ERROR_PERMISSIONS + ":" + exception.getStatusCode() + ":"
262 + "ERROR_AUTH_GET_PERM";
263 policyLogger.error(message);
265 if (exception.getStatusCode().equals(HttpStatus.BAD_REQUEST)) {
266 String message = XACMLErrorConstants.ERROR_DATA_ISSUE + ":" + exception.getStatusCode() + ":"
267 + exception.getResponseBodyAsString();
268 policyLogger.error(message);
270 if (exception.getStatusCode().equals(HttpStatus.NOT_FOUND)) {
272 XACMLErrorConstants.ERROR_PROCESS_FLOW + "Error while connecting to " + papUrl + exception;
273 policyLogger.error(message);
275 String message = XACMLErrorConstants.ERROR_PROCESS_FLOW + ":" + exception.getStatusCode() + ":"
276 + exception.getResponseBodyAsString();
277 policyLogger.error(message);
282 private String callPAP(HttpServletRequest request, String method, String uriValue) {
283 String uri = uriValue;
284 String papUrl = PolicyController.getPapUrl();
285 String papID = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_USERID);
286 PeCryptoUtils.initAesKey(XACMLProperties.getProperty(XACMLRestProperties.PROP_AES_KEY));
287 String papPass = PeCryptoUtils.decrypt((XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_PASS)));
289 Base64.Encoder encoder = Base64.getEncoder();
290 String encoding = encoder.encodeToString((papID + ":" + papPass).getBytes(StandardCharsets.UTF_8));
291 HttpHeaders headers = new HttpHeaders();
292 headers.set(AUTHORIZATION, BASIC + encoding);
293 headers.set(CONTENT_TYPE, PolicyController.getContenttype());
295 HttpURLConnection connection = null;
296 List<FileItem> items;
297 FileItem item = null;
299 if (uri.contains(IMPORT_DICTIONARY)) {
301 items = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(request);
303 file = new File(item.getName());
304 String newFile = file.toString();
305 uri = uri + "&dictionaryName=" + newFile;
306 } catch (Exception e2) {
307 policyLogger.error("Exception Occured while calling PAP with import dictionary request" + e2);
312 URL url = new URL(papUrl + uri);
313 connection = (HttpURLConnection) url.openConnection();
314 connection.setRequestMethod(method);
315 connection.setUseCaches(false);
316 connection.setInstanceFollowRedirects(false);
317 connection.setRequestProperty(AUTHORIZATION, BASIC + encoding);
318 connection.setDoOutput(true);
319 connection.setDoInput(true);
321 if (uri.contains("searchPolicy?action=delete&")) {
323 return doConnect(connection);
326 checkURI(request, uri, connection, item);
328 return doConnect(connection);
329 } catch (Exception e) {
330 policyLogger.error("Exception Occured" + e);
332 if (file != null && file.exists() && file.delete()) {
333 policyLogger.info("File Deleted Successfully");
335 if (connection != null) {
337 // For some reason trying to get the inputStream from the connection
338 // throws an exception rather than returning null when the InputStream does not exist.
339 InputStream is = connection.getInputStream();
343 } catch (IOException ex) {
344 policyLogger.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Failed to close connection: " + ex,
347 connection.disconnect();
353 private void checkURI(HttpServletRequest request, String uri, HttpURLConnection connection, FileItem item)
356 if (!(uri.endsWith("set_BRMSParamData") || uri.contains(IMPORT_DICTIONARY))) {
357 connection.setRequestProperty(CONTENT_TYPE, PolicyController.getContenttype());
358 ObjectMapper mapper = new ObjectMapper();
359 mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
360 JsonNode root = getJsonNode(request, mapper);
362 ObjectMapper mapper1 = new ObjectMapper();
363 mapper1.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
365 Object obj = mapper1.treeToValue(root, Object.class);
366 String json = mapper1.writeValueAsString(obj);
368 // send current configuration
369 try (InputStream content = new ByteArrayInputStream(json.getBytes());
370 OutputStream os = connection.getOutputStream()) {
371 int count = IOUtils.copy(content, os);
372 if (policyLogger.isDebugEnabled()) {
373 policyLogger.debug("copied to output, bytes=" + count);
376 } else if (uri.endsWith("set_BRMSParamData")) {
377 connection.setRequestProperty(CONTENT_TYPE, PolicyController.getContenttype());
378 try (OutputStream os = connection.getOutputStream()) {
379 IOUtils.copy(request.getInputStream(), os);
382 boundary = "===" + System.currentTimeMillis() + "===";
383 connection.setRequestProperty(CONTENT_TYPE, "multipart/form-data; boundary=" + boundary);
384 try (OutputStream os = connection.getOutputStream()) {
386 IOUtils.copy(item.getInputStream(), os);
392 private JsonNode getJsonNode(HttpServletRequest request, ObjectMapper mapper) {
393 JsonNode root = null;
395 root = mapper.readTree(request.getReader());
396 } catch (Exception e1) {
397 policyLogger.error("Exception Occured while calling PAP" + e1);
402 private String doConnect(final HttpURLConnection connection) throws IOException {
403 connection.connect();
404 int responseCode = connection.getResponseCode();
405 if (responseCode == 200) {
406 // get the response content into a String
407 String responseJson = null;
408 // read the inputStream into a buffer (trick found online scans entire input looking for end-of-file)
409 try (java.util.Scanner scanner = new java.util.Scanner(connection.getInputStream())) {
410 scanner.useDelimiter("\\A");
411 responseJson = scanner.hasNext() ? scanner.next() : "";
412 } catch (Exception e) {
413 // Reason for rethrowing the exception is if any exception occurs during reading of inputsteam
414 // then the exception handling is done by the outer block without returning the response immediately
415 // Also finally block is existing only in outer block and not here so all exception handling is
416 // done in only one place
417 policyLogger.error("Exception Occured" + e);
421 policyLogger.info("JSON response from PAP: " + responseJson);
427 @RequestMapping(value = {"/getDictionary/*"}, method = {RequestMethod.GET})
428 public void getDictionaryController(HttpServletRequest request, HttpServletResponse response) {
429 String uri = request.getRequestURI().replace("/getDictionary", "");
431 ResponseEntity<?> responseEntity = sendToPAP(null, uri, HttpMethod.GET);
432 if (responseEntity != null) {
433 body = responseEntity.getBody().toString();
438 response.getWriter().write(body);
439 } catch (IOException e) {
440 policyLogger.error("Exception occured while getting Dictionary entries", e);
444 @RequestMapping(value = {"/saveDictionary/*/*"}, method = {RequestMethod.POST})
445 public void saveDictionaryController(HttpServletRequest request, HttpServletResponse response) throws IOException {
447 String uri = request.getRequestURI().replace("/saveDictionary", "");
448 if (uri.startsWith("/")) {
449 uri = uri.substring(uri.indexOf('/') + 1);
451 uri = ONAP + uri.substring(uri.indexOf('/'));
452 if (uri.contains(IMPORT_DICTIONARY)) {
453 userId = UserUtils.getUserSession(request).getOrgUserId();
454 uri = uri + "?userId=" + userId;
458 "****************************************Logging UserID while Saving Dictionary*****************************************************");
459 policyLogger.info(USER_ID + userId);
461 "***********************************************************************************************************************************");
463 String body = callPAP(request, "POST", uri.replaceFirst("/", "").trim());
464 if (body != null && !body.isEmpty()) {
465 response.getWriter().write(body);
467 response.getWriter().write("Failed");
471 @RequestMapping(value = {"/deleteDictionary/*/*"}, method = {RequestMethod.POST})
472 public void deletetDictionaryController(HttpServletRequest request, HttpServletResponse response)
474 String uri = request.getRequestURI().replace("/deleteDictionary", "");
475 if (uri.startsWith("/")) {
476 uri = uri.substring(uri.indexOf('/') + 1);
478 uri = ONAP + uri.substring(uri.indexOf('/'));
480 String userId = UserUtils.getUserSession(request).getOrgUserId();
482 "****************************************Logging UserID while Deleting Dictionary*****************************************************");
483 policyLogger.info(USER_ID + userId);
485 "*************************************************************************************************************************************");
487 String body = callPAP(request, "POST", uri.replaceFirst("/", "").trim());
488 if (body != null && !body.isEmpty()) {
489 response.getWriter().write(body);
491 response.getWriter().write("Failed");
495 @RequestMapping(value = {"/searchDictionary"}, method = {RequestMethod.POST})
496 public ModelAndView searchDictionaryController(HttpServletRequest request, HttpServletResponse response)
499 String uri = request.getRequestURI();
500 if (uri.startsWith("/")) {
501 uri = uri.substring(uri.indexOf('/') + 1);
503 uri = ONAP + uri.substring(uri.indexOf('/'));
505 String body = callPAP(request, "POST", uri.replaceFirst("/", "").trim());
506 if (body.contains("CouldNotConnectException")) {
507 List<String> data = new ArrayList<>();
508 data.add("Elastic Search Server is down");
511 JSONObject json = new JSONObject(body);
512 resultList = json.get("policyresult");
514 } catch (Exception e) {
516 XACMLErrorConstants.ERROR_PROCESS_FLOW + "Exception Occured while querying Elastic Search: " + e);
517 List<String> data = new ArrayList<>();
518 data.add("Elastic Search Server is down");
522 response.setCharacterEncoding(PolicyController.getCharacterencoding());
523 response.setContentType(PolicyController.getContenttype());
524 PrintWriter out = response.getWriter();
525 JSONObject j = new JSONObject("{result: " + resultList + "}");
526 out.write(j.toString());
530 @RequestMapping(value = {"/searchPolicy"}, method = {RequestMethod.POST})
531 public ModelAndView searchPolicy(HttpServletRequest request, HttpServletResponse response) throws IOException {
533 String uri = request.getRequestURI() + "?action=search";
534 if (uri.startsWith("/")) {
535 uri = uri.substring(uri.indexOf('/') + 1);
537 uri = ONAP + uri.substring(uri.indexOf('/'));
538 String body = callPAP(request, "POST", uri.replaceFirst("/", "").trim());
540 JSONObject json = new JSONObject(body);
542 resultList = json.get("policyresult");
543 } catch (Exception e) {
544 List<String> data = new ArrayList<>();
545 resultList = json.get(DATA);
546 data.add("Exception");
547 data.add(resultList.toString());
549 policyLogger.error("Exception Occured while searching for Policy in Elastic Database" + e);
552 response.setCharacterEncoding(UTF_8);
553 response.setContentType("application / json");
554 request.setCharacterEncoding(UTF_8);
556 PrintWriter out = response.getWriter();
557 JSONObject j = new JSONObject("{result: " + resultList + "}");
558 out.write(j.toString());
562 public void deleteElasticData(String fileName) {
563 String uri = "searchPolicy?action=delete&policyName='" + fileName + "'";
564 callPAP(null, "POST", uri.trim());
567 public String notifyOtherPAPSToUpdateConfigurations(String mode, String newName, String oldName) {
569 "onap/notifyOtherPAPs?action=" + mode + "&newPolicyName=" + newName + "&oldPolicyName=" + oldName + "";
570 return callPAP(null, "POST", uri.trim());