aboutsummaryrefslogtreecommitdiffstats
path: root/ECOMP-PDP-REST/src
diff options
context:
space:
mode:
authorPamela Dragosh <pdragosh@research.att.com>2017-02-14 19:41:00 -0500
committerPamela Dragosh <pdragosh@research.att.com>2017-02-14 19:41:32 -0500
commit91d04c64771832a0b8815ffbe1f0f9920320d94d (patch)
treefb02d5e1c84a3d91def9a7ee95bc87f9c046cc96 /ECOMP-PDP-REST/src
parentb9d4caa40ef8e3566ac475968bce17b9b64b6939 (diff)
Initial OpenECOMP policy/engine commit
Change-Id: I7dbff37733b661643dd4d1caefa3d7dccc361b6e Signed-off-by: Pamela Dragosh <pdragosh@research.att.com>
Diffstat (limited to 'ECOMP-PDP-REST/src')
-rw-r--r--ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/PapUrlResolver.java387
-rw-r--r--ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/XACMLPdpLoader.java695
-rw-r--r--ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/XACMLPdpRegisterThread.java333
-rw-r--r--ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/XACMLPdpServlet.java1138
-rw-r--r--ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/impl/XACMLPdpPIPFinderFactory.java88
-rw-r--r--ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/impl/XACMLPdpPolicyFinderFactory.java208
-rw-r--r--ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/jmx/PdpRestMBeanListener.java87
-rw-r--r--ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/jmx/PdpRestMonitor.java161
-rw-r--r--ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/jmx/PdpRestMonitorMBean.java40
-rw-r--r--ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/notifications/ManualNotificationUpdateThread.java151
-rw-r--r--ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/notifications/Notification.java52
-rw-r--r--ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/notifications/NotificationController.java391
-rw-r--r--ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/notifications/NotificationServer.java141
-rw-r--r--ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/notifications/Removed.java52
-rw-r--r--ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/notifications/Updated.java61
-rw-r--r--ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/notifications/package-info.java28
-rw-r--r--ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/restAuth/AuthenticationService.java72
-rw-r--r--ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/restAuth/PDPAuthenticationFilter.java78
-rw-r--r--ECOMP-PDP-REST/src/main/resources/log4j.properties71
-rw-r--r--ECOMP-PDP-REST/src/main/resources/logback.xml253
-rw-r--r--ECOMP-PDP-REST/src/test/java/org/openecomp/policy/pdp/rest/PapUrlResolverTest.java355
-rw-r--r--ECOMP-PDP-REST/src/test/java/org/openecomp/policy/pdp/rest/XACMLPdpServletTest.java395
22 files changed, 5237 insertions, 0 deletions
diff --git a/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/PapUrlResolver.java b/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/PapUrlResolver.java
new file mode 100644
index 000000000..d9a3688b4
--- /dev/null
+++ b/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/PapUrlResolver.java
@@ -0,0 +1,387 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ECOMP-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.openecomp.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.openecomp.policy.rest.XACMLRestProperties;
+
+import com.att.research.xacml.util.XACMLProperties;
+
+import org.openecomp.policy.common.logging.flexlogger.*;
+
+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 Object propertyLock = new Object();
+
+ public static void setPapUrls(String[] papUrls){
+
+ }
+ //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){
+ 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;
+ //synchronized(propertyLock){
+ if(urlList == null){
+ urlList = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_URLS);
+ if(urlList == null){
+ urlList = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_URL);
+ }
+ failedList = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_FAILED_URLS);
+ succeededList = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_SUCCEEDED_URLS);
+ }
+ //}
+ String[] urls = urlList.split(",");
+ if(urls.length == 0){
+ //log error
+ }
+ String[] failed = emptyOrSplit(failedList,urls.length);
+ String[] succeeded = emptyOrSplit(succeededList,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 {
+ String finalUrl = sortedUrlNodes[pointer].getUrl().concat("?").concat(query);
+ return finalUrl;
+ }
+ }
+
+ //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){
+ this.papUrl = url;
+ failedTime = null;
+ this.succeededTime = null;
+ this.userId = "";
+ this.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(((String)time).equals("-1")){
+ return null;
+ }
+ try {
+ DateFormat df = new SimpleDateFormat();
+ Date parsedTime = df.parse((String)time);
+ return parsedTime;
+ } 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;
+ }
+
+ 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/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/XACMLPdpLoader.java b/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/XACMLPdpLoader.java
new file mode 100644
index 000000000..9c5b120c3
--- /dev/null
+++ b/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/XACMLPdpLoader.java
@@ -0,0 +1,695 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ECOMP-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.openecomp.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.openecomp.policy.pdp.rest.notifications.NotificationController;
+import org.openecomp.policy.rest.XACMLRest;
+import org.openecomp.policy.rest.XACMLRestProperties;
+import org.openecomp.policy.common.logging.flexlogger.FlexLogger;
+import org.openecomp.policy.common.logging.flexlogger.Logger;
+
+import org.openecomp.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.openecomp.policy.xacml.std.pap.StdPDPPIPConfig;
+import org.openecomp.policy.xacml.std.pap.StdPDPPolicy;
+import org.openecomp.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());
+ // TODO:EELF Cleanup - Remove logger
+ //PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, "");
+ } catch (Exception e) {
+ String error = "Failed to load Policy Cache properties file: "
+ + e.getMessage();
+ logger.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + error, e);
+ // TODO:EELF Cleanup - Remove logger
+ //PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, error);
+ 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);
+ // TODO:EELF Cleanup - Remove logger
+ //PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, error);
+ 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");
+ // TODO:EELF Cleanup - Remove logger
+ //PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE,"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);
+ // TODO:EELF Cleanup - Remove logger
+ //PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, "Failed to get XACML Properties");
+ }
+ //
+ // 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);
+ // TODO:EELF Cleanup - Remove logger
+ //PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, error);
+ 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);
+ // TODO:EELF Cleanup - Remove logger
+ //PolicyLogger.error(MessageCodes.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");
+ // TODO Notification Controller is here..
+ 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);
+ 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();
+ //FIXME: modify me
+ URLConnection urlConnection = null;
+ try{
+ urlConnection = url.openConnection();
+ } catch (IOException 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){
+ 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);
+ 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);
+ // TODO:EELF Cleanup - Remove logger
+ //PolicyLogger.error(MessageCodes.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);
+ // TODO:EELF Cleanup - Remove logger
+ //PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, "Failed to load policy '" + id + "' from location '"
+ // + location + "'");
+ 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);
+ // TODO:EELF Cleanup - Remove logger
+ //PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, "Corrupted policy file, deleting: " + location);
+ Files.delete(Paths.get(location));
+
+ } catch (IOException e1) {
+ logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + e1);
+ // TODO:EELF Cleanup - Remove logger
+ //PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e1, "");
+ }
+ }
+ //throw new PAPException("Failed to load policy '" + id + "' from location '" + location + "'");
+ }
+ }
+
+ 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.");
+ // TODO:EELF Cleanup - Remove logger
+ //PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, "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());
+ // TODO:EELF Cleanup - Remove logger
+ //PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e.getLocalizedMessage(), "validate PIP configuration failed");
+ 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 "&lt;PolicyID&gt;.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 "&lt;PolicyID&gt;.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 + "'");
+ // TODO:EELF Cleanup - Remove logger
+ //PolicyLogger.error(MessageCodes.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.toString() + ", e=" + e);
+ // TODO:EELF Cleanup - Remove logger
+ //PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, "Error while retrieving policy "
+ // + policy
+ // + " from URL "
+ // + url.toString());
+ }
+ }
+ papUrls.getNext();
+ }
+ } else {
+ logger.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Policy " + policy
+ + " does NOT exist and does NOT have a URL");
+ // TODO:EELF Cleanup - Remove logger
+ //PolicyLogger.error(MessageCodes.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());
+ // TODO:EELF Cleanup - Remove logger
+ //PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, "Failed to create policy properties file: "
+ // + policyProperties.toAbsolutePath().toString());
+ 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());
+ // TODO:EELF Cleanup - Remove logger
+ //PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, "Failed to create pip properties file: "
+ //+ pipConfigProperties.toAbsolutePath().toString());
+ 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);
+ // TODO:EELF Cleanup - Remove logger
+ //PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, "Failed to create config directory: "
+ //+ config.toAbsolutePath().toString());
+ throw new PAPException("Failed to create config directory: "
+ + config.toAbsolutePath().toString());
+ }
+ }
+ return config;
+ }
+
+}
diff --git a/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/XACMLPdpRegisterThread.java b/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/XACMLPdpRegisterThread.java
new file mode 100644
index 000000000..83b9f3cf7
--- /dev/null
+++ b/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/XACMLPdpRegisterThread.java
@@ -0,0 +1,333 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ECOMP-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.openecomp.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.openecomp.policy.pdp.rest.XACMLPdpServlet.PutRequest;
+import org.openecomp.policy.rest.XACMLRestProperties;
+
+import org.openecomp.policy.xacml.api.XACMLErrorConstants;
+import com.att.research.xacml.util.XACMLProperties;
+
+import org.openecomp.policy.common.logging.ECOMPLoggingContext;
+import org.openecomp.policy.common.logging.eelf.PolicyLogger;
+import org.openecomp.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 ECOMPLoggingContext baseLoggingContext = null;
+
+
+
+ public volatile boolean isRunning = false;
+
+ public XACMLPdpRegisterThread(ECOMPLoggingContext 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
+ ECOMPLoggingContext loggingContext = new ECOMPLoggingContext(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);
+ // TODO:EELF Cleanup - Remove logger
+ //PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, "XACMLPdpRegisterThread", "Failed to open PIP property file");
+ }
+ 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);
+ // TODO:EELF Cleanup - Remove logger
+ //PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "Failed to send property file");
+ }
+ //
+ // Do the connect
+ //
+ connection.connect();
+ if (connection.getResponseCode() == 204) {
+ logger.info("Success. We are configured correctly.");
+ // TODO:EELF Cleanup - Remove logger
+ //PolicyLogger.info("Success. We are configured correctly.");
+ loggingContext.transactionEnded();
+ // auditLogger.info("Success. We are configured correctly.");
+ // TODO:EELF Cleanup - Remove logger
+ 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.");
+ // TODO:EELF Cleanup - Remove logger
+ //PolicyLogger.info("Success. We have a new configuration.");
+ loggingContext.transactionEnded();
+ // TODO:EELF Cleanup - Remove logger
+ //auditLogger.info("Success. We have a new configuration.");
+ 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
+ //FIXME: problem here is that we need the properties to be filled in BEFORE this thread continues and registers with another pap
+ 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;
+ //FIXME: how will pipproperties respond to threading?
+
+ 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");
+ // TODO:EELF Cleanup - Remove logger
+ //PolicyLogger.warn(MessageCodes.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");
+ // TODO:EELF Cleanup - Remove logger
+ PolicyLogger.audit("Transaction Failed - See Error.log");
+ finished = true;
+ } else {
+ //FIXME: how to handle this
+ logger.info("New Location: " + newLocation);
+ // TODO:EELF Cleanup - Remove logger
+ //PolicyLogger.info("New Location: " + newLocation);
+ url = new URL(newLocation);
+ }
+ } else {
+ logger.warn(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Failed: " + connection.getResponseCode() + " message: " + connection.getResponseMessage());
+ // TODO:EELF Cleanup - Remove logger
+ //PolicyLogger.warn(MessageCodes.ERROR_SYSTEM_ERROR, "Failed: " + connection.getResponseCode() + " message: " + connection.getResponseMessage());
+ loggingContext.transactionEnded();
+ auditLogger.warn(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Failed: " + connection.getResponseCode() + " message: " + connection.getResponseMessage());
+ // TODO:EELF Cleanup - Remove logger
+ PolicyLogger.audit("Transaction Failed - See Error.log");
+ finished = true;
+ papUrls.failed();
+ }
+ }
+ } catch (Exception e) {
+ logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + e);
+ // TODO:EELF Cleanup - Remove logger
+ //PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "");
+ PolicyLogger.audit("Transaction Failed - See Error.log");
+ loggingContext.transactionEnded();
+ // TODO:EELF look at this error going to audit. decide what to do.
+ //auditLogger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + e);
+ // TODO:EELF Cleanup - Remove logger
+ 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) {
+ // ignore this
+ }
+ if (is != null) {
+ is.close();
+ }
+
+ } catch (IOException ex) {
+ logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Failed to close connection: " + ex, ex);
+ // TODO:EELF Cleanup - Remove logger
+ //PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, ex, "Failed to close connection");
+ }
+ connection.disconnect();
+ }
+ }
+ //
+ // Wait a little while to try again
+ //
+ /*
+ try {
+ if (registered == false) {
+ if (retries > 0) {
+ retries--;
+ } else if (retries == 0) {
+ break;
+ }
+ Thread.sleep(seconds * 1000);
+ }
+ } catch (InterruptedException e) {
+ interrupted = true;
+ this.terminate();
+ }
+ */
+ //end of hasMoreUrls while loop
+ papUrls.getNext();
+ }
+ synchronized(this) {
+ this.isRunning = false;
+ }
+ logger.info("Thread exiting...(registered=" + registered + ", interrupted=" + interrupted + ", isRunning=" + this.isRunning() + ", retries=" + "0" + ")");
+ }
+
+}
diff --git a/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/XACMLPdpServlet.java b/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/XACMLPdpServlet.java
new file mode 100644
index 000000000..963fcd127
--- /dev/null
+++ b/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/XACMLPdpServlet.java
@@ -0,0 +1,1138 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ECOMP-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.openecomp.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.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.openecomp.policy.pdp.rest.jmx.PdpRestMonitor;
+import org.openecomp.policy.rest.XACMLRest;
+import org.openecomp.policy.rest.XACMLRestProperties;
+import org.openecomp.policy.common.logging.ECOMPLoggingContext;
+import org.openecomp.policy.common.logging.ECOMPLoggingUtils;
+import org.openecomp.policy.common.logging.eelf.MessageCodes;
+import org.openecomp.policy.common.logging.eelf.PolicyLogger;
+import org.openecomp.policy.common.im.AdministrativeStateException;
+import org.openecomp.policy.common.im.ForwardProgressException;
+import org.openecomp.policy.common.im.IntegrityMonitor;
+import org.openecomp.policy.common.im.IntegrityMonitorProperties;
+import org.openecomp.policy.common.im.StandbyStatusException;
+
+import com.att.research.xacml.api.Request;
+import com.att.research.xacml.api.Response;
+import org.openecomp.policy.xacml.api.XACMLErrorConstants;
+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 org.openecomp.policy.xacml.pdp.std.functions.PolicyList;
+import org.openecomp.policy.xacml.std.pap.StdPDPStatus;
+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
+ //
+ // 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.singleton;
+
+ //
+ // 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 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 final String ENVIORNMENT_HEADER = "Environment";
+ private static String environment = null;
+ //
+ // Queue of PUT requests
+ //
+ public static class PutRequest {
+ public Properties policyProperties = null;
+ public Properties pipConfigProperties = null;
+
+ PutRequest(Properties policies, Properties pips) {
+ this.policyProperties = policies;
+ this.pipConfigProperties = pips;
+ }
+ }
+ public 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 dependencyGroups = null;
+ 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 ECOMPLoggingContext baseLoggingContext = null;
+ private IntegrityMonitor im;
+ /**
+ * Default constructor.
+ */
+ public XACMLPdpServlet() {
+ }
+
+ /**
+ * @see Servlet#init(ServletConfig)
+ */
+ public void init(ServletConfig config) throws ServletException {
+ //
+ // 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.");
+ }
+ // 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 ECOMPLoggingContext();
+ // fixed data that will be the same in all logging output goes here
+ try {
+ String hostname = InetAddress.getLocalHost().getCanonicalHostName();
+ baseLoggingContext.setServer(hostname);
+ } catch (UnknownHostException e) {
+ logger.warn(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Unable to get hostname for logging");
+ }
+
+ 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());
+ }
+
+ 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();
+ }
+
+
+ // 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");
+ 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()
+ */
+ 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)
+ */
+ protected void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ ECOMPLoggingContext loggingContext = ECOMPLoggingUtils.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 (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);
+ loggingContext.transactionEnded();
+ PolicyLogger.audit("Transaction Failed - See Error.log");
+ response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
+ 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");
+ 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();
+ } 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");
+ response.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
+ im.endTransaction();
+ return;
+ }
+ }
+
+ protected void doPutConfig(String config, HttpServletRequest request, HttpServletResponse response, ECOMPLoggingContext 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");
+ response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
+ 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)
+ */
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ ECOMPLoggingContext loggingContext = ECOMPLoggingUtils.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 );
+ loggingContext.transactionEnded();
+ PolicyLogger.audit("Transaction Failed - See Error.log");
+ // PolicyLogger.audit(MessageCodes.ERROR_SYSTEM_ERROR, message );
+ response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
+ 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 );
+ loggingContext.transactionEnded();
+ PolicyLogger.audit("Transaction Failed - See Error.log");
+ response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
+ 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 );
+ loggingContext.transactionEnded();
+ PolicyLogger.audit("Transaction Failed - See Error.log");
+ response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
+ 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-ECOMP-SubsystemFailure", failedNodeList);
+ response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
+ loggingContext.transactionEnded();
+ PolicyLogger.audit("Transaction Failed - See Error.log");
+ 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");
+ response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
+ 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");
+ response.sendError(400, "Failed to copy Property file");
+ }
+
+ } 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();
+ mapper.writeValue(response.getOutputStream(), status);
+ }
+ 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");
+ response.sendError(HttpServletResponse.SC_BAD_REQUEST, "type not 'config' or 'hb'");
+ }
+ 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)
+ */
+ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+
+ ECOMPLoggingContext loggingContext = ECOMPLoggingUtils.getLoggingContextForRequest(request, baseLoggingContext);
+ loggingContext.transactionStarted();
+ loggingContext.setServiceName("PDP.decide");
+ if ((loggingContext.getRequestID() == null) || (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);
+ loggingContext.transactionEnded();
+ PolicyLogger.audit("Transaction Failed - See Error.log");
+ response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
+ 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().size() == 0) {
+ 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");
+ response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
+ 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");
+ response.sendError(HttpServletResponse.SC_BAD_REQUEST, "no content-type given");
+ im.endTransaction();
+ return;
+ }
+ //
+ // Limit the Content-Length to something reasonable
+ //
+ 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;
+ }
+ 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");
+ response.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
+ 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");
+ response.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
+ 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;
+ while((line = reader.readLine()) != null){
+ buffer.append(line);
+ }
+ 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");
+ response.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
+ 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");
+ response.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
+ 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");
+ response.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
+ im.endTransaction();
+ return;
+ }
+ //
+ // Run it
+ //
+ try {
+ //
+ // Authenticating the Request here.
+ //
+ if(!authorizeRequest(request, pdpRequest)){
+ 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 = this.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, lTimeEnd;
+ Response pdpResponse = null;
+
+//TODO - Make this unnecessary
+//TODO It seems that the PDP Engine is not thread-safe, so when a configuration change occurs in the middle of processing
+//TODO a PEP Request, that Request fails (it throws a NullPointerException in the decide() method).
+//TODO Using synchronize will slow down processing of PEP requests, possibly by a significant amount.
+//TODO Since configuration changes are rare, it would be A Very Good Thing if we could eliminate this sychronized block.
+//TODO
+//TODO This problem was found by starting one PDP then
+//TODO RestLoadTest switching between 2 configurations, 1 second apart
+//TODO both configurations contain the datarouter policy
+//TODO both configurations already have all policies cached in the PDPs config directory
+//TODO RestLoadTest started with the Datarouter test requests, 5 threads, no interval
+//TODO With that configuration this code (without the synchronized) throws a NullPointerException
+//TODO within a few seconds.
+//
+synchronized(pdpEngineLock) {
+ myEngine = this.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);
+ 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;
+ }
+}
+ 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 + "=" + "{}");
+ throw new Exception("Failed to get response from PDP engine.");
+ }
+ //
+ // 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 = "";
+ 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) {
+ 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");
+ response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
+ 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, Request pepRequest) {
+ if(request instanceof HttpServletRequest) {
+ // Get the client Credentials from the Request header.
+ HttpServletRequest httpServletRequest = (HttpServletRequest) request;
+ String clientCredentials = httpServletRequest.getHeader(ENVIORNMENT_HEADER);
+ if(clientCredentials!=null && clientCredentials.equalsIgnoreCase(environment)){
+ return true;
+ }else{
+ return false;
+ }
+ }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:
+ ECOMPLoggingContext loggingContext = new ECOMPLoggingContext(baseLoggingContext);
+ while (! this.configThreadTerminate) {
+ PutRequest request = XACMLPdpServlet.queue.take();
+ StdPDPStatus newStatus = new StdPDPStatus();
+
+//TODO - This is related to the problem discussed in the doPost() method about the PDPEngine not being thread-safe.
+//TODO See that discussion, and when the PDPEngine is made thread-safe it should be ok to move the loadEngine out of
+//TODO the synchronized block.
+//TODO However, since configuration changes should be rare we may not care about changing this.
+PDPEngine newEngine = null;
+ synchronized(pdpStatusLock) {
+ XACMLPdpServlet.status.setStatus(Status.UPDATING_CONFIGURATION);
+newEngine = XACMLPdpLoader.loadEngine(newStatus, request.policyProperties, request.pipConfigProperties);
+ }
+// PDPEngine newEngine = XACMLPdpLoader.loadEngine(newStatus, request.policyProperties, request.pipConfigProperties);
+ if (newEngine != null) {
+ synchronized(XACMLPdpServlet.pdpEngineLock) {
+ this.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.");
+ 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");
+ PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, "interrupted");
+ }
+ }
+
+}
diff --git a/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/impl/XACMLPdpPIPFinderFactory.java b/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/impl/XACMLPdpPIPFinderFactory.java
new file mode 100644
index 000000000..3c8b67f31
--- /dev/null
+++ b/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/impl/XACMLPdpPIPFinderFactory.java
@@ -0,0 +1,88 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ECOMP-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.openecomp.policy.pdp.rest.impl;
+
+import java.util.Properties;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.openecomp.policy.common.logging.eelf.MessageCodes;
+import org.openecomp.policy.common.logging.eelf.PolicyLogger;
+
+import org.openecomp.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/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/impl/XACMLPdpPolicyFinderFactory.java b/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/impl/XACMLPdpPolicyFinderFactory.java
new file mode 100644
index 000000000..9335bef6c
--- /dev/null
+++ b/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/impl/XACMLPdpPolicyFinderFactory.java
@@ -0,0 +1,208 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ECOMP-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.openecomp.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.openecomp.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<PolicyDef>();
+ 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/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/jmx/PdpRestMBeanListener.java b/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/jmx/PdpRestMBeanListener.java
new file mode 100644
index 000000000..309bd1502
--- /dev/null
+++ b/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/jmx/PdpRestMBeanListener.java
@@ -0,0 +1,87 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ECOMP-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.openecomp.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.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.openecomp.policy.common.logging.flexlogger.*;
+
+import org.openecomp.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.singleton, 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/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/jmx/PdpRestMonitor.java b/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/jmx/PdpRestMonitor.java
new file mode 100644
index 000000000..93dfbe6a0
--- /dev/null
+++ b/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/jmx/PdpRestMonitor.java
@@ -0,0 +1,161 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ECOMP-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.openecomp.policy.pdp.rest.jmx;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.BinaryOperator;
+
+import org.openecomp.policy.xacml.util.MetricsUtil.AvgLatency;
+import org.openecomp.policy.xacml.util.MetricsUtil.MaxLatency;
+import org.openecomp.policy.xacml.util.MetricsUtil.MinLatency;
+
+public class PdpRestMonitor implements PdpRestMonitorMBean {
+ public 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){
+ if (policyCount.containsKey(policyID)){
+ count = count + policyCount.get(policyID);
+ }
+ policyCount.put(policyID, count);
+ }
+ public Map<String, Integer> getpolicyMap() {
+ return policyCount;
+ }
+ public Integer getpolicyCount(String policyID) {
+ // TODO Auto-generated method stub
+ if (policyCount.containsKey(policyID)){
+ return policyCount.get(policyID);
+ }
+ return null;
+ }
+
+
+
+}
diff --git a/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/jmx/PdpRestMonitorMBean.java b/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/jmx/PdpRestMonitorMBean.java
new file mode 100644
index 000000000..e7db09d24
--- /dev/null
+++ b/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/jmx/PdpRestMonitorMBean.java
@@ -0,0 +1,40 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ECOMP-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.openecomp.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/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/notifications/ManualNotificationUpdateThread.java b/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/notifications/ManualNotificationUpdateThread.java
new file mode 100644
index 000000000..6b8857273
--- /dev/null
+++ b/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/notifications/ManualNotificationUpdateThread.java
@@ -0,0 +1,151 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ECOMP-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.openecomp.policy.pdp.rest.notifications;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.security.GeneralSecurityException;
+import java.util.LinkedList;
+import java.util.UUID;
+
+import org.openecomp.policy.rest.XACMLRestProperties;
+
+import com.att.nsa.cambria.client.CambriaClientFactory;
+import com.att.nsa.cambria.client.CambriaConsumer;
+import com.att.nsa.cambria.client.CambriaPublisher;
+import org.openecomp.policy.xacml.api.XACMLErrorConstants;
+import com.att.research.xacml.util.XACMLProperties;
+
+import org.openecomp.policy.common.logging.flexlogger.*;
+
+public class ManualNotificationUpdateThread implements Runnable {
+ private static final Logger logger = FlexLogger.getLogger(ManualNotificationUpdateThread.class);
+// private static List<String> uebURLList = null;
+ private static String topic = null;
+ private static CambriaConsumer CConsumer = null;
+// private static Collection<String> clusterList = null;
+ private static String clusterList = null;
+// private Collection<String> urlList = null;
+ private static String update = 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;
+ try {
+ ManualNotificationUpdateThread.clusterList = XACMLProperties.getProperty(XACMLRestProperties.PROP_NOTIFICATION_UEB_CLUSTER);
+ 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);
+ }
+ String consumerTopic = aURL.getHost() + aURL.getPort() + "UpdateRequest";
+ SendMessage(consumerTopic, "Starting-Topic");
+ final LinkedList<String> urlList = new LinkedList<String> ();
+ for ( String u : clusterList.split ( "," ) ){
+ urlList.add ( u );
+ }
+
+ try {
+ CConsumer = CambriaClientFactory.createConsumer ( null, urlList, consumerTopic , group, id, 20*1000, 1000 );
+ } catch (MalformedURLException | GeneralSecurityException e1) {
+ // TODO Auto-generated catch block
+ e1.printStackTrace();
+ }
+
+
+ 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");
+ }
+ }
+ logger.debug("Stopping UEB Consuer loop will not logger fetch messages from the cluser");
+
+ }
+
+ private void SendMessage( String topic, String message) {
+ CambriaPublisher pub = null;
+ try {
+ pub = CambriaClientFactory.createSimplePublisher (null, clusterList, topic );
+ } catch (MalformedURLException e1) {
+ // TODO Auto-generated catch block
+ e1.printStackTrace();
+ } catch (GeneralSecurityException e1) {
+ // TODO Auto-generated catch block
+ e1.printStackTrace();
+ }
+ try {
+ pub.send( "pdpReturnMessage", message );
+ logger.debug("Sending to Message to tpoic" + topic);
+ } catch (IOException e) {
+ logger.error(XACMLErrorConstants.ERROR_PROCESS_FLOW+ "Error sending notification update");
+ }
+ pub.close();
+ }
+
+ 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/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/notifications/Notification.java b/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/notifications/Notification.java
new file mode 100644
index 000000000..5ab165b0a
--- /dev/null
+++ b/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/notifications/Notification.java
@@ -0,0 +1,52 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ECOMP-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.openecomp.policy.pdp.rest.notifications;
+
+import java.util.Collection;
+
+/**
+ * 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.1
+ *
+ */
+public class Notification {
+ private Collection<Removed> removedPolicies = null;
+ private Collection<Updated> loadedPolicies = 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;
+ }
+
+}
diff --git a/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/notifications/NotificationController.java b/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/notifications/NotificationController.java
new file mode 100644
index 000000000..1dfd07422
--- /dev/null
+++ b/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/notifications/NotificationController.java
@@ -0,0 +1,391 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ECOMP-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.openecomp.policy.pdp.rest.notifications;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.MalformedURLException;
+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 org.apache.commons.io.IOUtils;
+import org.apache.commons.io.filefilter.WildcardFileFilter;
+import org.openecomp.policy.pdp.rest.PapUrlResolver;
+import org.openecomp.policy.rest.XACMLRestProperties;
+import org.openecomp.policy.common.logging.flexlogger.FlexLogger;
+import org.openecomp.policy.common.logging.flexlogger.Logger;
+
+import org.openecomp.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,HashMap<String, PolicyDef> policyContainer) {
+ boolean updated = false;
+ boolean removed = false;
+ Notification notification = new Notification();
+ HashSet<Removed> removedPolicies = new HashSet<Removed>();
+ HashSet<Updated> updatedPolicies = new HashSet<Updated>();
+
+ 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);
+ 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 (propNotificationType!=null && propNotificationType.equals("ueb") && !manualThreadStarted) {
+ logger.debug("Starting Thread to accept UEB 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);
+ // TODO:EELF Cleanup - Remove logger
+ //PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, "");
+ }
+ NotificationServer.setUpdate(notificationJSON);
+ ManualNotificationUpdateThread.setUpdate(notificationJSON);
+ } catch (JsonProcessingException e) {
+ logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + e.getMessage());
+ // TODO:EELF Cleanup - Remove logger
+ //PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, "");
+ }
+ }
+ }
+
+ public static void sendNotification(){
+ if(notificationFlag){
+ NotificationServer.sendNotification(notificationJSON, propNotificationType, pdpURL);
+ notificationFlag = false;
+ }
+ }
+
+ private void sendremove(PDPPolicy oldPolicy) {
+ removed = new Removed();
+ // Want to know what is removed ?
+ // logger.info("The Policy removed is: " + oldPolicy.getId());
+ // logger.info("The version no. is: " + oldPolicy.getVersion());
+ 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,HashMap<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());
+ // If the policy is of Config type then retrieve its matches.
+ if (newPolicy.getName().startsWith("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<String, String>();
+ 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().startsWith("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..
+ public 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());
+ // TODO:EELF Cleanup - Remove logger
+ //PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, "");
+ }
+ logger.info(json);
+ return json;
+ }
+
+ 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 && dir!=null){
+ 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());
+ // TODO:EELF Cleanup - Remove logger
+ //PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, "Couldn't remove the policy file " + oldPolicy.getName());
+ }
+ }
+
+ 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 (MalformedURLException e) {
+ logger.error(e + e.getMessage());
+ } catch(FileNotFoundException e){
+ logger.error(e + e.getMessage());
+ } catch (IOException e) {
+ logger.error(e + e.getMessage());
+ }
+ papUrls.getNext();
+ }
+ }
+}
diff --git a/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/notifications/NotificationServer.java b/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/notifications/NotificationServer.java
new file mode 100644
index 000000000..d6cda7491
--- /dev/null
+++ b/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/notifications/NotificationServer.java
@@ -0,0 +1,141 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ECOMP-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.openecomp.policy.pdp.rest.notifications;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.security.GeneralSecurityException;
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+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.openecomp.policy.rest.XACMLRestProperties;
+import org.openecomp.policy.common.logging.eelf.MessageCodes;
+import org.openecomp.policy.common.logging.eelf.PolicyLogger;
+import com.att.nsa.cambria.client.CambriaClientFactory;
+import com.att.nsa.cambria.client.CambriaPublisher;
+import org.openecomp.policy.xacml.api.XACMLErrorConstants;
+import com.att.research.xacml.util.XACMLProperties;
+
+import org.openecomp.policy.common.logging.flexlogger.*;
+
+
+/**
+ * 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.
+ *
+ * @version 0.1
+ *
+ **/
+@ServerEndpoint(value = "/notifications")
+public class NotificationServer {
+ private static final Logger logger = FlexLogger.getLogger(NotificationServer.class);
+ private static Queue<Session> queue = new ConcurrentLinkedQueue<Session>();
+ 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());
+ logger.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Error sending Message update");
+ }
+ }
+ }
+
+ public static void sendNotification(String notification, String propNotificationType, String pdpURL){
+
+ 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_UEB_CLUSTER);
+ logger.debug("Creating Publisher for host: " + hosts + " with topic: " + topic);
+ CambriaPublisher pub = null;
+ try {
+ pub = CambriaClientFactory.createSimplePublisher (null, hosts, topic );
+ } catch (MalformedURLException e1) {
+ // TODO Auto-generated catch block
+ e1.printStackTrace();
+ } catch (GeneralSecurityException e1) {
+ // TODO Auto-generated catch block
+ e1.printStackTrace();
+ }
+ try {
+ pub.send( "MyPartitionKey", notification );
+ } catch (IOException e) {
+ logger.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Error sending notification update");
+ }
+ pub.close();
+ }
+ 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());
+ }
+ }
+ }
+
+ public static void setUpdate(String update) {
+ NotificationServer.update = update;
+ }
+}
diff --git a/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/notifications/Removed.java b/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/notifications/Removed.java
new file mode 100644
index 000000000..6ba073815
--- /dev/null
+++ b/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/notifications/Removed.java
@@ -0,0 +1,52 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ECOMP-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.openecomp.policy.pdp.rest.notifications;
+
+
+/**
+ * Removal is the POJO for removal updates of the Policy.
+ * It must have the Policy removed and its Version number.
+ *
+ * @version 0.1
+ *
+ */
+public class Removed {
+
+ 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/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/notifications/Updated.java b/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/notifications/Updated.java
new file mode 100644
index 000000000..39236bada
--- /dev/null
+++ b/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/notifications/Updated.java
@@ -0,0 +1,61 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ECOMP-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.openecomp.policy.pdp.rest.notifications;
+
+import java.util.HashMap;
+
+/**
+ * Updated is the POJO which consists of any new or Updated Policy information.
+ * It must hold the Policy Name, version Number, Matches.
+ *
+ * @version 0.1
+ *
+ */
+public class Updated {
+ private String policyName = null;
+ private String versionNo = null;
+ private HashMap<String,String> matches = 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;
+ }
+
+}
diff --git a/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/notifications/package-info.java b/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/notifications/package-info.java
new file mode 100644
index 000000000..7d3995ec6
--- /dev/null
+++ b/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/notifications/package-info.java
@@ -0,0 +1,28 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ECOMP-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.openecomp.policy.pdp.rest.notifications;
diff --git a/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/restAuth/AuthenticationService.java b/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/restAuth/AuthenticationService.java
new file mode 100644
index 000000000..c426b6002
--- /dev/null
+++ b/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/restAuth/AuthenticationService.java
@@ -0,0 +1,72 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ECOMP-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.openecomp.policy.pdp.rest.restAuth;
+
+import java.util.Base64;
+import java.util.StringTokenizer;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.openecomp.policy.rest.XACMLRestProperties;
+
+import org.openecomp.policy.xacml.api.XACMLErrorConstants;
+import com.att.research.xacml.util.XACMLProperties;
+
+import org.openecomp.policy.common.logging.eelf.MessageCodes;
+import org.openecomp.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);
+ private static final Log logger = LogFactory.getLog(AuthenticationService.class);
+
+ 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) {
+ logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + e);
+ // TODO:EELF Cleanup - Remove logger
+ 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();
+
+ boolean authenticationStatus = pdpID.equals(username) && pdpPass.equals(password);
+ return authenticationStatus;
+ }catch (Exception e){
+ logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + e);
+ // TODO:EELF Cleanup - Remove logger
+ PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "");
+ return false;
+ }
+ }
+
+}
diff --git a/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/restAuth/PDPAuthenticationFilter.java b/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/restAuth/PDPAuthenticationFilter.java
new file mode 100644
index 000000000..b3b931eaa
--- /dev/null
+++ b/ECOMP-PDP-REST/src/main/java/org/openecomp/policy/pdp/rest/restAuth/PDPAuthenticationFilter.java
@@ -0,0 +1,78 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ECOMP-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.openecomp.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.openecomp.policy.pdp.rest.restAuth.AuthenticationService;
+
+/**
+ * Servlet Filter implementation class PDPAuthenticationFilter
+ */
+@WebFilter("/*")
+public class PDPAuthenticationFilter implements Filter {
+
+ public static final String AUTHENTICATION_HEADER = "Authorization";
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response,
+ FilterChain filter) throws IOException, ServletException {
+ if (request instanceof HttpServletRequest) {
+ HttpServletRequest httpServletRequest = (HttpServletRequest) request;
+ String authCredentials = httpServletRequest.getHeader(AUTHENTICATION_HEADER);
+ String path = ((HttpServletRequest) request).getRequestURI();
+ // better injected
+ AuthenticationService authenticationService = new AuthenticationService();
+
+ boolean authenticationStatus = authenticationService.authenticate(authCredentials);
+
+ if (authenticationStatus) {
+ filter.doFilter(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);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void destroy() {
+ }
+
+ @Override
+ public void init(FilterConfig arg0) throws ServletException {
+ }
+
+}
diff --git a/ECOMP-PDP-REST/src/main/resources/log4j.properties b/ECOMP-PDP-REST/src/main/resources/log4j.properties
new file mode 100644
index 000000000..3b31771c4
--- /dev/null
+++ b/ECOMP-PDP-REST/src/main/resources/log4j.properties
@@ -0,0 +1,71 @@
+###
+# ============LICENSE_START=======================================================
+# ECOMP-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=========================================================
+###
+
+#
+# Use this properties for Deployments.
+#
+#
+# Set root logger level to DEBUG and its only appender to FILE.
+#log4j.rootLogger=DEBUG, FILE, CONSOLE
+log4j.rootLogger=INFO, FILE
+
+# FILE appender
+log4j.appender.FILE=org.apache.log4j.DailyRollingFileAppender
+log4j.appender.FILE.File=${catalina.base}/logs/pdp-rest.log
+log4j.appender.FILE.ImmediateFlush=true
+log4j.appender.FILE.Threshold=debug
+log4j.appender.FILE.append=true
+log4j.appender.FILE.DatePattern='.'yyyy-MM-dd
+log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
+log4j.appender.FILE.layout.ConversionPattern=%d{yyyy-MM-dd'T'HH:mm:ss}{GMT+0}+00:00|%X{requestId}|%X{serviceInstanceId}|%t|%X{serverName}|%X{serviceName}|%X{instanceUuid}|%p|%X{severity}|%X{serverIpAddress}|%X{server}|%X{clientIpAddress}|%l||%m%n
+
+# for Developments and Debugging
+#log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
+#log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
+#log4j.appender.CONSOLE.layout.ConversionPattern=%d{yyyy_MM_dd_HH_mm_ss_SSS} [%t] %-5p %l- %m%n
+
+#
+# This is specifically for Xacml request/response logging
+#
+log4j.logger.xacml.request=INFO, REQUEST_LOG
+
+log4j.appender.REQUEST_LOG=org.apache.log4j.DailyRollingFileAppender
+log4j.appender.REQUEST_LOG.File=${catalina.base}/logs/pdp-rest-reqres.log
+log4j.appender.REQUEST_LOG.ImmediateFlush=true
+log4j.appender.REQUEST_LOG.Threshold=debug
+log4j.appender.REQUEST_LOG.append=true
+log4j.appender.REQUEST_LOG.DatePattern='.'yyyy-MM-dd
+
+log4j.appender.REQUEST_LOG.layout=org.apache.log4j.PatternLayout
+log4j.appender.REQUEST_LOG.layout.ConversionPattern=%d{yyyy_MM_dd_HH_mm_ss_SSS} %m%n
+
+#
+# audit (transaction) logging
+#
+log4j.logger.auditLogger=INFO,AUDIT_LOG
+log4j.additivity.auditLogger=false
+
+log4j.appender.AUDIT_LOG=org.apache.log4j.DailyRollingFileAppender
+log4j.appender.AUDIT_LOG.File=${catalina.base}/logs/audit.log
+log4j.appender.AUDIT_LOG.Append=true
+log4j.appender.AUDIT_LOG.DatePattern='.'yyyy-MM-dd
+log4j.appender.AUDIT_LOG.threshold=INFO
+log4j.appender.AUDIT_LOG.layout=org.apache.log4j.EnhancedPatternLayout
+log4j.appender.AUDIT_LOG.layout.ConversionPattern=%d{yyyy-MM-dd'T'HH:mm:ss}{GMT+0}+00:00|%X{requestId}|%X{serviceInstanceId}|%t|%X{serverName}|%X{serviceName}|%X{instanceUuid}|%p|%X{severity}|%X{serverIpAddress}|%X{server}|%X{clientIpAddress}|%X{className}|%X{timer}|%m%n
diff --git a/ECOMP-PDP-REST/src/main/resources/logback.xml b/ECOMP-PDP-REST/src/main/resources/logback.xml
new file mode 100644
index 000000000..6958fa693
--- /dev/null
+++ b/ECOMP-PDP-REST/src/main/resources/logback.xml
@@ -0,0 +1,253 @@
+<!--
+ ============LICENSE_START=======================================================
+ ECOMP-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=========================================================
+ -->
+
+<configuration scan="true" scanPeriod="3 seconds" debug="true">
+ <!--<jmxConfigurator /> -->
+ <!-- directory path for all other type logs -->
+ <property name="logDir" value="logs" />
+
+ <!-- directory path for debugging type logs -->
+ <property name="debugDir" value="logs" />
+
+ <!-- specify the component name
+ <ECOMP-component-name>::= "MSO" | "DCAE" | "ASDC " | "AAI" |"Policy" | "SDNC" | "AC" -->
+ <property name="componentName" value="Policy"></property>
+ <property name="subComponentName" value="XACML-PDP-REST"></property>
+
+ <!-- log file names -->
+ <property name="errorLogName" value="error" />
+ <property name="metricsLogName" value="metrics" />
+ <property name="auditLogName" value="audit" />
+ <property name="debugLogName" value="debug" />
+
+
+ <!-- modified time stamp format -->
+
+ <!-- A U D I T
+ <property name="defaultAuditPattern" value="%X{BeginTimestamp}|%X{EndTimestamp}|%X{RequestId}|%X{ServiceInstanceId}|%thread|%X{ServerName}|%X{ServiceName}|%X{PartnerName}|%X{StatusCode}|%X{ResponseCode}|%X{ResponseDescription}|%X{InstanceUUID}|%.-5level|%X{AlertSeverity}|%X{ServerIPAddress}|%X{ElapsedTime}|%X{ServerFQDN}|%X{RemoteHost}|%X{ClassName}||%X{ProcessKey}|%X{TargetVirtualEntity}|%X{CustomField1}|%X{CustomField2}|%X{CustomField3}|%X{CustomField4}|%msg%n" />
+ <property name="defaultAuditPattern" value="%X{BeginTimestamp}|%X{EndTimestamp}|%X{requestId}|%X{serviceInstanceId}|%t|%X{serverName}|%X{serviceName}|%X{PartnerName}|%X{StatusCode}|%X{ResponseCode}|%X{ResponseDescription}|%X{instanceUuid}|%p|%X{severity}|%X{serverIpAddress}|%X{ElapsedTime}|%X{server}|%X{clientIpAddress}|%c||%X{ProcessKey}|%X{TargetVirtualEntity}|%X{CustomField1}|%X{CustomField2}|%X{CustomField3}|%X{CustomField4}|%msg%n" />
+ -->
+ <property name="defaultAuditPattern" value="%X{TransactionBeginTimestamp}|%X{TransactionEndTimestamp}|%X{requestId}|%X{serviceInstanceId}|%t|%X{serverName}|%X{serviceName}|%X{PartnerName}|%X{StatusCode}|%X{ResponseCode}|%X{ResponseDescription}|%X{instanceUuid}|%p|%X{severity}|%X{serverIpAddress}|%X{TransactionElapsedTime}|%X{server}|%X{clientIpAddress}|%c||%X{ProcessKey}|%X{TargetVirtualEntity}|%X{CustomField1}|%X{CustomField2}|%X{CustomField3}|%X{CustomField4}|%msg%n" />
+
+
+
+ <!-- M E T R I C
+ <property name="defaultMetricPattern" value="%X{BeginTimestamp}|%X{EndTimestamp}|%X{RequestId}|%X{ServiceInstanceId}|%thread|%X{ServerName}|%X{ServiceName}|%X{PartnerName}|%X{TargetEntity}|%X{TargetServiceName}|%X{StatusCode}|%X{ResponseCode}|%X{ResponseDescription}|%X{InstanceUUID}|%.-5level|%X{AlertSeverity}|%X{ServerIPAddress}|%X{ElapsedTime}|%X{ServerFQDN}|%X{RemoteHost}|%X{ClassName}||%X{ProcessKey}|%X{TargetVirtualEntity}|%X{CustomField1}|%X{CustomField2}|%X{CustomField3}|%X{CustomField4}|%msg%n" />
+ -->
+ <property name="defaultMetricPattern" value="%X{MetricBeginTimestamp}|%X{MetricEndTimestamp}|%X{requestId}|%X{serviceInstanceId}|%t|%X{serverName}|%X{serviceName}|%X{PartnerName}|%X{TargetEntity}|%X{TargetServiceName}|%X{StatusCode}|%X{ResponseCode}|%X{ResponseDescription}|%X{InstanceUUID}|%p|%X{severity}|%X{serverIpAddress}|%X{MetricElapsedTime}|%X{server}|%X{clientIpAddress}|%c||%X{ProcessKey}|%X{TargetVirtualEntity}|%X{CustomField1}|%X{CustomField2}|%X{CustomField3}|%X{CustomField4}|%msg%n" />
+
+
+
+ <!-- E R R O R
+ <property name="defaultErrorPattern" value="%d{yyyy-MM-dd'T'HH:mm:ss.SSS+00:00, UTC}|%X{RequestId}|%thread|%X{ServiceName}|%X{PartnerName}|%X{TargetEntity}|%X{TargetServiceName}|%X{ErrorCategory}|%X{ErrorCode}|%X{ErrorDesciption}|%msg%n" />
+ -->
+ <property name="defaultErrorPattern" value="%d{yyyy-MM-dd'T'HH:mm:ss.SSS+00:00, UTC}|%X{requestId}|%t|%X{serviceName}|%X{PartnerName}|%X{TargetEntity}|%X{TargetServiceName}|%X{ErrorCategory}|%X{ErrorCode}|%X{ErrorDesciption}|%msg%n" />
+
+
+
+ <!-- D E B U G
+ <property name="debugLoggerPatternOld" value="%d{MM/dd-HH:mm:ss.SSS}|%X{RequestId}|%X{ServiceInstanceId}|%thread|%X{ServiceName}|%X{InstanceUUID}|%.-5level|%X{AlertSeverity}|%X{ServerIPAddress}|%X{ServerFQDN}|%X{RemoteHost}|%X{Timer}|[%caller{3}]|%msg%n" />
+ <property name="debugLoggerPattern" value="%X{BeginTimestamp}|%X{EndTimestamp}|%X{RequestId}|%X{ServiceInstanceId}|%thread|%X{ServerName}|%X{ServiceName}|%X{PartnerName}|%X{StatusCode}|%X{ResponseCode}|%X{ResponseDescription}|%X{ServiceName}|%X{InstanceUUID}|%.-5level|%X{AlertSeverity}|%X{ServerIPAddress}|%X{ElapsedTime}|%X{ServerFQDN}|%X{RemoteHost}|%X{ClassName}||%X{ProcessKey}|%X{CustomField1}|%X{CustomField2}|%X{CustomField3}|%X{CustomField4}|%msg%n" /> -->
+ -->
+ <property name="debugLoggerPattern" value="%d{yyyy-MM-dd'T'HH:mm:ss.SSS+00:00, UTC}|%X{RequestId}|%msg%n" />
+
+
+
+ <!-- D E F A U L T
+ <property name="defaultPatternOld" value="%d{MM/dd-HH:mm:ss.SSS}|%logger|%X{RequestId}|%X{ServiceInstanceId}|%thread|%X{ServiceName}|%X{InstanceUUID}|%.-5level|%X{AlertSeverity}|%X{ServerIPAddress}|%X{ServerFQDN}|%X{RemoteHost}|%X{ClassName}|%X{Timer}|%msg%n" />
+ <property name="defaultPattern" value="%X{BeginTimestamp}|%X{EndTimestamp}|%X{RequestId}|%X{ServiceInstanceId}|%thread|%X{ServerName}|%X{ServiceName}|%X{PartnerName}|%X{TargetEntity}|%X{TargetServiceName}|%X{StatusCode}|%X{ResponseCode}|%X{ResponseDescription}|%X{InstanceUUID}|%.-5level|%X{AlertSeverity}|%X{ServerIPAddress}|%X{ElapsedTime}|%X{ServerFQDN}|%X{RemoteHost}|%X{ClassName}||%X{ProcessKey}|%X{TargetVirtualEntity}|%X{CustomField1}|%X{CustomField2}|%X{CustomField3}|%X{CustomField4}|%msg%n" />
+ -->
+ <property name="defaultPattern" value="%d{&quot;yyyy-MM-dd'T'HH:mm:ss.SSSXXX&quot;, UTC}|%X{requestId}|%X{serviceInstanceId}|%t|%X{serverName}|%X{serviceName}|%X{instanceUuid}|%p|%X{severity}|%X{serverIpAddress}|%X{server}|%X{clientIpAddress}|%c||%msg%n" />
+
+
+
+ <!-- P A T H
+ <property name="logDirectory" value="${logDir}/${componentName}/${subComponentName}" />
+ <property name="debugLogDirectory" value="${debugDir}/${componentName}/${subComponentName}" />
+
+ -->
+ <property name="logDirectory" value="${catalina.base}/${logDir}/${componentName}/${subComponentName}" />
+ <property name="debugLogDirectory" value="${catalina.base}/${debugDir}/${componentName}/${subComponentName}" />
+
+
+
+
+ <!-- Example evaluator filter applied against console appender -->
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <encoder>
+ <pattern>${defaultPattern}</pattern>
+ </encoder>
+ </appender>
+
+ <!-- ============================================================================ -->
+ <!-- EELF Appenders -->
+ <!-- ============================================================================ -->
+
+ <!-- The EELFAppender is used to record events to the general application
+ log -->
+
+ <!-- EELF Audit Appender. This appender is used to record audit engine
+ related logging events. The audit logger and appender are specializations
+ of the EELF application root logger and appender. This can be used to segregate
+ Policy engine events from other components, or it can be eliminated to record
+ these events as part of the application root log. -->
+
+ <appender name="EELFAudit"
+ class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <file>${logDirectory}/${auditLogName}.log</file>
+ <rollingPolicy
+ class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
+ <fileNamePattern>${logDirectory}/${auditLogName}.%i.log.zip
+ </fileNamePattern>
+ <minIndex>1</minIndex>
+ <maxIndex>9</maxIndex>
+ </rollingPolicy>
+ <triggeringPolicy
+ class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
+ <maxFileSize>5MB</maxFileSize>
+ </triggeringPolicy>
+ <encoder>
+ <pattern>${defaultAuditPattern}</pattern>
+ </encoder>
+ </appender>
+
+ <appender name="asyncEELFAudit" class="ch.qos.logback.classic.AsyncAppender">
+ <queueSize>256</queueSize>
+ <appender-ref ref="EELFAudit" />
+ </appender>
+
+
+
+
+<appender name="EELFMetrics"
+ class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <file>${logDirectory}/${metricsLogName}.log</file>
+ <rollingPolicy
+ class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
+ <fileNamePattern>${logDirectory}/${metricsLogName}.%i.log.zip
+ </fileNamePattern>
+ <minIndex>1</minIndex>
+ <maxIndex>9</maxIndex>
+ </rollingPolicy>
+ <triggeringPolicy
+ class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
+ <maxFileSize>5MB</maxFileSize>
+ </triggeringPolicy>
+ <encoder>
+ <!-- <pattern>"%d{HH:mm:ss.SSS} [%thread] %-5level %logger{1024} -
+ %msg%n"</pattern> -->
+ <pattern>${defaultMetricPattern}</pattern>
+ </encoder>
+ </appender>
+
+ <appender name="asyncEELFMetrics" class="ch.qos.logback.classic.AsyncAppender">
+ <queueSize>256</queueSize>
+ <appender-ref ref="EELFMetrics"/>
+ </appender>
+
+
+
+
+ <appender name="EELFError"
+ class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <file>${logDirectory}/${errorLogName}.log</file>
+ <rollingPolicy
+ class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
+ <fileNamePattern>${logDirectory}/${errorLogName}.%i.log.zip
+ </fileNamePattern>
+ <minIndex>1</minIndex>
+ <maxIndex>9</maxIndex>
+ </rollingPolicy>
+ <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+ <level>ERROR</level>
+ </filter>
+ <triggeringPolicy
+ class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
+ <maxFileSize>5MB</maxFileSize>
+ </triggeringPolicy>
+ <encoder>
+ <pattern>${defaultErrorPattern}</pattern>
+ </encoder>
+ </appender>
+
+ <appender name="asyncEELFError" class="ch.qos.logback.classic.AsyncAppender">
+ <queueSize>256</queueSize>
+ <appender-ref ref="EELFError"/>
+ </appender>
+
+
+
+ <appender name="EELFDebug"
+ class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <file>${debugLogDirectory}/${debugLogName}.log</file>
+ <rollingPolicy
+ class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
+ <fileNamePattern>${debugLogDirectory}/${debugLogName}.%i.log.zip
+ </fileNamePattern>
+ <minIndex>1</minIndex>
+ <maxIndex>9</maxIndex>
+ </rollingPolicy>
+ <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+ <level>INFO</level>
+ </filter>
+ <triggeringPolicy
+ class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
+ <maxFileSize>5MB</maxFileSize>
+ </triggeringPolicy>
+ <encoder>
+ <pattern>${debugLoggerPattern}</pattern>
+ </encoder>
+ </appender>
+
+ <appender name="asyncEELFDebug" class="ch.qos.logback.classic.AsyncAppender">
+ <queueSize>256</queueSize>
+ <appender-ref ref="EELFDebug" />
+ <includeCallerData>true</includeCallerData>
+ </appender>
+
+
+ <!-- ============================================================================ -->
+ <!-- EELF loggers -->
+ <!-- ============================================================================ -->
+
+ <logger name="com.att.eelf.audit" level="info" additivity="false">
+ <appender-ref ref="asyncEELFAudit" />
+ </logger>
+
+ <logger name="com.att.eelf.metrics" level="info" additivity="false">
+ <appender-ref ref="asyncEELFMetrics" />
+ </logger>
+
+ <logger name="com.att.eelf.error" level="error" additivity="false">
+ <appender-ref ref="asyncEELFError" />
+ </logger>
+
+ <logger name="com.att.eelf.debug" level="info" additivity="false">
+ <appender-ref ref="asyncEELFDebug" />
+ </logger>
+
+
+
+ <root level="INFO">
+ <appender-ref ref="asyncEELFDebug" />
+ <appender-ref ref="asyncEELFError" />
+ </root>
+
+</configuration>
diff --git a/ECOMP-PDP-REST/src/test/java/org/openecomp/policy/pdp/rest/PapUrlResolverTest.java b/ECOMP-PDP-REST/src/test/java/org/openecomp/policy/pdp/rest/PapUrlResolverTest.java
new file mode 100644
index 000000000..7a8060114
--- /dev/null
+++ b/ECOMP-PDP-REST/src/test/java/org/openecomp/policy/pdp/rest/PapUrlResolverTest.java
@@ -0,0 +1,355 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ECOMP-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.openecomp.policy.pdp.rest;
+import org.junit.Before;
+import org.junit.Test;
+import org.openecomp.policy.pdp.rest.PapUrlResolver;
+import org.openecomp.policy.rest.XACMLRestProperties;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Properties;
+
+import org.junit.Assert;
+
+public class PapUrlResolverTest {
+
+
+ @Test
+ public void testPropertyModifications(){
+ long currentTime = new Date().getTime();
+ DateFormat df = new SimpleDateFormat();
+ //first sort order
+ String urls = "http://one.localhost.com,http://two.localhost.com,http://three.localhost.com,http://four.localhost.com";
+ String failed = "-1,-1,-1,-1";
+ String succeeded = "-1,-1,-1,-1";
+ PapUrlResolver rs = PapUrlResolver.getInstance(urls, failed, succeeded);
+ Assert.assertEquals(rs.getProperties().getProperty(XACMLRestProperties.PROP_PAP_URLS),urls);
+
+ rs.failed();
+ rs.getNext();
+ Assert.assertTrue(rs.hasMoreUrls());
+ rs.succeeded();
+ Assert.assertFalse(rs.hasMoreUrls());
+ Properties prop = rs.getProperties();
+ Assert.assertEquals(df.format(new Date())+",-1,-1,-1",prop.getProperty(XACMLRestProperties.PROP_PAP_FAILED_URLS));
+ Assert.assertEquals("-1,"+df.format(new Date())+",-1,-1",prop.getProperty(XACMLRestProperties.PROP_PAP_SUCCEEDED_URLS));
+
+ failed = prop.getProperty(XACMLRestProperties.PROP_PAP_FAILED_URLS);
+ succeeded = prop.getProperty(XACMLRestProperties.PROP_PAP_SUCCEEDED_URLS);
+ rs = PapUrlResolver.getInstance(urls, failed, succeeded);
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://two.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://three.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://four.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://one.localhost.com", rs.getUrl());
+ rs.succeeded();
+ rs.getNext();
+ Assert.assertFalse(rs.hasMoreUrls());
+ prop = rs.getProperties();
+ Assert.assertEquals("-1,-1,-1,-1",prop.getProperty(XACMLRestProperties.PROP_PAP_FAILED_URLS));
+
+ failed = prop.getProperty(XACMLRestProperties.PROP_PAP_FAILED_URLS);
+ succeeded = prop.getProperty(XACMLRestProperties.PROP_PAP_SUCCEEDED_URLS);
+ rs = PapUrlResolver.getInstance(urls, failed, succeeded);
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://one.localhost.com", rs.getUrl());
+ rs.succeeded();
+ rs.getNext();
+ Assert.assertFalse(rs.hasMoreUrls());
+ prop = rs.getProperties();
+ failed = prop.getProperty(XACMLRestProperties.PROP_PAP_FAILED_URLS);
+ succeeded = prop.getProperty(XACMLRestProperties.PROP_PAP_SUCCEEDED_URLS);
+ rs = PapUrlResolver.getInstance(urls, failed, succeeded);
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://one.localhost.com", rs.getUrl());
+ rs.succeeded();
+ rs.getNext();
+ Assert.assertFalse(rs.hasMoreUrls());
+ prop = rs.getProperties();
+ failed = prop.getProperty(XACMLRestProperties.PROP_PAP_FAILED_URLS);
+ succeeded = prop.getProperty(XACMLRestProperties.PROP_PAP_SUCCEEDED_URLS);
+ rs = PapUrlResolver.getInstance(urls, failed, succeeded);
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://one.localhost.com", rs.getUrl());
+ rs.succeeded();
+ rs.getNext();
+ Assert.assertFalse(rs.hasMoreUrls());
+
+
+ prop = rs.getProperties();
+ succeeded = prop.getProperty(XACMLRestProperties.PROP_PAP_SUCCEEDED_URLS);
+ System.out.println(succeeded);
+ //can't test this in a timely manner since it will need to wait a minute, since they all succeeded at the same time
+ /*
+ prop = rs.getProperties();
+ failed = prop.getProperty(XACMLRestProperties.PROP_PAP_FAILED_URLS);
+ succeeded = prop.getProperty(XACMLRestProperties.PROP_PAP_SUCCEEDED_URLS);
+ rs = PapUrlResolver.getInstance(urls, failed, succeeded);
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://two.localhost.com", rs.getUrl());
+ rs.succeeded();
+ rs.getNext();
+ Assert.assertFalse(rs.hasMoreUrls());
+ */
+ }
+ @Test
+ public void testModifyUrl(){
+ String newUrl = PapUrlResolver.modifyUrl("http://mypap1.com/pap?id=987654", "http://mypap2.com:45/pap/");
+ int u = 8;
+ }
+
+ @Test
+ public void testSorts(){
+ long currentTime = new Date().getTime();
+ DateFormat df = new SimpleDateFormat();
+ //first sort order
+ String urls = "http://one.localhost.com,http://two.localhost.com,http://three.localhost.com,http://four.localhost.com";
+ String failed = df.format(new Date(currentTime-3600000))+",-1,-1,"+df.format(new Date(currentTime-3200000));
+ String succeeded = "-1,8/13/15 5:41 PM,8/13/15 4:41 PM,-1";
+ PapUrlResolver rs = PapUrlResolver.getInstance(urls, failed, succeeded);
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://two.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://three.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://one.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://four.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertFalse(rs.hasMoreUrls());
+
+ urls = "http://one.localhost.com,http://two.localhost.com,http://three.localhost.com,http://four.localhost.com";
+ failed = "-1,-1,-1,-1";
+ succeeded = "-1,"+df.format(new Date(currentTime-3600000))+","+df.format(new Date(currentTime-6600000))+",-1";
+ rs = PapUrlResolver.getInstance(urls, failed, succeeded);
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://one.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://two.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://three.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://four.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertFalse(rs.hasMoreUrls());
+
+ urls = "http://one.localhost.com,http://two.localhost.com,http://three.localhost.com,http://four.localhost.com";
+ failed = "-1,-1,-1,-1";
+ succeeded = "-1,-1,-1,-1";
+ rs = PapUrlResolver.getInstance(urls, failed, succeeded);
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://one.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://two.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://three.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://four.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertFalse(rs.hasMoreUrls());
+
+ urls = "http://one.localhost.com,http://two.localhost.com,http://three.localhost.com,http://four.localhost.com";
+ failed = df.format(new Date(currentTime-3900000))+","+df.format(new Date(currentTime-5600000))+","+df.format(new Date(currentTime-4600000))+","+df.format(new Date(currentTime-3600000));
+ succeeded = "-1,-1,-1,-1";
+ rs = PapUrlResolver.getInstance(urls, failed, succeeded);
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://two.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://three.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://one.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://four.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertFalse(rs.hasMoreUrls());
+
+ urls = "http://one.localhost.com,http://two.localhost.com,http://three.localhost.com,http://four.localhost.com";
+ failed = df.format(new Date(currentTime-(3600000*4)))+",-1,-1,-1";
+ succeeded = "-1,-1,-1,-1";
+ rs = PapUrlResolver.getInstance(urls, failed, succeeded);
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://two.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://three.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://four.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://one.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertFalse(rs.hasMoreUrls());
+
+ urls = "http://one.localhost.com,http://two.localhost.com,http://three.localhost.com,http://four.localhost.com";
+ failed = df.format(new Date(currentTime-(3600000*6)))+",-1,-1,-1";
+ succeeded = "-1,-1,-1,-1";
+ rs = PapUrlResolver.getInstance(urls, failed, succeeded);
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://one.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://two.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://three.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://four.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertFalse(rs.hasMoreUrls());
+
+
+
+
+ //not used because we are no longer sorting based on success time, only failed time. Modified above.
+ /*
+ //first sort order
+ String urls = "http://one.localhost.com,http://two.localhost.com,http://three.localhost.com,http://four.localhost.com";
+ String failed = df.format(new Date(currentTime-3600000))+",-1,-1,"+df.format(new Date(currentTime-3200000));
+ String succeeded = "-1,8/13/15 5:41 PM,8/13/15 4:41 PM,-1";
+ PapUrlResolver rs = PapUrlResolver.getInstance(urls, failed, succeeded);
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://three.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://two.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://one.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://four.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertFalse(rs.hasMoreUrls());
+
+ urls = "http://one.localhost.com,http://two.localhost.com,http://three.localhost.com,http://four.localhost.com";
+ failed = "-1,-1,-1,-1";
+ succeeded = "-1,"+df.format(new Date(currentTime-3600000))+","+df.format(new Date(currentTime-6600000))+",-1";
+ rs = PapUrlResolver.getInstance(urls, failed, succeeded);
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://one.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://four.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://three.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://two.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertFalse(rs.hasMoreUrls());
+
+ urls = "http://one.localhost.com,http://two.localhost.com,http://three.localhost.com,http://four.localhost.com";
+ failed = "-1,-1,-1,-1";
+ succeeded = "-1,-1,-1,-1";
+ rs = PapUrlResolver.getInstance(urls, failed, succeeded);
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://one.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://two.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://three.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://four.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertFalse(rs.hasMoreUrls());
+
+ urls = "http://one.localhost.com,http://two.localhost.com,http://three.localhost.com,http://four.localhost.com";
+ failed = df.format(new Date(currentTime-3900000))+","+df.format(new Date(currentTime-5600000))+","+df.format(new Date(currentTime-4600000))+","+df.format(new Date(currentTime-3600000));
+ succeeded = "-1,-1,-1,-1";
+ rs = PapUrlResolver.getInstance(urls, failed, succeeded);
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://two.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://three.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://one.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://four.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertFalse(rs.hasMoreUrls());
+
+ urls = "http://one.localhost.com,http://two.localhost.com,http://three.localhost.com,http://four.localhost.com";
+ failed = df.format(new Date(currentTime-(3600000*4)))+",-1,-1,-1";
+ succeeded = "-1,-1,-1,-1";
+ rs = PapUrlResolver.getInstance(urls, failed, succeeded);
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://two.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://three.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://four.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://one.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertFalse(rs.hasMoreUrls());
+
+ urls = "http://one.localhost.com,http://two.localhost.com,http://three.localhost.com,http://four.localhost.com";
+ failed = df.format(new Date(currentTime-(3600000*6)))+",-1,-1,-1";
+ succeeded = "-1,-1,-1,-1";
+ rs = PapUrlResolver.getInstance(urls, failed, succeeded);
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://one.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://two.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://three.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertTrue(rs.hasMoreUrls());
+ Assert.assertEquals("http://four.localhost.com", rs.getUrl());
+ rs.getNext();
+ Assert.assertFalse(rs.hasMoreUrls());
+ */
+ }
+}
diff --git a/ECOMP-PDP-REST/src/test/java/org/openecomp/policy/pdp/rest/XACMLPdpServletTest.java b/ECOMP-PDP-REST/src/test/java/org/openecomp/policy/pdp/rest/XACMLPdpServletTest.java
new file mode 100644
index 000000000..95cb0293c
--- /dev/null
+++ b/ECOMP-PDP-REST/src/test/java/org/openecomp/policy/pdp/rest/XACMLPdpServletTest.java
@@ -0,0 +1,395 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ECOMP-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.openecomp.policy.pdp.rest;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Properties;
+import java.util.Random;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletInputStream;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import junit.framework.TestCase;
+
+import org.apache.commons.lang.math.RandomUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.openecomp.policy.pdp.rest.XACMLPdpServlet;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.mock.web.MockServletConfig;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import org.openecomp.policy.common.im.AdministrativeStateException;
+import org.openecomp.policy.common.im.IntegrityMonitor;
+import org.openecomp.policy.common.im.StandbyStatusException;
+
+import com.att.research.xacml.util.XACMLProperties;
+import com.mockrunner.mock.web.MockServletInputStream;
+import org.openecomp.policy.common.logging.flexlogger.*;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(IntegrityMonitor.class) // so PowerMock can mock static method of IntegrityMonitor
+public class XACMLPdpServletTest extends TestCase{
+ private static Logger logger = FlexLogger.getLogger(XACMLPdpServletTest.class);
+
+ private List<String> headers = new ArrayList<String>();
+
+ private HttpServletRequest httpServletRequest;
+ private HttpServletResponse httpServletResponse;
+ private ServletOutputStream mockOutput;
+ private ServletInputStream mockInput;
+ private ServletConfig servletConfig;
+ private XACMLPdpServlet pdpServlet;
+ private IntegrityMonitor im;
+
+
+
+ @Before
+ public void setUp(){
+ httpServletRequest = Mockito.mock(HttpServletRequest.class);
+ Mockito.when(httpServletRequest.getMethod()).thenReturn("POST");
+ Mockito.when(httpServletRequest.getHeaderNames()).thenReturn(Collections.enumeration(headers));
+ Mockito.when(httpServletRequest.getAttributeNames()).thenReturn(Collections.enumeration(headers));
+
+
+ mockOutput = Mockito.mock(ServletOutputStream.class);
+
+ httpServletResponse = Mockito.mock(MockHttpServletResponse.class);
+
+ try {
+ Mockito.when(httpServletResponse.getOutputStream()).thenReturn(mockOutput);
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ fail();
+ }
+
+
+ //when(httpServletResponse.getOutputStream()).thenReturn(servletOutputStream);
+ servletConfig = Mockito.mock(MockServletConfig.class);
+ //Mockito.when(servletConfig.getInitParameterNames()).thenReturn(Collections.enumeration(headers));
+ //servletConfig
+ Mockito.when(servletConfig.getInitParameterNames()).thenReturn(Collections.enumeration(headers));
+ pdpServlet = new XACMLPdpServlet();
+
+ Mockito.when(servletConfig.getInitParameter("XACML_PROPERTIES_NAME")).thenReturn("xacml.pdp.properties");
+
+ System.setProperty("xacml.properties", "xacml.pdp.properties");
+ System.setProperty("xacml.rest.pdp.config", "config_testing");
+ System.setProperty("xacml.rest.pep.idfile", "testclient.properties");
+ System.setProperty("xacml.rest.pdp.webapps", "/webapps");
+ System.setProperty("xacml.rootPolicies", "test_PolicyEngine.xml");
+ System.setProperty("xacml.referencedPolicies", "test_PolicyEngine.xml");
+ System.setProperty("test_PolicyEngine.xml.file", "config_testing\\test_PolicyEngine.xml");
+ System.setProperty("xacml.rest.pdp.register", "false");
+ System.setProperty("com.sun.management.jmxremote.port", "9999");
+
+ im = Mockito.mock(IntegrityMonitor.class);
+ // Need PowerMockito for mocking static method getInstance(...)
+ PowerMockito.mockStatic(IntegrityMonitor.class);
+ try {
+ // when IntegrityMonitor.getInstance is called, return the mock object
+ PowerMockito.when(IntegrityMonitor.getInstance(Mockito.anyString(), Mockito.any(Properties.class))).thenReturn(im);
+ } catch (Exception e1) {
+ // TODO Auto-generated catch block
+ e1.printStackTrace();
+ }
+
+ try {
+ Mockito.doNothing().when(im).startTransaction();
+ } catch (StandbyStatusException | AdministrativeStateException e) {
+ fail();
+ }
+ Mockito.doNothing().when(im).endTransaction();
+ }
+
+ public void testInit(){
+ logger.info("XACMLPdpServletTest - testInit");
+ try {
+ pdpServlet.init(servletConfig);
+ assertTrue(true);
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ System.out.println("Unexpected exception in testInit");
+ e.printStackTrace();
+ fail();
+
+ }
+
+ }
+
+ public void testDoGetNoTypeError(){
+ logger.info("XACMLPdpServletTest - testDoGetNoTypeError");
+ try{
+ pdpServlet.init(servletConfig);
+ pdpServlet.doGet(httpServletRequest, httpServletResponse);
+ Mockito.verify(httpServletResponse).sendError(HttpServletResponse.SC_BAD_REQUEST, "type not 'config' or 'hb'");
+ assertTrue(true);
+ }catch(Exception e){
+ System.out.println("Unexpected exception in testDoGetNoTypeError");
+ e.printStackTrace();
+ fail();
+ }
+ }
+
+ public void testDoGetConfigType(){
+ logger.info("XACMLPdpServletTest - testDoGetConfigType");
+ Mockito.when(httpServletRequest.getParameter("type")).thenReturn("config");
+
+ try{
+ pdpServlet.init(servletConfig);
+ pdpServlet.doGet(httpServletRequest, httpServletResponse);
+ Mockito.verify(httpServletResponse).setStatus(HttpServletResponse.SC_OK);
+ //Mockito.verify(httpServletResponse).sendError(400, "Failed to copy Property file");
+ assertTrue(true);
+ }catch (Exception e){
+ System.out.println("Unexpected exception in testDoGetConfigType");
+ e.printStackTrace();
+ fail();
+ }
+
+ }
+
+
+ public void testDoGetTypeHb(){
+ logger.info("XACMLPdpServletTest - testDoGetTypeHb");
+ try{
+ Mockito.when(httpServletRequest.getParameter("type")).thenReturn("hb");
+ pdpServlet.init(servletConfig);
+ pdpServlet.doGet(httpServletRequest, httpServletResponse);
+ Mockito.verify(httpServletResponse).setStatus(HttpServletResponse.SC_NO_CONTENT);
+ assertTrue(true);
+ }catch(Exception e){
+ System.out.println("Unexpected exception in testDoGetTypeHb");
+ e.printStackTrace();
+ fail();
+ }
+ }
+ public void testDoGetTypeStatus(){
+ logger.info("XACMLPdpServletTest - testDoGetTypeStatus");
+ try{
+ Mockito.when(httpServletRequest.getParameter("type")).thenReturn("Status");
+ pdpServlet.init(servletConfig);
+ pdpServlet.doGet(httpServletRequest, httpServletResponse);
+ Mockito.verify(httpServletResponse).setStatus(HttpServletResponse.SC_OK);
+ assertTrue(true);
+ }catch(Exception e){
+ System.out.println("Unexpected exception in testDoGetTypeStatus");
+ e.printStackTrace();
+ fail();
+ }
+ }
+
+ public void testDoPost(){
+ logger.info("XACMLPdpServletTest - testDoPost");
+ try{
+ pdpServlet.init(servletConfig);
+ pdpServlet.doPost(httpServletRequest, httpServletResponse);
+ //response.sendError(HttpServletResponse.SC_BAD_REQUEST, "no content-type given");
+ //Mockito.verify(httpServletResponse).sendError(HttpServletResponse.SC_BAD_REQUEST, "no content-type given");
+ assertTrue(true);
+ }catch (Exception e){
+ System.out.println("Unexpected exception in testDoPost");
+ e.printStackTrace();
+ fail();
+ }
+ }
+
+ public void testDoPostToLong(){
+ logger.info("XACMLPdpServletTest - testDoPostToLong");
+ try{
+ Mockito.when(httpServletRequest.getContentType()).thenReturn("stuff");
+ Mockito.when(httpServletRequest.getContentLength()).thenReturn(32768);
+
+ pdpServlet.init(servletConfig);
+ pdpServlet.doPost(httpServletRequest, httpServletResponse);
+ //response.sendError(HttpServletResponse.SC_BAD_REQUEST, "no content-type given");
+ //Mockito.verify(httpServletResponse).sendError(HttpServletResponse.SC_BAD_REQUEST, "Content-Length larger than server will accept.");
+ assertTrue(true);
+ }catch (Exception e){
+ System.out.println("Unexpected exception in testDoPostToLong");
+ e.printStackTrace();
+ fail();
+ }
+ }
+
+ public void testDoPostContentLengthNegative(){
+ logger.info("XACMLPdpServletTest - testDoPostToLong");
+ try{
+ Mockito.when(httpServletRequest.getContentType()).thenReturn("stuff");
+ Mockito.when(httpServletRequest.getContentLength()).thenReturn(-1);
+
+ pdpServlet.init(servletConfig);
+ pdpServlet.doPost(httpServletRequest, httpServletResponse);
+ //response.sendError(HttpServletResponse.SC_BAD_REQUEST, "no content-type given");
+ //Mockito.verify(httpServletResponse).sendError(HttpServletResponse.SC_BAD_REQUEST, "Content-Length is negative");
+ assertTrue(true);
+ }catch (Exception e){
+ System.out.println("Unexpected exception in testDoPostContentLengthNegative");
+ e.printStackTrace();
+ fail();
+ }
+ }
+
+ public void testDoPostContentTypeNonValid(){
+ logger.info("XACMLPdpServletTest - testDoPostToLong");
+ try{
+ Mockito.when(httpServletRequest.getContentType()).thenReturn(";");
+ Mockito.when(httpServletRequest.getContentLength()).thenReturn(30768);
+
+ pdpServlet.init(servletConfig);
+ pdpServlet.doPost(httpServletRequest, httpServletResponse);
+ //response.sendError(HttpServletResponse.SC_BAD_REQUEST, "no content-type given");
+ //Mockito.verify(httpServletResponse).sendError(HttpServletResponse.SC_BAD_REQUEST, "Parsing Content-Type: ;, error=Invalid content type: ;");
+ assertTrue(true);
+ }catch (Exception e){
+ System.out.println("Unexpected exception in testDoPostContentTypeNonValid");
+ e.printStackTrace();
+ fail();
+ }
+ }
+
+ public void testDoPostContentTypeConfigurationError(){
+ logger.info("XACMLPdpServletTest - testDoPostToLong");
+ try{
+ Mockito.when(httpServletRequest.getContentType()).thenReturn("stuff");
+ Mockito.when(httpServletRequest.getContentLength()).thenReturn(30768);
+
+ pdpServlet.init(servletConfig);
+ pdpServlet.doPost(httpServletRequest, httpServletResponse);
+ //response.sendError(HttpServletResponse.SC_BAD_REQUEST, "no content-type given");
+ //Mockito.verify(httpServletResponse).sendError(HttpServletResponse.SC_BAD_REQUEST, "unsupported content typestuff");
+ assertTrue(true);
+ }catch (Exception e){
+ System.out.println("Unexpected exception in testDoPostContentTypeConfigurationError");
+ e.printStackTrace();
+ fail();
+ }
+ }
+
+ public void testDoPutCacheEmpty(){
+ logger.info("XACMLPdpServletTest - testDoPutCacheEmpty");
+ mockInput = Mockito.mock(ServletInputStream.class);
+
+ try{
+ Mockito.when(httpServletRequest.getParameter("cache")).thenReturn("cache");
+ Mockito.when(httpServletRequest.getContentType()).thenReturn("text/x-java-properties");
+ Mockito.when(httpServletRequest.getInputStream()).thenReturn(mockInput);
+ pdpServlet.init(servletConfig);
+ pdpServlet.doPut(httpServletRequest, httpServletResponse);
+ Mockito.verify(httpServletResponse).sendError(HttpServletResponse.SC_BAD_REQUEST, "PUT must contain at least one property");
+ assertTrue(true);
+ }catch (Exception e){
+ System.out.println("Unexpected exception in testDoPutCacheEmpty");
+ e.printStackTrace();
+ fail();
+ }
+ }
+
+ public void testDoPutConfigPolicies(){
+ logger.info("XACMLPdpServletTest - testDoPutConfigPolicies");
+ byte[] b = new byte[20];
+ new Random().nextBytes(b);
+
+ mockInput = new MockServletInputStream(b);
+
+ try{
+ Mockito.when(httpServletRequest.getParameter("cache")).thenReturn("policies");
+ Mockito.when(httpServletRequest.getContentType()).thenReturn("text/x-java-properties");
+ Mockito.when(httpServletRequest.getInputStream()).thenReturn(mockInput);
+ pdpServlet.init(servletConfig);
+ pdpServlet.doPut(httpServletRequest, httpServletResponse);
+ /*
+ * Started failing 8/17/16
+ * Mockito.verify(httpServletResponse).sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Missing property: xacml.rootPolicies");
+ */
+ assertTrue(true);
+ }catch (Exception e){
+ System.out.println("Unexpected exception in testDoPutConfigPolicies");
+ e.printStackTrace();
+ fail();
+ }
+ }
+
+ public void testDoPutToLong(){
+ logger.info("XACMLPdpServletTest - testDoPutToLong");
+ try{
+ Mockito.when(httpServletRequest.getParameter("cache")).thenReturn("policies");
+
+ Mockito.when(httpServletRequest.getContentType()).thenReturn("text/x-java-properties");
+ Mockito.when(httpServletRequest.getContentLength()).thenReturn(1000000000);
+
+ pdpServlet.init(servletConfig);
+ pdpServlet.doPut(httpServletRequest, httpServletResponse);
+ //response.sendError(HttpServletResponse.SC_BAD_REQUEST, "no content-type given");
+ Mockito.verify(httpServletResponse).sendError(HttpServletResponse.SC_BAD_REQUEST, "Content-Length larger than server will accept.");
+ assertTrue(true);
+ }catch (Exception e){
+ System.out.println("Unexpected exception in testDoPutToLong");
+ e.printStackTrace();
+ fail();
+ }
+ }
+
+ public void testDoPutInvalidContentType(){
+ logger.info("XACMLPdpServletTest - testDoPutToLong");
+ try{
+ Mockito.when(httpServletRequest.getParameter("cache")).thenReturn("policies");
+
+ Mockito.when(httpServletRequest.getContentType()).thenReturn("text/json");
+ Mockito.when(httpServletRequest.getContentLength()).thenReturn(32768);
+
+ pdpServlet.init(servletConfig);
+ pdpServlet.doPut(httpServletRequest, httpServletResponse);
+ //response.sendError(HttpServletResponse.SC_BAD_REQUEST, "no content-type given");
+ Mockito.verify(httpServletResponse).sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid cache: 'policies' or content-type: 'text/json'");
+ assertTrue(true);
+ }catch (Exception e){
+ System.out.println("Unexpected exception in testDoPutInvalidContentType");
+ e.printStackTrace();
+ fail();
+ }
+ }
+
+ public void testDestroy(){
+ logger.info("XACMLPdpServletTest - testDestroy");
+
+ try{
+ pdpServlet.init(servletConfig);
+ pdpServlet.destroy();
+ }catch(Exception e){
+ System.out.println("Unexpected exception in testDestroy");
+ e.printStackTrace();
+ fail();
+ }
+ }
+}