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 String userId = UserUtils.getUserSession(request).getOrgUserId();
136 ObjectMapper mapper = new ObjectMapper();
137 mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
139 updateAndSendToPap(request, response, userId, mapper);
140 } catch (Exception e) {
141 policyLogger.error("Exception Occured while saving policy", e);
145 private void updateAndSendToPap(HttpServletRequest request, HttpServletResponse response, String userId,
146 ObjectMapper mapper) throws IOException {
147 JsonNode root = mapper.readTree(request.getReader());
149 "********************Logging UserID while Create/Update Policy***********************************");
150 policyLogger.info(USER_ID + userId + "Policy Data Object: "
151 + root.get(PolicyController.getPolicydata()).get("policy").toString());
153 "************************************************************************************************");
155 PolicyRestAdapter policyData = mapper.readValue(
156 root.get(PolicyController.getPolicydata()).get("policy").toString(), PolicyRestAdapter.class);
157 modifyPolicyData(root, policyData);
159 if (policyData.getConfigPolicyType() != null) {
160 if (CLOSED_LOOP_FAULT.equalsIgnoreCase(policyData.getConfigPolicyType())) {
161 policyData = new CreateClosedLoopFaultController().setDataToPolicyRestAdapter(policyData, root);
162 } else if (FIREWALL_CONFIG.equalsIgnoreCase(policyData.getConfigPolicyType())) {
163 policyData = new CreateFirewallController().setDataToPolicyRestAdapter(policyData);
164 } else if (MICRO_SERVICE.equalsIgnoreCase(policyData.getConfigPolicyType())) {
165 policyData = new CreateDcaeMicroServiceController().setDataToPolicyRestAdapter(policyData, root);
166 } else if (OPTIMIZATION.equalsIgnoreCase(policyData.getConfigPolicyType())) {
167 policyData = new CreateOptimizationController().setDataToPolicyRestAdapter(policyData, root);
171 policyData.setUserId(userId);
174 String body = PolicyUtils.objectToJsonString(policyData);
175 String uri = request.getRequestURI();
176 ResponseEntity<?> responseEntity = sendToPap(body, uri, HttpMethod.POST);
177 if (responseEntity != null && responseEntity.getBody().equals(HttpServletResponse.SC_CONFLICT)) {
178 result = "PolicyExists";
179 } else if (responseEntity != null) {
180 result = responseEntity.getBody().toString();
181 String policyName = responseEntity.getHeaders().get(POLICY_NAME).get(0);
182 if (policyData.isEditPolicy() && SUCCESS.equalsIgnoreCase(result)) {
183 final PolicyNotificationMail email = new PolicyNotificationMail();
184 final String mode = "EditPolicy";
185 String watchPolicyName = policyName.replace(XML, "");
186 String version = watchPolicyName.substring(watchPolicyName.lastIndexOf('.') + 1);
188 watchPolicyName.substring(0, watchPolicyName.lastIndexOf('.')).replace(".", File.separator);
189 String policyVersionName = watchPolicyName.replace(".", File.separator);
190 watchPolicyName = watchPolicyName + "." + version + XML;
191 PolicyVersion entityItem = new PolicyVersion();
192 entityItem.setPolicyName(policyVersionName);
193 entityItem.setActiveVersion(Integer.parseInt(version));
194 entityItem.setModifiedBy(userId);
195 email.sendMail(entityItem, watchPolicyName, mode, commonClassDao);
198 result = "Response is null from PAP";
201 response.setCharacterEncoding(PolicyController.getCharacterencoding());
202 response.setContentType(PolicyController.getContenttype());
203 request.setCharacterEncoding(PolicyController.getCharacterencoding());
205 PrintWriter out = response.getWriter();
206 String responseString = mapper.writeValueAsString(result);
207 JSONObject json = new JSONObject("{policyData: " + responseString + "}");
208 out.write(json.toString());
211 private void modifyPolicyData(JsonNode root, PolicyRestAdapter policyData) {
212 if (FILE.equals(root.get(PolicyController.getPolicydata()).get(MODEL).get(TYPE).toString().replace("\"", ""))) {
213 policyData.setEditPolicy(true);
215 if (root.get(PolicyController.getPolicydata()).get(MODEL).get(PATH).size() != 0) {
217 for (int i = 0; i < root.get(PolicyController.getPolicydata()).get(MODEL).get(PATH).size(); i++) {
218 dirName = dirName.replace("\"", "") + root.get(PolicyController.getPolicydata()).get(MODEL).get(PATH)
219 .get(i).toString().replace("\"", "") + File.separator;
221 if (policyData.isEditPolicy()) {
222 policyData.setDomainDir(dirName.substring(0, dirName.lastIndexOf(File.separator)));
224 policyData.setDomainDir(dirName
225 + root.get(PolicyController.getPolicydata()).get(MODEL).get(NAME).toString().replace("\"", ""));
228 String domain = root.get(PolicyController.getPolicydata()).get(MODEL).get(NAME).toString();
229 if (domain.contains("/")) {
230 domain = domain.substring(0, domain.lastIndexOf('/')).replace("/", File.separator);
232 domain = domain.replace("\"", "");
233 policyData.setDomainDir(domain);
237 private ResponseEntity<?> sendToPap(String body, String requestUri, HttpMethod method) {
238 String papUrl = PolicyController.getPapUrl();
239 String papID = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_USERID);
240 String papPass = PeCryptoUtils.decrypt(XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_PASS));
241 Base64.Encoder encoder = Base64.getEncoder();
242 String encoding = encoder.encodeToString((papID + ":" + papPass).getBytes(StandardCharsets.UTF_8));
243 HttpHeaders headers = new HttpHeaders();
244 headers.set(AUTHORIZATION, BASIC + encoding);
245 headers.set(CONTENT_TYPE, PolicyController.getContenttype());
247 RestTemplate restTemplate = new RestTemplate();
248 HttpEntity<?> requestEntity = new HttpEntity<>(body, headers);
249 ResponseEntity<?> result = null;
250 HttpClientErrorException exception = null;
251 String uri = requestUri;
252 if (uri.startsWith("/")) {
253 uri = uri.substring(uri.indexOf('/') + 1);
255 uri = "onap" + uri.substring(uri.indexOf('/'));
257 result = restTemplate.exchange(papUrl + uri, method, requestEntity, String.class);
258 } catch (Exception e) {
259 policyLogger.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Error while connecting to " + papUrl, e);
260 exception = new HttpClientErrorException(HttpStatus.INTERNAL_SERVER_ERROR, e.getMessage());
261 if ("409 Conflict".equals(e.getMessage())) {
262 return ResponseEntity.ok(HttpServletResponse.SC_CONFLICT);
265 if (exception != null && exception.getStatusCode() != null) {
266 if (exception.getStatusCode().equals(HttpStatus.UNAUTHORIZED)) {
267 String message = XACMLErrorConstants.ERROR_PERMISSIONS + ":" + exception.getStatusCode() + ":"
268 + "ERROR_AUTH_GET_PERM";
269 policyLogger.error(message);
271 if (exception.getStatusCode().equals(HttpStatus.BAD_REQUEST)) {
272 String message = XACMLErrorConstants.ERROR_DATA_ISSUE + ":" + exception.getStatusCode() + ":"
273 + exception.getResponseBodyAsString();
274 policyLogger.error(message);
276 if (exception.getStatusCode().equals(HttpStatus.NOT_FOUND)) {
278 XACMLErrorConstants.ERROR_PROCESS_FLOW + "Error while connecting to " + papUrl + exception;
279 policyLogger.error(message);
281 String message = XACMLErrorConstants.ERROR_PROCESS_FLOW + ":" + exception.getStatusCode() + ":"
282 + exception.getResponseBodyAsString();
283 policyLogger.error(message);
288 private String callPap(HttpServletRequest request, String method, String uriValue) {
289 String papUrl = PolicyController.getPapUrl();
290 String papID = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_USERID);
291 PeCryptoUtils.initAesKey(XACMLProperties.getProperty(XACMLRestProperties.PROP_AES_KEY));
292 String papPass = PeCryptoUtils.decrypt((XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_PASS)));
294 Base64.Encoder encoder = Base64.getEncoder();
295 String encoding = encoder.encodeToString((papID + ":" + papPass).getBytes(StandardCharsets.UTF_8));
296 HttpHeaders headers = new HttpHeaders();
297 headers.set(AUTHORIZATION, BASIC + encoding);
298 headers.set(CONTENT_TYPE, PolicyController.getContenttype());
300 HttpURLConnection connection = null;
301 List<FileItem> items;
302 FileItem item = null;
304 String uri = uriValue;
305 if (uri.contains(IMPORT_DICTIONARY)) {
307 items = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(request);
309 file = new File(item.getName());
310 String newFile = file.toString();
311 uri = uri + "&dictionaryName=" + newFile;
312 } catch (Exception e2) {
313 policyLogger.error("Exception Occured while calling PAP with import dictionary request" + e2);
318 URL url = new URL(papUrl + uri);
319 connection = (HttpURLConnection) url.openConnection();
320 connection.setRequestMethod(method);
321 connection.setUseCaches(false);
322 connection.setInstanceFollowRedirects(false);
323 connection.setRequestProperty(AUTHORIZATION, BASIC + encoding);
324 connection.setDoOutput(true);
325 connection.setDoInput(true);
327 if (uri.contains("searchPolicy?action=delete&")) {
329 return doConnect(connection);
332 checkUri(request, uri, connection, item);
334 return doConnect(connection);
335 } catch (Exception e) {
336 policyLogger.error("Exception Occured" + e);
338 if (file != null && file.exists() && file.delete()) {
339 policyLogger.info("File Deleted Successfully");
341 if (connection != null) {
343 // For some reason trying to get the inputStream from the connection
344 // throws an exception rather than returning null when the InputStream does not exist.
345 InputStream is = connection.getInputStream();
349 } catch (IOException ex) {
350 policyLogger.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Failed to close connection: " + ex,
353 connection.disconnect();
359 private void checkUri(HttpServletRequest request, String uri, HttpURLConnection connection, FileItem item)
362 if (!(uri.endsWith("set_BRMSParamData") || uri.contains(IMPORT_DICTIONARY))) {
363 connection.setRequestProperty(CONTENT_TYPE, PolicyController.getContenttype());
364 ObjectMapper mapper = new ObjectMapper();
365 mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
366 JsonNode root = getJsonNode(request, mapper);
368 ObjectMapper mapper1 = new ObjectMapper();
369 mapper1.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
371 Object obj = mapper1.treeToValue(root, Object.class);
372 String json = mapper1.writeValueAsString(obj);
374 // send current configuration
375 try (InputStream content = new ByteArrayInputStream(json.getBytes());
376 OutputStream os = connection.getOutputStream()) {
377 int count = IOUtils.copy(content, os);
378 if (policyLogger.isDebugEnabled()) {
379 policyLogger.debug("copied to output, bytes=" + count);
382 } else if (uri.endsWith("set_BRMSParamData")) {
383 connection.setRequestProperty(CONTENT_TYPE, PolicyController.getContenttype());
384 try (OutputStream os = connection.getOutputStream()) {
385 IOUtils.copy(request.getInputStream(), os);
388 boundary = "===" + System.currentTimeMillis() + "===";
389 connection.setRequestProperty(CONTENT_TYPE, "multipart/form-data; boundary=" + boundary);
390 try (OutputStream os = connection.getOutputStream()) {
392 IOUtils.copy(item.getInputStream(), os);
398 private JsonNode getJsonNode(HttpServletRequest request, ObjectMapper mapper) {
399 JsonNode root = null;
401 root = mapper.readTree(request.getReader());
402 } catch (Exception e1) {
403 policyLogger.error("Exception Occured while calling PAP" + e1);
408 private String doConnect(final HttpURLConnection connection) throws IOException {
409 connection.connect();
410 int responseCode = connection.getResponseCode();
411 if (responseCode == 200) {
412 // get the response content into a String
413 String responseJson = null;
414 // read the inputStream into a buffer (trick found online scans entire input looking for end-of-file)
415 try (java.util.Scanner scanner = new java.util.Scanner(connection.getInputStream())) {
416 scanner.useDelimiter("\\A");
417 responseJson = scanner.hasNext() ? scanner.next() : "";
418 } catch (Exception e) {
419 // Reason for rethrowing the exception is if any exception occurs during reading of inputsteam
420 // then the exception handling is done by the outer block without returning the response immediately
421 // Also finally block is existing only in outer block and not here so all exception handling is
422 // done in only one place
423 policyLogger.error("Exception Occured" + e);
427 policyLogger.info("JSON response from PAP: " + responseJson);
434 * getDictionaryController.
436 * @param request Request
437 * @param response Response
439 @RequestMapping(value = {"/getDictionary/*"}, method = {RequestMethod.GET})
440 public void getDictionaryController(HttpServletRequest request, HttpServletResponse response) {
441 String uri = request.getRequestURI().replace("/getDictionary", "");
443 ResponseEntity<?> responseEntity = sendToPap(null, uri, HttpMethod.GET);
444 if (responseEntity != null) {
445 body = responseEntity.getBody().toString();
450 response.getWriter().write(body);
451 } catch (IOException e) {
452 policyLogger.error("Exception occured while getting Dictionary entries", e);
457 * saveDictionaryController.
459 * @param request Request
460 * @param response Response
461 * @throws IOException IO Exception
463 @RequestMapping(value = {"/saveDictionary/*/*"}, method = {RequestMethod.POST})
464 public void saveDictionaryController(HttpServletRequest request, HttpServletResponse response) throws IOException {
466 String uri = request.getRequestURI().replace("/saveDictionary", "");
467 if (uri.startsWith("/")) {
468 uri = uri.substring(uri.indexOf('/') + 1);
470 uri = ONAP + uri.substring(uri.indexOf('/'));
471 if (uri.contains(IMPORT_DICTIONARY)) {
472 userId = UserUtils.getUserSession(request).getOrgUserId();
473 uri = uri + "?userId=" + userId;
477 "********************Logging UserID while Saving Dictionary**************************************");
478 policyLogger.info(USER_ID + userId);
480 "************************************************************************************************");
482 String body = callPap(request, "POST", uri.replaceFirst("/", "").trim());
483 if (body != null && !body.isEmpty()) {
484 response.getWriter().write(body);
486 response.getWriter().write("Failed");
491 * deletetDictionaryController.
493 * @param request Request
494 * @param response Response
495 * @throws IOException IO Exception
497 @RequestMapping(value = {"/deleteDictionary/*/*"}, method = {RequestMethod.POST})
498 public void deletetDictionaryController(HttpServletRequest request, HttpServletResponse response)
500 String uri = request.getRequestURI().replace("/deleteDictionary", "");
501 if (uri.startsWith("/")) {
502 uri = uri.substring(uri.indexOf('/') + 1);
504 uri = ONAP + uri.substring(uri.indexOf('/'));
506 String userId = UserUtils.getUserSession(request).getOrgUserId();
508 "**********************Logging UserID while Deleting Dictionary*************************************");
509 policyLogger.info(USER_ID + userId);
511 "***************************************************************************************************");
513 String body = callPap(request, "POST", uri.replaceFirst("/", "").trim());
514 if (body != null && !body.isEmpty()) {
515 response.getWriter().write(body);
517 response.getWriter().write("Failed");
522 * searchDictionaryController.
524 * @param request Request
525 * @param response Response
526 * @return ModelAndView object
527 * @throws IOException IO Exception
529 @RequestMapping(value = {"/searchDictionary"}, method = {RequestMethod.POST})
530 public ModelAndView searchDictionaryController(HttpServletRequest request, HttpServletResponse response)
533 String uri = request.getRequestURI();
534 if (uri.startsWith("/")) {
535 uri = uri.substring(uri.indexOf('/') + 1);
537 uri = ONAP + uri.substring(uri.indexOf('/'));
539 String body = callPap(request, "POST", uri.replaceFirst("/", "").trim());
540 if (body.contains("CouldNotConnectException")) {
541 List<String> data = new ArrayList<>();
542 data.add("Elastic Search Server is down");
545 JSONObject json = new JSONObject(body);
546 resultList = json.get("policyresult");
548 } catch (Exception e) {
550 XACMLErrorConstants.ERROR_PROCESS_FLOW + "Exception Occured while querying Elastic Search: " + e);
551 List<String> data = new ArrayList<>();
552 data.add("Elastic Search Server is down");
556 response.setCharacterEncoding(PolicyController.getCharacterencoding());
557 response.setContentType(PolicyController.getContenttype());
558 PrintWriter out = response.getWriter();
559 JSONObject json = new JSONObject("{result: " + resultList + "}");
560 out.write(json.toString());
567 * @param request request
568 * @param response response
569 * @return ModelAndView object
570 * @throws IOException IO exception
572 @RequestMapping(value = {"/searchPolicy"}, method = {RequestMethod.POST})
573 public ModelAndView searchPolicy(HttpServletRequest request, HttpServletResponse response) throws IOException {
575 String uri = request.getRequestURI() + "?action=search";
576 if (uri.startsWith("/")) {
577 uri = uri.substring(uri.indexOf('/') + 1);
579 uri = ONAP + uri.substring(uri.indexOf('/'));
580 String body = callPap(request, "POST", uri.replaceFirst("/", "").trim());
582 JSONObject json = new JSONObject(body);
584 resultList = json.get("policyresult");
585 } catch (Exception e) {
586 List<String> data = new ArrayList<>();
587 resultList = json.get(DATA);
588 data.add("Exception");
589 data.add(resultList.toString());
591 policyLogger.error("Exception Occured while searching for Policy in Elastic Database" + e);
594 response.setCharacterEncoding(UTF_8);
595 response.setContentType("application / json");
596 request.setCharacterEncoding(UTF_8);
598 PrintWriter out = response.getWriter();
599 JSONObject json2 = new JSONObject("{result: " + resultList + "}");
600 out.write(json2.toString());
604 public void deleteElasticData(String fileName) {
605 String uri = "searchPolicy?action=delete&policyName='" + fileName + "'";
606 callPap(null, "POST", uri.trim());
610 * notifyOtherPAPSToUpdateConfigurations.
613 * @param newName New Name
614 * @param oldName Old Name
617 public String notifyOtherPapsToUpdateConfigurations(String mode, String newName, String oldName) {
619 "onap/notifyOtherPAPs?action=" + mode + "&newPolicyName=" + newName + "&oldPolicyName=" + oldName + "";
620 return callPap(null, "POST", uri.trim());