diff options
author | 2017-07-31 08:47:35 +0000 | |
---|---|---|
committer | 2017-07-31 15:51:10 -0400 | |
commit | 073cc188efe9abb4c010cf674e34e2cf46ef1c52 (patch) | |
tree | 155c23fbdf3a838ecb5f4183fc3bb6b09aac41eb /ONAP-PDP-REST/src/main/java/org | |
parent | 4ca818fdfb9b807562166800a086b413593d6894 (diff) |
[POLICY-73] replace openecomp for policy-engine
Change-Id: I54072f6bcd388c0e05562614ee89b4ae7ad67004
Signed-off-by: Guo Ruijing <ruijing.guo@intel.com>
Signed-off-by: Pamela Dragosh <pdragosh@research.att.com>
Diffstat (limited to 'ONAP-PDP-REST/src/main/java/org')
54 files changed, 11017 insertions, 0 deletions
diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/PapUrlResolver.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/PapUrlResolver.java new file mode 100644 index 000000000..cee07fd9f --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/PapUrlResolver.java @@ -0,0 +1,377 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.pdp.rest; + +import java.net.URI; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.NoSuchElementException; +import java.util.Properties; + +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; +import org.onap.policy.rest.XACMLRestProperties; + +import com.att.research.xacml.util.XACMLProperties; + +public class PapUrlResolver { + private static final Logger LOGGER = FlexLogger.getLogger(PapUrlResolver.class); + //how long to keep a pap failed before making it un-failed, in milli-seconds + private static final long FAIL_TIMEOUT = 18000000; + + //thread locks + public static final Object propertyLock = new Object(); + + //keeping this here for backward compatibility + public static String extractIdFromUrl(String url){ + return extractQuery(url); + } + public static String extractQuery(String url){ + try{ + return URI.create(url).getQuery(); + } catch(Exception e){ + LOGGER.error("Exception occured while extracting query. So, empty string is returned"+e); + return ""; + } + } + public static String modifyUrl(String idUrl, String serverUrl){ + URI one = URI.create(idUrl); + String host = one.getPath()+one.getQuery(); + URI two = URI.create(serverUrl); + two.resolve(host); + return two.toString(); + } + + //get an instance of a new PapUrlResolver, using XACMLProperties to get the url lists + public static PapUrlResolver getInstance(){ + return new PapUrlResolver(null,null,null,true); + } + + //get an instance of a new PapUrlResolver, using the provides strings for the url lists + public static PapUrlResolver getInstance(String urlList, String failedList, String succeededList){ + return new PapUrlResolver(urlList, failedList, succeededList,false); + } + + //keeps track of our current location in the list of urls, allows for iterating + private int pointer; + + //should the XACML property lists be updated after anything changes or should we wait for the update + //method to be called. + private boolean autoUpdateProperties; + + //this list keeps the sorted, priority of PAP URLs + private PapUrlNode[] sortedUrlNodes; + //this list keeps the original list of nodes so that they can be entered into the property list correctly + private PapUrlNode[] originalUrlNodes; + + //private constructor to make an instance of a PapUrlResolver, called by static method getInstance. + //If the list property strings are not defined, we get the values from XACMLProperties. + //The instance acts as an iterator, with hasNext and next methods, but does not implement Iterable, + //because it is used for a difference purpose. + private PapUrlResolver(String urlList, String failedList, String succeededList, boolean autoUpdateProperties){ + this.autoUpdateProperties = autoUpdateProperties; + String papUrlLists = urlList; + String papUrlFailedList = failedList; + String papUrlSuccessList = succeededList; + if(papUrlLists == null){ + papUrlLists = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_URLS); + if(papUrlLists == null){ + papUrlLists = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_URL); + } + papUrlFailedList = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_FAILED_URLS); + papUrlSuccessList = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_SUCCEEDED_URLS); + } + + String[] urls = papUrlLists.split(","); + if(urls.length == 0){ + //log error + } + String[] failed = emptyOrSplit(papUrlFailedList,urls.length); + String[] succeeded = emptyOrSplit(papUrlSuccessList,urls.length); + + sortedUrlNodes = new PapUrlNode[urls.length]; + for(int i=0;i<urls.length;i++){ + + String userId = null; + String pass = null; + userId = XACMLProperties.getProperty(urls[i]+"."+XACMLRestProperties.PROP_PAP_USERID); + pass = XACMLProperties.getProperty(urls[i]+"."+XACMLRestProperties.PROP_PAP_PASS); + if(userId == null || pass == null){ + userId = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_USERID); + pass = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_PASS); + } + if(userId == null || pass == null){ + userId = ""; + pass = ""; + } + PapUrlNode newNode = new PapUrlNode(urls[i],userId,pass); + newNode.setFailedTime(failed[i]); + newNode.setSucceededTime(succeeded[i]); + if(sortedUrlNodes[i] == null){ + sortedUrlNodes[i] = newNode; + } + } + originalUrlNodes = sortedUrlNodes.clone(); + sort(sortedUrlNodes); + pointer = 0; + } + + + //either split a list by commas, or fill an array to the expected length, if the property list is not long enough + private String[] emptyOrSplit(String list,int expectedLength){ + String[] ret; + if(list == null){ + ret = new String[expectedLength]; + for(int i=0;i<expectedLength;i++){ + ret[i] = "-1"; + } + } else { + ret = list.split(","); + if(ret.length != expectedLength){ + ret = emptyOrSplit(null,expectedLength); + } + } + return ret; + } + + private void sort(PapUrlNode[] array){ + + //O(n^2) double-loop most likely the best in this case, since number of records will be VERY small + for(int i=0;i<array.length;i++){ + for(int j=i;j<array.length;j++){ + if(array[j].compareTo(array[i])<0){ + PapUrlNode temp = array[i]; + array[i] = array[j]; + array[j] = temp; + } + } + } + } + + //returns whether this PapUrlResolver object has more PAP urls that can be tried + public boolean hasMoreUrls(){ + return pointer < sortedUrlNodes.length; + } + + //sets the current PAP url as being failed + //this will set the failed time to now and remove any succeeded time + public void failed(){ + LOGGER.error("PAP Server FAILED: "+sortedUrlNodes[pointer].getUrl()); + + sortedUrlNodes[pointer].setFailedTime(new Date()); + sortedUrlNodes[pointer].setSucceededTime(null); + propertiesUpdated(); + } + + //sets the current PAP url as being working + //this will set the succeeded time to now and remove any failed time + //Also, this will cause hasMoreUrls to return false, since a working one has been found + + public void succeeded(){ + registered(); + pointer = sortedUrlNodes.length; + } + public void registered(){ + sortedUrlNodes[pointer].setFailedTime(null); + sortedUrlNodes[pointer].setSucceededTime(new Date()); + LOGGER.info("PAP server SUCCEEDED "+sortedUrlNodes[pointer].getUrl()); + propertiesUpdated(); + } + + //returns a properties object with the properties that pertain to PAP urls + public Properties getProperties(){ + String failedPropertyString = ""; + String succeededPropertyString = ""; + String urlPropertyString = ""; + for(int i=0;i<originalUrlNodes.length;i++){ + failedPropertyString = failedPropertyString.concat(",").concat(originalUrlNodes[i].getFailedTime()); + succeededPropertyString = succeededPropertyString.concat(",").concat(originalUrlNodes[i].getSucceededTime()); + urlPropertyString = urlPropertyString.concat(",").concat(originalUrlNodes[i].getUrl()); + } + Properties prop = new Properties(); + failedPropertyString = failedPropertyString.substring(1); + succeededPropertyString = succeededPropertyString.substring(1); + urlPropertyString = urlPropertyString.substring(1); + prop.setProperty(XACMLRestProperties.PROP_PAP_FAILED_URLS,failedPropertyString); + prop.setProperty(XACMLRestProperties.PROP_PAP_URLS,urlPropertyString); + prop.setProperty(XACMLRestProperties.PROP_PAP_SUCCEEDED_URLS,succeededPropertyString); + return prop; + } + + //saves the updates urls to the correct properties + private void propertiesUpdated(){ + if(!autoUpdateProperties){ + return; + } + Properties prop = getProperties(); + + LOGGER.debug("Failed PAP Url List: "+prop.getProperty(XACMLRestProperties.PROP_PAP_FAILED_URLS)); + LOGGER.debug("Succeeded PAP Url List: "+prop.getProperty(XACMLRestProperties.PROP_PAP_SUCCEEDED_URLS)); + XACMLProperties.setProperty(XACMLRestProperties.PROP_PAP_FAILED_URLS,prop.getProperty(XACMLRestProperties.PROP_PAP_FAILED_URLS)); + XACMLProperties.setProperty(XACMLRestProperties.PROP_PAP_SUCCEEDED_URLS,prop.getProperty(XACMLRestProperties.PROP_PAP_SUCCEEDED_URLS)); + } + + //iterates to the next available PAP url, according to the priority order + public void getNext(){ + pointer++; + } + + //returns the url of the current PAP server that we are iterating over + //will append the provided policy id to the url + public String getUrl(String query){ + if(sortedUrlNodes[pointer]== null){ + throw new NoSuchElementException(); + } else { + return sortedUrlNodes[pointer].getUrl().concat("?").concat(query); + } + } + + //returns the url of the current PAP server that we are iterating over + //Just returns the url, with no id appended to it + public String getUrl(){ + if(sortedUrlNodes[pointer]== null){ + throw new NoSuchElementException(); + } else { + + return sortedUrlNodes[pointer].getUrl(); + } + } + public String getUserId(){ + if(sortedUrlNodes[pointer]== null){ + throw new NoSuchElementException(); + } else { + + return sortedUrlNodes[pointer].getUserId(); + } + } + public String getPass(){ + if(sortedUrlNodes[pointer]== null){ + throw new NoSuchElementException(); + } else { + + return sortedUrlNodes[pointer].getPass(); + } + } + + + //This is the class to hold the details of a single PAP URL + //including: the url itself, the last time it failed, and the last time it succeeded + //It also includes the custom comparer which can compare based on failed and succeeded times, and takes into account + //the timeout on failures. + private class PapUrlNode implements Comparable<PapUrlNode> { + private String papUrl; + private Date failedTime; + private Date succeededTime; + private String userId; + private String pass; + + public PapUrlNode(String url,String userId,String pass){ + this.papUrl = url; + failedTime = null; + this.succeededTime = null; + this.userId = userId; + this.pass = pass; + + } + public String getUserId(){ + return this.userId; + } + public String getPass(){ + return this.pass; + } + + public void setFailedTime(Object time){ + Date failedTimeAsDate = setHandler(time); + if(failedTimeAsDate == null){ + this.failedTime = null; + } else { + long timeDifference = new Date().getTime() - failedTimeAsDate.getTime(); + if(timeDifference < FAIL_TIMEOUT){ + this.failedTime = failedTimeAsDate; + } else { + this.failedTime = null; + } + } + } + + //set the time that this url succeeded at + public void setSucceededTime(Object time){ + this.succeededTime = setHandler(time); + } + + //parses string into a date or a null date, if the url never failed/succeeded (since -1 will be in the property) + private Date setHandler(Object time){ + if(time instanceof String){ + if("-1".equals((String)time)){ + return null; + } + try { + DateFormat df = new SimpleDateFormat(); + return df.parse((String)time); + } catch (ParseException e) { + return null; + } + } + if(time instanceof Date){ + return (Date)time; + } + return null; + } + + + public String getFailedTime(){ + return formatTime(this.failedTime); + } + + public String getSucceededTime(){ + return formatTime(this.succeededTime); + } + + //formats a Date into a string or a -1 if there is not date (-1 is used in properties for no date) + private String formatTime(Date d){ + if(d == null){ + return "-1"; + } + DateFormat df = new SimpleDateFormat(); + return df.format(d); + } + + public String getUrl(){ + return papUrl; + } + + @Override + public int compareTo(PapUrlNode other){ + if(this.failedTime == null && other.failedTime != null){ + return -1; + } + if(this.failedTime != null && other.failedTime == null){ + return 1; + } + if(this.failedTime != null){ + return this.failedTime.compareTo(other.failedTime); + } + return 0; + } + } +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/XACMLPdpLoader.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/XACMLPdpLoader.java new file mode 100644 index 000000000..7526af692 --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/XACMLPdpLoader.java @@ -0,0 +1,645 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.pdp.rest; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.net.URLConnection; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Base64; +import java.util.ConcurrentModificationException; +import java.util.HashMap; +import java.util.Properties; +import java.util.Set; + +import org.apache.commons.io.IOUtils; +import org.onap.policy.pdp.rest.notifications.NotificationController; +import org.onap.policy.rest.XACMLRest; +import org.onap.policy.rest.XACMLRestProperties; +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; + +import org.onap.policy.xacml.api.XACMLErrorConstants; +import com.att.research.xacml.api.pap.PAPException; +import com.att.research.xacml.api.pap.PDPStatus; +import com.att.research.xacml.api.pap.PDPStatus.Status; +import com.att.research.xacml.api.pdp.PDPEngine; +import com.att.research.xacml.api.pdp.PDPEngineFactory; +import com.att.research.xacml.api.pip.PIPEngine; +import com.att.research.xacml.api.pip.PIPException; +import com.att.research.xacml.api.pip.PIPFinder; +import com.att.research.xacml.api.pip.PIPFinderFactory; +import org.onap.policy.xacml.std.pap.StdPDPPIPConfig; +import org.onap.policy.xacml.std.pap.StdPDPPolicy; +import org.onap.policy.xacml.std.pap.StdPDPStatus; +import com.att.research.xacml.util.FactoryException; +import com.att.research.xacml.util.XACMLProperties; +import com.att.research.xacmlatt.pdp.policy.PolicyDef; +import com.att.research.xacmlatt.pdp.policy.dom.DOMPolicyDef; +import com.att.research.xacmlatt.pdp.std.StdPolicyFinderFactory; +import com.google.common.base.Splitter; + +/** + * Does the work for loading policy and PIP configurations sent from the PAP + * servlet. + * + * + * + */ +public class XACMLPdpLoader { + private static final Logger LOGGER = FlexLogger.getLogger(XACMLPdpLoader.class); + private static NotificationController notificationController = new NotificationController(); + private static final Long notifyDelay = (long) XACMLPdpServlet.getNotificationDelay(); + + + public static synchronized PDPEngine loadEngine(StdPDPStatus status, + Properties policyProperties, Properties pipProperties) { + LOGGER.info("loadEngine: " + policyProperties + " " + pipProperties); + // + // First load our policies + // + try { + // + // Were we given some properties? + // + if (policyProperties == null) { + // + // On init we have no incoming configuration, so just + // Load our current saved configuration + // + policyProperties = new Properties(); + try (InputStream is = Files.newInputStream(getPDPPolicyCache())) { + policyProperties.load(is); + } + } + + // + // Get our policy cache up-to-date + // + // Side effects of this include: + // - downloading of policies from remote locations, and + // - creating new "<PolicyId>.file" properties for files existing + // local + // + XACMLPdpLoader.cachePolicies(policyProperties); + // + // Validate the policies + // + XACMLPdpLoader.validatePolicies(policyProperties, status); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Status: " + status); + } + } catch (ConcurrentModificationException e) { + LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + e.getMessage() + e); + } catch (Exception e) { + String error = "Failed to load Policy Cache properties file: " + + e.getMessage(); + LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + error, e); + status.addLoadError(error); + status.setStatus(PDPStatus.Status.LOAD_ERRORS); + } + // + // Load our PIP configuration + // + try { + // + // Were we given some properties to use? + // + if (pipProperties == null) { + // + // Load our current saved configuration + // + pipProperties = new Properties(); + try (InputStream is = Files.newInputStream(getPIPConfig())) { + pipProperties.load(is); + } + } + // + // Validate our PIP configurations + // + XACMLPdpLoader.validatePipConfiguration(pipProperties, status); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Status: " + status); + } + } catch (Exception e) { + String error = "Failed to load/validate Pip Config properties file: " + + e.getMessage(); + LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + error, e); + status.addLoadError(XACMLErrorConstants.ERROR_PROCESS_FLOW + error); + status.setStatus(PDPStatus.Status.LOAD_ERRORS); + } + // + // Were they validated? + // + if (status.getStatus() == Status.LOAD_ERRORS) { + LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW +"there were load errors"); + return null; + } + // + // Reset our official properties the PDP factory + // uses to configure the PDP engine. + // + XACMLRest.loadXacmlProperties(policyProperties, pipProperties); + // + // Dump ALL our properties that we are trying to load + // + try { + LOGGER.info(XACMLProperties.getProperties().toString()); + } catch (IOException e) { + LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Failed to get XACML Properties", e); + } + // + // Now load the PDP engine + // + PDPEngineFactory factory = null; + PDPEngine engine = null; + try { + factory = PDPEngineFactory.newInstance(); + engine = factory.newEngine(); + LOGGER.info("Loaded new PDP engine."); + status.setStatus(Status.UP_TO_DATE); + } catch (FactoryException e) { + String error = "Failed to create new PDP Engine"; + LOGGER.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR +error, e); + status.addLoadError(error); + } + // Notification will be Sent Here. + sendNotification(); + return engine; + } + + private static HashMap<String, PolicyDef> policyContainer = null; + + private static void sendNotification(){ + Thread notify = new Thread(){ + public void run(){ + try{ + Thread.sleep(notifyDelay); + NotificationController.sendNotification(); + }catch(Exception e){ + LOGGER.error(XACMLErrorConstants.ERROR_UNKNOWN + e); + } + } + }; + notify.start(); + } + + public static synchronized void validatePolicies(Properties properties, + StdPDPStatus status) throws PAPException { + Set<String> rootPolicies = XACMLProperties.getRootPolicyIDs(properties); + Set<String> refPolicies = XACMLProperties + .getReferencedPolicyIDs(properties); + policyContainer = new HashMap<String, PolicyDef>(); + + for (String id : rootPolicies) { + loadPolicy(properties, status, id, true); + } + // remember which policies were root policies + status.addAllLoadedRootPolicies(status.getLoadedPolicies()); + + for (String id : refPolicies) { + loadPolicy(properties, status, id, false); + } + LOGGER.info("Loaded " + status.getLoadedPolicies().size() + + " policies, failed to load " + + status.getFailedPolicies().size() + " policies, " + + status.getLoadedRootPolicies().size() + " root policies"); + notificationController.check(status, policyContainer); + if (status.getLoadedRootPolicies().size() == 0) { + LOGGER.warn(XACMLErrorConstants.ERROR_PROCESS_FLOW +"NO ROOT POLICIES LOADED!!! Cannot serve PEP Requests."); + status.addLoadWarning("NO ROOT POLICIES LOADED!!! Cannot serve PEP Requests."); + } + policyContainer.clear(); + } + + + public static synchronized void loadPolicy(Properties properties, + StdPDPStatus status, String id, boolean isRoot) throws PAPException { + PolicyDef policy = null; + String location = null; + URI locationURI = null; + boolean isFile = false; + boolean rougeFile = false; + try { + location = properties.getProperty(id + ".file"); + if(location != null){ + isFile = true; + locationURI = Paths.get(location).toUri(); + try (InputStream is = Files.newInputStream(Paths.get(location))) { + policy = DOMPolicyDef.load(is); + } catch (Exception e){ + // This Happens if a any issue with the error policyFile. Lets remove it. + try { + LOGGER.error("Corrupted policy file, deleting: " + location + e); + Files.delete(Paths.get(location)); + properties.remove(id + ".file"); + rougeFile = true; + } catch (IOException e1) { + LOGGER.error(e1); + } + } + } + if(location==null || rougeFile){ + if(rougeFile){ + rougeFile = false; + } + location = properties.getProperty(id + ".url"); + if (location != null) { + // + // Construct the URL + // + int errorCount=0; + boolean error= false; + do{ + error=false; + PapUrlResolver papUrls = PapUrlResolver.getInstance(); + while(papUrls.hasMoreUrls()){ + String papID = papUrls.getUserId(); + String papPass = papUrls.getPass(); + Base64.Encoder encoder = Base64.getEncoder(); + String encoding = encoder.encodeToString((papID+":"+papPass).getBytes(StandardCharsets.UTF_8)); + locationURI = URI.create(papUrls.getUrl(PapUrlResolver.extractIdFromUrl(location))); + URL url = locationURI.toURL(); + URLConnection urlConnection = null; + try{ + urlConnection = url.openConnection(); + } catch (IOException e){ + LOGGER.error("Exception Occured while opening connection" +e); + papUrls.failed(); + papUrls.getNext(); + break; + } + urlConnection.setRequestProperty(XACMLRestProperties.PROP_PDP_HTTP_HEADER_ID, + XACMLProperties.getProperty(XACMLRestProperties.PROP_PDP_ID)); + urlConnection.setRequestProperty("Authorization", "Basic " + encoding); + // + // Now construct the output file name + // + Path outFile = Paths.get(getPDPConfig().toAbsolutePath() + .toString(), id); + // + // Copy it to disk + // + try (FileOutputStream fos = new FileOutputStream( + outFile.toFile())) { + IOUtils.copy(urlConnection.getInputStream(), fos); + } catch(IOException e){ + LOGGER.error("Exception Occured while Copying input stream" +e); + papUrls.failed(); + papUrls.getNext(); + break; + } + // + // Now try to load + // + isFile = true; + try (InputStream fis = Files.newInputStream(outFile)) { + policy = DOMPolicyDef.load(fis); + }catch(Exception e){ + try { + LOGGER.error("Corrupted policy file, deleting: " + location +e); + Files.delete(outFile); + error = true; + errorCount++; + break; + } catch (IOException e1) { + LOGGER.error(e1); + } + } + // + // Save it + // + properties.setProperty(id + ".file", outFile + .toAbsolutePath().toString()); + error = false; + break; + } + }while(error && errorCount>2); + } + } + if (policy != null) { + status.addLoadedPolicy(new StdPDPPolicy(id, isRoot, + locationURI, properties)); + LOGGER.info("Loaded policy: " + policy.getIdentifier() + + " version: " + policy.getVersion().stringValue()); + // Sending the policy objects to the Notification Controller. + policyContainer.put(id, policy); + } else { + String error = "Failed to load policy " + location; + LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + error); + status.setStatus(PDPStatus.Status.LOAD_ERRORS); + status.addLoadError(error); + status.addFailedPolicy(new StdPDPPolicy(id, isRoot)); + } + } catch (Exception e) { + LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW +"Failed to load policy '" + id + "' from location '" + + location + "'", e); + status.setStatus(PDPStatus.Status.LOAD_ERRORS); + status.addFailedPolicy(new StdPDPPolicy(id, isRoot)); + // + // Is it a file? + // + if (isFile) { + // + // Let's remove it + // + try { + LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Corrupted policy file, deleting: " + location); + Files.delete(Paths.get(location)); + + } catch (IOException e1) { + LOGGER.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + e1); + } + } + } + } + + public static synchronized void validatePipConfiguration( + Properties properties, StdPDPStatus status) throws PAPException { + try { + PIPFinderFactory factory = PIPFinderFactory.newInstance(properties); + if (factory == null) { + throw new FactoryException( + "Could not create PIP Finder Factory: " + + properties + .getProperty(XACMLProperties.PROP_PIPFINDERFACTORY)); + } + PIPFinder finder = factory.getFinder(properties); + // + // Check for this, although it should always return something + // + if (finder == null) { + LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "pip finder factory returned a null engine."); + throw new PIPException("Could not create PIP Finder"); + } else { + LOGGER.info("Loaded PIP finder"); + } + for (PIPEngine engine : finder.getPIPEngines()) { + LOGGER.info("Configured PIP Engine: " + engine.getName()); + StdPDPPIPConfig config = new StdPDPPIPConfig(); + config.setName(engine.getName()); + status.addLoadedPipConfig(config); + } + } catch (FactoryException | PIPException e) { + LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "validate PIP configuration failed: " + + e.getLocalizedMessage()); + status.addLoadError(e.getLocalizedMessage()); + status.setStatus(Status.LOAD_ERRORS); + throw new PAPException(e); + } + } + + /** + * Iterates the policies defined in the props object to ensure they are + * loaded locally. Policies are searched for in the following order: - see + * if the current properties has a "<PolicyID>.file" entry and that + * file exists in the local directory - if not, see if the file exists in + * the local directory; if so create a ".file" property for it. - if not, + * get the "<PolicyID>.url" property and try to GET the policy from + * that location (and set the ".file" property) + * + * If the ".file" property is created, then true is returned to tell the + * caller that the props object changed. + * + * @param props + * @return true/false if anything was changed in the props object + * @throws PAPException + */ + public static synchronized boolean cachePolicies(Properties props) + throws PAPException { + boolean changed = false; + String[] lists = new String[2]; + lists[0] = props.getProperty(XACMLProperties.PROP_ROOTPOLICIES); + lists[1] = props.getProperty(XACMLProperties.PROP_REFERENCEDPOLICIES); + for (String list : lists) { + // + // Check for a null or empty parameter + // + if (list == null || list.length() == 0) { + continue; + } + Iterable<String> policies = Splitter.on(',').trimResults() + .omitEmptyStrings().split(list); + for (String policy : policies) { + boolean policyExists = false; + + // First look for ".file" property and verify the file exists + String propLocation = props.getProperty(policy + + StdPolicyFinderFactory.PROP_FILE); + if (propLocation != null) { + // + // Does it exist? + // + policyExists = Files.exists(Paths.get(propLocation)); + if (policyExists == false) { + LOGGER.warn(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Policy file " + policy + " expected at " + + propLocation + " does NOT exist."); + } + } + + // If ".file" property does not exist, try looking for the local + // file anyway + // (it might exist without having a ".file" property set for it) + if (policyExists == false) { + // + // Now construct the output file name + // + Path outFile = Paths.get(getPDPConfig().toAbsolutePath() + .toString(), policy); + // + // Double check to see if we pulled it at some point + // + policyExists = Files.exists(outFile); + if (policyExists) { + // + // Set the property so the PDP engine doesn't have + // to pull it from the URL but rather the FILE. + // + LOGGER.info("Policy does exist: " + + outFile.toAbsolutePath().toString()); + props.setProperty(policy + + StdPolicyFinderFactory.PROP_FILE, outFile + .toAbsolutePath().toString()); + // + // Indicate that there were changes made to the + // properties + // + changed = true; + } else { + + // File does not exist locally, so we need to get it + // from the location given in the ".url" property (which + // MUST exist) + + // + // There better be a URL to retrieve it + // + propLocation = props.getProperty(policy + + StdPolicyFinderFactory.PROP_URL); + if (propLocation != null) { + // + // Get it + // + PapUrlResolver papUrls = PapUrlResolver.getInstance(); + while(papUrls.hasMoreUrls()){ + String papID = papUrls.getUserId(); + String papPass = papUrls.getPass(); + Base64.Encoder encoder = Base64.getEncoder(); + String encoding = encoder.encodeToString((papID+":"+papPass).getBytes(StandardCharsets.UTF_8)); + URL url = null; + try { + // + // Create the URL + // + url = new URL(papUrls.getUrl(PapUrlResolver.extractIdFromUrl(propLocation))); + LOGGER.info("Pulling " + url.toString()); + // + // Open the connection + // + URLConnection urlConnection = url.openConnection(); + urlConnection.setRequestProperty(XACMLRestProperties.PROP_PDP_HTTP_HEADER_ID, + XACMLProperties.getProperty(XACMLRestProperties.PROP_PDP_ID)); + urlConnection.setRequestProperty("Authorization", "Basic " + encoding); + // + // Copy it to disk + // + try (InputStream is = urlConnection + .getInputStream(); + OutputStream os = new FileOutputStream( + outFile.toFile())) { + IOUtils.copy(is, os); + } + // + // Now save it in the properties as a .file + // + LOGGER.info("Pulled policy: " + + outFile.toAbsolutePath().toString()); + props.setProperty(policy + + StdPolicyFinderFactory.PROP_FILE, + outFile.toAbsolutePath().toString()); + papUrls.succeeded(); + // + // Indicate that there were changes made to the + // properties + // + changed = true; + } catch (Exception e) { + papUrls.failed(); + if (e instanceof MalformedURLException) { + LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Policy '" + + policy + + "' had bad URL in new configuration, URL='" + + propLocation + "'"); + + } else { + LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Error while retrieving policy " + + policy + + " from URL " + + url + ", e=" + e); + } + } + papUrls.getNext(); + } + } else { + LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Policy " + policy + + " does NOT exist and does NOT have a URL"); + } + } + } + } + } + return changed; + } + + public static synchronized Path getPDPPolicyCache() throws PAPException { + Path config = getPDPConfig(); + Path policyProperties = Paths.get(config.toAbsolutePath().toString(), + "xacml.policy.properties"); + if (Files.notExists(policyProperties)) { + LOGGER.warn(XACMLErrorConstants.ERROR_PROCESS_FLOW + policyProperties.toAbsolutePath().toString() + + " does NOT exist."); + // + // Try to create the file + // + try { + Files.createFile(policyProperties); + } catch (IOException e) { + LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Failed to create policy properties file: " + + policyProperties.toAbsolutePath().toString() +e); + throw new PAPException( + "Failed to create policy properties file: " + + policyProperties.toAbsolutePath().toString()); + } + } + return policyProperties; + } + + public static synchronized Path getPIPConfig() throws PAPException { + Path config = getPDPConfig(); + Path pipConfigProperties = Paths.get( + config.toAbsolutePath().toString(), "xacml.pip.properties"); + if (Files.notExists(pipConfigProperties)) { + LOGGER.warn(XACMLErrorConstants.ERROR_PROCESS_FLOW + pipConfigProperties.toAbsolutePath().toString() + + " does NOT exist."); + // + // Try to create the file + // + try { + Files.createFile(pipConfigProperties); + } catch (IOException e) { + LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Failed to create pip properties file: " + + pipConfigProperties.toAbsolutePath().toString() +e); + throw new PAPException("Failed to create pip properties file: " + + pipConfigProperties.toAbsolutePath().toString()); + } + } + return pipConfigProperties; + } + + public static synchronized Path getPDPConfig() throws PAPException { + Path config = Paths.get(XACMLProperties + .getProperty(XACMLRestProperties.PROP_PDP_CONFIG)); + if (Files.notExists(config)) { + LOGGER.warn(XACMLErrorConstants.ERROR_PROCESS_FLOW + config.toAbsolutePath().toString() + " does NOT exist."); + // + // Try to create the directory + // + try { + Files.createDirectories(config); + } catch (IOException e) { + LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Failed to create config directory: " + + config.toAbsolutePath().toString(), e); + throw new PAPException("Failed to create config directory: " + + config.toAbsolutePath().toString()); + } + } + return config; + } + +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/XACMLPdpRegisterThread.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/XACMLPdpRegisterThread.java new file mode 100644 index 000000000..14b312f6d --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/XACMLPdpRegisterThread.java @@ -0,0 +1,285 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + + +package org.onap.policy.pdp.rest; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.util.Base64; +import java.util.Properties; +import java.util.UUID; + +import org.apache.commons.io.IOUtils; +import org.onap.policy.pdp.rest.XACMLPdpServlet.PutRequest; +import org.onap.policy.rest.XACMLRestProperties; + +import org.onap.policy.xacml.api.XACMLErrorConstants; +import com.att.research.xacml.util.XACMLProperties; + +import org.onap.policy.common.logging.ONAPLoggingContext; +import org.onap.policy.common.logging.eelf.PolicyLogger; +import org.onap.policy.common.logging.flexlogger.*; + +public class XACMLPdpRegisterThread implements Runnable { + private static final Logger LOGGER = FlexLogger.getLogger(XACMLPdpRegisterThread.class); + private static final Logger auditLogger = FlexLogger.getLogger("auditLogger"); + private ONAPLoggingContext baseLoggingContext = null; + + + + public volatile boolean isRunning = false; + + public XACMLPdpRegisterThread(ONAPLoggingContext baseLoggingContext) { + this.baseLoggingContext = baseLoggingContext; + } + + public synchronized boolean isRunning() { + return this.isRunning; + } + + public synchronized void terminate() { + this.isRunning = false; + } + + /** + * + * This is our thread that runs on startup to tell the PAP server we are up-and-running. + * + */ + @Override + public void run() { + synchronized(this) { + this.isRunning = true; + } + // get a new logging context for the thread + ONAPLoggingContext loggingContext = new ONAPLoggingContext(baseLoggingContext); + loggingContext.setServiceName("PDP:PAP.register"); + //are we registered with at least one + boolean registered = false; + boolean interrupted = false; + /* + int seconds; + try { + seconds = Integer.parseInt(XACMLProperties.getProperty(XACMLRestProperties.PROP_PDP_REGISTER_SLEEP)); + } catch (NumberFormatException e) { + LOGGER.error( XACMLErrorConstants.ERROR_SYSTEM_ERROR +"REGISTER_SLEEP: ", e); + seconds = 5; + } + if (seconds < 5) { + seconds = 5; + } + int retries; + try { + retries = Integer.parseInt(XACMLProperties.getProperty(XACMLRestProperties.PROP_PDP_REGISTER_RETRIES)); + } catch (NumberFormatException e) { + LOGGER.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR +" REGISTER_SLEEP: ", e); + retries = -1; + } + */ + PapUrlResolver papUrls = PapUrlResolver.getInstance(); + //while (! registered && ! interrupted && this.isRunning()) { + String tempRootPoliciesProperty = XACMLProperties.getProperty(XACMLProperties.PROP_ROOTPOLICIES); + String tempReferencedPoliciesProperty = XACMLProperties.getProperty(XACMLProperties.PROP_REFERENCEDPOLICIES); + Properties tempPipConfigProperties = new Properties(); + try(InputStream pipFile = Files.newInputStream(XACMLPdpLoader.getPIPConfig())){ + tempPipConfigProperties.load(pipFile); + } catch(Exception e){ + LOGGER.error("Failed to open PIP property file", e); + } + while(papUrls.hasMoreUrls()){ + String papID = papUrls.getUserId(); + String papPass = papUrls.getPass(); + Base64.Encoder encoder = Base64.getEncoder(); + String encoding = encoder.encodeToString((papID+":"+papPass).getBytes(StandardCharsets.UTF_8)); + HttpURLConnection connection = null; + try { + // get a new transaction (request) ID and update the logging context. + // each time through the outer loop is considered a new transaction. + // each time through the inner loop (which handles redirects) is a + // continuation of the same transaction. + UUID requestID = UUID.randomUUID(); + loggingContext.setRequestID(requestID.toString()); + //PolicyLogger.info("Request Id generated in XACMLPdpRegisterThread under XACML-PDP-REST"); + loggingContext.transactionStarted(); + // + // Get the list of PAP Servlet URLs from the property file + // + //String papUrlList = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_URL); + //String[] papUrls = papUrlList.split(","); + //PapUrlResolver.setPapUrls(papUrls); + URL url = new URL(papUrls.getUrl()); + LOGGER.info("Registering with " + url.toString()); + //PolicyLogger.info("new transaction (request) ID and update to logging context in XACMLPdpRegisterThread"); + boolean finished = false; + while (! finished) { + // + // Open up the connection + // + connection = (HttpURLConnection)url.openConnection(); + // + // Setup our method and headers + // + connection.setRequestMethod("POST"); + connection.setRequestProperty("Authorization", "Basic " + encoding); + connection.setRequestProperty("Accept", "text/x-java-properties"); + connection.setRequestProperty("Content-Type", "text/x-java-properties"); + connection.setRequestProperty(XACMLRestProperties.PROP_PDP_HTTP_HEADER_ID, XACMLProperties.getProperty(XACMLRestProperties.PROP_PDP_ID)); + connection.setRequestProperty(XACMLRestProperties.PROP_PDP_HTTP_HEADER_JMX_PORT, XACMLProperties.getProperty(XACMLRestProperties.PROP_PDP_JMX_PORT)); + connection.setRequestProperty("X-ECOMP-RequestID", requestID.toString()); + connection.setUseCaches(false); + // + // Adding this in. It seems the HttpUrlConnection class does NOT + // properly forward our headers for POST re-direction. It does so + // for a GET re-direction. + // + // So we need to handle this ourselves. + // + connection.setInstanceFollowRedirects(false); + connection.setDoOutput(true); + connection.setDoInput(true); + try { + // + // Send our current policy configuration + // + String lists = XACMLProperties.PROP_ROOTPOLICIES + "=" + tempRootPoliciesProperty; + lists = lists + "\n" + XACMLProperties.PROP_REFERENCEDPOLICIES + "=" + tempReferencedPoliciesProperty + "\n"; + try (InputStream listsInputStream = new ByteArrayInputStream(lists.getBytes()); + OutputStream os = connection.getOutputStream()) { + IOUtils.copy(listsInputStream, os); + + // + // Send our current PIP configuration + // + //IOUtils.copy(pipInputStream, os); + tempPipConfigProperties.store(os, ""); + } + } catch (Exception e) { + LOGGER.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR +"Failed to send property file", e); + } + // + // Do the connect + // + connection.connect(); + if (connection.getResponseCode() == 204) { + LOGGER.info("Success. We are configured correctly."); + loggingContext.transactionEnded(); + PolicyLogger.audit("Success. We are configured correctly."); + papUrls.registered(); + finished = true; + registered = true; + } else if (connection.getResponseCode() == 200) { + LOGGER.info("Success. We have a new configuration."); + loggingContext.transactionEnded(); + PolicyLogger.audit("Success. We have a new configuration."); + papUrls.registered(); + Properties properties = new Properties(); + properties.load(connection.getInputStream()); + LOGGER.info("New properties: " + properties.toString()); + // + // Queue it + // + // The incoming properties does NOT include urls + Properties returnedPolicyProperties = XACMLProperties.getPolicyProperties(properties, false); + tempRootPoliciesProperty = new String(returnedPolicyProperties.getProperty(XACMLProperties.PROP_ROOTPOLICIES)); + tempReferencedPoliciesProperty = new String(returnedPolicyProperties.getProperty(XACMLProperties.PROP_REFERENCEDPOLICIES)); + Properties returnedPipProperties = XACMLProperties.getPipProperties(properties); + Properties threadSafeReturnedPipProperties = new Properties(); + ByteArrayOutputStream threadSafeReturnedPipPropertiesOs = new ByteArrayOutputStream(); + returnedPipProperties.store(threadSafeReturnedPipPropertiesOs, ""); + InputStream threadSafeReturnedPipPropertiesIs = new ByteArrayInputStream(threadSafeReturnedPipPropertiesOs.toByteArray()); + threadSafeReturnedPipProperties.load(threadSafeReturnedPipPropertiesIs); + tempPipConfigProperties = threadSafeReturnedPipProperties; + + PutRequest req = new PutRequest(returnedPolicyProperties,returnedPipProperties); + XACMLPdpServlet.queue.offer(req); + // + // We are now registered + // + finished = true; + registered=true; + } else if (connection.getResponseCode() >= 300 && connection.getResponseCode() <= 399) { + // + // Re-direction + // + String newLocation = connection.getHeaderField("Location"); + if (newLocation == null || newLocation.isEmpty()) { + LOGGER.warn(XACMLErrorConstants.ERROR_SYSTEM_ERROR +"Did not receive a valid re-direction location"); + loggingContext.transactionEnded(); + auditLogger.warn(XACMLErrorConstants.ERROR_SYSTEM_ERROR +"Did not receive a valid re-direction location"); + PolicyLogger.audit("Transaction Failed - See Error.log"); + finished = true; + } else { + LOGGER.info("New Location: " + newLocation); + url = new URL(newLocation); + } + } else { + LOGGER.warn(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Failed: " + connection.getResponseCode() + " message: " + connection.getResponseMessage()); + loggingContext.transactionEnded(); + auditLogger.warn(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Failed: " + connection.getResponseCode() + " message: " + connection.getResponseMessage()); + PolicyLogger.audit("Transaction Failed - See Error.log"); + finished = true; + papUrls.failed(); + } + } + } catch (Exception e) { + LOGGER.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + e); + PolicyLogger.audit("Transaction Failed - See Error.log"); + loggingContext.transactionEnded(); + papUrls.failed(); + } finally { + // cleanup the connection + if (connection != null) { + try { + // For some reason trying to get the inputStream from the connection + // throws an exception rather than returning null when the InputStream does not exist. + InputStream is = null; + try { + is = connection.getInputStream(); + } catch (Exception e1) { + LOGGER.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Failed to get Input Stream: " + e1); + } + if (is != null) { + is.close(); + } + + } catch (IOException ex) { + LOGGER.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Failed to close connection: " + ex, ex); + } + connection.disconnect(); + } + } + + papUrls.getNext(); + } + synchronized(this) { + this.isRunning = false; + } + LOGGER.info("Thread exiting...(registered=" + registered + ", interrupted=" + interrupted + ", isRunning=" + this.isRunning() + ", retries=" + "0" + ")"); + } + +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/XACMLPdpServlet.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/XACMLPdpServlet.java new file mode 100644 index 000000000..1e1b94d9b --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/XACMLPdpServlet.java @@ -0,0 +1,1266 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.pdp.rest; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.lang.reflect.Constructor; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.nio.file.Files; +import java.util.Properties; +import java.util.UUID; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + +import javax.servlet.Servlet; +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.annotation.WebInitParam; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.http.entity.ContentType; +import org.onap.policy.api.PolicyParameters; +import org.onap.policy.common.im.AdministrativeStateException; +import org.onap.policy.common.im.ForwardProgressException; +import org.onap.policy.common.im.IntegrityMonitor; +import org.onap.policy.common.im.IntegrityMonitorProperties; +import org.onap.policy.common.im.StandbyStatusException; +import org.onap.policy.common.logging.ONAPLoggingContext; +import org.onap.policy.common.logging.ONAPLoggingUtils; +import org.onap.policy.common.logging.eelf.MessageCodes; +import org.onap.policy.common.logging.eelf.PolicyLogger; +import org.onap.policy.pdp.rest.jmx.PdpRestMonitor; +import org.onap.policy.rest.XACMLRest; +import org.onap.policy.rest.XACMLRestProperties; +import org.onap.policy.xacml.api.XACMLErrorConstants; +import org.onap.policy.xacml.pdp.std.functions.PolicyList; +import org.onap.policy.xacml.std.pap.StdPDPStatus; + +import com.att.research.xacml.api.Request; +import com.att.research.xacml.api.Response; +import com.att.research.xacml.api.pap.PDPStatus.Status; +import com.att.research.xacml.api.pdp.PDPEngine; +import com.att.research.xacml.api.pdp.PDPException; +import com.att.research.xacml.std.dom.DOMRequest; +import com.att.research.xacml.std.dom.DOMResponse; +import com.att.research.xacml.std.json.JSONRequest; +import com.att.research.xacml.std.json.JSONResponse; +import com.att.research.xacml.util.XACMLProperties; +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * Servlet implementation class XacmlPdpServlet + * + * This is an implementation of the XACML 3.0 RESTful Interface with added features to support + * simple PAP RESTful API for policy publishing and PIP configuration changes. + * + * If you are running this the first time, then we recommend you look at the xacml.pdp.properties file. + * This properties file has all the default parameter settings. If you are running the servlet as is, + * then we recommend setting up you're container to run it on port 8080 with context "/pdp". Wherever + * the default working directory is set to, a "config" directory will be created that holds the policy + * and pip cache. This setting is located in the xacml.pdp.properties file. + * + * When you are ready to customize, you can create a separate xacml.pdp.properties on you're local file + * system and setup the parameters as you wish. Just set the Java VM System variable to point to that file: + * + * -Dxacml.properties=/opt/app/xacml/etc/xacml.pdp.properties + * + * Or if you only want to change one or two properties, simply set the Java VM System variable for that property. + * + * -Dxacml.rest.pdp.register=false + * + * + */ +@WebServlet( + description = "Implements the XACML PDP RESTful API and client PAP API.", + urlPatterns = { "/" }, + loadOnStartup=1, + initParams = { + @WebInitParam(name = "XACML_PROPERTIES_NAME", value = "xacml.pdp.properties", description = "The location of the PDP xacml.pdp.properties file holding configuration information.") + }) +public class XACMLPdpServlet extends HttpServlet implements Runnable { + private static final long serialVersionUID = 1L; + private static final String DEFAULT_MAX_CONTENT_LENGTH = "999999999"; //32767 + private static final String CREATE_UPDATE_POLICY_SERVICE = "org.onap.policy.pdp.rest.api.services.CreateUpdatePolicyServiceImpl"; + // + // Our application debug log + // + private static final Log logger = LogFactory.getLog(XACMLPdpServlet.class); + // + // This logger is specifically only for Xacml requests and their corresponding response. + // It's output ideally should be sent to a separate file from the application logger. + // + private static final Log requestLogger = LogFactory.getLog("xacml.request"); + // + // audit logger + private static final Log auditLogger = LogFactory.getLog("auditLogger"); + + private static final PdpRestMonitor monitor = PdpRestMonitor.getSingleton(); + + // + // This thread may getting invoked on startup, to let the PAP know + // that we are up and running. + // + private Thread registerThread = null; + private XACMLPdpRegisterThread registerRunnable = null; + // + // This is our PDP engine pointer. There is a synchronized lock used + // for access to the pointer. In case we are servicing PEP requests while + // an update is occurring from the PAP. + // + private static PDPEngine pdpEngine = null; + private static final Object pdpEngineLock = new Object(); + // + // This is our PDP's status. What policies are loaded (or not) and + // what PIP configurations are loaded (or not). + // There is a synchronized lock used for access to the object. + // + private static volatile StdPDPStatus status = new StdPDPStatus(); + private static final Object pdpStatusLock = new Object(); + private static Constructor<?> createUpdatePolicyConstructor; + + private static final String ENVIORNMENT_HEADER = "Environment"; + private static String environment = null; + // + // Queue of PUT requests + // + public static class PutRequest { + private Properties policyProperties = null; + private Properties pipConfigProperties = null; + + PutRequest(Properties policies, Properties pips) { + this.policyProperties = policies; + this.pipConfigProperties = pips; + } + } + protected static volatile BlockingQueue<PutRequest> queue = null; + // For notification Delay. + private static int notificationDelay = 0; + public static int getNotificationDelay(){ + return XACMLPdpServlet.notificationDelay; + } + + private static String pdpResourceName; + private static String[] dependencyNodes = null; + + // + // This is our configuration thread that attempts to load + // a new configuration request. + // + private Thread configThread = null; + private volatile boolean configThreadTerminate = false; + private ONAPLoggingContext baseLoggingContext = null; + private IntegrityMonitor im; + /** + * Default constructor. + */ + public XACMLPdpServlet() { + //Default constructor. + } + + /** + * @see Servlet#init(ServletConfig) + */ + @Override + public void init(ServletConfig config) throws ServletException { + String createUpdateResourceName = null; + String dependencyGroups = null; + // + // Initialize + // + XACMLRest.xacmlInit(config); + // Load the Notification Delay. + try{ + XACMLPdpServlet.notificationDelay = Integer.parseInt(XACMLProperties.getProperty(XACMLRestProperties.PROP_NOTIFICATION_DELAY)); + }catch(Exception e){ + logger.info("Notification Delay Not set. Keeping it 0 as default."+e); + } + // Load Queue size. + int queueSize = 5; // Set default Queue Size here. + queueSize = Integer.parseInt(XACMLProperties.getProperty("REQUEST_BUFFER_SIZE",String.valueOf(queueSize))); + queue = new LinkedBlockingQueue<PutRequest>(queueSize); + // Load our engine - this will use the latest configuration + // that was saved to disk and set our initial status object. + // + PDPEngine engine = XACMLPdpLoader.loadEngine(XACMLPdpServlet.status, null, null); + if (engine != null) { + synchronized(pdpEngineLock) { + pdpEngine = engine; + } + } + // + // Logging stuff.... + // + baseLoggingContext = new ONAPLoggingContext(); + // fixed data that will be the same in all logging output goes here + try { + String ipaddress = InetAddress.getLocalHost().getHostAddress(); + baseLoggingContext.setServer(ipaddress); + } catch (UnknownHostException e) { + logger.warn(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Unable to get hostname for logging"+e); + } + + Properties properties; + try { + properties = XACMLProperties.getProperties(); + } catch (IOException e) { + PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, + "Error loading properties with: XACMLProperties.getProperties()"); + throw new ServletException(e.getMessage(), e.getCause()); + } + if(properties.getProperty(XACMLRestProperties.PDP_RESOURCE_NAME)==null){ + XACMLProperties.reloadProperties(); + try { + properties = XACMLProperties.getProperties(); + } catch (IOException e) { + PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, + "Error loading properties with: XACMLProperties.getProperties()"); + throw new ServletException(e.getMessage(), e.getCause()); + } + PolicyLogger.info("\n Properties Given : \n" + properties.toString()); + } + pdpResourceName = properties.getProperty(XACMLRestProperties.PDP_RESOURCE_NAME); + if(pdpResourceName == null){ + PolicyLogger.error(MessageCodes.MISS_PROPERTY_ERROR, XACMLRestProperties.PDP_RESOURCE_NAME, "xacml.pdp"); + throw new ServletException("pdpResourceName is null"); + } + + dependencyGroups = properties.getProperty(IntegrityMonitorProperties.DEPENDENCY_GROUPS); + if(dependencyGroups == null){ + PolicyLogger.error(MessageCodes.MISS_PROPERTY_ERROR, IntegrityMonitorProperties.DEPENDENCY_GROUPS, "xacml.pdp"); + throw new ServletException("dependency_groups is null"); + } + // dependency_groups is a semicolon-delimited list of groups, and + // each group is a comma-separated list of nodes. For our purposes + // we just need a list of dependencies without regard to grouping, + // so split the list into nodes separated by either comma or semicolon. + dependencyNodes = dependencyGroups.split("[;,]"); + for (int i = 0 ; i < dependencyNodes.length ; i++){ + dependencyNodes[i] = dependencyNodes[i].trim(); + } + + // CreateUpdatePolicy ResourceName + createUpdateResourceName = properties.getProperty("createUpdatePolicy.impl.className", CREATE_UPDATE_POLICY_SERVICE); + setCreateUpdatePolicyConstructor(createUpdateResourceName); + + // Create an IntegrityMonitor + try { + logger.info("Creating IntegrityMonitor"); + im = IntegrityMonitor.getInstance(pdpResourceName, properties); + } catch (Exception e) { + PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "Failed to create IntegrityMonitor" +e); + throw new ServletException(e); + } + + environment = XACMLProperties.getProperty("ENVIRONMENT", "DEVL"); + // + // Kick off our thread to register with the PAP servlet. + // + if (Boolean.parseBoolean(XACMLProperties.getProperty(XACMLRestProperties.PROP_PDP_REGISTER))) { + this.registerRunnable = new XACMLPdpRegisterThread(baseLoggingContext); + this.registerThread = new Thread(this.registerRunnable); + this.registerThread.start(); + } + // + // This is our thread that manages incoming configuration + // changes. + // + this.configThread = new Thread(this); + this.configThread.start(); + } + + /** + * @see Servlet#destroy() + */ + @Override + public void destroy() { + super.destroy(); + logger.info("Destroying...."); + // + // Make sure the register thread is not running + // + if (this.registerRunnable != null) { + try { + this.registerRunnable.terminate(); + if (this.registerThread != null) { + this.registerThread.interrupt(); + this.registerThread.join(); + } + } catch (InterruptedException e) { + logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + e); + PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, ""); + } + } + // + // Make sure the configure thread is not running + // + this.configThreadTerminate = true; + try { + this.configThread.interrupt(); + this.configThread.join(); + } catch (InterruptedException e) { + logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + e); + PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, ""); + } + logger.info("Destroyed."); + } + + /** + * PUT - The PAP engine sends configuration information using HTTP PUT request. + * + * One parameter is expected: + * + * config=[policy|pip|all] + * + * policy - Expect a properties file that contains updated lists of the root and referenced policies that the PDP should + * be using for PEP requests. + * + * Specifically should AT LEAST contain the following properties: + * xacml.rootPolicies + * xacml.referencedPolicies + * + * In addition, any relevant information needed by the PDP to load or retrieve the policies to store in its cache. + * + * EXAMPLE: + * xacml.rootPolicies=PolicyA.1, PolicyB.1 + * + * PolicyA.1.url=http://localhost:9090/PAP?id=b2d7b86d-d8f1-4adf-ba9d-b68b2a90bee1&version=1 + * PolicyB.1.url=http://localhost:9090/PAP/id=be962404-27f6-41d8-9521-5acb7f0238be&version=1 + * + * xacml.referencedPolicies=RefPolicyC.1, RefPolicyD.1 + * + * RefPolicyC.1.url=http://localhost:9090/PAP?id=foobar&version=1 + * RefPolicyD.1.url=http://localhost:9090/PAP/id=example&version=1 + * + * pip - Expect a properties file that contain PIP engine configuration properties. + * + * Specifically should AT LEAST the following property: + * xacml.pip.engines + * + * In addition, any relevant information needed by the PDP to load and configure the PIPs. + * + * EXAMPLE: + * xacml.pip.engines=foo,bar + * + * foo.classname=com.foo + * foo.sample=abc + * foo.example=xyz + * ...... + * + * bar.classname=com.bar + * ...... + * + * all - Expect ALL new configuration properties for the PDP + * + * @see HttpServlet#doPut(HttpServletRequest request, HttpServletResponse response) + */ + @Override + protected void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + ONAPLoggingContext loggingContext = ONAPLoggingUtils.getLoggingContextForRequest(request, baseLoggingContext); + loggingContext.transactionStarted(); + if ((loggingContext.getRequestID() == null) || "".equals(loggingContext.getRequestID())){ + UUID requestID = UUID.randomUUID(); + loggingContext.setRequestID(requestID.toString()); + PolicyLogger.info("requestID not provided in call to XACMLPdpSrvlet (doPut) so we generated one"); + } else { + PolicyLogger.info("requestID was provided in call to XACMLPdpSrvlet (doPut)"); + } + loggingContext.metricStarted(); + loggingContext.metricEnded(); + PolicyLogger.metrics("Metric example posted here - 1 of 2"); + loggingContext.metricStarted(); + loggingContext.metricEnded(); + PolicyLogger.metrics("Metric example posted here - 2 of 2"); + // + // Dump our request out + // + if (logger.isDebugEnabled()) { + XACMLRest.dumpRequest(request); + } + + try { + im.startTransaction(); + } + catch (AdministrativeStateException | StandbyStatusException e) { + String message = e.toString(); + PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message + e); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + try{ + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message); + }catch(Exception e1){ + logger.error("Exception occured while sending error in response" +e1); + } + return; + } + // + // What is being PUT? + // + String cache = request.getParameter("cache"); + // + // Should be a list of policy and pip configurations in Java properties format + // + if (cache != null && request.getContentType().equals("text/x-java-properties")) { + loggingContext.setServiceName("PDP.putConfig"); + try{ + if (request.getContentLength() > Integer.parseInt(XACMLProperties.getProperty("MAX_CONTENT_LENGTH", DEFAULT_MAX_CONTENT_LENGTH))) { + String message = "Content-Length larger than server will accept."; + logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + message); + loggingContext.transactionEnded(); + PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, message); + PolicyLogger.audit("Transaction Failed - See Error.log"); + response.sendError(HttpServletResponse.SC_BAD_REQUEST, message); + im.endTransaction(); + return; + } + this.doPutConfig(cache, request, response, loggingContext); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction ended"); + + im.endTransaction(); + }catch(Exception e){ + logger.error("Exception Occured while getting Max Content lenght"+e); + } + } else { + String message = "Invalid cache: '" + cache + "' or content-type: '" + request.getContentType() + "'"; + logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + message); + PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + try{ + response.sendError(HttpServletResponse.SC_BAD_REQUEST, message); + }catch(Exception e1){ + logger.error("Exception occured while sending error in response" +e1); + } + im.endTransaction(); + return; + } + } + + protected void doPutConfig(String config, HttpServletRequest request, HttpServletResponse response, ONAPLoggingContext loggingContext) throws ServletException, IOException { + try { + // prevent multiple configuration changes from stacking up + if (XACMLPdpServlet.queue.remainingCapacity() <= 0) { + logger.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Queue capacity reached"); + PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, "Queue capacity reached"); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + response.sendError(HttpServletResponse.SC_CONFLICT, "Multiple configuration changes waiting processing."); + return; + } + // + // Read the properties data into an object. + // + Properties newProperties = new Properties(); + newProperties.load(request.getInputStream()); + // should have something in the request + if (newProperties.size() == 0) { + logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "No properties in PUT"); + PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, "No properties in PUT"); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + response.sendError(HttpServletResponse.SC_BAD_REQUEST, "PUT must contain at least one property"); + return; + } + // + // Which set of properties are they sending us? Whatever they send gets + // put on the queue (if there is room). + // For audit logging purposes, we consider the transaction done once the + // the request gets put on the queue. + // + if (config.equals("policies")) { + newProperties = XACMLProperties.getPolicyProperties(newProperties, true); + if (newProperties.size() == 0) { + logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "No policy properties in PUT"); + PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, "No policy properties in PUT"); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + response.sendError(HttpServletResponse.SC_BAD_REQUEST, "PUT with cache=policies must contain at least one policy property"); + return; + } + XACMLPdpServlet.queue.offer(new PutRequest(newProperties, null)); + loggingContext.transactionEnded(); + auditLogger.info("Success"); + PolicyLogger.audit("Success"); + } else if (config.equals("pips")) { + newProperties = XACMLProperties.getPipProperties(newProperties); + if (newProperties.size() == 0) { + logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "No pips properties in PUT"); + PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, "No pips properties in PUT"); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + response.sendError(HttpServletResponse.SC_BAD_REQUEST, "PUT with cache=pips must contain at least one pip property"); + return; + } + XACMLPdpServlet.queue.offer(new PutRequest(null, newProperties)); + loggingContext.transactionEnded(); + auditLogger.info("Success"); + PolicyLogger.audit("Success"); + } else if (config.equals("all")) { + Properties newPolicyProperties = XACMLProperties.getPolicyProperties(newProperties, true); + if (newPolicyProperties.size() == 0) { + logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "No policy properties in PUT"); + PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, "No policy properties in PUT"); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + response.sendError(HttpServletResponse.SC_BAD_REQUEST, "PUT with cache=all must contain at least one policy property"); + return; + } + Properties newPipProperties = XACMLProperties.getPipProperties(newProperties); + if (newPipProperties.size() == 0) { + logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "No pips properties in PUT"); + PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, "No pips properties in PUT"); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + response.sendError(HttpServletResponse.SC_BAD_REQUEST, "PUT with cache=all must contain at least one pip property"); + return; + } + XACMLPdpServlet.queue.offer(new PutRequest(newPolicyProperties, newPipProperties)); + loggingContext.transactionEnded(); + auditLogger.info("Success"); + PolicyLogger.audit("Success"); + } else { + // + // Invalid value + // + logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Invalid config value: " + config); + PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, "Invalid config value: " + config); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Config must be one of 'policies', 'pips', 'all'"); + return; + } + } catch (Exception e) { + logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Failed to process new configuration.", e); + PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "Failed to process new configuration"); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + try{ + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage()); + }catch(Exception e1){ + logger.error("Exception occured while sending error in response" +e1); + } + return; + } + + } + + /** + * Parameters: type=hb|config|Status + * + * 1. HeartBeat Status + * HeartBeat + * OK - All Policies are Loaded, All PIPs are Loaded + * LOADING_IN_PROGRESS - Currently loading a new policy set/pip configuration + * LAST_UPDATE_FAILED - Need to track the items that failed during last update + * LOAD_FAILURE - ??? Need to determine what information is sent and how + * 2. Configuration + * 3. Status + * return the StdPDPStatus object in the Response content + * + * + * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) + */ + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + ONAPLoggingContext loggingContext = ONAPLoggingUtils.getLoggingContextForRequest(request, baseLoggingContext); + loggingContext.transactionStarted(); + if ((loggingContext.getRequestID() == null) || (loggingContext.getRequestID() == "")){ + UUID requestID = UUID.randomUUID(); + loggingContext.setRequestID(requestID.toString()); + PolicyLogger.info("requestID not provided in call to XACMLPdpSrvlet (doGet) so we generated one"); + } else { + PolicyLogger.info("requestID was provided in call to XACMLPdpSrvlet (doGet)"); + } + loggingContext.metricStarted(); + loggingContext.metricEnded(); + PolicyLogger.metrics("Metric example posted here - 1 of 2"); + loggingContext.metricStarted(); + loggingContext.metricEnded(); + PolicyLogger.metrics("Metric example posted here - 2 of 2"); + + XACMLRest.dumpRequest(request); + + String pathInfo = request.getRequestURI(); + if (pathInfo != null){ + // health check from Global Site Selector (iDNS). + // DO NOT do a im.startTransaction for the test request + if (pathInfo.equals("/pdp/test")) { + loggingContext.setServiceName("iDNS:PDP.test"); + try { + im.evaluateSanity(); + //If we make it this far, all is well + String message = "GET:/pdp/test called and PDP " + pdpResourceName + " is OK"; + PolicyLogger.debug(message); + loggingContext.transactionEnded(); + PolicyLogger.audit("Success"); + response.setStatus(HttpServletResponse.SC_OK); + return; + } catch (ForwardProgressException fpe){ + //No forward progress is being made + String message = "GET:/pdp/test called and PDP " + pdpResourceName + " is not making forward progress." + + " Exception Message: " + fpe.getMessage(); + PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message + fpe); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + try{ + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message); + }catch(Exception e1){ + logger.error("Exception occured while sending error in response" +e1); + } + return; + }catch (AdministrativeStateException ase){ + //Administrative State is locked + String message = "GET:/pdp/test called and PDP " + pdpResourceName + " Administrative State is LOCKED " + + " Exception Message: " + ase.getMessage(); + PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message + ase); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + try{ + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message); + }catch(Exception e1){ + logger.error("Exception occured while sending error in response" +e1); + } + return; + }catch (StandbyStatusException sse){ + //Administrative State is locked + String message = "GET:/pdp/test called and PDP " + pdpResourceName + " Standby Status is NOT PROVIDING SERVICE " + + " Exception Message: " + sse.getMessage(); + PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message + sse); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + try{ + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message); + }catch(Exception e1){ + logger.error("Exception occured while sending error in response" +e1); + } + return; + } catch (Exception e) { + //A subsystem is not making progress or is not responding + String eMsg = e.getMessage(); + if(eMsg == null){ + eMsg = "No Exception Message"; + } + String message = "GET:/pdp/test called and PDP " + pdpResourceName + " has had a subsystem failure." + + " Exception Message: " + eMsg; + PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message ); + //Get the specific list of subsystems that failed + String failedNodeList = null; + for(String node : dependencyNodes){ + if(eMsg.contains(node)){ + if(failedNodeList == null){ + failedNodeList = node; + }else{ + failedNodeList = failedNodeList.concat(","+node); + } + } + } + if(failedNodeList == null){ + failedNodeList = "UnknownSubSystem"; + } + response.addHeader("X-ONAP-SubsystemFailure", failedNodeList); + try{ + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message); + }catch(Exception e1){ + logger.error("Exception occured while sending error in response" +e1); + } + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log" + e); + return; + } + } + } + + try { + im.startTransaction(); + } + catch (AdministrativeStateException | StandbyStatusException e) { + String message = e.toString(); + PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log" +e); + try{ + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message); + }catch(Exception e1){ + logger.error("Exception occured while sending error in response" +e1); + } + return; + } + // + // What are they requesting? + // + boolean returnHB = false; + response.setHeader("Cache-Control", "no-cache"); + String type = request.getParameter("type"); + // type might be null, so use equals on string constants + if ("config".equals(type)) { + loggingContext.setServiceName("PDP.getConfig"); + response.setContentType("text/x-java-properties"); + try { + String lists = XACMLProperties.PROP_ROOTPOLICIES + "=" + XACMLProperties.getProperty(XACMLProperties.PROP_ROOTPOLICIES, ""); + lists = lists + "\n" + XACMLProperties.PROP_REFERENCEDPOLICIES + "=" + XACMLProperties.getProperty(XACMLProperties.PROP_REFERENCEDPOLICIES, "") + "\n"; + try (InputStream listInputStream = new ByteArrayInputStream(lists.getBytes()); + InputStream pipInputStream = Files.newInputStream(XACMLPdpLoader.getPIPConfig()); + OutputStream os = response.getOutputStream()) { + IOUtils.copy(listInputStream, os); + IOUtils.copy(pipInputStream, os); + } + loggingContext.transactionEnded(); + auditLogger.info("Success"); + PolicyLogger.audit("Success"); + response.setStatus(HttpServletResponse.SC_OK); + } catch (Exception e) { + logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Failed to copy property file", e); + PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "Failed to copy property file"); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + try{ + response.sendError(400, "Failed to copy Property file"); + }catch(Exception e1){ + logger.error("Exception occured while sending error in response" +e1); + } + } + + } else if ("hb".equals(type)) { + returnHB = true; + response.setStatus(HttpServletResponse.SC_NO_CONTENT); + + } else if ("Status".equals(type)) { + loggingContext.setServiceName("PDP.getStatus"); + // convert response object to JSON and include in the response + synchronized(pdpStatusLock) { + ObjectMapper mapper = new ObjectMapper(); + try{ + mapper.writeValue(response.getOutputStream(), status); + }catch(Exception e1){ + logger.error("Exception occured while writing output stream" +e1); + } + } + response.setStatus(HttpServletResponse.SC_OK); + loggingContext.transactionEnded(); + auditLogger.info("Success"); + PolicyLogger.audit("Success"); + + } else { + logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Invalid type value: " + type); + PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, "Invalid type value: " + type); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + try{ + response.sendError(HttpServletResponse.SC_BAD_REQUEST, "type not 'config' or 'hb'"); + }catch(Exception e1){ + logger.error("Exception occured while sending error in response" +e1); + } + } + if (returnHB) { + synchronized(pdpStatusLock) { + response.addHeader(XACMLRestProperties.PROP_PDP_HTTP_HEADER_HB, status.getStatus().toString()); + } + } + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Ended"); + im.endTransaction(); + + } + + /** + * POST - We expect XACML requests to be posted by PEP applications. They can be in the form of XML or JSON according + * to the XACML 3.0 Specifications for both. + * + * + * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) + */ + @Override + protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + + ONAPLoggingContext loggingContext = ONAPLoggingUtils.getLoggingContextForRequest(request, baseLoggingContext); + loggingContext.transactionStarted(); + loggingContext.setServiceName("PDP.decide"); + if ((loggingContext.getRequestID() == null) || ("".equals(loggingContext.getRequestID()))){ + UUID requestID = UUID.randomUUID(); + loggingContext.setRequestID(requestID.toString()); + PolicyLogger.info("requestID not provided in call to XACMLPdpSrvlet (doPost) so we generated one"); + } else { + PolicyLogger.info("requestID was provided in call to XACMLPdpSrvlet (doPost)"); + } + loggingContext.metricStarted(); + loggingContext.metricEnded(); + PolicyLogger.metrics("Metric example posted here - 1 of 2"); + loggingContext.metricStarted(); + loggingContext.metricEnded(); + PolicyLogger.metrics("Metric example posted here - 2 of 2"); + monitor.pdpEvaluationAttempts(); + + try { + im.startTransaction(); + } + catch (AdministrativeStateException | StandbyStatusException e) { + String message = e.toString(); + PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message + e); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + try{ + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message); + }catch(Exception e1){ + logger.error("Exception occured while sending error in response" +e1); + } + return; + } + // + // no point in doing any work if we know from the get-go that we cannot do anything with the request + // + if (status.getLoadedRootPolicies().isEmpty()) { + logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Request from PEP at " + request.getRequestURI() + " for service when PDP has No Root Policies loaded"); + PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, "Request from PEP at " + request.getRequestURI() + " for service when PDP has No Root Policies loaded"); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + try{ + response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE); + }catch(Exception e1){ + logger.error("Exception occured while sending error in response" +e1); + } + im.endTransaction(); + return; + } + + XACMLRest.dumpRequest(request); + // + // Set our no-cache header + // + response.setHeader("Cache-Control", "no-cache"); + // + // They must send a Content-Type + // + if (request.getContentType() == null) { + logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Must specify a Content-Type"); + PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, "Must specify a Content-Type"); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + try{ + response.sendError(HttpServletResponse.SC_BAD_REQUEST, "no content-type given"); + }catch(Exception e1){ + logger.error("Exception occured while sending error in response" +e1); + } + im.endTransaction(); + return; + } + // + // Limit the Content-Length to something reasonable + // + try{ + if (request.getContentLength() > Integer.parseInt(XACMLProperties.getProperty("MAX_CONTENT_LENGTH", "32767"))) { + String message = "Content-Length larger than server will accept."; + logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + message); + PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, message); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + response.sendError(HttpServletResponse.SC_BAD_REQUEST, message); + im.endTransaction(); + return; + } + }catch(Exception e){ + logger.error("Exception occured while getting max content length"+e); + } + + if (request.getContentLength() <= 0) { + String message = "Content-Length is negative"; + logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + message); + PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, message); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + try{ + response.sendError(HttpServletResponse.SC_BAD_REQUEST, message); + }catch(Exception e1){ + logger.error("Exception occured while sending error in response" +e1); + } + im.endTransaction(); + return; + } + ContentType contentType = null; + try { + contentType = ContentType.parse(request.getContentType()); + } + catch (Exception e) { + String message = "Parsing Content-Type: " + request.getContentType() + ", error=" + e.getMessage(); + logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + message, e); + loggingContext.transactionEnded(); + PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, message); + PolicyLogger.audit("Transaction Failed - See Error.log"); + try{ + response.sendError(HttpServletResponse.SC_BAD_REQUEST, message); + }catch(Exception e1){ + logger.error("Exception occured while sending error in response" +e1); + } + im.endTransaction(); + return; + } + // + // What exactly did they send us? + // + String incomingRequestString = null; + Request pdpRequest = null; + if (contentType.getMimeType().equalsIgnoreCase(ContentType.APPLICATION_JSON.getMimeType()) || + contentType.getMimeType().equalsIgnoreCase(ContentType.APPLICATION_XML.getMimeType()) || + contentType.getMimeType().equalsIgnoreCase("application/xacml+xml") ) { + // + // Read in the string + // + StringBuilder buffer = new StringBuilder(); + BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream())); + String line; + try{ + while((line = reader.readLine()) != null){ + buffer.append(line); + } + }catch(Exception e){ + logger.error("Exception Occured while reading line"+e); + } + + incomingRequestString = buffer.toString(); + logger.info(incomingRequestString); + // + // Parse into a request + // + try { + if (contentType.getMimeType().equalsIgnoreCase(ContentType.APPLICATION_JSON.getMimeType())) { + pdpRequest = JSONRequest.load(incomingRequestString); + } else if ( contentType.getMimeType().equalsIgnoreCase(ContentType.APPLICATION_XML.getMimeType()) || + contentType.getMimeType().equalsIgnoreCase("application/xacml+xml")) { + pdpRequest = DOMRequest.load(incomingRequestString); + } + } + catch(Exception e) { + logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Could not parse request", e); + PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, "Could not parse request"); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + try{ + response.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage()); + }catch(Exception e1){ + logger.error("Exception occured while sending error in response" +e1); + } + im.endTransaction(); + return; + } + } else { + String message = "unsupported content type" + request.getContentType(); + logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + message); + PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, message); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + try{ + response.sendError(HttpServletResponse.SC_BAD_REQUEST, message); + }catch(Exception e1){ + logger.error("Exception occured while sending error in response" +e1); + } + im.endTransaction(); + return; + } + // + // Did we successfully get and parse a request? + // + if (pdpRequest == null || pdpRequest.getRequestAttributes() == null || pdpRequest.getRequestAttributes().size() <= 0) { + String message = "Zero Attributes found in the request"; + logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + message); + PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, message); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + try{ + response.sendError(HttpServletResponse.SC_BAD_REQUEST, message); + }catch(Exception e1){ + logger.error("Exception occured while sending error in response" +e1); + } + im.endTransaction(); + return; + } + // + // Run it + // + try { + // + // Authenticating the Request here. + // + if(!authorizeRequest(request)){ + String message = "PEP not Authorized for making this Request!! \n Contact Administrator for this Scope. "; + logger.error(XACMLErrorConstants.ERROR_PERMISSIONS + message ); + PolicyLogger.error(MessageCodes.ERROR_PERMISSIONS, message); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + response.sendError(HttpServletResponse.SC_FORBIDDEN, message); + im.endTransaction(); + return; + } + // + // Get the pointer to the PDP Engine + // + PDPEngine myEngine = null; + synchronized(pdpEngineLock) { + myEngine = XACMLPdpServlet.pdpEngine; + } + if (myEngine == null) { + String message = "No engine loaded."; + logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + message); + PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message); + im.endTransaction(); + return; + } + // + // Send the request and save the response + // + long lTimeStart; + long lTimeEnd; + Response pdpResponse = null; + + synchronized(pdpEngineLock) { + myEngine = XACMLPdpServlet.pdpEngine; + try { + PolicyList.clearPolicyList(); + lTimeStart = System.currentTimeMillis(); + pdpResponse = myEngine.decide(pdpRequest); + lTimeEnd = System.currentTimeMillis(); + } catch (PDPException e) { + String message = "Exception during decide: " + e.getMessage(); + logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + message +e); + PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + try{ + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message); + }catch(Exception e1){ + logger.error("Exception occured while sending error in response" +e1); + } + im.endTransaction(); + return; + } + } + monitor.computeLatency(lTimeEnd - lTimeStart); + requestLogger.info(lTimeStart + "=" + incomingRequestString); + for(String policy : PolicyList.getpolicyList()){ + monitor.policyCountAdd(policy, 1); + } + + + logger.info("PolicyID triggered in Request: " + PolicyList.getpolicyList()); + + //need to go through the list and find out if the value is unique and then add it other wise + // monitor.policyCountAdd(PolicyList.getpolicyList(), 1); + + if (logger.isDebugEnabled()) { + logger.debug("Request time: " + (lTimeEnd - lTimeStart) + "ms"); + } + // + // Convert Response to appropriate Content-Type + // + if (pdpResponse == null) { + requestLogger.info(lTimeStart + "=" + "{}"); + try{ + throw new PDPException("Failed to get response from PDP engine."); + }catch(Exception e1){ + logger.error("Exception occured while throwing Exception" +e1); + } + } + // + // Set our content-type + // + response.setContentType(contentType.getMimeType()); + // + // Convert the PDP response object to a String to + // return to our caller as well as dump to our loggers. + // + String outgoingResponseString = ""; + try{ + if (contentType.getMimeType().equalsIgnoreCase(ContentType.APPLICATION_JSON.getMimeType())) { + // + // Get it as a String. This is not very efficient but we need to log our + // results for auditing. + // + outgoingResponseString = JSONResponse.toString(pdpResponse, logger.isDebugEnabled()); + if (logger.isDebugEnabled()) { + logger.debug(outgoingResponseString); + // + // Get rid of whitespace + // + outgoingResponseString = JSONResponse.toString(pdpResponse, false); + } + } else if ( contentType.getMimeType().equalsIgnoreCase(ContentType.APPLICATION_XML.getMimeType()) || + contentType.getMimeType().equalsIgnoreCase("application/xacml+xml")) { + // + // Get it as a String. This is not very efficient but we need to log our + // results for auditing. + // + outgoingResponseString = DOMResponse.toString(pdpResponse, logger.isDebugEnabled()); + if (logger.isDebugEnabled()) { + logger.debug(outgoingResponseString); + // + // Get rid of whitespace + // + outgoingResponseString = DOMResponse.toString(pdpResponse, false); + } + } + // adding the jmx values for NA, Permit and Deny + // + if (outgoingResponseString.contains("NotApplicable") || outgoingResponseString.contains("Decision not a Permit")){ + monitor.pdpEvaluationNA(); + } + + if (outgoingResponseString.contains("Permit") && !outgoingResponseString.contains("Decision not a Permit")){ + monitor.pdpEvaluationPermit(); + } + + if (outgoingResponseString.contains("Deny")){ + monitor.pdpEvaluationDeny(); + } + // + // lTimeStart is used as an ID within the requestLogger to match up + // request's with responses. + // + requestLogger.info(lTimeStart + "=" + outgoingResponseString); + response.getWriter().print(outgoingResponseString); + }catch(Exception e){ + logger.error("Exception Occured"+e ); + } + } + catch (Exception e) { + String message = "Exception executing request: " + e; + logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + message, e); + PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, message); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + try{ + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message); + }catch(Exception e1){ + logger.error("Exception occured while sending error in response" +e1); + } + return; + } + + monitor.pdpEvaluationSuccess(); + response.setStatus(HttpServletResponse.SC_OK); + + loggingContext.transactionEnded(); + auditLogger.info("Success"); + PolicyLogger.audit("Success"); + + } + + /* + * Added for Authorizing the PEP Requests for Environment check. + */ + private boolean authorizeRequest(HttpServletRequest request) { + // Get the client Credentials from the Request header. + HttpServletRequest httpServletRequest = request; + String clientCredentials = httpServletRequest.getHeader(ENVIORNMENT_HEADER); + if(clientCredentials!=null && clientCredentials.equalsIgnoreCase(environment)){ + return true; + }else{ + return false; + } + } + + @Override + public void run() { + // + // Keep running until we are told to terminate + // + try { + // variable not used, but constructor has needed side-effects so don't remove: + while (! this.configThreadTerminate) { + PutRequest request = XACMLPdpServlet.queue.take(); + StdPDPStatus newStatus = new StdPDPStatus(); + + PDPEngine newEngine = null; + synchronized(pdpStatusLock) { + XACMLPdpServlet.status.setStatus(Status.UPDATING_CONFIGURATION); + newEngine = XACMLPdpLoader.loadEngine(newStatus, request.policyProperties, request.pipConfigProperties); + } + if (newEngine != null) { + synchronized(XACMLPdpServlet.pdpEngineLock) { + XACMLPdpServlet.pdpEngine = newEngine; + try { + logger.info("Saving configuration."); + if (request.policyProperties != null) { + try (OutputStream os = Files.newOutputStream(XACMLPdpLoader.getPDPPolicyCache())) { + request.policyProperties.store(os, ""); + } + } + if (request.pipConfigProperties != null) { + try (OutputStream os = Files.newOutputStream(XACMLPdpLoader.getPIPConfig())) { + request.pipConfigProperties.store(os, ""); + } + } + newStatus.setStatus(Status.UP_TO_DATE); + } catch (Exception e) { + logger.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Failed to store new properties."+e); + PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, "Failed to store new properties"); + newStatus.setStatus(Status.LOAD_ERRORS); + newStatus.addLoadWarning("Unable to save configuration: " + e.getMessage()); + } + } + } else { + newStatus.setStatus(Status.LAST_UPDATE_FAILED); + } + synchronized(pdpStatusLock) { + XACMLPdpServlet.status.set(newStatus); + } + } + } catch (InterruptedException e) { + logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "interrupted"+e); + PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, "interrupted"); + Thread.currentThread().interrupt(); + } + } + + public static PDPEngine getPDPEngine(){ + PDPEngine myEngine = null; + synchronized(pdpEngineLock) { + myEngine = XACMLPdpServlet.pdpEngine; + } + return myEngine; + } + + public static Constructor<?> getCreateUpdatePolicyConstructor(){ + return createUpdatePolicyConstructor; + } + + private static void setCreateUpdatePolicyConstructor(String createUpdateResourceName) throws ServletException{ + try{ + Class<?> createUpdateclass = Class.forName(createUpdateResourceName); + createUpdatePolicyConstructor = createUpdateclass.getConstructor(PolicyParameters.class, String.class, boolean.class); + }catch(Exception e){ + PolicyLogger.error(MessageCodes.MISS_PROPERTY_ERROR, "createUpdatePolicy.impl.className", "xacml.pdp.init" +e); + throw new ServletException("Could not find the Class name : " +createUpdateResourceName + "\n" +e.getMessage()); + } + } +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/controller/PolicyEngineServices.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/controller/PolicyEngineServices.java new file mode 100644 index 000000000..2348fd0da --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/controller/PolicyEngineServices.java @@ -0,0 +1,658 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.policy.pdp.rest.api.controller; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; + +import java.lang.reflect.InvocationTargetException; +import java.util.Collection; +import java.util.concurrent.atomic.AtomicLong; + +import javax.servlet.http.HttpServletRequest; + +import org.onap.policy.api.ConfigRequestParameters; +import org.onap.policy.api.DecisionRequestParameters; +import org.onap.policy.api.DecisionResponse; +import org.onap.policy.api.DeletePolicyParameters; +import org.onap.policy.api.DictionaryParameters; +import org.onap.policy.api.DictionaryResponse; +import org.onap.policy.api.EventRequestParameters; +import org.onap.policy.api.MetricsResponse; +import org.onap.policy.api.PolicyParameters; +import org.onap.policy.api.PolicyResponse; +import org.onap.policy.api.PushPolicyParameters; +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; +import org.onap.policy.pdp.rest.XACMLPdpServlet; +import org.onap.policy.pdp.rest.api.models.ConfigFirewallPolicyAPIRequest; +import org.onap.policy.pdp.rest.api.models.ConfigNameRequest; +import org.onap.policy.pdp.rest.api.models.ConfigPolicyAPIRequest; +import org.onap.policy.pdp.rest.api.models.PolicyConfig; +import org.onap.policy.pdp.rest.api.services.CreateUpdateConfigPolicyService; +import org.onap.policy.pdp.rest.api.services.CreateUpdateDictionaryService; +import org.onap.policy.pdp.rest.api.services.CreateUpdateFirewallPolicyService; +import org.onap.policy.pdp.rest.api.services.CreateUpdatePolicyService; +import org.onap.policy.pdp.rest.api.services.DeletePolicyService; +import org.onap.policy.pdp.rest.api.services.GetConfigService; +import org.onap.policy.pdp.rest.api.services.GetDecisionService; +import org.onap.policy.pdp.rest.api.services.GetDictionaryService; +import org.onap.policy.pdp.rest.api.services.GetMetricsService; +import org.onap.policy.pdp.rest.api.services.ListConfigService; +import org.onap.policy.pdp.rest.api.services.NotificationService; +import org.onap.policy.pdp.rest.api.services.NotificationService.NotificationServiceType; +import org.onap.policy.pdp.rest.api.services.PolicyEngineImportService; +import org.onap.policy.pdp.rest.api.services.PushPolicyService; +import org.onap.policy.pdp.rest.api.services.SendEventService; +import org.onap.policy.pdp.rest.config.PDPApiAuth; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import springfox.documentation.annotations.ApiIgnore; + +@RestController +@Api(value = "Policy Engine Services") +@RequestMapping("/") +public class PolicyEngineServices { + private static Logger logger = FlexLogger.getLogger(PolicyEngineServices.class.getName()); + private static final String NOTIFICATIONPERM = "notification"; + + private final AtomicLong configCounter = new AtomicLong(); + private final AtomicLong configNameCounter = new AtomicLong(); + private final AtomicLong eventCounter = new AtomicLong(); + private final AtomicLong decisionCounter = new AtomicLong(); + private final AtomicLong pushCounter = new AtomicLong(); + private final AtomicLong deleteCounter = new AtomicLong(); + private final AtomicLong createPolicyCounter = new AtomicLong(); + private final AtomicLong updatePolicyCounter = new AtomicLong(); + private final AtomicLong createDictionaryCounter = new AtomicLong(); + private final AtomicLong updateDictionaryCounter = new AtomicLong(); + private final AtomicLong getDictionaryCounter = new AtomicLong(); + private final AtomicLong policyEngineImportCounter = new AtomicLong(); + private final AtomicLong deprecatedCounter = new AtomicLong(); + private final AtomicLong metricCounter = new AtomicLong(); + private final AtomicLong notificationCounter = new AtomicLong(); + + @ApiImplicitParams({ + @ApiImplicitParam(name = "Authorization", required = true, paramType = "Header"), + @ApiImplicitParam(name = "Environment", required = true, paramType = "Header") }) + @ApiOperation(value = "Gets the configuration from the PolicyDecisionPoint(PDP)") + @RequestMapping(value = "/getConfig", method = RequestMethod.POST) + @ResponseBody + public ResponseEntity<Collection<PolicyConfig>> getConfig( + @RequestBody ConfigRequestParameters configRequestParameters, + @RequestHeader(value = "ClientAuth", required = true) String clientEncoding, + @RequestHeader(value = "X-ECOMP-RequestID", required = false) String requestID) { + Collection<PolicyConfig> policyConfig = null; + HttpStatus status = HttpStatus.UNAUTHORIZED; + // Check Permissions. + if (PDPApiAuth.checkPermissions(clientEncoding, requestID, "getConfig")) { + GetConfigService getConfigService = new GetConfigService( + configRequestParameters, requestID); + policyConfig = getConfigService.getResult(); + status = getConfigService.getResponseCode(); + } + configCounter.incrementAndGet(); + return new ResponseEntity<>(policyConfig, status); + } + + @ApiImplicitParams({ + @ApiImplicitParam(name = "Authorization", required = true, paramType = "Header"), + @ApiImplicitParam(name = "Environment", required = true, paramType = "Header") }) + @ApiOperation(value = "Gets the configuration from the PolicyDecisionPoint(PDP) using PolicyName") + @RequestMapping(value = "/getConfigByPolicyName", method = RequestMethod.POST) + @ResponseBody + @Deprecated + public ResponseEntity<Collection<PolicyConfig>> getConfigByPolicyName( + @RequestBody ConfigNameRequest configNameRequest, + @RequestHeader(value = "ClientAuth", required = true) String clientEncoding, + @RequestHeader(value = "X-ECOMP-RequestID", required = false) String requestID) { + Collection<PolicyConfig> policyConfig = null; + HttpStatus status = HttpStatus.UNAUTHORIZED; + // Check Permissions. + if (PDPApiAuth.checkPermissions(clientEncoding, requestID,"getConfigByPolicyName")) { + ConfigRequestParameters configRequestParameters = new ConfigRequestParameters(); + configRequestParameters.setPolicyName(configNameRequest + .getPolicyName()); + GetConfigService getConfigService = new GetConfigService( + configRequestParameters, requestID); + policyConfig = getConfigService.getResult(); + status = getConfigService.getResponseCode(); + } + configNameCounter.incrementAndGet(); + return new ResponseEntity<>(policyConfig, status); + } + + @ApiImplicitParams({ + @ApiImplicitParam(name = "Authorization", required = true, paramType = "Header"), + @ApiImplicitParam(name = "Environment", required = true, paramType = "Header") }) + @ApiOperation(value = "Gets the list of configuration policies from the PDP") + @RequestMapping(value = "/listConfig", method = RequestMethod.POST) + @ResponseBody + public ResponseEntity<Collection<String>> listConfig( + @RequestBody ConfigRequestParameters configRequestParameters, + @RequestHeader(value = "ClientAuth", required = true) String clientEncoding, + @RequestHeader(value = "X-ECOMP-RequestID", required = false) String requestID) { + Collection<String> results = null; + HttpStatus status = HttpStatus.UNAUTHORIZED; + // Check Permissions. + if (PDPApiAuth + .checkPermissions(clientEncoding, requestID, "listConfig")) { + ListConfigService listConfigService = new ListConfigService( + configRequestParameters, requestID); + results = listConfigService.getResult(); + status = listConfigService.getResponseCode(); + } + configCounter.incrementAndGet(); + return new ResponseEntity<>(results, status); + } + + @ApiImplicitParams({ + @ApiImplicitParam(name ="Authorization", required = true, paramType = "Header"), + @ApiImplicitParam(name ="Environment", required = true, paramType = "Header") + }) + @ApiOperation(value= "Gets the policy metrics from the PolicyAccessPoint(PAP)") + @RequestMapping(value="/getMetrics", method=RequestMethod.GET) + @ResponseBody + public ResponseEntity<MetricsResponse> getMetrics( + @RequestHeader(value="ClientAuth", required=true)String clientEncoding, + @RequestHeader(value="X-ECOMP-RequestID", required=false)String requestID) { + MetricsResponse response = null; + HttpStatus status = HttpStatus.UNAUTHORIZED; + // Check Permissions. + if(PDPApiAuth.checkPermissions(clientEncoding, requestID, "getMetrics")){ + GetMetricsService getMetricsService = new GetMetricsService(requestID); + response = getMetricsService.getResult(); + status = getMetricsService.getResponseCode(); + } + metricCounter.incrementAndGet(); + return new ResponseEntity<>(response, status); + } + + @ApiImplicitParams({ + @ApiImplicitParam(name = "Authorization", required = true, paramType = "Header"), + @ApiImplicitParam(name = "Environment", required = true, paramType = "Header") }) + @ApiOperation(value = "Registers DMaaP Topic to recieve notification from Policy Engine") + @RequestMapping(value = "/getNotification", method = RequestMethod.POST) + @ResponseBody + public ResponseEntity<String> getNotification( + @RequestBody String notificationTopic, + @RequestHeader(value = "ClientAuth", required = true) String clientEncoding, + @RequestHeader(value = "X-ECOMP-RequestID", required = false) String requestID) { + String policyResponse = "Error Unauthorized to use Notification Service."; + HttpStatus status = HttpStatus.UNAUTHORIZED; + // Check Permissions. + if (PDPApiAuth.checkPermissions(clientEncoding, requestID, NOTIFICATIONPERM)) { + NotificationService notificationService = new NotificationService(notificationTopic, requestID, NotificationServiceType.ADD); + policyResponse = notificationService.getResult(); + status = notificationService.getResponseCode(); + } + notificationCounter.incrementAndGet(); + return new ResponseEntity<>(policyResponse, status); + } + + @ApiImplicitParams({ + @ApiImplicitParam(name = "Authorization", required = true, paramType = "Header"), + @ApiImplicitParam(name = "Environment", required = true, paramType = "Header") }) + @ApiOperation(value = "De-Registers DMaaP Topic to stop recieving notifications from Policy Engine") + @RequestMapping(value = "/stopNotification", method = RequestMethod.POST) + @ResponseBody + public ResponseEntity<String> stopNotification( + @RequestBody String notificationTopic, + @RequestHeader(value = "ClientAuth", required = true) String clientEncoding, + @RequestHeader(value = "X-ECOMP-RequestID", required = false) String requestID) { + String policyResponse = "Error Unauthorized to use Notification Service."; + HttpStatus status = HttpStatus.UNAUTHORIZED; + // Check Permissions. + if (PDPApiAuth.checkPermissions(clientEncoding, requestID, NOTIFICATIONPERM)) { + NotificationService notificationService = new NotificationService(notificationTopic, requestID, NotificationServiceType.REMOVE); + policyResponse = notificationService.getResult(); + status = notificationService.getResponseCode(); + } + notificationCounter.incrementAndGet(); + return new ResponseEntity<>(policyResponse, status); + } + + @ApiImplicitParams({ + @ApiImplicitParam(name = "Authorization", required = true, paramType = "Header"), + @ApiImplicitParam(name = "Environment", required = true, paramType = "Header") }) + @ApiOperation(value = "Sends Heartbeat to DMaaP Topic Registry to continue recieving notifications from Policy Engine") + @RequestMapping(value = "/sendHeartbeat", method = RequestMethod.POST) + @ResponseBody + public ResponseEntity<String> sendHeartbeat( + @RequestBody String notificationTopic, + @RequestHeader(value = "ClientAuth", required = true) String clientEncoding, + @RequestHeader(value = "X-ECOMP-RequestID", required = false) String requestID) { + String policyResponse = "Error Unauthorized to use Heartbeat Service."; + HttpStatus status = HttpStatus.UNAUTHORIZED; + // Check Permissions. + if (PDPApiAuth.checkPermissions(clientEncoding, requestID, NOTIFICATIONPERM)) { + NotificationService notificationService = new NotificationService(notificationTopic, requestID, NotificationServiceType.HB); + policyResponse = notificationService.getResult(); + status = notificationService.getResponseCode(); + } + return new ResponseEntity<>(policyResponse, status); + } + + @ApiImplicitParams({ + @ApiImplicitParam(name = "Authorization", required = true, paramType = "Header"), + @ApiImplicitParam(name = "Environment", required = true, paramType = "Header") }) + @ApiOperation(value = "Sends the Events specified to the Policy Engine") + @RequestMapping(value = "/sendEvent", method = RequestMethod.POST) + @ResponseBody + public ResponseEntity<Collection<PolicyResponse>> sendEvent( + @RequestBody EventRequestParameters eventRequestParameters, + @RequestHeader(value = "ClientAuth", required = true) String clientEncoding, + @RequestHeader(value = "X-ECOMP-RequestID", required = false) String requestID) { + Collection<PolicyResponse> policyResponse = null; + HttpStatus status = HttpStatus.UNAUTHORIZED; + // Check Permissions. + if (PDPApiAuth.checkPermissions(clientEncoding, requestID, "sendEvent")) { + SendEventService sendEventService = new SendEventService( + eventRequestParameters, requestID); + policyResponse = sendEventService.getResult(); + status = sendEventService.getResponseCode(); + } + eventCounter.incrementAndGet(); + return new ResponseEntity<>(policyResponse, + status); + } + + @ApiImplicitParams({ + @ApiImplicitParam(name = "Authorization", required = true, paramType = "Header"), + @ApiImplicitParam(name = "Environment", required = true, paramType = "Header") }) + @ApiOperation(value = "Gets the Decision using specified decision parameters") + @RequestMapping(value = "/getDecision", method = RequestMethod.POST) + @ResponseBody + public ResponseEntity<DecisionResponse> getDecision( + @RequestBody DecisionRequestParameters decisionRequestParameters, + @RequestHeader(value = "ClientAuth", required = true) String clientEncoding, + @RequestHeader(value = "X-ECOMP-RequestID", required = false) String requestID) { + DecisionResponse decisionResponse = null; + HttpStatus status = HttpStatus.UNAUTHORIZED; + // Check Permissions. + if (PDPApiAuth.checkPermissions(clientEncoding, requestID, + "getDecision")) { + GetDecisionService getDecisionService = new GetDecisionService( + decisionRequestParameters, requestID); + decisionResponse = getDecisionService.getResult(); + status = getDecisionService.getResponseCode(); + } + decisionCounter.incrementAndGet(); + return new ResponseEntity<>(decisionResponse, status); + } + + @ApiImplicitParams({ + @ApiImplicitParam(name = "Authorization", required = true, paramType = "Header"), + @ApiImplicitParam(name = "Environment", required = true, paramType = "Header") }) + @ApiOperation(value = "Pushes the specified policy to the PDP Group.") + @RequestMapping(value = "/pushPolicy", method = RequestMethod.PUT) + @ResponseBody + public ResponseEntity<String> pushPolicy( + @RequestBody PushPolicyParameters pushPolicyParameters, + @RequestHeader(value = "ClientAuth", required = true) String clientEncoding, + @RequestHeader(value = "X-ECOMP-RequestID", required = false) String requestID) { + String response = null; + HttpStatus status = HttpStatus.UNAUTHORIZED; + // Check Permissions. + if (PDPApiAuth + .checkPermissions(clientEncoding, requestID, "pushPolicy")) { + PushPolicyService pushPolicyService = new PushPolicyService( + pushPolicyParameters, requestID); + response = pushPolicyService.getResult(); + status = pushPolicyService.getResponseCode(); + } + pushCounter.incrementAndGet(); + return new ResponseEntity<>(response, status); + } + + @ApiImplicitParams({ + @ApiImplicitParam(name = "Authorization", required = true, paramType = "Header"), + @ApiImplicitParam(name = "Environment", required = true, paramType = "Header") }) + @ApiOperation(value = "Deletes the specified policy from the PDP Group or PAP.") + @RequestMapping(value = "/deletePolicy", method = RequestMethod.DELETE) + @ResponseBody + public ResponseEntity<String> deletePolicy( + @RequestBody DeletePolicyParameters deletePolicyParameters, + @RequestHeader(value = "ClientAuth", required = true) String clientEncoding, + @RequestHeader(value = "X-ECOMP-RequestID", required = false) String requestID) { + String response = null; + HttpStatus status = HttpStatus.UNAUTHORIZED; + // Check Permissions. + if (PDPApiAuth.checkPermissions(clientEncoding, requestID, + "deletePolicy")) { + DeletePolicyService deletePolicyService = new DeletePolicyService( + deletePolicyParameters, requestID); + response = deletePolicyService.getResult(); + status = deletePolicyService.getResponseCode(); + } + deleteCounter.incrementAndGet(); + return new ResponseEntity<>(response, status); + } + + @ApiImplicitParams({ + @ApiImplicitParam(name = "Authorization", required = true, paramType = "Header"), + @ApiImplicitParam(name = "Environment", required = true, paramType = "Header") }) + @ApiOperation(value = "Creates a Policy based on given Policy Parameters.") + @RequestMapping(value = "/createPolicy", method = RequestMethod.PUT) + @ResponseBody + public ResponseEntity<String> createPolicy( + @RequestBody PolicyParameters policyParameters, + @RequestHeader(value = "ClientAuth", required = true) String clientEncoding, + @RequestHeader(value = "X-ECOMP-RequestID", required = false) String requestID) { + String response = null; + HttpStatus status = HttpStatus.UNAUTHORIZED; + // Check Permissions. + if (PDPApiAuth.checkPermissions(clientEncoding, requestID, + "createPolicy")) { + CreateUpdatePolicyService createPolicyService; + try { + createPolicyService = (CreateUpdatePolicyService) XACMLPdpServlet.getCreateUpdatePolicyConstructor().newInstance( + policyParameters, requestID, false); + response = createPolicyService.getResult(); + status = createPolicyService.getResponseCode(); + } catch (InstantiationException | IllegalAccessException + | IllegalArgumentException | InvocationTargetException e) { + logger.error(e.getMessage(), e); + response = "Problem with CreateUpdate Policy Service. "; + status = HttpStatus.INTERNAL_SERVER_ERROR; + } + } + createPolicyCounter.incrementAndGet(); + return new ResponseEntity<>(response, status); + } + + @ApiImplicitParams({ + @ApiImplicitParam(name = "Authorization", required = true, paramType = "Header"), + @ApiImplicitParam(name = "Environment", required = true, paramType = "Header") }) + @ApiOperation(value = "Updates a Policy based on given Policy Parameters.") + @RequestMapping(value = "/updatePolicy", method = RequestMethod.PUT) + @ResponseBody + public ResponseEntity<String> updatePolicy( + @RequestBody PolicyParameters policyParameters, + @RequestHeader(value = "ClientAuth", required = true) String clientEncoding, + @RequestHeader(value = "X-ECOMP-RequestID", required = false) String requestID) { + String response = null; + HttpStatus status = HttpStatus.UNAUTHORIZED; + // Check Permissions. + if (PDPApiAuth.checkPermissions(clientEncoding, requestID, + "updatePolicy")) { + CreateUpdatePolicyService updatePolicyService; + try { + updatePolicyService = (CreateUpdatePolicyService) XACMLPdpServlet.getCreateUpdatePolicyConstructor().newInstance( + policyParameters, requestID, true); + response = updatePolicyService.getResult(); + status = updatePolicyService.getResponseCode(); + } catch (InstantiationException | IllegalAccessException + | IllegalArgumentException | InvocationTargetException e) { + logger.error(e.getMessage(), e); + response = "Problem with CreateUpdate Policy Service. "; + status = HttpStatus.INTERNAL_SERVER_ERROR; + } + } + updatePolicyCounter.incrementAndGet(); + return new ResponseEntity<>(response, status); + } + + @ApiImplicitParams({ + @ApiImplicitParam(name = "Authorization", required = true, paramType = "Header"), + @ApiImplicitParam(name = "Environment", required = true, paramType = "Header") }) + @ApiOperation(value = "Creates a Dictionary Item for a specific dictionary based on given Parameters.") + @RequestMapping(value = "/createDictionaryItem", method = RequestMethod.PUT) + @ResponseBody + public ResponseEntity<String> createDictionaryItem( + @RequestBody DictionaryParameters dictionaryParameters, + @RequestHeader(value = "ClientAuth", required = true) String clientEncoding, + @RequestHeader(value = "X-ECOMP-RequestID", required = false) String requestID) { + String response = null; + HttpStatus status = HttpStatus.UNAUTHORIZED; + // Check Permissions. + if (PDPApiAuth.checkPermissions(clientEncoding, requestID, + "createDictionary")) { + CreateUpdateDictionaryService createDictionaryService = new CreateUpdateDictionaryService( + dictionaryParameters, requestID, false); + response = createDictionaryService.getResult(); + status = createDictionaryService.getResponseCode(); + } + createDictionaryCounter.incrementAndGet(); + return new ResponseEntity<>(response, status); + } + + @ApiImplicitParams({ + @ApiImplicitParam(name = "Authorization", required = true, paramType = "Header"), + @ApiImplicitParam(name = "Environment", required = true, paramType = "Header") }) + @ApiOperation(value = "Updates a Dictionary Item for a specific dictionary based on given Parameters.") + @RequestMapping(value = "/updateDictionaryItem", method = RequestMethod.PUT) + @ResponseBody + public ResponseEntity<String> updateDictionaryItem( + @RequestBody DictionaryParameters dictionaryParameters, + @RequestHeader(value = "ClientAuth", required = true) String clientEncoding, + @RequestHeader(value = "X-ECOMP-RequestID", required = false) String requestID) { + String response = null; + HttpStatus status = HttpStatus.UNAUTHORIZED; + // Check Permissions. + if (PDPApiAuth.checkPermissions(clientEncoding, requestID, + "updateDictionary")) { + CreateUpdateDictionaryService updateDictionaryService = new CreateUpdateDictionaryService( + dictionaryParameters, requestID, true); + response = updateDictionaryService.getResult(); + status = updateDictionaryService.getResponseCode(); + } + updateDictionaryCounter.incrementAndGet(); + return new ResponseEntity<>(response, status); + } + + @ApiImplicitParams({ + @ApiImplicitParam(name = "Authorization", required = true, paramType = "Header"), + @ApiImplicitParam(name = "Environment", required = true, paramType = "Header") }) + @ApiOperation(value = "Gets the dictionary items from the PAP") + @RequestMapping(value = "/getDictionaryItems", method = RequestMethod.POST) + @ResponseBody + public ResponseEntity<DictionaryResponse> getDictionaryItems( + @RequestBody DictionaryParameters dictionaryParameters, + @RequestHeader(value = "ClientAuth", required = true) String clientEncoding, + @RequestHeader(value = "X-ECOMP-RequestID", required = false) String requestID) { + DictionaryResponse dictionaryResponse = null; + HttpStatus status = HttpStatus.UNAUTHORIZED; + // Check Permissions. + if (PDPApiAuth.checkPermissions(clientEncoding, requestID, + "getDictionary")) { + GetDictionaryService getDictionaryService = new GetDictionaryService( + dictionaryParameters, requestID); + dictionaryResponse = getDictionaryService.getResult(); + status = getDictionaryService.getResponseCode(); + } + getDictionaryCounter.incrementAndGet(); + return new ResponseEntity<>(dictionaryResponse, + status); + } + + @ApiImplicitParams({ + @ApiImplicitParam(name = "Authorization", required = true, paramType = "Header"), + @ApiImplicitParam(name = "Environment", required = true, paramType = "Header") }) + @ApiOperation(value = "Imports Policy based on the parameters which represent the service used to create a policy Service.") + @RequestMapping(value = "/policyEngineImport", method = RequestMethod.POST) + @ResponseBody + public ResponseEntity<String> policyEngineImport( + @RequestParam("importParametersJson") String importParametersJson, + @RequestParam("file") MultipartFile file, + @RequestHeader(value = "ClientAuth", required = true) String clientEncoding, + @RequestHeader(value = "X-ECOMP-RequestID", required = false) String requestID) { + String response = null; + HttpStatus status = HttpStatus.UNAUTHORIZED; + // Check Permissions. + if (PDPApiAuth.checkPermissions(clientEncoding, requestID, + "policyEngineImport")) { + PolicyEngineImportService policyEngineImportService = new PolicyEngineImportService( + importParametersJson, file, requestID); + response = policyEngineImportService.getResult(); + status = policyEngineImportService.getResponseCode(); + } + policyEngineImportCounter.incrementAndGet(); + return new ResponseEntity<>(response, status); + } + + @ApiImplicitParams({ + @ApiImplicitParam(name = "Authorization", required = true, paramType = "Header"), + @ApiImplicitParam(name = "Environment", required = true, paramType = "Header") }) + @ApiOperation(value = "Creates a Config Policy based on given Policy Parameters.") + @RequestMapping(value = "/createConfig", method = RequestMethod.PUT) + @ResponseBody + @Deprecated + public ResponseEntity<String> createConfig( + @RequestBody ConfigPolicyAPIRequest configPolicyAPIRequest, + @RequestHeader(value = "ClientAuth", required = true) String clientEncoding, + @RequestHeader(value = "X-ECOMP-RequestID", required = false) String requestID) { + String response = null; + HttpStatus status = HttpStatus.UNAUTHORIZED; + // Check Permissions. + if (PDPApiAuth.checkPermissions(clientEncoding, requestID, + "createPolicy")) { + CreateUpdateConfigPolicyService createPolicyService = new CreateUpdateConfigPolicyService( + configPolicyAPIRequest, requestID, false); + response = createPolicyService.getResult(); + status = createPolicyService.getResponseCode(); + } + deprecatedCounter.incrementAndGet(); + return new ResponseEntity<>(response, status); + } + + @ApiImplicitParams({ + @ApiImplicitParam(name = "Authorization", required = true, paramType = "Header"), + @ApiImplicitParam(name = "Environment", required = true, paramType = "Header") }) + @ApiOperation(value = "Updates a Config Policy based on given Policy Parameters.") + @RequestMapping(value = "/updateConfig", method = RequestMethod.PUT) + @ResponseBody + @Deprecated + public ResponseEntity<String> updateConfig( + @RequestBody ConfigPolicyAPIRequest configPolicyAPIRequest, + @RequestHeader(value = "ClientAuth", required = true) String clientEncoding, + @RequestHeader(value = "X-ECOMP-RequestID", required = false) String requestID) { + String response = null; + HttpStatus status = HttpStatus.UNAUTHORIZED; + // Check Permissions. + if (PDPApiAuth.checkPermissions(clientEncoding, requestID, + "updatePolicy")) { + CreateUpdateConfigPolicyService updatePolicyService = new CreateUpdateConfigPolicyService( + configPolicyAPIRequest, requestID, true); + response = updatePolicyService.getResult(); + status = updatePolicyService.getResponseCode(); + } + deprecatedCounter.incrementAndGet(); + return new ResponseEntity<>(response, status); + } + + @ApiImplicitParams({ + @ApiImplicitParam(name = "Authorization", required = true, paramType = "Header"), + @ApiImplicitParam(name = "Environment", required = true, paramType = "Header") }) + @ApiOperation(value = "Creates a Config Firewall Policy") + @RequestMapping(value = "/createFirewallConfig", method = RequestMethod.PUT) + @ResponseBody + @Deprecated + public ResponseEntity<String> createFirewallConfig( + @RequestBody ConfigFirewallPolicyAPIRequest configFirewallPolicyAPIRequest, + @RequestHeader(value = "ClientAuth", required = true) String clientEncoding, + @RequestHeader(value = "X-ECOMP-RequestID", required = false) String requestID) { + String response = null; + HttpStatus status = HttpStatus.UNAUTHORIZED; + // Check Permissions. + if (PDPApiAuth.checkPermissions(clientEncoding, requestID, + "createPolicy")) { + CreateUpdateFirewallPolicyService createFirewallPolicyService = new CreateUpdateFirewallPolicyService( + configFirewallPolicyAPIRequest, requestID, false); + response = createFirewallPolicyService.getResult(); + status = createFirewallPolicyService.getResponseCode(); + } + deprecatedCounter.incrementAndGet(); + return new ResponseEntity<>(response, status); + } + + @ApiImplicitParams({ + @ApiImplicitParam(name = "Authorization", required = true, paramType = "Header"), + @ApiImplicitParam(name = "Environment", required = true, paramType = "Header") }) + @ApiOperation(value = "Updates a Config Firewall Policy") + @RequestMapping(value = "/updateFirewallConfig", method = RequestMethod.PUT) + @ResponseBody + @Deprecated + public ResponseEntity<String> updateFirewallConfig( + @RequestBody ConfigFirewallPolicyAPIRequest configFirewallPolicyAPIRequest, + @RequestHeader(value = "ClientAuth", required = true) String clientEncoding, + @RequestHeader(value = "X-ECOMP-RequestID", required = false) String requestID) { + String response = null; + HttpStatus status = HttpStatus.UNAUTHORIZED; + // Check Permissions. + if (PDPApiAuth.checkPermissions(clientEncoding, requestID, + "updatePolicy")) { + CreateUpdateFirewallPolicyService updateFirewallPolicyService = new CreateUpdateFirewallPolicyService( + configFirewallPolicyAPIRequest, requestID, true); + response = updateFirewallPolicyService.getResult(); + status = updateFirewallPolicyService.getResponseCode(); + } + deprecatedCounter.incrementAndGet(); + return new ResponseEntity<>(response, status); + } + + @ApiOperation(value = "Gets the API Services usage Information") + @ApiIgnore + @RequestMapping(value = "/count", method = RequestMethod.GET) + public String getCount() { + return "Total Config Calls : " + configCounter + "\n" + + "Total Config calls made using Policy File Name: " + + configNameCounter + "\n" + "Total Event Calls : " + + eventCounter + "\nTotal Decision Calls: " + decisionCounter + + "\nTotal Push policy Calls: " + pushCounter + + "\nTotal Delete Policy Calls: " + deleteCounter + + "\nTotal Create Policy Calls: " + createPolicyCounter + + "\nTotal Update Policy Calls: " + updatePolicyCounter + + "\nTotal Create Dictionary Calls: " + createDictionaryCounter + + "\nTotal Update Dictionary Calls: " + updateDictionaryCounter + + "\nTotal Get Dictionary Calls: " + getDictionaryCounter + + "\nTotal PolicyEngine Import Calls: " + + policyEngineImportCounter + + "\nTotal Deprecated Policy Calls: " + deprecatedCounter + + "\nTotal Metrics Calls:" + metricCounter + + "\nTotal Notification Calls:" + notificationCounter; + } + + @ExceptionHandler({ HttpMessageNotReadableException.class }) + public ResponseEntity<String> messageNotReadableExceptionHandler( + HttpServletRequest req, HttpMessageNotReadableException exception) { + logger.error("Request not readable: {}", exception); + StringBuilder message = new StringBuilder(); + message.append(exception.getMessage()); + if (exception.getCause() != null) { + message.append(" Reason Caused: " + + exception.getCause().getMessage()); + } + return new ResponseEntity<>(message.toString(), HttpStatus.BAD_REQUEST); + } +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/models/ConfigFirewallPolicyAPIRequest.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/models/ConfigFirewallPolicyAPIRequest.java new file mode 100644 index 000000000..5c9b9efcc --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/models/ConfigFirewallPolicyAPIRequest.java @@ -0,0 +1,80 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.policy.pdp.rest.api.models; + +import io.swagger.annotations.ApiModel; + +import java.io.Serializable; + +@ApiModel +public class ConfigFirewallPolicyAPIRequest implements Serializable{ + private static final long serialVersionUID = -7460640390070215401L; + + private String policyName = null; + private String policyScope = null; + private String firewallJson = null; + private String riskType = "default"; + private String riskLevel = "5"; + private String guard = "false"; + private String ttlDate = null; + + public String getPolicyName() { + return policyName; + } + public String getPolicyScope() { + return policyScope; + } + public String getFirewallJson() { + return firewallJson; + } + public void setPolicyName(String policyName) { + this.policyName = policyName; + } + public void setPolicyScope(String policyScope) { + this.policyScope = policyScope; + } + public void setFirewallJson(String firewallJson) { + this.firewallJson = firewallJson; + } + public String getRiskType() { + return riskType; + } + public void setRiskType(String riskType) { + this.riskType = riskType; + } + public String getRiskLevel() { + return riskLevel; + } + public void setRiskLevel(String riskLevel) { + this.riskLevel = riskLevel; + } + public String getGuard() { + return guard; + } + public void setGuard(String guard) { + this.guard = guard; + } + public String getTtlDate() { + return ttlDate; + } + public void setTtlDate(String ttlDate) { + this.ttlDate = ttlDate; + } +}
\ No newline at end of file diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/models/ConfigNameRequest.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/models/ConfigNameRequest.java new file mode 100644 index 000000000..945445991 --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/models/ConfigNameRequest.java @@ -0,0 +1,39 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.policy.pdp.rest.api.models; + +import io.swagger.annotations.ApiModel; + +import java.io.Serializable; + +@ApiModel +public class ConfigNameRequest implements Serializable{ + private static final long serialVersionUID = 4487978240532425305L; + + private String policyName = null; + + public void setPolicyName(String policyName) { + this.policyName = policyName; + } + + public String getPolicyName() { + return policyName; + } +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/models/ConfigPolicyAPIRequest.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/models/ConfigPolicyAPIRequest.java new file mode 100644 index 000000000..dd40bfe5f --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/models/ConfigPolicyAPIRequest.java @@ -0,0 +1,188 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.policy.pdp.rest.api.models; + +import io.swagger.annotations.ApiModel; + +import java.io.Serializable; +import java.util.Map; + +@ApiModel +public class ConfigPolicyAPIRequest implements Serializable{ + private static final long serialVersionUID = -4103391389984557025L; + + private String policyScope = null; + private String policyName = null; + private String policyDescription = null; + private String onapName = null; + private String configName = null; + private Map<String,String> configAttributes = null; + private String configType = null; + private String body = null; + private String riskType = "default"; + private String riskLevel = "5"; + private String guard = "false"; + private String ttlDate = null; + + /** + * @return the policyScope + */ + public String getPolicyScope() { + return policyScope; + } + /** + * @return the policyName + */ + public String getPolicyName() { + return policyName; + } + /** + * @return the policyDescription + */ + public String getPolicyDescription() { + return policyDescription; + } + /** + * @return the onapName + */ + public String getOnapName() { + return onapName; + } + /** + * @return the configName + */ + public String getConfigName() { + return configName; + } + /** + * @return the configAttributes + */ + public Map<String, String> getConfigAttributes() { + return configAttributes; + } + /** + * @return the configType + */ + public String getConfigType() { + return configType; + } + /** + * @return the body + */ + public String getBody() { + return body; + } + /** + * @param policyScope the policyScope to set + */ + public void setPolicyScope(String policyScope) { + this.policyScope = policyScope; + } + /** + * @param policyName the policyName to set + */ + public void setPolicyName(String policyName) { + this.policyName = policyName; + } + /** + * @param policyDescription the policyDescription to set + */ + public void setPolicyDescription(String policyDescription) { + this.policyDescription = policyDescription; + } + /** + * @param onapName the onapName to set + */ + public void setOnapName(String onapName) { + this.onapName = onapName; + } + /** + * @param configName the configName to set + */ + public void setConfigName(String configName) { + this.configName = configName; + } + /** + * @param configAttributes the configAttributes to set + */ + public void setConfigAttributes(Map<String, String> configAttributes) { + this.configAttributes = configAttributes; + } + /** + * @param configType the configType to set + */ + public void setConfigType(String configType) { + this.configType = configType; + } + /** + * @param body the body to set + */ + public void setBody(String body) { + this.body = body; + } + /** + * @return the guard + */ + public String getGuard() { + return guard; + } + /** + * @param guard the guard to set + */ + public void setGuard(String guard) { + this.guard = guard; + } + /** + * @return the riskLevel + */ + public String getRiskLevel() { + return riskLevel; + } + /** + * @param riskLevel the riskLevel to set + */ + public void setRiskLevel(String riskLevel) { + this.riskLevel = riskLevel; + } + /** + * @return the ttlDate + */ + public String getTtlDate() { + return ttlDate; + } + /** + * @param ttlDate the ttlDate to set + */ + public void setTtlDate(String ttlDate) { + this.ttlDate = ttlDate; + } + /** + * @return the riskType + */ + public String getRiskType() { + return riskType; + } + /** + * @param riskType the riskType to set + */ + public void setRiskType(String riskType) { + this.riskType = riskType; + } +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/models/PDPResponse.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/models/PDPResponse.java new file mode 100644 index 000000000..c2dbbdef0 --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/models/PDPResponse.java @@ -0,0 +1,159 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.policy.pdp.rest.api.models; + +import java.util.Map; + +import org.onap.policy.api.DecisionResponse; +import org.onap.policy.api.PolicyConfigStatus; +import org.onap.policy.api.PolicyDecision; +import org.onap.policy.api.PolicyResponse; +import org.onap.policy.api.PolicyResponseStatus; +import org.onap.policy.api.PolicyType; +import org.onap.policy.models.APIConfigResponse; + +public class PDPResponse implements APIConfigResponse, PolicyResponse, DecisionResponse{ + private String policyConfigMessage; + private PolicyConfigStatus policyConfigStatus; + private PolicyType type; + private String config; + private String policyName; + private String policyVersion; + private Map<String, String> matchingConditions; + private Map<String, String> responseAttributes; + private Map<String, String> property; + private PolicyResponseStatus policyResponseStatus; + private String policyResponseMessage; + private Map<String,String> actionAdvised; + private Map<String,String> actionTaken; + private Map<String,String> requestAttributes; + private PolicyDecision policyDecision; + private String details; + + public void setStatus(String message, PolicyResponseStatus policyResponseStatus, PolicyConfigStatus policyConfigStatus) { + this.policyConfigMessage = message; + this.policyResponseMessage = message; + this.policyResponseStatus = policyResponseStatus; + this.policyConfigStatus = policyConfigStatus; + } + public String getConfig() { + return config; + } + public void setConfig(String config) { + this.config = config; + } + public PolicyType getType() { + return type; + } + public void setType(PolicyType type) { + this.type = type; + } + public PolicyConfigStatus getPolicyConfigStatus() { + return policyConfigStatus; + } + public void setPolicyConfigStatus(PolicyConfigStatus policyConfigStatus) { + this.policyConfigStatus = policyConfigStatus; + } + public String getPolicyConfigMessage() { + return policyConfigMessage; + } + public void setPolicyConfigMessage(String policyConfigMessage) { + this.policyConfigMessage = policyConfigMessage; + } + public Map<String, String> getProperty() { + return property; + } + public void setProperty(Map<String, String> property) { + this.property = property; + } + public String getPolicyName(){ + return policyName; + } + public void setPolicyName(String policyName){ + this.policyName = policyName; + } + public String getPolicyVersion(){ + return policyVersion; + } + public void setPolicyVersion(String policyVersion){ + this.policyVersion = policyVersion; + } + public Map<String, String> getMatchingConditions(){ + return matchingConditions; + } + public void setMatchingConditions(Map<String, String> matchingConditions){ + this.matchingConditions = matchingConditions; + } + public void setResponseAttributes(Map<String,String> responseAttributes){ + this.responseAttributes = responseAttributes; + } + public Map<String,String> getResponseAttributes(){ + return responseAttributes; + } + public void setPolicyResponseStatus(PolicyResponseStatus policyResponseStatus) { + this.policyResponseStatus = policyResponseStatus; + } + @Override + public PolicyResponseStatus getPolicyResponseStatus() { + return policyResponseStatus; + } + public void setDecision(PolicyDecision policyDecision){ + this.policyDecision = policyDecision; + } + @Override + public PolicyDecision getDecision() { + return policyDecision; + } + public void setDetails(String details){ + this.details = details; + } + @Override + public String getDetails() { + return details; + } + public void setActionAdvised(Map<String, String> actionAdvised) { + this.actionAdvised = actionAdvised; + } + @Override + public Map<String, String> getActionAdvised() { + return actionAdvised; + } + public void setActionTaken(Map<String, String> actionTaken) { + this.actionTaken = actionTaken; + } + @Override + public Map<String, String> getActionTaken() { + return actionTaken; + } + public void setRequestAttributes(Map<String, String> requestAttributes) { + this.requestAttributes = requestAttributes; + } + @Override + public Map<String, String> getRequestAttributes() { + return requestAttributes; + } + public void setPolicyResponseMessage(String policyResponseMessage) { + this.policyResponseMessage = policyResponseMessage; + } + @Override + public String getPolicyResponseMessage() { + return policyResponseMessage; + } +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/models/PolicyConfig.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/models/PolicyConfig.java new file mode 100644 index 000000000..391ef6c8a --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/models/PolicyConfig.java @@ -0,0 +1,95 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.policy.pdp.rest.api.models; + +import io.swagger.annotations.ApiModel; + +import java.util.Map; + +import org.onap.policy.api.PolicyConfigStatus; +import org.onap.policy.api.PolicyType; +import org.onap.policy.models.APIConfigResponse; + +@ApiModel +public class PolicyConfig implements APIConfigResponse{ + private String policyConfigMessage; + private PolicyConfigStatus policyConfigStatus; + private PolicyType type; + private String config; + private String policyName; + private String policyVersion; + private Map<String, String> matchingConditions; + private Map<String, String> responseAttributes; + private Map<String, String> property; + public String getConfig() { + return config; + } + public void setConfig(String config) { + this.config = config; + } + public PolicyType getType() { + return type; + } + public void setType(PolicyType type) { + this.type = type; + } + public PolicyConfigStatus getPolicyConfigStatus() { + return policyConfigStatus; + } + public void setPolicyConfigStatus(PolicyConfigStatus policyConfigStatus) { + this.policyConfigStatus = policyConfigStatus; + } + public String getPolicyConfigMessage() { + return policyConfigMessage; + } + public void setPolicyConfigMessage(String policyConfigMessage) { + this.policyConfigMessage = policyConfigMessage; + } + public Map<String, String> getProperty() { + return property; + } + public void setProperty(Map<String, String> property) { + this.property = property; + } + public String getPolicyName(){ + return policyName; + } + public void setPolicyName(String policyName){ + this.policyName = policyName; + } + public String getPolicyVersion(){ + return policyVersion; + } + public void setPolicyVersion(String policyVersion){ + this.policyVersion = policyVersion; + } + public Map<String, String> getMatchingConditions(){ + return matchingConditions; + } + public void setMatchingConditions(Map<String, String> matchingConditions){ + this.matchingConditions = matchingConditions; + } + public void setResponseAttributes(Map<String,String> responseAttributes){ + this.responseAttributes = responseAttributes; + } + public Map<String,String> getResponseAttributes(){ + return responseAttributes; + } +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/ActionPolicyService.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/ActionPolicyService.java new file mode 100644 index 000000000..66920e0db --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/ActionPolicyService.java @@ -0,0 +1,105 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.policy.pdp.rest.api.services; + +import java.util.Map; + +import org.onap.policy.api.AttributeType; +import org.onap.policy.api.PolicyException; +import org.onap.policy.api.PolicyParameters; +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; +import org.onap.policy.xacml.api.XACMLErrorConstants; +import org.onap.policy.xacml.std.pap.StdPAPPolicy; + +/** + * Action Policy Implementation. + * + * @version 0.1 + */ +public class ActionPolicyService { + private static final Logger LOGGER = FlexLogger.getLogger(ActionPolicyService.class.getName()); + private PAPServices papServices = null; + + private PolicyParameters policyParameters = null; + private String message = null; + private String policyName = null; + private String policyScope = null; + private Map<String,String> componentAttributes = null; + private String actionAttribute = null; + private String actionPerformer = null; + + public ActionPolicyService(String policyScope, String policyName, + PolicyParameters policyParameters) { + this.policyParameters = policyParameters; + this.policyName = policyName; + this.policyScope = policyScope; + papServices = new PAPServices(); + } + + public Boolean getValidation() { + if(policyParameters.getAttributes()==null || policyParameters.getAttributes().isEmpty()){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No Component Attributes given."; + return false; + } + componentAttributes = policyParameters.getAttributes().get(AttributeType.MATCHING); + if (componentAttributes==null||componentAttributes.isEmpty()){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No Component Attributes given."; + return false; + } + actionAttribute = policyParameters.getActionAttribute(); + if (actionAttribute==null||actionAttribute.trim().isEmpty()){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No Action Attribute given."; + return false; + } + actionPerformer = policyParameters.getActionPerformer(); + if (actionPerformer==null||actionPerformer.trim().isEmpty()){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No Action Performer given."; + return false; + } + if(!"PEP".equalsIgnoreCase(actionPerformer)&& !"PDP".equalsIgnoreCase(actionPerformer)){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "Invalid Action Performer given."; + return false; + } + return true; + } + + public String getMessage() { + return message; + } + + public String getResult(boolean updateFlag) throws PolicyException { + String response = null; + String operation = null; + if (updateFlag){ + operation = "update"; + } else { + operation = "create"; + } + // Create Policy + StdPAPPolicy newPAPPolicy = new StdPAPPolicy(policyName, policyParameters.getPolicyDescription(), + componentAttributes, policyParameters.getDynamicRuleAlgorithmLabels(), policyParameters.getDynamicRuleAlgorithmFunctions(), + policyParameters.getDynamicRuleAlgorithmField1(), policyParameters.getDynamicRuleAlgorithmField2(), actionPerformer, actionAttribute, updateFlag, policyScope, 0); + // send Json to PAP + response = (String) papServices.callPAP(newPAPPolicy, new String[] {"operation="+operation, "apiflag=api", "policyType=Action"}, policyParameters.getRequestID(), "Action"); + LOGGER.info(response); + return response; + } +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/BRMSParamPolicyService.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/BRMSParamPolicyService.java new file mode 100644 index 000000000..dd2bd452e --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/BRMSParamPolicyService.java @@ -0,0 +1,96 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.policy.pdp.rest.api.services; + +import java.util.Map; + +import org.onap.policy.api.AttributeType; +import org.onap.policy.api.PolicyException; +import org.onap.policy.api.PolicyParameters; +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; +import org.onap.policy.pdp.rest.api.utils.PolicyApiUtils; +import org.onap.policy.xacml.api.XACMLErrorConstants; +import org.onap.policy.xacml.std.pap.StdPAPPolicy; + +/** + * BRMS Param Policy Implementation. + * + * @version 0.1 + */ +public class BRMSParamPolicyService{ + private static final Logger LOGGER = FlexLogger.getLogger(BRMSParamPolicyService.class.getName()); + private PAPServices papServices = null; + + private PolicyParameters policyParameters = null; + private String message = null; + private String policyName = null; + private String policyScope = null; + private String date = null; + private Map<AttributeType, Map<String, String>> drlRuleAndUIParams = null; + + public BRMSParamPolicyService(String policyName, String policyScope, + PolicyParameters policyParameters, String date) { + this.policyParameters = policyParameters; + this.policyName = policyName; + this.policyScope = policyScope; + this.date = date; + papServices = new PAPServices(); + } + + public Boolean getValidation() { + boolean levelCheck = PolicyApiUtils.isNumeric(policyParameters.getRiskLevel()); + if(!levelCheck){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "Incorrect Risk Level given."; + return false; + } + drlRuleAndUIParams = policyParameters.getAttributes(); + if(drlRuleAndUIParams==null || drlRuleAndUIParams.isEmpty()){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No Rule Attributes given."; + return false; + } + return true; + } + + public String getMessage() { + return message; + } + + public String getResult(boolean updateFlag) throws PolicyException { + String response = null; + String operation = null; + if (updateFlag){ + operation = "update"; + } else { + operation = "create"; + } + // Create Policy + StdPAPPolicy newPAPPolicy = new StdPAPPolicy("BRMS_Param",policyName, policyParameters.getPolicyDescription(), + "BRMS_PARAM_RULE",updateFlag,policyScope, + drlRuleAndUIParams.get(AttributeType.MATCHING), 0, "DROOLS", + null, drlRuleAndUIParams.get(AttributeType.RULE), policyParameters.getRiskLevel(), + policyParameters.getRiskType(), String.valueOf(policyParameters.getGuard()), date, policyParameters.getControllerName(), policyParameters.getDependencyNames()); + // Send JSON to PAP + response = (String) papServices.callPAP(newPAPPolicy, new String[] {"operation="+operation, "apiflag=api", "policyType=Config"}, policyParameters.getRequestID(), "ConfigBrmsParam"); + LOGGER.info(response); + return response; + } + +}
\ No newline at end of file diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/BRMSRawPolicyService.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/BRMSRawPolicyService.java new file mode 100644 index 000000000..ea17529ba --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/BRMSRawPolicyService.java @@ -0,0 +1,106 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.policy.pdp.rest.api.services; + +import java.util.Map; + +import org.onap.policy.api.AttributeType; +import org.onap.policy.api.PolicyException; +import org.onap.policy.api.PolicyParameters; +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; +import org.onap.policy.pdp.rest.api.utils.PolicyApiUtils; +import org.onap.policy.utils.PolicyUtils; +import org.onap.policy.xacml.api.XACMLErrorConstants; +import org.onap.policy.xacml.std.pap.StdPAPPolicy; + +/** + * BRMS RAW Policy Implementation. + * + * @version 0.1 + */ +public class BRMSRawPolicyService{ + private static Logger LOGGER = FlexLogger.getLogger(BRMSRawPolicyService.class.getName()); + private static PAPServices papServices = null; + + private PolicyParameters policyParameters = null; + private String message = null; + private String policyName = null; + private String policyScope = null; + private String date = null; + private boolean levelCheck = false; + private String brmsRawBody = null; + + public BRMSRawPolicyService(String policyName, String policyScope, + PolicyParameters policyParameters, String date) { + this.policyParameters = policyParameters; + this.policyName = policyName; + this.policyScope = policyScope; + this.date = date; + papServices = new PAPServices(); + } + + public Boolean getValidation() { + brmsRawBody = policyParameters.getConfigBody(); + if(brmsRawBody==null || brmsRawBody.trim().isEmpty()){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE+ " No Rule Body given"; + return false; + } + message = PolicyUtils.brmsRawValidate(brmsRawBody); + if(message.contains("[ERR")){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "Raw rule given is invalid" +message; + return false; + } + levelCheck = PolicyApiUtils.isNumeric(policyParameters.getRiskLevel()); + if(!levelCheck){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "Incorrect Risk Level given."; + return false; + } + return true; + } + + public String getMessage() { + return message; + } + + public String getResult(boolean updateFlag) throws PolicyException { + String response = null; + String operation = null; + if (updateFlag){ + operation = "update"; + } else { + operation = "create"; + } + Map<String,String> ruleAttributes = null; + if(policyParameters.getAttributes()!=null){ + ruleAttributes = policyParameters.getAttributes().get(AttributeType.RULE); + } + // Create Policy + StdPAPPolicy newPAPPolicy = new StdPAPPolicy("BRMS_Raw",policyName,policyParameters.getPolicyDescription(), + "BRMS_RAW_RULE",updateFlag,policyScope, ruleAttributes, 0, "DROOLS", + brmsRawBody, policyParameters.getRiskLevel(), + policyParameters.getRiskType(), String.valueOf(policyParameters.getGuard()), date, policyParameters.getControllerName(), policyParameters.getDependencyNames()); + // Send JSON to PAP + response = (String) papServices.callPAP(newPAPPolicy, new String[] {"operation="+operation, "apiflag=api", "policyType=Config"}, policyParameters.getRequestID(), "ConfigBrmsRaw"); + LOGGER.info(response); + return response; + } + +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/ClosedLoopFaultPolicyService.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/ClosedLoopFaultPolicyService.java new file mode 100644 index 000000000..5817d7410 --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/ClosedLoopFaultPolicyService.java @@ -0,0 +1,121 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.policy.pdp.rest.api.services; + +import javax.json.JsonException; +import javax.json.JsonObject; + +import org.onap.policy.api.PolicyException; +import org.onap.policy.api.PolicyParameters; +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; +import org.onap.policy.pdp.rest.api.utils.PolicyApiUtils; +import org.onap.policy.xacml.api.XACMLErrorConstants; +import org.onap.policy.xacml.std.pap.StdPAPPolicy; + +/** + * Closed Loop Fault Policy Implementation. + * + * @version 0.1 + */ +public class ClosedLoopFaultPolicyService{ + private static final Logger LOGGER = FlexLogger.getLogger(ClosedLoopFaultPolicyService.class.getName()); + private PAPServices papServices = null; + + private PolicyParameters policyParameters = null; + private String message = null; + private String policyName = null; + private String policyScope = null; + private String date = null; + private JsonObject configBody = null; + + public ClosedLoopFaultPolicyService(String policyName, String policyScope, + PolicyParameters policyParameters, String date) { + this.policyParameters = policyParameters; + this.policyName = policyName; + this.policyScope = policyScope; + this.date = date; + papServices = new PAPServices(); + } + + public Boolean getValidation() { + if(policyParameters.getConfigBody()==null){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE+ " No Config Body Present"; + return false; + } + if(!PolicyApiUtils.validateNONASCIICharactersAndAllowSpaces(policyParameters.getConfigBody())){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE+ " improper JSON object : " + policyParameters.getConfigBody(); + return false; + } + try{ + configBody = PolicyApiUtils.stringToJsonObject(policyParameters.getConfigBody()); + } catch(JsonException| IllegalStateException e){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE+ " improper JSON object : " + policyParameters.getConfigBody(); + LOGGER.error("Json Parse Exception.", e); + return false; + } + return true; + } + + public String getMessage() { + return message; + } + + public String getResult(boolean updateFlag) throws PolicyException { + String response = null; + String operation = null; + String oldPolicyName = null; + if (updateFlag){ + operation = "update"; + if (policyName.endsWith("_Draft")) { + oldPolicyName = policyName + "_Draft.1"; + } + } else { + operation = "create"; + } + // get values and attributes from the JsonObject + if(!configBody.containsKey("onapname")){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No Onap Name given."; + LOGGER.error(message); + return message; + } + String onapName = configBody.get("onapname").toString().trim().replace("\"", ""); + if (onapName==null||onapName.trim().isEmpty()){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No Onap Name given."; + LOGGER.error(message); + return message; + } + boolean levelCheck = PolicyApiUtils.isNumeric(policyParameters.getRiskLevel()); + if (!levelCheck){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "Incorrect Risk Level given."; + LOGGER.error(message); + return message; + } + String jsonBody = configBody.toString(); + // Create Policy. + StdPAPPolicy newPAPPolicy = new StdPAPPolicy("ClosedLoop_Fault", policyName, policyParameters.getPolicyDescription(), onapName, + jsonBody, false, oldPolicyName, null, updateFlag, policyScope, 0, policyParameters.getRiskLevel(), + policyParameters.getRiskType(), String.valueOf(policyParameters.getGuard()), date); + //send JSON object to PAP + response = (String) papServices.callPAP(newPAPPolicy, new String[] {"operation="+operation, "apiflag=api", "policyType=Config"}, policyParameters.getRequestID(), "ConfigClosedLoop"); + return response; + } + +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/ClosedLoopPMPolicyService.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/ClosedLoopPMPolicyService.java new file mode 100644 index 000000000..74c4bd71d --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/ClosedLoopPMPolicyService.java @@ -0,0 +1,122 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.policy.pdp.rest.api.services; + +import javax.json.JsonException; +import javax.json.JsonObject; + +import org.onap.policy.api.PolicyException; +import org.onap.policy.api.PolicyParameters; +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; +import org.onap.policy.pdp.rest.api.utils.PolicyApiUtils; +import org.onap.policy.xacml.api.XACMLErrorConstants; +import org.onap.policy.xacml.std.pap.StdPAPPolicy; + +/** + * Closed Loop PM policy Implementation. + * + * @version 0.1 + */ +public class ClosedLoopPMPolicyService{ + private static final Logger LOGGER = FlexLogger.getLogger(ClosedLoopPMPolicyService.class.getName()); + + private PAPServices papServices = null; + private PolicyParameters policyParameters = null; + private String message = null; + private String policyName = null; + private String policyScope = null; + private String date = null; + private JsonObject configBody = null; + + public ClosedLoopPMPolicyService(String policyName, String policyScope, + PolicyParameters policyParameters, String date) { + this.policyParameters = policyParameters; + this.policyName = policyName; + this.policyScope = policyScope; + this.date = date; + papServices = new PAPServices(); + } + + public Boolean getValidation() { + if(policyParameters.getConfigBody()==null){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE+ " No Config Body Present"; + return false; + } + if(!PolicyApiUtils.validateNONASCIICharactersAndAllowSpaces(policyParameters.getConfigBody())){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE+ " improper JSON object : " + policyParameters.getConfigBody(); + return false; + } + try{ + configBody = PolicyApiUtils.stringToJsonObject(policyParameters.getConfigBody()); + } catch(JsonException| IllegalStateException e){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE+ " improper JSON object : " + policyParameters.getConfigBody(); + LOGGER.error("Error during parsing JSON config body for Closed loop PM policy " , e); + return false; + } + return true; + } + + public String getMessage() { + return message; + } + + public String getResult(boolean updateFlag) throws PolicyException{ + String response = null; + String operation = null; + if (updateFlag){ + operation = "update"; + } else { + operation = "create"; + } + // get values and attributes from the JsonObject + if(!configBody.containsKey("onapname")){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No Onap Name given."; + LOGGER.error(message); + return message; + } + if(!configBody.containsKey("serviceTypePolicyName")){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No Service Type Policy Name given."; + LOGGER.error(message); + return message; + } + String onapName = configBody.get("onapname").toString().trim().replace("\"", ""); + if (onapName==null||onapName.trim().isEmpty()){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No Onap Name given."; + LOGGER.error(message); + return message; + } + boolean levelCheck = PolicyApiUtils.isNumeric(policyParameters.getRiskLevel()); + if (!levelCheck){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "Incorrect Risk Level given."; + LOGGER.error(message); + return message; + } + String jsonBody = configBody.toString(); + String serviceType = configBody.get("serviceTypePolicyName").toString().replace("\"", ""); + // Create Policy. + StdPAPPolicy newPAPPolicy = new StdPAPPolicy("ClosedLoop_PM", policyName, policyParameters.getPolicyDescription(), onapName, + jsonBody, false, null, serviceType, updateFlag, policyScope, 0, policyParameters.getRiskLevel(), + policyParameters.getRiskType(), String.valueOf(policyParameters.getGuard()), date); + //send JSON object to PAP + response = (String) papServices.callPAP(newPAPPolicy, new String[] {"operation="+operation, "apiflag=api", "policyType=Config"}, policyParameters.getRequestID(), "ConfigClosedLoop"); + return response; + } +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/ConfigPolicyService.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/ConfigPolicyService.java new file mode 100644 index 000000000..c8d3d74d1 --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/ConfigPolicyService.java @@ -0,0 +1,136 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.policy.pdp.rest.api.services; + +import java.util.Map; + +import org.onap.policy.api.AttributeType; +import org.onap.policy.api.PolicyException; +import org.onap.policy.api.PolicyParameters; +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; +import org.onap.policy.pdp.rest.api.utils.PolicyApiUtils; +import org.onap.policy.utils.PolicyUtils; +import org.onap.policy.xacml.api.XACMLErrorConstants; +import org.onap.policy.xacml.std.pap.StdPAPPolicy; + +/** + * Config Base Policy Implementation. + * + * @version 0.1 + */ +public class ConfigPolicyService { + private static final Logger LOGGER = FlexLogger.getLogger(ConfigPolicyService.class.getName()); + private PAPServices papServices = null; + + private PolicyParameters policyParameters = null; + private String message = null; + private String policyName = null; + private String policyScope = null; + private String date = null; + private String onapName = null; + private String configName = null; + + public ConfigPolicyService(String policyName, String policyScope, + PolicyParameters policyParameters, String date) { + this.policyParameters = policyParameters; + this.policyName = policyName; + this.policyScope = policyScope; + this.date = date; + papServices = new PAPServices(); + } + + public Boolean getValidation() { + if(policyParameters.getConfigBody()==null || policyParameters.getConfigBody().trim().isEmpty()){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE+ "No Config Body given."; + return false; + } + if(policyParameters.getConfigBodyType()==null){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE+ "No Config Body Type given."; + return false; + } + boolean levelCheck = false; + levelCheck = PolicyApiUtils.isNumeric(policyParameters.getRiskLevel()); + if (!levelCheck){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "Incorrect Risk Level given."; + return false; + } + onapName = policyParameters.getOnapName(); + configName = policyParameters.getConfigName(); + if(onapName==null || onapName.trim().isEmpty()){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No ONAP Name given."; + return false; + } + if(configName==null || configName.trim().isEmpty()){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No Config Name given."; + return false; + } + message = PolicyUtils.emptyPolicyValidator(onapName); + if(!message.contains("success")){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE+ message; + return false; + } + message = PolicyUtils.emptyPolicyValidator(configName); + if(!message.contains("success")){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE+ message; + return false; + } + return true; + } + + public String getMessage() { + return message; + } + + public String getResult(boolean updateFlag) throws PolicyException { + String response = null; + String operation = null; + if (updateFlag){ + operation = "update"; + } else { + operation = "create"; + } + String configType = policyParameters.getConfigBodyType().toString(); + String body = policyParameters.getConfigBody(); + String configBody = null; + //check body for JSON form and remove single quotes if present + if ("JSON".equalsIgnoreCase(configType)) { + if (body.contains("'")) { + configBody = body.replace("'", "\""); + } else { + configBody = body; + } + } else { + configBody = body; + } + Map<String,String> configAttributes = null; + if(policyParameters.getAttributes()!=null){ + configAttributes = policyParameters.getAttributes().get(AttributeType.MATCHING); + } + // create Policy. + StdPAPPolicy newPAPPolicy = new StdPAPPolicy("Base", policyName, policyParameters.getPolicyDescription(), onapName, configName, configAttributes, configType, + configBody, updateFlag, policyScope,0, policyParameters.getRiskLevel(),policyParameters.getRiskType(), String.valueOf(policyParameters.getGuard()), date); + // Send Json to PAP. + response = (String) papServices.callPAP(newPAPPolicy, new String[] {"operation="+operation, "apiflag=api", "policyType=Config"}, policyParameters.getRequestID(), "Config"); + LOGGER.info(response); + return response; + } + +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/CreateUpdateConfigPolicyService.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/CreateUpdateConfigPolicyService.java new file mode 100644 index 000000000..d8cca2bb9 --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/CreateUpdateConfigPolicyService.java @@ -0,0 +1,118 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.policy.pdp.rest.api.services; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.HashMap; +import java.util.Map; + +import org.onap.policy.api.AttributeType; +import org.onap.policy.api.PolicyClass; +import org.onap.policy.api.PolicyConfigType; +import org.onap.policy.api.PolicyException; +import org.onap.policy.api.PolicyParameters; +import org.onap.policy.api.PolicyType; +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; +import org.onap.policy.pdp.rest.api.models.ConfigPolicyAPIRequest; +import org.onap.policy.xacml.api.XACMLErrorConstants; +import org.springframework.http.HttpStatus; + +public class CreateUpdateConfigPolicyService { + private static final Logger LOGGER = FlexLogger.getLogger(CreateUpdateConfigPolicyService.class.getName()); + + private String response = null; + private HttpStatus status = HttpStatus.BAD_REQUEST; + + public CreateUpdateConfigPolicyService( + ConfigPolicyAPIRequest configPolicyAPIRequest, String requestID, + boolean updateFlag) { + try{ + run(configPolicyAPIRequest, requestID, updateFlag); + }catch(PolicyException e){ + response = XACMLErrorConstants.ERROR_DATA_ISSUE + e; + status = HttpStatus.BAD_REQUEST; + } + } + + private void run(ConfigPolicyAPIRequest configPolicyAPIRequest, + String requestID, boolean updateFlag) throws PolicyException{ + PolicyParameters policyParameters = new PolicyParameters(); + policyParameters.setPolicyClass(PolicyClass.Config); + policyParameters.setPolicyConfigType(PolicyConfigType.Base); + if(configPolicyAPIRequest.getPolicyScope()==null|| configPolicyAPIRequest.getPolicyScope().trim().isEmpty()){ + String message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No Policy Scope given."; + LOGGER.error(message); + throw new PolicyException(message); + } + if(configPolicyAPIRequest.getPolicyName()==null|| configPolicyAPIRequest.getPolicyName().trim().isEmpty()){ + String message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No Policy Name given."; + LOGGER.error(message); + throw new PolicyException(message); + } + policyParameters.setPolicyName(configPolicyAPIRequest.getPolicyScope()+"."+configPolicyAPIRequest.getPolicyName()); + policyParameters.setPolicyDescription(configPolicyAPIRequest.getPolicyDescription()); + policyParameters.setOnapName(configPolicyAPIRequest.getOnapName()); + policyParameters.setConfigName(configPolicyAPIRequest.getConfigName()); + Map<AttributeType, Map<String, String>> attributes = new HashMap<>(); + attributes.put(AttributeType.MATCHING, configPolicyAPIRequest.getConfigAttributes()); + policyParameters.setAttributes(attributes); + if(configPolicyAPIRequest.getConfigType()==null){ + String message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No Policy ConfigType given."; + LOGGER.error(message); + throw new PolicyException(message); + } + try{ + policyParameters.setConfigBodyType(PolicyType.valueOf(configPolicyAPIRequest.getConfigType())); + }catch(IllegalArgumentException e){ + String message = XACMLErrorConstants.ERROR_DATA_ISSUE + "Improper ConfigType given."; + LOGGER.error(message, e); + throw new PolicyException(message); + } + policyParameters.setConfigBody(configPolicyAPIRequest.getBody()); + policyParameters.setRiskLevel(configPolicyAPIRequest.getRiskLevel()); + policyParameters.setRiskType(configPolicyAPIRequest.getRiskType()); + policyParameters.setGuard(Boolean.parseBoolean(configPolicyAPIRequest.getGuard())); + if(configPolicyAPIRequest.getTtlDate()==null){ + LOGGER.warn("No TTL date given "); + policyParameters.setTtlDate(null); + }else{ + try { + policyParameters.setTtlDate(new SimpleDateFormat("dd-MM-yyyy").parse(configPolicyAPIRequest.getTtlDate())); + } catch (ParseException e) { + LOGGER.warn("Error Parsing date given " + configPolicyAPIRequest.getTtlDate(), e); + policyParameters.setTtlDate(null); + } + } + CreateUpdatePolicyService createUpdatePolicyService = new CreateUpdatePolicyServiceImpl(policyParameters, requestID, updateFlag); + status = createUpdatePolicyService.getResponseCode(); + response = createUpdatePolicyService.getResult(); + } + + public String getResult() { + return response; + } + + public HttpStatus getResponseCode() { + return status; + } + +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/CreateUpdateDictionaryService.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/CreateUpdateDictionaryService.java new file mode 100644 index 000000000..9d2577426 --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/CreateUpdateDictionaryService.java @@ -0,0 +1,153 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.policy.pdp.rest.api.services; + +import java.io.ByteArrayInputStream; +import java.util.UUID; + +import javax.json.JsonException; +import javax.json.JsonObject; + +import org.onap.policy.api.DictionaryParameters; +import org.onap.policy.api.PolicyException; +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; +import org.onap.policy.pdp.rest.api.utils.PolicyApiUtils; +import org.onap.policy.xacml.api.XACMLErrorConstants; +import org.springframework.http.HttpStatus; + +public class CreateUpdateDictionaryService { + private static final Logger LOGGER = FlexLogger.getLogger(CreateUpdateDictionaryService.class.getName()); + + private String dictionaryResult = null; + private HttpStatus status = HttpStatus.BAD_REQUEST; + private String message = null; + private Boolean updateFlag = false; + private DictionaryParameters dictionaryParameters = null; + + public CreateUpdateDictionaryService( + DictionaryParameters dictionaryParameters, String requestID, + boolean updateFlag) { + this.updateFlag = updateFlag; + this.dictionaryParameters = dictionaryParameters; + if(dictionaryParameters.getRequestID()==null){ + UUID requestUUID = null; + if (requestID != null && !requestID.isEmpty()) { + try { + requestUUID = UUID.fromString(requestID); + } catch (IllegalArgumentException e) { + requestUUID = UUID.randomUUID(); + LOGGER.info("Generated Random UUID: " + requestUUID.toString(),e); + } + }else{ + requestUUID = UUID.randomUUID(); + LOGGER.info("Generated Random UUID: " + requestUUID.toString()); + } + this.dictionaryParameters.setRequestID(requestUUID); + } + try{ + run(); + specialCheck(); + }catch(PolicyException e){ + dictionaryResult = XACMLErrorConstants.ERROR_DATA_ISSUE + e; + status = HttpStatus.BAD_REQUEST; + } + } + + private void specialCheck() { + if(dictionaryResult== null || dictionaryResult.contains("BAD REQUEST")||dictionaryResult.contains("PE300")){ + status = HttpStatus.BAD_REQUEST; + } else if (dictionaryResult.contains("Policy Exist Error")) { + status = HttpStatus.CONFLICT; + } else if (dictionaryResult.contains("PE200")){ + status = HttpStatus.INTERNAL_SERVER_ERROR; + } + } + + private void run() throws PolicyException{ + // Check Validation. + if(!getValidation()){ + LOGGER.error(message); + throw new PolicyException(message); + } + // Get Result. + try{ + status = HttpStatus.OK; + dictionaryResult = processResult(); + }catch (Exception e){ + LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + e); + status = HttpStatus.BAD_REQUEST; + throw new PolicyException(e); + } + } + + private String processResult() throws PolicyException{ + String operation = null; + if (updateFlag){ + operation = "update"; + } else { + operation = "create"; + } + JsonObject json = null; + try{ + json = PolicyApiUtils.stringToJsonObject(dictionaryParameters.getDictionaryJson()); + } catch(JsonException| IllegalStateException e){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE+ " improper Dictionary JSON object : " + dictionaryParameters.getDictionaryJson(); + LOGGER.error(message, e); + return message; + } + String dictionaryFields = json.toString(); + PAPServices papServices = new PAPServices(); + return (String) papServices.callPAP(new ByteArrayInputStream(dictionaryFields.getBytes()), new String[] {"operation="+operation, "apiflag=api", "dictionaryType="+dictionaryParameters.getDictionary()}, dictionaryParameters.getRequestID(), "dictionaryItem"); + } + + private boolean getValidation() { + if(dictionaryParameters==null){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "Dictionary Parameters are not given."; + return false; + } + if(dictionaryParameters.getDictionaryType()==null || dictionaryParameters.getDictionaryType().toString().trim().isEmpty()){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No Dictionary Type given."; + return false; + } + if(dictionaryParameters.getDictionary()==null || dictionaryParameters.getDictionary().trim().isEmpty()){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No Dictionary given."; + return false; + } + if(dictionaryParameters.getDictionaryJson()==null || dictionaryParameters.getDictionaryJson().isEmpty()){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No Dictionary JSON given."; + return false; + } + if (updateFlag && "MicroServiceDictionary".equalsIgnoreCase(dictionaryParameters.getDictionary())&& !dictionaryParameters.getDictionaryJson().contains("initialFields")){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "Mising the required field initialFields."; + return false; + } + return true; + } + + public String getResult() { + return dictionaryResult; + } + + public HttpStatus getResponseCode() { + return status; + } + +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/CreateUpdateFirewallPolicyService.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/CreateUpdateFirewallPolicyService.java new file mode 100644 index 000000000..d4d686a13 --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/CreateUpdateFirewallPolicyService.java @@ -0,0 +1,92 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.policy.pdp.rest.api.services; + +import java.text.ParseException; +import java.text.SimpleDateFormat; + +import org.onap.policy.api.PolicyClass; +import org.onap.policy.api.PolicyConfigType; +import org.onap.policy.api.PolicyException; +import org.onap.policy.api.PolicyParameters; +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; +import org.onap.policy.pdp.rest.api.models.ConfigFirewallPolicyAPIRequest; +import org.onap.policy.xacml.api.XACMLErrorConstants; +import org.springframework.http.HttpStatus; + +public class CreateUpdateFirewallPolicyService { + private static final Logger LOGGER = FlexLogger.getLogger(CreateUpdateFirewallPolicyService.class.getName()); + + private String response = null; + private HttpStatus status = HttpStatus.BAD_REQUEST; + + public CreateUpdateFirewallPolicyService( + ConfigFirewallPolicyAPIRequest configFirewallPolicyAPIRequest, + String requestID, boolean updateFlag) { + try{ + run(configFirewallPolicyAPIRequest, requestID, updateFlag); + }catch(PolicyException e){ + response = XACMLErrorConstants.ERROR_DATA_ISSUE + e; + status = HttpStatus.BAD_REQUEST; + } + } + + private void run( + ConfigFirewallPolicyAPIRequest configFirewallPolicyAPIRequest, + String requestID, boolean updateFlag) throws PolicyException{ + PolicyParameters policyParameters = new PolicyParameters(); + policyParameters.setPolicyClass(PolicyClass.Config); + policyParameters.setPolicyConfigType(PolicyConfigType.Firewall); + if(configFirewallPolicyAPIRequest.getPolicyScope()==null|| configFirewallPolicyAPIRequest.getPolicyScope().trim().isEmpty()){ + String message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No Policy Scope given."; + LOGGER.error(message); + throw new PolicyException(message); + } + if(configFirewallPolicyAPIRequest.getPolicyName()==null|| configFirewallPolicyAPIRequest.getPolicyName().trim().isEmpty()){ + String message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No Policy Name given."; + LOGGER.error(message); + throw new PolicyException(message); + } + policyParameters.setPolicyName(configFirewallPolicyAPIRequest.getPolicyScope()+"."+configFirewallPolicyAPIRequest.getPolicyName()); + policyParameters.setConfigBody(configFirewallPolicyAPIRequest.getFirewallJson()); + policyParameters.setRiskLevel(configFirewallPolicyAPIRequest.getRiskLevel()); + policyParameters.setRiskType(configFirewallPolicyAPIRequest.getRiskType()); + policyParameters.setGuard(Boolean.parseBoolean(configFirewallPolicyAPIRequest.getGuard())); + try { + policyParameters.setTtlDate(new SimpleDateFormat("dd-MM-yyyy").parse(configFirewallPolicyAPIRequest.getTtlDate())); + } catch (NullPointerException | ParseException e) { + LOGGER.warn("Error Parsing date given " + configFirewallPolicyAPIRequest.getTtlDate(), e); + policyParameters.setTtlDate(null); + } + CreateUpdatePolicyService createUpdatePolicyService = new CreateUpdatePolicyServiceImpl(policyParameters, requestID, updateFlag); + status = createUpdatePolicyService.getResponseCode(); + response = createUpdatePolicyService.getResult(); + } + + public String getResult() { + return response; + } + + public HttpStatus getResponseCode() { + return status; + } + +}
\ No newline at end of file diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/CreateUpdatePolicyService.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/CreateUpdatePolicyService.java new file mode 100644 index 000000000..0ff5f4a0a --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/CreateUpdatePolicyService.java @@ -0,0 +1,35 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.policy.pdp.rest.api.services; + +import org.onap.policy.api.PolicyException; +import org.springframework.http.HttpStatus; + +public interface CreateUpdatePolicyService { + + public void run() throws PolicyException; + + public String processResult() throws PolicyException; + + public String getResult(); + + public HttpStatus getResponseCode(); + +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/CreateUpdatePolicyServiceImpl.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/CreateUpdatePolicyServiceImpl.java new file mode 100644 index 000000000..945cdba8b --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/CreateUpdatePolicyServiceImpl.java @@ -0,0 +1,293 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.policy.pdp.rest.api.services; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.UUID; + +import org.onap.policy.api.PolicyException; +import org.onap.policy.api.PolicyParameters; +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; +import org.onap.policy.pdp.rest.api.utils.PolicyApiUtils; +import org.onap.policy.utils.PolicyUtils; +import org.onap.policy.xacml.api.XACMLErrorConstants; +import org.springframework.http.HttpStatus; + +public class CreateUpdatePolicyServiceImpl implements CreateUpdatePolicyService { + private static final Logger LOGGER = FlexLogger.getLogger(CreateUpdatePolicyServiceImpl.class.getName()); + + private String policyResult = null; + private HttpStatus status = HttpStatus.BAD_REQUEST; + private Boolean updateFlag = false; + private String message = null; + private PolicyParameters policyParameters = new PolicyParameters(); + private String policyName = null; + private String policyScope = null; + private String date = null; + + public CreateUpdatePolicyServiceImpl(PolicyParameters policyParameters, + String requestID, boolean updateFlag) { + this.updateFlag = updateFlag; + this.policyParameters = policyParameters; + if(policyParameters.getRequestID()==null){ + UUID requestUUID = null; + if (requestID != null && !requestID.isEmpty()) { + try { + requestUUID = UUID.fromString(requestID); + } catch (IllegalArgumentException e) { + requestUUID = UUID.randomUUID(); + LOGGER.info("Generated Random UUID: " + requestUUID.toString(), e); + } + }else{ + requestUUID = UUID.randomUUID(); + LOGGER.info("Generated Random UUID: " + requestUUID.toString()); + } + this.policyParameters.setRequestID(requestUUID); + } + try{ + run(); + specialCheck(); + }catch(PolicyException e){ + policyResult = XACMLErrorConstants.ERROR_DATA_ISSUE + e; + status = HttpStatus.BAD_REQUEST; + } + } + + public void run() throws PolicyException{ + // Check Validation. + if(!getValidation()){ + LOGGER.error(message); + throw new PolicyException(message); + } + // Get Result. + try{ + status = HttpStatus.OK; + policyResult = processResult(); + }catch (Exception e){ + LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + e); + status = HttpStatus.BAD_REQUEST; + throw new PolicyException(e); + } + } + + @SuppressWarnings("incomplete-switch") + public String processResult() throws PolicyException{ + String response = null; + if(policyParameters.getPolicyConfigType()!=null){ + // This is a Config Type Policy. + switch(policyParameters.getPolicyConfigType()){ + case BRMS_PARAM: + BRMSParamPolicyService bRMSParamPolicyService = new BRMSParamPolicyService(policyName, policyScope, policyParameters, date); + // Check Validation. + if(!bRMSParamPolicyService.getValidation()){ + LOGGER.error(bRMSParamPolicyService.getMessage()); + status = HttpStatus.BAD_REQUEST; + return bRMSParamPolicyService.getMessage(); + } + // Get Result. + response = bRMSParamPolicyService.getResult(updateFlag); + break; + case BRMS_RAW: + BRMSRawPolicyService bRMSRawPolicyService = new BRMSRawPolicyService(policyName, policyScope, policyParameters, date); + // Check Validation. + if(!bRMSRawPolicyService.getValidation()){ + LOGGER.error(bRMSRawPolicyService.getMessage()); + status = HttpStatus.BAD_REQUEST; + return bRMSRawPolicyService.getMessage(); + } + // Get Result. + response = bRMSRawPolicyService.getResult(updateFlag); + break; + case Base: + ConfigPolicyService configPolicyService = new ConfigPolicyService(policyName, policyScope, policyParameters, date); + // Check Validation. + if(!configPolicyService.getValidation()){ + LOGGER.error(configPolicyService.getMessage()); + status = HttpStatus.BAD_REQUEST; + return configPolicyService.getMessage(); + } + // Get Result. + response = configPolicyService.getResult(updateFlag); + break; + case ClosedLoop_Fault: + ClosedLoopFaultPolicyService closedLoopFaultPolicyService = new ClosedLoopFaultPolicyService(policyName, policyScope, policyParameters, date); + // Check Validation. + if(!closedLoopFaultPolicyService.getValidation()){ + LOGGER.error(closedLoopFaultPolicyService.getMessage()); + status = HttpStatus.BAD_REQUEST; + return closedLoopFaultPolicyService.getMessage(); + } + // Get Result. + response = closedLoopFaultPolicyService.getResult(updateFlag); + break; + case ClosedLoop_PM: + ClosedLoopPMPolicyService closedLoopPMPolicyService = new ClosedLoopPMPolicyService(policyName, policyScope, policyParameters, date); + // Check Validation. + if(!closedLoopPMPolicyService.getValidation()){ + LOGGER.error(closedLoopPMPolicyService.getMessage()); + status = HttpStatus.BAD_REQUEST; + return closedLoopPMPolicyService.getMessage(); + } + // Get Result. + response = closedLoopPMPolicyService.getResult(updateFlag); + break; + case Firewall: + FirewallPolicyService firewallPolicyService = new FirewallPolicyService(policyName, policyScope, policyParameters, date); + // Check Validation. + if(!firewallPolicyService.getValidation()){ + LOGGER.error(firewallPolicyService.getMessage()); + status = HttpStatus.BAD_REQUEST; + return firewallPolicyService.getMessage(); + } + // Get Result. + response = firewallPolicyService.getResult(updateFlag); + break; + case MicroService: + MicroServicesPolicyService microServicesPolicyService = new MicroServicesPolicyService(policyName, policyScope, policyParameters, date); + // Check Validation. + if(!microServicesPolicyService.getValidation()){ + LOGGER.error(microServicesPolicyService.getMessage()); + status = HttpStatus.BAD_REQUEST; + return microServicesPolicyService.getMessage(); + } + // Get Result. + response = microServicesPolicyService.getResult(updateFlag); + break; + default: + String message = XACMLErrorConstants.ERROR_DATA_ISSUE+ " Invalid Config Type Present"; + LOGGER.error(message); + status = HttpStatus.BAD_REQUEST; + return message; + } + }else if (policyParameters.getPolicyClass()!=null){ + switch (policyParameters.getPolicyClass()){ + case Action: + ActionPolicyService actionPolicyService = new ActionPolicyService(policyScope, policyName, policyParameters); + // Check Validation. + if(!actionPolicyService.getValidation()){ + LOGGER.error(actionPolicyService.getMessage()); + status = HttpStatus.BAD_REQUEST; + return actionPolicyService.getMessage(); + } + // Get Result. + response = actionPolicyService.getResult(updateFlag); + break; + case Decision: + DecisionPolicyService decisionPolicyService = new DecisionPolicyService(policyScope, policyName, policyParameters); + // Check Validation. + if(!decisionPolicyService.getValidation()){ + LOGGER.error(decisionPolicyService.getMessage()); + status = HttpStatus.BAD_REQUEST; + return decisionPolicyService.getMessage(); + } + // Get Result. + response = decisionPolicyService.getResult(updateFlag); + break; + } + }else { + String message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No Policy Class found."; + LOGGER.error(message); + status = HttpStatus.BAD_REQUEST; + response = message; + } + return response; + } + + protected boolean getValidation() { + if(policyParameters == null){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No Policy parameters given. "; + return false; + } + if(policyParameters.getPolicyName() == null){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No Policy Name given."; + return false; + } + if (policyParameters.getPolicyName().contains(".")) { + policyName = policyParameters.getPolicyName().substring(policyParameters.getPolicyName().lastIndexOf('.') + 1, + policyParameters.getPolicyName().length()); + policyScope = policyParameters.getPolicyName().substring(0,policyParameters.getPolicyName().lastIndexOf('.')); + LOGGER.info("Name is " + policyName + " scope is " + policyScope); + } else { + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No Policy Scope given."; + return false; + } + if (policyName==null||policyName.trim().isEmpty()){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No Policy Name given."; + return false; + } + message = PolicyUtils.emptyPolicyValidator(policyScope); + if(!message.contains("success")){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE+ message; + return false; + } + message = PolicyUtils.emptyPolicyValidator(policyName); + if(!message.contains("success")){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE+ message; + return false; + } + if(policyParameters.getPolicyDescription()!=null){ + message = PolicyUtils.descriptionValidator(policyParameters.getPolicyDescription()); + if(!message.contains("success")){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE+ message; + return false; + } + } + if(!PolicyApiUtils.validateNONASCIICharactersAndAllowSpaces(policyParameters.toString())){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE+ "This requests contains Non ASCII Characters. Please review your input parameter" + + " values and correct the illegal characters."; + return false; + } + // Set some default Values. + if (policyParameters.getTtlDate()!=null){ + date = convertDate(policyParameters.getTtlDate()); + } + return true; + } + + protected String convertDate(Date date) { + String strDate = null; + if (date!=null) { + SimpleDateFormat dateformatJava = new SimpleDateFormat("dd-MM-yyyy"); + strDate = dateformatJava.format(date); + } + return (strDate==null) ? "NA": strDate; + } + + protected void specialCheck() { + if(policyResult== null || policyResult.contains("BAD REQUEST")||policyResult.contains("PE300")){ + status = HttpStatus.BAD_REQUEST; + } else if (policyResult.contains("Policy Exist Error")) { + status = HttpStatus.CONFLICT; + } else if (policyResult.contains("PE200")||policyResult.contains("PE900")){ + status = HttpStatus.INTERNAL_SERVER_ERROR; + } + } + + public String getResult() { + return policyResult; + } + + public HttpStatus getResponseCode() { + return status; + } + +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/DecisionPolicyService.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/DecisionPolicyService.java new file mode 100644 index 000000000..c283ff14c --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/DecisionPolicyService.java @@ -0,0 +1,100 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.policy.pdp.rest.api.services; + +import java.util.Map; + +import org.onap.policy.api.AttributeType; +import org.onap.policy.api.PolicyException; +import org.onap.policy.api.PolicyParameters; +import org.onap.policy.api.RuleProvider; +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; +import org.onap.policy.xacml.api.XACMLErrorConstants; +import org.onap.policy.xacml.std.pap.StdPAPPolicy; + +/** + * Decision Policy Implementation + * + * @version 0.1 + */ +public class DecisionPolicyService{ + private static Logger LOGGER = FlexLogger.getLogger(DecisionPolicyService.class.getName()); + private static PAPServices papServices = null; + + private String message = null; + private String policyScope = null; + private String policyName = null; + private PolicyParameters policyParameters = null; + private String onapName = null; + + public DecisionPolicyService(String policyScope, String policyName, + PolicyParameters policyParameters) { + this.policyScope = policyScope; + this.policyName = policyName; + this.policyParameters = policyParameters; + papServices = new PAPServices(); + } + + public Boolean getValidation() { + onapName = policyParameters.getOnapName(); + if (onapName==null||onapName.trim().isEmpty()){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No ONAP Name given."; + return false; + } + return true; + } + + public String getMessage() { + return message; + } + + public String getResult(boolean updateFlag) throws PolicyException { + String response = null; + String operation = null; + if (updateFlag){ + operation = "update"; + } else { + operation = "create"; + } + RuleProvider ruleProvider = policyParameters.getRuleProvider(); + if (ruleProvider==null) { + ruleProvider = RuleProvider.CUSTOM ; + } + Map<String,String> matchingAttributes = null; + Map<String,String> settingsAttributes = null; + if (policyParameters.getAttributes()!=null && policyParameters.getAttributes().containsKey(AttributeType.MATCHING) && policyParameters.getAttributes().containsKey(AttributeType.SETTINGS)) { + matchingAttributes = policyParameters.getAttributes().get(AttributeType.MATCHING); + settingsAttributes = policyParameters.getAttributes().get(AttributeType.SETTINGS); + }else if(policyParameters.getAttributes()!=null && !policyParameters.getAttributes().containsKey(AttributeType.MATCHING) && policyParameters.getAttributes().containsKey(AttributeType.SETTINGS)){ + settingsAttributes = policyParameters.getAttributes().get(AttributeType.SETTINGS); + }else if(policyParameters.getAttributes()!=null && policyParameters.getAttributes().containsKey(AttributeType.MATCHING) && !policyParameters.getAttributes().containsKey(AttributeType.SETTINGS)){ + matchingAttributes = policyParameters.getAttributes().get(AttributeType.MATCHING); + } + // Create Policy. + StdPAPPolicy newPAPPolicy = new StdPAPPolicy(policyName, policyParameters.getPolicyDescription(), onapName, ruleProvider.toString(), matchingAttributes, settingsAttributes, policyParameters.getDynamicRuleAlgorithmLabels(), + policyParameters.getDynamicRuleAlgorithmFunctions(), policyParameters.getDynamicRuleAlgorithmField1(), policyParameters.getDynamicRuleAlgorithmField2(), null, null, null, updateFlag, policyScope, 0); + // Send JSON to PAP. + response = (String) papServices.callPAP(newPAPPolicy, new String[] {"operation="+operation, "apiflag=api", "policyType=Decision"}, policyParameters.getRequestID(), "Decision"); + LOGGER.info(message); + return response; + } + +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/DeletePolicyService.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/DeletePolicyService.java new file mode 100644 index 000000000..01670a5fd --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/DeletePolicyService.java @@ -0,0 +1,258 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.policy.pdp.rest.api.services; + +import java.io.File; +import java.util.UUID; + +import org.onap.policy.api.DeletePolicyParameters; +import org.onap.policy.api.PolicyException; +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; +import org.onap.policy.xacml.api.XACMLErrorConstants; +import org.onap.policy.xacml.std.pap.StdPAPPolicy; +import org.springframework.http.HttpStatus; + +public class DeletePolicyService { + private static final Logger LOGGER = FlexLogger.getLogger(DeletePolicyService.class.getName()); + + private String deleteResult = null; + private HttpStatus status = HttpStatus.BAD_REQUEST; + private DeletePolicyParameters deletePolicyParameters = null; + private String message = null; + private String filePrefix = null; + private String clientScope = null; + private String policyType = null; + private String policyName = null; + private String policyScope = null; + + public DeletePolicyService(DeletePolicyParameters deletePolicyParameters, + String requestID) { + this.deletePolicyParameters = deletePolicyParameters; + if(deletePolicyParameters.getRequestID()==null){ + UUID requestUUID = null; + if (requestID != null && !requestID.isEmpty()) { + try { + requestUUID = UUID.fromString(requestID); + } catch (IllegalArgumentException e) { + requestUUID = UUID.randomUUID(); + LOGGER.info("Generated Random UUID: " + requestUUID.toString(), e); + } + }else{ + requestUUID = UUID.randomUUID(); + LOGGER.info("Generated Random UUID: " + requestUUID.toString()); + } + this.deletePolicyParameters.setRequestID(requestUUID); + } + try{ + run(); + specialCheck(); + }catch(PolicyException e){ + deleteResult = XACMLErrorConstants.ERROR_DATA_ISSUE + e; + status = HttpStatus.BAD_REQUEST; + } + } + + private void specialCheck() { + if(deleteResult==null){ + return; + } + if (deleteResult.contains("BAD REQUEST")||deleteResult.contains("PE300")||deleteResult.contains("PE200")||deleteResult.contains("not exist")||deleteResult.contains("Invalid policyName")) { + status = HttpStatus.BAD_REQUEST; + } else if (deleteResult.contains("locked down")){ + status = HttpStatus.ACCEPTED; + } else if (deleteResult.contains("not Authorized")) { + status = HttpStatus.FORBIDDEN; + } else if (deleteResult.contains("groupId")) { + status = HttpStatus.NOT_FOUND; + } else if (deleteResult.contains("JPAUtils")||deleteResult.contains("database")||deleteResult.contains("policy file")|| + deleteResult.contains("unknown")||deleteResult.contains("configuration")) { + status = HttpStatus.INTERNAL_SERVER_ERROR; + } + } + + private void run() throws PolicyException{ + // Check Validation. + if(!getValidation()){ + LOGGER.error(message); + throw new PolicyException(message); + } + // Get Result. + try{ + status = HttpStatus.OK; + deleteResult = processResult(); + }catch (Exception e){ + LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + e); + status = HttpStatus.BAD_REQUEST; + throw new PolicyException(e); + } + } + + private String processResult() throws PolicyException{ + String response = null; + String fullPolicyName = null; + String pdpGroup = deletePolicyParameters.getPdpGroup(); + // PDP Group Check. + if (pdpGroup==null){ + pdpGroup="NA"; + } + PAPServices papServices = new PAPServices(); + if (!deletePolicyParameters.getPolicyName().contains("xml")) { + + String activeVersion = papServices.getActiveVersion(policyScope, filePrefix, policyName, clientScope, deletePolicyParameters.getRequestID()); + LOGGER.debug("The active version of " + policyScope + File.separator + filePrefix + policyName + " is " + activeVersion); + String id = null; + if ("pe100".equalsIgnoreCase(activeVersion)) { + response = XACMLErrorConstants.ERROR_PERMISSIONS + "response code of the URL is 403. PEP is not Authorized for making this Request!! " + + "Contact Administrator for this Scope. "; + LOGGER.error(response); + return response; + } else if ("pe300".equalsIgnoreCase(activeVersion)) { + response = XACMLErrorConstants.ERROR_DATA_ISSUE + "response code of the URL is 404. " + + "This indicates a problem with getting the version from the PAP or the policy does not exist."; + LOGGER.error(response); + return response; + } + if (!activeVersion.equalsIgnoreCase("0")) { + id = policyScope + "." + filePrefix + policyName + "." + activeVersion + ".xml"; + LOGGER.debug("The policyId is " + id); + } else { + response = XACMLErrorConstants.ERROR_DATA_ISSUE + "could not retrieve the activeVersion for this policy. could not retrieve the activeVersion for this policy. " + + "This indicates the policy does not exist, please verify the policy exists."; + LOGGER.error(response); + return response; + } + + fullPolicyName = policyScope + "." + filePrefix + policyName + "." + activeVersion + ".xml"; + + } else { + fullPolicyName = policyName; + } + + if ("PAP".equalsIgnoreCase(deletePolicyParameters.getPolicyComponent())) { + if (deletePolicyParameters.getDeleteCondition()==null||deletePolicyParameters.getDeleteCondition().toString().trim().isEmpty()){ + String message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No Delete Condition given."; + LOGGER.error(message); + return message; + } + + StdPAPPolicy deletePapPolicy = new StdPAPPolicy(fullPolicyName, deletePolicyParameters.getDeleteCondition().toString()); + //send JSON object to PAP + response = (String) papServices.callPAP(deletePapPolicy, new String[] {"groupId="+pdpGroup, "apiflag=deletePapApi", "operation=delete" }, deletePolicyParameters.getRequestID(), clientScope); + } else if ("PDP".equalsIgnoreCase(deletePolicyParameters.getPolicyComponent())) { + if (deletePolicyParameters.getPdpGroup()==null||deletePolicyParameters.getPdpGroup().trim().isEmpty()){ + String message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No PDP Group given."; + LOGGER.error(message); + return message; + } + //send JSON object to PAP + response = (String) papServices.callPAP(null, new String[] {"policyName="+fullPolicyName, "groupId="+pdpGroup, "apiflag=deletePdpApi", "operation=delete" }, deletePolicyParameters.getRequestID(), clientScope); + } else { + String message = XACMLErrorConstants.ERROR_DATA_ISSUE + "Policy Component does not exist. Please enter either PAP or PDP to delete the policy from a specified Policy Component."; + LOGGER.error(message); + response = message; + } + return response; + } + + private boolean getValidation() { + // While Validating, extract the required values. + if (deletePolicyParameters.getPolicyName()==null||deletePolicyParameters.getPolicyName().trim().isEmpty()){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No Policy Name given."; + return false; + } + if (!deletePolicyParameters.getPolicyName().contains("xml")) { + if (deletePolicyParameters.getPolicyName() != null + && deletePolicyParameters.getPolicyName().contains(".")) { + policyName = deletePolicyParameters.getPolicyName().substring(deletePolicyParameters.getPolicyName().lastIndexOf(".") + 1, + deletePolicyParameters.getPolicyName().length()); + policyScope = deletePolicyParameters.getPolicyName().substring(0,deletePolicyParameters.getPolicyName().lastIndexOf(".")); + LOGGER.info("Name is " + policyName + " scope is " + policyScope); + } else { + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No Policy Scope given."; + return false; + } + } else { + policyName = deletePolicyParameters.getPolicyName(); + } + policyType = deletePolicyParameters.getPolicyType(); + if(policyType== null || policyType.trim().isEmpty()){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No PolicyType given."; + return false; + } + setClientScope(); + if (clientScope==null||clientScope.trim().isEmpty()){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + deletePolicyParameters.getPolicyType() + " is not a valid Policy Type."; + LOGGER.error(message); + return false; + } + LOGGER.debug("clientScope is " + clientScope); + LOGGER.debug("filePrefix is " + filePrefix); + if(deletePolicyParameters.getPolicyComponent()==null){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No Policy Component given."; + return false; + } + return true; + } + + private void setClientScope() { + if ("Firewall".equalsIgnoreCase(policyType)) { + clientScope = "ConfigFirewall"; + filePrefix = "Config_FW_"; + } else if ("Action".equalsIgnoreCase(policyType)) { + clientScope = "Action"; + filePrefix = "Action_"; + } else if ("Decision".equalsIgnoreCase(policyType)) { + clientScope = "Decision"; + filePrefix = "Decision_"; + } else if ("Base".equalsIgnoreCase(policyType)) { + clientScope = "Config"; + filePrefix = "Config_"; + } else if ("ClosedLoop_Fault".equalsIgnoreCase(policyType)) { + clientScope = "ConfigClosedLoop"; + filePrefix = "Config_Fault_"; + } else if ("ClosedLoop_PM".equalsIgnoreCase(policyType)) { + clientScope = "ConfigClosedLoop"; + filePrefix = "Config_PM_"; + } else if ("MicroService".equalsIgnoreCase(policyType)) { + clientScope = "ConfigMS"; + filePrefix = "Config_MS_"; + }else if ("BRMS_RAW".equalsIgnoreCase(policyType)) { + clientScope = "ConfigBrmsRaw"; + filePrefix = "Config_BRMS_Raw_"; + } else if ("BRMS_PARAM".equalsIgnoreCase(policyType)) { + clientScope = "ConfigBrmsParam"; + filePrefix = "Config_BRMS_Param_"; + } else { + clientScope = null; + message = XACMLErrorConstants.ERROR_DATA_ISSUE + policyType + + " is not a valid Policy Type."; + } + } + + public String getResult() { + return deleteResult; + } + + public HttpStatus getResponseCode() { + return status; + } + +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/FirewallPolicyService.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/FirewallPolicyService.java new file mode 100644 index 000000000..8f4ba9a79 --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/FirewallPolicyService.java @@ -0,0 +1,113 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.policy.pdp.rest.api.services; + +import javax.json.JsonException; +import javax.json.JsonObject; + +import org.onap.policy.api.PolicyException; +import org.onap.policy.api.PolicyParameters; +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; +import org.onap.policy.pdp.rest.api.utils.PolicyApiUtils; +import org.onap.policy.xacml.api.XACMLErrorConstants; +import org.onap.policy.xacml.std.pap.StdPAPPolicy; + +/** + * Firewall Policy Implementation. + * + * @version 0.1 + */ +public class FirewallPolicyService { + private static final Logger LOGGER = FlexLogger.getLogger(FirewallPolicyService.class.getName()); + + private PAPServices papServices = null; + private PolicyParameters policyParameters = null; + private String message = null; + private String policyName = null; + private String policyScope = null; + private String date = null; + private JsonObject firewallJson = null; + + public FirewallPolicyService(String policyName, String policyScope, + PolicyParameters policyParameters, String date) { + this.policyParameters = policyParameters; + this.policyName = policyName; + this.policyScope = policyScope; + this.date = date; + papServices = new PAPServices(); + } + + public Boolean getValidation() { + if(policyParameters.getConfigBody()==null){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE+ "No Config Body given."; + return false; + } + try{ + firewallJson = PolicyApiUtils.stringToJsonObject(policyParameters.getConfigBody()); + } catch(JsonException| IllegalStateException e){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE+ " improper JSON object : " + policyParameters.getConfigBody(); + LOGGER.error("Error while parsing JSON body for creating Firewall Policy " , e); + return false; + } + if(firewallJson==null|| firewallJson.isEmpty()){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No Config-Body given."; + return false; + } + boolean levelCheck = false; + levelCheck = PolicyApiUtils.isNumeric(policyParameters.getRiskLevel()); + if (!levelCheck){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "Incorrect Risk Level given."; + return false; + } + return true; + } + + public String getMessage() { + return message; + } + + public String getResult(boolean updateFlag) throws PolicyException { + String response = null; + String operation = null; + if (updateFlag){ + operation = "update"; + } else { + operation = "create"; + } + //set values for basic policy information + if(!firewallJson.containsKey("configName")){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No configName given in firwall JSON."; + LOGGER.error(message); + return message; + } + String configName = firewallJson.get("configName").toString(); + String configDescription = ""; + String json = firewallJson.toString(); + // Create Policy. + StdPAPPolicy newPAPPolicy = new StdPAPPolicy("Firewall Config", policyName, configDescription, configName, updateFlag, policyScope, json, 0, + policyParameters.getRiskLevel(),policyParameters.getRiskType(), String.valueOf(policyParameters.getGuard()), date); + // Send Json to PAP. + response = (String) papServices.callPAP(newPAPPolicy, new String[] {"operation="+operation, "apiflag=api", "policyType=Config"}, policyParameters.getRequestID(), "ConfigFirewall"); + LOGGER.info(response); + return response; + } + +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/GetConfigService.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/GetConfigService.java new file mode 100644 index 000000000..1817d8861 --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/GetConfigService.java @@ -0,0 +1,318 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.policy.pdp.rest.api.services; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import javax.json.Json; +import javax.json.JsonArrayBuilder; +import javax.json.JsonObject; +import javax.json.JsonObjectBuilder; + +import org.onap.policy.api.ConfigRequestParameters; +import org.onap.policy.api.PolicyConfigException; +import org.onap.policy.api.PolicyConfigStatus; +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; +import org.onap.policy.pdp.rest.api.models.PDPResponse; +import org.onap.policy.pdp.rest.api.models.PolicyConfig; +import org.onap.policy.xacml.api.XACMLErrorConstants; +import org.springframework.http.HttpStatus; + +public class GetConfigService { + private static final Logger LOGGER = FlexLogger.getLogger(GetConfigService.class.getName()); + + private ConfigRequestParameters configRequestParameters = null; + private String message = null; + private HttpStatus responseCode = HttpStatus.BAD_REQUEST; + private Collection<PolicyConfig> policyConfigs = null; + private boolean unique = false; + + public GetConfigService(ConfigRequestParameters configRequestParameters, + String requestID){ + this.configRequestParameters = configRequestParameters; + if(configRequestParameters.getRequestID()==null){ + UUID requestUUID = null; + if (requestID != null && !requestID.isEmpty()) { + try { + requestUUID = UUID.fromString(requestID); + } catch (IllegalArgumentException e) { + requestUUID = UUID.randomUUID(); + LOGGER.info("Generated Random UUID: " + requestUUID.toString(),e); + } + }else{ + requestUUID = UUID.randomUUID(); + LOGGER.info("Generated Random UUID: " + requestUUID.toString()); + } + this.configRequestParameters.setRequestID(requestUUID); + } + policyConfigs = new ArrayList<>(); + try{ + run(); + specialCheck(); + }catch(PolicyConfigException e){ + LOGGER.error(e); + PolicyConfig policyConfig = new PolicyConfig(); + policyConfig.setPolicyConfigMessage(e.getMessage()); + policyConfig.setPolicyConfigStatus(PolicyConfigStatus.CONFIG_NOT_FOUND); + policyConfigs.add(policyConfig); + responseCode = HttpStatus.BAD_REQUEST; + } + } + + private void specialCheck() { + if(policyConfigs==null || policyConfigs.isEmpty()){ + responseCode = HttpStatus.BAD_REQUEST; + }else if(policyConfigs.size()==1){ + for(PolicyConfig policyConfig: policyConfigs){ + if(policyConfig.getPolicyConfigMessage()!=null && policyConfig.getPolicyConfigMessage().contains("PE300")){ + responseCode = HttpStatus.BAD_REQUEST; + } + } + }else{ + responseCode = HttpStatus.OK; + } + } + + private void run() throws PolicyConfigException{ + // getValidation. + if(!getValidation()){ + LOGGER.error(message); + throw new PolicyConfigException(message); + } + // Generate Request. + String modelString = getModel().toString(); + LOGGER.debug("Generated JSON Request is: " + modelString); + if(configRequestParameters.getUnique()){ + LOGGER.info("Requested for Unique Result only. "); + unique = true; + } + // Process Result. + try { + PDPServices pdpServices = new PDPServices(); + responseCode = HttpStatus.OK; + policyConfigs = configResult(pdpServices.generateRequest(modelString, configRequestParameters.getRequestID(), unique, false)); + // Filter addition. + policyConfigs = filterResults(policyConfigs, configRequestParameters); + } catch (Exception e) { + LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + e); + responseCode = HttpStatus.BAD_REQUEST; + throw new PolicyConfigException(XACMLErrorConstants.ERROR_DATA_ISSUE +e); + } + } + + private Collection<PolicyConfig> configResult( + Collection<PDPResponse> generateRequest) { + Collection<PolicyConfig> result = new HashSet<>(); + if (generateRequest == null) { + return null; + } + if (!generateRequest.isEmpty()) { + for (PDPResponse stdStatus : generateRequest) { + PolicyConfig policyConfig = new PolicyConfig(); + policyConfig.setConfig(stdStatus.getConfig()); + policyConfig.setMatchingConditions(stdStatus.getMatchingConditions()); + policyConfig.setPolicyConfigMessage(stdStatus.getPolicyConfigMessage()); + policyConfig.setPolicyConfigStatus(stdStatus.getPolicyConfigStatus()); + policyConfig.setPolicyName(stdStatus.getPolicyName()); + policyConfig.setPolicyVersion(stdStatus.getPolicyVersion()); + policyConfig.setProperty(stdStatus.getProperty()); + policyConfig.setResponseAttributes(stdStatus.getResponseAttributes()); + policyConfig.setType(stdStatus.getType()); + result.add(policyConfig); + } + } + return result; + } + + // Filter logic required for results comparing with requests. + private Collection<PolicyConfig> filterResults( + Collection<PolicyConfig> policyConfigs, + ConfigRequestParameters configRequestParameters) { + List<PolicyConfig> policyConfig = new ArrayList<>(); + for(PolicyConfig config: policyConfigs){ + if(config.getPolicyName()!=null && configRequestParameters.getPolicyName()!=null && configRequestParameters.getPolicyName().trim().length()>0){ + if(!config.getPolicyName().matches(configRequestParameters.getPolicyName())){ + continue; + } + } + if(config.getMatchingConditions()!=null && config.getMatchingConditions().size()>0){ + if(configRequestParameters.getOnapName()!=null && configRequestParameters.getOnapName().trim().length()>0 && config.getMatchingConditions().containsKey("ONAPName")){ + if(!config.getMatchingConditions().get("ONAPName").matches(configRequestParameters.getOnapName())){ + continue; + } + } + if(configRequestParameters.getConfigName()!=null && configRequestParameters.getConfigName().trim().length()>0 && config.getMatchingConditions().containsKey("ConfigName")){ + if(!config.getMatchingConditions().get("ConfigName").matches(configRequestParameters.getConfigName())){ + continue; + } + } + if(configRequestParameters.getConfigAttributes()!=null && configRequestParameters.getConfigAttributes().size()>0){ + boolean flag = false; + for(String key: configRequestParameters.getConfigAttributes().keySet()){ + if(key.equals("RiskType")||key.equals("RiskLevel")||key.equals("guard")||key.equals("TTLDate")){ + continue; + } + if(config.getMatchingConditions().containsKey(key)){ + if(config.getMatchingConditions().get(key).contains(",")){ + List<String> elements = Arrays.asList(config.getMatchingConditions().get(key).split(",")); + if(!elements.contains(configRequestParameters.getConfigAttributes().get(key))){ + flag=true; + } + }else if(!config.getMatchingConditions().get(key).matches(configRequestParameters.getConfigAttributes().get(key))){ + flag = true; + } + }else{ + flag = true; + } + if(flag){ + break; + } + } + if(flag){ + continue; + } + } + } + policyConfig.add(config); + } + if(policyConfig.isEmpty()){ + PolicyConfig pConfig = new PolicyConfig(); + pConfig.setPolicyConfigStatus(PolicyConfigStatus.CONFIG_NOT_FOUND); + pConfig.setPolicyConfigMessage(XACMLErrorConstants.ERROR_DATA_ISSUE+"No Match Found, for the parameters sent."); + policyConfig.add(pConfig); + } + return policyConfig; + } + + private JsonObject getModel() throws PolicyConfigException{ + String policyName = configRequestParameters.getPolicyName(); + if(policyName!= null && !policyName.trim().isEmpty() && !policyName.endsWith("xml")){ + policyName = policyName + ".[\\d].*"; + configRequestParameters.setPolicyName(policyName); + } + JsonArrayBuilder subjectArray = Json.createArrayBuilder(); + JsonArrayBuilder resourceArray = Json.createArrayBuilder(); + if(configRequestParameters.getPolicyName()!=null){ + JsonObjectBuilder subjectBuilder = Json.createObjectBuilder(); + subjectBuilder.add("Value", policyName); + subjectBuilder.add("AttributeId", "PolicyName"); + subjectArray.add(subjectBuilder); + }else{ + LOGGER.info("PolicyName values are not given. "); + } + if(configRequestParameters.getOnapName()!=null){ + JsonObjectBuilder subjectBuilder = Json.createObjectBuilder(); + subjectBuilder.add("Value", configRequestParameters.getOnapName()); + subjectBuilder.add("AttributeId", "ONAPName"); + subjectArray.add(subjectBuilder); + if(configRequestParameters.getConfigName()!=null){ + subjectBuilder = Json.createObjectBuilder(); + subjectBuilder.add("Value", configRequestParameters.getConfigName()); + subjectBuilder.add("AttributeId", "ConfigName"); + subjectArray.add(subjectBuilder); + resourceArray = getResourceArray(configRequestParameters.getConfigAttributes()); + }else{ + LOGGER.info("Config Name is not given. "); + } + }else{ + LOGGER.info("Onap Name is not given. "); + } + return Json.createObjectBuilder() + .add("Request",Json.createObjectBuilder() + .add("AccessSubject",Json.createObjectBuilder() + .add("Attribute",subjectArray)) + .add("Action",Json.createObjectBuilder() + .add("Attribute",Json.createObjectBuilder() + .add("Value","ACCESS") + .add("AttributeId","urn:oasis:names:tc:xacml:1.0:action:action-id"))) + .add("Resource",Json.createObjectBuilder() + .add("Attribute",resourceArray + .add(Json.createObjectBuilder() + .add("Value","Config") + .add("AttributeId","urn:oasis:names:tc:xacml:1.0:resource:resource-id"))))) + .build(); + } + + private JsonArrayBuilder getResourceArray(Map<String, String> configAttributes) throws PolicyConfigException{ + JsonArrayBuilder resourceArray = Json.createArrayBuilder(); + configAttributes = configRequestParameters.getConfigAttributes(); + if (configAttributes != null && !configAttributes.isEmpty()) { + if(!configAttributes.containsKey("RiskType")){ + configAttributes.put("RiskType", ".*"); + } + if(!configAttributes.containsKey("RiskLevel")){ + configAttributes.put("RiskLevel", ".*"); + } + if(!configAttributes.containsKey("guard")){ + configAttributes.put("guard", ".*"); + } + if(!configAttributes.containsKey("TTLDate")){ + configAttributes.put("TTLDate", ".*"); + } + }else{ + // ConfigAttributes is Null. So add basic values. + configAttributes = new HashMap<>(); + configAttributes.put("RiskType", ".*"); + configAttributes.put("RiskLevel", ".*"); + configAttributes.put("guard", ".*"); + configAttributes.put("TTLDate", ".*"); + } + for (String key : configAttributes.keySet()) { + if (key.isEmpty()) { + String message = XACMLErrorConstants.ERROR_DATA_ISSUE + "Cannot have an Empty Key"; + LOGGER.error(message); + throw new PolicyConfigException(message); + } + JsonObjectBuilder resourceBuilder = Json.createObjectBuilder(); + resourceBuilder.add("Value", configAttributes.get(key)); + resourceBuilder.add("AttributeId", key); + resourceArray.add(resourceBuilder); + } + return resourceArray; + } + + private Boolean getValidation(){ + if(configRequestParameters==null){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No config Request Parameters given."; + return false; + } + if(configRequestParameters.getOnapName()==null && configRequestParameters.getPolicyName()==null){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "Cannot proceed without onapComponentName or PolicyName"; + return false; + } + return true; + } + + public Collection<PolicyConfig> getResult() { + return policyConfigs; + } + + public HttpStatus getResponseCode() { + return responseCode; + } +}
\ No newline at end of file diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/GetDecisionService.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/GetDecisionService.java new file mode 100644 index 000000000..66beb0663 --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/GetDecisionService.java @@ -0,0 +1,189 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.policy.pdp.rest.api.services; + +import java.util.Collection; +import java.util.Map; +import java.util.Map.Entry; +import java.util.UUID; + +import javax.json.Json; +import javax.json.JsonArrayBuilder; +import javax.json.JsonObject; +import javax.json.JsonObjectBuilder; + +import org.onap.policy.api.DecisionRequestParameters; +import org.onap.policy.api.DecisionResponse; +import org.onap.policy.api.PolicyDecision; +import org.onap.policy.api.PolicyDecisionException; +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; +import org.onap.policy.pdp.rest.api.models.PDPResponse; +import org.onap.policy.std.StdDecisionResponse; +import org.onap.policy.xacml.api.XACMLErrorConstants; +import org.springframework.http.HttpStatus; + +public class GetDecisionService { + private static final Logger LOGGER = FlexLogger.getLogger(GetDecisionService.class.getName()); + + private DecisionResponse decisionResponse = null; + private HttpStatus status = HttpStatus.BAD_REQUEST; + private DecisionRequestParameters decisionRequestParameters = null; + private String message = null; + private String onapComponentName = null; + private Map<String,String> decisionAttributes = null; + + public GetDecisionService( + DecisionRequestParameters decisionRequestParameters, + String requestID) { + this.decisionRequestParameters = decisionRequestParameters; + if(decisionRequestParameters.getRequestID()==null){ + UUID requestUUID = null; + if (requestID != null && !requestID.isEmpty()) { + try { + requestUUID = UUID.fromString(requestID); + } catch (IllegalArgumentException e) { + requestUUID = UUID.randomUUID(); + LOGGER.info("Generated Random UUID: " + requestUUID.toString(),e); + } + }else{ + requestUUID = UUID.randomUUID(); + LOGGER.info("Generated Random UUID: " + requestUUID.toString()); + } + this.decisionRequestParameters.setRequestID(requestUUID); + } + try{ + run(); + }catch(PolicyDecisionException e){ + StdDecisionResponse decisionResponse = new StdDecisionResponse(); + decisionResponse.setDecision(PolicyDecision.ERROR); + decisionResponse.setDetails(XACMLErrorConstants.ERROR_DATA_ISSUE + e); + this.decisionResponse = decisionResponse; + status = HttpStatus.BAD_REQUEST; + } + } + + private void run() throws PolicyDecisionException{ + // Get Validation. + if(!getValidation()){ + LOGGER.error(message); + throw new PolicyDecisionException(message); + } + // Generate Request. + String modelString = getModel().toString(); + LOGGER.debug("Generated JSON Request is: " + modelString); + // Process Result. + try { + PDPServices pdpServices = new PDPServices(); + status = HttpStatus.OK; + decisionResponse = decisionResult(pdpServices.generateRequest(modelString, decisionRequestParameters.getRequestID(), false, true)); + } catch (Exception e) { + LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + e); + status = HttpStatus.BAD_REQUEST; + throw new PolicyDecisionException(e); + } + } + + private DecisionResponse decisionResult( + Collection<PDPResponse> generateRequest) { + StdDecisionResponse policyDecision = new StdDecisionResponse(); + if (generateRequest == null) { + return policyDecision; + } + if (!generateRequest.isEmpty()) { + for (PDPResponse stdStatus : generateRequest) { + policyDecision.setDecision(stdStatus.getDecision()); + policyDecision.setDetails(stdStatus.getDetails()); + } + } + return policyDecision; + } + + private JsonObject getModel() throws PolicyDecisionException{ + JsonArrayBuilder resourceArray = Json.createArrayBuilder(); + for (Entry<String,String> key : decisionAttributes.entrySet()) { + if (key.getKey().isEmpty()) { + String message = XACMLErrorConstants.ERROR_DATA_ISSUE + "Cannot have an Empty Key"; + LOGGER.error(message); + throw new PolicyDecisionException(message); + } + JsonObjectBuilder resourceBuilder = Json.createObjectBuilder(); + if (key.getValue().matches("[0-9]+")) { + + if ((key.getKey().equals("ErrorCode")) || (key.getKey().equals("WorkStep"))) { + + resourceBuilder.add("Value", key.getValue()); + + } else { + + int val = Integer.parseInt(key.getValue()); + resourceBuilder.add("Value", val); + + } + + } else { + resourceBuilder.add("Value", key.getValue()); + } + resourceBuilder.add("AttributeId", key.getKey()); + resourceArray.add(resourceBuilder); + } + return Json.createObjectBuilder() + .add("Request", Json.createObjectBuilder() + .add("AccessSubject", Json.createObjectBuilder() + .add("Attribute", Json.createObjectBuilder() + .add("Value", onapComponentName) + .add("AttributeId", "ONAPName"))) + .add("Resource", Json.createObjectBuilder() + .add("Attribute", resourceArray)) + .add("Action", Json.createObjectBuilder() + .add("Attribute", Json.createObjectBuilder() + .add("Value", "DECIDE") + .add("AttributeId", "urn:oasis:names:tc:xacml:1.0:action:action-id")))) + .build(); + } + + private boolean getValidation() { + if(decisionRequestParameters==null){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No Decision Request Paramaters"; + return false; + } + onapComponentName = decisionRequestParameters.getONAPComponentName(); + decisionAttributes = decisionRequestParameters.getDecisionAttributes(); + if (onapComponentName == null || onapComponentName.isEmpty()) { + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No onapComponentName given : " + onapComponentName; + return false; + } + if (decisionAttributes == null || decisionAttributes.isEmpty()) { + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No Decision Attributes Given. "; + return false; + } + return true; + } + + public DecisionResponse getResult() { + return decisionResponse; + } + + public HttpStatus getResponseCode() { + return status; + } + +} + diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/GetDictionaryService.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/GetDictionaryService.java new file mode 100644 index 000000000..8f88ef7c7 --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/GetDictionaryService.java @@ -0,0 +1,276 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.policy.pdp.rest.api.services; + +import java.util.UUID; + +import javax.json.JsonException; +import javax.json.JsonObject; + +import org.onap.policy.api.DictionaryParameters; +import org.onap.policy.api.DictionaryResponse; +import org.onap.policy.api.PolicyException; +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; +import org.onap.policy.pdp.rest.api.utils.PolicyApiUtils; +import org.onap.policy.std.StdDictionaryResponse; +import org.onap.policy.xacml.api.XACMLErrorConstants; +import org.springframework.http.HttpStatus; + +public class GetDictionaryService { + private static final Logger LOGGER = FlexLogger.getLogger(GetDictionaryService.class.getName()); + + private DictionaryResponse dictionaryResponse = null; + private HttpStatus status = HttpStatus.BAD_REQUEST; + private String message = null; + private DictionaryParameters dictionaryParameters = null; + + public GetDictionaryService(DictionaryParameters dictionaryParameters, + String requestID) { + this.dictionaryParameters = dictionaryParameters; + if(dictionaryParameters.getRequestID()==null){ + UUID requestUUID = null; + if (requestID != null && !requestID.isEmpty()) { + try { + requestUUID = UUID.fromString(requestID); + } catch (IllegalArgumentException e) { + requestUUID = UUID.randomUUID(); + LOGGER.info("Generated Random UUID: " + requestUUID.toString(), e); + } + }else{ + requestUUID = UUID.randomUUID(); + LOGGER.info("Generated Random UUID: " + requestUUID.toString()); + } + this.dictionaryParameters.setRequestID(requestUUID); + } + try{ + run(); + specialCheck(); + }catch(PolicyException e){ + StdDictionaryResponse dictionaryResponse = new StdDictionaryResponse(); + dictionaryResponse.setResponseMessage(XACMLErrorConstants.ERROR_DATA_ISSUE + e); + this.dictionaryResponse = dictionaryResponse; + status = HttpStatus.BAD_REQUEST; + } + } + + private void specialCheck() { + if(dictionaryResponse!=null && (dictionaryResponse.getResponseMessage()!=null && dictionaryResponse.getResponseMessage().contains("PE300"))){ + status = HttpStatus.BAD_REQUEST; + } + } + + private void run() throws PolicyException{ + // Check Validation. + if(!getValidation()){ + LOGGER.error(message); + throw new PolicyException(message); + } + // Get Result. + try{ + status = HttpStatus.OK; + dictionaryResponse = processResult(); + }catch (Exception e){ + LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + e); + status = HttpStatus.BAD_REQUEST; + throw new PolicyException(e); + } + } + + private DictionaryResponse processResult() throws PolicyException{ + StdDictionaryResponse response = new StdDictionaryResponse(); + PAPServices papServices = new PAPServices(); + String result = (String) papServices.callPAP(null, new String[] {"operation=get", "apiflag=api", "dictionaryType="+dictionaryParameters.getDictionary()}, dictionaryParameters.getRequestID(), "dictionaryItem"); + + if (result!=null && result.contains("data")) { + String jsonString = formatDictionaryJson(result); + String responseMessage = result.substring(0, 82); + JsonObject json = null; + try{ + json = PolicyApiUtils.stringToJsonObject(jsonString.replace("\\\\\\", "\\")); + String datas = json.getString("data").replaceFirst("\"\\[", "["); + int i = datas.lastIndexOf("]"); + if( i>=0 ) { + datas = new StringBuilder(datas).replace(i, i+2,"]").toString(); + } + json = PolicyApiUtils.stringToJsonObject(datas); + } catch(JsonException| IllegalStateException e){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE+ " improper Dictionary JSON object : " + dictionaryParameters.getDictionaryJson(); + LOGGER.error(message, e); + response.setResponseMessage(message); + response.setResponseCode(400); + return response; + } + response.setResponseCode(papServices.getResponseCode()); + response.setDictionaryJson(json); + response.setResponseMessage(responseMessage); + } else { + response.setResponseCode(400); + response.setResponseMessage(result); + if(result!=null && result.contains("PE200")){ + status=HttpStatus.INTERNAL_SERVER_ERROR; + }else{ + status=HttpStatus.BAD_REQUEST; + } + } + return response; + } + + private String formatDictionaryJson(String result) { + String jsonString = result.substring(82); + String dictionary = dictionaryParameters.getDictionary(); + + switch (dictionary) { + case "OnapName": + jsonString = jsonString.replace("onapNameDictionaryDatas", "DictionaryDatas"); + break; + case "Attribute": + jsonString = jsonString.replace("attributeDictionaryDatas", "DictionaryDatas"); + break; + case "Action": + jsonString = jsonString.replace("actionPolicyDictionaryDatas", "DictionaryDatas"); + break; + case "BRMSParamTemplate": + jsonString = jsonString.replace("brmsParamDictionaryDatas", "DictionaryDatas"); + break; + case "VSCLAction": + jsonString = jsonString.replace("vsclActionDictionaryDatas", "DictionaryDatas"); + break; + case "VNFType": + jsonString = jsonString.replace("vnfTypeDictionaryDatas", "DictionaryDatas"); + break; + case "PEPOptions": + jsonString = jsonString.replace("pepOptionsDictionaryDatas", "DictionaryDatas"); + break; + case "Varbind": + jsonString = jsonString.replace("varbindDictionaryDatas", "DictionaryDatas"); + break; + case "Service": + jsonString = jsonString.replace("closedLoopServiceDictionaryDatas", "DictionaryDatas"); + break; + case "Site": + jsonString = jsonString.replace("closedLoopSiteDictionaryDatas", "DictionaryDatas"); + break; + case "Settings": + jsonString = jsonString.replace("settingsDictionaryDatas", "DictionaryDatas"); + break; + case "DescriptiveScope": + jsonString = jsonString.replace("descriptiveScopeDictionaryDatas", "DictionaryDatas"); + break; + case "Enforcer": + jsonString = jsonString.replace("enforcerDictionaryDatas", "DictionaryDatas"); + break; + case "ActionList": + jsonString = jsonString.replace("actionListDictionaryDatas", "DictionaryDatas"); + break; + case "ProtocolList": + jsonString = jsonString.replace("protocolListDictionaryDatas", "DictionaryDatas"); + break; + case "Zone": + jsonString = jsonString.replace("zoneDictionaryDatas", "DictionaryDatas"); + break; + case "SecurityZone": + jsonString = jsonString.replace("securityZoneDictionaryDatas", "DictionaryDatas"); + break; + case "PrefixList": + jsonString = jsonString.replace("prefixListDictionaryDatas", "DictionaryDatas"); + break; + case "AddressGroup": + jsonString = jsonString.replace("addressGroupDictionaryDatas", "DictionaryDatas"); + break; + case "ServiceGroup": + jsonString = jsonString.replace("serviceGroupDictionaryDatas", "DictionaryDatas"); + break; + case "ServiceList": + jsonString = jsonString.replace("serviceListDictionaryDatas", "DictionaryDatas"); + break; + case "TermList": + case "RuleList": + case "FirewallRuleList": + case "Term": + jsonString = jsonString.replace("termListDictionaryDatas", "DictionaryDatas"); + break; + case "MicroServiceLocation": + jsonString = jsonString.replace("microServiceLocationDictionaryDatas", "DictionaryDatas"); + break; + case "MicroServiceConfigName": + jsonString = jsonString.replace("microServiceCongigNameDictionaryDatas", "DictionaryDatas"); + break; + case "DCAEUUID": + jsonString = jsonString.replace("dcaeUUIDDictionaryDatas", "DictionaryDatas"); + break; + case "MicroServiceModels": + jsonString = jsonString.replace("microServiceModelsDictionaryDatas", "DictionaryDatas"); + break; + case "PolicyScopeService": + jsonString = jsonString.replace("psServiceDictionaryDatas", "DictionaryDatas"); + break; + case "PolicyScopeResource": + jsonString = jsonString.replace("psResourceDictionaryDatas", "DictionaryDatas"); + break; + case "PolicyScopeType": + jsonString = jsonString.replace("psTypeDictionaryDatas", "DictionaryDatas"); + break; + case "PolicyScopeClosedLoop": + jsonString = jsonString.replace("psClosedLoopDictionaryDatas", "DictionaryDatas"); + break; + case "GroupPolicyScopeList": + jsonString = jsonString.replace("groupPolicyScopeListDatas", "DictionaryDatas"); + break; + case "RiskType": + jsonString = jsonString.replace("riskTypeDictionaryDatas", "DictionaryDatas"); + break; + case "SafePolicyWarning": + jsonString = jsonString.replace("safePolicyWarningDatas", "DictionaryDatas"); + break; + case "MicroServiceDictionary": + jsonString = jsonString.replace("microServiceDictionaryDatas", "DictionaryDatas"); + break; + default: + return null; + } + return jsonString; + } + + private boolean getValidation() { + if(dictionaryParameters==null){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "Dictionary Parameters are not given."; + return false; + } + if(dictionaryParameters.getDictionaryType()==null || dictionaryParameters.getDictionaryType().toString().trim().isEmpty()){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No Dictionary Type given."; + return false; + } + if(dictionaryParameters.getDictionary()==null || dictionaryParameters.getDictionary().trim().isEmpty()){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No Dictionary given."; + return false; + } + return true; + } + + public DictionaryResponse getResult() { + return dictionaryResponse; + } + + public HttpStatus getResponseCode() { + return status; + } + +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/GetMetricsService.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/GetMetricsService.java new file mode 100644 index 000000000..a0a477cdf --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/GetMetricsService.java @@ -0,0 +1,157 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.policy.pdp.rest.api.services; + +import java.util.UUID; + +import javax.json.JsonException; + +import org.json.JSONObject; +import org.onap.policy.api.MetricsRequestParameters; +import org.onap.policy.api.MetricsResponse; +import org.onap.policy.api.PolicyException; +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; +import org.onap.policy.std.StdMetricsResponse; +import org.onap.policy.xacml.api.XACMLErrorConstants; +import org.springframework.http.HttpStatus; + +public class GetMetricsService { + private static final Logger LOGGER = FlexLogger + .getLogger(GetMetricsService.class.getName()); + + private MetricsResponse response = null; + private HttpStatus status = HttpStatus.BAD_REQUEST; + private MetricsRequestParameters metricsParameters = null; + + public GetMetricsService(String requestID) { + UUID requestUUID = null; + if (requestID != null && !requestID.isEmpty()) { + try { + requestUUID = UUID.fromString(requestID); + } catch (IllegalArgumentException e) { + requestUUID = UUID.randomUUID(); + LOGGER.info("Generated Random UUID: " + requestUUID.toString(), e); + } + } else { + requestUUID = UUID.randomUUID(); + LOGGER.info("Generated Random UUID: " + requestUUID.toString()); + } + metricsParameters = new MetricsRequestParameters(); + this.metricsParameters.setRequestID(requestUUID); + + try { + run(); + specialCheck(); + } catch (PolicyException e) { + StdMetricsResponse metricsResponse = new StdMetricsResponse(); + metricsResponse + .setResponseMessage(XACMLErrorConstants.ERROR_DATA_ISSUE + + e); + this.response = metricsResponse; + status = HttpStatus.BAD_REQUEST; + } + } + + private void specialCheck() { + if (response != null && (response.getResponseMessage() != null + && response.getResponseMessage().contains("PE300"))) { + status = HttpStatus.BAD_REQUEST; + } + } + + private void run() throws PolicyException { + // Get Result. + try { + status = HttpStatus.OK; + response = processResult(); + } catch (Exception e) { + LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + e); + status = HttpStatus.BAD_REQUEST; + throw new PolicyException(e); + } + } + + private MetricsResponse processResult() throws PolicyException { + StdMetricsResponse metricsResponse = new StdMetricsResponse(); + PAPServices papServices = new PAPServices(); + String result = (String) papServices.callPAP(null, new String[] { + "operation=get", "apiflag=getMetrics" }, + metricsParameters.getRequestID(), "metrics"); + + JSONObject json = null; + String message = null; + if (result != null) { + if (result.length() > 81 && result.contains("{")) { + try { + String responseMessage = result.substring(0, 82); + String jsonString = result.substring(result.indexOf('{'), + result.length()); + json = new JSONObject(jsonString); + + int papCount = (int) json.get("papCount"); + int pdpCount = (int) json.get("pdpCount"); + + metricsResponse.setResponseCode(papServices + .getResponseCode()); + metricsResponse.setResponseMessage(responseMessage); + metricsResponse.setPapMetrics(papCount); + metricsResponse.setPdpMetrics(pdpCount); + + } catch (JsonException | IllegalStateException e) { + String jsonString = null; + if(json != null){ + jsonString = json.toString(); + } + message = XACMLErrorConstants.ERROR_DATA_ISSUE + + " improper JSON object : " + jsonString; + LOGGER.error(message + e); + metricsResponse.setResponseMessage(message); + metricsResponse.setResponseCode(400); + return metricsResponse; + } + } else { + message = result; + metricsResponse.setResponseCode(400); + metricsResponse.setResponseMessage(message); + return metricsResponse; + } + + } else { + message = XACMLErrorConstants.ERROR_SYSTEM_ERROR + + "There was an issue with connecting to the PAP, " + + "review the logs for further debugging."; + metricsResponse.setResponseCode(500); + metricsResponse.setResponseMessage(message); + return metricsResponse; + } + + return metricsResponse; + } + + public MetricsResponse getResult() { + return response; + } + + public HttpStatus getResponseCode() { + return status; + } + +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/ListConfigService.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/ListConfigService.java new file mode 100644 index 000000000..26f491963 --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/ListConfigService.java @@ -0,0 +1,64 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.policy.pdp.rest.api.services; + +import java.util.ArrayList; +import java.util.Collection; + +import org.onap.policy.api.ConfigRequestParameters; +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; +import org.onap.policy.pdp.rest.api.models.PolicyConfig; +import org.springframework.http.HttpStatus; + +public class ListConfigService { + private static Logger LOGGER = FlexLogger.getLogger(ListConfigService.class.getName()); + + private Collection<String> results = null; + private HttpStatus status = HttpStatus.BAD_REQUEST; + + public ListConfigService(ConfigRequestParameters configRequestParameters, + String requestID) { + GetConfigService getConfigService = new GetConfigService(configRequestParameters,requestID); + Collection<PolicyConfig> policyConfigs = getConfigService.getResult(); + LOGGER.info("Transferring Config Results to List. "); + if(policyConfigs!=null){ + results = new ArrayList<String>(); + status = HttpStatus.OK; + for(PolicyConfig policyConfig : policyConfigs){ + if(policyConfig.getPolicyConfigMessage()!=null && policyConfig.getPolicyConfigMessage().contains("PE300")){ + results.add(policyConfig.getPolicyConfigMessage()); + status = HttpStatus.BAD_REQUEST; + } else { + results.add("Policy Name: " + policyConfig.getPolicyName()); + } + } + } + } + + public Collection<String> getResult() { + return results; + } + + public HttpStatus getResponseCode() { + return status; + } + +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/MicroServicesPolicyService.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/MicroServicesPolicyService.java new file mode 100644 index 000000000..22d8873d7 --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/MicroServicesPolicyService.java @@ -0,0 +1,135 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.policy.pdp.rest.api.services; + +import javax.json.JsonException; +import javax.json.JsonObject; + +import org.onap.policy.api.PolicyException; +import org.onap.policy.api.PolicyParameters; +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; +import org.onap.policy.pdp.rest.api.utils.PolicyApiUtils; +import org.onap.policy.xacml.api.XACMLErrorConstants; +import org.onap.policy.xacml.std.pap.StdPAPPolicy; + +/** + * MicroServices Policy implementation. + * + * @version 0.1 + */ +public class MicroServicesPolicyService{ + private static final Logger LOGGER = FlexLogger.getLogger(MicroServicesPolicyService.class.getName()); + + private PAPServices papServices = null; + private PolicyParameters policyParameters = null; + private String message = null; + private String policyName = null; + private String policyScope = null; + private String date = null; + private String onapName = null; + private JsonObject microServiceAttributes = null; + + public MicroServicesPolicyService(String policyName, String policyScope, PolicyParameters policyParameters, String date) { + this.policyParameters = policyParameters; + this.policyName = policyName; + this.policyScope = policyScope; + this.date = date; + papServices = new PAPServices(); + } + + public Boolean getValidation() { + if(policyParameters.getConfigBody()==null){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE+ " No Micro Service or Attributes Config Body Present"; + return false; + } + try{ + microServiceAttributes = PolicyApiUtils.stringToJsonObject(policyParameters.getConfigBody()); + } catch(JsonException| IllegalStateException e){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE+ " improper JSON object : " + policyParameters.getConfigBody(); + LOGGER.error("Error while parsing JSON body for MicroService Policy creation. ", e); + return false; + } + onapName = policyParameters.getOnapName(); + if (onapName==null||onapName.trim().isEmpty()){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No Onap Name given."; + return false; + } + boolean levelCheck = false; + levelCheck = PolicyApiUtils.isNumeric(policyParameters.getRiskLevel()); + if (!levelCheck){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "Incorrect Risk Level given."; + return false; + } + return true; + } + + public String getMessage() { + return message; + } + + public String getResult(boolean updateFlag) throws PolicyException{ + String response = null; + String operation = null; + if (updateFlag){ + operation = "update"; + } else { + operation = "create"; + } + // get values and attributes from the JsonObject + String uuid = null; + String msLocation = null; + String configName = null; + String microService = null; + String policyDescription=null; + String priority=null; + String version=null; + if (microServiceAttributes.get("service")!=null){ + microService = microServiceAttributes.get("service").toString().replace("\"", ""); + } + if (microServiceAttributes.get("uuid")!=null){ + uuid = microServiceAttributes.get("uuid").toString().replace("\"", ""); + } + if (microServiceAttributes.get("location")!=null){ + msLocation = microServiceAttributes.get("location").toString().replace("\"", ""); + } + if (microServiceAttributes.get("configName")!=null){ + configName = microServiceAttributes.get("configName").toString().replace("\"", ""); + } + if(microServiceAttributes.containsKey("description")){ + policyDescription = microServiceAttributes.get("description").toString().replace("\"", ""); + } + if(microServiceAttributes.containsKey("priority")){ + priority = microServiceAttributes.get("priority").toString().replace("\"", ""); + } + if(microServiceAttributes.containsKey("version")){ + version = microServiceAttributes.get("version").toString().replace("\"", ""); + } + // Create Policy. + StdPAPPolicy newPAPPolicy = new StdPAPPolicy("Micro Service", policyName, policyDescription, onapName, + configName, microService, uuid, msLocation, microServiceAttributes.toString(), priority, + version, updateFlag, policyScope, 0, policyParameters.getRiskLevel(), + policyParameters.getRiskType(), String.valueOf(policyParameters.getGuard()), date); + // Send JSON Object to PAP. + response = (String) papServices.callPAP(newPAPPolicy, new String[] {"operation="+operation, "apiflag=api", "policyType=Config"}, policyParameters.getRequestID(), "ConfigMS"); + LOGGER.info("Policy MS created Response: " + response); + return response; + } +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/NotificationService.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/NotificationService.java new file mode 100644 index 000000000..c1b9f63e1 --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/NotificationService.java @@ -0,0 +1,314 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.policy.pdp.rest.api.services; + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.onap.policy.api.PolicyException; +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; +import org.onap.policy.rest.XACMLRestProperties; +import org.onap.policy.utils.BusPublisher; +import org.onap.policy.xacml.api.XACMLErrorConstants; +import org.springframework.http.HttpStatus; + +import com.att.research.xacml.util.XACMLProperties; + +public class NotificationService { + public static final String BACKUPFILE = "topicBackup.txt"; + private static Logger logger = FlexLogger.getLogger(GetDictionaryService.class.getName()); + private static ConcurrentHashMap<String, Date> topicQueue = new ConcurrentHashMap<>(); + private static int interval = 15000; + private static Thread backUpthread = null; + private static Object resourceLock = new Object(); + private static List<String> dmaapList = null; + private static String dmaapServers = null; + private static String aafLogin = null; + private static String aafPassword = null; + + private String notificationResponse = null; + private HttpStatus status = HttpStatus.BAD_REQUEST; + + /** + * NotificationService Constructor. + * + * @param notificationTopic Topic Name in String format. + * @param requestID Request ID in String format. + * @param serviceType Needs to be NotificationServiceType based enumeration value. + */ + public NotificationService(String notificationTopic, String requestID, NotificationServiceType serviceType) { + init(); + if(dmaapServers==null || aafLogin==null || aafPassword==null){ + notificationResponse = XACMLErrorConstants.ERROR_DATA_ISSUE + "DMaaP properties are missing from the property file"; + return; + } + UUID requestUUID = null; + if (requestID != null && !requestID.isEmpty()) { + try { + requestUUID = UUID.fromString(requestID); + } catch (IllegalArgumentException e) { + requestUUID = UUID.randomUUID(); + logger.info("Generated Random UUID: " + requestUUID.toString(), e); + } + }else{ + requestUUID = UUID.randomUUID(); + logger.info("Generated Random UUID: " + requestUUID.toString()); + } + try{ + run(notificationTopic, serviceType); + }catch(PolicyException e){ + notificationResponse = XACMLErrorConstants.ERROR_DATA_ISSUE + e; + status = HttpStatus.BAD_REQUEST; + } + } + + private static void init() { + if(dmaapServers==null || aafLogin==null || aafPassword==null){ + dmaapServers = XACMLProperties.getProperty(XACMLRestProperties.PROP_NOTIFICATION_SERVERS); + aafLogin = XACMLProperties.getProperty("DMAAP_AAF_LOGIN"); + aafPassword = XACMLProperties.getProperty("DMAAP_AAF_PASSWORD"); + interval = Integer.parseInt(XACMLProperties.getProperty(XACMLRestProperties.PROP_NOTIFICATION_DELAY, Integer.toString(interval))); + if(dmaapServers==null || aafLogin==null || aafPassword==null){ + logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "DMaaP properties are missing from the property file "); + return; + } + // Cleanup Values. + dmaapServers= dmaapServers.trim(); + aafLogin = aafLogin.trim(); + aafPassword = aafPassword.trim(); + // Get servers to List. + if(dmaapServers.contains(",")) { + dmaapList = new ArrayList<>(Arrays.asList(dmaapServers.split("\\s*,\\s*"))); + } else { + dmaapList = new ArrayList<>(); + dmaapList.add(dmaapServers); + } + callThread(); + } + } + + private void run(String notificationTopic, NotificationServiceType serviceType) throws PolicyException{ + // Check Validation + if(notificationTopic==null){ + String message = "Notification Topic is null"; + logger.error(message); + throw new PolicyException(message); + } + notificationTopic = notificationTopic.trim(); + if(notificationTopic.isEmpty()){ + String message = "Notification Topic is not valid. "; + logger.error(message); + throw new PolicyException(message); + } + // if already exists give error.Saying already registered. + // Get Result. + try{ + status = HttpStatus.OK; + switch (serviceType) { + case ADD: + addTopic(notificationTopic); + notificationResponse = "Success!! Please give permissions to " + aafLogin + " that PDP will use to publish on given topic :" + notificationTopic + + "\n Start calling /sendHeartbeat API at an interval less than " + Integer.toString(interval) + "ms"; + break; + case REMOVE: + removeTopic(notificationTopic); + notificationResponse = "Notification Topic :" + notificationTopic + " has been removed and PDP will not publish notifications to this Topic."; + break; + case HB: + heartBeat(notificationTopic); + notificationResponse = "Success!! HeartBeat registered."; + break; + } + }catch (Exception e){ + logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + e); + status = HttpStatus.BAD_REQUEST; + throw new PolicyException(e); + } + } + + // Used to register Heart beat. + private void heartBeat(String notificationTopic) throws PolicyException{ + if(!topicQueue.isEmpty()&& topicQueue.containsKey(notificationTopic)){ + topicQueue.put(notificationTopic, new Date()); + }else{ + logger.info("Failed HeartBeat, Topic " + notificationTopic + "is not registered."); + throw new PolicyException("Failed HeartBeat, Topic " + notificationTopic + "is not registered."); + } + } + + // Used to remove Topic. + private static void removeTopic(String notificationTopic) throws PolicyException{ + if(topicQueue.containsKey(notificationTopic)){ + topicQueue.remove(notificationTopic); + removeTopicFromBackup(notificationTopic); + }else{ + logger.info("Failed Removal, Topic " + notificationTopic + " is not registered."); + throw new PolicyException("Failed Removal, Topic " + notificationTopic + " is not registered."); + } + } + + private static void removeTopicFromBackup(String notificationTopic) { + synchronized (resourceLock) { + try (Stream<String> lines = Files.lines(Paths.get(BACKUPFILE))) { + List<String> replaced = lines.map(line-> (line.split("=")[0].equals(notificationTopic)?"":line)).collect(Collectors.toList()); + try (PrintWriter pw = new PrintWriter( BACKUPFILE, "UTF-8")) { + replaced.forEach(line-> { + if(line.trim().isEmpty()){ + return; + } + pw.println(line); + }); + } + lines.close(); + } catch (IOException e) { + logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + " Could not remove/recreate the backup. ", e); + } + } + } + + // Used to add Topic. + private void addTopic(String notificationTopic) throws PolicyException{ + // validate if topic exists. + if(!topicQueue.isEmpty()&& topicQueue.containsKey(notificationTopic)){ + topicQueue.put(notificationTopic, new Date()); + logger.info("Topic " + notificationTopic + " is already registered."); + throw new PolicyException("Topic " + notificationTopic + " is already registered."); + } + topicQueue.put(notificationTopic, new Date()); + addTopictoBackUp(notificationTopic); + } + + private void addTopictoBackUp(String notificationTopic) { + synchronized (resourceLock) { + try { + Files.write(Paths.get(BACKUPFILE),( notificationTopic+"="+new Date().toString()+"\n").getBytes() , StandardOpenOption.APPEND); + } catch (IOException e) { + logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + " Could not add to the backup. ", e); + } + } + } + + // Maintains BackUp and Queue Topic. + private static void callThread() { + // Create the backup file if it not exists. + backup(); + if(backUpthread==null){ + Runnable task = () -> { + logger.info("BackUpThread not set. Starting now !"); + threadTask(); + }; + backUpthread = new Thread(task); + backUpthread.start(); + } + } + + private static void backup(){ + synchronized (resourceLock) { + try{ + File backUpFile = new File(BACKUPFILE); + if(!backUpFile.exists() && backUpFile.createNewFile()){ + logger.info(" BackUp File for topic's has been created !"); + }else{ + // File Already exists. Process file and load the Memory. + Stream<String> stream = Files.lines(Paths.get(BACKUPFILE)); + Map<String,Date> data = stream.map(line -> line.split(",")).collect(Collectors.toMap(e->e[0],e-> new Date())); + stream.close(); + data.forEach((key, value)->logger.debug("Topic retrieved from backUp : " + key + " with Time : " + value)); + topicQueue.putAll(data); + } + }catch(IOException e){ + logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + " Could not process the backup. ", e); + } + } + } + + private static void threadTask() { + while(true){ + try { + TimeUnit.MILLISECONDS.sleep(interval); + for(Map.Entry<String, Date> map : topicQueue.entrySet()){ + Date currentTime = new Date(); + long timeDiff = 0; + timeDiff = currentTime.getTime()-map.getValue().getTime(); + if(timeDiff < (interval+1500)){ + removeTopic(map.getKey()); + } + } + } catch (InterruptedException | PolicyException e) { + logger.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Error during thread execution ", e); + } + } + } + + public String getResult() { + return notificationResponse; + } + + public HttpStatus getResponseCode() { + return status; + } + + /** + * Entry point for sending Notifications from Notification Server. + * @param notification String JSON format of notification message which needs to be sent. + */ + public static void sendNotification(String notification) { + init(); + for (String topic: topicQueue.keySet()){ + sendDmaapMessage(topic, notification); + } + } + + private static void sendDmaapMessage(String topic, String notification) { + BusPublisher publisher = new BusPublisher.DmaapPublisherWrapper(dmaapList, + topic, + aafLogin, + aafPassword); + // Sending notification through DMaaP Message Router + publisher.send( "MyPartitionKey", notification); + logger.debug("Message Published on DMaaP :" + dmaapList.get(0) + "for Topic: " + topic); + publisher.close(); + } + + /** + * Notification service Type Enumeration + */ + public enum NotificationServiceType{ + ADD, + REMOVE, + HB + } + +}
\ No newline at end of file diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/PAPServices.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/PAPServices.java new file mode 100644 index 000000000..e7216e152 --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/PAPServices.java @@ -0,0 +1,656 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.policy.pdp.rest.api.services; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Base64; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import org.apache.commons.io.IOUtils; +import org.onap.policy.api.PolicyException; +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; +import org.onap.policy.pdp.rest.config.PDPApiAuth; +import org.onap.policy.rest.XACMLRestProperties; +import org.onap.policy.xacml.api.XACMLErrorConstants; +import org.onap.policy.xacml.std.pap.StdPDPPolicy; + +import com.att.research.xacml.util.XACMLProperties; +import com.fasterxml.jackson.databind.ObjectMapper; + +public class PAPServices { + private static final String SUCCESS = "success"; + private static Logger LOGGER = FlexLogger.getLogger(PAPServices.class + .getName()); + + private int responseCode = 0; + private static String environment = "DEVL"; + private static Boolean junit = false; + private static List<String> paps = null; + private static final Object papResourceLock = new Object(); + private String operation = null; + private String requestMethod = null; + private String encoding = null; + + public PAPServices() { + environment = PDPApiAuth.getEnvironment(); + if(paps == null){ + synchronized (papResourceLock) { + String urlList = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_URLS); + if(urlList == null){ + urlList = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_URL); + } + paps = Arrays.asList(urlList.split(",")); + } + } + } + + private String getPAPEncoding(){ + if(encoding == null){ + String userID = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_USERID); + String pass = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_PASS); + Base64.Encoder encoder = Base64.getEncoder(); + encoding = encoder.encodeToString((userID+":"+pass).getBytes(StandardCharsets.UTF_8)); + } + return encoding; + } + + private void rotatePAPList(){ + synchronized (papResourceLock) { + Collections.rotate(paps, -1); + } + } + + private String getPAP(){ + String result; + synchronized (papResourceLock) { + result = paps.get(0); + } + return result; + } + + public int getResponseCode() { + return responseCode; + } + + public Object callPAP(Object content, String[] parameters, UUID requestID, + String clientScope) throws PolicyException { + String response = null; + HttpURLConnection connection = null; + responseCode = 0; + // Checking for the available PAPs is done during the first Request and + // the List is going to have the connected PAP as first element. + // This makes it Real-Time to change the list depending on their + // availability. + if (paps == null || paps.isEmpty()) { + String message = XACMLErrorConstants.ERROR_DATA_ISSUE + "PAPs List is Empty."; + LOGGER.error(message); + throw new PolicyException(message); + } + int papsCount = 0; + boolean connected = false; + while (papsCount < paps.size()) { + try { + String fullURL = getPAP(); + fullURL = checkParameter(parameters, fullURL); + URL url = new URL(fullURL); + LOGGER.debug("--- Sending Request to PAP : "+ url.toString() + " ---"); + // Open the connection + connection = (HttpURLConnection) url.openConnection(); + // Setting Content-Type + connection.setRequestProperty("Content-Type","application/json"); + // Adding Authorization + connection.setRequestProperty("Authorization", "Basic "+ getPAPEncoding()); + connection.setRequestProperty("Environment", environment); + connection.setRequestProperty("ClientScope", clientScope); + // set the method and headers + connection.setRequestMethod(requestMethod); + connection.setUseCaches(false); + connection.setInstanceFollowRedirects(false); + connection.setDoOutput(true); + connection.setDoInput(true); + // Adding RequestID + if (requestID == null) { + requestID = UUID.randomUUID(); + LOGGER.info("No request ID provided, sending generated ID: " + + requestID.toString()); + } else { + LOGGER.info("Using provided request ID: " + + requestID.toString()); + } + connection.setRequestProperty("X-ECOMP-RequestID", + requestID.toString()); + if (content != null && (content instanceof InputStream)) { + // send current configuration + try (OutputStream os = connection.getOutputStream()) { + int count = IOUtils.copy((InputStream) content, os); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("copied to output, bytes=" + count); + } + } + } else if(content != null){ + // the content is an object to be encoded in JSON + ObjectMapper mapper = new ObjectMapper(); + if (!junit) { + mapper.writeValue(connection.getOutputStream(), + content); + } + } + // DO the connect + connection.connect(); + responseCode = connection.getResponseCode(); + // If Connected to PAP then break from the loop and continue + // with the Request + if (connection.getResponseCode() > 0 || junit) { + connected = true; + break; + } else { + LOGGER.debug(XACMLErrorConstants.ERROR_PERMISSIONS+ "PAP Response Code : " + connection.getResponseCode()); + rotatePAPList(); + } + } catch (Exception e) { + // This means that the PAP is not working + if (junit) { + connected = true; + break; + } + LOGGER.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + + "PAP connection Error : " + e); + rotatePAPList(); + } + papsCount++; + } + if (connected) { + // Read the Response + LOGGER.debug("connected to the PAP : " + getPAP()); + LOGGER.debug("--- Response: ---"); + if(connection != null){ + Map<String, List<String>> headers = connection.getHeaderFields(); + for (String key : headers.keySet()) { + LOGGER.debug("Header :" + key + " Value: " + headers.get(key)); + } + + try { + response = checkResponse(connection, requestID); + } catch (IOException e) { + LOGGER.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + e); + response = XACMLErrorConstants.ERROR_SYSTEM_ERROR + e; + throw new PolicyException( + XACMLErrorConstants.ERROR_SYSTEM_ERROR + + "Decoding the result ", e); + } + if (junit) { + response = SUCCESS; + } + }else{ + response = XACMLErrorConstants.ERROR_SYSTEM_ERROR + "connection is null"; + } + return response; + } else { + response = XACMLErrorConstants.ERROR_SYSTEM_ERROR + + "Unable to get valid response from PAP(s) " + paps; + return response; + } + } + + public String getActiveVersion(String policyScope, String filePrefix, String policyName, String clientScope, UUID requestID) { + String version = null; + HttpURLConnection connection = null; + String [] parameters = {"apiflag=version","policyScope="+policyScope, "filePrefix="+filePrefix, "policyName="+policyName}; + if (paps == null || paps.isEmpty()) { + LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "PAPs List is Empty."); + try { + throw new Exception(XACMLErrorConstants.ERROR_DATA_ISSUE +"PAPs List is empty."); + } catch (Exception e) { + LOGGER.error(e.getMessage() + e); + } + }else { + int papsCount = 0; + boolean connected = false; + while (papsCount < paps.size()) { + try { + String fullURL = getPAP(); + if (parameters != null && parameters.length > 0) { + String queryString = ""; + for (String p : parameters) { + queryString += "&" + p; + } + fullURL += "?" + queryString.substring(1); + } + + URL url = new URL (fullURL); + + //Open the connection + connection = (HttpURLConnection)url.openConnection(); + + // Setting Content-Type + connection.setRequestProperty("Content-Type", + "application/json"); + + // Adding Authorization + connection.setRequestProperty("Authorization", "Basic " + + getPAPEncoding()); + + connection.setRequestProperty("Environment", environment); + connection.setRequestProperty("ClientScope", clientScope); + + + //set the method and headers + connection.setRequestMethod("GET"); + connection.setUseCaches(false); + connection.setInstanceFollowRedirects(false); + connection.setDoOutput(true); + connection.setDoInput(true); + connection.setRequestProperty("X-ECOMP-RequestID", requestID.toString()); + + //DO the connect + connection.connect(); + + // If Connected to PAP then break from the loop and continue with the Request + if (connection.getResponseCode() > 0) { + connected = true; + break; + + } else { + LOGGER.debug(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "PAP connection Error"); + } + } catch (Exception e) { + // This means that the PAP is not working + LOGGER.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "PAP connection Error : " + e); + rotatePAPList(); + } + papsCount++; + } + + if (connected) { + //Read the Response + LOGGER.debug("connected to the PAP : " + getPAP()); + LOGGER.debug("--- Response: ---"); + Map<String, List<String>> headers = connection.getHeaderFields(); + for (String key : headers.keySet()) { + LOGGER.debug("Header :" + key + " Value: " + headers.get(key)); + } + try { + if (connection.getResponseCode() == 200) { + // Check for successful creation of policy + version = connection.getHeaderField("version"); + LOGGER.debug("ActiveVersion from the Header: " + version); + } else if (connection.getResponseCode() == 403) { + LOGGER.error(XACMLErrorConstants.ERROR_PERMISSIONS + "response code of the URL is " + + connection.getResponseCode() + ". PEP is not Authorized for making this Request!! \n Contact Administrator for this Scope. "); + version = "pe100"; + } else if (connection.getResponseCode() == 404) { + LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "response code of the URL is " + + connection.getResponseCode() + ". This indicates a problem with getting the version from the PAP"); + version = "pe300"; + } else { + LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "BAD REQUEST: Error occured while getting the version from the PAP. The request may be incorrect."); + } + } catch (IOException e) { + LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + e); + try { + throw new Exception(XACMLErrorConstants.ERROR_DATA_ISSUE +"ERROR in connecting to the PAP ", e); + } catch (Exception e1) { + LOGGER.error(e1.getMessage() + e1); + } + } + + } else { + LOGGER.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Unable to get valid response from PAP(s) " + paps); + try { + throw new Exception(XACMLErrorConstants.ERROR_DATA_ISSUE +"ERROR in connecting to the PAP "); + } catch (Exception e) { + LOGGER.error(e.getMessage() + e); + } + } + } + return version; + } + + private String checkResponse(HttpURLConnection connection, UUID requestID) throws IOException { + String response = null; + if (responseCode == 200 || junit) { + // Check for successful creation of policy + String isSuccess = null; + if (!junit) { // is this a junit test? + isSuccess = connection.getHeaderField("successMapKey"); + operation = connection.getHeaderField("operation"); + } else { + isSuccess = SUCCESS; + } + if (SUCCESS.equals(isSuccess)) { + if ("update".equals(operation)) { + response = "Transaction ID: " + requestID + " --Policy with the name "+ connection.getHeaderField("policyName") + + " was successfully updated. "; + if (connection.getHeaderField("safetyChecker")!=null) { + response = response + + "\n\nPolicy Safety Checker Warning: This closedLoopControlName " + + "is potentially in conflict with " + connection.getHeaderField("conflictCLName") + + " that already exists." + " See detailed information on ClosedLoop Pairs below: " + +"\n\n"+connection.getHeaderField("safetyChecker"); + } + } else if ("create".equals(operation)) { + response = "Transaction ID: " + requestID + " --Policy with the name "+ connection.getHeaderField("policyName") + + " was successfully created."; + if (connection.getHeaderField("safetyChecker")!=null) { + response = response + + "\n\nPolicy Safety Checker Warning: This closedLoopControlName " + + "is potentially in conflict with " + connection.getHeaderField("conflictCLName") + + " that already exists. " + "See detailed information on ClosedLoop Pairs below: " + +"\n\n"+connection.getHeaderField("safetyChecker"); + } + } else if ("delete".equals(operation)) { + response = "Transaction ID: " + requestID + " --The policy was successfully deleted."; + } else if ("import".equals(operation)) { + response = "Transaction ID: " + requestID + " --The policy engine import for "+ connection.getHeaderField("service") + + " was successfull."; + } else if ("createDictionary".equals(operation)) { + response = "Transaction ID: " + requestID + " --Dictionary Item was added successfully!"; + } else if ("updateDictionary".equals(operation)) { + response = "Transaction ID: " + requestID + " --Dictionary Item was updated successfully!"; + } else if ("getDictionary".equals(operation)) { + String json = null; + try { + + //get the json string from the response + InputStream is = connection.getInputStream(); + + // read the inputStream into a buffer (trick found online scans entire input looking for end-of-file) + java.util.Scanner scanner = new java.util.Scanner(is); + scanner.useDelimiter("\\A"); + json = scanner.hasNext() ? scanner.next() : ""; + scanner.close(); + + } catch (IOException e1) { + LOGGER.error(e1.getMessage() + e1); + } + response = "Transaction ID: " + requestID + " --Dictionary Items Retrieved " + json; + } else if ("getMetrics".equals(operation)) { + response = "Transaction ID: " + requestID + " --Policy Metrics Retrieved " + connection.getHeaderField("metrics"); + } + LOGGER.info(response); + } else { + String message = XACMLErrorConstants.ERROR_DATA_ISSUE + + "Operation unsuccessful, unable to complete the request!"; + LOGGER.error(message); + response = message; + } + } else if (connection.getResponseCode() == 202) { + if ("delete".equalsIgnoreCase(connection.getHeaderField("operation")) && + "true".equals(connection.getHeaderField("lockdown"))) { + response = "Transaction ID: " + + requestID + + " --Policies are locked down, please try again later."; + LOGGER.warn(response); + } + } else if (connection.getResponseCode() == 204) { + if ("push".equals(connection.getHeaderField("operation"))) { + response = "Transaction ID: " + + requestID + + " --Policy '" + + connection.getHeaderField("policyId") + + "' was successfully pushed to the PDP group '" + + connection.getHeaderField("groupId") + "'."; + LOGGER.info(response); + } + } else if (connection.getResponseCode() == 400 && connection.getHeaderField("error") != null) { + response = connection.getHeaderField("error"); + LOGGER.error(response); + } else if (connection.getResponseCode() == 403) { + response = XACMLErrorConstants.ERROR_PERMISSIONS + + "response code of the URL is " + + connection.getResponseCode() + + ". PEP is not Authorized for making this Request!! \n Contact Administrator for this Scope. "; + LOGGER.error(response); + } else if (connection.getResponseCode() == 404 && connection.getHeaderField("error") != null) { + if ("unknownGroupId".equals(connection.getHeaderField("error"))) { + response = XACMLErrorConstants.ERROR_DATA_ISSUE + + connection.getHeaderField("message") + + " Please check the pdpGroup you are requesting to move the policy to."; + LOGGER.error(response); + } + } else if (connection.getResponseCode() == 409 && connection.getHeaderField("error") != null) { + if ("modelExistsDB".equals(connection.getHeaderField("error"))) { + response = XACMLErrorConstants.ERROR_DATA_ISSUE + + "Import Value Exist Error: The import value " + + connection.getHeaderField("service") + + " already exist on the PAP. " + + "Please create a new import value."; + } else if ("policyExists".equals(connection.getHeaderField("error"))) { + response = XACMLErrorConstants.ERROR_DATA_ISSUE + + "Policy Exist Error: The Policy " + + connection.getHeaderField("policyName") + + " already exist on the PAP. " + + "Please create a new policy or use the update API to modify the existing one."; + } else if ("dictionaryItemExists".equals(connection.getHeaderField("error"))) { + response = XACMLErrorConstants.ERROR_DATA_ISSUE + + "Dictionary Item Exist Error: The Dictionary Item already exist in the database. " + + "Please create a new Dictionary Item or use the update API to modify the existing one."; + } else if ("duplicateGroup".equals(connection.getHeaderField("error"))) { + response = XACMLErrorConstants.ERROR_DATA_ISSUE + + "Group Policy Scope List Exist Error: The Group Policy Scope List for this Dictionary Item already exist in the database. " + + "Duplicate Group Policy Scope Lists for multiple groupNames is not allowed. " + + "Please review the request and verify that the groupPolicyScopeListData1 is unique compared to existing groups."; + } else if("PolicyInPDP".equals(connection.getHeaderField("error"))){ + response = XACMLErrorConstants.ERROR_DATA_ISSUE + + "Policy Exist Error: The Policy trying to be deleted is active in PDP. " + + "Active PDP Polcies are not allowed to be deleted from PAP. " + + "Please First remove the policy from PDP in order to successfully delete the Policy from PAP."; + } + LOGGER.error(response); + } else if (connection.getResponseCode() == 500 && connection.getHeaderField("error") != null) { + if ("jpautils".equals(connection.getHeaderField("error"))) { + response = XACMLErrorConstants.ERROR_SYSTEM_ERROR + + "Could not create JPAUtils instance on the PAP"; + } else if ("deleteDB".equals(connection.getHeaderField("error"))) { + response = XACMLErrorConstants.ERROR_SYSTEM_ERROR + + "Failed to delete Policy from database."; + } else if ("deleteFile".equals(connection.getHeaderField("error"))) { + response = XACMLErrorConstants.ERROR_DATA_ISSUE + + "Cannot delete the policy file"; + } else if ("groupUpdate".equals(connection.getHeaderField("error"))) { + response = connection.getHeaderField("message"); + } else if ("unknown".equals(connection.getHeaderField("error"))) { + response = XACMLErrorConstants.ERROR_UNKNOWN + + "Failed to delete the policy for an unknown reason. Check the file system and other logs for further information."; + } else if ("deleteConfig".equals(connection.getHeaderField("error"))) { + response = XACMLErrorConstants.ERROR_DATA_ISSUE + + "Cannot delete the configuration or action body file in specified location."; + } else if ("missing".equals(connection.getHeaderField("error"))) { + response = XACMLErrorConstants.ERROR_DATA_ISSUE + + "Failed to create value in database because service does match a value in file"; + } else if ("importDB".equals(connection.getHeaderField("error"))) { + response = XACMLErrorConstants.ERROR_DATA_ISSUE + + "Database errors during policy engine import"; + } else if ("policyCopyError".equals(connection.getHeaderField("error"))) { + response = XACMLErrorConstants.ERROR_PROCESS_FLOW + + connection.getHeaderField("message"); + } else if ("addGroupError".equals(connection.getHeaderField("error"))) { + response = connection.getHeaderField("message"); + } else if ("validation".equals(connection.getHeaderField("error"))){ + response = XACMLErrorConstants.ERROR_DATA_ISSUE + + "Validation errors during policy engine " + connection.getHeaderField("operation") + + " for " + connection.getHeaderField("service"); + } else if ("error".equals(connection.getHeaderField("error"))) { + response = XACMLErrorConstants.ERROR_UNKNOWN + + "Could not create or update the policy for and unknown reason"; + }else{ + response = XACMLErrorConstants.ERROR_DATA_ISSUE + + "BAD REQUEST: Error occured while attempting perform this operation.. the request may be incorrect. " + connection.getHeaderField("error"); + } + LOGGER.error(response); + } else { + response = XACMLErrorConstants.ERROR_DATA_ISSUE + + "BAD REQUEST: Error occured while attempting perform this operation.. the request may be incorrect."; + LOGGER.error(response); + } + return response; + } + + private String checkParameter(String[] parameters, String fullURL) { + if (parameters != null && parameters.length > 0) { + String queryString = ""; + for (String p : parameters) { + queryString += "&" + p; + if (p.equalsIgnoreCase("operation=post")) { + requestMethod = "POST"; + } else if (p.equalsIgnoreCase("operation=delete")) { + requestMethod = "DELETE"; + operation = "delete"; + } else if (p.equalsIgnoreCase("operation=get")) { + requestMethod = "GET"; + operation = "get"; + } else if (p.equalsIgnoreCase("operation=put")||p.equalsIgnoreCase("operation=create") + ||p.equalsIgnoreCase("operation=update")||p.equalsIgnoreCase("operation=createDictionary")){ + requestMethod = "PUT"; + if (p.equalsIgnoreCase("operation=create")) { + operation = "create"; + } else if (p.equalsIgnoreCase("operation=update")) { + operation = "update"; + } else if (p.equalsIgnoreCase("operation=createDictionary")){ + operation = "createDictionary"; + } + }else if (p.equalsIgnoreCase("importService=MICROSERVICE")||p.equalsIgnoreCase("importService=BRMSPARAM")){ + requestMethod = "PUT"; + } + } + fullURL += "?" + queryString.substring(1); + } + return fullURL; + } + + public StdPDPPolicy pushPolicy(String policyScope, String filePrefix, + String policyName, String clientScope, String pdpGroup, + UUID requestID) throws PolicyException { + String json = "{ " + + "\"apiflag\": \"api\"," + + "\"policyScope\": \""+policyScope+"\"," + + "\"filePrefix\": \""+filePrefix+"\"," + + "\"policyName\": \""+policyName+"\"," + + "\"clientScope\": \""+clientScope+"\"," + + "\"pdpGroup\": \""+pdpGroup+"\"}"; + //String response = null; + HttpURLConnection connection = null; + responseCode = 0; + if (paps == null || paps.isEmpty()) { + String message = XACMLErrorConstants.ERROR_DATA_ISSUE + "PAPs List is Empty."; + LOGGER.error(message); + throw new PolicyException(message); + } + int papsCount = 0; + boolean connected = false; + while (papsCount < paps.size()) { + try { + String fullURL = getPAP(); + fullURL = (fullURL.endsWith("/"))? fullURL+"onap/pushPolicy" : fullURL+"/onap/pushPolicy"; + URL url = new URL(fullURL); + LOGGER.debug("--- Sending Request to PAP : "+ url.toString() + " ---"); + // Open the connection + connection = (HttpURLConnection) url.openConnection(); + // Setting Content-Type + connection.setRequestProperty("Content-Type","application/json"); + // Adding Authorization + connection.setRequestProperty("Authorization", "Basic "+ getPAPEncoding()); + connection.setRequestProperty("Environment", environment); + connection.setRequestProperty("ClientScope", clientScope); + // set the method and headers + connection.setRequestMethod("POST"); + connection.setUseCaches(false); + connection.setInstanceFollowRedirects(false); + connection.setDoOutput(true); + // Adding RequestID + if (requestID == null) { + requestID = UUID.randomUUID(); + LOGGER.info("No request ID provided, sending generated ID: " + + requestID.toString()); + } else { + LOGGER.info("Using provided request ID: " + + requestID.toString()); + } + connection.setRequestProperty("X-ECOMP-RequestID", + requestID.toString()); + // DO the connect + try (OutputStream os = connection.getOutputStream()) { + int count = IOUtils.copy(new ByteArrayInputStream(json.getBytes(StandardCharsets.UTF_8)), os); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("copied to output, bytes=" + count); + } + } + connection.connect(); + responseCode = connection.getResponseCode(); + // If Connected to PAP then break from the loop and continue + // with the Request + if (connection.getResponseCode() > 0 || junit) { + connected = true; + break; + } else { + LOGGER.debug(XACMLErrorConstants.ERROR_PERMISSIONS+ "PAP Response Code : " + connection.getResponseCode()); + rotatePAPList(); + } + } catch (Exception e) { + // This means that the PAP is not working + if (junit) { + connected = true; + break; + } + LOGGER.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + + "PAP connection Error : " + e); + rotatePAPList(); + } + papsCount++; + } + if (connected) { + // Read the Response + LOGGER.debug("connected to the PAP : " + getPAP()); + LOGGER.debug("--- Response: ---"); + if(connection != null){ + Map<String, List<String>> headers = connection.getHeaderFields(); + for (String key : headers.keySet()) { + LOGGER.debug("Header :" + key + " Value: " + headers.get(key)); + } + try { + if(responseCode==202){ + StdPDPPolicy policy = (StdPDPPolicy) new ObjectInputStream(connection.getInputStream()).readObject(); + return policy; + } + } catch (IOException | ClassNotFoundException e) { + LOGGER.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + e); + throw new PolicyException( + XACMLErrorConstants.ERROR_SYSTEM_ERROR + + "Decoding the result ", e); + } + } + return null; + } else { + return null; + } + } +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/PDPServices.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/PDPServices.java new file mode 100644 index 000000000..e495c9950 --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/PDPServices.java @@ -0,0 +1,439 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.policy.pdp.rest.api.services; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.StringWriter; +import java.net.MalformedURLException; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Properties; +import java.util.UUID; + +import javax.json.Json; +import javax.json.JsonReader; +import javax.xml.XMLConstants; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.apache.commons.io.IOUtils; +import org.onap.policy.api.PolicyConfigStatus; +import org.onap.policy.api.PolicyDecision; +import org.onap.policy.api.PolicyException; +import org.onap.policy.api.PolicyResponseStatus; +import org.onap.policy.api.PolicyType; +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; +import org.onap.policy.pdp.rest.XACMLPdpServlet; +import org.onap.policy.pdp.rest.api.models.PDPResponse; +import org.onap.policy.rest.XACMLRestProperties; +import org.onap.policy.std.Matches; +import org.onap.policy.xacml.api.XACMLErrorConstants; +import org.w3c.dom.Document; + +import com.att.research.xacml.api.Advice; +import com.att.research.xacml.api.AttributeAssignment; +import com.att.research.xacml.api.Decision; +import com.att.research.xacml.api.Obligation; +import com.att.research.xacml.api.Request; +import com.att.research.xacml.api.Response; +import com.att.research.xacml.api.Result; +import com.att.research.xacml.api.pdp.PDPEngine; +import com.att.research.xacml.std.json.JSONRequest; +import com.att.research.xacml.std.json.JSONResponse; +import com.att.research.xacml.util.XACMLProperties; + +public class PDPServices { + private static final Logger LOGGER = FlexLogger.getLogger(PDPServices.class.getName()); + // Change the default Priority value here. + private static final int DEFAULT_PRIORITY = 9999; + private boolean unique = false; + private Boolean decide = false; + private Request rainydayRequest = null; + + public Collection<PDPResponse> generateRequest(String jsonString, UUID requestID, boolean unique, boolean decide) throws PolicyException{ + this.unique = unique; + this.decide = decide; + Collection<PDPResponse> results = null; + Response response = null; + // Create Request. We need XACML API here. + try { + Request request = JSONRequest.load(jsonString); + // Assign a rainy day treatment request to parse the decided treatment + if (jsonString.contains("BB_ID")) { + rainydayRequest = request; + } + // Call the PDP + LOGGER.info("--- Generating Request: ---\n" + JSONRequest.toString(request)); + response = callPDP(request, requestID); + } catch (Exception e) { + LOGGER.error(XACMLErrorConstants.ERROR_SCHEMA_INVALID + e); + PDPResponse pdpResponse = new PDPResponse(); + results = new HashSet<>(); + pdpResponse.setPolicyConfigMessage("Unable to Call PDP. Error with the URL"); + pdpResponse.setPolicyConfigStatus(PolicyConfigStatus.CONFIG_NOT_FOUND); + pdpResponse.setPolicyResponseStatus(PolicyResponseStatus.NO_ACTION_REQUIRED); + results.add(pdpResponse); + throw new PolicyException(e); + } + if (response != null) { + results = checkResponse(response); + } else { + LOGGER.info("No Response Received from PDP"); + PDPResponse pdpResponse = new PDPResponse(); + results = new HashSet<>(); + pdpResponse.setPolicyConfigMessage("No Response Received"); + pdpResponse.setPolicyConfigStatus(PolicyConfigStatus.CONFIG_NOT_FOUND); + pdpResponse.setPolicyResponseStatus(PolicyResponseStatus.NO_ACTION_REQUIRED); + results.add(pdpResponse); + } + return results; + } + + private Collection<PDPResponse> checkResponse(Response response) throws PolicyException{ + String pdpConfigLocation = null; + Collection<PDPResponse> combinedResult = new HashSet<>(); + int priority = DEFAULT_PRIORITY; + Map<Integer, PDPResponse> uniqueResult = new HashMap<>(); + for (Result result : response.getResults()) { + if (!result.getDecision().equals(Decision.PERMIT)) { + LOGGER.info("Decision not a Permit. " + result.getDecision().toString()); + PDPResponse pdpResponse = new PDPResponse(); + if (decide) { + String indeterminatePropValue = XACMLProperties.getProperty("decision.inStringdeterminate.response"); + if(result.getDecision().equals(Decision.INDETERMINATE)&& indeterminatePropValue != null){ + if("PERMIT".equalsIgnoreCase(indeterminatePropValue)){ + pdpResponse.setDecision(PolicyDecision.PERMIT); + }else{ + pdpResponse.setDecision(PolicyDecision.DENY); + } + }else{ + pdpResponse.setDecision(PolicyDecision.DENY); + } + for(Advice advice: result.getAssociatedAdvice()){ + for(AttributeAssignment attribute: advice.getAttributeAssignments()){ + pdpResponse.setDetails(attribute.getAttributeValue().getValue().toString()); + break; + } + } + combinedResult.add(pdpResponse); + return combinedResult; + } + pdpResponse.setStatus(XACMLErrorConstants.ERROR_DATA_ISSUE + "Incorrect Params passed: Decision not a Permit.",PolicyResponseStatus.NO_ACTION_REQUIRED,PolicyConfigStatus.CONFIG_NOT_FOUND); + combinedResult.add(pdpResponse); + return combinedResult; + } else { + if (decide) { + // check for Decision for decision based calls. + PDPResponse pdpResponse = new PDPResponse(); + pdpResponse.setDecision(PolicyDecision.PERMIT); + + //if this is a Rainy Day treatment decision we need to get the selected treatment + if(rainydayRequest!=null){ + pdpResponse.setDetails(getRainyDayTreatment(result)); + } else { + pdpResponse.setDetails("Decision Permit. OK!"); + } + combinedResult.add(pdpResponse); + return combinedResult; + } + if (!result.getAssociatedAdvice().isEmpty()) { + // Configurations should be in advice. + // Also PDP took actions could be here. + for (Advice advice : result.getAssociatedAdvice()) { + int config = 0, uri = 0; + String configURL = null; + String policyName = null; + String policyVersion = null; + Matches match = new Matches(); + Map<String, String> matchingConditions = new HashMap<>(); + Map<String, String> configAttributes = new HashMap<>(); + Map<String, String> responseAttributes = new HashMap<>(); + Map<String, String> actionTaken = new HashMap<>(); + PDPResponse pdpResponse = new PDPResponse(); + Map<String, String> adviseAttributes = new HashMap<>(); + for (AttributeAssignment attribute : advice.getAttributeAssignments()) { + adviseAttributes.put(attribute.getAttributeId().stringValue(), attribute.getAttributeValue().getValue().toString()); + if ("CONFIGURATION".equalsIgnoreCase(attribute.getAttributeValue().getValue().toString())) { + config++; + } else if (attribute.getDataTypeId().stringValue().endsWith("anyURI")) { + uri++; + if (uri == 1) { + configURL = attribute.getAttributeValue().getValue().toString(); + pdpConfigLocation = configURL.replace("$URL", XACMLProperties.getProperty(XACMLRestProperties.PROP_PDP_WEBAPPS)); + } else { + if (!("PDP".equalsIgnoreCase(attribute.getIssuer()))) { + throw new PolicyException(XACMLErrorConstants.ERROR_DATA_ISSUE + "Error having multiple URI in the Policy"); + } + } + } else if ("PolicyName".equalsIgnoreCase(attribute.getAttributeId().stringValue())) { + policyName = attribute.getAttributeValue().getValue().toString(); + } else if ("VersionNumber".equalsIgnoreCase(attribute.getAttributeId().stringValue())) { + policyVersion = attribute.getAttributeValue().getValue().toString(); + } else if ("Priority".equalsIgnoreCase(attribute.getAttributeId().stringValue())){ + try{ + priority = Integer.parseInt(attribute.getAttributeValue().getValue().toString()); + } catch(Exception e){ + LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE+ "Unable to Parse Integer for Priority. Setting to default value",e); + priority = DEFAULT_PRIORITY; + } + } else if (attribute.getAttributeId().stringValue().startsWith("matching")) { + matchingConditions.put(attribute.getAttributeId().stringValue() + .replaceFirst("(matching).", ""),attribute.getAttributeValue().getValue().toString()); + if ("ONAPName".equals(attribute.getAttributeId().stringValue() + .replaceFirst("(matching).", ""))) { + match.setOnapName(attribute.getAttributeValue().getValue().toString()); + } else if ("ConfigName".equals(attribute.getAttributeId().stringValue() + .replaceFirst("(matching).", ""))) { + match.setConfigName(attribute.getAttributeValue().getValue().toString()); + } else { + configAttributes.put(attribute.getAttributeId().stringValue() + .replaceFirst("(matching).", ""),attribute.getAttributeValue().getValue().toString()); + } + } else if (attribute.getAttributeId().stringValue().startsWith("key:")) { + responseAttributes.put(attribute.getAttributeId().stringValue().replaceFirst("(key).", ""), + attribute.getAttributeValue().getValue().toString()); + } else if (attribute.getAttributeId().stringValue().startsWith("controller:")) { + responseAttributes.put("$"+ attribute.getAttributeId().stringValue(), + attribute.getAttributeValue().getValue().toString()); + } else if (attribute.getAttributeId().stringValue().startsWith("dependencies:")) { + responseAttributes.put("$dependency$", + attribute.getAttributeValue().getValue().toString()); + } + } + if (!configAttributes.isEmpty()) { + match.setConfigAttributes(configAttributes); + } + if ((config == 1) && (uri == 1)) { + // If there is a configuration. + try { + LOGGER.debug("Configuration Call to : " + configURL); + pdpResponse = configCall(pdpConfigLocation); + } catch (Exception e) { + LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW+ e); + pdpResponse.setStatus("Error in Calling the Configuration URL "+ e, + PolicyResponseStatus.NO_ACTION_REQUIRED, + PolicyConfigStatus.CONFIG_NOT_FOUND); + } + pdpResponse.setPolicyName(policyName); + pdpResponse.setPolicyVersion(policyVersion); + pdpResponse.setMatchingConditions(matchingConditions); + pdpResponse.setResponseAttributes(responseAttributes); + if(!unique){ + combinedResult.add(pdpResponse); + }else{ + if(!uniqueResult.isEmpty()){ + if(uniqueResult.containsKey(priority)){ + // Not any more unique, check the matching conditions size + int oldSize = uniqueResult.get(priority).getMatchingConditions().size(); + int newSize = matchingConditions.size(); + if(oldSize < newSize){ + uniqueResult.put(priority, pdpResponse); + }else if(oldSize == newSize){ + pdpResponse = new PDPResponse(); + pdpResponse.setStatus("Two/more Policies have Same Priority and matching conditions, Please correct your policies.", + PolicyResponseStatus.NO_ACTION_REQUIRED, + PolicyConfigStatus.CONFIG_NOT_FOUND); + combinedResult.add(pdpResponse); + unique = false; + return combinedResult; + } + }else{ + uniqueResult.put(priority, pdpResponse); + } + }else{ + uniqueResult.put(priority, pdpResponse); + } + } + } else { + // Else it is Action Taken. + LOGGER.info("Action Taken by PDP. "); + actionTaken.putAll(adviseAttributes); + pdpResponse.setActionTaken(actionTaken); + pdpResponse.setPolicyResponseStatus(PolicyResponseStatus.ACTION_TAKEN); + pdpResponse.setPolicyResponseMessage("Action Taken by the PDP"); + combinedResult.add(pdpResponse); + } + } + } + if (!result.getObligations().isEmpty()) { + // Obligation actions + // Action advised should be in obligations. + for (Obligation obligation : result.getObligations()) { + Map<String, String> actionAdvised = new HashMap<>(); + PDPResponse pdpResponse = new PDPResponse(); + for (AttributeAssignment attribute : obligation.getAttributeAssignments()) { + actionAdvised.put(attribute.getAttributeId().stringValue(), + attribute.getAttributeValue().getValue().toString()); + } + pdpResponse.setActionAdvised(actionAdvised); + pdpResponse.setPolicyResponseStatus(PolicyResponseStatus.ACTION_ADVISED); + pdpResponse.setPolicyResponseMessage("Action has been Advised "); + combinedResult.add(pdpResponse); + } + } + } + } + if(unique){ + // Select Unique policy. + int minNum = DEFAULT_PRIORITY; + for(int num: uniqueResult.keySet()){ + if(num < minNum){ + minNum = num; + } + } + combinedResult.add(uniqueResult.get(minNum)); + // Turn off Unique + unique = false; + } + + return combinedResult; + } + + private String getRainyDayTreatment(Result result) { + String treatment = null; + if (rainydayRequest!=null&& !result.getAssociatedAdvice().isEmpty()) { + // Get the desired treatment for requested errorCode from the Advice + for (Advice advice : result.getAssociatedAdvice()) { + Map<String, String> adviseAttributes = new HashMap<>(); + for (AttributeAssignment attribute : advice.getAttributeAssignments()) { + adviseAttributes.put(attribute.getAttributeId().stringValue(), attribute.getAttributeValue().getValue().toString()); + if ("treatment".equalsIgnoreCase(attribute.getAttributeId().stringValue())){ + treatment = attribute.getAttributeValue().getValue().toString(); + } + } + } + } + return treatment; + } + + private PDPResponse configCall(String pdpConfigLocation) throws Exception{ + PDPResponse pdpResponse = new PDPResponse(); + if(pdpConfigLocation.contains("/")){ + pdpConfigLocation = pdpConfigLocation.replace("/", File.separator); + } + InputStream inputStream = null; + try { + inputStream = new FileInputStream(new File(pdpConfigLocation)); + try { + if (pdpConfigLocation.endsWith("json")) { + pdpResponse.setType(PolicyType.JSON); + JsonReader jsonReader = Json.createReader(inputStream); + pdpResponse.setConfig(jsonReader.readObject().toString()); + jsonReader.close(); + } else if (pdpConfigLocation.endsWith("xml")) { + pdpResponse.setType(PolicyType.XML); + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + DocumentBuilder db = null; + try { + db = dbf.newDocumentBuilder(); + Document document = db.parse(inputStream); + DOMSource domSource = new DOMSource(document); + StringWriter writer = new StringWriter(); + StreamResult result = new StreamResult(writer); + TransformerFactory tf = TransformerFactory.newInstance(); + Transformer transformer; + transformer = tf.newTransformer(); + transformer.transform(domSource, result); + pdpResponse.setConfig(writer.toString()); + } catch (Exception e) { + LOGGER.error(XACMLErrorConstants.ERROR_SCHEMA_INVALID+ e); + throw new Exception(XACMLErrorConstants.ERROR_SCHEMA_INVALID+ "Unable to parse the XML config", e); + } + } else if (pdpConfigLocation.endsWith("properties")) { + pdpResponse.setType(PolicyType.PROPERTIES); + Properties configProp = new Properties(); + configProp.load(inputStream); + Map<String, String> propVal = new HashMap<>(); + for(String name: configProp.stringPropertyNames()) { + propVal.put(name, configProp.getProperty(name)); + } + pdpResponse.setProperty(propVal); + } else if (pdpConfigLocation.endsWith("txt")) { + pdpResponse.setType(PolicyType.OTHER); + String other = IOUtils.toString(inputStream); + IOUtils.closeQuietly(inputStream); + pdpResponse.setConfig(other); + } else { + LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Config Not Found"); + pdpResponse.setPolicyConfigStatus(PolicyConfigStatus.CONFIG_NOT_FOUND); + pdpResponse.setPolicyConfigMessage("Illegal form of Configuration Type Found."); + inputStream.close(); + return pdpResponse; + } + LOGGER.info("config Retrieved " + pdpConfigLocation); + pdpResponse.setStatus("Config Retrieved! ", + PolicyResponseStatus.NO_ACTION_REQUIRED, + PolicyConfigStatus.CONFIG_RETRIEVED); + return pdpResponse; + } catch (IOException e) { + LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + e); + throw new Exception(XACMLErrorConstants.ERROR_PROCESS_FLOW + + "Cannot open a connection to the configURL", e); + } + } catch (MalformedURLException e) { + LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + e); + throw new Exception(XACMLErrorConstants.ERROR_DATA_ISSUE + "Error in ConfigURL", e); + }finally{ + if(inputStream != null){ + inputStream.close(); + } + } + } + + private Response callPDP(Request request, + UUID requestID) throws Exception{ + Response response = null; + // Get the PDPEngine + if (requestID == null) { + requestID = UUID.randomUUID(); + LOGGER.debug("No request ID provided, sending generated ID: " + requestID.toString()); + } else { + LOGGER.debug("Using provided request ID: " + requestID.toString()); + } + PDPEngine pdpEngine = XACMLPdpServlet.getPDPEngine(); + if (pdpEngine == null) { + String message = "PDPEngine not loaded."; + LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + message); + return response; + } + // call the PDPEngine to decide and give the response on the Request. + try { + response = pdpEngine.decide(request); + LOGGER.info("Response from the PDP is: \n" + JSONResponse.toString(response)); + } catch (Exception e) { + LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + e); + return null; + } + return response; + } + +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/PolicyEngineImportService.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/PolicyEngineImportService.java new file mode 100644 index 000000000..2d8af54c5 --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/PolicyEngineImportService.java @@ -0,0 +1,186 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.policy.pdp.rest.api.services; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.UUID; + +import org.onap.policy.api.ImportParameters; +import org.onap.policy.api.PolicyException; +import org.onap.policy.api.ImportParameters.IMPORT_TYPE; +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; +import org.onap.policy.utils.PolicyUtils; +import org.onap.policy.xacml.api.XACMLErrorConstants; +import org.springframework.http.HttpStatus; +import org.springframework.web.multipart.MultipartFile; + +public class PolicyEngineImportService { + private static Logger LOGGER = FlexLogger.getLogger(PolicyEngineImportService.class.getName()); + + private String importResponse = null; + private HttpStatus status = HttpStatus.BAD_REQUEST; + private String message = null; + private ImportParameters importParameters = null; + private MultipartFile file = null; + + public PolicyEngineImportService(String importParametersJson, + MultipartFile file, + String requestID) { + try { + this.importParameters = PolicyUtils.jsonStringToObject(importParametersJson, ImportParameters.class); + } catch (Exception e) { + importResponse = XACMLErrorConstants.ERROR_DATA_ISSUE + e; + status = HttpStatus.BAD_REQUEST; + // This needs to stop here in case if there a issue here. Avoiding Null pointer exceptions. + return; + } + this.file = file; + if(importParameters.getRequestID()==null){ + UUID requestUUID = null; + if (requestID != null && !requestID.isEmpty()) { + try { + requestUUID = UUID.fromString(requestID); + } catch (IllegalArgumentException e) { + requestUUID = UUID.randomUUID(); + LOGGER.info("Generated Random UUID: " + requestUUID.toString()); + } + }else{ + requestUUID = UUID.randomUUID(); + LOGGER.info("Generated Random UUID: " + requestUUID.toString()); + } + this.importParameters.setRequestID(requestUUID); + } + try{ + run(); + specialCheck(); + }catch(PolicyException e){ + importResponse = XACMLErrorConstants.ERROR_DATA_ISSUE + e; + status = HttpStatus.BAD_REQUEST; + } + } + + private void specialCheck() { + if(importResponse==null || importResponse.contains("PE200")){ + status = HttpStatus.INTERNAL_SERVER_ERROR; + }else if(importResponse.contains("BAD REQUEST") || importResponse.contains("PE300")){ + status = HttpStatus.BAD_REQUEST; + } + } + + private void run() throws PolicyException{ + // Check Validation. + if(!getValidation()){ + LOGGER.error(message); + throw new PolicyException(message); + } + // Get Result. + try{ + status = HttpStatus.OK; + importResponse = processResult(); + }catch (Exception e){ + LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + e); + status = HttpStatus.BAD_REQUEST; + throw new PolicyException(e); + } + } + + private String processResult() throws PolicyException{ + String response = null; + InputStream targetStream = null; + String fileName = file.getOriginalFilename(); + switch (importParameters.getServiceType()){ + case MICROSERVICE: + if (fileName.endsWith(".xmi") || fileName.endsWith(".zip")){ + try { + targetStream = new BufferedInputStream(file.getInputStream()); + } catch (IOException e) { + response = XACMLErrorConstants.ERROR_DATA_ISSUE + "Error in reading in the file provided"; + LOGGER.error(response + e); + return response; + } + }else{ + response = XACMLErrorConstants.ERROR_DATA_ISSUE + "Incorrect File Type Given. Please use a file of type .xmi or .zip."; + LOGGER.error(response); + return response; + } + break; + case BRMSPARAM: + if (fileName.endsWith(".drl")){ + try { + targetStream = new BufferedInputStream(file.getInputStream()); + } catch (IOException e) { + response = XACMLErrorConstants.ERROR_DATA_ISSUE + "Error in reading in the file provided"; + LOGGER.error(response + e); + return response; + } + }else{ + response = XACMLErrorConstants.ERROR_DATA_ISSUE + "Incorrect File Type Given. Please use a file of type .drl"; + LOGGER.error(response); + return response; + } + break; + default: + response = XACMLErrorConstants.ERROR_DATA_ISSUE + "Incorrect ServiceType Given. "; + LOGGER.error(response); + return response; + } + String[] parameters = new String[] {"importService=" + importParameters.getServiceType(), "serviceName=" + + importParameters.getServiceName(), "fileName=" + fileName, "version=" + importParameters.getVersion(), "description=" + importParameters.getDescription()}; + PAPServices papServices = new PAPServices(); + response = (String) papServices.callPAP(targetStream, parameters, importParameters.getRequestID(), "importMS"); + return response; + } + + private boolean getValidation() { + if(importParameters==null){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + " no Import Parameters given. "; + return false; + } + if(importParameters.getServiceName()==null || importParameters.getServiceName().trim().isEmpty()){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "Missing service name value."; + return false; + } + if(importParameters.getServiceType()==null || importParameters.getServiceType().toString().trim().isEmpty()){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "Missing service Type value."; + return false; + } + if(importParameters.getServiceType().equals(IMPORT_TYPE.MICROSERVICE) && (importParameters.getVersion()==null || importParameters.getVersion().trim().isEmpty())){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "Missing version value."; + return false; + } + if(file==null || file.isEmpty()){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "Missing File."; + return false; + } + return true; + } + + public String getResult() { + return importResponse; + } + + public HttpStatus getResponseCode() { + return status; + } + +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/PushPolicyService.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/PushPolicyService.java new file mode 100644 index 000000000..f2c6c221c --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/PushPolicyService.java @@ -0,0 +1,236 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.policy.pdp.rest.api.services; + +import java.util.UUID; + +import org.onap.policy.api.PolicyException; +import org.onap.policy.api.PushPolicyParameters; +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; +import org.onap.policy.xacml.api.XACMLErrorConstants; +import org.onap.policy.xacml.std.pap.StdPAPPolicy; +import org.onap.policy.xacml.std.pap.StdPDPPolicy; +import org.springframework.http.HttpStatus; + +import com.att.research.xacml.api.pap.PAPException; +import com.att.research.xacml.api.pap.PDPPolicy; + +public class PushPolicyService { + private static final Logger LOGGER = FlexLogger.getLogger(PushPolicyService.class.getName()); + + private String pushResult = null; + private HttpStatus status = HttpStatus.BAD_REQUEST; + private PushPolicyParameters pushPolicyParameters = null; + private String message = null; + private String policyName = null; + private String policyScope = null; + private String pdpGroup = null; + private String policyType = null; + private String filePrefix = null; + private String clientScope = null; + + public PushPolicyService(PushPolicyParameters pushPolicyParameters, + String requestID) { + this.pushPolicyParameters = pushPolicyParameters; + if(pushPolicyParameters.getRequestID()==null){ + UUID requestUUID = null; + if (requestID != null && !requestID.isEmpty()) { + try { + requestUUID = UUID.fromString(requestID); + } catch (IllegalArgumentException e) { + requestUUID = UUID.randomUUID(); + LOGGER.info("Generated Random UUID: " + requestUUID.toString(), e); + } + }else{ + requestUUID = UUID.randomUUID(); + LOGGER.info("Generated Random UUID: " + requestUUID.toString()); + } + this.pushPolicyParameters.setRequestID(requestUUID); + } + try{ + run(); + specialCheck(); + }catch(PolicyException e){ + pushResult = XACMLErrorConstants.ERROR_DATA_ISSUE + e; + status = HttpStatus.BAD_REQUEST; + } + } + + private void specialCheck() { + if(pushResult.contains("BAD REQUEST") || pushResult.contains("PE300")){ + status = HttpStatus.BAD_REQUEST; + } + } + + private void run() throws PolicyException{ + // Check Validation. + if(!getValidation()){ + LOGGER.error(message); + throw new PolicyException(message); + } + // Process Results. + try{ + status = HttpStatus.OK; + pushResult = processResult(); + }catch(Exception e){ + LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + e); + status = HttpStatus.BAD_REQUEST; + throw new PolicyException(e); + } + } + + private String processResult() throws PolicyException{ + PAPServices papServices = new PAPServices(); + String response = null; + StdPDPPolicy selectedPolicy = papServices.pushPolicy(policyScope, filePrefix, policyName, clientScope, pdpGroup, pushPolicyParameters.getRequestID()); + if(selectedPolicy==null){ + response = XACMLErrorConstants.ERROR_DATA_ISSUE + "response code of the URL is 404. " + + "This indicates a problem with getting the version from the PAP or the policy does not exist."; + LOGGER.error(response); + return response; + } + try { + LOGGER.debug("StdPDPPolicy object contains: " + selectedPolicy.getId() + ", " + selectedPolicy.getName() + ", " + selectedPolicy.getLocation().toString()); + response = copyPolicy(selectedPolicy, pdpGroup, clientScope, pushPolicyParameters.getRequestID()); + } catch (PAPException e) { + LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW+e.getMessage()); + throw new PolicyException(e); + } + LOGGER.debug("copyPolicy response: " + response); + if(response.contains("successfully")){ + response = (String) papServices.callPAP(selectedPolicy, new String[]{"groupId=" + pdpGroup, "policyId="+selectedPolicy.getId(), "apiflag=addPolicyToGroup", "operation=PUT"}, pushPolicyParameters.getRequestID(), clientScope); + } + LOGGER.debug("Final API response: " + response); + return response; + } + + private String copyPolicy(PDPPolicy policy, String group, String policyType, UUID requestID) throws PAPException { + String response = null; + if (policy == null || group == null) { + throw new PAPException("Null input policy="+policy+" group="+group); + } + try { + StdPAPPolicy location = new StdPAPPolicy(policy.getLocation()); + response = copyFile(policy.getId(), group, location, policyType, requestID); + } catch (Exception e) { + String message = "Unable to PUT policy '" + policy.getId() + "', e:" + e; + LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + message, e); + throw new PAPException(message); + } + return response; + } + + private String copyFile(String policyId, String group, StdPAPPolicy location, String clientScope, UUID requestID) throws PAPException { + String response = null; + // send the policy file to the PAP Servlet + PAPServices papService = new PAPServices(); + try { + response = (String) papService.callPAP(location, new String[] {"groupId=" + group, "policyId="+policyId, "apiflag=api", "operation=post"}, requestID, clientScope); + } catch (Exception e) { + String message = "Unable to PUT policy '" + policyId + "', e:" + e; + LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + message, e); + throw new PAPException(message); + } + return response; + } + + private boolean getValidation() { + // While Validating, extract the required values. + if (pushPolicyParameters.getPolicyName() != null + && pushPolicyParameters.getPolicyName().contains(".")) { + policyName = pushPolicyParameters.getPolicyName().substring(pushPolicyParameters.getPolicyName().lastIndexOf('.') + 1, + pushPolicyParameters.getPolicyName().length()); + policyScope = pushPolicyParameters.getPolicyName().substring(0,pushPolicyParameters.getPolicyName().lastIndexOf('.')); + LOGGER.info("Name is " + policyName + " scope is " + policyScope); + } else { + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No Policy Scope given."; + return false; + } + if (policyName==null||policyName.trim().isEmpty()){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No Policy Name given."; + return false; + } + policyType = pushPolicyParameters.getPolicyType(); + if(policyType== null || policyType.trim().isEmpty()){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No PolicyType given."; + return false; + } + + setClientScope(); + if(clientScope==null){ + return false; + } + + pdpGroup = pushPolicyParameters.getPdpGroup(); + if(pdpGroup==null || pdpGroup.trim().isEmpty()){ + pdpGroup = "default"; + } + + LOGGER.debug("clientScope is " + clientScope); + LOGGER.debug("filePrefix is " + filePrefix); + + return true; + } + + private void setClientScope() { + if ("Firewall".equalsIgnoreCase(policyType)) { + clientScope = "ConfigFirewall"; + filePrefix = "Config_FW_"; + } else if ("Action".equalsIgnoreCase(policyType)) { + clientScope = "Action"; + filePrefix = "Action_"; + } else if ("Decision".equalsIgnoreCase(policyType)) { + clientScope = "Decision"; + filePrefix = "Decision_"; + } else if ("Base".equalsIgnoreCase(policyType)) { + clientScope = "Config"; + filePrefix = "Config_"; + } else if ("ClosedLoop_Fault".equalsIgnoreCase(policyType)) { + clientScope = "ConfigClosedLoop"; + filePrefix = "Config_Fault_"; + } else if ("ClosedLoop_PM".equalsIgnoreCase(policyType)) { + clientScope = "ConfigClosedLoop"; + filePrefix = "Config_PM_"; + } else if ("MicroService".equalsIgnoreCase(policyType)) { + clientScope = "ConfigMS"; + filePrefix = "Config_MS_"; + } else if ("BRMS_RAW".equalsIgnoreCase(policyType)) { + clientScope = "ConfigBrmsRaw"; + filePrefix = "Config_BRMS_Raw_"; + } else if ("BRMS_PARAM".equalsIgnoreCase(policyType)) { + clientScope = "ConfigBrmsParam"; + filePrefix = "Config_BRMS_Param_"; + } else { + clientScope = null; + message = XACMLErrorConstants.ERROR_DATA_ISSUE + policyType + + " is not a valid Policy Type."; + } + } + + public String getResult() { + return pushResult; + } + + public HttpStatus getResponseCode() { + return status; + } + +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/SendEventService.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/SendEventService.java new file mode 100644 index 000000000..c655a2ad4 --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/SendEventService.java @@ -0,0 +1,170 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.policy.pdp.rest.api.services; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Map; +import java.util.Map.Entry; +import java.util.UUID; + +import javax.json.Json; +import javax.json.JsonArrayBuilder; +import javax.json.JsonObject; +import javax.json.JsonObjectBuilder; + +import org.onap.policy.api.EventRequestParameters; +import org.onap.policy.api.PolicyEventException; +import org.onap.policy.api.PolicyResponse; +import org.onap.policy.api.PolicyResponseStatus; +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; +import org.onap.policy.pdp.rest.api.models.PDPResponse; +import org.onap.policy.std.StdPolicyResponse; +import org.onap.policy.xacml.api.XACMLErrorConstants; +import org.springframework.http.HttpStatus; + +public class SendEventService { + private static final Logger LOGGER = FlexLogger.getLogger(SendEventService.class.getName()); + + private Collection<PolicyResponse> policyResponses = null; + private HttpStatus status = HttpStatus.BAD_REQUEST; + private EventRequestParameters eventRequestParameters = null; + private String message = null; + + public SendEventService(EventRequestParameters eventRequestParameters, + String requestID) { + this.eventRequestParameters=eventRequestParameters; + if(eventRequestParameters.getRequestID()==null){ + UUID requestUUID = null; + if (requestID != null && !requestID.isEmpty()) { + try { + requestUUID = UUID.fromString(requestID); + } catch (IllegalArgumentException e) { + requestUUID = UUID.randomUUID(); + LOGGER.info("Generated Random UUID: " + requestUUID.toString(), e); + } + }else{ + requestUUID = UUID.randomUUID(); + LOGGER.info("Generated Random UUID: " + requestUUID.toString()); + } + this.eventRequestParameters.setRequestID(requestUUID); + } + policyResponses = new ArrayList<>(); + try{ + run(); + }catch(PolicyEventException e){ + StdPolicyResponse policyResponse = new StdPolicyResponse(); + policyResponse.setPolicyResponseMessage(XACMLErrorConstants.ERROR_DATA_ISSUE+e); + policyResponse.setPolicyResponseStatus(PolicyResponseStatus.NO_ACTION_REQUIRED); + policyResponses.add(policyResponse); + status = HttpStatus.BAD_REQUEST; + } + } + + private void run() throws PolicyEventException{ + // getValidation. + if(!getValidation()){ + LOGGER.error(message); + throw new PolicyEventException(message); + } + // Generate Request. + String modelString = getModel().toString(); + LOGGER.debug("Generated JSON Request is: " + modelString); + // Process Result. + try { + PDPServices pdpServices = new PDPServices(); + status = HttpStatus.OK; + policyResponses = eventResult(pdpServices.generateRequest(modelString, eventRequestParameters.getRequestID(),false, false)); + } catch (Exception e) { + LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + e); + status = HttpStatus.BAD_REQUEST; + throw new PolicyEventException(XACMLErrorConstants.ERROR_DATA_ISSUE +e); + } + } + + private Collection<PolicyResponse> eventResult( + Collection<PDPResponse> generateRequest) { + Collection<PolicyResponse> result = new HashSet<>(); + if (generateRequest == null) { + return result; + } + if (!generateRequest.isEmpty()) { + for (PDPResponse stdStatus : generateRequest) { + StdPolicyResponse policyResponse = new StdPolicyResponse(); + policyResponse.setActionAdvised(stdStatus.getActionAdvised()); + policyResponse.setActionTaken(stdStatus.getActionTaken()); + policyResponse.setPolicyResponseMessage(stdStatus.getPolicyResponseMessage()); + policyResponse.setPolicyResponseStatus(stdStatus.getPolicyResponseStatus()); + policyResponse.setRequestAttributes(eventRequestParameters.getEventAttributes()); + result.add(policyResponse); + } + } + return result; + } + + private JsonObject getModel() throws PolicyEventException{ + JsonArrayBuilder resourceArray = Json.createArrayBuilder(); + Map<String,String> eventAttributes = eventRequestParameters.getEventAttributes(); + for (Entry<String,String> key : eventAttributes.entrySet()) { + if (key.getKey().isEmpty()) { + String message = XACMLErrorConstants.ERROR_DATA_ISSUE + "Cannot have an Empty Key"; + LOGGER.error(message); + throw new PolicyEventException(message); + } + JsonObjectBuilder resourceBuilder = Json.createObjectBuilder(); + if (key.getValue().matches("[0-9]+")) { + int val = Integer.parseInt(key.getValue()); + resourceBuilder.add("Value", val); + } else { + resourceBuilder.add("Value", key.getValue()); + } + resourceBuilder.add("AttributeId", key.getKey()); + resourceArray.add(resourceBuilder); + } + return Json.createObjectBuilder() + .add("Request", Json.createObjectBuilder() + .add("Resource",Json.createObjectBuilder() + .add("Attribute",resourceArray))) + .build(); + } + + private boolean getValidation() { + if (eventRequestParameters == null) { + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No event Parameters Given. "; + return false; + } + if (eventRequestParameters.getEventAttributes() == null || eventRequestParameters.getEventAttributes().isEmpty()){ + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No event Attributes Given. "; + return false; + } + return true; + } + + public Collection<PolicyResponse> getResult() { + return policyResponses; + } + + public HttpStatus getResponseCode() { + return status; + } + +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/utils/PolicyApiUtils.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/utils/PolicyApiUtils.java new file mode 100644 index 000000000..cd107d0ba --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/utils/PolicyApiUtils.java @@ -0,0 +1,72 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.policy.pdp.rest.api.utils; + +import java.io.StringReader; + +import javax.json.Json; +import javax.json.JsonException; +import javax.json.JsonObject; +import javax.json.JsonReader; +import javax.json.stream.JsonParsingException; + +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; + +import com.google.common.base.CharMatcher; + +public class PolicyApiUtils { + private static Logger LOGGER = FlexLogger.getLogger(PolicyApiUtils.class + .getName()); + + public static Boolean validateNONASCIICharactersAndAllowSpaces( + String jsonString) { + Boolean isValidForm = false; + if (jsonString.isEmpty()) { + LOGGER.error("The Value is empty."); + return false; + } else { + if (CharMatcher.ASCII.matchesAllOf((CharSequence) jsonString)) { + LOGGER.info("The Value does not contain ASCII Characters"); + isValidForm = true; + } else { + LOGGER.error("The Value Contains Non ASCII Characters"); + isValidForm = false; + } + } + return isValidForm; + } + + public static boolean isNumeric(String str) { + for (char c : str.toCharArray()) { + if (!Character.isDigit(c)) + return false; + } + return true; + } + + public static JsonObject stringToJsonObject(String value) + throws JsonException, JsonParsingException, IllegalStateException { + JsonReader jsonReader = Json.createReader(new StringReader(value)); + JsonObject object = jsonReader.readObject(); + jsonReader.close(); + return object; + } +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/config/PDPApiAuth.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/config/PDPApiAuth.java new file mode 100644 index 000000000..1e3a41aeb --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/config/PDPApiAuth.java @@ -0,0 +1,189 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.policy.pdp.rest.config; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Base64; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; +import java.util.StringTokenizer; + +import org.onap.policy.api.PolicyEngineException; +import org.onap.policy.common.logging.eelf.MessageCodes; +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; +import org.onap.policy.rest.XACMLRestProperties; +import org.onap.policy.utils.AAFPolicyClient; +import org.onap.policy.utils.AAFPolicyException; +import org.onap.policy.utils.PolicyUtils; +import org.onap.policy.xacml.api.XACMLErrorConstants; + +import com.att.research.xacml.util.XACMLProperties; + +public class PDPApiAuth { + private static final Logger LOGGER = FlexLogger.getLogger(PDPApiAuth.class); + + private static String environment = null; + private static Path clientPath = null; + private static Map<String,ArrayList<String>> clientMap = null; + private static Long oldModified = null; + private static AAFPolicyClient aafClient = null; + + private PDPApiAuth(){ + // Private Constructor + } + + /* + * Set Property by reading the properties File. + */ + public static void setProperty() { + environment = XACMLProperties.getProperty("ENVIRONMENT", "DEVL"); + String clientFile = XACMLProperties.getProperty(XACMLRestProperties.PROP_PEP_IDFILE); + if(clientFile!=null){ + clientPath = Paths.get(clientFile); + } + try { + aafClient = AAFPolicyClient.getInstance(XACMLProperties.getProperties()); + } catch (AAFPolicyException | IOException e) { + LOGGER.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "AAF Client Not instantiated properly."); + } + } + + /* + * Return Environment value of the PDP servlet. + */ + public static String getEnvironment() { + if(environment==null){ + setProperty(); + } + return environment; + } + + /* + * Security check for authentication and authorizations. + */ + public static boolean checkPermissions(String clientEncoding, String requestID, + String resource) { + try{ + String[] userNamePass = PolicyUtils.decodeBasicEncoding(clientEncoding); + if(userNamePass==null || userNamePass.length==0){ + String usernameAndPassword = null; + byte[] decodedBytes = Base64.getDecoder().decode(clientEncoding); + usernameAndPassword = new String(decodedBytes, "UTF-8"); + StringTokenizer tokenizer = new StringTokenizer(usernameAndPassword, ":"); + String username = tokenizer.nextToken(); + String password = tokenizer.nextToken(); + userNamePass= new String[]{username, password}; + } + LOGGER.info("User " + userNamePass[0] + " is Accessing Policy Engine API."); + Boolean result = false; + // Check Backward Compatibility. + try{ + result = clientAuth(userNamePass); + }catch(Exception e){ + LOGGER.error(MessageCodes.ERROR_PERMISSIONS, e); + } + if(!result){ + String aafPolicyNameSpace = XACMLProperties.getProperty("policy.aaf.namespace"); + String aafResource = XACMLProperties.getProperty("policy.aaf.resource"); + if(!userNamePass[0].contains("@") && aafPolicyNameSpace!= null){ + userNamePass[0] = userNamePass[0] + "@" + aafPolicyNameSpace; + }else{ + LOGGER.info("No AAF NameSpace specified in properties"); + } + if(aafResource != null){ + resource = aafResource + resource; + }else{ + LOGGER.info("No AAF Resource specified in properties"); + } + LOGGER.info("Contacting AAF in : " + environment); + result = aafClient.checkAuthPerm(userNamePass[0], userNamePass[1], resource, environment, ".*"); + } + return result; + }catch(Exception e){ + LOGGER.error(MessageCodes.ERROR_PERMISSIONS, e); + return false; + } + } + + private static Boolean clientAuth(String[] userNamePass){ + if(clientPath==null){ + setProperty(); + } + if (!clientPath.toFile().exists()) { + return false; + }else if(clientPath.toString().endsWith(".properties")) { + try { + readProps(clientPath); + if (clientMap.containsKey(userNamePass[0]) && clientMap.get(userNamePass[0]).get(0).equals(userNamePass[1])) { + return true; + } + }catch(PolicyEngineException e){ + LOGGER.error(MessageCodes.ERROR_PERMISSIONS, e); + return false; + } + } + return false; + } + + private static Map<String, ArrayList<String>> readProps(Path clientPath) throws PolicyEngineException{ + if(oldModified!=null){ + Long newModified = clientPath.toFile().lastModified(); + if (newModified == oldModified) { + return clientMap; + } + } + InputStream in; + Properties clientProp = new Properties(); + try { + in = new FileInputStream(clientPath.toFile()); + clientProp.load(in); + } catch (IOException e) { + LOGGER.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR , e); + throw new PolicyEngineException(XACMLErrorConstants.ERROR_SYSTEM_ERROR +"Cannot Load the Properties file", e); + } + // Read the Properties and Load the Clients and their scopes. + clientMap = new HashMap<>(); + // + for (Object propKey : clientProp.keySet()) { + String clientID = (String)propKey; + String clientValue = clientProp.getProperty(clientID); + if (clientValue != null && clientValue.contains(",")) { + ArrayList<String> clientValues = new ArrayList<>(Arrays.asList(clientValue.split("\\s*,\\s*"))); + if(clientValues.get(0)!=null || clientValues.get(1)!=null || clientValues.get(0).isEmpty() || clientValues.get(1).isEmpty()){ + clientMap.put(clientID, clientValues); + } + } + } + if (clientMap.isEmpty()) { + LOGGER.debug(XACMLErrorConstants.ERROR_PERMISSIONS + "No Clients ID , Client Key and Scopes are available. Cannot serve any Clients !!"); + throw new PolicyEngineException("Empty Client file"); + } + oldModified = clientPath.toFile().lastModified(); + return clientMap; + } +}
\ No newline at end of file diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/config/PDPRestConfig.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/config/PDPRestConfig.java new file mode 100644 index 000000000..078cab2aa --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/config/PDPRestConfig.java @@ -0,0 +1,77 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.policy.pdp.rest.config; + +import javax.servlet.MultipartConfigElement; + +import org.onap.policy.common.logging.eelf.PolicyLogger; +import org.onap.policy.pdp.rest.api.controller.PolicyEngineServices; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; + +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +@Configuration +@EnableWebMvc +@EnableSwagger2 +@ComponentScan(basePackageClasses = PolicyEngineServices.class) +public class PDPRestConfig extends WebMvcConfigurerAdapter{ + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/"); + registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/"); + } + + private ApiInfo apiInfo(){ + return new ApiInfoBuilder() + .title("Policy Engine REST API") + .description("This API helps to make queries against Policy Engine") + .version("3.0") + .build(); + } + + @Bean + public Docket policyAPI(){ + PolicyLogger.info("Setting up Swagger... "); + return new Docket(DocumentationType.SWAGGER_2) + .select() + .apis(RequestHandlerSelectors.basePackage("org.onap.policy.pdp.rest.api")) + .paths(PathSelectors.any()) + .build() + .apiInfo(apiInfo()); + } + + @Bean + public MultipartConfigElement multipartConfigElement(){ + String location = System.getProperty("java.io.tmpdir"); + MultipartConfigElement mp = new MultipartConfigElement(location); + return mp; + } +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/config/PDPRestInitializer.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/config/PDPRestInitializer.java new file mode 100644 index 000000000..0c1e97e62 --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/config/PDPRestInitializer.java @@ -0,0 +1,51 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.policy.pdp.rest.config; + +import javax.servlet.MultipartConfigElement; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletRegistration; + +import org.onap.policy.common.logging.eelf.PolicyLogger; +import org.springframework.web.WebApplicationInitializer; +import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; +import org.springframework.web.servlet.DispatcherServlet; + +/** + * PDP REST API configuration initialization. + * + * @version 0.1 + */ +public class PDPRestInitializer implements WebApplicationInitializer { + @Override + public void onStartup(ServletContext container) throws ServletException { + PolicyLogger.info("PDP-REST Application Initialization Started... "); + AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext(); + ctx.register(PDPRestConfig.class); + ctx.setServletContext(container); + ctx.refresh(); + ServletRegistration.Dynamic servlet = container.addServlet( + "dispatcher", new DispatcherServlet(ctx)); + servlet.setLoadOnStartup(1); + servlet.addMapping("/api/*"); + servlet.setMultipartConfig(ctx.getBean(MultipartConfigElement.class)); + } +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/impl/XACMLPdpPIPFinderFactory.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/impl/XACMLPdpPIPFinderFactory.java new file mode 100644 index 000000000..babcafaeb --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/impl/XACMLPdpPIPFinderFactory.java @@ -0,0 +1,88 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.policy.pdp.rest.impl; + +import java.util.Properties; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.onap.policy.common.logging.eelf.MessageCodes; +import org.onap.policy.common.logging.eelf.PolicyLogger; + +import org.onap.policy.xacml.api.XACMLErrorConstants; +import com.att.research.xacml.api.pip.PIPException; +import com.att.research.xacml.api.pip.PIPFinder; +import com.att.research.xacml.api.pip.PIPFinderFactory; +import com.att.research.xacml.std.pip.finders.ConfigurableEngineFinder; +import com.att.research.xacml.util.XACMLProperties; + +public class XACMLPdpPIPFinderFactory extends PIPFinderFactory { + private ConfigurableEngineFinder pipFinder; + + private static Log LOGGER = LogFactory.getLog(XACMLPdpPIPFinderFactory.class); + + public XACMLPdpPIPFinderFactory() { + } + + public XACMLPdpPIPFinderFactory(Properties properties) { + } + + @Override + public PIPFinder getFinder() throws PIPException { + if (pipFinder == null) { + synchronized(this) { + if (pipFinder == null) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Creating default configurable engine finder"); + } + pipFinder = new ConfigurableEngineFinder(); + Properties xacmlProperties = null; + try { + xacmlProperties = XACMLProperties.getProperties(); + } catch (Exception ex) { + LOGGER.error( XACMLErrorConstants.ERROR_SYSTEM_ERROR+ "Exception getting XACML properties: " + ex.getMessage(), ex); + PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, ex, "Exception getting XACML properties"); + return null; + } + if (xacmlProperties != null) { + ((ConfigurableEngineFinder)pipFinder).configure(xacmlProperties); + } + } + } + } + return pipFinder; + } + + @Override + public PIPFinder getFinder(Properties properties) throws PIPException { + if (pipFinder == null) { + synchronized(this) { + if (pipFinder == null) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Creating configurable engine finder using: " + properties); + } + pipFinder = new ConfigurableEngineFinder(); + ((ConfigurableEngineFinder)pipFinder).configure(properties); + } + } + } + return this.pipFinder; + } +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/impl/XACMLPdpPolicyFinderFactory.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/impl/XACMLPdpPolicyFinderFactory.java new file mode 100644 index 000000000..5641d8b0a --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/impl/XACMLPdpPolicyFinderFactory.java @@ -0,0 +1,208 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.pdp.rest.impl; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.onap.policy.xacml.api.XACMLErrorConstants; +import com.att.research.xacml.std.StdStatusCode; +import com.att.research.xacml.std.dom.DOMStructureException; +import com.att.research.xacml.util.FactoryException; +import com.att.research.xacml.util.XACMLProperties; +import com.att.research.xacmlatt.pdp.policy.Policy; +import com.att.research.xacmlatt.pdp.policy.PolicyDef; +import com.att.research.xacmlatt.pdp.policy.PolicyFinder; +import com.att.research.xacmlatt.pdp.policy.PolicyFinderFactory; +import com.att.research.xacmlatt.pdp.policy.dom.DOMPolicyDef; +import com.att.research.xacmlatt.pdp.std.StdPolicyFinder; +import com.google.common.base.Splitter; + +public class XACMLPdpPolicyFinderFactory extends PolicyFinderFactory { + public static final String PROP_FILE = ".file"; + public static final String PROP_URL = ".url"; + + private static Log LOGGER = LogFactory.getLog(XACMLPdpPolicyFinderFactory.class); + private List<PolicyDef> rootPolicies; + private List<PolicyDef> referencedPolicies; + private boolean needsInit = true; + + private Properties properties = null; + + public XACMLPdpPolicyFinderFactory() { + // + // Here we differ from the StdPolicyFinderFactory in that we initialize right away. + // We do not wait for a policy request to happen to look for and load policies. + // + this.init(); + } + + public XACMLPdpPolicyFinderFactory(Properties properties) { + // + // Save our properties + // + this.properties = properties; + // + // Here we differ from the StdPolicyFinderFactory in that we initialize right away. + // We do not wait for a policy request to happen to look for and load policies. + // + this.init(); + } + + /** + * Loads the <code>PolicyDef</code> for the given <code>String</code> identifier by looking first + * for a ".file" property associated with the ID and using that to load from a <code>File</code> and + * looking for a ".url" property associated with the ID and using that to load from a <code>URL</code>. + * + * @param policyId the <code>String</code> identifier for the policy + * @return a <code>PolicyDef</code> loaded from the given identifier + */ + protected PolicyDef loadPolicyDef(String policyId) { + String propLocation = null; + if (this.properties == null) { + propLocation = XACMLProperties.getProperty(policyId + PROP_FILE); + } else { + propLocation = this.properties.getProperty(policyId + PROP_FILE); + } + if (propLocation != null) { + File fileLocation = new File(propLocation); + if (!fileLocation.exists()) { + XACMLPdpPolicyFinderFactory.LOGGER.error("Policy file " + fileLocation.getAbsolutePath() + " does not exist."); + } else if (!fileLocation.canRead()) { + XACMLPdpPolicyFinderFactory.LOGGER.error("Policy file " + fileLocation.getAbsolutePath() + " cannot be read."); + } else { + try { + XACMLPdpPolicyFinderFactory.LOGGER.info("Loading policy file " + fileLocation); + PolicyDef policyDef = DOMPolicyDef.load(fileLocation); + if (policyDef != null) { + return policyDef; + } + } catch (DOMStructureException ex) { + XACMLPdpPolicyFinderFactory.LOGGER.error( XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Error loading policy file " + fileLocation.getAbsolutePath() + ": " + ex.getMessage(), ex); + return new Policy(StdStatusCode.STATUS_CODE_SYNTAX_ERROR, ex.getMessage()); + } + } + } + if (this.properties == null) { + propLocation = XACMLProperties.getProperty(policyId + PROP_URL); + } else { + propLocation = this.properties.getProperty(policyId + PROP_URL); + } + if (propLocation != null) { + InputStream is = null; + try { + URL url = new URL(propLocation); + URLConnection urlConnection = url.openConnection(); + XACMLPdpPolicyFinderFactory.LOGGER.info("Loading policy file " + url.toString()); + is = urlConnection.getInputStream(); + PolicyDef policyDef = DOMPolicyDef.load(is); + if (policyDef != null) { + return policyDef; + } + } catch (MalformedURLException ex) { + XACMLPdpPolicyFinderFactory.LOGGER.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Invalid URL " + propLocation + ": " + ex.getMessage(), ex); + } catch (IOException ex) { + XACMLPdpPolicyFinderFactory.LOGGER.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "IOException opening URL " + propLocation + ": " + ex.getMessage(), ex); + } catch (DOMStructureException ex) { + XACMLPdpPolicyFinderFactory.LOGGER.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Invalid Policy " + propLocation + ": " + ex.getMessage(), ex); + return new Policy(StdStatusCode.STATUS_CODE_SYNTAX_ERROR, ex.getMessage()); + } finally { + if (is != null) { + try { + is.close(); + } catch (IOException e) { + XACMLPdpPolicyFinderFactory.LOGGER.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Exception closing InputStream for GET of url " + propLocation + " : " + e.getMessage() + " (May be memory leak)", e); + } + } + } + } + + XACMLPdpPolicyFinderFactory.LOGGER.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR +"No known location for Policy " + policyId); + return null; + } + + /** + * Finds the identifiers for all of the policies referenced by the given property name in the + * <code>XACMLProperties</code> and loads them using the requested loading method. + * + * @param propertyName the <code>String</code> name of the property containing the list of policy identifiers + * @return a <code>List</code> of <code>PolicyDef</code>s loaded from the given property name + */ + protected List<PolicyDef> getPolicyDefs(String propertyName) { + String policyIds = XACMLProperties.getProperty(propertyName); + if (policyIds == null || policyIds.length() == 0) { + return null; + } + + Iterable<String> policyIdArray = Splitter.on(',').trimResults().omitEmptyStrings().split(policyIds); + if (policyIdArray == null) { + return null; + } + + List<PolicyDef> listPolicyDefs = new ArrayList<>(); + for (String policyId : policyIdArray) { + PolicyDef policyDef = this.loadPolicyDef(policyId); + if (policyDef != null) { + listPolicyDefs.add(policyDef); + } + } + return listPolicyDefs; + } + + protected synchronized void init() { + if (this.needsInit) { + if (XACMLPdpPolicyFinderFactory.LOGGER.isDebugEnabled()) { + XACMLPdpPolicyFinderFactory.LOGGER.debug("Initializing"); + } + this.rootPolicies = this.getPolicyDefs(XACMLProperties.PROP_ROOTPOLICIES); + this.referencedPolicies = this.getPolicyDefs(XACMLProperties.PROP_REFERENCEDPOLICIES); + if (XACMLPdpPolicyFinderFactory.LOGGER.isDebugEnabled()) { + XACMLPdpPolicyFinderFactory.LOGGER.debug("Root Policies: " + this.rootPolicies); + XACMLPdpPolicyFinderFactory.LOGGER.debug("Referenced Policies: " + this.referencedPolicies); + } + this.needsInit = false; + } + } + + @Override + public PolicyFinder getPolicyFinder() throws FactoryException { + // + // Force using any properties that were passed upon construction + // + return new StdPolicyFinder(this.rootPolicies, this.referencedPolicies, this.properties); + } + + @Override + public PolicyFinder getPolicyFinder(Properties properties) throws FactoryException { + return new StdPolicyFinder(this.rootPolicies, this.referencedPolicies, properties); + } + +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/jmx/PdpRestMBeanListener.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/jmx/PdpRestMBeanListener.java new file mode 100644 index 000000000..3232b6b8c --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/jmx/PdpRestMBeanListener.java @@ -0,0 +1,85 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.pdp.rest.jmx; + +import java.lang.management.ManagementFactory; + +import javax.management.MBeanServer; +import javax.management.ObjectName; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import javax.servlet.annotation.WebListener; + +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; +import org.onap.policy.xacml.api.XACMLErrorConstants; +/** + * + * + */ + +@WebListener +public class PdpRestMBeanListener implements ServletContextListener { + private static final String JMX_OBJECT_NAME = "PdpRest:type=PdpRestMonitor"; + private static final Logger LOGGER = FlexLogger.getLogger(PdpRestMBeanListener.class); + + private ObjectName objectName; + + @Override + public void contextInitialized(ServletContextEvent contextEvent) { + if (LOGGER.isInfoEnabled()) + LOGGER.info("Registering."); + + final MBeanServer server = ManagementFactory.getPlatformMBeanServer(); + try { + objectName = new ObjectName(JMX_OBJECT_NAME); + server.registerMBean(PdpRestMonitor.getSingleton(), objectName); + LOGGER.info("MBean registered: " + objectName); + } catch (Exception e) { + + LOGGER.warn(e.getMessage(), e); + + LOGGER.warn(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Unable to Register " +e.getMessage(), e); + + } + } + // mark + @Override + public void contextDestroyed(ServletContextEvent contextEvent) { + if (LOGGER.isInfoEnabled()) + LOGGER.info("Unregistering"); + final MBeanServer server = ManagementFactory.getPlatformMBeanServer(); + try { + objectName = new ObjectName(JMX_OBJECT_NAME); + server.unregisterMBean(objectName); + if (LOGGER.isInfoEnabled()) + LOGGER.info("MBean unregistered: " + objectName); + } catch (Exception e) { + + LOGGER.warn(e.getMessage(), e); + + LOGGER.warn(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Unable to Destroy Context" +e.getMessage(), e); + + } + } + +} + diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/jmx/PdpRestMonitor.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/jmx/PdpRestMonitor.java new file mode 100644 index 000000000..cdeec9acb --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/jmx/PdpRestMonitor.java @@ -0,0 +1,162 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.pdp.rest.jmx; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; + +import org.onap.policy.xacml.util.MetricsUtil.AvgLatency; +import org.onap.policy.xacml.util.MetricsUtil.MaxLatency; +import org.onap.policy.xacml.util.MetricsUtil.MinLatency; + +public class PdpRestMonitor implements PdpRestMonitorMBean { + private static PdpRestMonitor singleton = new PdpRestMonitor(); + + private final AtomicLong pdpEvaluationAttempts = new AtomicLong(); + private final AtomicLong pdpEvaluationSuccesses = new AtomicLong(); + private final AtomicLong pdpEvaluationNA = new AtomicLong(); + private final AtomicLong pdpEvaluationPermit = new AtomicLong(); + private final AtomicLong pdpEvaluationDeny = new AtomicLong(); + private final Map<String, Integer> policyCount = new HashMap<>(); + + private final MinLatency pdpEngineDecisionMinLatency = new MinLatency(); + private final MaxLatency pdpEngineDecisionMaxLatency = new MaxLatency(); + private final AvgLatency pdpEngineDecisionAvgLatency = new AvgLatency(); + + private volatile long lastDecisionLatency = 0; + + @Override + public long getPdpEvaluationAttempts() { + return pdpEvaluationAttempts.longValue(); + } + @Override + public long getPdpEvaluationPermit() { + return pdpEvaluationPermit.longValue(); + } + @Override + public long getPdpEvaluationDeny() { + return pdpEvaluationDeny.longValue(); + } + @Override + public long getPdpEvaluationSuccesses() { + return pdpEvaluationSuccesses.longValue(); + } + + @Override + public long getpdpEvaluationNA() { + return pdpEvaluationNA.longValue(); + } + @Override + public long getLastDecisionLatency() { + return lastDecisionLatency; + } + + /** + * @return the pdpEngineDecisionMinLatency + */ + @Override + public long getPdpEngineDecisionMinLatency() { + return pdpEngineDecisionMinLatency.min(); + } + + /** + * @return the pdpEngineDecisionMaxLatency + */ + @Override + public long getPdpEngineDecisionMaxLatency() { + return pdpEngineDecisionMaxLatency.max(); + } + + /** + * @return the pdpEngineDecisionAvgLatency + */ + @Override + public long getPdpEngineDecisionAvgLatency() { + return pdpEngineDecisionAvgLatency.avg(); + } + + @Override + public synchronized void resetLatency() { + this.lastDecisionLatency = 0; + this.pdpEngineDecisionMinLatency.reset(); + this.pdpEngineDecisionMaxLatency.reset(); + this.pdpEngineDecisionAvgLatency.reset(); + } + + @Override + public synchronized void resetCounters() { + this.pdpEvaluationAttempts.set(0); + this.pdpEvaluationSuccesses.set(0); + this.pdpEvaluationNA.set(0); + this.policyCount.clear(); + } + + public void pdpEvaluationAttempts() { + pdpEvaluationAttempts.incrementAndGet(); + } + + public void pdpEvaluationSuccess() { + pdpEvaluationSuccesses.incrementAndGet(); + } + + public void pdpEvaluationNA(){ + pdpEvaluationNA.incrementAndGet(); + } + public void pdpEvaluationPermit(){ + pdpEvaluationPermit.incrementAndGet(); + } + public void pdpEvaluationDeny(){ + pdpEvaluationDeny.incrementAndGet(); + } + + public synchronized void computeLatency(long latency) { + this.lastDecisionLatency = latency; + this.pdpEngineDecisionMinLatency.compute(latency); + this.pdpEngineDecisionMaxLatency.compute(latency); + this.pdpEngineDecisionAvgLatency.compute(latency); + } + + public void policyCountAdd(String policyID, Integer count){ + int countValue = count; + if (policyCount.containsKey(policyID)){ + countValue = countValue + policyCount.get(policyID); + } + policyCount.put(policyID, countValue); + } + public Map<String, Integer> getpolicyMap() { + return policyCount; + } + public Integer getpolicyCount(String policyID) { + if (policyCount.containsKey(policyID)){ + return policyCount.get(policyID); + } + return null; + } + + public static PdpRestMonitor getSingleton() { + return singleton; + } + public static void setSingleton(PdpRestMonitor singleton) { + PdpRestMonitor.singleton = singleton; + } + +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/jmx/PdpRestMonitorMBean.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/jmx/PdpRestMonitorMBean.java new file mode 100644 index 000000000..4acfbb7f5 --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/jmx/PdpRestMonitorMBean.java @@ -0,0 +1,40 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.pdp.rest.jmx; + +import java.util.Map; + +public interface PdpRestMonitorMBean { + public long getPdpEvaluationAttempts(); + public long getPdpEvaluationSuccesses(); + public long getLastDecisionLatency(); + public long getPdpEngineDecisionMinLatency(); + public long getPdpEngineDecisionMaxLatency(); + public long getPdpEngineDecisionAvgLatency(); + public Integer getpolicyCount(String policyID); + + public void resetLatency(); + public void resetCounters(); + public long getpdpEvaluationNA(); + public long getPdpEvaluationPermit(); + public long getPdpEvaluationDeny(); + public Map<String, Integer> getpolicyMap(); +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/notifications/ManualNotificationUpdateThread.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/notifications/ManualNotificationUpdateThread.java new file mode 100644 index 000000000..c1306572f --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/notifications/ManualNotificationUpdateThread.java @@ -0,0 +1,229 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.pdp.rest.notifications; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.security.GeneralSecurityException; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.UUID; + +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; +import org.onap.policy.rest.XACMLRestProperties; +import org.onap.policy.utils.BusConsumer; +import org.onap.policy.utils.BusPublisher; +import org.onap.policy.xacml.api.XACMLErrorConstants; + +import com.att.nsa.cambria.client.CambriaClientFactory; +import com.att.nsa.cambria.client.CambriaConsumer; +import com.att.nsa.cambria.client.CambriaPublisher; +import com.att.research.xacml.util.XACMLProperties; + +@SuppressWarnings("deprecation") +public class ManualNotificationUpdateThread implements Runnable { + + private static final Logger LOGGER = FlexLogger.getLogger(ManualNotificationUpdateThread.class); + + private static String topic = null; + private static CambriaConsumer CConsumer = null; + private static String clusterList = null; + private static String update = null; + private static BusConsumer dmaapConsumer = null; + private static List<String> dmaapList = null; + private static String propNotificationType = null; + private static String aafLogin = null; + private static String aafPassword = null; + + public volatile boolean isRunning = false; + + public synchronized boolean isRunning() { + return this.isRunning; + } + + public synchronized void terminate() { + this.isRunning = false; + } + + /** + * + * This is our thread that runs on startup if the system is configured to UEB to accept manual update requests + * + */ + @Override + public void run() { + synchronized(this) { + this.isRunning = true; + } + + URL aURL = null; + String group = UUID.randomUUID ().toString (); + String id = "0"; + String returnTopic = null; + propNotificationType = XACMLProperties.getProperty(XACMLRestProperties.PROP_NOTIFICATION_TYPE); + if ("ueb".equals(propNotificationType)){ + try { + clusterList = XACMLProperties.getProperty(XACMLRestProperties.PROP_NOTIFICATION_SERVERS).trim(); + String url = XACMLProperties.getProperty(XACMLRestProperties.PROP_PDP_ID); + aURL = new URL(url); + topic = aURL.getHost() + aURL.getPort(); + } catch (NumberFormatException e) { + LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Unable to get UEB cluster list or pdp url: ", e); + this.isRunning = false; + } catch (MalformedURLException e) { + LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Error in processing URL to create topic for Notification ", e); + } + if(aURL != null){ + String consumerTopic = aURL.getHost() + aURL.getPort() + "UpdateRequest"; + SendMessage(consumerTopic, "Starting-Topic"); + final LinkedList<String> urlList = new LinkedList<> (); + for ( String u : clusterList.split ( "," ) ){ + urlList.add ( u ); + } + + try { + CConsumer = CambriaClientFactory.createConsumer ( null, urlList, consumerTopic , group, id, 20*1000, 1000 ); + } catch (MalformedURLException | GeneralSecurityException e1) { + LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Unable to create UEB Consumer: ", e1); + } + + while (this.isRunning()) { + LOGGER.debug("While loop test _ take out "); + try { + for ( String msg : CConsumer.fetch () ){ + LOGGER.debug("Manual Notification Recieved Message " + msg + " from UEB cluster : "); + returnTopic = processMessage(msg); + if(returnTopic != null){ + SendMessage(returnTopic, update); + } + } + } catch (IOException e) { + LOGGER.debug(XACMLErrorConstants.ERROR_DATA_ISSUE + "Error in processing UEB message" + e); + } + } + LOGGER.debug("Stopping UEB Consumer loop will no longer fetch messages from the cluster"); + } + } else if ("dmaap".equals(propNotificationType)) { + String dmaapServers = null; + try { + dmaapServers = XACMLProperties.getProperty(XACMLRestProperties.PROP_NOTIFICATION_SERVERS); + topic = XACMLProperties.getProperty(XACMLRestProperties.PROP_NOTIFICATION_TOPIC); + aafLogin = XACMLProperties.getProperty("DMAAP_AAF_LOGIN"); + aafPassword = XACMLProperties.getProperty("DMAAP_AAF_PASSWORD"); + } catch (Exception e) { + LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Unable to get DMaaP servers list:", e); + this.isRunning = false; + } + + if(dmaapServers==null || topic==null){ + LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "DMaaP properties are missing from the property file "); + try { + throw new Exception(XACMLErrorConstants.ERROR_DATA_ISSUE + "DMaaP properties are missing from the property file "); + } catch (Exception e) { + LOGGER.error(e); + } + } + + dmaapServers.trim(); + topic.trim(); + aafLogin.trim(); + aafPassword.trim(); + + String consumerTopic = XACMLProperties.getProperty(XACMLRestProperties.PROP_NOTIFICATION_TOPIC).trim(); + SendMessage(consumerTopic, "Starting-Topic"); + dmaapList = new ArrayList<>(); + for ( String u : dmaapServers.split ( "," ) ){ + dmaapList.add ( u ); + } + + try { + + dmaapConsumer = new BusConsumer.DmaapConsumerWrapper(dmaapList, consumerTopic, aafLogin, aafPassword, group, id, 20*1000, 1000); + } catch (Exception e1) { + LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Unable to create DMaaP Consumer: ", e1); + } + + while (this.isRunning()) { + LOGGER.debug("While loop test _ take out "); + try { + for ( String msg : dmaapConsumer.fetch () ){ + LOGGER.debug("Manual Notification Recieved Message " + msg + " from DMaaP server : "); + returnTopic = processMessage(msg); + if(returnTopic != null){ + SendMessage(returnTopic, update); + } + } + }catch (Exception e) { + LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Error in processing DMaaP message: ", e); } + } + LOGGER.debug("Stopping DMaaP Consumer loop will no longer fetch messages from the servers"); + } + } + + private void SendMessage( String topic, String message) { + CambriaPublisher pub = null; + BusPublisher publisher = null; + try { + if ("ueb".equals(propNotificationType)) { + pub = CambriaClientFactory.createSimplePublisher (null, clusterList, topic ); + pub.send( "pdpReturnMessage", message ); + LOGGER.debug("Sending Message to UEB topic: " + topic); + pub.close(); + + } else if ("dmaap".equals(propNotificationType)){ + publisher = new BusPublisher.DmaapPublisherWrapper(dmaapList,topic,aafLogin,aafPassword); + publisher.send( "pdpReturnMessage", message ); + LOGGER.debug("Sending to Message to DMaaP topic: " + topic); + publisher.close(); + } + + } catch (Exception e) { + LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW+ "Error sending notification update: ", e); + } + if(pub != null){ + try { + pub.send( "pdpReturnMessage", message ); + LOGGER.debug("Sending to Message to tpoic" + topic); + pub.close(); + } catch (IOException e) { + LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW+ "Error sending notification update" +e); + } + } + } + + private String processMessage(String msg) { + LOGGER.debug("notification message: " + msg); + String[] UID = msg.split("=")[1].split("\""); + + String returnTopic = topic + UID[0]; + if(msg.contains("Starting-Topic")){ + return null; + } + return returnTopic; + } + public static void setUpdate(String update) { + ManualNotificationUpdateThread.update = update; + } + +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/notifications/Notification.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/notifications/Notification.java new file mode 100644 index 000000000..2d68708c8 --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/notifications/Notification.java @@ -0,0 +1,62 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.pdp.rest.notifications; + +import java.util.Collection; + +import org.onap.policy.api.NotificationType; + +/** + * Notification is the POJO which will be used to send the Notifications to the Server. + * Notification must contain the Removal and Updated policies. + * + * @version 0.2 + * + */ +public class Notification { + private Collection<Removed> removedPolicies = null; + private Collection<Updated> loadedPolicies = null; + private NotificationType notificationType= null; + + public Collection<Removed> getRemovedPolicies() { + return removedPolicies; + } + + public void setRemovedPolicies(Collection<Removed> removedPolicies) { + this.removedPolicies = removedPolicies; + } + + public Collection<Updated> getLoadedPolicies() { + return loadedPolicies; + } + + public void setLoadedPolicies(Collection<Updated> loadedPolicies) { + this.loadedPolicies = loadedPolicies; + } + + public NotificationType getNotificationType() { + return notificationType; + } + + public void setNotificationType(NotificationType notificationType){ + this.notificationType= notificationType; + } +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/notifications/NotificationController.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/notifications/NotificationController.java new file mode 100644 index 000000000..873db4b6c --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/notifications/NotificationController.java @@ -0,0 +1,415 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.pdp.rest.notifications; + +import java.io.File; +import java.io.FileFilter; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URL; +import java.net.URLConnection; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.io.filefilter.WildcardFileFilter; +import org.onap.policy.api.NotificationType; +import org.onap.policy.api.RemovedPolicy; +import org.onap.policy.api.UpdateType; +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; +import org.onap.policy.pdp.rest.PapUrlResolver; +import org.onap.policy.rest.XACMLRestProperties; +import org.onap.policy.xacml.api.XACMLErrorConstants; + +import com.att.research.xacml.api.pap.PDPPolicy; +import com.att.research.xacml.api.pap.PDPStatus; +import com.att.research.xacml.util.XACMLProperties; +import com.att.research.xacmlatt.pdp.policy.AllOf; +import com.att.research.xacmlatt.pdp.policy.AnyOf; +import com.att.research.xacmlatt.pdp.policy.Match; +import com.att.research.xacmlatt.pdp.policy.PolicyDef; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectWriter; + +/** + * NotificationController Checks for the Updated and Removed policies. It + * notifies the Server to send Notifications to the Client. + * + * @version 0.2 + * + */ +public class NotificationController { + private static final Logger LOGGER = FlexLogger.getLogger(NotificationController.class); + private static Notification record = new Notification(); + private PDPStatus oldStatus = null; + private Removed removed = null; + private Updated updated = null; + private ManualNotificationUpdateThread registerMaunualNotificationRunnable = null; + private Thread manualNotificationThread = null; + private boolean manualThreadStarted = false; + + private static String notificationJSON = null; + private static String propNotificationType = null; + private static String pdpURL = null; + private static Boolean notificationFlag = false; + + public void check(PDPStatus newStatus,Map<String, PolicyDef> policyContainer) { + boolean updated = false; + boolean removed = false; + Notification notification = new Notification(); + HashSet<Removed> removedPolicies = new HashSet<>(); + HashSet<Updated> updatedPolicies = new HashSet<>(); + + if (oldStatus == null) { + oldStatus = newStatus; + } + // Debugging purpose only. + LOGGER.debug("old config Status :" + oldStatus.getStatus()); + LOGGER.debug("new config Status :" + newStatus.getStatus()); + + // Depending on the above condition taking the Change as an Update. + if (oldStatus.getStatus().toString() != newStatus.getStatus().toString()) { + LOGGER.info("There is an Update to the PDP"); + LOGGER.debug(oldStatus.getLoadedPolicies()); + LOGGER.debug(newStatus.getLoadedPolicies()); + // Check if there is an Update/additions in the policy. + for (PDPPolicy newPolicy : newStatus.getLoadedPolicies()) { + boolean change = true; + for (PDPPolicy oldPolicy : oldStatus.getLoadedPolicies()) { + // Check if there are same policies. + if (oldPolicy.getId().equals(newPolicy.getId())) { + // Check if they have same version. + if (oldPolicy.getVersion().equals(newPolicy.getVersion())) { + change = false; + } + } + } + // if there is a change Send the notifications to the Client. + if (change) { + sendUpdate(newPolicy, policyContainer); + updated = true; + updatedPolicies.add(this.updated); + } + } + // Check if there is any removal of policy. + for (PDPPolicy oldPolicy : oldStatus.getLoadedPolicies()) { + boolean change = true; + for (PDPPolicy newPolicy : newStatus.getLoadedPolicies()) { + // Check if there are same policies. + if (oldPolicy.getId().equals(newPolicy.getId())) { + // Check if they have same version. + if (oldPolicy.getVersion().equals(newPolicy.getVersion())) { + change = false; + } + } + } + // if there is a change Send the notifications to the Client. + if (change) { + sendremove(oldPolicy); + removed = true; + removedPolicies.add(this.removed); + } + } + } + // At the end the oldStatus must be updated with the newStatus. + oldStatus = newStatus; + // Sending Notification to the Server to pass over to the clients + if (updated || removed) { + // Call the Notification Server.. + notification.setRemovedPolicies(removedPolicies); + notification.setLoadedPolicies(updatedPolicies); + notification = setUpdateTypes(updated, removed, notification); + ObjectWriter om = new ObjectMapper().writer(); + try { + notificationJSON = om.writeValueAsString(notification); + LOGGER.info(notificationJSON); + // NotificationServer Method here. + propNotificationType = XACMLProperties.getProperty(XACMLRestProperties.PROP_NOTIFICATION_TYPE); + pdpURL = XACMLProperties.getProperty(XACMLRestProperties.PROP_PDP_ID); + if (("ueb".equals(propNotificationType)||"dmaap".equals(propNotificationType)) && !manualThreadStarted) { + LOGGER.debug("Starting Thread to accept UEB or DMAAP notfications."); + this.registerMaunualNotificationRunnable = new ManualNotificationUpdateThread(); + this.manualNotificationThread = new Thread(this.registerMaunualNotificationRunnable); + this.manualNotificationThread.start(); + manualThreadStarted = true; + } + String notificationJSON= null; + notificationFlag = true; + try{ + notificationJSON= record(notification); + }catch(Exception e){ + LOGGER.error(e); + } + NotificationServer.setUpdate(notificationJSON); + ManualNotificationUpdateThread.setUpdate(notificationJSON); + } catch (JsonProcessingException e) { + LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + e.getMessage() +e); + } + } + } + + public static void sendNotification(){ + if(notificationFlag){ + try { + NotificationServer.sendNotification(notificationJSON, propNotificationType, pdpURL); + } catch (Exception e) { + LOGGER.info(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Error in sending the Event Notification: "+ e.getMessage() + e); + } + notificationFlag = false; + } + } + + private void sendremove(PDPPolicy oldPolicy) { + removed = new Removed(); + // Want to know what is removed ? + LOGGER.info("Policy removed: " + oldPolicy.getId()+ " with version number: " + oldPolicy.getVersion()); + removed.setPolicyName(oldPolicy.getId()); + removed.setVersionNo(oldPolicy.getVersion()); + removeFile(oldPolicy); + } + + private void sendUpdate(PDPPolicy newPolicy,Map<String, PolicyDef> policyContainer) { + updated = new Updated(); + // Want to know what is new ? + LOGGER.info("The new Policy is: " + newPolicy.getId()); + LOGGER.info("The version no. is: " + newPolicy.getVersion()); + updated.setPolicyName(newPolicy.getId()); + updated.setVersionNo(newPolicy.getVersion()); + updated.setUpdateType(UpdateType.NEW); + // If the policy is of Config type then retrieve its matches. + if (newPolicy.getName().contains(".Config_")) { + // Take a Configuration copy to PDP webapps. + final String urlStart = "attributeId=URLID,expression"; + final String urlEnd = "}}},{"; + String policy = policyContainer.get(newPolicy.getId()).toString(); + if(policy.contains(urlStart)){ + String urlFinePartOne = policy.substring(policy.indexOf(urlStart)+urlStart.length()); + String urlFinePart = urlFinePartOne.substring(0,urlFinePartOne.indexOf(urlEnd)); + String urlString = urlFinePart.substring(urlFinePart.indexOf("value=$URL")+6); + callPap(urlString, "Config"); + } + Iterator<AnyOf> anyOfs = policyContainer.get(newPolicy.getId()).getTarget().getAnyOfs(); + while (anyOfs.hasNext()) { + AnyOf anyOf = anyOfs.next(); + Iterator<AllOf> allOfs = anyOf.getAllOfs(); + while (allOfs.hasNext()) { + AllOf allOf = allOfs.next(); + Iterator<Match> matches = allOf.getMatches(); + HashMap<String, String> matchValues = new HashMap<>(); + while (matches.hasNext()) { + Match match = matches.next(); + LOGGER.info("Attribute Value is: "+ match.getAttributeValue().getValue().toString()); + String[] result = match.getAttributeRetrievalBase().toString().split("attributeId="); + result[1] = result[1].replaceAll("}", ""); + if (!result[1].equals("urn:oasis:names:tc:xacml:1.0:subject:subject-id")) { + LOGGER.info("Attribute id is: " + result[1]); + } + matchValues.put(result[1], match.getAttributeValue().getValue().toString()); + LOGGER.info("Match is : "+ result[1]+ " , " + match.getAttributeValue().getValue().toString()); + } + updated.setMatches(matchValues); + } + } + }else if(newPolicy.getName().contains(".Action_")){ + // Take Configuration copy to PDP Webapps. + // Action policies have .json as extension. + String urlString = "$URL/Action/" + newPolicy.getId().substring(0, newPolicy.getId().lastIndexOf(".")) + ".json"; + callPap(urlString, "Action"); + } + } + + // Adding this for Recording the changes to serve Polling requests.. + private static String record(Notification notification) throws Exception { + // Initialization with updates. + if (record.getRemovedPolicies() == null || record.getLoadedPolicies() == null) { + record.setRemovedPolicies(notification.getRemovedPolicies()); + record.setLoadedPolicies(notification.getLoadedPolicies()); + } else { + // Check if there is anything new and update the record.. + if (record.getLoadedPolicies() != null || record.getRemovedPolicies() != null) { + HashSet<Removed> removedPolicies = (HashSet<Removed>) record.getRemovedPolicies(); + HashSet<Updated> updatedPolicies = (HashSet<Updated>) record.getLoadedPolicies(); + + // Checking with New updated policies. + if (notification.getLoadedPolicies() != null && !notification.getLoadedPolicies().isEmpty()) { + for (Updated newUpdatedPolicy : notification.getLoadedPolicies()) { + // If it was removed earlier then we need to remove from our record + Iterator<Removed> oldRemovedPolicy = removedPolicies.iterator(); + while (oldRemovedPolicy.hasNext()) { + Removed policy = oldRemovedPolicy.next(); + if (newUpdatedPolicy.getPolicyName().equals(policy.getPolicyName())) { + if (newUpdatedPolicy.getVersionNo().equals(policy.getVersionNo())) { + oldRemovedPolicy.remove(); + } + } + } + // If it was previously updated need to Overwrite it to the record. + Iterator<Updated> oldUpdatedPolicy = updatedPolicies.iterator(); + while (oldUpdatedPolicy.hasNext()) { + Updated policy = oldUpdatedPolicy.next(); + if (newUpdatedPolicy.getPolicyName().equals(policy.getPolicyName())) { + if (newUpdatedPolicy.getVersionNo().equals(policy.getVersionNo())) { + oldUpdatedPolicy.remove(); + } + } + } + updatedPolicies.add(newUpdatedPolicy); + } + } + // Checking with New Removed policies. + if (notification.getRemovedPolicies() != null && !notification.getRemovedPolicies().isEmpty()) { + for (Removed newRemovedPolicy : notification.getRemovedPolicies()) { + // If it was previously removed Overwrite it to the record. + Iterator<Removed> oldRemovedPolicy = removedPolicies.iterator(); + while (oldRemovedPolicy.hasNext()) { + Removed policy = oldRemovedPolicy.next(); + if (newRemovedPolicy.getPolicyName().equals(policy.getPolicyName())) { + if (newRemovedPolicy.getVersionNo().equals(policy.getVersionNo())) { + oldRemovedPolicy.remove(); + } + } + } + // If it was added earlier then we need to remove from our record. + Iterator<Updated> oldUpdatedPolicy = updatedPolicies.iterator(); + while (oldUpdatedPolicy.hasNext()) { + Updated policy = oldUpdatedPolicy.next(); + if (newRemovedPolicy.getPolicyName().equals(policy.getPolicyName())) { + if (newRemovedPolicy.getVersionNo().equals(policy.getVersionNo())) { + oldUpdatedPolicy.remove(); + } + } + } + removedPolicies.add(newRemovedPolicy); + } + } + record.setRemovedPolicies(removedPolicies); + record.setLoadedPolicies(updatedPolicies); + } + } + // Send the Result to the caller. + ObjectWriter om = new ObjectMapper().writer(); + String json = null; + try { + json = om.writeValueAsString(record); + } catch (JsonProcessingException e) { + LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + e.getMessage() + e); + } + LOGGER.info(json); + return json; + } + + private static Notification setUpdateTypes(boolean updated, boolean removed, Notification notification) { + if(notification!=null){ + if(updated && removed){ + notification.setNotificationType(NotificationType.BOTH); + if(notification.getLoadedPolicies()!=null){ + HashSet<Updated> updatedPolicies = new HashSet<>(); + for(Updated oldUpdatedPolicy: notification.getLoadedPolicies()){ + Updated updatePolicy = oldUpdatedPolicy; + if(notification.getRemovedPolicies()!=null){ + for(RemovedPolicy removedPolicy: notification.getRemovedPolicies()){ + String regex = ".(\\d)*.xml"; + if(removedPolicy.getPolicyName().replaceAll(regex, "").equals(oldUpdatedPolicy.getPolicyName().replaceAll(regex, ""))){ + updatePolicy.setUpdateType(UpdateType.UPDATE); + break; + } + } + } + updatedPolicies.add(updatePolicy); + } + notification.setLoadedPolicies(updatedPolicies); + } + }else if(updated){ + notification.setNotificationType(NotificationType.UPDATE); + }else if(removed){ + notification.setNotificationType(NotificationType.REMOVE); + } + } + return notification; + } + + private void removeFile(PDPPolicy oldPolicy) { + try{ + Path removedPolicyFile = Paths.get(XACMLProperties.getProperty(XACMLRestProperties.PROP_PDP_CONFIG)+File.separator+oldPolicy.getId()); + Files.deleteIfExists(removedPolicyFile); + boolean delete=false; + File dir= null; + if(oldPolicy.getName().startsWith("Config")){ + delete = true; + dir = new File(XACMLProperties.getProperty(XACMLRestProperties.PROP_PDP_WEBAPPS)+File.separator+"Config"); + }else if(oldPolicy.getName().startsWith("Action")){ + delete = true; + dir = new File(XACMLProperties.getProperty(XACMLRestProperties.PROP_PDP_WEBAPPS)+File.separator+"Action"); + } + if(delete){ + FileFilter fileFilter = new WildcardFileFilter(oldPolicy.getId().substring(0, oldPolicy.getId().lastIndexOf("."))+".*"); + File[] configFile = dir.listFiles(fileFilter); + if(configFile.length==1){ + Files.deleteIfExists(configFile[0].toPath()); + } + } + }catch(Exception e){ + LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Couldn't remove the policy/config file " + oldPolicy.getName() + e); + } + } + + private void callPap(String urlString, String type) { + Path configLocation = Paths.get(XACMLProperties.getProperty(XACMLRestProperties.PROP_PDP_WEBAPPS)+File.separator+type); + if(Files.notExists(configLocation)){ + try { + Files.createDirectories(configLocation); + } catch (IOException e) { + LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW +"Failed to create config directory: " + configLocation.toAbsolutePath().toString(), e); + } + } + PapUrlResolver papUrls = PapUrlResolver.getInstance(); + while(papUrls.hasMoreUrls()){ + String papPath = papUrls.getUrl(); + papPath = papPath.substring(0, papPath.lastIndexOf("/pap")); + String papAddress= urlString.replace("$URL", papPath); + String fileName = papAddress.substring(papAddress.lastIndexOf("/")+1); + String fileLocation = configLocation.toString() + File.separator + fileName; + try { + URL papURL = new URL(papAddress); + LOGGER.info("Calling " +papAddress + " for Configuration Copy."); + URLConnection urlConnection = papURL.openConnection(); + File file= new File(fileLocation); + try (InputStream is = urlConnection.getInputStream(); + OutputStream os = new FileOutputStream(file)) { + IOUtils.copy(is, os); + break; + } + } catch (Exception e) { + LOGGER.error(e + e.getMessage()); + } + papUrls.getNext(); + } + } +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/notifications/NotificationServer.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/notifications/NotificationServer.java new file mode 100644 index 000000000..690d8c517 --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/notifications/NotificationServer.java @@ -0,0 +1,224 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.pdp.rest.notifications; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.security.GeneralSecurityException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.TimeUnit; + +import javax.websocket.OnClose; +import javax.websocket.OnError; +import javax.websocket.OnMessage; +import javax.websocket.OnOpen; +import javax.websocket.Session; +import javax.websocket.server.ServerEndpoint; + +import org.onap.policy.common.logging.eelf.MessageCodes; +import org.onap.policy.common.logging.eelf.PolicyLogger; +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; +import org.onap.policy.pdp.rest.api.services.NotificationService; +import org.onap.policy.rest.XACMLRestProperties; +import org.onap.policy.utils.BusPublisher; +import org.onap.policy.xacml.api.XACMLErrorConstants; + +import com.att.nsa.cambria.client.CambriaBatchingPublisher; +import com.att.nsa.cambria.client.CambriaClientBuilders; +import com.att.research.xacml.util.XACMLProperties; + + +/** + * The NotificationServer sends the Server Notifications to the Clients once there is any Event. + * WebSockets is being used as a medium for sending Notifications. + * UEB is being used as a medium for sending Notifications. + * DMAAP is being used as a medium for sending Notifications. + * + * @version 0.2 + * + **/ +@ServerEndpoint(value = "/notifications") +public class NotificationServer { + private static final Logger LOGGER = FlexLogger.getLogger(NotificationServer.class); + private static Queue<Session> queue = new ConcurrentLinkedQueue<>(); + private static String update = null; + private static String hosts = null; + private static URL aURL = null; + + @OnOpen + public void openConnection(Session session) { + LOGGER.info("Session Connected: " + session.getId()); + queue.add(session); + } + + @OnClose + public void closeConnection(Session session) { + queue.remove(session); + } + + @OnError + public void error(Session session, Throwable t) { + queue.remove(session); + LOGGER.info(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Session Error for : " + session.getId() + " Error: " + t.getMessage()); + + } + + @OnMessage + public void Message(String message, Session session) { + + if(message.equalsIgnoreCase("Manual")) { + try { + session.getBasicRemote().sendText(update); + session.close(); + } catch (IOException e) { + LOGGER.info(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Error in sending the Event Notification: "+ e.getMessage() + e); + LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Error sending Message update"); + } + } + } + + public static void sendNotification(String notification, String propNotificationType, String pdpURL) throws Exception { + + LOGGER.debug("Notification set to " + propNotificationType); + if (propNotificationType.equals("ueb")){ + + String topic = null; + try { + aURL = new URL(pdpURL); + topic = aURL.getHost() + aURL.getPort(); + } catch (MalformedURLException e1) { + pdpURL = pdpURL.replace("/", ""); + topic = pdpURL.replace(":", ""); + LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Error in parsing out pdpURL for UEB notfication "); + PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e1, "Error in parsing out pdpURL for UEB notfication "); + } + hosts = XACMLProperties.getProperty(XACMLRestProperties.PROP_NOTIFICATION_SERVERS); + String apiKey = XACMLProperties.getProperty(XACMLRestProperties.PROP_UEB_API_KEY); + String apiSecret = XACMLProperties.getProperty(XACMLRestProperties.PROP_UEB_API_SECRET); + + LOGGER.debug("Creating Publisher for host: " + hosts + " with topic: " + topic); + CambriaBatchingPublisher pub = null; + try { + if(hosts==null || topic==null || apiKey==null || apiSecret==null){ + LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "UEB properties are missing from the property file "); + throw new Exception(XACMLErrorConstants.ERROR_DATA_ISSUE + "UEB properties are missing from the property file "); + } + + hosts.trim(); + topic.trim(); + apiKey.trim(); + apiSecret.trim(); + pub = new CambriaClientBuilders.PublisherBuilder () + .usingHosts ( hosts ) + .onTopic ( topic ) + .authenticatedBy ( apiKey, apiSecret ) + .build () + ; + + } catch (MalformedURLException e1) { + LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Error creating the UEB publisher" + e1.getMessage()); + } catch (GeneralSecurityException e1) { + LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Error creating the UEB publisher" + e1.getMessage() +e1); + } + if(pub != null){ + try { + pub.send( "MyPartitionKey", notification ); + } catch (IOException e) { + LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Error sending notification update" + e.getMessage() + e); + } + // close the publisher. The batching publisher does not send events + // immediately, so you MUST use close to send any remaining messages. + // You provide the amount of time you're willing to wait for the sends + // to succeed before giving up. If any messages are unsent after that time, + // they're returned to your app. You could, for example, persist to disk + // and try again later. + final List<?> stuck = pub.close ( 20, TimeUnit.SECONDS ); + + if (!stuck.isEmpty()){ + LOGGER.error( stuck.size() + " messages unsent" ); + }else{ + LOGGER.info( "Clean exit; all messages sent: " + notification ); + } + } + } else if (propNotificationType.equals("dmaap")) { + + // Setting up the Publisher for DMaaP MR + String dmaapServers = XACMLProperties.getProperty(XACMLRestProperties.PROP_NOTIFICATION_SERVERS); + String topic = XACMLProperties.getProperty(XACMLRestProperties.PROP_NOTIFICATION_TOPIC); + String aafLogin = XACMLProperties.getProperty("DMAAP_AAF_LOGIN"); + String aafPassword = XACMLProperties.getProperty("DMAAP_AAF_PASSWORD"); + + try { + if(dmaapServers==null || topic==null){ + LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "DMaaP properties are missing from the property file "); + throw new Exception(XACMLErrorConstants.ERROR_DATA_ISSUE + "DMaaP properties are missing from the property file "); + } + + dmaapServers.trim(); + topic.trim(); + aafLogin.trim(); + aafPassword.trim(); + + List<String> dmaapList = null; + if(dmaapServers.contains(",")) { + dmaapList = new ArrayList<>(Arrays.asList(dmaapServers.split("\\s*,\\s*"))); + } else { + dmaapList = new ArrayList<>(); + dmaapList.add(dmaapServers); + } + + BusPublisher publisher = + new BusPublisher.DmaapPublisherWrapper(dmaapList, + topic, + aafLogin, + aafPassword); + + // Sending notification through DMaaP Message Router + publisher.send( "MyPartitionKey", notification); + LOGGER.debug("Message Published on DMaaP :" + dmaapList.get(0) + "for Topic: " + topic); + publisher.close(); + + } catch (Exception e) { + LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Error sending notification update" + e.getMessage() + e); + } + } + + for(Session session: queue) { + try { + session.getBasicRemote().sendText(notification); + } catch (IOException e) { + LOGGER.info(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Error in sending the Event Notification: "+ e.getMessage() + e); + } + } + NotificationService.sendNotification(notification); + } + + public static void setUpdate(String update) { + NotificationServer.update = update; + } + +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/notifications/Removed.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/notifications/Removed.java new file mode 100644 index 000000000..f6c9bfaa5 --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/notifications/Removed.java @@ -0,0 +1,54 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.pdp.rest.notifications; + +import org.onap.policy.api.RemovedPolicy; + + +/** + * Removal is the POJO for removal updates of the Policy. + * It must have the Policy removed and its Version number. + * + * @version 0.2 + * + */ +public class Removed implements RemovedPolicy{ + + private String policyName = null; + private String versionNo = null; + + public String getVersionNo() { + return versionNo; + } + + public void setVersionNo(String versionNo) { + this.versionNo = versionNo; + } + + public String getPolicyName() { + return policyName; + } + + public void setPolicyName(String policyName) { + this.policyName = policyName; + } + +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/notifications/Updated.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/notifications/Updated.java new file mode 100644 index 000000000..002886de9 --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/notifications/Updated.java @@ -0,0 +1,74 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.pdp.rest.notifications; + +import java.util.HashMap; + +import org.onap.policy.api.LoadedPolicy; +import org.onap.policy.api.UpdateType; + +/** + * Updated is the POJO which consists of any new or Updated Policy information. + * It must hold the Policy Name, version Number, Matches. + * + * @version 0.2 + * + */ +public class Updated implements LoadedPolicy{ + private String policyName = null; + private String versionNo = null; + private HashMap<String,String> matches = null; + private UpdateType updateType = null; + + public String getPolicyName() { + return policyName; + } + + public void setPolicyName(String policyName) { + this.policyName = policyName; + } + + public String getVersionNo() { + return versionNo; + } + + public void setVersionNo(String versionNo) { + this.versionNo = versionNo; + } + + public HashMap<String,String> getMatches() { + return matches; + } + + public void setMatches(HashMap<String,String> matches) { + this.matches = matches; + } + + @Override + public UpdateType getUpdateType() { + return this.updateType; + } + + public void setUpdateType(UpdateType updateType){ + this.updateType = updateType; + } + +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/notifications/package-info.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/notifications/package-info.java new file mode 100644 index 000000000..5bf894d0a --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/notifications/package-info.java @@ -0,0 +1,28 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +/** + * This is the new Addition to the PDP Server added for sending Notifications to the Clients + * about the policy Updates/ Removals. + * + * @version 0.1 + * + */ +package org.onap.policy.pdp.rest.notifications; diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/restAuth/AuthenticationService.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/restAuth/AuthenticationService.java new file mode 100644 index 000000000..0d066c59c --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/restAuth/AuthenticationService.java @@ -0,0 +1,62 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.pdp.rest.restAuth; + +import java.util.Base64; +import java.util.StringTokenizer; + +import org.onap.policy.rest.XACMLRestProperties; + +import com.att.research.xacml.util.XACMLProperties; + +import org.onap.policy.common.logging.eelf.MessageCodes; +import org.onap.policy.common.logging.eelf.PolicyLogger; + +public class AuthenticationService { + private String pdpID = XACMLProperties.getProperty(XACMLRestProperties.PROP_PDP_USERID); + private String pdpPass = XACMLProperties.getProperty(XACMLRestProperties.PROP_PDP_PASS); + + public boolean authenticate(String authCredentials) { + + if (null == authCredentials) + return false; + // header value format will be "Basic encodedstring" for Basic authentication. + final String encodedUserPassword = authCredentials.replaceFirst("Basic" + " ", ""); + String usernameAndPassword = null; + try { + byte[] decodedBytes = Base64.getDecoder().decode(encodedUserPassword); + usernameAndPassword = new String(decodedBytes, "UTF-8"); + } catch (Exception e) { + PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, ""); + return false; + } + try { + final StringTokenizer tokenizer = new StringTokenizer(usernameAndPassword, ":"); + final String username = tokenizer.nextToken(); + final String password = tokenizer.nextToken(); + return pdpID.equals(username) && pdpPass.equals(password); + }catch (Exception e){ + PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, ""); + return false; + } + } + +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/restAuth/PDPAuthenticationFilter.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/restAuth/PDPAuthenticationFilter.java new file mode 100644 index 000000000..5b01ca9e5 --- /dev/null +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/restAuth/PDPAuthenticationFilter.java @@ -0,0 +1,117 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP-REST + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.pdp.rest.restAuth; + +import java.io.IOException; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.annotation.WebFilter; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.onap.policy.pdp.rest.config.PDPApiAuth; + +/** + * Servlet Filter implementation class PDPAuthenticationFilter + */ +@WebFilter("/*") +public class PDPAuthenticationFilter implements Filter { + + public static final String AUTHENTICATION_HEADER = "Authorization"; + public static final String ENVIRONMENT_HEADER = "Environment"; + + @Override + public void doFilter(ServletRequest request, ServletResponse response, + FilterChain filter) throws IOException, ServletException { + if (request instanceof HttpServletRequest) { + HttpServletRequest httpServletRequest = (HttpServletRequest) request; + String environment = httpServletRequest.getHeader(ENVIRONMENT_HEADER); + String authCredentials = httpServletRequest.getHeader(AUTHENTICATION_HEADER); + String path = ((HttpServletRequest) request).getRequestURI(); + // better injected + AuthenticationService authenticationService = new AuthenticationService(); + + boolean authenticationStatus = authenticationService.authenticate(authCredentials); + + if (authenticationStatus) { + if (check(path)) { + // New API request. + path = path.substring(path.substring(1).indexOf("/") + 1); + if (environment == null) { + // Allow Old clients. + if(!path.contains("/api/")){ + request.getRequestDispatcher("/api/" + path).forward(request,response); + }else{ + request.getRequestDispatcher(path).forward(request,response); + } + } else if (environment.equalsIgnoreCase(PDPApiAuth.getEnvironment())) { + // Validated new Clients. + if(!path.contains("/api/")){ + request.getRequestDispatcher("/api/" + path).forward(request,response); + }else{ + request.getRequestDispatcher(path).forward(request,response); + } + } else if(response instanceof HttpServletResponse) { + HttpServletResponse httpServletResponse = (HttpServletResponse) response; + httpServletResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + } + } else { + filter.doFilter(request, response); + } + } else if (path.contains("swagger") || path.contains("api-docs") + || path.contains("configuration") || path.contains("count")) { + path = path.substring(path.substring(1).indexOf("/") + 2); + request.getRequestDispatcher("/api/" + path).forward(request,response); + } else if(path.contains("notifications")){ + filter.doFilter(request, response); + } else { + if (response instanceof HttpServletResponse) { + HttpServletResponse httpServletResponse = (HttpServletResponse) response; + httpServletResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + } + } + } + } + + private boolean check(String path) { + if(path.endsWith("/pdp/")|| path.endsWith("/pdp")|| path.endsWith("/test")){ + return false; + }else{ + return true; + } + } + + @Override + public void destroy() { + // Do nothing. + } + + @Override + public void init(FilterConfig arg0) throws ServletException { + // Do nothing. + } + +} |