From 7cf00931901b54b916a9e25f957bf7904aa9b068 Mon Sep 17 00:00:00 2001 From: "a.sreekumar" Date: Tue, 3 Sep 2019 14:44:15 +0000 Subject: Enable https support in ApexRestServer Enable https support in ApexRestServer by using the RestServer from policy-common Change-Id: I3dc8d88a499dfa9f0a82585a083526e236420c6e Issue-ID: POLICY-2016 Signed-off-by: a.sreekumar --- .../plugins-event-carrier-restserver/pom.xml | 5 ++ .../restserver/ApexRestServerAafFilter.java | 39 +++++++++++++ .../carrier/restserver/ApexRestServerConsumer.java | 49 +++++++++++------ .../RestServerCarrierTechnologyParameters.java | 35 +++--------- .../carrier/restserver/RestServerEndpoint.java | 64 ++++++++++++++++++++-- .../restserver/ApexRestServerConsumerTest.java | 2 +- .../RestServerCarrierTechnologyParametersTest.java | 61 +++++++++++++++++++++ 7 files changed, 204 insertions(+), 51 deletions(-) create mode 100644 plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/main/java/org/onap/policy/apex/plugins/event/carrier/restserver/ApexRestServerAafFilter.java (limited to 'plugins') diff --git a/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/pom.xml b/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/pom.xml index 4233c1973..ffd9f4563 100644 --- a/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/pom.xml +++ b/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/pom.xml @@ -50,6 +50,11 @@ jersey-container-servlet-core ${version.jersey} + + org.onap.policy.common + policy-endpoints + ${version.policy.common} + diff --git a/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/main/java/org/onap/policy/apex/plugins/event/carrier/restserver/ApexRestServerAafFilter.java b/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/main/java/org/onap/policy/apex/plugins/event/carrier/restserver/ApexRestServerAafFilter.java new file mode 100644 index 000000000..2c38cb489 --- /dev/null +++ b/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/main/java/org/onap/policy/apex/plugins/event/carrier/restserver/ApexRestServerAafFilter.java @@ -0,0 +1,39 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.apex.plugins.event.carrier.restserver; + +import org.onap.policy.common.endpoints.http.server.aaf.AafGranularAuthFilter; + +/** + * Class to manage aaf filters for Apex Rest Server. + * + * @author Ajith Sreekumar (ajith.sreekumar@est.tech) + */ +public class ApexRestServerAafFilter extends AafGranularAuthFilter { + + public static final String AAF_NODETYPE = "apex-rest-server"; + public static final String AAF_ROOT_PERMISSION = DEFAULT_NAMESPACE + "." + AAF_NODETYPE; + + @Override + public String getPermissionTypeRoot() { + return AAF_ROOT_PERMISSION; + } +} diff --git a/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/main/java/org/onap/policy/apex/plugins/event/carrier/restserver/ApexRestServerConsumer.java b/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/main/java/org/onap/policy/apex/plugins/event/carrier/restserver/ApexRestServerConsumer.java index a8c508659..c8a07f234 100644 --- a/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/main/java/org/onap/policy/apex/plugins/event/carrier/restserver/ApexRestServerConsumer.java +++ b/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/main/java/org/onap/policy/apex/plugins/event/carrier/restserver/ApexRestServerConsumer.java @@ -1,6 +1,7 @@ /*- * ============LICENSE_START======================================================= * Copyright (C) 2016-2018 Ericsson. All rights reserved. + * Modifications Copyright (C) 2019 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,17 +21,11 @@ package org.onap.policy.apex.plugins.event.carrier.restserver; -import java.net.URI; import java.util.EnumMap; import java.util.Map; import java.util.Properties; import java.util.concurrent.atomic.AtomicLong; - import javax.ws.rs.core.Response; - -import org.glassfish.grizzly.http.server.HttpServer; -import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory; -import org.glassfish.jersey.server.ResourceConfig; import org.onap.policy.apex.core.infrastructure.threading.ApplicationThreadFactory; import org.onap.policy.apex.core.infrastructure.threading.ThreadUtilities; import org.onap.policy.apex.service.engine.event.ApexEventConsumer; @@ -40,6 +35,9 @@ import org.onap.policy.apex.service.engine.event.PeeredReference; import org.onap.policy.apex.service.engine.event.SynchronousEventCache; import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerParameters; import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerPeeredMode; +import org.onap.policy.common.endpoints.http.server.HttpServletServer; +import org.onap.policy.common.endpoints.http.server.HttpServletServerFactoryInstance; +import org.onap.policy.common.gson.GsonMessageBodyHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -52,8 +50,6 @@ public class ApexRestServerConsumer implements ApexEventConsumer, Runnable { // Get a reference to the logger private static final Logger LOGGER = LoggerFactory.getLogger(ApexRestServerConsumer.class); - private static final String BASE_URI_TEMPLATE = "http://%s:%d/apex"; - // The amount of time to wait in milliseconds between checks that the consumer thread has stopped private static final long REST_SERVER_CONSUMER_WAIT_SLEEP_TIME = 50; @@ -71,7 +67,7 @@ public class ApexRestServerConsumer implements ApexEventConsumer, Runnable { private boolean stopOrderedFlag = false; // The local HTTP server to use for REST call reception if we are running a local Grizzly server - private HttpServer server; + private HttpServletServer server; // Holds the next identifier for event execution. private static AtomicLong nextExecutionID = new AtomicLong(0L); @@ -126,15 +122,11 @@ public class ApexRestServerConsumer implements ApexEventConsumer, Runnable { throw new ApexEventException(errorMessage); } - // Compose the URI for the standalone server - final String baseUrl = String.format(BASE_URI_TEMPLATE, restConsumerProperties.getHost(), - restConsumerProperties.getPort()); - // Instantiate the standalone server - final ResourceConfig rc = new ResourceConfig(RestServerEndpoint.class, AccessControlFilter.class); - server = GrizzlyHttpServerFactory.createHttpServer(URI.create(baseUrl), rc); - - while (!server.isStarted()) { + LOGGER.info("Creating the Apex Rest Server"); + createServer(restConsumerProperties); + server.start(); + while (!server.isAlive()) { ThreadUtilities.sleep(REST_SERVER_CONSUMER_WAIT_SLEEP_TIME); } } @@ -143,6 +135,26 @@ public class ApexRestServerConsumer implements ApexEventConsumer, Runnable { RestServerEndpoint.registerApexRestServerConsumer(this.name, this); } + private void createServer(RestServerCarrierTechnologyParameters restConsumerProperties) { + + server = HttpServletServerFactoryInstance.getServerFactory().build( + restConsumerProperties.getName(), + restConsumerProperties.isHttps(), + restConsumerProperties.getHost(), + restConsumerProperties.getPort(), null, true, false); + if (restConsumerProperties.isAaf()) { + server.addFilterClass(null, ApexRestServerAafFilter.class.getName()); + } + server.addServletClass(null, RestServerEndpoint.class.getName()); + server.addServletClass(null, AccessControlFilter.class.getName()); + server.setSerializationProvider(GsonMessageBodyHandler.class.getName()); + if (null != restConsumerProperties.getUserName() + && null != restConsumerProperties.getPassword()) { + server.setBasicAuthentication(restConsumerProperties.getUserName(), + restConsumerProperties.getPassword(), null); + } + } + /** * {@inheritDoc}. */ @@ -262,5 +274,8 @@ public class ApexRestServerConsumer implements ApexEventConsumer, Runnable { while (consumerThread.isAlive()) { ThreadUtilities.sleep(REST_SERVER_CONSUMER_WAIT_SLEEP_TIME); } + if (server != null) { + server.stop(); + } } } diff --git a/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/main/java/org/onap/policy/apex/plugins/event/carrier/restserver/RestServerCarrierTechnologyParameters.java b/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/main/java/org/onap/policy/apex/plugins/event/carrier/restserver/RestServerCarrierTechnologyParameters.java index 9a98588a5..42613bcf8 100644 --- a/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/main/java/org/onap/policy/apex/plugins/event/carrier/restserver/RestServerCarrierTechnologyParameters.java +++ b/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/main/java/org/onap/policy/apex/plugins/event/carrier/restserver/RestServerCarrierTechnologyParameters.java @@ -1,6 +1,7 @@ /*- * ============LICENSE_START======================================================= * Copyright (C) 2016-2018 Ericsson. All rights reserved. + * Modifications Copyright (C) 2019 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +21,7 @@ package org.onap.policy.apex.plugins.event.carrier.restserver; +import lombok.Getter; import org.onap.policy.apex.service.parameters.carriertechnology.CarrierTechnologyParameters; import org.onap.policy.common.parameters.GroupValidationResult; import org.onap.policy.common.parameters.ValidationStatus; @@ -40,6 +42,7 @@ import org.onap.policy.common.parameters.ValidationStatus; * * @author Liam Fallon (liam.fallon@ericsson.com) */ +@Getter public class RestServerCarrierTechnologyParameters extends CarrierTechnologyParameters { // @formatter:off private static final int MIN_USER_PORT = 1024; @@ -58,6 +61,10 @@ public class RestServerCarrierTechnologyParameters extends CarrierTechnologyPara private boolean standalone = false; private String host = null; private int port = -1; + private String userName; + private String password; + private boolean https; + private boolean aaf; // @formatter:on /** @@ -73,34 +80,6 @@ public class RestServerCarrierTechnologyParameters extends CarrierTechnologyPara this.setEventConsumerPluginClass(RESTSERVER_EVENT_CONSUMER_PLUGIN_CLASS); } - /** - * Check if the REST server is running in standalone mode or is using an underlying servlet infrastructure to manage - * requests. - * - * @return true if in standalone mode - */ - public boolean isStandalone() { - return standalone; - } - - /** - * Gets the host. - * - * @return the host - */ - public String getHost() { - return host; - } - - /** - * Gets the port. - * - * @return the port - */ - public int getPort() { - return port; - } - /** * {@inheritDoc}. */ diff --git a/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/main/java/org/onap/policy/apex/plugins/event/carrier/restserver/RestServerEndpoint.java b/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/main/java/org/onap/policy/apex/plugins/event/carrier/restserver/RestServerEndpoint.java index ca2d797b9..c4354918f 100644 --- a/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/main/java/org/onap/policy/apex/plugins/event/carrier/restserver/RestServerEndpoint.java +++ b/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/main/java/org/onap/policy/apex/plugins/event/carrier/restserver/RestServerEndpoint.java @@ -1,6 +1,7 @@ /*- * ============LICENSE_START======================================================= * Copyright (C) 2016-2018 Ericsson. All rights reserved. + * Modifications Copyright (C) 2019 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,9 +21,19 @@ package org.onap.policy.apex.plugins.event.carrier.restserver; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import io.swagger.annotations.Authorization; +import io.swagger.annotations.BasicAuthDefinition; +import io.swagger.annotations.Info; +import io.swagger.annotations.SecurityDefinition; +import io.swagger.annotations.SwaggerDefinition; +import io.swagger.annotations.Tag; +import java.net.HttpURLConnection; import java.util.LinkedHashMap; import java.util.Map; - import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.POST; @@ -32,7 +43,6 @@ import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -42,15 +52,35 @@ import org.slf4j.LoggerFactory; * * @author Liam Fallon (liam.fallon@ericsson.com) */ -@Path("/{eventInput}") +@Path("/apex/{eventInput}") +@Api(value = "APEX REST SERVER API") @Produces( { MediaType.APPLICATION_JSON }) @Consumes( { MediaType.APPLICATION_JSON }) +@SwaggerDefinition( + info = @Info(description = + "APEX RestServer that handles REST requests and responses to and from Apex.", version = "v1.0", + title = "APEX RESTSERVER"), + consumes = {MediaType.APPLICATION_JSON}, + produces = {MediaType.APPLICATION_JSON}, + schemes = {SwaggerDefinition.Scheme.HTTP, SwaggerDefinition.Scheme.HTTPS}, + tags = {@Tag(name = "APEX RESTSERVER", description = "APEX RESTSERVER")}, + securityDefinition = @SecurityDefinition(basicAuthDefinitions = {@BasicAuthDefinition(key = "basicAuth")})) public class RestServerEndpoint { // Get a reference to the logger private static final Logger LOGGER = LoggerFactory.getLogger(RestServerEndpoint.class); + public static final String AUTHORIZATION_TYPE = "basicAuth"; + + public static final int AUTHENTICATION_ERROR_CODE = HttpURLConnection.HTTP_UNAUTHORIZED; + public static final int AUTHORIZATION_ERROR_CODE = HttpURLConnection.HTTP_FORBIDDEN; + public static final int SERVER_ERROR_CODE = HttpURLConnection.HTTP_INTERNAL_ERROR; + + public static final String AUTHENTICATION_ERROR_MESSAGE = "Authentication Error"; + public static final String AUTHORIZATION_ERROR_MESSAGE = "Authorization Error"; + public static final String SERVER_ERROR_MESSAGE = "Internal Server Error"; + // Statistics on the amount of HTTP messages handled private static int getMessagesReceived = 0; private static int postEventMessagesReceived = 0; @@ -82,6 +112,14 @@ public class RestServerEndpoint { */ @Path("/Status") @GET + @ApiOperation( + value = "Get Statistics", + notes = "Get statistics on apex REST event handlin", + authorizations = @Authorization(value = AUTHORIZATION_TYPE)) + @ApiResponses( + value = {@ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE), + @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE), + @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)}) public Response serviceGetStats() { incrementGetMessages(); return Response.status(Response.Status.OK.getStatusCode()) @@ -92,13 +130,21 @@ public class RestServerEndpoint { } /** - * Service post request, an incoming event over RETS to Apex. + * Service post request, an incoming event over REST to Apex. * * @param jsonString the JSON string containing the data coming in on the REST call * @return the response event to the request */ @Path("/EventIn") @POST + @ApiOperation( + value = "Post Event", + notes = "Service post request, an incoming event over REST to Apex", + authorizations = @Authorization(value = AUTHORIZATION_TYPE)) + @ApiResponses( + value = {@ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE), + @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE), + @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)}) public Response servicePostRequest(final String jsonString) { incrementPostEventMessages(); @@ -112,13 +158,21 @@ public class RestServerEndpoint { } /** - * Service put request, an incoming event over RETS to Apex. + * Service put request, an incoming event over REST to Apex. * * @param jsonString the JSON string containing the data coming in on the REST call * @return the response event to the request */ @Path("/EventIn") @PUT + @ApiOperation( + value = "Put Event", + notes = "Service put request, an incoming event over REST to Apex", + authorizations = @Authorization(value = AUTHORIZATION_TYPE)) + @ApiResponses( + value = {@ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE), + @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE), + @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)}) public Response servicePutRequest(final String jsonString) { incrementPutEventMessages(); diff --git a/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/test/java/org/onap/policy/apex/plugins/event/carrier/restserver/ApexRestServerConsumerTest.java b/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/test/java/org/onap/policy/apex/plugins/event/carrier/restserver/ApexRestServerConsumerTest.java index 02daed02e..07f705cc6 100644 --- a/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/test/java/org/onap/policy/apex/plugins/event/carrier/restserver/ApexRestServerConsumerTest.java +++ b/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/test/java/org/onap/policy/apex/plugins/event/carrier/restserver/ApexRestServerConsumerTest.java @@ -93,7 +93,7 @@ public class ApexRestServerConsumerTest { incomingEventReceiver); } - @Test(expected = IllegalStateException.class) + @Test(expected = IllegalArgumentException.class) public void testInitWithSynchronousModeAndProperValues() throws ApexEventException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { diff --git a/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/test/java/org/onap/policy/apex/plugins/event/carrier/restserver/RestServerCarrierTechnologyParametersTest.java b/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/test/java/org/onap/policy/apex/plugins/event/carrier/restserver/RestServerCarrierTechnologyParametersTest.java index dbe20c960..2c8a764e8 100644 --- a/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/test/java/org/onap/policy/apex/plugins/event/carrier/restserver/RestServerCarrierTechnologyParametersTest.java +++ b/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/test/java/org/onap/policy/apex/plugins/event/carrier/restserver/RestServerCarrierTechnologyParametersTest.java @@ -86,4 +86,65 @@ public class RestServerCarrierTechnologyParametersTest { assertFalse(result.isValid()); } + @Test + public void testValidateWithValidValues() throws NoSuchFieldException, SecurityException, + IllegalArgumentException, IllegalAccessException { + + Field field = RestServerCarrierTechnologyParameters.class.getDeclaredField("standalone"); + field.setAccessible(true); + field.set(restServerCarrierTechnologyParameters, true); + field = RestServerCarrierTechnologyParameters.class.getDeclaredField("host"); + field.setAccessible(true); + field.set(restServerCarrierTechnologyParameters, "localhost"); + field = RestServerCarrierTechnologyParameters.class.getDeclaredField("port"); + field.setAccessible(true); + field.set(restServerCarrierTechnologyParameters, 6969); + field = RestServerCarrierTechnologyParameters.class.getDeclaredField("userName"); + field.setAccessible(true); + field.set(restServerCarrierTechnologyParameters, "username"); + field = RestServerCarrierTechnologyParameters.class.getDeclaredField("password"); + field.setAccessible(true); + field.set(restServerCarrierTechnologyParameters, "password"); + field = RestServerCarrierTechnologyParameters.class.getDeclaredField("https"); + field.setAccessible(true); + field.set(restServerCarrierTechnologyParameters, true); + field = RestServerCarrierTechnologyParameters.class.getDeclaredField("aaf"); + field.setAccessible(true); + field.set(restServerCarrierTechnologyParameters, true); + result = restServerCarrierTechnologyParameters.validate(); + assertNotNull(result); + assertTrue(result.isValid()); + } + + @Test + public void testValidateWithInvalidValues() throws NoSuchFieldException, SecurityException, + IllegalArgumentException, IllegalAccessException { + + Field field = RestServerCarrierTechnologyParameters.class.getDeclaredField("standalone"); + field.setAccessible(true); + field.set(restServerCarrierTechnologyParameters, false); + field = RestServerCarrierTechnologyParameters.class.getDeclaredField("host"); + field.setAccessible(true); + field.set(restServerCarrierTechnologyParameters, "localhost"); + field = RestServerCarrierTechnologyParameters.class.getDeclaredField("port"); + field.setAccessible(true); + field.set(restServerCarrierTechnologyParameters, 6969); + field = RestServerCarrierTechnologyParameters.class.getDeclaredField("userName"); + field.setAccessible(true); + field.set(restServerCarrierTechnologyParameters, "username"); + field = RestServerCarrierTechnologyParameters.class.getDeclaredField("password"); + field.setAccessible(true); + field.set(restServerCarrierTechnologyParameters, "password"); + field = RestServerCarrierTechnologyParameters.class.getDeclaredField("https"); + field.setAccessible(true); + field.set(restServerCarrierTechnologyParameters, true); + field = RestServerCarrierTechnologyParameters.class.getDeclaredField("aaf"); + field.setAccessible(true); + field.set(restServerCarrierTechnologyParameters, true); + result = restServerCarrierTechnologyParameters.validate(); + assertNotNull(result); + assertFalse(result.isValid()); + assertTrue(result.getResult().contains("host is specified only in standalone mode")); + assertTrue(result.getResult().contains("port is specified only in standalone mode")); + } } -- cgit 1.2.3-korg