Update xacml-pdp for checkstyle 8.43
[policy/xacml-pdp.git] / main / src / main / java / org / onap / policy / pdpx / main / rest / XacmlPdpRestController.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved.
4  * Modifications Copyright (C) 2021 Nordix Foundation.
5  * ================================================================================
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * SPDX-License-Identifier: Apache-2.0
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.policy.pdpx.main.rest;
23
24 import com.att.research.xacml.api.Request;
25 import io.swagger.annotations.Api;
26 import io.swagger.annotations.ApiOperation;
27 import io.swagger.annotations.ApiParam;
28 import io.swagger.annotations.ApiResponse;
29 import io.swagger.annotations.ApiResponses;
30 import io.swagger.annotations.Authorization;
31 import io.swagger.annotations.BasicAuthDefinition;
32 import io.swagger.annotations.Extension;
33 import io.swagger.annotations.ExtensionProperty;
34 import io.swagger.annotations.Info;
35 import io.swagger.annotations.ResponseHeader;
36 import io.swagger.annotations.SecurityDefinition;
37 import io.swagger.annotations.SwaggerDefinition;
38 import java.util.UUID;
39 import javax.servlet.http.HttpServletRequest;
40 import javax.ws.rs.Consumes;
41 import javax.ws.rs.GET;
42 import javax.ws.rs.HeaderParam;
43 import javax.ws.rs.POST;
44 import javax.ws.rs.Path;
45 import javax.ws.rs.Produces;
46 import javax.ws.rs.core.Context;
47 import javax.ws.rs.core.MediaType;
48 import javax.ws.rs.core.Response;
49 import javax.ws.rs.core.Response.ResponseBuilder;
50 import org.onap.policy.common.endpoints.report.HealthCheckReport;
51 import org.onap.policy.models.decisions.concepts.DecisionException;
52 import org.onap.policy.models.decisions.concepts.DecisionRequest;
53 import org.onap.policy.models.decisions.concepts.DecisionResponse;
54 import org.onap.policy.models.errors.concepts.ErrorResponse;
55 import org.onap.policy.pdpx.main.rest.model.StatisticsReport;
56 import org.onap.policy.pdpx.main.rest.provider.DecisionProvider;
57 import org.onap.policy.pdpx.main.rest.provider.HealthCheckProvider;
58 import org.onap.policy.pdpx.main.rest.provider.StatisticsProvider;
59 import org.slf4j.Logger;
60 import org.slf4j.LoggerFactory;
61
62 /**
63  * Class to provide xacml pdp REST services.
64  *
65  */
66 @Path("/policy/pdpx/v1")
67 @Api
68 @Produces({MediaType.APPLICATION_JSON, XacmlPdpRestController.APPLICATION_YAML})
69 @Consumes({MediaType.APPLICATION_JSON, XacmlPdpRestController.APPLICATION_YAML})
70 @SwaggerDefinition(info = @Info(description = "Policy Xacml PDP Service", version = "1.0.0", title = "Policy Xacml PDP",
71         extensions = {
72             @Extension(
73                 properties = {
74                     @ExtensionProperty(name = "planned-retirement-date", value = "tbd"),
75                     @ExtensionProperty(name = "component", value = "Policy Framework")
76                 })
77             }),
78         schemes = {SwaggerDefinition.Scheme.HTTP, SwaggerDefinition.Scheme.HTTPS},
79         securityDefinition = @SecurityDefinition(basicAuthDefinitions = {@BasicAuthDefinition(key = "basicAuth")}))
80 public class XacmlPdpRestController {
81     private static final Logger LOGGER = LoggerFactory.getLogger(XacmlPdpRestController.class);
82     public static final String APPLICATION_YAML = "application/yaml";
83     public static final String APPLICATION_XACML_JSON = "application/xacml+json";
84     public static final String APPLICATION_XACML_XML = "application/xacml+xml";
85
86     @GET
87     @Path("/healthcheck")
88     @ApiOperation(value = "Perform a system healthcheck",
89             notes = "Provides healthy status of the Policy Xacml PDP component", response = HealthCheckReport.class,
90             responseHeaders = {
91                 @ResponseHeader(name = "X-MinorVersion",
92                             description = "Used to request or communicate a MINOR version back from the client"
93                                     + " to the server, and from the server back to the client",
94                             response = String.class),
95                 @ResponseHeader(name = "X-PatchVersion",
96                             description = "Used only to communicate a PATCH version in a response for"
97                                     + " troubleshooting purposes only, and will not be provided by"
98                                     + " the client on request",
99                             response = String.class),
100                 @ResponseHeader(name = "X-LatestVersion",
101                             description = "Used only to communicate an API's latest version", response = String.class),
102                 @ResponseHeader(name = "X-ONAP-RequestID",
103                             description = "Used to track REST transactions for logging purpose",
104                             response = UUID.class)},
105             authorizations = @Authorization(value = "basicAuth"), tags = {"HealthCheck", },
106             extensions = {
107                 @Extension(name = "interface info",
108                     properties = {
109                         @ExtensionProperty(name = "pdpx-version", value = "1.0.0"),
110                         @ExtensionProperty(name = "last-mod-release", value = "Dublin")
111                     })
112                 })
113     @ApiResponses(value = {
114         @ApiResponse(code = 401, message = "Authentication Error"),
115         @ApiResponse(code = 403, message = "Authorization Error"),
116         @ApiResponse(code = 500, message = "Internal Server Error")})
117     public Response healthcheck(
118             @HeaderParam("X-ONAP-RequestID") @ApiParam("RequestID for http transaction") UUID requestId) {
119         return addLoggingHeaders(addVersionControlHeaders(Response.status(Response.Status.OK)), requestId)
120                 .entity(new HealthCheckProvider().performHealthCheck()).build();
121     }
122
123     @GET
124     @Path("/statistics")
125     @ApiOperation(value = "Fetch current statistics",
126             notes = "Provides current statistics of the Policy Xacml PDP component", response = StatisticsReport.class,
127             responseHeaders = {
128                 @ResponseHeader(name = "X-MinorVersion",
129                             description = "Used to request or communicate a MINOR version back from the client"
130                                     + " to the server, and from the server back to the client",
131                             response = String.class),
132                 @ResponseHeader(name = "X-PatchVersion",
133                             description = "Used only to communicate a PATCH version in a response for"
134                                     + " troubleshooting purposes only, and will not be provided by"
135                                     + " the client on request",
136                             response = String.class),
137                 @ResponseHeader(name = "X-LatestVersion",
138                             description = "Used only to communicate an API's latest version", response = String.class),
139                 @ResponseHeader(name = "X-ONAP-RequestID",
140                             description = "Used to track REST transactions for logging purpose",
141                             response = UUID.class)},
142             authorizations = @Authorization(value = "basicAuth"), tags = {"Statistics", },
143             extensions = {
144                 @Extension(name = "interface info",
145                     properties = {
146                         @ExtensionProperty(name = "pdpx-version", value = "1.0.0"),
147                         @ExtensionProperty(name = "last-mod-release", value = "Dublin")
148                     })
149                 })
150     @ApiResponses(value = {
151         @ApiResponse(code = 401, message = "Authentication Error"),
152         @ApiResponse(code = 403, message = "Authorization Error"),
153         @ApiResponse(code = 500, message = "Internal Server Error")})
154     public Response statistics(
155             @HeaderParam("X-ONAP-RequestID") @ApiParam("RequestID for http transaction") UUID requestId) {
156         return addLoggingHeaders(addVersionControlHeaders(Response.status(Response.Status.OK)), requestId)
157                 .entity(new StatisticsProvider().fetchCurrentStatistics()).build();
158     }
159
160     /**
161      * Our decision entry point.
162      *
163      * @param body Should be a DecisionRequest object
164      * @param requestId Unique request id
165      * @return DecisionResponse or ErrorResponse object
166      */
167     @POST
168     @Path("/decision")
169     @ApiOperation(value = "Fetch the decision using specified decision parameters",
170             notes = "Returns the policy decision from Policy Xacml PDP", response = DecisionResponse.class,
171             responseHeaders = {
172                 @ResponseHeader(name = "X-MinorVersion",
173                             description = "Used to request or communicate a MINOR version back from the client"
174                                     + " to the server, and from the server back to the client",
175                             response = String.class),
176                 @ResponseHeader(name = "X-PatchVersion",
177                             description = "Used only to communicate a PATCH version in a response for"
178                                     + " troubleshooting purposes only, and will not be provided by"
179                                     + " the client on request",
180                             response = String.class),
181                 @ResponseHeader(name = "X-LatestVersion",
182                             description = "Used only to communicate an API's latest version", response = String.class),
183                 @ResponseHeader(name = "X-ONAP-RequestID",
184                             description = "Used to track REST transactions for logging purpose",
185                             response = UUID.class)},
186             authorizations = @Authorization(value = "basicAuth"), tags = {"Decision", },
187             extensions = {
188                 @Extension(name = "interface info",
189                     properties = {
190                         @ExtensionProperty(name = "pdpx-version", value = "1.0.0"),
191                         @ExtensionProperty(name = "last-mod-release", value = "Dublin")
192                     })
193                 })
194     @ApiResponses(value = {
195         @ApiResponse(code = 400, message = "Bad Request", response = ErrorResponse.class),
196         @ApiResponse(code = 401, message = "Authentication Error"),
197         @ApiResponse(code = 403, message = "Authorization Error"),
198         @ApiResponse(code = 500, message = "Internal Server Error")})
199     public Response decision(DecisionRequest body,
200             @HeaderParam("X-ONAP-RequestID") @ApiParam("RequestID for http transaction") UUID requestId,
201             @Context HttpServletRequest request) {
202         try {
203             return addLoggingHeaders(addVersionControlHeaders(Response.status(Response.Status.OK)), requestId)
204                     .entity(new DecisionProvider().fetchDecision(body, request.getParameterMap())).build();
205         } catch (DecisionException e) {
206             LOGGER.error("Decision exception", e);
207             XacmlPdpStatisticsManager.getCurrent().updateErrorCount();
208             return addLoggingHeaders(
209                     addVersionControlHeaders(Response.status((e.getErrorResponse().getResponseCode()))), requestId)
210                     .entity(e.getErrorResponse()).build();
211         }
212     }
213
214     /**
215      * Our native decision entry point.
216      *
217      * @param body Should be an Xacml Request object
218      * @param requestId Unique request id
219      * @return Xacml Response or ErrorResponse object
220      */
221     @POST
222     @Path("/xacml")
223     @Produces({XacmlPdpRestController.APPLICATION_XACML_JSON, XacmlPdpRestController.APPLICATION_XACML_XML})
224     @Consumes({XacmlPdpRestController.APPLICATION_XACML_JSON, XacmlPdpRestController.APPLICATION_XACML_XML})
225     @ApiOperation(value = "Fetch the decision using specified decision parameters",
226             notes = "Returns the policy decision from Policy Xacml PDP",
227             response = com.att.research.xacml.api.Response.class,
228             responseHeaders = {
229                 @ResponseHeader(name = "X-MinorVersion",
230                             description = "Used to request or communicate a MINOR version back from the client"
231                                     + " to the server, and from the server back to the client",
232                             response = String.class),
233                 @ResponseHeader(name = "X-PatchVersion",
234                             description = "Used only to communicate a PATCH version in a response for"
235                                     + " troubleshooting purposes only, and will not be provided by"
236                                     + " the client on request",
237                             response = String.class),
238                 @ResponseHeader(name = "X-LatestVersion",
239                             description = "Used only to communicate an API's latest version", response = String.class),
240                 @ResponseHeader(name = "X-ONAP-RequestID",
241                             description = "Used to track REST transactions for logging purpose",
242                             response = UUID.class)},
243             authorizations = @Authorization(value = "basicAuth"), tags = {"Decision", },
244             extensions = {
245                 @Extension(name = "interface info",
246                     properties = {
247                         @ExtensionProperty(name = "pdpx-version", value = "1.0.0"),
248                         @ExtensionProperty(name = "last-mod-release", value = "Frankfurt")
249                     })
250                 })
251     @ApiResponses(value = {
252         @ApiResponse(code = 400, message = "Bad Request", response = ErrorResponse.class),
253         @ApiResponse(code = 401, message = "Authentication Error"),
254         @ApiResponse(code = 403, message = "Authorization Error"),
255         @ApiResponse(code = 500, message = "Internal Server Error")})
256     public Response xacml(Request body,
257             @HeaderParam("X-ONAP-RequestID") @ApiParam("RequestID for http transaction") UUID requestId) {
258         try {
259             return addLoggingHeaders(addVersionControlHeaders(Response.status(Response.Status.OK)), requestId)
260                     .entity(new DecisionProvider().fetchNativeDecision(body)).build();
261         } catch (DecisionException e) {
262             LOGGER.error("Decision exception", e);
263             XacmlPdpStatisticsManager.getCurrent().updateErrorCount();
264             return addLoggingHeaders(
265                     addVersionControlHeaders(Response.status((e.getErrorResponse().getResponseCode()))), requestId)
266                     .entity(e.getErrorResponse()).build();
267         }
268     }
269
270     private ResponseBuilder addVersionControlHeaders(ResponseBuilder rb) {
271         return rb.header("X-MinorVersion", "0").header("X-PatchVersion", "0").header("X-LatestVersion", "1.0.0");
272     }
273
274     private ResponseBuilder addLoggingHeaders(ResponseBuilder rb, UUID requestId) {
275         if (requestId == null) {
276             // Generate a random uuid if client does not embed requestId in rest request
277             return rb.header("X-ONAP-RequestID", UUID.randomUUID());
278         }
279         return rb.header("X-ONAP-RequestID", requestId);
280     }
281 }