XACML Platform Enhancements
[policy/engine.git] / ONAP-PDP-REST / src / main / java / org / onap / policy / pdp / rest / api / services / GetDecisionService.java
index a74203c..5b1b0ba 100644 (file)
@@ -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.
  * 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<String,String> decisionAttributes = null;
-    
-    public GetDecisionService(
-            DecisionRequestParameters decisionRequestParameters,
-            String requestID) {
+    private Map<String, String> 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<PDPResponse> 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<PDPResponse> 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<String,String> key : decisionAttributes.entrySet()) {
-            if (key.getKey().isEmpty()) {
-                String message = XACMLErrorConstants.ERROR_DATA_ISSUE + "Cannot have an Empty Key";
-                LOGGER.error(message);
-                throw new PolicyDecisionException(message);
+        for (Entry<String, String> 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;
+    }
+
+}