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;
128 * policyCreationController.
130 * @param request Request
131 * @param response Response
133 @RequestMapping(value = {"/policycreation/save_policy"}, method = {RequestMethod.POST})
134 public void policyCreationController(HttpServletRequest request, HttpServletResponse response) {
135 ObjectMapper mapper = new ObjectMapper();
136 mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
138 updateAndSendToPap(request, response, UserUtils.getUserSession(request).getOrgUserId(), mapper);
139 } catch (Exception e) {
140 policyLogger.error("Exception Occured while saving policy", e);
144 private void updateAndSendToPap(HttpServletRequest request, HttpServletResponse response, String userId,
145 ObjectMapper mapper) throws IOException {
146 JsonNode root = mapper.readTree(request.getReader());
148 "********************Logging UserID while Create/Update Policy***********************************");
149 policyLogger.info(USER_ID + userId + "Policy Data Object: "
150 + root.get(PolicyController.getPolicydata()).get("policy").toString());
152 "************************************************************************************************");
154 PolicyRestAdapter policyData = mapper.readValue(
155 root.get(PolicyController.getPolicydata()).get("policy").toString(), PolicyRestAdapter.class);
156 modifyPolicyData(root, policyData);
158 if (policyData.getConfigPolicyType() != null) {
159 if (CLOSED_LOOP_FAULT.equalsIgnoreCase(policyData.getConfigPolicyType())) {
160 policyData = new CreateClosedLoopFaultController().setDataToPolicyRestAdapter(policyData, root);
161 } else if (FIREWALL_CONFIG.equalsIgnoreCase(policyData.getConfigPolicyType())) {
162 policyData = new CreateFirewallController().setDataToPolicyRestAdapter(policyData);
163 } else if (MICRO_SERVICE.equalsIgnoreCase(policyData.getConfigPolicyType())) {
164 policyData = new CreateDcaeMicroServiceController().setDataToPolicyRestAdapter(policyData, root);
165 } else if (OPTIMIZATION.equalsIgnoreCase(policyData.getConfigPolicyType())) {
166 policyData = new CreateOptimizationController().setDataToPolicyRestAdapter(policyData, root);
170 policyData.setUserId(userId);
173 ResponseEntity<?> responseEntity = sendToPap(PolicyUtils.objectToJsonString(policyData),
174 request.getRequestURI(), HttpMethod.POST);
175 if (responseEntity != null && responseEntity.getBody().equals(HttpServletResponse.SC_CONFLICT)) {
176 result = "PolicyExists";
177 } else if (responseEntity != null) {
178 result = responseEntity.getBody().toString();
179 String policyName = responseEntity.getHeaders().get(POLICY_NAME).get(0);
180 if (policyData.isEditPolicy() && SUCCESS.equalsIgnoreCase(result)) {
181 final PolicyNotificationMail email = new PolicyNotificationMail();
182 final String mode = "EditPolicy";
183 String watchPolicyName = policyName.replace(XML, "");
184 String version = watchPolicyName.substring(watchPolicyName.lastIndexOf('.') + 1);
186 watchPolicyName.substring(0, watchPolicyName.lastIndexOf('.')).replace(".", File.separator);
187 String policyVersionName = watchPolicyName.replace(".", File.separator);
188 watchPolicyName = watchPolicyName + "." + version + XML;
189 PolicyVersion entityItem = new PolicyVersion();
190 entityItem.setPolicyName(policyVersionName);
191 entityItem.setActiveVersion(Integer.parseInt(version));
192 entityItem.setModifiedBy(userId);
193 email.sendMail(entityItem, watchPolicyName, mode, commonClassDao);
196 result = "Response is null from PAP";
199 response.setCharacterEncoding(PolicyController.getCharacterencoding());
200 response.setContentType(PolicyController.getContenttype());
201 request.setCharacterEncoding(PolicyController.getCharacterencoding());
203 PrintWriter out = response.getWriter();
204 String responseString = mapper.writeValueAsString(result);
205 JSONObject json = new JSONObject("{policyData: " + responseString + "}");
206 out.write(json.toString());
209 private void modifyPolicyData(JsonNode root, PolicyRestAdapter policyData) {
210 if (FILE.equals(root.get(PolicyController.getPolicydata()).get(MODEL).get(TYPE).toString().replace("\"", ""))) {
211 policyData.setEditPolicy(true);
213 if (root.get(PolicyController.getPolicydata()).get(MODEL).get(PATH).size() != 0) {
215 for (int i = 0; i < root.get(PolicyController.getPolicydata()).get(MODEL).get(PATH).size(); i++) {
216 dirName = dirName.replace("\"", "") + root.get(PolicyController.getPolicydata()).get(MODEL).get(PATH)
217 .get(i).toString().replace("\"", "") + File.separator;
219 if (policyData.isEditPolicy()) {
220 policyData.setDomainDir(dirName.substring(0, dirName.lastIndexOf(File.separator)));
222 policyData.setDomainDir(dirName
223 + root.get(PolicyController.getPolicydata()).get(MODEL).get(NAME).toString().replace("\"", ""));
226 String domain = root.get(PolicyController.getPolicydata()).get(MODEL).get(NAME).toString();
227 if (domain.contains("/")) {
228 domain = domain.substring(0, domain.lastIndexOf('/')).replace("/", File.separator);
230 domain = domain.replace("\"", "");
231 policyData.setDomainDir(domain);
235 private ResponseEntity<?> sendToPap(String body, String requestUri, HttpMethod method) {
236 String papUrl = PolicyController.getPapUrl();
237 String papPass = PeCryptoUtils.decrypt(XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_PASS));
238 String encoding = Base64.getEncoder().encodeToString(
239 (XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_USERID)
240 + ":" + papPass).getBytes(StandardCharsets.UTF_8));
241 HttpHeaders headers = new HttpHeaders();
242 headers.set(AUTHORIZATION, BASIC + encoding);
243 headers.set(CONTENT_TYPE, PolicyController.getContenttype());
245 RestTemplate restTemplate = new RestTemplate();
246 HttpEntity<?> requestEntity = new HttpEntity<>(body, headers);
247 ResponseEntity<?> result = null;
248 HttpClientErrorException exception = null;
249 String uri = requestUri;
250 if (uri.startsWith("/")) {
251 uri = uri.substring(uri.indexOf('/') + 1);
253 uri = "onap" + uri.substring(uri.indexOf('/'));
255 result = restTemplate.exchange(papUrl + uri, method, requestEntity, String.class);
256 } catch (Exception e) {
257 policyLogger.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Error while connecting to " + papUrl, e);
258 exception = new HttpClientErrorException(HttpStatus.INTERNAL_SERVER_ERROR, e.getMessage());
259 if ("409 Conflict".equals(e.getMessage())) {
260 return ResponseEntity.ok(HttpServletResponse.SC_CONFLICT);
263 if (exception != null && exception.getStatusCode() != null) {
264 if (exception.getStatusCode().equals(HttpStatus.UNAUTHORIZED)) {
265 String message = XACMLErrorConstants.ERROR_PERMISSIONS + ":" + exception.getStatusCode() + ":"
266 + "ERROR_AUTH_GET_PERM";
267 policyLogger.error(message);
269 if (exception.getStatusCode().equals(HttpStatus.BAD_REQUEST)) {
270 String message = XACMLErrorConstants.ERROR_DATA_ISSUE + ":" + exception.getStatusCode() + ":"
271 + exception.getResponseBodyAsString();
272 policyLogger.error(message);
274 if (exception.getStatusCode().equals(HttpStatus.NOT_FOUND)) {
276 XACMLErrorConstants.ERROR_PROCESS_FLOW + "Error while connecting to " + papUrl + exception;
277 policyLogger.error(message);
279 String message = XACMLErrorConstants.ERROR_PROCESS_FLOW + ":" + exception.getStatusCode() + ":"
280 + exception.getResponseBodyAsString();
281 policyLogger.error(message);
286 private String callPap(HttpServletRequest request, String method, String uriValue) {
287 PeCryptoUtils.initAesKey(XACMLProperties.getProperty(XACMLRestProperties.PROP_AES_KEY));
288 String papPass = PeCryptoUtils.decrypt((XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_PASS)));
290 Base64.Encoder encoder = Base64.getEncoder();
291 String encoding = encoder.encodeToString((XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_USERID)
292 + ":" + papPass).getBytes(StandardCharsets.UTF_8));
293 HttpHeaders headers = new HttpHeaders();
294 headers.set(AUTHORIZATION, BASIC + encoding);
295 headers.set(CONTENT_TYPE, PolicyController.getContenttype());
297 HttpURLConnection connection = null;
298 FileItem item = null;
300 String uri = uriValue;
301 if (uri.contains(IMPORT_DICTIONARY)) {
303 List<FileItem> items = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(request);
305 file = new File(item.getName());
306 String newFile = file.toString();
307 uri = uri + "&dictionaryName=" + newFile;
308 } catch (Exception e2) {
309 policyLogger.error("Exception Occured while calling PAP with import dictionary request" + e2);
314 URL url = new URL(PolicyController.getPapUrl() + uri);
315 connection = (HttpURLConnection) url.openConnection();
316 connection.setRequestMethod(method);
317 connection.setUseCaches(false);
318 connection.setInstanceFollowRedirects(false);
319 connection.setRequestProperty(AUTHORIZATION, BASIC + encoding);
320 connection.setDoOutput(true);
321 connection.setDoInput(true);
323 if (uri.contains("searchPolicy?action=delete&")) {
325 return doConnect(connection);
328 checkUri(request, uri, connection, item);
330 return doConnect(connection);
331 } catch (Exception e) {
332 policyLogger.error("Exception Occured" + e);
334 if (file != null && file.exists() && file.delete()) {
335 policyLogger.info("File Deleted Successfully");
337 if (connection != null) {
339 // For some reason trying to get the inputStream from the connection
340 // throws an exception rather than returning null when the InputStream does not exist.
341 InputStream is = connection.getInputStream();
345 } catch (IOException ex) {
346 policyLogger.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Failed to close connection: " + ex,
349 connection.disconnect();
355 private void checkUri(HttpServletRequest request, String uri, HttpURLConnection connection, FileItem item)
357 if (!(uri.endsWith("set_BRMSParamData") || uri.contains(IMPORT_DICTIONARY))) {
358 connection.setRequestProperty(CONTENT_TYPE, PolicyController.getContenttype());
359 ObjectMapper mapper = new ObjectMapper();
360 mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
361 JsonNode root = getJsonNode(request, mapper);
363 ObjectMapper mapper1 = new ObjectMapper();
364 mapper1.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
366 Object obj = mapper1.treeToValue(root, Object.class);
367 String json = mapper1.writeValueAsString(obj);
369 // send current configuration
370 try (InputStream content = new ByteArrayInputStream(json.getBytes());
371 OutputStream os = connection.getOutputStream()) {
372 int count = IOUtils.copy(content, os);
373 if (policyLogger.isDebugEnabled()) {
374 policyLogger.debug("copied to output, bytes=" + count);
377 } else if (uri.endsWith("set_BRMSParamData")) {
378 connection.setRequestProperty(CONTENT_TYPE, PolicyController.getContenttype());
379 try (OutputStream os = connection.getOutputStream()) {
380 IOUtils.copy(request.getInputStream(), os);
383 String boundary = "===" + System.currentTimeMillis() + "===";
384 connection.setRequestProperty(CONTENT_TYPE, "multipart/form-data; boundary=" + boundary);
385 try (OutputStream os = connection.getOutputStream()) {
387 IOUtils.copy(item.getInputStream(), os);
393 private JsonNode getJsonNode(HttpServletRequest request, ObjectMapper mapper) {
394 JsonNode root = null;
396 root = mapper.readTree(request.getReader());
397 } catch (Exception e1) {
398 policyLogger.error("Exception Occured while calling PAP" + e1);
403 private String doConnect(final HttpURLConnection connection) throws IOException {
404 connection.connect();
405 if (connection.getResponseCode() == 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);
428 * getDictionaryController.
430 * @param request Request
431 * @param response Response
433 @RequestMapping(value = {"/getDictionary/*"}, method = {RequestMethod.GET})
434 public void getDictionaryController(HttpServletRequest request, HttpServletResponse response) {
436 ResponseEntity<?> responseEntity = sendToPap(null, request.getRequestURI().replace("/getDictionary", ""),
438 if (responseEntity != null) {
439 body = responseEntity.getBody().toString();
444 response.getWriter().write(body);
445 } catch (IOException e) {
446 policyLogger.error("Exception occured while getting Dictionary entries", e);
451 * saveDictionaryController.
453 * @param request Request
454 * @param response Response
455 * @throws IOException IO Exception
457 @RequestMapping(value = {"/saveDictionary/*/*"}, method = {RequestMethod.POST})
458 public void saveDictionaryController(HttpServletRequest request, HttpServletResponse response) throws IOException {
460 String uri = request.getRequestURI().replace("/saveDictionary", "");
461 if (uri.startsWith("/")) {
462 uri = uri.substring(uri.indexOf('/') + 1);
464 uri = ONAP + uri.substring(uri.indexOf('/'));
465 if (uri.contains(IMPORT_DICTIONARY)) {
466 userId = UserUtils.getUserSession(request).getOrgUserId();
467 uri = uri + "?userId=" + userId;
471 "********************Logging UserID while Saving Dictionary**************************************");
472 policyLogger.info(USER_ID + userId);
474 "************************************************************************************************");
476 String body = callPap(request, "POST", uri.replaceFirst("/", "").trim());
477 if (body != null && !body.isEmpty()) {
478 response.getWriter().write(body);
480 response.getWriter().write("Failed");
485 * deletetDictionaryController.
487 * @param request Request
488 * @param response Response
489 * @throws IOException IO Exception
491 @RequestMapping(value = {"/deleteDictionary/*/*"}, method = {RequestMethod.POST})
492 public void deletetDictionaryController(HttpServletRequest request, HttpServletResponse response)
494 String uri = request.getRequestURI().replace("/deleteDictionary", "");
495 if (uri.startsWith("/")) {
496 uri = uri.substring(uri.indexOf('/') + 1);
498 uri = ONAP + uri.substring(uri.indexOf('/'));
500 String userId = UserUtils.getUserSession(request).getOrgUserId();
502 "**********************Logging UserID while Deleting Dictionary*************************************");
503 policyLogger.info(USER_ID + userId);
505 "***************************************************************************************************");
507 String body = callPap(request, "POST", uri.replaceFirst("/", "").trim());
508 if (body != null && !body.isEmpty()) {
509 response.getWriter().write(body);
511 response.getWriter().write("Failed");
516 * searchDictionaryController.
518 * @param request Request
519 * @param response Response
520 * @return ModelAndView object
521 * @throws IOException IO Exception
523 @RequestMapping(value = {"/searchDictionary"}, method = {RequestMethod.POST})
524 public ModelAndView searchDictionaryController(HttpServletRequest request, HttpServletResponse response)
527 String uri = request.getRequestURI();
528 if (uri.startsWith("/")) {
529 uri = uri.substring(uri.indexOf('/') + 1);
531 uri = ONAP + uri.substring(uri.indexOf('/'));
533 String body = callPap(request, "POST", uri.replaceFirst("/", "").trim());
534 if (body.contains("CouldNotConnectException")) {
535 List<String> data = new ArrayList<>();
536 data.add("Elastic Search Server is down");
539 resultList = new JSONObject(body).get("policyresult");
541 } catch (Exception e) {
543 XACMLErrorConstants.ERROR_PROCESS_FLOW + "Exception Occured while querying Elastic Search: " + e);
544 List<String> data = new ArrayList<>();
545 data.add("Elastic Search Server is down");
549 response.setCharacterEncoding(PolicyController.getCharacterencoding());
550 response.setContentType(PolicyController.getContenttype());
551 response.getWriter().write(new JSONObject("{result: " + resultList + "}").toString());
558 * @param request request
559 * @param response response
560 * @return ModelAndView object
561 * @throws IOException IO exception
563 @RequestMapping(value = {"/searchPolicy"}, method = {RequestMethod.POST})
564 public ModelAndView searchPolicy(HttpServletRequest request, HttpServletResponse response) throws IOException {
566 String uri = request.getRequestURI() + "?action=search";
567 if (uri.startsWith("/")) {
568 uri = uri.substring(uri.indexOf('/') + 1);
570 uri = ONAP + uri.substring(uri.indexOf('/'));
571 String body = callPap(request, "POST", uri.replaceFirst("/", "").trim());
573 JSONObject json = new JSONObject(body);
575 resultList = json.get("policyresult");
576 } catch (Exception e) {
577 List<String> data = new ArrayList<>();
578 resultList = json.get(DATA);
579 data.add("Exception");
580 data.add(resultList.toString());
582 policyLogger.error("Exception Occured while searching for Policy in Elastic Database" + e);
585 response.setCharacterEncoding(UTF_8);
586 response.setContentType("application / json");
587 request.setCharacterEncoding(UTF_8);
589 response.getWriter().write(new JSONObject("{result: " + resultList + "}").toString());
593 public void deleteElasticData(String fileName) {
594 String uri = "searchPolicy?action=delete&policyName='" + fileName + "'";
595 callPap(null, "POST", uri.trim());
599 * notifyOtherPAPSToUpdateConfigurations.
602 * @param newName New Name
603 * @param oldName Old Name
606 public String notifyOtherPapsToUpdateConfigurations(String mode, String newName, String oldName) {
608 "onap/notifyOtherPAPs?action=" + mode + "&newPolicyName=" + newName + "&oldPolicyName=" + oldName + "";
609 return callPap(null, "POST", uri.trim());