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;
30 import java.io.ByteArrayInputStream;
32 import java.io.IOException;
33 import java.io.InputStream;
34 import java.io.OutputStream;
35 import java.io.PrintWriter;
36 import java.net.HttpURLConnection;
38 import java.nio.charset.StandardCharsets;
39 import java.util.ArrayList;
40 import java.util.Base64;
41 import java.util.List;
42 import javax.servlet.http.HttpServletRequest;
43 import javax.servlet.http.HttpServletResponse;
44 import org.apache.commons.fileupload.FileItem;
45 import org.apache.commons.fileupload.disk.DiskFileItemFactory;
46 import org.apache.commons.fileupload.servlet.ServletFileUpload;
47 import org.apache.commons.io.IOUtils;
48 import org.json.JSONObject;
49 import org.onap.policy.common.logging.flexlogger.FlexLogger;
50 import org.onap.policy.common.logging.flexlogger.Logger;
51 import org.onap.policy.controller.CreateClosedLoopFaultController;
52 import org.onap.policy.controller.CreateDcaeMicroServiceController;
53 import org.onap.policy.controller.CreateFirewallController;
54 import org.onap.policy.controller.CreateOptimizationController;
55 import org.onap.policy.controller.PolicyController;
56 import org.onap.policy.rest.XACMLRestProperties;
57 import org.onap.policy.rest.adapter.PolicyRestAdapter;
58 import org.onap.policy.rest.dao.CommonClassDao;
59 import org.onap.policy.rest.jpa.PolicyVersion;
60 import org.onap.policy.utils.PeCryptoUtils;
61 import org.onap.policy.utils.PolicyUtils;
62 import org.onap.policy.xacml.api.XACMLErrorConstants;
63 import org.onap.portalsdk.core.controller.RestrictedBaseController;
64 import org.onap.portalsdk.core.web.support.UserUtils;
65 import org.springframework.beans.factory.annotation.Autowired;
66 import org.springframework.http.HttpEntity;
67 import org.springframework.http.HttpHeaders;
68 import org.springframework.http.HttpMethod;
69 import org.springframework.http.HttpStatus;
70 import org.springframework.http.ResponseEntity;
71 import org.springframework.web.bind.annotation.RequestMapping;
72 import org.springframework.web.bind.annotation.RequestMethod;
73 import org.springframework.web.bind.annotation.RestController;
74 import org.springframework.web.client.HttpClientErrorException;
75 import org.springframework.web.client.RestTemplate;
76 import org.springframework.web.servlet.ModelAndView;
80 public class PolicyRestController extends RestrictedBaseController {
82 private static final Logger policyLogger = FlexLogger.getLogger(PolicyRestController.class);
84 private static final String MODEL = "model";
85 private static final String IMPORT_DICTIONARY = "import_dictionary";
86 private static final String FILE = "file";
87 private static final String TYPE = "type";
88 private static final String PATH = "path";
89 private static final String NAME = "name";
90 private static final String CLOSED_LOOP_FAULT = "ClosedLoop_Fault";
91 private static final String FIREWALL_CONFIG = "Firewall Config";
92 private static final String MICRO_SERVICE = "Micro Service";
93 private static final String OPTIMIZATION = "Optimization";
94 private static final String POLICY_NAME = "policyName";
95 private static final String SUCCESS = "success";
96 private static final String XML = ".xml";
97 private static final String UTF_8 = "UTF-8";
98 private static final String DATA = "data";
99 private static final String USER_ID = "UserId: ";
100 private static final String BASIC = "Basic ";
101 private static final String AUTHORIZATION = "Authorization";
102 private static final String CONTENT_TYPE = "Content-Type";
103 private static final String ONAP = "/onap";
105 private static CommonClassDao commonClassDao;
107 public PolicyRestController() {
108 // default constructor
112 private PolicyRestController(CommonClassDao commonClassDao) {
113 PolicyRestController.commonClassDao = commonClassDao;
116 public static CommonClassDao getCommonClassDao() {
117 return commonClassDao;
120 public static void setCommonClassDao(CommonClassDao commonClassDao) {
121 PolicyRestController.commonClassDao = commonClassDao;
126 @RequestMapping(value = {"/policycreation/save_policy"}, method = {RequestMethod.POST})
127 public void policyCreationController(HttpServletRequest request, HttpServletResponse response) {
128 String userId = UserUtils.getUserSession(request).getOrgUserId();
129 ObjectMapper mapper = new ObjectMapper();
130 mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
132 updateAndSendToPAP(request, response, userId, mapper);
133 } catch (Exception e) {
134 policyLogger.error("Exception Occured while saving policy", e);
138 private void updateAndSendToPAP(HttpServletRequest request, HttpServletResponse response, String userId,
139 ObjectMapper mapper) throws IOException {
140 JsonNode root = mapper.readTree(request.getReader());
142 "****************************************Logging UserID while Create/Update Policy**************************************************");
143 policyLogger.info(USER_ID + userId + "Policy Data Object: "
144 + root.get(PolicyController.getPolicydata()).get("policy").toString());
146 "***********************************************************************************************************************************");
148 PolicyRestAdapter policyData = mapper.readValue(
149 root.get(PolicyController.getPolicydata()).get("policy").toString(), PolicyRestAdapter.class);
150 modifyPolicyData(root, policyData);
152 if (policyData.getConfigPolicyType() != null) {
153 if (CLOSED_LOOP_FAULT.equalsIgnoreCase(policyData.getConfigPolicyType())) {
154 policyData = new CreateClosedLoopFaultController().setDataToPolicyRestAdapter(policyData, root);
155 } else if (FIREWALL_CONFIG.equalsIgnoreCase(policyData.getConfigPolicyType())) {
156 policyData = new CreateFirewallController().setDataToPolicyRestAdapter(policyData);
157 } else if (MICRO_SERVICE.equalsIgnoreCase(policyData.getConfigPolicyType())) {
158 policyData = new CreateDcaeMicroServiceController().setDataToPolicyRestAdapter(policyData, root);
159 } else if (OPTIMIZATION.equalsIgnoreCase(policyData.getConfigPolicyType())) {
160 policyData = new CreateOptimizationController().setDataToPolicyRestAdapter(policyData, root);
164 policyData.setUserId(userId);
167 String body = PolicyUtils.objectToJsonString(policyData);
168 String uri = request.getRequestURI();
169 ResponseEntity<?> responseEntity = sendToPAP(body, uri, HttpMethod.POST);
170 if (responseEntity != null && responseEntity.getBody().equals(HttpServletResponse.SC_CONFLICT)) {
171 result = "PolicyExists";
172 } else if (responseEntity != null) {
173 result = responseEntity.getBody().toString();
174 String policyName = responseEntity.getHeaders().get(POLICY_NAME).get(0);
175 if (policyData.isEditPolicy() && SUCCESS.equalsIgnoreCase(result)) {
176 PolicyNotificationMail email = new PolicyNotificationMail();
177 String mode = "EditPolicy";
178 String watchPolicyName = policyName.replace(XML, "");
179 String version = watchPolicyName.substring(watchPolicyName.lastIndexOf('.') + 1);
181 watchPolicyName.substring(0, watchPolicyName.lastIndexOf('.')).replace(".", File.separator);
182 String policyVersionName = watchPolicyName.replace(".", File.separator);
183 watchPolicyName = watchPolicyName + "." + version + XML;
184 PolicyVersion entityItem = new PolicyVersion();
185 entityItem.setPolicyName(policyVersionName);
186 entityItem.setActiveVersion(Integer.parseInt(version));
187 entityItem.setModifiedBy(userId);
188 email.sendMail(entityItem, watchPolicyName, mode, commonClassDao);
191 result = "Response is null from PAP";
194 response.setCharacterEncoding(PolicyController.getCharacterencoding());
195 response.setContentType(PolicyController.getContenttype());
196 request.setCharacterEncoding(PolicyController.getCharacterencoding());
198 PrintWriter out = response.getWriter();
199 String responseString = mapper.writeValueAsString(result);
200 JSONObject j = new JSONObject("{policyData: " + responseString + "}");
201 out.write(j.toString());
204 private void modifyPolicyData(JsonNode root, PolicyRestAdapter policyData) {
205 if (FILE.equals(root.get(PolicyController.getPolicydata()).get(MODEL).get(TYPE).toString().replace("\"", ""))) {
206 policyData.setEditPolicy(true);
208 if (root.get(PolicyController.getPolicydata()).get(MODEL).get(PATH).size() != 0) {
210 for (int i = 0; i < root.get(PolicyController.getPolicydata()).get(MODEL).get(PATH).size(); i++) {
211 dirName = dirName.replace("\"", "") + root.get(PolicyController.getPolicydata()).get(MODEL).get(PATH)
212 .get(i).toString().replace("\"", "") + File.separator;
214 if (policyData.isEditPolicy()) {
215 policyData.setDomainDir(dirName.substring(0, dirName.lastIndexOf(File.separator)));
217 policyData.setDomainDir(dirName
218 + root.get(PolicyController.getPolicydata()).get(MODEL).get(NAME).toString().replace("\"", ""));
221 String domain = root.get(PolicyController.getPolicydata()).get(MODEL).get(NAME).toString();
222 if (domain.contains("/")) {
223 domain = domain.substring(0, domain.lastIndexOf('/')).replace("/", File.separator);
225 domain = domain.replace("\"", "");
226 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());
296 HttpURLConnection connection = null;
297 List<FileItem> items;
298 FileItem item = null;
300 if (uri.contains(IMPORT_DICTIONARY)) {
302 items = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(request);
304 file = new File(item.getName());
305 String newFile = file.toString();
306 uri = uri + "&dictionaryName=" + newFile;
307 } catch (Exception e2) {
308 policyLogger.error("Exception Occured while calling PAP with import dictionary request" + e2);
313 URL url = new URL(papUrl + uri);
314 connection = (HttpURLConnection) url.openConnection();
315 connection.setRequestMethod(method);
316 connection.setUseCaches(false);
317 connection.setInstanceFollowRedirects(false);
318 connection.setRequestProperty(AUTHORIZATION, BASIC + encoding);
319 connection.setDoOutput(true);
320 connection.setDoInput(true);
322 if (uri.contains("searchPolicy?action=delete&")) {
324 return doConnect(connection);
327 checkURI(request, uri, connection, item);
329 return doConnect(connection);
330 } catch (Exception e) {
331 policyLogger.error("Exception Occured" + e);
333 if (file != null && file.exists() && file.delete()) {
334 policyLogger.info("File Deleted Successfully");
336 if (connection != null) {
338 // For some reason trying to get the inputStream from the connection
339 // throws an exception rather than returning null when the InputStream does not exist.
340 InputStream is = connection.getInputStream();
344 } catch (IOException ex) {
345 policyLogger.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Failed to close connection: " + ex,
348 connection.disconnect();
354 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 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 int responseCode = connection.getResponseCode();
406 if (responseCode == 200) {
407 // get the response content into a String
408 String responseJson = null;
409 // read the inputStream into a buffer (trick found online scans entire input looking for end-of-file)
410 try (java.util.Scanner scanner = new java.util.Scanner(connection.getInputStream())) {
411 scanner.useDelimiter("\\A");
412 responseJson = scanner.hasNext() ? scanner.next() : "";
413 } catch (Exception e) {
414 // Reason for rethrowing the exception is if any exception occurs during reading of inputsteam
415 // then the exception handling is done by the outer block without returning the response immediately
416 // Also finally block is existing only in outer block and not here so all exception handling is
417 // done in only one place
418 policyLogger.error("Exception Occured" + e);
422 policyLogger.info("JSON response from PAP: " + responseJson);
428 @RequestMapping(value = {"/getDictionary/*"}, method = {RequestMethod.GET})
429 public void getDictionaryController(HttpServletRequest request, HttpServletResponse response) {
430 String uri = request.getRequestURI().replace("/getDictionary", "");
432 ResponseEntity<?> responseEntity = sendToPAP(null, uri, HttpMethod.GET);
433 if (responseEntity != null) {
434 body = responseEntity.getBody().toString();
439 response.getWriter().write(body);
440 } catch (IOException e) {
441 policyLogger.error("Exception occured while getting Dictionary entries", e);
445 @RequestMapping(value = {"/saveDictionary/*/*"}, method = {RequestMethod.POST})
446 public void saveDictionaryController(HttpServletRequest request, HttpServletResponse response) throws IOException {
448 String uri = request.getRequestURI().replace("/saveDictionary", "");
449 if (uri.startsWith("/")) {
450 uri = uri.substring(uri.indexOf('/') + 1);
452 uri = ONAP + uri.substring(uri.indexOf('/'));
453 if (uri.contains(IMPORT_DICTIONARY)) {
454 userId = UserUtils.getUserSession(request).getOrgUserId();
455 uri = uri + "?userId=" + userId;
459 "****************************************Logging UserID while Saving Dictionary*****************************************************");
460 policyLogger.info(USER_ID + userId);
462 "***********************************************************************************************************************************");
464 String body = callPAP(request, "POST", uri.replaceFirst("/", "").trim());
465 if (body != null && !body.isEmpty()) {
466 response.getWriter().write(body);
468 response.getWriter().write("Failed");
472 @RequestMapping(value = {"/deleteDictionary/*/*"}, method = {RequestMethod.POST})
473 public void deletetDictionaryController(HttpServletRequest request, HttpServletResponse response)
475 String uri = request.getRequestURI().replace("/deleteDictionary", "");
476 if (uri.startsWith("/")) {
477 uri = uri.substring(uri.indexOf('/') + 1);
479 uri = ONAP + uri.substring(uri.indexOf('/'));
481 String userId = UserUtils.getUserSession(request).getOrgUserId();
483 "****************************************Logging UserID while Deleting Dictionary*****************************************************");
484 policyLogger.info(USER_ID + userId);
486 "*************************************************************************************************************************************");
488 String body = callPAP(request, "POST", uri.replaceFirst("/", "").trim());
489 if (body != null && !body.isEmpty()) {
490 response.getWriter().write(body);
492 response.getWriter().write("Failed");
496 @RequestMapping(value = {"/searchDictionary"}, method = {RequestMethod.POST})
497 public ModelAndView searchDictionaryController(HttpServletRequest request, HttpServletResponse response)
500 String uri = request.getRequestURI();
501 if (uri.startsWith("/")) {
502 uri = uri.substring(uri.indexOf('/') + 1);
504 uri = ONAP + uri.substring(uri.indexOf('/'));
506 String body = callPAP(request, "POST", uri.replaceFirst("/", "").trim());
507 if (body.contains("CouldNotConnectException")) {
508 List<String> data = new ArrayList<>();
509 data.add("Elastic Search Server is down");
512 JSONObject json = new JSONObject(body);
513 resultList = json.get("policyresult");
515 } catch (Exception e) {
517 XACMLErrorConstants.ERROR_PROCESS_FLOW + "Exception Occured while querying Elastic Search: " + e);
518 List<String> data = new ArrayList<>();
519 data.add("Elastic Search Server is down");
523 response.setCharacterEncoding(PolicyController.getCharacterencoding());
524 response.setContentType(PolicyController.getContenttype());
525 PrintWriter out = response.getWriter();
526 JSONObject j = new JSONObject("{result: " + resultList + "}");
527 out.write(j.toString());
531 @RequestMapping(value = {"/searchPolicy"}, method = {RequestMethod.POST})
532 public ModelAndView searchPolicy(HttpServletRequest request, HttpServletResponse response) throws IOException {
534 String uri = request.getRequestURI() + "?action=search";
535 if (uri.startsWith("/")) {
536 uri = uri.substring(uri.indexOf('/') + 1);
538 uri = ONAP + uri.substring(uri.indexOf('/'));
539 String body = callPAP(request, "POST", uri.replaceFirst("/", "").trim());
541 JSONObject json = new JSONObject(body);
543 resultList = json.get("policyresult");
544 } catch (Exception e) {
545 List<String> data = new ArrayList<>();
546 resultList = json.get(DATA);
547 data.add("Exception");
548 data.add(resultList.toString());
550 policyLogger.error("Exception Occured while searching for Policy in Elastic Database" + e);
553 response.setCharacterEncoding(UTF_8);
554 response.setContentType("application / json");
555 request.setCharacterEncoding(UTF_8);
557 PrintWriter out = response.getWriter();
558 JSONObject j = new JSONObject("{result: " + resultList + "}");
559 out.write(j.toString());
563 public void deleteElasticData(String fileName) {
564 String uri = "searchPolicy?action=delete&policyName='" + fileName + "'";
565 callPAP(null, "POST", uri.trim());
568 public String notifyOtherPAPSToUpdateConfigurations(String mode, String newName, String oldName) {
570 "onap/notifyOtherPAPs?action=" + mode + "&newPolicyName=" + newName + "&oldPolicyName=" + oldName + "";
571 return callPAP(null, "POST", uri.trim());