From 7fd58e9a2427a215daa6b543e901534e83d3c246 Mon Sep 17 00:00:00 2001 From: rb7147 Date: Tue, 4 Sep 2018 14:16:04 -0400 Subject: XACML Platform Enhancements To Support Raw Policy Creation from GUI and API. GetDecision on combining algorithim with Policy Set. Issue-ID: POLICY-902 Change-Id: Ie3189f8ded2e03366bc7d65d15b95b88c89b0acd Signed-off-by: rb7147 --- .../org/onap/policy/pdp/rest/XACMLPdpServlet.java | 2390 ++++++++++---------- .../rest/api/services/DecisionPolicyService.java | 3 +- .../pdp/rest/api/services/GetDecisionService.java | 255 ++- .../policy/pdp/rest/api/services/PDPServices.java | 457 ++-- 4 files changed, 1713 insertions(+), 1392 deletions(-) (limited to 'ONAP-PDP-REST/src/main/java/org/onap/policy') diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/XACMLPdpServlet.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/XACMLPdpServlet.java index 567ff2e78..87cafc4ef 100644 --- a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/XACMLPdpServlet.java +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/XACMLPdpServlet.java @@ -34,7 +34,6 @@ 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; @@ -43,7 +42,6 @@ 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; @@ -65,7 +63,6 @@ import org.onap.policy.rest.XACMLRestProperties; import org.onap.policy.xacml.api.XACMLErrorConstants; import org.onap.policy.xacml.pdp.std.functions.PolicyList; import org.onap.policy.xacml.std.pap.StdPDPStatus; - import com.att.research.xacml.api.Request; import com.att.research.xacml.api.Response; import com.att.research.xacml.api.pap.PDPStatus.Status; @@ -81,17 +78,17 @@ 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. + * 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. + * 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: + * 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 * @@ -101,186 +98,189 @@ import com.fasterxml.jackson.databind.ObjectMapper; * * */ -@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.") - }) +@WebServlet(description = "Implements the XACML PDP RESTful API and client PAP API.", urlPatterns = {"/"}, + loadOnStartup = 1, initParams = {@WebInitParam(name = "XACML_PROPERTIES_NAME", value = "xacml.pdp.properties", + description = "The location of the PDP xacml.pdp.properties file holding configuration information.")}) public class XACMLPdpServlet extends HttpServlet implements Runnable { - private static final long serialVersionUID = 1L; - private static final String DEFAULT_MAX_CONTENT_LENGTH = "999999999"; //32767 - private static final String CREATE_UPDATE_POLICY_SERVICE = "org.onap.policy.pdp.rest.api.services.CreateUpdatePolicyServiceImpl"; - // - // Our application debug log - // - private static final Log logger = LogFactory.getLog(XACMLPdpServlet.class); - // - // This logger is specifically only for Xacml requests and their corresponding response. - // It's output ideally should be sent to a separate file from the application logger. - // - private static final Log requestLogger = LogFactory.getLog("xacml.request"); - // - // audit logger - private static final Log auditLogger = LogFactory.getLog("auditLogger"); - - private static final PdpRestMonitor monitor = PdpRestMonitor.getSingleton(); - - // - // This thread may getting invoked on startup, to let the PAP know - // that we are up and running. - // - private static transient Thread registerThread = null; - private static transient XACMLPdpRegisterThread registerRunnable = null; - // - // This is our PDP engine pointer. There is a synchronized lock used - // for access to the pointer. In case we are servicing PEP requests while - // an update is occurring from the PAP. - // - private static PDPEngine pdpEngine = null; - private static final Object pdpEngineLock = new Object(); - // - // This is our PDP's status. What policies are loaded (or not) and - // what PIP configurations are loaded (or not). - // There is a synchronized lock used for access to the object. - // - private static volatile StdPDPStatus status = new StdPDPStatus(); - private static final Object pdpStatusLock = new Object(); - private static Constructor createUpdatePolicyConstructor; - - private static final String ENVIORNMENT_HEADER = "Environment"; - private static String environment = null; - // - // Queue of PUT requests - // - public static class PutRequest { - private Properties policyProperties = null; - private Properties pipConfigProperties = null; - - PutRequest(Properties policies, Properties pips) { - this.policyProperties = policies; - this.pipConfigProperties = pips; - } - } - protected static volatile BlockingQueue queue = null; - // For notification Delay. - private static int notificationDelay = 0; - public static int getNotificationDelay(){ - return XACMLPdpServlet.notificationDelay; - } - - private static String pdpResourceName; - private static String[] dependencyNodes = null; - - // - // This is our configuration thread that attempts to load - // a new configuration request. - // - private static transient Thread configThread = null; - private static volatile boolean configThreadTerminate = false; - private transient ONAPLoggingContext baseLoggingContext = null; - private transient IntegrityMonitor im; - public IntegrityMonitor getIm() { - return im; - } - - public void setIm(IntegrityMonitor im) { - this.im = im; - } - - /** - * Default constructor. - */ - public XACMLPdpServlet() { - //Default constructor. - } - - /** - * @see Servlet#init(ServletConfig) - */ - @Override - public void init(ServletConfig config) throws ServletException { - String createUpdateResourceName = null; - String dependencyGroups = null; - // - // Initialize - // - XACMLRest.xacmlInit(config); - // Load the Notification Delay. - setNotificationDelay(); - // Load Queue size. Not sure if we really need to have the queue bounded, we should look further into this - int queueSize = 50; // Set default Queue Size here. - queueSize = Integer.parseInt(XACMLProperties.getProperty("REQUEST_BUFFER_SIZE",String.valueOf(queueSize))); - initQueue(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; - } - // Notification will be Sent Here. - XACMLPdpLoader.sendNotification(); - } - // - // Logging stuff.... - // - baseLoggingContext = new ONAPLoggingContext(); - // 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"+e); - } - - Properties properties; - try { - properties = XACMLProperties.getProperties(); - } catch (IOException e) { - PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, - "Error loading properties with: XACMLProperties.getProperties()"); - throw new ServletException(e.getMessage(), e.getCause()); - } - if(properties.getProperty(XACMLRestProperties.PDP_RESOURCE_NAME)==null){ - XACMLProperties.reloadProperties(); - try { - properties = XACMLProperties.getProperties(); - } catch (IOException e) { - PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, - "Error loading properties with: XACMLProperties.getProperties()"); - throw new ServletException(e.getMessage(), e.getCause()); - } - PolicyLogger.info("\n Properties Given : \n" + properties.toString()); - } - setPDPResourceName(properties); - 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"); - } - setDependencyNodes(dependencyGroups); - - - // CreateUpdatePolicy ResourceName - createUpdateResourceName = properties.getProperty("createUpdatePolicy.impl.className", CREATE_UPDATE_POLICY_SERVICE); - setCreateUpdatePolicyConstructor(createUpdateResourceName); - - // Create an IntegrityMonitor - try { - logger.info("Creating IntegrityMonitor"); - im = IntegrityMonitor.getInstance(pdpResourceName, properties); - } catch (Exception e) { - PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "Failed to create IntegrityMonitor" +e); - throw new ServletException(e); - } - startThreads(baseLoggingContext, new Thread(this)); - } - - private static void startThreads(ONAPLoggingContext baseLoggingContext, Thread thread) { - environment = XACMLProperties.getProperty("ENVIRONMENT", "DEVL"); + private static final long serialVersionUID = 1L; + private static final String DEFAULT_MAX_CONTENT_LENGTH = "999999999"; // 32767 + private static final String CREATE_UPDATE_POLICY_SERVICE = + "org.onap.policy.pdp.rest.api.services.CreateUpdatePolicyServiceImpl"; + // + // Our application debug log + // + private static final Log logger = LogFactory.getLog(XACMLPdpServlet.class); + // + // This logger is specifically only for Xacml requests and their corresponding response. + // It's output ideally should be sent to a separate file from the application logger. + // + private static final Log requestLogger = LogFactory.getLog("xacml.request"); + // + // audit logger + private static final Log auditLogger = LogFactory.getLog("auditLogger"); + + public static final PdpRestMonitor monitor = PdpRestMonitor.getSingleton(); + + // + // This thread may getting invoked on startup, to let the PAP know + // that we are up and running. + // + private static transient Thread registerThread = null; + private static transient XACMLPdpRegisterThread registerRunnable = null; + // + // This is our PDP engine pointer. There is a synchronized lock used + // for access to the pointer. In case we are servicing PEP requests while + // an update is occurring from the PAP. + // + private static PDPEngine pdpEngine = null; + private static final Object pdpEngineLock = new Object(); + // + // This is our PDP's status. What policies are loaded (or not) and + // what PIP configurations are loaded (or not). + // There is a synchronized lock used for access to the object. + // + private static volatile StdPDPStatus status = new StdPDPStatus(); + private static final Object pdpStatusLock = new Object(); + private static Constructor createUpdatePolicyConstructor; + + private static final String ENVIORNMENT_HEADER = "Environment"; + private static String environment = null; + + // + // Queue of PUT requests + // + public static class PutRequest { + private Properties policyProperties = null; + private Properties pipConfigProperties = null; + + PutRequest(Properties policies, Properties pips) { + this.policyProperties = policies; + this.pipConfigProperties = pips; + } + } + + protected static volatile BlockingQueue queue = null; + // For notification Delay. + private static int notificationDelay = 0; + + public static int getNotificationDelay() { + return XACMLPdpServlet.notificationDelay; + } + + private static String pdpResourceName; + private static String[] dependencyNodes = null; + + // + // This is our configuration thread that attempts to load + // a new configuration request. + // + private static transient Thread configThread = null; + private static volatile boolean configThreadTerminate = false; + private transient ONAPLoggingContext baseLoggingContext = null; + private transient IntegrityMonitor im; + + public IntegrityMonitor getIm() { + return im; + } + + public void setIm(IntegrityMonitor im) { + this.im = im; + } + + /** + * Default constructor. + */ + public XACMLPdpServlet() { + // Default constructor. + } + + /** + * @see Servlet#init(ServletConfig) + */ + @Override + public void init(ServletConfig config) throws ServletException { + String createUpdateResourceName = null; + String dependencyGroups = null; + // + // Initialize + // + XACMLRest.xacmlInit(config); + // Load the Notification Delay. + setNotificationDelay(); + // Load Queue size. Not sure if we really need to have the queue bounded, we should look further into this + int queueSize = 50; // Set default Queue Size here. + queueSize = Integer.parseInt(XACMLProperties.getProperty("REQUEST_BUFFER_SIZE", String.valueOf(queueSize))); + initQueue(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; + } + // Notification will be Sent Here. + XACMLPdpLoader.sendNotification(); + } + // + // Logging stuff.... + // + baseLoggingContext = new ONAPLoggingContext(); + // 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" + e); + } + + Properties properties; + try { + properties = XACMLProperties.getProperties(); + } catch (IOException e) { + PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, + "Error loading properties with: XACMLProperties.getProperties()"); + throw new ServletException(e.getMessage(), e.getCause()); + } + if (properties.getProperty(XACMLRestProperties.PDP_RESOURCE_NAME) == null) { + XACMLProperties.reloadProperties(); + try { + properties = XACMLProperties.getProperties(); + } catch (IOException e) { + PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, + "Error loading properties with: XACMLProperties.getProperties()"); + throw new ServletException(e.getMessage(), e.getCause()); + } + PolicyLogger.info("\n Properties Given : \n" + properties.toString()); + } + setPDPResourceName(properties); + 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"); + } + setDependencyNodes(dependencyGroups); + + + // CreateUpdatePolicy ResourceName + createUpdateResourceName = + properties.getProperty("createUpdatePolicy.impl.className", CREATE_UPDATE_POLICY_SERVICE); + setCreateUpdatePolicyConstructor(createUpdateResourceName); + + // Create an IntegrityMonitor + try { + logger.info("Creating IntegrityMonitor"); + im = IntegrityMonitor.getInstance(pdpResourceName, properties); + } catch (Exception e) { + PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "Failed to create IntegrityMonitor" + e); + throw new ServletException(e); + } + startThreads(baseLoggingContext, new Thread(this)); + } + + private static void startThreads(ONAPLoggingContext baseLoggingContext, Thread thread) { + environment = XACMLProperties.getProperty("ENVIRONMENT", "DEVL"); // // Kick off our thread to register with the PAP servlet. // @@ -298,1029 +298,1039 @@ public class XACMLPdpServlet extends HttpServlet implements Runnable { } private static void setDependencyNodes(String dependencyGroups) { - // dependency_groups is a semicolon-delimited list of groups, and + // 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++){ + for (int i = 0; i < dependencyNodes.length; i++) { dependencyNodes[i] = dependencyNodes[i].trim(); } } private static void setPDPResourceName(Properties properties) throws ServletException { - pdpResourceName = properties.getProperty(XACMLRestProperties.PDP_RESOURCE_NAME); - if(pdpResourceName == null){ + 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"); } } private static void initQueue(int queueSize) { - queue = new LinkedBlockingQueue<>(queueSize); + queue = new LinkedBlockingQueue<>(queueSize); } private static void setNotificationDelay() { - try{ - XACMLPdpServlet.notificationDelay = Integer.parseInt(XACMLProperties.getProperty(XACMLRestProperties.PROP_NOTIFICATION_DELAY)); - }catch(NumberFormatException e){ + try { + XACMLPdpServlet.notificationDelay = + Integer.parseInt(XACMLProperties.getProperty(XACMLRestProperties.PROP_NOTIFICATION_DELAY)); + } catch (NumberFormatException e) { logger.error("Error in notification delay format, Taking the default value.", e); } } /** - * @see Servlet#destroy() - */ - @Override - public void destroy() { - super.destroy(); - logger.info("Destroying...."); - // - // Make sure the register thread is not running - // - if (XACMLPdpServlet.registerRunnable != null) { - try { - XACMLPdpServlet.registerRunnable.terminate(); - if (XACMLPdpServlet.registerThread != null) { - XACMLPdpServlet.registerThread.interrupt(); - XACMLPdpServlet.registerThread.join(); - } - } catch (InterruptedException e) { - logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + e); - PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, ""); - XACMLPdpServlet.registerThread.interrupt(); - } - } - // - // Make sure the configure thread is not running - // - setConfigThreadTerminate(true); - try { - XACMLPdpServlet.configThread.interrupt(); - XACMLPdpServlet.configThread.join(); - } catch (InterruptedException e) { - logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + e); - PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, ""); - XACMLPdpServlet.configThread.interrupt(); - } - logger.info("Destroyed."); - } - - private static void setConfigThreadTerminate(boolean value) { - XACMLPdpServlet.configThreadTerminate = value; + * @see Servlet#destroy() + */ + @Override + public void destroy() { + super.destroy(); + logger.info("Destroying...."); + // + // Make sure the register thread is not running + // + if (XACMLPdpServlet.registerRunnable != null) { + try { + XACMLPdpServlet.registerRunnable.terminate(); + if (XACMLPdpServlet.registerThread != null) { + XACMLPdpServlet.registerThread.interrupt(); + XACMLPdpServlet.registerThread.join(); + } + } catch (InterruptedException e) { + logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + e); + PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, ""); + XACMLPdpServlet.registerThread.interrupt(); + } + } + // + // Make sure the configure thread is not running + // + setConfigThreadTerminate(true); + try { + XACMLPdpServlet.configThread.interrupt(); + XACMLPdpServlet.configThread.join(); + } catch (InterruptedException e) { + logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + e); + PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, ""); + XACMLPdpServlet.configThread.interrupt(); + } + logger.info("Destroyed."); + } + + private static void setConfigThreadTerminate(boolean value) { + XACMLPdpServlet.configThreadTerminate = value; + } + + /** + * PUT - The PAP engine sends configuration information using HTTP PUT request. + * + * One parameter is expected: + * + * config=[policy|pip|all] + * + * policy - Expect a properties file that contains updated lists of the root and referenced policies that the PDP + * should be using for PEP requests. + * + * Specifically should AT LEAST contain the following properties: xacml.rootPolicies xacml.referencedPolicies + * + * In addition, any relevant information needed by the PDP to load or retrieve the policies to store in its cache. + * + * EXAMPLE: xacml.rootPolicies=PolicyA.1, PolicyB.1 + * + * PolicyA.1.url=http://localhost:9090/PAP?id=b2d7b86d-d8f1-4adf-ba9d-b68b2a90bee1&version=1 + * PolicyB.1.url=http://localhost:9090/PAP/id=be962404-27f6-41d8-9521-5acb7f0238be&version=1 + * + * xacml.referencedPolicies=RefPolicyC.1, RefPolicyD.1 + * + * RefPolicyC.1.url=http://localhost:9090/PAP?id=foobar&version=1 + * RefPolicyD.1.url=http://localhost:9090/PAP/id=example&version=1 + * + * pip - Expect a properties file that contain PIP engine configuration properties. + * + * Specifically should AT LEAST the following property: xacml.pip.engines + * + * In addition, any relevant information needed by the PDP to load and configure the PIPs. + * + * EXAMPLE: xacml.pip.engines=foo,bar + * + * foo.classname=com.foo foo.sample=abc foo.example=xyz ...... + * + * bar.classname=com.bar ...... + * + * all - Expect ALL new configuration properties for the PDP + * + * @see HttpServlet#doPut(HttpServletRequest request, HttpServletResponse response) + */ + @Override + protected void doPut(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + ONAPLoggingContext loggingContext = ONAPLoggingUtils.getLoggingContextForRequest(request, baseLoggingContext); + loggingContext.transactionStarted(); + if ((loggingContext.getRequestID() == null) || "".equals(loggingContext.getRequestID())) { + UUID requestID = UUID.randomUUID(); + loggingContext.setRequestID(requestID.toString()); + PolicyLogger.info("requestID not provided in call to XACMLPdpSrvlet (doPut) so we generated one"); + } else { + PolicyLogger.info("requestID was provided in call to XACMLPdpSrvlet (doPut)"); + } + loggingContext.metricStarted(); + loggingContext.metricEnded(); + PolicyLogger.metrics("Metric example posted here - 1 of 2"); + loggingContext.metricStarted(); + loggingContext.metricEnded(); + PolicyLogger.metrics("Metric example posted here - 2 of 2"); + // + // Dump our request out + // + if (logger.isDebugEnabled()) { + XACMLRest.dumpRequest(request); + } + + try { + im.startTransaction(); + } catch (IntegrityMonitorException e) { + String message = e.toString(); + PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message + e); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + try { + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message); + } catch (Exception e1) { + logger.error("Exception occured while sending error in response" + e1); + } + return; + } + // + // What is being PUT? + // + String cache = request.getParameter("cache"); + // + // Should be a list of policy and pip configurations in Java properties format + // + if (cache != null && request.getContentType().equals("text/x-java-properties")) { + loggingContext.setServiceName("PDP.putConfig"); + try { + if (request.getContentLength() > Integer + .parseInt(XACMLProperties.getProperty("MAX_CONTENT_LENGTH", DEFAULT_MAX_CONTENT_LENGTH))) { + String message = "Content-Length larger than server will accept."; + logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + message); + loggingContext.transactionEnded(); + PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, message); + PolicyLogger.audit("Transaction Failed - See Error.log"); + response.sendError(HttpServletResponse.SC_BAD_REQUEST, message); + im.endTransaction(); + return; + } + logger.info("XACMLPdpServlet: calling doPutConfig to add properties to the queue"); + this.doPutConfig(cache, request, response, loggingContext); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction ended"); + + im.endTransaction(); + } catch (Exception e) { + logger.error("Exception Occured while getting Max Content lenght" + e); + } + } else { + String message = "Invalid cache: '" + cache + "' or content-type: '" + request.getContentType() + "'"; + logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + message); + PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + try { + response.sendError(HttpServletResponse.SC_BAD_REQUEST, message); + } catch (Exception e1) { + logger.error("Exception occured while sending error in response" + e1); + } + im.endTransaction(); + return; + } + } + + protected void doPutConfig(String config, HttpServletRequest request, HttpServletResponse response, + ONAPLoggingContext loggingContext) throws ServletException, IOException { + try { + // prevent multiple configuration changes from stacking up + logger.info("XACMLPdpServlet: checking remainingCapacity of Queue."); + 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; + } + logger.info("XACMLPdpServlet: offer policies to queue. No pip properties added."); + 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; + } + logger.info("XACMLPdpServlet: offer pips to queue. No policy properties added."); + 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; + } + logger.info("XACMLPdpServlet: offer policies and pips to queue."); + XACMLPdpServlet.queue.offer(new PutRequest(newPolicyProperties, newPipProperties)); + loggingContext.transactionEnded(); + auditLogger.info("Success"); + PolicyLogger.audit("Success"); + + } else { + // + // Invalid value + // + logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Invalid config value: " + config); + PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, "Invalid config value: " + config); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + response.sendError(HttpServletResponse.SC_BAD_REQUEST, + "Config must be one of 'policies', 'pips', 'all'"); + return; + } + } catch (Exception e) { + logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Failed to process new configuration.", e); + PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "Failed to process new configuration"); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + try { + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage()); + } catch (Exception e1) { + logger.error("Exception occured while sending error in response" + e1); + } + return; + } + + } + + /** + * Parameters: type=hb|config|Status + * + * 1. HeartBeat Status HeartBeat OK - All Policies are Loaded, All PIPs are Loaded LOADING_IN_PROGRESS - Currently + * loading a new policy set/pip configuration LAST_UPDATE_FAILED - Need to track the items that failed during last + * update LOAD_FAILURE - ??? Need to determine what information is sent and how 2. Configuration 3. Status return + * the StdPDPStatus object in the Response content + * + * + * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) + */ + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + ONAPLoggingContext loggingContext = ONAPLoggingUtils.getLoggingContextForRequest(request, baseLoggingContext); + loggingContext.transactionStarted(); + if ((loggingContext.getRequestID() == null) || (loggingContext.getRequestID() == "")) { + UUID requestID = UUID.randomUUID(); + loggingContext.setRequestID(requestID.toString()); + PolicyLogger.info("requestID not provided in call to XACMLPdpSrvlet (doGet) so we generated one"); + } else { + PolicyLogger.info("requestID was provided in call to XACMLPdpSrvlet (doGet)"); + } + loggingContext.metricStarted(); + loggingContext.metricEnded(); + PolicyLogger.metrics("Metric example posted here - 1 of 2"); + loggingContext.metricStarted(); + loggingContext.metricEnded(); + PolicyLogger.metrics("Metric example posted here - 2 of 2"); + + XACMLRest.dumpRequest(request); + + String pathInfo = request.getRequestURI(); + if (pathInfo != null) { + // health check from Global Site Selector (iDNS). + // DO NOT do a im.startTransaction for the test request + if (pathInfo.equals("/pdp/test")) { + loggingContext.setServiceName("iDNS:PDP.test"); + try { + im.evaluateSanity(); + // If we make it this far, all is well + String message = "GET:/pdp/test called and PDP " + pdpResourceName + " is OK"; + PolicyLogger.debug(message); + loggingContext.transactionEnded(); + PolicyLogger.audit("Success"); + response.setStatus(HttpServletResponse.SC_OK); + return; + } catch (ForwardProgressException fpe) { + // No forward progress is being made + String message = "GET:/pdp/test called and PDP " + pdpResourceName + + " is not making forward progress." + " Exception Message: " + fpe.getMessage(); + PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message + fpe); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + try { + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message); + } catch (Exception e1) { + logger.error("Exception occured while sending error in response" + e1); + } + return; + } catch (AdministrativeStateException ase) { + // Administrative State is locked + String message = "GET:/pdp/test called and PDP " + pdpResourceName + + " Administrative State is LOCKED " + " Exception Message: " + ase.getMessage(); + PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message + ase); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + try { + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message); + } catch (Exception e1) { + logger.error("Exception occured while sending error in response" + e1); + } + return; + } catch (StandbyStatusException sse) { + // Administrative State is locked + String message = "GET:/pdp/test called and PDP " + pdpResourceName + + " Standby Status is NOT PROVIDING SERVICE " + " Exception Message: " + sse.getMessage(); + PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message + sse); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + try { + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message); + } catch (Exception e1) { + logger.error("Exception occured while sending error in response" + e1); + } + return; + } catch (Exception e) { + // A subsystem is not making progress or is not responding + String eMsg = e.getMessage(); + if (eMsg == null) { + eMsg = "No Exception Message"; + } + String message = "GET:/pdp/test called and PDP " + pdpResourceName + " has had a subsystem failure." + + " Exception Message: " + eMsg; + PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message); + // Get the specific list of subsystems that failed + String failedNodeList = null; + for (String node : dependencyNodes) { + if (eMsg.contains(node)) { + if (failedNodeList == null) { + failedNodeList = node; + } else { + failedNodeList = failedNodeList.concat("," + node); + } + } + } + if (failedNodeList == null) { + failedNodeList = "UnknownSubSystem"; + } + response.addHeader("X-ONAP-SubsystemFailure", failedNodeList); + try { + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message); + } catch (Exception e1) { + logger.error("Exception occured while sending error in response" + e1); + } + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log" + e); + return; + } + } + } + + try { + im.startTransaction(); + } catch (IntegrityMonitorException e) { + String message = e.toString(); + PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log" + e); + try { + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message); + } catch (Exception e1) { + logger.error("Exception occured while sending error in response" + e1); + } + return; + } + // + // What are they requesting? + // + boolean returnHB = false; + response.setHeader("Cache-Control", "no-cache"); + String type = request.getParameter("type"); + // type might be null, so use equals on string constants + if ("config".equals(type)) { + loggingContext.setServiceName("PDP.getConfig"); + response.setContentType("text/x-java-properties"); + try { + String lists = XACMLProperties.PROP_ROOTPOLICIES + "=" + + XACMLProperties.getProperty(XACMLProperties.PROP_ROOTPOLICIES, ""); + lists = lists + "\n" + XACMLProperties.PROP_REFERENCEDPOLICIES + "=" + + XACMLProperties.getProperty(XACMLProperties.PROP_REFERENCEDPOLICIES, "") + "\n"; + try (InputStream listInputStream = new ByteArrayInputStream(lists.getBytes()); + InputStream pipInputStream = Files.newInputStream(XACMLPdpLoader.getPIPConfig()); + OutputStream os = response.getOutputStream()) { + IOUtils.copy(listInputStream, os); + IOUtils.copy(pipInputStream, os); + } + loggingContext.transactionEnded(); + auditLogger.info("Success"); + PolicyLogger.audit("Success"); + response.setStatus(HttpServletResponse.SC_OK); + } catch (Exception e) { + logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Failed to copy property file", e); + PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "Failed to copy property file"); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + try { + response.sendError(400, "Failed to copy Property file"); + } catch (Exception e1) { + logger.error("Exception occured while sending error in response" + e1); + } + } + + } else if ("hb".equals(type)) { + returnHB = true; + response.setStatus(HttpServletResponse.SC_NO_CONTENT); + + } else if ("Status".equals(type)) { + loggingContext.setServiceName("PDP.getStatus"); + // convert response object to JSON and include in the response + synchronized (pdpStatusLock) { + ObjectMapper mapper = new ObjectMapper(); + try { + mapper.writeValue(response.getOutputStream(), status); + } catch (Exception e1) { + logger.error("Exception occured while writing output stream" + e1); + } + } + response.setStatus(HttpServletResponse.SC_OK); + loggingContext.transactionEnded(); + auditLogger.info("Success"); + PolicyLogger.audit("Success"); + + } else { + logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Invalid type value: " + type); + PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, "Invalid type value: " + type); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + try { + response.sendError(HttpServletResponse.SC_BAD_REQUEST, "type not 'config' or 'hb'"); + } catch (Exception e1) { + logger.error("Exception occured while sending error in response" + e1); + } + } + if (returnHB) { + synchronized (pdpStatusLock) { + response.addHeader(XACMLRestProperties.PROP_PDP_HTTP_HEADER_HB, status.getStatus().toString()); + } + } + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Ended"); + im.endTransaction(); + } /** - * PUT - The PAP engine sends configuration information using HTTP PUT request. - * - * One parameter is expected: - * - * config=[policy|pip|all] - * - * policy - Expect a properties file that contains updated lists of the root and referenced policies that the PDP should - * be using for PEP requests. - * - * Specifically should AT LEAST contain the following properties: - * xacml.rootPolicies - * xacml.referencedPolicies - * - * In addition, any relevant information needed by the PDP to load or retrieve the policies to store in its cache. - * - * EXAMPLE: - * xacml.rootPolicies=PolicyA.1, PolicyB.1 - * - * PolicyA.1.url=http://localhost:9090/PAP?id=b2d7b86d-d8f1-4adf-ba9d-b68b2a90bee1&version=1 - * PolicyB.1.url=http://localhost:9090/PAP/id=be962404-27f6-41d8-9521-5acb7f0238be&version=1 - * - * xacml.referencedPolicies=RefPolicyC.1, RefPolicyD.1 - * - * RefPolicyC.1.url=http://localhost:9090/PAP?id=foobar&version=1 - * RefPolicyD.1.url=http://localhost:9090/PAP/id=example&version=1 - * - * pip - Expect a properties file that contain PIP engine configuration properties. - * - * Specifically should AT LEAST the following property: - * xacml.pip.engines - * - * In addition, any relevant information needed by the PDP to load and configure the PIPs. - * - * EXAMPLE: - * xacml.pip.engines=foo,bar - * - * foo.classname=com.foo - * foo.sample=abc - * foo.example=xyz - * ...... - * - * bar.classname=com.bar - * ...... - * - * all - Expect ALL new configuration properties for the PDP - * - * @see HttpServlet#doPut(HttpServletRequest request, HttpServletResponse response) - */ - @Override - protected void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - ONAPLoggingContext loggingContext = ONAPLoggingUtils.getLoggingContextForRequest(request, baseLoggingContext); - loggingContext.transactionStarted(); - if ((loggingContext.getRequestID() == null) || "".equals(loggingContext.getRequestID())){ - UUID requestID = UUID.randomUUID(); - loggingContext.setRequestID(requestID.toString()); - PolicyLogger.info("requestID not provided in call to XACMLPdpSrvlet (doPut) so we generated one"); - } else { - PolicyLogger.info("requestID was provided in call to XACMLPdpSrvlet (doPut)"); - } - loggingContext.metricStarted(); - loggingContext.metricEnded(); - PolicyLogger.metrics("Metric example posted here - 1 of 2"); - loggingContext.metricStarted(); - loggingContext.metricEnded(); - PolicyLogger.metrics("Metric example posted here - 2 of 2"); - // - // Dump our request out - // - if (logger.isDebugEnabled()) { - XACMLRest.dumpRequest(request); - } - - try { - im.startTransaction(); - } - catch (IntegrityMonitorException e) { - String message = e.toString(); - PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message + e); - loggingContext.transactionEnded(); - PolicyLogger.audit("Transaction Failed - See Error.log"); - try{ - response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message); - }catch(Exception e1){ - logger.error("Exception occured while sending error in response" +e1); - } - return; - } - // - // What is being PUT? - // - String cache = request.getParameter("cache"); - // - // Should be a list of policy and pip configurations in Java properties format - // - if (cache != null && request.getContentType().equals("text/x-java-properties")) { - loggingContext.setServiceName("PDP.putConfig"); - try{ - if (request.getContentLength() > Integer.parseInt(XACMLProperties.getProperty("MAX_CONTENT_LENGTH", DEFAULT_MAX_CONTENT_LENGTH))) { - String message = "Content-Length larger than server will accept."; - logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + message); - loggingContext.transactionEnded(); - PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, message); - PolicyLogger.audit("Transaction Failed - See Error.log"); - response.sendError(HttpServletResponse.SC_BAD_REQUEST, message); - im.endTransaction(); - return; - } - logger.info("XACMLPdpServlet: calling doPutConfig to add properties to the queue"); - this.doPutConfig(cache, request, response, loggingContext); - loggingContext.transactionEnded(); - PolicyLogger.audit("Transaction ended"); - - im.endTransaction(); - }catch(Exception e){ - logger.error("Exception Occured while getting Max Content lenght"+e); - } - } else { - String message = "Invalid cache: '" + cache + "' or content-type: '" + request.getContentType() + "'"; - logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + message); - PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message); - loggingContext.transactionEnded(); - PolicyLogger.audit("Transaction Failed - See Error.log"); - try{ - response.sendError(HttpServletResponse.SC_BAD_REQUEST, message); - }catch(Exception e1){ - logger.error("Exception occured while sending error in response" +e1); - } - im.endTransaction(); - return; - } - } - - protected void doPutConfig(String config, HttpServletRequest request, HttpServletResponse response, ONAPLoggingContext loggingContext) throws ServletException, IOException { - try { - // prevent multiple configuration changes from stacking up - logger.info("XACMLPdpServlet: checking remainingCapacity of Queue."); - 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; - } - logger.info("XACMLPdpServlet: offer policies to queue. No pip properties added."); - 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; - } - logger.info("XACMLPdpServlet: offer pips to queue. No policy properties added."); - 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; - } - logger.info("XACMLPdpServlet: offer policies and pips to queue."); - XACMLPdpServlet.queue.offer(new PutRequest(newPolicyProperties, newPipProperties)); - loggingContext.transactionEnded(); - auditLogger.info("Success"); - PolicyLogger.audit("Success"); - - } else { - // - // Invalid value - // - logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Invalid config value: " + config); - PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, "Invalid config value: " + config); - loggingContext.transactionEnded(); - PolicyLogger.audit("Transaction Failed - See Error.log"); - response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Config must be one of 'policies', 'pips', 'all'"); - return; - } - } catch (Exception e) { - logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Failed to process new configuration.", e); - PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "Failed to process new configuration"); - loggingContext.transactionEnded(); - PolicyLogger.audit("Transaction Failed - See Error.log"); - try{ - response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage()); - }catch(Exception e1){ - logger.error("Exception occured while sending error in response" +e1); - } - return; - } - - } - - /** - * Parameters: type=hb|config|Status - * - * 1. HeartBeat Status - * HeartBeat - * OK - All Policies are Loaded, All PIPs are Loaded - * LOADING_IN_PROGRESS - Currently loading a new policy set/pip configuration - * LAST_UPDATE_FAILED - Need to track the items that failed during last update - * LOAD_FAILURE - ??? Need to determine what information is sent and how - * 2. Configuration - * 3. Status - * return the StdPDPStatus object in the Response content - * - * - * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) - */ - @Override - protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - ONAPLoggingContext loggingContext = ONAPLoggingUtils.getLoggingContextForRequest(request, baseLoggingContext); - loggingContext.transactionStarted(); - if ((loggingContext.getRequestID() == null) || (loggingContext.getRequestID() == "")){ - UUID requestID = UUID.randomUUID(); - loggingContext.setRequestID(requestID.toString()); - PolicyLogger.info("requestID not provided in call to XACMLPdpSrvlet (doGet) so we generated one"); - } else { - PolicyLogger.info("requestID was provided in call to XACMLPdpSrvlet (doGet)"); - } - loggingContext.metricStarted(); - loggingContext.metricEnded(); - PolicyLogger.metrics("Metric example posted here - 1 of 2"); - loggingContext.metricStarted(); - loggingContext.metricEnded(); - PolicyLogger.metrics("Metric example posted here - 2 of 2"); - - XACMLRest.dumpRequest(request); - - String pathInfo = request.getRequestURI(); - if (pathInfo != null){ - // health check from Global Site Selector (iDNS). - // DO NOT do a im.startTransaction for the test request - if (pathInfo.equals("/pdp/test")) { - loggingContext.setServiceName("iDNS:PDP.test"); - try { - im.evaluateSanity(); - //If we make it this far, all is well - String message = "GET:/pdp/test called and PDP " + pdpResourceName + " is OK"; - PolicyLogger.debug(message); - loggingContext.transactionEnded(); - PolicyLogger.audit("Success"); - response.setStatus(HttpServletResponse.SC_OK); - return; - } catch (ForwardProgressException fpe){ - //No forward progress is being made - String message = "GET:/pdp/test called and PDP " + pdpResourceName + " is not making forward progress." - + " Exception Message: " + fpe.getMessage(); - PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message + fpe); - loggingContext.transactionEnded(); - PolicyLogger.audit("Transaction Failed - See Error.log"); - try{ - response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message); - }catch(Exception e1){ - logger.error("Exception occured while sending error in response" +e1); - } - return; - }catch (AdministrativeStateException ase){ - //Administrative State is locked - String message = "GET:/pdp/test called and PDP " + pdpResourceName + " Administrative State is LOCKED " - + " Exception Message: " + ase.getMessage(); - PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message + ase); - loggingContext.transactionEnded(); - PolicyLogger.audit("Transaction Failed - See Error.log"); - try{ - response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message); - }catch(Exception e1){ - logger.error("Exception occured while sending error in response" +e1); - } - return; - }catch (StandbyStatusException sse){ - //Administrative State is locked - String message = "GET:/pdp/test called and PDP " + pdpResourceName + " Standby Status is NOT PROVIDING SERVICE " - + " Exception Message: " + sse.getMessage(); - PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message + sse); - loggingContext.transactionEnded(); - PolicyLogger.audit("Transaction Failed - See Error.log"); - try{ - response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message); - }catch(Exception e1){ - logger.error("Exception occured while sending error in response" +e1); - } - return; - } catch (Exception e) { - //A subsystem is not making progress or is not responding - String eMsg = e.getMessage(); - if(eMsg == null){ - eMsg = "No Exception Message"; - } - String message = "GET:/pdp/test called and PDP " + pdpResourceName + " has had a subsystem failure." - + " Exception Message: " + eMsg; - PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message ); - //Get the specific list of subsystems that failed - String failedNodeList = null; - for(String node : dependencyNodes){ - if(eMsg.contains(node)){ - if(failedNodeList == null){ - failedNodeList = node; - }else{ - failedNodeList = failedNodeList.concat(","+node); - } - } - } - if(failedNodeList == null){ - failedNodeList = "UnknownSubSystem"; - } - response.addHeader("X-ONAP-SubsystemFailure", failedNodeList); - try{ - response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message); - }catch(Exception e1){ - logger.error("Exception occured while sending error in response" +e1); - } - loggingContext.transactionEnded(); - PolicyLogger.audit("Transaction Failed - See Error.log" + e); - return; - } - } - } - - try { - im.startTransaction(); - } - catch (IntegrityMonitorException e) { - String message = e.toString(); - PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message); - loggingContext.transactionEnded(); - PolicyLogger.audit("Transaction Failed - See Error.log" +e); - try{ - response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message); - }catch(Exception e1){ - logger.error("Exception occured while sending error in response" +e1); - } - return; - } - // - // What are they requesting? - // - boolean returnHB = false; - response.setHeader("Cache-Control", "no-cache"); - String type = request.getParameter("type"); - // type might be null, so use equals on string constants - if ("config".equals(type)) { - loggingContext.setServiceName("PDP.getConfig"); - response.setContentType("text/x-java-properties"); - try { - String lists = XACMLProperties.PROP_ROOTPOLICIES + "=" + XACMLProperties.getProperty(XACMLProperties.PROP_ROOTPOLICIES, ""); - lists = lists + "\n" + XACMLProperties.PROP_REFERENCEDPOLICIES + "=" + XACMLProperties.getProperty(XACMLProperties.PROP_REFERENCEDPOLICIES, "") + "\n"; - try (InputStream listInputStream = new ByteArrayInputStream(lists.getBytes()); - InputStream pipInputStream = Files.newInputStream(XACMLPdpLoader.getPIPConfig()); - OutputStream os = response.getOutputStream()) { - IOUtils.copy(listInputStream, os); - IOUtils.copy(pipInputStream, os); - } - loggingContext.transactionEnded(); - auditLogger.info("Success"); - PolicyLogger.audit("Success"); - response.setStatus(HttpServletResponse.SC_OK); - } catch (Exception e) { - logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Failed to copy property file", e); - PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "Failed to copy property file"); - loggingContext.transactionEnded(); - PolicyLogger.audit("Transaction Failed - See Error.log"); - try{ - response.sendError(400, "Failed to copy Property file"); - }catch(Exception e1){ - logger.error("Exception occured while sending error in response" +e1); - } - } - - } else if ("hb".equals(type)) { - returnHB = true; - response.setStatus(HttpServletResponse.SC_NO_CONTENT); - - } else if ("Status".equals(type)) { - loggingContext.setServiceName("PDP.getStatus"); - // convert response object to JSON and include in the response - synchronized(pdpStatusLock) { - ObjectMapper mapper = new ObjectMapper(); - try{ - mapper.writeValue(response.getOutputStream(), status); - }catch(Exception e1){ - logger.error("Exception occured while writing output stream" +e1); - } - } - response.setStatus(HttpServletResponse.SC_OK); - loggingContext.transactionEnded(); - auditLogger.info("Success"); - PolicyLogger.audit("Success"); - - } else { - logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Invalid type value: " + type); - PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, "Invalid type value: " + type); - loggingContext.transactionEnded(); - PolicyLogger.audit("Transaction Failed - See Error.log"); - try{ - response.sendError(HttpServletResponse.SC_BAD_REQUEST, "type not 'config' or 'hb'"); - }catch(Exception e1){ - logger.error("Exception occured while sending error in response" +e1); - } - } - if (returnHB) { - synchronized(pdpStatusLock) { - response.addHeader(XACMLRestProperties.PROP_PDP_HTTP_HEADER_HB, status.getStatus().toString()); - } - } - loggingContext.transactionEnded(); - PolicyLogger.audit("Transaction Ended"); - im.endTransaction(); - - } - - /** - * POST - We expect XACML requests to be posted by PEP applications. They can be in the form of XML or JSON according - * to the XACML 3.0 Specifications for both. - * - * - * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) - */ - @Override - protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - - ONAPLoggingContext loggingContext = ONAPLoggingUtils.getLoggingContextForRequest(request, baseLoggingContext); - loggingContext.transactionStarted(); - loggingContext.setServiceName("PDP.decide"); - if ((loggingContext.getRequestID() == null) || ("".equals(loggingContext.getRequestID()))){ - UUID requestID = UUID.randomUUID(); - loggingContext.setRequestID(requestID.toString()); - PolicyLogger.info("requestID not provided in call to XACMLPdpSrvlet (doPost) so we generated one"); - } else { - PolicyLogger.info("requestID was provided in call to XACMLPdpSrvlet (doPost)"); - } - loggingContext.metricStarted(); - loggingContext.metricEnded(); - PolicyLogger.metrics("Metric example posted here - 1 of 2"); - loggingContext.metricStarted(); - loggingContext.metricEnded(); - PolicyLogger.metrics("Metric example posted here - 2 of 2"); - monitor.pdpEvaluationAttempts(); - - try { - im.startTransaction(); - } - catch (IntegrityMonitorException e) { - String message = e.toString(); - PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message + e); - loggingContext.transactionEnded(); - PolicyLogger.audit("Transaction Failed - See Error.log"); - try{ - response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message); - }catch(Exception e1){ - logger.error("Exception occured while sending error in response" +e1); - } - return; - } - // - // no point in doing any work if we know from the get-go that we cannot do anything with the request - // - if (status.getLoadedRootPolicies().isEmpty()) { - logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Request from PEP at " + request.getRequestURI() + " for service when PDP has No Root Policies loaded"); - PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, "Request from PEP at " + request.getRequestURI() + " for service when PDP has No Root Policies loaded"); - loggingContext.transactionEnded(); - PolicyLogger.audit("Transaction Failed - See Error.log"); - try{ - response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE); - }catch(Exception e1){ - logger.error("Exception occured while sending error in response" +e1); - } - im.endTransaction(); - return; - } - - XACMLRest.dumpRequest(request); - // - // Set our no-cache header - // - response.setHeader("Cache-Control", "no-cache"); - // - // They must send a Content-Type - // - if (request.getContentType() == null) { - logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Must specify a Content-Type"); - PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, "Must specify a Content-Type"); - loggingContext.transactionEnded(); - PolicyLogger.audit("Transaction Failed - See Error.log"); - try{ - response.sendError(HttpServletResponse.SC_BAD_REQUEST, "no content-type given"); - }catch(Exception e1){ - logger.error("Exception occured while sending error in response" +e1); - } - im.endTransaction(); - return; - } - // - // Limit the Content-Length to something reasonable - // - try{ - if (request.getContentLength() > Integer.parseInt(XACMLProperties.getProperty("MAX_CONTENT_LENGTH", "32767"))) { - String message = "Content-Length larger than server will accept."; - logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + message); - PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, message); - loggingContext.transactionEnded(); - PolicyLogger.audit("Transaction Failed - See Error.log"); - response.sendError(HttpServletResponse.SC_BAD_REQUEST, message); - im.endTransaction(); - return; - } - }catch(Exception e){ - logger.error("Exception occured while getting max content length"+e); - } - - if (request.getContentLength() <= 0) { - String message = "Content-Length is negative"; - logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + message); - PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, message); - loggingContext.transactionEnded(); - PolicyLogger.audit("Transaction Failed - See Error.log"); - try{ - response.sendError(HttpServletResponse.SC_BAD_REQUEST, message); - }catch(Exception e1){ - logger.error("Exception occured while sending error in response" +e1); - } - im.endTransaction(); - return; - } - ContentType contentType = null; - try { - contentType = ContentType.parse(request.getContentType()); - } - catch (Exception e) { - String message = "Parsing Content-Type: " + request.getContentType() + ", error=" + e.getMessage(); - logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + message, e); - loggingContext.transactionEnded(); - PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, message); - PolicyLogger.audit("Transaction Failed - See Error.log"); - try{ - response.sendError(HttpServletResponse.SC_BAD_REQUEST, message); - }catch(Exception e1){ - logger.error("Exception occured while sending error in response" +e1); - } - im.endTransaction(); - return; - } - // - // What exactly did they send us? - // - String incomingRequestString = null; - Request pdpRequest = null; - if (contentType.getMimeType().equalsIgnoreCase(ContentType.APPLICATION_JSON.getMimeType()) || - contentType.getMimeType().equalsIgnoreCase(ContentType.APPLICATION_XML.getMimeType()) || - contentType.getMimeType().equalsIgnoreCase("application/xacml+xml") ) { - // - // Read in the string - // - StringBuilder buffer = new StringBuilder(); - BufferedReader reader = null; - try{ - reader = new BufferedReader(new InputStreamReader(request.getInputStream())); - }catch(IOException e){ - logger.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Error during reading input stream",e); - return; - } - String line; - try{ - while((line = reader.readLine()) != null){ - buffer.append(line); - } - }catch(Exception e){ - logger.error("Exception Occured while reading line"+e); - } - - incomingRequestString = buffer.toString(); - logger.info(incomingRequestString); - // - // Parse into a request - // - try { - if (contentType.getMimeType().equalsIgnoreCase(ContentType.APPLICATION_JSON.getMimeType())) { - pdpRequest = JSONRequest.load(incomingRequestString); - } else if ( contentType.getMimeType().equalsIgnoreCase(ContentType.APPLICATION_XML.getMimeType()) || - contentType.getMimeType().equalsIgnoreCase("application/xacml+xml")) { - pdpRequest = DOMRequest.load(incomingRequestString); - } - } - catch(Exception e) { - logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Could not parse request", e); - PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, "Could not parse request"); - loggingContext.transactionEnded(); - PolicyLogger.audit("Transaction Failed - See Error.log"); - try{ - response.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage()); - }catch(Exception e1){ - logger.error("Exception occured while sending error in response" +e1); - } - im.endTransaction(); - return; - } - } else { - String message = "unsupported content type" + request.getContentType(); - logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + message); - PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, message); - loggingContext.transactionEnded(); - PolicyLogger.audit("Transaction Failed - See Error.log"); - try{ - response.sendError(HttpServletResponse.SC_BAD_REQUEST, message); - }catch(Exception e1){ - logger.error("Exception occured while sending error in response" +e1); - } - im.endTransaction(); - return; - } - // - // Did we successfully get and parse a request? - // - if (pdpRequest == null || pdpRequest.getRequestAttributes() == null || pdpRequest.getRequestAttributes().size() <= 0) { - String message = "Zero Attributes found in the request"; - logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + message); - PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, message); - loggingContext.transactionEnded(); - PolicyLogger.audit("Transaction Failed - See Error.log"); - try{ - response.sendError(HttpServletResponse.SC_BAD_REQUEST, message); - }catch(Exception e1){ - logger.error("Exception occured while sending error in response" +e1); - } - im.endTransaction(); - return; - } - // - // Run it - // - try { - // - // Authenticating the Request here. - // - if(!authorizeRequest(request)){ - String message = "PEP not Authorized for making this Request!! \n Contact Administrator for this Scope. "; - logger.error(XACMLErrorConstants.ERROR_PERMISSIONS + message ); - PolicyLogger.error(MessageCodes.ERROR_PERMISSIONS, message); - loggingContext.transactionEnded(); - PolicyLogger.audit("Transaction Failed - See Error.log"); - response.sendError(HttpServletResponse.SC_FORBIDDEN, message); - im.endTransaction(); - return; - } - // - // Get the pointer to the PDP Engine - // - PDPEngine myEngine = null; - synchronized(pdpEngineLock) { - myEngine = XACMLPdpServlet.pdpEngine; - } - if (myEngine == null) { - String message = "No engine loaded."; - logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + message); - PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message); - loggingContext.transactionEnded(); - PolicyLogger.audit("Transaction Failed - See Error.log"); - response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message); - im.endTransaction(); - return; - } - // - // Send the request and save the response - // - long lTimeStart; - long lTimeEnd; - Response pdpResponse = null; - - synchronized(pdpEngineLock) { - myEngine = XACMLPdpServlet.pdpEngine; - try { - PolicyList.clearPolicyList(); - lTimeStart = System.currentTimeMillis(); - pdpResponse = myEngine.decide(pdpRequest); - lTimeEnd = System.currentTimeMillis(); - } catch (PDPException e) { - String message = "Exception during decide: " + e.getMessage(); - logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + message +e); - PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message); - loggingContext.transactionEnded(); - PolicyLogger.audit("Transaction Failed - See Error.log"); - try{ - response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message); - }catch(Exception e1){ - logger.error("Exception occured while sending error in response" +e1); - } - im.endTransaction(); - return; - } - } - monitor.computeLatency(lTimeEnd - lTimeStart); - requestLogger.info(lTimeStart + "=" + incomingRequestString); - for(String policy : PolicyList.getpolicyList()){ - monitor.policyCountAdd(policy, 1); - } - - - logger.info("PolicyID triggered in Request: " + PolicyList.getpolicyList()); - - //need to go through the list and find out if the value is unique and then add it other wise - // monitor.policyCountAdd(PolicyList.getpolicyList(), 1); - - if (logger.isDebugEnabled()) { - logger.debug("Request time: " + (lTimeEnd - lTimeStart) + "ms"); - } - // - // Convert Response to appropriate Content-Type - // - if (pdpResponse == null) { - requestLogger.info(lTimeStart + "=" + "{}"); - try{ - throw new PDPException("Failed to get response from PDP engine."); - }catch(Exception e1){ - logger.error("Exception occured while throwing Exception" +e1); - } - } - // - // Set our content-type - // - response.setContentType(contentType.getMimeType()); - // - // Convert the PDP response object to a String to - // return to our caller as well as dump to our loggers. - // - String outgoingResponseString = ""; - try{ - if (contentType.getMimeType().equalsIgnoreCase(ContentType.APPLICATION_JSON.getMimeType())) { - // - // Get it as a String. This is not very efficient but we need to log our - // results for auditing. - // - outgoingResponseString = JSONResponse.toString(pdpResponse, logger.isDebugEnabled()); - if (logger.isDebugEnabled()) { - logger.debug(outgoingResponseString); - // - // Get rid of whitespace - // - outgoingResponseString = JSONResponse.toString(pdpResponse, false); - } - } else if ( contentType.getMimeType().equalsIgnoreCase(ContentType.APPLICATION_XML.getMimeType()) || - contentType.getMimeType().equalsIgnoreCase("application/xacml+xml")) { - // - // Get it as a String. This is not very efficient but we need to log our - // results for auditing. - // - outgoingResponseString = DOMResponse.toString(pdpResponse, logger.isDebugEnabled()); - if (logger.isDebugEnabled()) { - logger.debug(outgoingResponseString); - // - // Get rid of whitespace - // - outgoingResponseString = DOMResponse.toString(pdpResponse, false); - } - } - // adding the jmx values for NA, Permit and Deny - // - if (outgoingResponseString.contains("NotApplicable") || outgoingResponseString.contains("Decision not a Permit")){ - monitor.pdpEvaluationNA(); - } - - if (outgoingResponseString.contains("Permit") && !outgoingResponseString.contains("Decision not a Permit")){ - monitor.pdpEvaluationPermit(); - } - - if (outgoingResponseString.contains("Deny")){ - monitor.pdpEvaluationDeny(); - } - // - // lTimeStart is used as an ID within the requestLogger to match up - // request's with responses. - // - requestLogger.info(lTimeStart + "=" + outgoingResponseString); - response.getWriter().print(outgoingResponseString); - }catch(Exception e){ - logger.error("Exception Occured"+e ); - } - } - catch (Exception e) { - String message = "Exception executing request: " + e; - logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + message, e); - PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, message); - loggingContext.transactionEnded(); - PolicyLogger.audit("Transaction Failed - See Error.log"); - try{ - response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message); - }catch(Exception e1){ - logger.error("Exception occured while sending error in response" +e1); - } - return; - } - - monitor.pdpEvaluationSuccess(); - response.setStatus(HttpServletResponse.SC_OK); - - loggingContext.transactionEnded(); - auditLogger.info("Success"); - PolicyLogger.audit("Success"); - - } - - /* - * Added for Authorizing the PEP Requests for Environment check. - */ - private boolean authorizeRequest(HttpServletRequest request) { - // Get the client Credentials from the Request header. - HttpServletRequest httpServletRequest = request; - String clientCredentials = httpServletRequest.getHeader(ENVIORNMENT_HEADER); - if(clientCredentials!=null && clientCredentials.equalsIgnoreCase(environment)){ - return true; - }else{ - return false; - } - } - - @Override - public void run() { - // - // Keep running until we are told to terminate - // - try { - // variable not used, but constructor has needed side-effects so don't remove: - while (! XACMLPdpServlet.configThreadTerminate) { - logger.info("XACMLPdpServlet: Taking requests from the queue"); - PutRequest request = XACMLPdpServlet.queue.take(); - logger.info("XACMLPdpServlet: Taking requests from the queue COMPLETED"); - StdPDPStatus newStatus = new StdPDPStatus(); - - PDPEngine newEngine = null; - synchronized(pdpStatusLock) { - XACMLPdpServlet.status.setStatus(Status.UPDATING_CONFIGURATION); - - logger.info("created new PDPEngine"); - newEngine = XACMLPdpLoader.loadEngine(newStatus, request.policyProperties, request.pipConfigProperties); - } - if (newEngine != null) { - logger.info("XACMLPdpServlet: newEngine created, assigning newEngine to the pdpEngine."); - synchronized(XACMLPdpServlet.pdpEngineLock) { - XACMLPdpServlet.pdpEngine = newEngine; - try { - logger.info("Saving configuration."); - if (request.policyProperties != null) { - logger.info("Saving configuration: Policy Properties: " + request.policyProperties); - try (OutputStream os = Files.newOutputStream(XACMLPdpLoader.getPDPPolicyCache())) { - request.policyProperties.store(os, ""); - } - } - if (request.pipConfigProperties != null) { - logger.info("Saving configuration: PIP Properties: " + request.pipConfigProperties); - try (OutputStream os = Files.newOutputStream(XACMLPdpLoader.getPIPConfig())) { - request.pipConfigProperties.store(os, ""); - } - } - newStatus.setStatus(Status.UP_TO_DATE); - } catch (Exception e) { - logger.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Failed to store new properties."+e); - PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, "Failed to store new properties"); - newStatus.setStatus(Status.LOAD_ERRORS); - newStatus.addLoadWarning("Unable to save configuration: " + e.getMessage()); - } - } - } else { - newStatus.setStatus(Status.LAST_UPDATE_FAILED); - } - synchronized(pdpStatusLock) { - XACMLPdpServlet.status.set(newStatus); - } - logger.info("New PDP Servlet Status: " + newStatus.getStatus()); - if (Status.UP_TO_DATE.equals(newStatus.getStatus())) { - // Notification will be Sent Here. - XACMLPdpLoader.sendNotification(); - } - } - } catch (InterruptedException e) { - logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "interrupted"+e); - PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, "interrupted"); - Thread.currentThread().interrupt(); - } - } - - public static PDPEngine getPDPEngine(){ - PDPEngine myEngine = null; - synchronized(pdpEngineLock) { - myEngine = XACMLPdpServlet.pdpEngine; - } - return myEngine; - } - - public static Constructor getCreateUpdatePolicyConstructor(){ - return createUpdatePolicyConstructor; - } - - private static void setCreateUpdatePolicyConstructor(String createUpdateResourceName) throws ServletException{ - try{ - Class createUpdateclass = Class.forName(createUpdateResourceName); - createUpdatePolicyConstructor = createUpdateclass.getConstructor(PolicyParameters.class, String.class, boolean.class); - }catch(Exception e){ - PolicyLogger.error(MessageCodes.MISS_PROPERTY_ERROR, "createUpdatePolicy.impl.className", "xacml.pdp.init" +e); - throw new ServletException("Could not find the Class name : " +createUpdateResourceName + "\n" +e.getMessage()); - } - } + * POST - We expect XACML requests to be posted by PEP applications. They can be in the form of XML or JSON + * according to the XACML 3.0 Specifications for both. + * + * + * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) + */ + @Override + protected void doPost(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + + ONAPLoggingContext loggingContext = ONAPLoggingUtils.getLoggingContextForRequest(request, baseLoggingContext); + loggingContext.transactionStarted(); + loggingContext.setServiceName("PDP.decide"); + if ((loggingContext.getRequestID() == null) || ("".equals(loggingContext.getRequestID()))) { + UUID requestID = UUID.randomUUID(); + loggingContext.setRequestID(requestID.toString()); + PolicyLogger.info("requestID not provided in call to XACMLPdpSrvlet (doPost) so we generated one"); + } else { + PolicyLogger.info("requestID was provided in call to XACMLPdpSrvlet (doPost)"); + } + loggingContext.metricStarted(); + loggingContext.metricEnded(); + PolicyLogger.metrics("Metric example posted here - 1 of 2"); + loggingContext.metricStarted(); + loggingContext.metricEnded(); + PolicyLogger.metrics("Metric example posted here - 2 of 2"); + monitor.pdpEvaluationAttempts(); + + try { + im.startTransaction(); + } catch (IntegrityMonitorException e) { + String message = e.toString(); + PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message + e); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + try { + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message); + } catch (Exception e1) { + logger.error("Exception occured while sending error in response" + e1); + } + return; + } + // + // no point in doing any work if we know from the get-go that we cannot do anything with the request + // + if (status.getLoadedRootPolicies().isEmpty()) { + logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Request from PEP at " + request.getRequestURI() + + " for service when PDP has No Root Policies loaded"); + PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, "Request from PEP at " + request.getRequestURI() + + " for service when PDP has No Root Policies loaded"); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + try { + response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE); + } catch (Exception e1) { + logger.error("Exception occured while sending error in response" + e1); + } + im.endTransaction(); + return; + } + + XACMLRest.dumpRequest(request); + // + // Set our no-cache header + // + response.setHeader("Cache-Control", "no-cache"); + // + // They must send a Content-Type + // + if (request.getContentType() == null) { + logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Must specify a Content-Type"); + PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, "Must specify a Content-Type"); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + try { + response.sendError(HttpServletResponse.SC_BAD_REQUEST, "no content-type given"); + } catch (Exception e1) { + logger.error("Exception occured while sending error in response" + e1); + } + im.endTransaction(); + return; + } + // + // Limit the Content-Length to something reasonable + // + try { + if (request.getContentLength() > Integer + .parseInt(XACMLProperties.getProperty("MAX_CONTENT_LENGTH", "32767"))) { + String message = "Content-Length larger than server will accept."; + logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + message); + PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, message); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + response.sendError(HttpServletResponse.SC_BAD_REQUEST, message); + im.endTransaction(); + return; + } + } catch (Exception e) { + logger.error("Exception occured while getting max content length" + e); + } + + if (request.getContentLength() <= 0) { + String message = "Content-Length is negative"; + logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + message); + PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, message); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + try { + response.sendError(HttpServletResponse.SC_BAD_REQUEST, message); + } catch (Exception e1) { + logger.error("Exception occured while sending error in response" + e1); + } + im.endTransaction(); + return; + } + ContentType contentType = null; + try { + contentType = ContentType.parse(request.getContentType()); + } catch (Exception e) { + String message = "Parsing Content-Type: " + request.getContentType() + ", error=" + e.getMessage(); + logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + message, e); + loggingContext.transactionEnded(); + PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, message); + PolicyLogger.audit("Transaction Failed - See Error.log"); + try { + response.sendError(HttpServletResponse.SC_BAD_REQUEST, message); + } catch (Exception e1) { + logger.error("Exception occured while sending error in response" + e1); + } + im.endTransaction(); + return; + } + // + // What exactly did they send us? + // + String incomingRequestString = null; + Request pdpRequest = null; + if (contentType.getMimeType().equalsIgnoreCase(ContentType.APPLICATION_JSON.getMimeType()) + || contentType.getMimeType().equalsIgnoreCase(ContentType.APPLICATION_XML.getMimeType()) + || contentType.getMimeType().equalsIgnoreCase("application/xacml+xml")) { + // + // Read in the string + // + StringBuilder buffer = new StringBuilder(); + BufferedReader reader = null; + try { + reader = new BufferedReader(new InputStreamReader(request.getInputStream())); + } catch (IOException e) { + logger.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Error during reading input stream", e); + return; + } + String line; + try { + while ((line = reader.readLine()) != null) { + buffer.append(line); + } + } catch (Exception e) { + logger.error("Exception Occured while reading line" + e); + } + + incomingRequestString = buffer.toString(); + logger.info(incomingRequestString); + // + // Parse into a request + // + try { + if (contentType.getMimeType().equalsIgnoreCase(ContentType.APPLICATION_JSON.getMimeType())) { + pdpRequest = JSONRequest.load(incomingRequestString); + } else if (contentType.getMimeType().equalsIgnoreCase(ContentType.APPLICATION_XML.getMimeType()) + || contentType.getMimeType().equalsIgnoreCase("application/xacml+xml")) { + pdpRequest = DOMRequest.load(incomingRequestString); + } + } catch (Exception e) { + logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Could not parse request", e); + PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, "Could not parse request"); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + try { + response.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage()); + } catch (Exception e1) { + logger.error("Exception occured while sending error in response" + e1); + } + im.endTransaction(); + return; + } + } else { + String message = "unsupported content type" + request.getContentType(); + logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + message); + PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, message); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + try { + response.sendError(HttpServletResponse.SC_BAD_REQUEST, message); + } catch (Exception e1) { + logger.error("Exception occured while sending error in response" + e1); + } + im.endTransaction(); + return; + } + // + // Did we successfully get and parse a request? + // + if (pdpRequest == null || pdpRequest.getRequestAttributes() == null + || pdpRequest.getRequestAttributes().size() <= 0) { + String message = "Zero Attributes found in the request"; + logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + message); + PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, message); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + try { + response.sendError(HttpServletResponse.SC_BAD_REQUEST, message); + } catch (Exception e1) { + logger.error("Exception occured while sending error in response" + e1); + } + im.endTransaction(); + return; + } + // + // Run it + // + try { + // + // Authenticating the Request here. + // + if (!authorizeRequest(request)) { + String message = + "PEP not Authorized for making this Request!! \n Contact Administrator for this Scope. "; + logger.error(XACMLErrorConstants.ERROR_PERMISSIONS + message); + PolicyLogger.error(MessageCodes.ERROR_PERMISSIONS, message); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + response.sendError(HttpServletResponse.SC_FORBIDDEN, message); + im.endTransaction(); + return; + } + // + // Get the pointer to the PDP Engine + // + PDPEngine myEngine = null; + synchronized (pdpEngineLock) { + myEngine = XACMLPdpServlet.pdpEngine; + } + if (myEngine == null) { + String message = "No engine loaded."; + logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + message); + PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message); + im.endTransaction(); + return; + } + // + // Send the request and save the response + // + long lTimeStart; + long lTimeEnd; + Response pdpResponse = null; + + synchronized (pdpEngineLock) { + myEngine = XACMLPdpServlet.pdpEngine; + try { + PolicyList.clearPolicyList(); + lTimeStart = System.currentTimeMillis(); + pdpResponse = myEngine.decide(pdpRequest); + lTimeEnd = System.currentTimeMillis(); + } catch (PDPException e) { + String message = "Exception during decide: " + e.getMessage(); + logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + message + e); + PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + try { + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message); + } catch (Exception e1) { + logger.error("Exception occured while sending error in response" + e1); + } + im.endTransaction(); + return; + } + } + monitor.computeLatency(lTimeEnd - lTimeStart); + requestLogger.info(lTimeStart + "=" + incomingRequestString); + for (String policy : PolicyList.getpolicyList()) { + monitor.policyCountAdd(policy, 1); + } + + + logger.info("PolicyID triggered in Request: " + PolicyList.getpolicyList()); + + // need to go through the list and find out if the value is unique and then add it other wise + // monitor.policyCountAdd(PolicyList.getpolicyList(), 1); + + if (logger.isDebugEnabled()) { + logger.debug("Request time: " + (lTimeEnd - lTimeStart) + "ms"); + } + // + // Convert Response to appropriate Content-Type + // + if (pdpResponse == null) { + requestLogger.info(lTimeStart + "=" + "{}"); + try { + throw new PDPException("Failed to get response from PDP engine."); + } catch (Exception e1) { + logger.error("Exception occured while throwing Exception" + e1); + } + } + // + // Set our content-type + // + response.setContentType(contentType.getMimeType()); + // + // Convert the PDP response object to a String to + // return to our caller as well as dump to our loggers. + // + String outgoingResponseString = ""; + try { + if (contentType.getMimeType().equalsIgnoreCase(ContentType.APPLICATION_JSON.getMimeType())) { + // + // Get it as a String. This is not very efficient but we need to log our + // results for auditing. + // + outgoingResponseString = JSONResponse.toString(pdpResponse, logger.isDebugEnabled()); + if (logger.isDebugEnabled()) { + logger.debug(outgoingResponseString); + // + // Get rid of whitespace + // + outgoingResponseString = JSONResponse.toString(pdpResponse, false); + } + } else if (contentType.getMimeType().equalsIgnoreCase(ContentType.APPLICATION_XML.getMimeType()) + || contentType.getMimeType().equalsIgnoreCase("application/xacml+xml")) { + // + // Get it as a String. This is not very efficient but we need to log our + // results for auditing. + // + outgoingResponseString = DOMResponse.toString(pdpResponse, logger.isDebugEnabled()); + if (logger.isDebugEnabled()) { + logger.debug(outgoingResponseString); + // + // Get rid of whitespace + // + outgoingResponseString = DOMResponse.toString(pdpResponse, false); + } + } + // adding the jmx values for NA, Permit and Deny + // + if (outgoingResponseString.contains("NotApplicable") + || outgoingResponseString.contains("Decision not a Permit")) { + monitor.pdpEvaluationNA(); + } + + if (outgoingResponseString.contains("Permit") + && !outgoingResponseString.contains("Decision not a Permit")) { + monitor.pdpEvaluationPermit(); + } + + if (outgoingResponseString.contains("Deny")) { + monitor.pdpEvaluationDeny(); + } + // + // lTimeStart is used as an ID within the requestLogger to match up + // request's with responses. + // + requestLogger.info(lTimeStart + "=" + outgoingResponseString); + response.getWriter().print(outgoingResponseString); + } catch (Exception e) { + logger.error("Exception Occured" + e); + } + } catch (Exception e) { + String message = "Exception executing request: " + e; + logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + message, e); + PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, message); + loggingContext.transactionEnded(); + PolicyLogger.audit("Transaction Failed - See Error.log"); + try { + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message); + } catch (Exception e1) { + logger.error("Exception occured while sending error in response" + e1); + } + return; + } + + monitor.pdpEvaluationSuccess(); + response.setStatus(HttpServletResponse.SC_OK); + + loggingContext.transactionEnded(); + auditLogger.info("Success"); + PolicyLogger.audit("Success"); + + } + + /* + * Added for Authorizing the PEP Requests for Environment check. + */ + private boolean authorizeRequest(HttpServletRequest request) { + // Get the client Credentials from the Request header. + HttpServletRequest httpServletRequest = request; + String clientCredentials = httpServletRequest.getHeader(ENVIORNMENT_HEADER); + if (clientCredentials != null && clientCredentials.equalsIgnoreCase(environment)) { + return true; + } else { + return false; + } + } + + @Override + public void run() { + // + // Keep running until we are told to terminate + // + try { + // variable not used, but constructor has needed side-effects so don't remove: + while (!XACMLPdpServlet.configThreadTerminate) { + logger.info("XACMLPdpServlet: Taking requests from the queue"); + PutRequest request = XACMLPdpServlet.queue.take(); + logger.info("XACMLPdpServlet: Taking requests from the queue COMPLETED"); + StdPDPStatus newStatus = new StdPDPStatus(); + + PDPEngine newEngine = null; + synchronized (pdpStatusLock) { + XACMLPdpServlet.status.setStatus(Status.UPDATING_CONFIGURATION); + + logger.info("created new PDPEngine"); + newEngine = + XACMLPdpLoader.loadEngine(newStatus, request.policyProperties, request.pipConfigProperties); + } + if (newEngine != null) { + logger.info("XACMLPdpServlet: newEngine created, assigning newEngine to the pdpEngine."); + synchronized (XACMLPdpServlet.pdpEngineLock) { + XACMLPdpServlet.pdpEngine = newEngine; + try { + logger.info("Saving configuration."); + if (request.policyProperties != null) { + logger.info("Saving configuration: Policy Properties: " + request.policyProperties); + try (OutputStream os = Files.newOutputStream(XACMLPdpLoader.getPDPPolicyCache())) { + request.policyProperties.store(os, ""); + } + } + if (request.pipConfigProperties != null) { + logger.info("Saving configuration: PIP Properties: " + request.pipConfigProperties); + try (OutputStream os = Files.newOutputStream(XACMLPdpLoader.getPIPConfig())) { + request.pipConfigProperties.store(os, ""); + } + } + newStatus.setStatus(Status.UP_TO_DATE); + } catch (Exception e) { + logger.error( + XACMLErrorConstants.ERROR_PROCESS_FLOW + "Failed to store new properties." + e); + PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, "Failed to store new properties"); + newStatus.setStatus(Status.LOAD_ERRORS); + newStatus.addLoadWarning("Unable to save configuration: " + e.getMessage()); + } + } + } else { + newStatus.setStatus(Status.LAST_UPDATE_FAILED); + } + synchronized (pdpStatusLock) { + XACMLPdpServlet.status.set(newStatus); + } + logger.info("New PDP Servlet Status: " + newStatus.getStatus()); + if (Status.UP_TO_DATE.equals(newStatus.getStatus())) { + // Notification will be Sent Here. + XACMLPdpLoader.sendNotification(); + } + } + } catch (InterruptedException e) { + logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "interrupted" + e); + PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, "interrupted"); + Thread.currentThread().interrupt(); + } + } + + public static PDPEngine getPDPEngine() { + PDPEngine myEngine = null; + synchronized (pdpEngineLock) { + myEngine = XACMLPdpServlet.pdpEngine; + } + return myEngine; + } + + public static Constructor getCreateUpdatePolicyConstructor() { + return createUpdatePolicyConstructor; + } + + public static Object getPDPEngineLock() { + return pdpEngineLock; + } + + private static void setCreateUpdatePolicyConstructor(String createUpdateResourceName) throws ServletException { + try { + Class createUpdateclass = Class.forName(createUpdateResourceName); + createUpdatePolicyConstructor = + createUpdateclass.getConstructor(PolicyParameters.class, String.class, boolean.class); + } catch (Exception e) { + PolicyLogger.error(MessageCodes.MISS_PROPERTY_ERROR, "createUpdatePolicy.impl.className", + "xacml.pdp.init" + e); + throw new ServletException( + "Could not find the Class name : " + createUpdateResourceName + "\n" + e.getMessage()); + } + } } diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/DecisionPolicyService.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/DecisionPolicyService.java index 85e9c6ae5..88f27232f 100644 --- a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/DecisionPolicyService.java +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/DecisionPolicyService.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP-PDP-REST * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. * Modified Copyright (C) 2018 Samsung Electronics Co., Ltd. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -114,6 +114,7 @@ public class DecisionPolicyService { .editPolicy(updateFlag) .domain(policyScope) .highestVersion(0) + .rawXacmlPolicy(policyParameters.getRawXacmlPolicy()) .build()); // Send JSON to PAP. response = (String) papServices.callPAP(newPAPPolicy, new String[]{"operation=" + operation, "apiflag=api", diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/GetDecisionService.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/GetDecisionService.java index a74203cca..5b1b0ba88 100644 --- a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/GetDecisionService.java +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/GetDecisionService.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP-PDP-REST * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2017-2018 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. @@ -17,18 +17,26 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.policy.pdp.rest.api.services; +import com.att.research.xacml.api.Decision; +import com.att.research.xacml.api.Request; +import com.att.research.xacml.api.Response; +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 java.util.Collection; import java.util.Map; import java.util.Map.Entry; import java.util.UUID; - import javax.json.Json; import javax.json.JsonArrayBuilder; import javax.json.JsonObject; import javax.json.JsonObjectBuilder; - +import org.apache.commons.text.StringEscapeUtils; +import org.apache.commons.lang3.StringUtils; import org.onap.policy.api.DecisionRequestParameters; import org.onap.policy.api.DecisionResponse; import org.onap.policy.api.PolicyDecision; @@ -40,60 +48,83 @@ import org.onap.policy.std.StdDecisionResponse; import org.onap.policy.xacml.api.XACMLErrorConstants; import org.springframework.http.HttpStatus; + + public class GetDecisionService { private static final Logger LOGGER = FlexLogger.getLogger(GetDecisionService.class.getName()); - + private DecisionResponse decisionResponse = null; private HttpStatus status = HttpStatus.BAD_REQUEST; private DecisionRequestParameters decisionRequestParameters = null; private String message = null; private String onapComponentName = null; - private Map decisionAttributes = null; - - public GetDecisionService( - DecisionRequestParameters decisionRequestParameters, - String requestID) { + private Map decisionAttributes = null; + private UUID requestUuid = null; + private String requestType = null; + + /** + * Instantiates a new gets the decision service. + * + * @param decisionRequestParameters the decision request parameters + * @param requestId the request id + */ + public GetDecisionService(DecisionRequestParameters decisionRequestParameters, String requestId) { this.decisionRequestParameters = decisionRequestParameters; - if(decisionRequestParameters.getRequestID()==null){ - UUID requestUUID = null; - if (requestID != null && !requestID.isEmpty()) { + if (decisionRequestParameters.getRequestID() == null) { + if (!StringUtils.isBlank(requestId)) { try { - requestUUID = UUID.fromString(requestID); + requestUuid = UUID.fromString(requestId); } catch (IllegalArgumentException e) { - requestUUID = UUID.randomUUID(); - LOGGER.info("Generated Random UUID: " + requestUUID.toString(),e); + requestUuid = UUID.randomUUID(); + LOGGER.info("Generated Random UUID: " + requestUuid.toString(), e); } - }else{ - requestUUID = UUID.randomUUID(); - LOGGER.info("Generated Random UUID: " + requestUUID.toString()); + } else { + requestUuid = UUID.randomUUID(); + LOGGER.info("Generated Random UUID: " + requestUuid.toString()); } - this.decisionRequestParameters.setRequestID(requestUUID); + this.decisionRequestParameters.setRequestID(requestUuid); } - try{ + try { run(); - }catch(PolicyDecisionException e){ - StdDecisionResponse decisionResponse = new StdDecisionResponse(); - decisionResponse.setDecision(PolicyDecision.ERROR); - decisionResponse.setDetails(XACMLErrorConstants.ERROR_DATA_ISSUE + e); - this.decisionResponse = decisionResponse; + } catch (PolicyDecisionException e) { + StdDecisionResponse decisionResp = new StdDecisionResponse(); + decisionResp.setDecision(PolicyDecision.ERROR); + decisionResp.setDetails(XACMLErrorConstants.ERROR_DATA_ISSUE + e); + this.decisionResponse = decisionResp; status = HttpStatus.BAD_REQUEST; } } - private void run() throws PolicyDecisionException{ + private void run() throws PolicyDecisionException { // Get Validation. - if(!getValidation()){ + if (!getValidation()) { LOGGER.error(message); throw new PolicyDecisionException(message); } - // Generate Request. - String modelString = getModel().toString(); - LOGGER.debug("Generated JSON Request is: " + modelString); - // Process Result. + try { + // first check whether it is a raw xacml req + if (!StringUtils.isBlank(requestType) && PDPServices.DECISION_RAW_XACML.equals(requestType)) { + this.setRequestType(PDPServices.DECISION_RAW_XACML); + processRawXacmlReq(); + return; + } + + // Generate Request. + String modelString = getModel().toString(); + LOGGER.debug("Generated JSON Request is: " + modelString); + // Process Result. + PDPServices pdpServices = new PDPServices(); + if (modelString.contains(PDPServices.RAINYDAY_TYPE)) { + pdpServices.setRequestType(PDPServices.RAINYDAY_TYPE); + this.setRequestType(PDPServices.RAINYDAY_TYPE); + } else if (PDPServices.DECISION_MS_NAMING_TYPE.equals(requestType)) { + pdpServices.setRequestType(PDPServices.DECISION_MS_NAMING_TYPE); + } status = HttpStatus.OK; - decisionResponse = decisionResult(pdpServices.generateRequest(modelString, decisionRequestParameters.getRequestID(), false, true)); + decisionResponse = decisionResult( + pdpServices.generateRequest(modelString, decisionRequestParameters.getRequestID(), false, true)); } catch (Exception e) { LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + e); status = HttpStatus.BAD_REQUEST; @@ -101,8 +132,65 @@ public class GetDecisionService { } } - private DecisionResponse decisionResult( - Collection generateRequest) { + private void processRawXacmlReq() throws PolicyDecisionException { + Request pdpRequest = null; + Response pdpResponse = null; + // Process Result. + try { + PDPServices pdpServices = new PDPServices(); + pdpServices.setRequestType(PDPServices.DECISION_RAW_XACML); + String rawXacmlReq = decisionAttributes.get(PDPServices.DECISION_RAW_XACML); + if (StringUtils.isBlank(rawXacmlReq)) { + LOGGER.error("Raw XACML request cannot be empty."); + throw new PolicyDecisionException( + "Raw XACML request cannot be empty. Please provide the XACML request in " + + PDPServices.DECISION_RAW_XACML); + } + String rawXacmlReqMode = decisionAttributes.get(PDPServices.DECISION_RAW_XACML_TYPE); + String reqType = PDPServices.DECISION_RAW_XACML_XML_TYPE; + if (!StringUtils.isBlank(rawXacmlReqMode) + && PDPServices.DECISION_RAW_XACML_JSON_TYPE.equalsIgnoreCase(rawXacmlReqMode.trim())) { + pdpRequest = JSONRequest.load(rawXacmlReq); + reqType = PDPServices.DECISION_RAW_XACML_JSON_TYPE; + } else { + pdpRequest = DOMRequest.load(StringEscapeUtils.unescapeXml(rawXacmlReq)); + pdpServices.setRequestFormat(PDPServices.DECISION_RAW_XACML_XML_TYPE); + } + + status = HttpStatus.OK; + pdpResponse = pdpServices.callPdp(pdpRequest, getRequestUuid()); + + String outgoingResponseString = null; + if (PDPServices.DECISION_RAW_XACML_JSON_TYPE.equalsIgnoreCase(reqType)) { + outgoingResponseString = JSONResponse.toString(pdpResponse, false); + } else { + outgoingResponseString = DOMResponse.toString(pdpResponse, false); + if (!StringUtils.isBlank(outgoingResponseString)) { + outgoingResponseString = StringEscapeUtils.escapeXml10(outgoingResponseString); + } + } + + LOGGER.info("processRawXacmlReq - Request - \n" + rawXacmlReq + "\n Reponse:\n" + outgoingResponseString); + StdDecisionResponse decisionResp = new StdDecisionResponse(); + if (!StringUtils.isBlank(outgoingResponseString) + && outgoingResponseString.contains(Decision.PERMIT.toString())) { + decisionResp.setDecision(PolicyDecision.PERMIT); + } else if (!StringUtils.isBlank(outgoingResponseString) + && outgoingResponseString.contains(Decision.DENY.toString())) { + decisionResp.setDecision(PolicyDecision.DENY); + } else { + decisionResp.setDecision(PolicyDecision.ERROR); + } + decisionResp.setDetails(outgoingResponseString); + this.decisionResponse = decisionResp; + } catch (Exception e) { + LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + e); + status = HttpStatus.BAD_REQUEST; + throw new PolicyDecisionException(e); + } + } + + private DecisionResponse decisionResult(Collection generateRequest) { StdDecisionResponse policyDecision = new StdDecisionResponse(); if (generateRequest == null) { return policyDecision; @@ -116,64 +204,70 @@ public class GetDecisionService { return policyDecision; } - private JsonObject getModel() throws PolicyDecisionException{ + private JsonObject getModel() throws PolicyDecisionException { JsonArrayBuilder resourceArray = Json.createArrayBuilder(); - for (Entry key : decisionAttributes.entrySet()) { - if (key.getKey().isEmpty()) { - String message = XACMLErrorConstants.ERROR_DATA_ISSUE + "Cannot have an Empty Key"; - LOGGER.error(message); - throw new PolicyDecisionException(message); + for (Entry entry : decisionAttributes.entrySet()) { + if (entry.getKey().isEmpty()) { + String msg = XACMLErrorConstants.ERROR_DATA_ISSUE + "Cannot have an Empty Key"; + LOGGER.error(msg); + throw new PolicyDecisionException(msg); } + if (PDPServices.DECISION_MS_NAMING_TYPE.equalsIgnoreCase(entry.getKey().trim())) { + // this is used for only Model execution and not for identifying + // policy. It is input data for MS Naming model execution and + // will be parsed in the naming service. Skip here. + this.setRequestType(PDPServices.DECISION_MS_NAMING_TYPE); + continue; + } + JsonObjectBuilder resourceBuilder = Json.createObjectBuilder(); - if (key.getValue().matches("[0-9]+")) { - - if ((key.getKey().equals("ErrorCode")) || (key.getKey().equals("WorkStep"))) { - - resourceBuilder.add("Value", key.getValue()); - - } else { - - int val = Integer.parseInt(key.getValue()); + if (entry.getValue().matches("[0-9]+")) { + + if ((entry.getKey().equals("ErrorCode")) || (entry.getKey().equals("WorkStep"))) { + + resourceBuilder.add("Value", entry.getValue()); + + } else { + + int val = Integer.parseInt(entry.getValue()); resourceBuilder.add("Value", val); - - } - + + } + } else { - resourceBuilder.add("Value", key.getValue()); + resourceBuilder.add("Value", entry.getValue()); } - resourceBuilder.add("AttributeId", key.getKey()); + resourceBuilder.add("AttributeId", entry.getKey()); resourceArray.add(resourceBuilder); } - return Json.createObjectBuilder() - .add("Request", Json.createObjectBuilder() - .add("AccessSubject", Json.createObjectBuilder() - .add("Attribute", Json.createObjectBuilder() - .add("Value", onapComponentName) - .add("AttributeId", "ONAPName"))) - .add("Resource", Json.createObjectBuilder() - .add("Attribute", resourceArray)) - .add("Action", Json.createObjectBuilder() - .add("Attribute", Json.createObjectBuilder() - .add("Value", "DECIDE") - .add("AttributeId", "urn:oasis:names:tc:xacml:1.0:action:action-id")))) + return Json.createObjectBuilder().add("Request", Json.createObjectBuilder().add("AccessSubject", + Json.createObjectBuilder().add("Attribute", + Json.createObjectBuilder().add("Value", onapComponentName).add("AttributeId", "ONAPName"))) + .add("Resource", Json.createObjectBuilder().add("Attribute", resourceArray)) + .add("Action", Json.createObjectBuilder().add("Attribute", Json.createObjectBuilder() + .add("Value", "DECIDE").add("AttributeId", "urn:oasis:names:tc:xacml:1.0:action:action-id")))) .build(); } private boolean getValidation() { - if(decisionRequestParameters==null){ + if (decisionRequestParameters == null) { message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No Decision Request Paramaters"; - return false; + return false; } onapComponentName = decisionRequestParameters.getOnapName(); decisionAttributes = decisionRequestParameters.getDecisionAttributes(); - if (onapComponentName == null || onapComponentName.isEmpty()) { - message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No onapComponentName given : " + onapComponentName; - return false; - } if (decisionAttributes == null || decisionAttributes.isEmpty()) { message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No Decision Attributes Given. "; return false; } + if (decisionAttributes.containsKey(PDPServices.DECISION_RAW_XACML)) { + // onapName not mandatory for raw requests + requestType = PDPServices.DECISION_RAW_XACML; + } else if (onapComponentName == null || onapComponentName.isEmpty()) { + message = XACMLErrorConstants.ERROR_DATA_ISSUE + "No onapComponentName given : " + onapComponentName; + return false; + } + return true; } @@ -185,5 +279,20 @@ public class GetDecisionService { return status; } -} + public UUID getRequestUuid() { + return requestUuid; + } + public void setRequestUuid(UUID requestId) { + this.requestUuid = requestId; + } + + public String getRequestType() { + return requestType; + } + + public void setRequestType(String requestType) { + this.requestType = requestType; + } + +} diff --git a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/PDPServices.java b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/PDPServices.java index 6dae064a7..e61bbd3aa 100644 --- a/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/PDPServices.java +++ b/ONAP-PDP-REST/src/main/java/org/onap/policy/pdp/rest/api/services/PDPServices.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP-PDP-REST * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. * Modified Copyright (C) 2018 Samsung Electronics Co., Ltd. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,21 +18,38 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.policy.pdp.rest.api.services; +import com.att.research.xacml.api.Advice; +import com.att.research.xacml.api.AttributeAssignment; +import com.att.research.xacml.api.Decision; +import com.att.research.xacml.api.Obligation; +import com.att.research.xacml.api.Request; +import com.att.research.xacml.api.Response; +import com.att.research.xacml.api.Result; +import com.att.research.xacml.api.pdp.PDPEngine; +import com.att.research.xacml.api.pdp.PDPException; +import com.att.research.xacml.std.dom.DOMRequest; +import com.att.research.xacml.std.dom.DOMResponse; +import com.att.research.xacml.std.json.JSONRequest; +import com.att.research.xacml.std.json.JSONResponse; +import com.att.research.xacml.util.XACMLProperties; +import com.google.common.base.Strings; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.StringWriter; +import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Properties; import java.util.UUID; - import javax.json.Json; import javax.json.JsonReader; import javax.xml.XMLConstants; @@ -43,7 +60,6 @@ import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; - import org.apache.commons.io.IOUtils; import org.onap.policy.api.PolicyConfigStatus; import org.onap.policy.api.PolicyDecision; @@ -59,42 +75,56 @@ import org.onap.policy.std.Matches; import org.onap.policy.xacml.api.XACMLErrorConstants; import org.w3c.dom.Document; -import com.att.research.xacml.api.Advice; -import com.att.research.xacml.api.AttributeAssignment; -import com.att.research.xacml.api.Decision; -import com.att.research.xacml.api.Obligation; -import com.att.research.xacml.api.Request; -import com.att.research.xacml.api.Response; -import com.att.research.xacml.api.Result; -import com.att.research.xacml.api.pdp.PDPEngine; -import com.att.research.xacml.api.pdp.PDPException; -import com.att.research.xacml.std.json.JSONRequest; -import com.att.research.xacml.std.json.JSONResponse; -import com.att.research.xacml.util.XACMLProperties; public class PDPServices { private static final Logger LOGGER = FlexLogger.getLogger(PDPServices.class.getName()); - // Change the default Priority value here. + // Change the default Priority value here. private static final int DEFAULT_PRIORITY = 9999; private boolean unique = false; private Boolean decide = false; - private Request rainydayRequest = null; - - public Collection generateRequest(String jsonString, UUID requestID, boolean unique, boolean decide) throws PolicyException{ + private String requestType = null; + private String requestFormat = DECISION_RAW_XACML_JSON_TYPE; + private List policyList = null; + public static final String RAINYDAY_TYPE = "BB_ID"; + public static final String DECISION_MS_NAMING_TYPE = "main-resource-keys"; + public static final String DECISION_RAW_XACML = "raw-xacml-request"; + public static final String DECISION_RAW_XACML_TYPE = "raw-xacml-type"; + public static final String DECISION_RAW_XACML_XML_TYPE = "XML"; + public static final String DECISION_RAW_XACML_JSON_TYPE = "JSON"; + + /** + * Generate request. + * + * @param reqStr the json string + * @param requestId the request id + * @param unique the unique + * @param decide the decide + * @return the collection + * @throws PolicyException the policy exception + */ + public Collection generateRequest(String reqStr, UUID requestId, boolean unique, boolean decide) + throws PolicyException { this.unique = unique; this.decide = decide; Collection results = null; Response response = null; // Create Request. We need XACML API here. try { - Request request = JSONRequest.load(jsonString); - // Assign a rainy day treatment request to parse the decided treatment - if (jsonString.contains("BB_ID")) { - rainydayRequest = request; + Request request = null; + if (DECISION_RAW_XACML_JSON_TYPE.equals(requestFormat)) { + request = JSONRequest.load(reqStr); + LOGGER.info("--- Generating Request: ---" + requestId + "\n" + JSONRequest.toString(request)); + } else { + request = DOMRequest.load(reqStr); + LOGGER.info("--- Generating Request: ---" + requestId + "\n" + reqStr); } + // Call the PDP - LOGGER.info("--- Generating Request: ---\n" + JSONRequest.toString(request)); - response = callPDP(request, requestID); + response = callPdp(request, requestId); + if (response == null) { + response = callPdp(request, requestId); + } + } catch (Exception e) { LOGGER.error(XACMLErrorConstants.ERROR_SCHEMA_INVALID + e); PDPResponse pdpResponse = new PDPResponse(); @@ -105,8 +135,14 @@ public class PDPServices { results.add(pdpResponse); throw new PolicyException(e); } + if (response != null) { results = checkResponse(response); + if (policyList != null) { + for (String policy : policyList) { + XACMLPdpServlet.monitor.policyCountAdd(policy, 1); + } + } } else { LOGGER.info("No Response Received from PDP"); PDPResponse pdpResponse = new PDPResponse(); @@ -119,59 +155,39 @@ public class PDPServices { return results; } - private Collection checkResponse(Response response) throws PolicyException{ + private Collection checkResponse(Response response) throws PolicyException { String pdpConfigLocation = null; Collection combinedResult = new HashSet<>(); int priority = DEFAULT_PRIORITY; Map uniqueResult = new HashMap<>(); for (Result result : response.getResults()) { - if (!result.getDecision().equals(Decision.PERMIT)) { - LOGGER.info("Decision not a Permit. " + result.getDecision().toString()); - PDPResponse pdpResponse = new PDPResponse(); - if (decide) { - String indeterminatePropValue = XACMLProperties.getProperty("decision.indeterminate.response"); - if(result.getDecision().equals(Decision.INDETERMINATE)&& indeterminatePropValue != null){ - if("PERMIT".equalsIgnoreCase(indeterminatePropValue)){ - pdpResponse.setDecision(PolicyDecision.PERMIT); - }else{ - pdpResponse.setDecision(PolicyDecision.DENY); - } - }else{ - pdpResponse.setDecision(PolicyDecision.DENY); - } - for(Advice advice: result.getAssociatedAdvice()){ - for(AttributeAssignment attribute: advice.getAttributeAssignments()){ - pdpResponse.setDetails(attribute.getAttributeValue().getValue().toString()); - break; - } - } + // Process the decision policies. We only return one back for + // decision + if (decide) { + PDPResponse pdpResponse = processDecisionResult(result); + if (pdpResponse != null) { combinedResult.add(pdpResponse); - return combinedResult; + } else { + LOGGER.info("processDecisionResult returned null"); } - pdpResponse.setStatus(XACMLErrorConstants.ERROR_DATA_ISSUE + "Incorrect Params passed: Decision not a Permit.",PolicyResponseStatus.NO_ACTION_REQUIRED,PolicyConfigStatus.CONFIG_NOT_FOUND); + return combinedResult; + } + if (!result.getDecision().equals(Decision.PERMIT)) { + LOGGER.info("Decision not a Permit. " + result.getDecision().toString()); + PDPResponse pdpResponse = new PDPResponse(); + pdpResponse.setStatus( + XACMLErrorConstants.ERROR_DATA_ISSUE + "Incorrect Params passed: Decision not a Permit.", + PolicyResponseStatus.NO_ACTION_REQUIRED, PolicyConfigStatus.CONFIG_NOT_FOUND); combinedResult.add(pdpResponse); return combinedResult; } else { - if (decide) { - // check for Decision for decision based calls. - PDPResponse pdpResponse = new PDPResponse(); - pdpResponse.setDecision(PolicyDecision.PERMIT); - - //if this is a Rainy Day treatment decision we need to get the selected treatment - if(rainydayRequest!=null){ - pdpResponse.setDetails(getRainyDayTreatment(result)); - } else { - pdpResponse.setDetails("Decision Permit. OK!"); - } - combinedResult.add(pdpResponse); - return combinedResult; - } if (!result.getAssociatedAdvice().isEmpty()) { - // Configurations should be in advice. + // Configurations should be in advice. // Also PDP took actions could be here. for (Advice advice : result.getAssociatedAdvice()) { - int config = 0, uri = 0; - String configURL = null; + int config = 0; + int uri = 0; + String configUrl = null; String policyName = null; String policyVersion = null; Matches match = new Matches(); @@ -182,48 +198,60 @@ public class PDPServices { PDPResponse pdpResponse = new PDPResponse(); Map adviseAttributes = new HashMap<>(); for (AttributeAssignment attribute : advice.getAttributeAssignments()) { - adviseAttributes.put(attribute.getAttributeId().stringValue(), attribute.getAttributeValue().getValue().toString()); + adviseAttributes.put(attribute.getAttributeId().stringValue(), + attribute.getAttributeValue().getValue().toString()); if ("CONFIGURATION".equalsIgnoreCase(attribute.getAttributeValue().getValue().toString())) { config++; } else if (attribute.getDataTypeId().stringValue().endsWith("anyURI")) { uri++; if (uri == 1) { - configURL = attribute.getAttributeValue().getValue().toString(); - pdpConfigLocation = configURL.replace("$URL", XACMLProperties.getProperty(XACMLRestProperties.PROP_PDP_WEBAPPS)); + configUrl = attribute.getAttributeValue().getValue().toString(); + pdpConfigLocation = configUrl.replace("$URL", + XACMLProperties.getProperty(XACMLRestProperties.PROP_PDP_WEBAPPS)); } else { if (!("PDP".equalsIgnoreCase(attribute.getIssuer()))) { - throw new PolicyException(XACMLErrorConstants.ERROR_DATA_ISSUE + "Error having multiple URI in the Policy"); + throw new PolicyException(XACMLErrorConstants.ERROR_DATA_ISSUE + + "Error having multiple URI in the Policy"); } } } else if ("PolicyName".equalsIgnoreCase(attribute.getAttributeId().stringValue())) { policyName = attribute.getAttributeValue().getValue().toString(); + policyList.add(policyName); } else if ("VersionNumber".equalsIgnoreCase(attribute.getAttributeId().stringValue())) { policyVersion = attribute.getAttributeValue().getValue().toString(); - } else if ("Priority".equalsIgnoreCase(attribute.getAttributeId().stringValue())){ - try{ + } else if ("Priority".equalsIgnoreCase(attribute.getAttributeId().stringValue())) { + try { priority = Integer.parseInt(attribute.getAttributeValue().getValue().toString()); - } catch(Exception e){ - LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE+ "Unable to Parse Integer for Priority. Setting to default value",e); + } catch (Exception e) { + LOGGER.error( + XACMLErrorConstants.ERROR_DATA_ISSUE + + "Unable to Parse Integer for Priority. Setting to default value", + e); priority = DEFAULT_PRIORITY; } } else if (attribute.getAttributeId().stringValue().startsWith("matching")) { - matchingConditions.put(attribute.getAttributeId().stringValue() - .replaceFirst("(matching).", ""),attribute.getAttributeValue().getValue().toString()); - if ("ONAPName".equals(attribute.getAttributeId().stringValue() - .replaceFirst("(matching).", ""))) { + matchingConditions.put( + attribute.getAttributeId().stringValue().replaceFirst("(matching).", ""), + attribute.getAttributeValue().getValue().toString()); + if ("ONAPName".equals( + attribute.getAttributeId().stringValue().replaceFirst("(matching).", ""))) { match.setOnapName(attribute.getAttributeValue().getValue().toString()); - } else if ("ConfigName".equals(attribute.getAttributeId().stringValue() - .replaceFirst("(matching).", ""))) { + matchingConditions.put("ECOMPName", + attribute.getAttributeValue().getValue().toString()); + } else if ("ConfigName".equals( + attribute.getAttributeId().stringValue().replaceFirst("(matching).", ""))) { match.setConfigName(attribute.getAttributeValue().getValue().toString()); } else { - configAttributes.put(attribute.getAttributeId().stringValue() - .replaceFirst("(matching).", ""),attribute.getAttributeValue().getValue().toString()); + configAttributes.put( + attribute.getAttributeId().stringValue().replaceFirst("(matching).", ""), + attribute.getAttributeValue().getValue().toString()); } } else if (attribute.getAttributeId().stringValue().startsWith("key:")) { - responseAttributes.put(attribute.getAttributeId().stringValue().replaceFirst("(key).", ""), + responseAttributes.put( + attribute.getAttributeId().stringValue().replaceFirst("(key).", ""), attribute.getAttributeValue().getValue().toString()); } else if (attribute.getAttributeId().stringValue().startsWith("controller:")) { - responseAttributes.put("$"+ attribute.getAttributeId().stringValue(), + responseAttributes.put("$" + attribute.getAttributeId().stringValue(), attribute.getAttributeValue().getValue().toString()); } else if (attribute.getAttributeId().stringValue().startsWith("dependencies:")) { responseAttributes.put("$dependency$", @@ -236,41 +264,42 @@ public class PDPServices { if ((config == 1) && (uri == 1)) { // If there is a configuration. try { - LOGGER.debug("Configuration Call to : " + configURL); + LOGGER.debug("Configuration Call to : " + configUrl); pdpResponse = configCall(pdpConfigLocation); } catch (Exception e) { - LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW+ e); - pdpResponse.setStatus("Error in Calling the Configuration URL "+ e, - PolicyResponseStatus.NO_ACTION_REQUIRED, - PolicyConfigStatus.CONFIG_NOT_FOUND); + LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + e); + pdpResponse.setStatus("Error in Calling the Configuration URL " + e, + PolicyResponseStatus.NO_ACTION_REQUIRED, PolicyConfigStatus.CONFIG_NOT_FOUND); } pdpResponse.setPolicyName(policyName); pdpResponse.setPolicyVersion(policyVersion); pdpResponse.setMatchingConditions(matchingConditions); pdpResponse.setResponseAttributes(responseAttributes); - if(!unique){ + if (!unique) { combinedResult.add(pdpResponse); - }else{ - if(!uniqueResult.isEmpty()){ - if(uniqueResult.containsKey(priority)){ - // Not any more unique, check the matching conditions size + } else { + if (!uniqueResult.isEmpty()) { + if (uniqueResult.containsKey(priority)) { + // Not any more unique, check the + // matching conditions size int oldSize = uniqueResult.get(priority).getMatchingConditions().size(); int newSize = matchingConditions.size(); - if(oldSize < newSize){ + if (oldSize < newSize) { uniqueResult.put(priority, pdpResponse); - }else if(oldSize == newSize){ + } else if (oldSize == newSize) { pdpResponse = new PDPResponse(); - pdpResponse.setStatus("Two/more Policies have Same Priority and matching conditions, Please correct your policies.", + pdpResponse.setStatus( + "Two/more Policies have Same Priority and matching conditions, Please correct your policies.", PolicyResponseStatus.NO_ACTION_REQUIRED, PolicyConfigStatus.CONFIG_NOT_FOUND); combinedResult.add(pdpResponse); unique = false; return combinedResult; } - }else{ + } else { uniqueResult.put(priority, pdpResponse); } - }else{ + } else { uniqueResult.put(priority, pdpResponse); } } @@ -303,11 +332,11 @@ public class PDPServices { } } } - if(unique){ - // Select Unique policy. + if (unique) { + // Select Unique policy. int minNum = DEFAULT_PRIORITY; - for(int num: uniqueResult.keySet()){ - if(num < minNum){ + for (int num : uniqueResult.keySet()) { + if (num < minNum) { minNum = num; } } @@ -315,19 +344,122 @@ public class PDPServices { // Turn off Unique unique = false; } - + return combinedResult; } - + + /** + * Process Decision Result. + * + * @param result input from Response. + * @return pdpResposne based on result. + */ + private PDPResponse processDecisionResult(Result result) { + PDPResponse pdpResponse = new PDPResponse(); + pdpResponse.setDecision(PolicyDecision.DENY); + + if (!result.getDecision().equals(Decision.PERMIT)) { + LOGGER.info("processDecisionResult: Decision not a Permit. " + result.getDecision().toString()); + String indeterminatePropValue = XACMLProperties.getProperty("decision.indeterminate.response"); + if (result.getDecision().equals(Decision.INDETERMINATE) && indeterminatePropValue != null) { + if ("PERMIT".equalsIgnoreCase(indeterminatePropValue)) { + pdpResponse.setDecision(PolicyDecision.PERMIT); + } else { + pdpResponse.setDecision(PolicyDecision.DENY); + } + } else { + pdpResponse.setDecision(PolicyDecision.DENY); + } + for (Advice advice : result.getAssociatedAdvice()) { + for (AttributeAssignment attribute : advice.getAttributeAssignments()) { + pdpResponse.setDetails(attribute.getAttributeValue().getValue().toString()); + break; + } + } + pdpResponse.setStatus( + XACMLErrorConstants.ERROR_DATA_ISSUE + "Incorrect Params passed: Decision not a Permit.", + PolicyResponseStatus.NO_ACTION_REQUIRED, PolicyConfigStatus.CONFIG_NOT_FOUND); + } else { + checkDecision(pdpResponse, result); + } + return pdpResponse; + } + + + /** + * Check for Decision for decision based calls. + * + * @param pdpResponseInput pdpResponse. + * @param result result. + * @return pdpResponse. + */ + private PDPResponse checkDecision(PDPResponse pdpResponseInput, Result result) { + PDPResponse pdpResponse = pdpResponseInput; + // check for Decision for decision based calls. + pdpResponse.setDecision(PolicyDecision.PERMIT); + + // if this is a Rainy Day treatment decision we need to get + // the selected treatment + if (!Strings.isNullOrEmpty(requestType) && RAINYDAY_TYPE.equals(requestType)) { + pdpResponse.setDetails(getRainyDayTreatment(result)); + } else if (!Strings.isNullOrEmpty(requestType) && DECISION_MS_NAMING_TYPE.equals(requestType)) { + boolean configRetrieved = false; + for (Advice advice : result.getAssociatedAdvice()) { + configRetrieved = checkConfig(advice, configRetrieved, pdpResponse); + } + if (!configRetrieved) { + LOGGER.error(" Failed to retrieve Config data for " + DECISION_MS_NAMING_TYPE); + pdpResponse.setDetails("Error in retrieving Config Data"); + } + + } else { + pdpResponse.setDetails("Decision Permit. OK!"); + } + return pdpResponse; + } + + /** + * Check if there is a configuration. + * + * @param advice advice. + * @param configRetrieved boolean. + * @param pdpResponse pdpResposneInput. + * @return pdpResponse. + */ + private boolean checkConfig(Advice advice, boolean configRetrieved, PDPResponse pdpResponse) { + for (AttributeAssignment attribute : advice.getAttributeAssignments()) { + if (attribute.getDataTypeId().stringValue().endsWith("anyURI")) { + String configUrl = attribute.getAttributeValue().getValue().toString(); + String pdpConfigLocation = + configUrl.replace("$URL", XACMLProperties.getProperty(XACMLRestProperties.PROP_PDP_WEBAPPS)); + // If there is a configuration. + try { + LOGGER.debug("processDecisionResult: Configuration Call to : " + configUrl); + pdpResponse = configCall(pdpConfigLocation); + pdpResponse.setDecision(PolicyDecision.PERMIT); + pdpResponse.setDetails(pdpResponse.getConfig()); + configRetrieved = true; + break; + } catch (Exception e) { + LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + e); + LOGGER.error(" Failed to retrieve Config data for " + configUrl); + pdpResponse.setDetails("Error in retrieving Config Data from the Configuration URL " + configUrl); + } + } + } + return configRetrieved; + } + private String getRainyDayTreatment(Result result) { String treatment = null; - if (rainydayRequest!=null&& !result.getAssociatedAdvice().isEmpty()) { + if (result != null && !result.getAssociatedAdvice().isEmpty()) { // Get the desired treatment for requested errorCode from the Advice for (Advice advice : result.getAssociatedAdvice()) { Map adviseAttributes = new HashMap<>(); for (AttributeAssignment attribute : advice.getAttributeAssignments()) { - adviseAttributes.put(attribute.getAttributeId().stringValue(), attribute.getAttributeValue().getValue().toString()); - if ("treatment".equalsIgnoreCase(attribute.getAttributeId().stringValue())){ + adviseAttributes.put(attribute.getAttributeId().stringValue(), + attribute.getAttributeValue().getValue().toString()); + if ("treatment".equalsIgnoreCase(attribute.getAttributeId().stringValue())) { treatment = attribute.getAttributeValue().getValue().toString(); } } @@ -336,16 +468,15 @@ public class PDPServices { return treatment; } - private PDPResponse configCall(String pdpConfigLocation) throws PDPException, IOException{ + private PDPResponse configCall(String pdpConfigLocation) throws PDPException, IOException { PDPResponse pdpResponse = new PDPResponse(); - if(pdpConfigLocation.contains("/")){ + if (pdpConfigLocation.contains("/")) { pdpConfigLocation = pdpConfigLocation.replace("/", File.separator); } - - try(InputStream inputStream = new FileInputStream(new File(pdpConfigLocation))) { + try (InputStream inputStream = new FileInputStream(new File(pdpConfigLocation))) { if (pdpConfigLocation.endsWith("json")) { pdpResponse.setType(PolicyType.JSON); - try(JsonReader jsonReader = Json.createReader(inputStream);) { + try (JsonReader jsonReader = Json.createReader(inputStream)) { pdpResponse.setConfig(jsonReader.readObject().toString()); } } else if (pdpConfigLocation.endsWith("xml")) { @@ -366,15 +497,16 @@ public class PDPServices { transformer.transform(domSource, result); pdpResponse.setConfig(writer.toString()); } catch (Exception e) { - LOGGER.error(XACMLErrorConstants.ERROR_SCHEMA_INVALID+ e); - throw new PDPException(XACMLErrorConstants.ERROR_SCHEMA_INVALID+ "Unable to parse the XML config", e); + LOGGER.error(XACMLErrorConstants.ERROR_SCHEMA_INVALID + e); + throw new PDPException(XACMLErrorConstants.ERROR_SCHEMA_INVALID + "Unable to parse the XML config", + e); } } else if (pdpConfigLocation.endsWith("properties")) { pdpResponse.setType(PolicyType.PROPERTIES); Properties configProp = new Properties(); configProp.load(inputStream); Map propVal = new HashMap<>(); - for(String name: configProp.stringPropertyNames()) { + for (String name : configProp.stringPropertyNames()) { propVal.put(name, configProp.getProperty(name)); } pdpResponse.setProperty(propVal); @@ -387,11 +519,11 @@ public class PDPServices { LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Config Not Found"); pdpResponse.setPolicyConfigStatus(PolicyConfigStatus.CONFIG_NOT_FOUND); pdpResponse.setPolicyConfigMessage("Illegal form of Configuration Type Found."); + inputStream.close(); return pdpResponse; } LOGGER.info("config Retrieved " + pdpConfigLocation); - pdpResponse.setStatus("Config Retrieved! ", - PolicyResponseStatus.NO_ACTION_REQUIRED, + pdpResponse.setStatus("Config Retrieved! ", PolicyResponseStatus.NO_ACTION_REQUIRED, PolicyConfigStatus.CONFIG_RETRIEVED); return pdpResponse; } catch (FileNotFoundException e) { @@ -399,35 +531,104 @@ public class PDPServices { throw new PDPException(XACMLErrorConstants.ERROR_DATA_ISSUE + "Error in ConfigURL", e); } catch (IOException | ParserConfigurationException e) { LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + e); - throw new PDPException(XACMLErrorConstants.ERROR_PROCESS_FLOW + - "Cannot open a connection to the configURL", e); + throw new PDPException(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Cannot open a connection to the configURL", + e); } } - private Response callPDP(Request request, UUID requestID){ + /** + * Call pdp. + * + * @param request the request + * @param requestIdParam the request id param + * @return the response + */ + public Response callPdp(Request request, UUID requestIdParam) { + policyList = new ArrayList<>(); Response response = null; // Get the PDPEngine - if (requestID == null) { - requestID = UUID.randomUUID(); - LOGGER.debug("No request ID provided, sending generated ID: " + requestID.toString()); + if (requestIdParam == null) { + requestIdParam = UUID.randomUUID(); + LOGGER.debug("No request ID provided, sending generated ID: " + requestIdParam.toString()); } else { - LOGGER.debug("Using provided request ID: " + requestID.toString()); + LOGGER.debug("Using provided request ID: " + requestIdParam.toString()); } PDPEngine pdpEngine = XACMLPdpServlet.getPDPEngine(); if (pdpEngine == null) { String message = "PDPEngine not loaded."; - LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + message); + LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + message + "\n RequestId : " + requestIdParam); return response; } + XACMLPdpServlet.monitor.pdpEvaluationAttempts(); // call the PDPEngine to decide and give the response on the Request. + long timeStart; + long timeEnd; try { - response = pdpEngine.decide(request); - LOGGER.info("Response from the PDP is: \n" + JSONResponse.toString(response)); + synchronized (XACMLPdpServlet.getPDPEngineLock()) { + timeStart = System.currentTimeMillis(); + response = pdpEngine.decide(request); + timeEnd = System.currentTimeMillis(); + } + + String outgoingResponseString = null; + if (DECISION_RAW_XACML_JSON_TYPE.equalsIgnoreCase(requestFormat)) { + outgoingResponseString = JSONResponse.toString(response); + LOGGER.info("Response from the PDP is : \n" + JSONResponse.toString(response, true) + "\n RequestId : " + + requestIdParam + " pdpEngine : " + pdpEngine); + } else { + outgoingResponseString = DOMResponse.toString(response); + LOGGER.info("Response from the PDP is : \n" + DOMResponse.toString(response, true) + "\n RequestId : " + + requestIdParam + " pdpEngine : " + pdpEngine); + } + + XACMLPdpServlet.monitor.computeLatency(timeEnd - timeStart); + + // adding the jmx values for NA, Permit and Deny + // + if (outgoingResponseString.contains("NotApplicable") + || outgoingResponseString.contains("Decision not a Permit")) { + XACMLPdpServlet.monitor.pdpEvaluationNA(); + } + + if (outgoingResponseString.contains("Permit") + && !outgoingResponseString.contains("Decision not a Permit")) { + XACMLPdpServlet.monitor.pdpEvaluationPermit(); + } + + if (outgoingResponseString.contains("Deny")) { + XACMLPdpServlet.monitor.pdpEvaluationDeny(); + } } catch (Exception e) { - LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + e); + LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + e + "\n RequestId : " + requestIdParam); return null; } return response; } + public String getRequestType() { + return requestType; + } + + public void setRequestType(String requestType) { + this.requestType = requestType; + } + + /** + * Returns the requestFormat. + * + * @return the requestFormat. + */ + public String getRequestFormat() { + return requestFormat; + } + + /** + * Set the Request Format. + * + * @param requestMode to set requestFormat. + */ + public void setRequestFormat(String requestMode) { + this.requestFormat = requestMode; + } + } -- cgit 1.2.3-korg