Initial OpenECOMP policy/engine commit
[policy/engine.git] / ECOMP-PDP-REST / src / main / java / org / openecomp / policy / pdp / rest / XACMLPdpServlet.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ECOMP-PDP-REST
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.openecomp.policy.pdp.rest;
22
23 import java.io.BufferedReader;
24 import java.io.ByteArrayInputStream;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.io.InputStreamReader;
28 import java.io.OutputStream;
29 import java.net.InetAddress;
30 import java.net.UnknownHostException;
31 import java.nio.file.Files;
32 import java.util.Properties;
33 import java.util.UUID;
34 import java.util.concurrent.BlockingQueue;
35 import java.util.concurrent.LinkedBlockingQueue;
36
37 import javax.servlet.Servlet;
38 import javax.servlet.ServletConfig;
39 import javax.servlet.ServletException;
40 import javax.servlet.annotation.WebInitParam;
41 import javax.servlet.annotation.WebServlet;
42 import javax.servlet.http.HttpServlet;
43 import javax.servlet.http.HttpServletRequest;
44 import javax.servlet.http.HttpServletResponse;
45
46 import org.apache.commons.io.IOUtils;
47 import org.apache.commons.logging.Log;
48 import org.apache.commons.logging.LogFactory;
49 import org.apache.http.entity.ContentType;
50 import org.openecomp.policy.pdp.rest.jmx.PdpRestMonitor;
51 import org.openecomp.policy.rest.XACMLRest;
52 import org.openecomp.policy.rest.XACMLRestProperties;
53 import org.openecomp.policy.common.logging.ECOMPLoggingContext;
54 import org.openecomp.policy.common.logging.ECOMPLoggingUtils;
55 import org.openecomp.policy.common.logging.eelf.MessageCodes;
56 import org.openecomp.policy.common.logging.eelf.PolicyLogger;
57 import org.openecomp.policy.common.im.AdministrativeStateException;
58 import org.openecomp.policy.common.im.ForwardProgressException;
59 import org.openecomp.policy.common.im.IntegrityMonitor;
60 import org.openecomp.policy.common.im.IntegrityMonitorProperties;
61 import org.openecomp.policy.common.im.StandbyStatusException;
62
63 import com.att.research.xacml.api.Request;
64 import com.att.research.xacml.api.Response;
65 import org.openecomp.policy.xacml.api.XACMLErrorConstants;
66 import com.att.research.xacml.api.pap.PDPStatus.Status;
67 import com.att.research.xacml.api.pdp.PDPEngine;
68 import com.att.research.xacml.api.pdp.PDPException;
69 import com.att.research.xacml.std.dom.DOMRequest;
70 import com.att.research.xacml.std.dom.DOMResponse;
71 import com.att.research.xacml.std.json.JSONRequest;
72 import com.att.research.xacml.std.json.JSONResponse;
73 import com.att.research.xacml.util.XACMLProperties;
74 import org.openecomp.policy.xacml.pdp.std.functions.PolicyList;
75 import org.openecomp.policy.xacml.std.pap.StdPDPStatus;
76 import com.fasterxml.jackson.databind.ObjectMapper;
77
78 /**
79  * Servlet implementation class XacmlPdpServlet
80  * 
81  * This is an implementation of the XACML 3.0 RESTful Interface with added features to support
82  * simple PAP RESTful API for policy publishing and PIP configuration changes.
83  * 
84  * If you are running this the first time, then we recommend you look at the xacml.pdp.properties file.
85  * This properties file has all the default parameter settings. If you are running the servlet as is,
86  * then we recommend setting up you're container to run it on port 8080 with context "/pdp". Wherever
87  * the default working directory is set to, a "config" directory will be created that holds the policy
88  * and pip cache. This setting is located in the xacml.pdp.properties file.
89  * 
90  * When you are ready to customize, you can create a separate xacml.pdp.properties on you're local file
91  * system and setup the parameters as you wish. Just set the Java VM System variable to point to that file:
92  * 
93  * -Dxacml.properties=/opt/app/xacml/etc/xacml.pdp.properties
94  * 
95  * Or if you only want to change one or two properties, simply set the Java VM System variable for that property.
96  * 
97  * -Dxacml.rest.pdp.register=false
98  *
99  *
100  */
101 @WebServlet(
102                 description = "Implements the XACML PDP RESTful API and client PAP API.", 
103                 urlPatterns = { "/" }, 
104                 loadOnStartup=1,
105                 initParams = { 
106                                 @WebInitParam(name = "XACML_PROPERTIES_NAME", value = "xacml.pdp.properties", description = "The location of the PDP xacml.pdp.properties file holding configuration information.")
107                 })
108 public class XACMLPdpServlet extends HttpServlet implements Runnable {
109         private static final long serialVersionUID = 1L;
110         private static final String DEFAULT_MAX_CONTENT_LENGTH = "999999999"; //32767
111         //
112         // Our application debug log
113         //
114         private static final Log logger = LogFactory.getLog(XACMLPdpServlet.class);
115         //
116         // This logger is specifically only for Xacml requests and their corresponding response.
117         // It's output ideally should be sent to a separate file from the application logger.
118         //
119         private static final Log requestLogger = LogFactory.getLog("xacml.request");
120         // 
121         // audit logger
122         private static final Log auditLogger = LogFactory.getLog("auditLogger");
123         
124         private static final PdpRestMonitor monitor = PdpRestMonitor.singleton;
125         
126         //
127         // This thread may getting invoked on startup, to let the PAP know
128         // that we are up and running.
129         //
130         private Thread registerThread = null;
131         private XACMLPdpRegisterThread registerRunnable = null;
132         //
133         // This is our PDP engine pointer. There is a synchronized lock used
134         // for access to the pointer. In case we are servicing PEP requests while
135         // an update is occurring from the PAP.
136         //
137         private PDPEngine pdpEngine     = null;
138         private static final Object pdpEngineLock = new Object();
139         //
140         // This is our PDP's status. What policies are loaded (or not) and
141         // what PIP configurations are loaded (or not).
142         // There is a synchronized lock used for access to the object.
143         //
144         private static volatile StdPDPStatus status = new StdPDPStatus();
145         private static final Object pdpStatusLock = new Object();
146         
147         private static final String ENVIORNMENT_HEADER = "Environment";
148         private static String environment = null;
149         //
150         // Queue of PUT requests
151         //
152         public static class PutRequest {
153                 public Properties policyProperties = null;
154                 public Properties pipConfigProperties = null;
155                 
156                 PutRequest(Properties policies, Properties pips) {
157                         this.policyProperties = policies;
158                         this.pipConfigProperties = pips;
159                 }
160         }
161         public static volatile BlockingQueue<PutRequest> queue = null;
162         // For notification Delay.
163         private static int notificationDelay = 0;
164         public static int getNotificationDelay(){
165                 return XACMLPdpServlet.notificationDelay;
166         }
167
168         private static String pdpResourceName;
169         private static String dependencyGroups = null;
170         private static String[] dependencyNodes = null;
171
172         //
173         // This is our configuration thread that attempts to load
174         // a new configuration request.
175         //
176         private Thread configThread = null;
177         private volatile boolean configThreadTerminate = false;
178     private ECOMPLoggingContext baseLoggingContext = null;
179         private IntegrityMonitor im;
180     /**
181      * Default constructor. 
182      */
183     public XACMLPdpServlet() {
184     }
185
186         /**
187          * @see Servlet#init(ServletConfig)
188          */
189         public void init(ServletConfig config) throws ServletException {
190                 //
191                 // Initialize
192                 //
193                 XACMLRest.xacmlInit(config);
194                 // Load the Notification Delay. 
195                 try{
196                         XACMLPdpServlet.notificationDelay = Integer.parseInt(XACMLProperties.getProperty(XACMLRestProperties.PROP_NOTIFICATION_DELAY));
197                 }catch(Exception e){
198                         logger.info("Notification Delay Not set. Keeping it 0 as default.");
199                 }
200                 // Load Queue size. 
201                 int queueSize = 5; // Set default Queue Size here. 
202                 queueSize = Integer.parseInt(XACMLProperties.getProperty("REQUEST_BUFFER_SIZE",String.valueOf(queueSize)));
203                 queue = new LinkedBlockingQueue<PutRequest>(queueSize);
204                 // Load our engine - this will use the latest configuration
205                 // that was saved to disk and set our initial status object.
206                 //
207                 PDPEngine engine = XACMLPdpLoader.loadEngine(XACMLPdpServlet.status, null, null);
208                 if (engine != null) {
209                         synchronized(pdpEngineLock) {
210                                 pdpEngine = engine;
211                         }
212                 }
213                 //
214                 // Logging stuff....
215                 //
216                 baseLoggingContext = new ECOMPLoggingContext();
217                 // fixed data that will be the same in all logging output goes here
218                 try {
219                         String hostname = InetAddress.getLocalHost().getCanonicalHostName();
220                         baseLoggingContext.setServer(hostname);
221                 } catch (UnknownHostException e) {
222                         logger.warn(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Unable to get hostname for logging");
223                 }
224
225                 Properties properties;
226                 try {
227                         properties = XACMLProperties.getProperties();
228                 } catch (IOException e) {
229                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e,
230                                         "Error loading properties with: XACMLProperties.getProperties()");
231                         throw new ServletException(e.getMessage(), e.getCause());
232                 }
233                 
234                 pdpResourceName = properties.getProperty(XACMLRestProperties.PDP_RESOURCE_NAME);
235                 if(pdpResourceName == null){
236                         PolicyLogger.error(MessageCodes.MISS_PROPERTY_ERROR, XACMLRestProperties.PDP_RESOURCE_NAME, "xacml.pdp");
237                         throw new ServletException("pdpResourceName is null");
238                 }
239
240                 dependencyGroups = properties.getProperty(IntegrityMonitorProperties.DEPENDENCY_GROUPS);
241                 if(dependencyGroups == null){
242                         PolicyLogger.error(MessageCodes.MISS_PROPERTY_ERROR, IntegrityMonitorProperties.DEPENDENCY_GROUPS, "xacml.pdp");
243                         throw new ServletException("dependency_groups is null");
244                 }
245                 // dependency_groups is a semicolon-delimited list of groups, and
246                 // each group is a comma-separated list of nodes. For our purposes
247                 // we just need a list of dependencies without regard to grouping,
248                 // so split the list into nodes separated by either comma or semicolon.
249                 dependencyNodes = dependencyGroups.split("[;,]");
250                 for (int i = 0 ; i < dependencyNodes.length ; i++){
251                         dependencyNodes[i] = dependencyNodes[i].trim();
252                 }
253
254
255                 // Create an IntegrityMonitor
256                 try {
257                         logger.info("Creating IntegrityMonitor");
258                         im = IntegrityMonitor.getInstance(pdpResourceName, properties);
259                 } catch (Exception e) { 
260                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "Failed to create IntegrityMonitor");
261                         throw new ServletException(e);
262                 }
263                 
264                 environment = XACMLProperties.getProperty("ENVIRONMENT", "DEVL");
265                 //
266                 // Kick off our thread to register with the PAP servlet.
267                 //
268                 if (Boolean.parseBoolean(XACMLProperties.getProperty(XACMLRestProperties.PROP_PDP_REGISTER))) {
269                         this.registerRunnable = new XACMLPdpRegisterThread(baseLoggingContext);
270                         this.registerThread = new Thread(this.registerRunnable);
271                         this.registerThread.start();
272                 }
273                 //
274                 // This is our thread that manages incoming configuration
275                 // changes.
276                 //
277                 this.configThread = new Thread(this);
278                 this.configThread.start();
279         }
280
281         /**
282          * @see Servlet#destroy()
283          */
284         public void destroy() {
285                 super.destroy();
286                 logger.info("Destroying....");
287                 //
288                 // Make sure the register thread is not running
289                 //
290                 if (this.registerRunnable != null) {
291                         try {
292                                 this.registerRunnable.terminate();
293                                 if (this.registerThread != null) {
294                                         this.registerThread.interrupt();
295                                         this.registerThread.join();
296                                 }
297                         } catch (InterruptedException e) {
298                                 logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + e);
299                                 PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "");
300                         }
301                 }
302                 //
303                 // Make sure the configure thread is not running
304                 //
305                 this.configThreadTerminate = true;
306                 try {
307                         this.configThread.interrupt();
308                         this.configThread.join();
309                 } catch (InterruptedException e) {
310                         logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + e);
311                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "");
312                 }
313                 logger.info("Destroyed.");
314         }
315
316         /**
317          * PUT - The PAP engine sends configuration information using HTTP PUT request.
318          * 
319          * One parameter is expected:
320          * 
321          * config=[policy|pip|all]
322          * 
323          *      policy - Expect a properties file that contains updated lists of the root and referenced policies that the PDP should
324          *                       be using for PEP requests.
325          * 
326          *              Specifically should AT LEAST contain the following properties:
327          *              xacml.rootPolicies
328          *              xacml.referencedPolicies
329          * 
330          *              In addition, any relevant information needed by the PDP to load or retrieve the policies to store in its cache.
331          *
332          *              EXAMPLE:
333          *                      xacml.rootPolicies=PolicyA.1, PolicyB.1
334          *
335          *                      PolicyA.1.url=http://localhost:9090/PAP?id=b2d7b86d-d8f1-4adf-ba9d-b68b2a90bee1&version=1
336          *                      PolicyB.1.url=http://localhost:9090/PAP/id=be962404-27f6-41d8-9521-5acb7f0238be&version=1
337          *      
338          *                      xacml.referencedPolicies=RefPolicyC.1, RefPolicyD.1
339          *
340          *                      RefPolicyC.1.url=http://localhost:9090/PAP?id=foobar&version=1
341          *                      RefPolicyD.1.url=http://localhost:9090/PAP/id=example&version=1
342          *      
343          * pip - Expect a properties file that contain PIP engine configuration properties.
344          * 
345          *              Specifically should AT LEAST the following property:
346          *                      xacml.pip.engines
347          * 
348          *              In addition, any relevant information needed by the PDP to load and configure the PIPs.
349          * 
350          *              EXAMPLE:
351          *                      xacml.pip.engines=foo,bar
352          * 
353          *                      foo.classname=com.foo
354          *                      foo.sample=abc
355          *                      foo.example=xyz
356          *                      ......
357          * 
358          *                      bar.classname=com.bar
359          *                      ......
360          * 
361          * all - Expect ALL new configuration properties for the PDP
362          * 
363          * @see HttpServlet#doPut(HttpServletRequest request, HttpServletResponse response)
364          */
365         protected void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
366                 ECOMPLoggingContext loggingContext = ECOMPLoggingUtils.getLoggingContextForRequest(request, baseLoggingContext);
367                 loggingContext.transactionStarted();
368                 if ((loggingContext.getRequestID() == null) || (loggingContext.getRequestID() == "")){
369                         UUID requestID = UUID.randomUUID();
370                         loggingContext.setRequestID(requestID.toString());
371                         PolicyLogger.info("requestID not provided in call to XACMLPdpSrvlet (doPut) so we generated one");
372                 } else {
373                         PolicyLogger.info("requestID was provided in call to XACMLPdpSrvlet (doPut)");
374                 }
375                                 loggingContext.metricStarted();
376                                 loggingContext.metricEnded();
377                                 PolicyLogger.metrics("Metric example posted here - 1 of 2");
378                                 loggingContext.metricStarted();
379                                 loggingContext.metricEnded();
380                                 PolicyLogger.metrics("Metric example posted here - 2 of 2");
381                 //
382                 // Dump our request out
383                 //
384                 if (logger.isDebugEnabled()) {
385                         XACMLRest.dumpRequest(request);
386                 }
387
388                 try {
389                         im.startTransaction();
390                 }
391                 catch (AdministrativeStateException | StandbyStatusException e) {
392                         String message = e.toString();
393                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message);
394                         loggingContext.transactionEnded();
395                         PolicyLogger.audit("Transaction Failed - See Error.log");
396                         response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
397                         return;
398                 }
399                 //
400                 // What is being PUT?
401                 //
402                 String cache = request.getParameter("cache");
403                 //
404                 // Should be a list of policy and pip configurations in Java properties format
405                 //
406                 if (cache != null && request.getContentType().equals("text/x-java-properties")) {
407                         loggingContext.setServiceName("PDP.putConfig");
408                         if (request.getContentLength() > Integer.parseInt(XACMLProperties.getProperty("MAX_CONTENT_LENGTH", DEFAULT_MAX_CONTENT_LENGTH))) {
409                                 String message = "Content-Length larger than server will accept.";
410                                 logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + message);
411                                 loggingContext.transactionEnded();
412                                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, message);
413                                 PolicyLogger.audit("Transaction Failed - See Error.log");
414                                 response.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
415                                 im.endTransaction();
416                                 return;
417                         }
418                         this.doPutConfig(cache, request, response, loggingContext);
419                         loggingContext.transactionEnded();
420                         PolicyLogger.audit("Transaction ended");
421
422                         im.endTransaction();
423                 } else {
424                         String message = "Invalid cache: '" + cache + "' or content-type: '" + request.getContentType() + "'";
425                         logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + message);
426                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message);
427                         loggingContext.transactionEnded();
428                         PolicyLogger.audit("Transaction Failed - See Error.log");
429                         response.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
430                         im.endTransaction();
431                         return;
432                 }
433         }
434         
435         protected void doPutConfig(String config, HttpServletRequest request, HttpServletResponse response, ECOMPLoggingContext loggingContext)  throws ServletException, IOException {
436                 try {
437                         // prevent multiple configuration changes from stacking up
438                         if (XACMLPdpServlet.queue.remainingCapacity() <= 0) {
439                                 logger.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Queue capacity reached");
440                                 PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, "Queue capacity reached");
441                                 loggingContext.transactionEnded();
442                                 PolicyLogger.audit("Transaction Failed - See Error.log");
443                                 response.sendError(HttpServletResponse.SC_CONFLICT, "Multiple configuration changes waiting processing.");
444                                 return;
445                         }
446                         //
447                         // Read the properties data into an object.
448                         //
449                         Properties newProperties = new Properties();
450                         newProperties.load(request.getInputStream());
451                         // should have something in the request
452                         if (newProperties.size() == 0) {
453                                 logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "No properties in PUT");
454                                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, "No properties in PUT");
455                                 loggingContext.transactionEnded();
456                                 PolicyLogger.audit("Transaction Failed - See Error.log");
457                                 response.sendError(HttpServletResponse.SC_BAD_REQUEST, "PUT must contain at least one property");
458                                 return;
459                         }
460                         //
461                         // Which set of properties are they sending us? Whatever they send gets
462                         // put on the queue (if there is room).
463                         // For audit logging purposes, we consider the transaction done once the
464                         // the request gets put on the queue.
465                         //
466                         if (config.equals("policies")) {
467                                 newProperties = XACMLProperties.getPolicyProperties(newProperties, true);
468                                 if (newProperties.size() == 0) {
469                                         logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "No policy properties in PUT");
470                                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, "No policy properties in PUT");
471                                         loggingContext.transactionEnded();
472                                         PolicyLogger.audit("Transaction Failed - See Error.log");
473                                         response.sendError(HttpServletResponse.SC_BAD_REQUEST, "PUT with cache=policies must contain at least one policy property");
474                                         return;
475                                 }
476                                 XACMLPdpServlet.queue.offer(new PutRequest(newProperties, null));
477                                 loggingContext.transactionEnded();
478                                 auditLogger.info("Success");
479                 PolicyLogger.audit("Success");
480                         } else if (config.equals("pips")) {
481                                 newProperties = XACMLProperties.getPipProperties(newProperties);
482                                 if (newProperties.size() == 0) {
483                                         logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "No pips properties in PUT");
484                                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, "No pips properties in PUT");
485                                         loggingContext.transactionEnded();
486                                         PolicyLogger.audit("Transaction Failed - See Error.log");
487                                         response.sendError(HttpServletResponse.SC_BAD_REQUEST, "PUT with cache=pips must contain at least one pip property");
488                                         return;
489                                 }
490                                 XACMLPdpServlet.queue.offer(new PutRequest(null, newProperties));
491                                 loggingContext.transactionEnded();
492                                 auditLogger.info("Success");
493                 PolicyLogger.audit("Success");
494                         } else if (config.equals("all")) {
495                                 Properties newPolicyProperties = XACMLProperties.getPolicyProperties(newProperties, true);
496                                 if (newPolicyProperties.size() == 0) {
497                                         logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "No policy properties in PUT");
498                                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, "No policy properties in PUT");
499                                         loggingContext.transactionEnded();
500                                         PolicyLogger.audit("Transaction Failed - See Error.log");
501                                         response.sendError(HttpServletResponse.SC_BAD_REQUEST, "PUT with cache=all must contain at least one policy property");
502                                         return;
503                                 }
504                                 Properties newPipProperties = XACMLProperties.getPipProperties(newProperties);
505                                 if (newPipProperties.size() == 0) {
506                                         logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "No pips properties in PUT");
507                                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, "No pips properties in PUT");
508                                         loggingContext.transactionEnded();
509                                         PolicyLogger.audit("Transaction Failed - See Error.log");
510                                         response.sendError(HttpServletResponse.SC_BAD_REQUEST, "PUT with cache=all must contain at least one pip property");
511                                         return;
512                                 }
513                                 XACMLPdpServlet.queue.offer(new PutRequest(newPolicyProperties, newPipProperties));
514                                 loggingContext.transactionEnded();
515                                 auditLogger.info("Success");
516                 PolicyLogger.audit("Success");
517                         } else {
518                                 //
519                                 // Invalid value
520                                 //
521                                 logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Invalid config value: " + config);
522                                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, "Invalid config value: " + config);
523                                 loggingContext.transactionEnded();
524                                 PolicyLogger.audit("Transaction Failed - See Error.log");
525                                 response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Config must be one of 'policies', 'pips', 'all'");
526                                 return;
527                         }
528                 } catch (Exception e) {
529                         logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Failed to process new configuration.", e);
530                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "Failed to process new configuration");
531                         loggingContext.transactionEnded();
532                         PolicyLogger.audit("Transaction Failed - See Error.log");
533                         response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
534                         return;
535                 }
536                 
537         }
538         
539         /**
540          * Parameters: type=hb|config|Status
541          * 
542          * 1. HeartBeat Status 
543          * HeartBeat
544          *              OK - All Policies are Loaded, All PIPs are Loaded
545          *      LOADING_IN_PROGRESS - Currently loading a new policy set/pip configuration
546          *      LAST_UPDATE_FAILED - Need to track the items that failed during last update
547          *      LOAD_FAILURE - ??? Need to determine what information is sent and how 
548          * 2. Configuration
549          * 3. Status
550          *              return the StdPDPStatus object in the Response content
551          * 
552          * 
553          * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
554          */
555         protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
556                 ECOMPLoggingContext loggingContext = ECOMPLoggingUtils.getLoggingContextForRequest(request, baseLoggingContext);
557                 loggingContext.transactionStarted();
558                 if ((loggingContext.getRequestID() == null) || (loggingContext.getRequestID() == "")){
559                         UUID requestID = UUID.randomUUID();
560                         loggingContext.setRequestID(requestID.toString());
561                         PolicyLogger.info("requestID not provided in call to XACMLPdpSrvlet (doGet) so we generated one");
562                 } else {
563                         PolicyLogger.info("requestID was provided in call to XACMLPdpSrvlet (doGet)");
564                 }
565                                 loggingContext.metricStarted();
566                                 loggingContext.metricEnded();
567                                 PolicyLogger.metrics("Metric example posted here - 1 of 2");
568                                 loggingContext.metricStarted();
569                                 loggingContext.metricEnded();
570                                 PolicyLogger.metrics("Metric example posted here - 2 of 2");
571
572                 XACMLRest.dumpRequest(request);
573
574                 String pathInfo = request.getRequestURI();
575                 if (pathInfo != null){
576                         // health check from Global Site Selector (iDNS).
577                         // DO NOT do a im.startTransaction for the test request
578                         if (pathInfo.equals("/pdp/test")) {
579                                 loggingContext.setServiceName("iDNS:PDP.test");
580                                 try {
581                                         im.evaluateSanity();
582                                         //If we make it this far, all is well
583                                         String message = "GET:/pdp/test called and PDP " + pdpResourceName + " is OK";
584                                         PolicyLogger.debug(message);
585                                         loggingContext.transactionEnded();
586                                         PolicyLogger.audit("Success");
587                                         response.setStatus(HttpServletResponse.SC_OK);
588                                         return;
589                                 } catch (ForwardProgressException fpe){
590                                         //No forward progress is being made
591                                         String message = "GET:/pdp/test called and PDP " + pdpResourceName + " is not making forward progress."
592                                                         + " Exception Message: " + fpe.getMessage();
593                                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message );
594                                         loggingContext.transactionEnded();
595                                         PolicyLogger.audit("Transaction Failed - See Error.log");
596                                         // PolicyLogger.audit(MessageCodes.ERROR_SYSTEM_ERROR, message );
597                                         response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
598                                         return;
599                                 }catch (AdministrativeStateException ase){
600                                         //Administrative State is locked
601                                         String message = "GET:/pdp/test called and PDP " + pdpResourceName + " Administrative State is LOCKED "
602                                                         + " Exception Message: " + ase.getMessage();
603                                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message );
604                                         loggingContext.transactionEnded();
605                                         PolicyLogger.audit("Transaction Failed - See Error.log");
606                                         response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
607                                         return;
608                                 }catch (StandbyStatusException sse){
609                                         //Administrative State is locked
610                                         String message = "GET:/pdp/test called and PDP " + pdpResourceName + " Standby Status is NOT PROVIDING SERVICE "
611                                                         + " Exception Message: " + sse.getMessage();
612                                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message );
613                                         loggingContext.transactionEnded();
614                                         PolicyLogger.audit("Transaction Failed - See Error.log");
615                                         response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
616                                         return;
617                                 } catch (Exception e) {
618                                         //A subsystem is not making progress or is not responding
619                                         String eMsg = e.getMessage();
620                                         if(eMsg == null){
621                                                 eMsg = "No Exception Message";
622                                         }
623                                         String message = "GET:/pdp/test called and PDP " + pdpResourceName + " has had a subsystem failure."
624                                                         + " Exception Message: " + eMsg;
625                                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message );
626                                         //Get the specific list of subsystems that failed
627                                         String failedNodeList = null;
628                                         for(String node : dependencyNodes){
629                                                 if(eMsg.contains(node)){
630                                                         if(failedNodeList == null){
631                                                                 failedNodeList = node;
632                                                         }else{
633                                                                 failedNodeList = failedNodeList.concat(","+node);
634                                                         }
635                                                 }
636                                         }
637                                         if(failedNodeList == null){
638                                                 failedNodeList = "UnknownSubSystem";
639                                         }
640                                         response.addHeader("X-ECOMP-SubsystemFailure", failedNodeList);
641                                         response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
642                                         loggingContext.transactionEnded();
643                                         PolicyLogger.audit("Transaction Failed - See Error.log");
644                                         return;
645                                 }
646                         }
647                 }
648                 
649                 try {
650                         im.startTransaction();
651                 }
652                 catch (AdministrativeStateException | StandbyStatusException e) {
653                         String message = e.toString();
654                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message);
655                         loggingContext.transactionEnded();
656                         PolicyLogger.audit("Transaction Failed - See Error.log");
657                         response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
658                         return;
659                 }
660                 //
661                 // What are they requesting?
662                 //
663                 boolean returnHB = false;
664                 response.setHeader("Cache-Control", "no-cache");
665                 String type = request.getParameter("type");
666                 // type might be null, so use equals on string constants
667                 if ("config".equals(type)) {
668                         loggingContext.setServiceName("PDP.getConfig");
669                         response.setContentType("text/x-java-properties");
670                         try {
671                         String lists = XACMLProperties.PROP_ROOTPOLICIES + "=" + XACMLProperties.getProperty(XACMLProperties.PROP_ROOTPOLICIES, "");
672                         lists = lists + "\n" + XACMLProperties.PROP_REFERENCEDPOLICIES + "=" + XACMLProperties.getProperty(XACMLProperties.PROP_REFERENCEDPOLICIES, "") + "\n";
673                         try (InputStream listInputStream = new ByteArrayInputStream(lists.getBytes());
674                                         InputStream pipInputStream = Files.newInputStream(XACMLPdpLoader.getPIPConfig());
675                                         OutputStream os = response.getOutputStream()) {
676                                 IOUtils.copy(listInputStream, os);
677                                 IOUtils.copy(pipInputStream, os);
678                                 }
679                         loggingContext.transactionEnded();
680                         auditLogger.info("Success");
681                 PolicyLogger.audit("Success");
682                 response.setStatus(HttpServletResponse.SC_OK);
683                         } catch (Exception e) {
684                                 logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Failed to copy property file", e);
685                                 PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "Failed to copy property file");
686                                 loggingContext.transactionEnded();
687                                 PolicyLogger.audit("Transaction Failed - See Error.log");
688                                 response.sendError(400, "Failed to copy Property file");
689                         }
690                         
691                 } else if ("hb".equals(type)) {
692                         returnHB = true;
693                         response.setStatus(HttpServletResponse.SC_NO_CONTENT);
694                         
695                 } else if ("Status".equals(type)) {
696                         loggingContext.setServiceName("PDP.getStatus");
697                         // convert response object to JSON and include in the response
698                         synchronized(pdpStatusLock) {
699                                 ObjectMapper mapper = new ObjectMapper();
700                     mapper.writeValue(response.getOutputStream(),  status);
701                         }
702             response.setStatus(HttpServletResponse.SC_OK);
703                         loggingContext.transactionEnded();
704                         auditLogger.info("Success");
705                 PolicyLogger.audit("Success");
706             
707                 } else {
708                         logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Invalid type value: " + type);
709                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, "Invalid type value: " + type);
710                         loggingContext.transactionEnded();
711                         PolicyLogger.audit("Transaction Failed - See Error.log");
712                         response.sendError(HttpServletResponse.SC_BAD_REQUEST, "type not 'config' or 'hb'");
713                 }
714                 if (returnHB) {
715                         synchronized(pdpStatusLock) {
716                                 response.addHeader(XACMLRestProperties.PROP_PDP_HTTP_HEADER_HB, status.getStatus().toString());
717                         }
718                 }
719                 loggingContext.transactionEnded();
720                 PolicyLogger.audit("Transaction Ended");
721                 im.endTransaction();
722
723         }
724
725         /**
726          * POST - We expect XACML requests to be posted by PEP applications. They can be in the form of XML or JSON according
727          * to the XACML 3.0 Specifications for both.
728          * 
729          * 
730          * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
731          */
732         protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
733
734                 ECOMPLoggingContext loggingContext = ECOMPLoggingUtils.getLoggingContextForRequest(request, baseLoggingContext);
735                 loggingContext.transactionStarted();
736                 loggingContext.setServiceName("PDP.decide");
737                 if ((loggingContext.getRequestID() == null) || (loggingContext.getRequestID() == "")){
738                         UUID requestID = UUID.randomUUID();
739                         loggingContext.setRequestID(requestID.toString());
740                         PolicyLogger.info("requestID not provided in call to XACMLPdpSrvlet (doPost) so we generated one");
741                 } else {
742                         PolicyLogger.info("requestID was provided in call to XACMLPdpSrvlet (doPost)");
743                 }
744                                 loggingContext.metricStarted();
745                                 loggingContext.metricEnded();
746                                 PolicyLogger.metrics("Metric example posted here - 1 of 2");
747                                 loggingContext.metricStarted();
748                                 loggingContext.metricEnded();
749                                 PolicyLogger.metrics("Metric example posted here - 2 of 2");
750                 monitor.pdpEvaluationAttempts();
751                 
752                 try {
753                         im.startTransaction();
754                 }
755                 catch (AdministrativeStateException | StandbyStatusException e) {
756                         String message = e.toString();
757                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message);
758                         loggingContext.transactionEnded();
759                         PolicyLogger.audit("Transaction Failed - See Error.log");
760                         response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
761                         return;
762                 }
763                 //
764                 // no point in doing any work if we know from the get-go that we cannot do anything with the request
765                 //
766                 if (status.getLoadedRootPolicies().size() == 0) {
767                         logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Request from PEP at " + request.getRequestURI() + " for service when PDP has No Root Policies loaded");
768                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, "Request from PEP at " + request.getRequestURI() + " for service when PDP has No Root Policies loaded");
769                         loggingContext.transactionEnded();
770                         PolicyLogger.audit("Transaction Failed - See Error.log");
771                         response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
772                         im.endTransaction();
773                         return;
774                 }
775                 
776                 XACMLRest.dumpRequest(request);
777                 //
778                 // Set our no-cache header
779                 //
780                 response.setHeader("Cache-Control", "no-cache");
781                 //
782                 // They must send a Content-Type
783                 //
784                 if (request.getContentType() == null) {
785                         logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Must specify a Content-Type");
786                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, "Must specify a Content-Type");
787                         loggingContext.transactionEnded();
788                         PolicyLogger.audit("Transaction Failed - See Error.log");
789                         response.sendError(HttpServletResponse.SC_BAD_REQUEST, "no content-type given");
790                         im.endTransaction();
791                         return;
792                 }
793                 //
794                 // Limit the Content-Length to something reasonable
795                 //
796                 if (request.getContentLength() > Integer.parseInt(XACMLProperties.getProperty("MAX_CONTENT_LENGTH", "32767"))) {
797                         String message = "Content-Length larger than server will accept.";
798                         logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + message);
799                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, message);
800                         loggingContext.transactionEnded();
801                         PolicyLogger.audit("Transaction Failed - See Error.log");
802                         response.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
803                         im.endTransaction();
804                         return;
805                 }
806                 if (request.getContentLength() <= 0) {
807                         String message = "Content-Length is negative";
808                         logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + message);
809                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, message);
810                         loggingContext.transactionEnded();
811                         PolicyLogger.audit("Transaction Failed - See Error.log");
812                         response.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
813                         im.endTransaction();
814                         return;
815                 }
816                 ContentType contentType = null;
817                 try {
818                         contentType = ContentType.parse(request.getContentType());
819                 }
820                 catch (Exception e) {
821                         String message = "Parsing Content-Type: " + request.getContentType() + ", error=" + e.getMessage();
822                         logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + message, e);
823                         loggingContext.transactionEnded();
824                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, message);
825                         PolicyLogger.audit("Transaction Failed - See Error.log");
826                         response.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
827                         im.endTransaction();
828                         return;
829                 }
830                 //
831                 // What exactly did they send us?
832                 //
833                 String incomingRequestString = null;
834                 Request pdpRequest = null;
835                 if (contentType.getMimeType().equalsIgnoreCase(ContentType.APPLICATION_JSON.getMimeType()) ||
836                                 contentType.getMimeType().equalsIgnoreCase(ContentType.APPLICATION_XML.getMimeType()) ||
837                                 contentType.getMimeType().equalsIgnoreCase("application/xacml+xml") ) {
838                         //
839                         // Read in the string
840                         //
841                         StringBuilder buffer = new StringBuilder();
842                         BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream()));
843                         String line;
844                         while((line = reader.readLine()) != null){
845                                 buffer.append(line);
846                         }
847                         incomingRequestString = buffer.toString();
848                         logger.info(incomingRequestString);
849                     //
850                         // Parse into a request
851                         //
852                         try {
853                                 if (contentType.getMimeType().equalsIgnoreCase(ContentType.APPLICATION_JSON.getMimeType())) {
854                                         pdpRequest = JSONRequest.load(incomingRequestString);
855                                 } else if (     contentType.getMimeType().equalsIgnoreCase(ContentType.APPLICATION_XML.getMimeType()) ||
856                                                         contentType.getMimeType().equalsIgnoreCase("application/xacml+xml")) {
857                                         pdpRequest = DOMRequest.load(incomingRequestString);
858                                 }
859                         }
860                         catch(Exception e) {
861                                 logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Could not parse request", e);
862                                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, "Could not parse request");
863                                 loggingContext.transactionEnded();
864                                 PolicyLogger.audit("Transaction Failed - See Error.log");
865                                 response.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
866                                 im.endTransaction();
867                                 return;
868                         }
869                 } else {
870                         String message = "unsupported content type" + request.getContentType();
871                         logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + message);
872                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, message);
873                         loggingContext.transactionEnded();
874                         PolicyLogger.audit("Transaction Failed - See Error.log");
875                         response.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
876                         im.endTransaction();
877                         return;
878                 }
879                 //
880                 // Did we successfully get and parse a request?
881                 //
882                 if (pdpRequest == null || pdpRequest.getRequestAttributes() == null || pdpRequest.getRequestAttributes().size() <= 0) {
883                         String message = "Zero Attributes found in the request";
884                         logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + message);
885                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, message);
886                         loggingContext.transactionEnded();
887                         PolicyLogger.audit("Transaction Failed - See Error.log");
888                         response.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
889                         im.endTransaction();
890                         return;
891                 }
892                 //
893                 // Run it
894                 //
895                 try {
896                         //
897                         // Authenticating the Request here. 
898                         //
899                         if(!authorizeRequest(request, pdpRequest)){
900                                 String message = "PEP not Authorized for making this Request!! \n Contact Administrator for this Scope. ";
901                                 logger.error(XACMLErrorConstants.ERROR_PERMISSIONS + message );
902                                 PolicyLogger.error(MessageCodes.ERROR_PERMISSIONS, message);
903                                 loggingContext.transactionEnded();
904                                 PolicyLogger.audit("Transaction Failed - See Error.log");
905                                 response.sendError(HttpServletResponse.SC_FORBIDDEN, message);
906                                 im.endTransaction();
907                                 return;
908                         }
909                         //
910                 // Get the pointer to the PDP Engine
911                 //
912                         PDPEngine myEngine = null;
913                         synchronized(pdpEngineLock) {
914                                 myEngine = this.pdpEngine;
915                         }
916                         if (myEngine == null) {
917                                 String message = "No engine loaded.";
918                                 logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + message);
919                                 PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message);
920                                 loggingContext.transactionEnded();
921                                 PolicyLogger.audit("Transaction Failed - See Error.log");
922                                 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
923                                 im.endTransaction();
924                                 return;
925                         }
926                         //
927                         // Send the request and save the response
928                         //
929                         long lTimeStart, lTimeEnd;
930                         Response pdpResponse    = null;
931
932 //TODO - Make this unnecessary
933 //TODO  It seems that the PDP Engine is not thread-safe, so when a configuration change occurs in the middle of processing
934 //TODO  a PEP Request, that Request fails (it throws a NullPointerException in the decide() method).
935 //TODO  Using synchronize will slow down processing of PEP requests, possibly by a significant amount.
936 //TODO  Since configuration changes are rare, it would be A Very Good Thing if we could eliminate this sychronized block.
937 //TODO
938 //TODO  This problem was found by starting one PDP then
939 //TODO          RestLoadTest switching between 2 configurations, 1 second apart
940 //TODO                  both configurations contain the datarouter policy
941 //TODO                  both configurations already have all policies cached in the PDPs config directory
942 //TODO          RestLoadTest started with the Datarouter test requests, 5 threads, no interval
943 //TODO  With that configuration this code (without the synchronized) throws a NullPointerException
944 //TODO  within a few seconds.
945 //
946 synchronized(pdpEngineLock) {
947         myEngine = this.pdpEngine;
948                         try {
949                                 PolicyList.clearPolicyList();
950                                 lTimeStart = System.currentTimeMillis();                
951                                 pdpResponse     = myEngine.decide(pdpRequest);
952                                 lTimeEnd = System.currentTimeMillis();
953                         } catch (PDPException e) {
954                                 String message = "Exception during decide: " + e.getMessage();
955                                 logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + message);
956                                 PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message);
957                                 loggingContext.transactionEnded();
958                                 PolicyLogger.audit("Transaction Failed - See Error.log");
959                                 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
960                                 im.endTransaction();
961                                 return;
962                         }
963 }
964                         monitor.computeLatency(lTimeEnd - lTimeStart);  
965                         requestLogger.info(lTimeStart + "=" + incomingRequestString);
966                         for(String policy : PolicyList.getpolicyList()){
967                                 monitor.policyCountAdd(policy, 1);
968                         }
969                         
970                         
971                         logger.info("PolicyID triggered in Request: " + PolicyList.getpolicyList());
972                         
973                         //need to go through the list and find out if the value is unique and then add it other wise 
974 //                      monitor.policyCountAdd(PolicyList.getpolicyList(), 1);
975         
976                         if (logger.isDebugEnabled()) {
977                                 logger.debug("Request time: " + (lTimeEnd - lTimeStart) + "ms");
978                         }
979                         //
980                         // Convert Response to appropriate Content-Type
981                         //
982                         if (pdpResponse == null) {
983                                 requestLogger.info(lTimeStart + "=" + "{}");
984                                 throw new Exception("Failed to get response from PDP engine.");
985                         }
986                         //
987                         // Set our content-type
988                         //
989                         response.setContentType(contentType.getMimeType());
990                         //
991                         // Convert the PDP response object to a String to
992                         // return to our caller as well as dump to our loggers.
993                         //
994                         String outgoingResponseString = "";
995                         if (contentType.getMimeType().equalsIgnoreCase(ContentType.APPLICATION_JSON.getMimeType())) {
996                                 //
997                                 // Get it as a String. This is not very efficient but we need to log our
998                                 // results for auditing.
999                                 //
1000                                 outgoingResponseString = JSONResponse.toString(pdpResponse, logger.isDebugEnabled());
1001                                 if (logger.isDebugEnabled()) {
1002                                         logger.debug(outgoingResponseString);
1003                                         //
1004                                         // Get rid of whitespace
1005                                         //
1006                                         outgoingResponseString = JSONResponse.toString(pdpResponse, false);
1007                                 }
1008                         } else if (     contentType.getMimeType().equalsIgnoreCase(ContentType.APPLICATION_XML.getMimeType()) ||
1009                                                 contentType.getMimeType().equalsIgnoreCase("application/xacml+xml")) {
1010                                 //
1011                                 // Get it as a String. This is not very efficient but we need to log our
1012                                 // results for auditing.
1013                                 //
1014                                 outgoingResponseString = DOMResponse.toString(pdpResponse, logger.isDebugEnabled());
1015                                 if (logger.isDebugEnabled()) {
1016                                         logger.debug(outgoingResponseString);
1017                                         //
1018                                         // Get rid of whitespace
1019                                         //
1020                                         outgoingResponseString = DOMResponse.toString(pdpResponse, false);
1021                                 }
1022                         }
1023                         //      adding the jmx values for NA, Permit and Deny
1024                         //
1025                         if (outgoingResponseString.contains("NotApplicable") || outgoingResponseString.contains("Decision not a Permit")){
1026                                 monitor.pdpEvaluationNA();
1027                         }
1028                         
1029                         if (outgoingResponseString.contains("Permit") && !outgoingResponseString.contains("Decision not a Permit")){
1030                                 monitor.pdpEvaluationPermit();
1031                         }
1032                         
1033                         if (outgoingResponseString.contains("Deny")){
1034                                 monitor.pdpEvaluationDeny();
1035                         }
1036                         //
1037                         // lTimeStart is used as an ID within the requestLogger to match up
1038                         // request's with responses.
1039                         //
1040                         requestLogger.info(lTimeStart + "=" + outgoingResponseString);
1041                         response.getWriter().print(outgoingResponseString);
1042                 }
1043                 catch (Exception e) {
1044                         String message = "Exception executing request: " + e;
1045                         logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + message, e);
1046                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, message);
1047                         loggingContext.transactionEnded();
1048                         PolicyLogger.audit("Transaction Failed - See Error.log");
1049                         response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
1050                         return;
1051                 }
1052                 
1053                 monitor.pdpEvaluationSuccess();
1054                 response.setStatus(HttpServletResponse.SC_OK);
1055
1056                 loggingContext.transactionEnded();
1057                 auditLogger.info("Success");
1058         PolicyLogger.audit("Success");
1059
1060 }
1061         
1062         /*
1063          * Added for Authorizing the PEP Requests for Environment check. 
1064          */
1065         private boolean authorizeRequest(HttpServletRequest request, Request pepRequest) {
1066                 if(request instanceof HttpServletRequest) {
1067                         // Get the client Credentials from the Request header. 
1068                         HttpServletRequest httpServletRequest = (HttpServletRequest) request;
1069                         String clientCredentials = httpServletRequest.getHeader(ENVIORNMENT_HEADER);
1070                         if(clientCredentials!=null && clientCredentials.equalsIgnoreCase(environment)){
1071                                 return true;
1072                         }else{
1073                                 return false;
1074                         }
1075                 }else{
1076                         return false;
1077                 }
1078         }
1079
1080         @Override
1081         public void run() {
1082                 //
1083                 // Keep running until we are told to terminate
1084                 //
1085                 try {
1086                         // variable not used, but constructor has needed side-effects so don't remove:
1087                         ECOMPLoggingContext loggingContext = new ECOMPLoggingContext(baseLoggingContext);
1088                         while (! this.configThreadTerminate) {
1089                                 PutRequest request = XACMLPdpServlet.queue.take();
1090                                 StdPDPStatus newStatus = new StdPDPStatus();
1091
1092 //TODO - This is related to the problem discussed in the doPost() method about the PDPEngine not being thread-safe.
1093 //TODO  See that discussion, and when the PDPEngine is made thread-safe it should be ok to move the loadEngine out of
1094 //TODO  the synchronized block.
1095 //TODO  However, since configuration changes should be rare we may not care about changing this.
1096 PDPEngine newEngine = null;
1097                                 synchronized(pdpStatusLock) {
1098                                         XACMLPdpServlet.status.setStatus(Status.UPDATING_CONFIGURATION);
1099 newEngine = XACMLPdpLoader.loadEngine(newStatus, request.policyProperties, request.pipConfigProperties);
1100                                 }
1101 //                              PDPEngine newEngine = XACMLPdpLoader.loadEngine(newStatus, request.policyProperties, request.pipConfigProperties);
1102                                 if (newEngine != null) {
1103                                         synchronized(XACMLPdpServlet.pdpEngineLock) {
1104                                                 this.pdpEngine = newEngine;
1105                                                 try {
1106                                                         logger.info("Saving configuration.");
1107                                                         if (request.policyProperties != null) {
1108                                                                 try (OutputStream os = Files.newOutputStream(XACMLPdpLoader.getPDPPolicyCache())) {
1109                                                                         request.policyProperties.store(os, "");
1110                                                                 }
1111                                                         }
1112                                                         if (request.pipConfigProperties != null) {
1113                                                                 try (OutputStream os = Files.newOutputStream(XACMLPdpLoader.getPIPConfig())) {
1114                                                                         request.pipConfigProperties.store(os, "");
1115                                                                 }
1116                                                         }
1117                                                         newStatus.setStatus(Status.UP_TO_DATE);
1118                                                 } catch (Exception e) {
1119                                                         logger.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Failed to store new properties.");
1120                                                         PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, "Failed to store new properties");
1121                                                         newStatus.setStatus(Status.LOAD_ERRORS);
1122                                                         newStatus.addLoadWarning("Unable to save configuration: " + e.getMessage());
1123                                                 }
1124                                         }
1125                                 } else {
1126                                         newStatus.setStatus(Status.LAST_UPDATE_FAILED);
1127                                 }
1128                                 synchronized(pdpStatusLock) {
1129                                         XACMLPdpServlet.status.set(newStatus);
1130                                 }
1131                         }
1132                 } catch (InterruptedException e) {
1133                         logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "interrupted");
1134                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, "interrupted");
1135                 }
1136         }       
1137
1138 }