From 8cb2c97c400b30fb71a89aefaf19f247b450d49f Mon Sep 17 00:00:00 2001 From: Fiete Ostkamp Date: Sun, 20 Oct 2024 20:15:17 +0200 Subject: Clean up babel GenerateArtifactsService - rename GenerateArtifactsService to Controller - move request logging into central request filter - move request authentication into central request filter - constructor-inject gson to avoid creating the mapper on each request Issue-ID: AAI-4021 Change-Id: Ifb95644858ddf4b3364e08291d1685da469edd71 Signed-off-by: Fiete Ostkamp --- .../org/onap/aai/babel/JerseyConfiguration.java | 7 +- .../org/onap/aai/babel/config/MappingConfig.java | 36 ++++ .../babel/filters/AuthenticationRequestFilter.java | 72 +++++++ .../aai/babel/filters/LoggingRequestFilter.java | 85 +++++++++ .../java/org/onap/aai/babel/logging/LogHelper.java | 5 +- .../org/onap/aai/babel/request/RequestHeaders.java | 6 + .../babel/service/GenerateArtifactsController.java | 46 +++++ .../service/GenerateArtifactsControllerImpl.java | 165 ++++++++++++++++ .../babel/service/GenerateArtifactsService.java | 46 ----- .../service/GenerateArtifactsServiceImpl.java | 212 --------------------- src/main/resources/babel-beans.xml | 3 + 11 files changed, 420 insertions(+), 263 deletions(-) create mode 100644 src/main/java/org/onap/aai/babel/config/MappingConfig.java create mode 100644 src/main/java/org/onap/aai/babel/filters/AuthenticationRequestFilter.java create mode 100644 src/main/java/org/onap/aai/babel/filters/LoggingRequestFilter.java create mode 100644 src/main/java/org/onap/aai/babel/service/GenerateArtifactsController.java create mode 100644 src/main/java/org/onap/aai/babel/service/GenerateArtifactsControllerImpl.java delete mode 100644 src/main/java/org/onap/aai/babel/service/GenerateArtifactsService.java delete mode 100644 src/main/java/org/onap/aai/babel/service/GenerateArtifactsServiceImpl.java (limited to 'src/main') diff --git a/src/main/java/org/onap/aai/babel/JerseyConfiguration.java b/src/main/java/org/onap/aai/babel/JerseyConfiguration.java index 16a7aa0..84cda4d 100644 --- a/src/main/java/org/onap/aai/babel/JerseyConfiguration.java +++ b/src/main/java/org/onap/aai/babel/JerseyConfiguration.java @@ -22,7 +22,7 @@ package org.onap.aai.babel; import javax.ws.rs.ApplicationPath; import org.glassfish.jersey.server.ResourceConfig; -import org.onap.aai.babel.service.GenerateArtifactsServiceImpl; +import org.onap.aai.babel.service.GenerateArtifactsControllerImpl; import org.onap.aai.babel.service.InfoService; import org.springframework.context.annotation.Configuration; @@ -31,8 +31,9 @@ import org.springframework.context.annotation.Configuration; public class JerseyConfiguration extends ResourceConfig { public JerseyConfiguration() { - register(GenerateArtifactsServiceImpl.class); - register(InfoService.class); + packages("org.onap.aai.babel"); + // register(GenerateArtifactsControllerImpl.class); + // register(InfoService.class); } } diff --git a/src/main/java/org/onap/aai/babel/config/MappingConfig.java b/src/main/java/org/onap/aai/babel/config/MappingConfig.java new file mode 100644 index 0000000..321f86e --- /dev/null +++ b/src/main/java/org/onap/aai/babel/config/MappingConfig.java @@ -0,0 +1,36 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2024 Deutsche Telekom. 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. + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.aai.babel.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +@Configuration +public class MappingConfig { + + @Bean + public Gson gson() { + return new GsonBuilder().disableHtmlEscaping().create(); + } +} diff --git a/src/main/java/org/onap/aai/babel/filters/AuthenticationRequestFilter.java b/src/main/java/org/onap/aai/babel/filters/AuthenticationRequestFilter.java new file mode 100644 index 0000000..deeafb0 --- /dev/null +++ b/src/main/java/org/onap/aai/babel/filters/AuthenticationRequestFilter.java @@ -0,0 +1,72 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2024 Deutsche Telekom. 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. + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.aai.babel.filters; + +import org.onap.aai.auth.AAIMicroServiceAuth; +import org.onap.aai.auth.AAIMicroServiceAuthCore.HTTP_METHODS; +import org.onap.aai.babel.logging.ApplicationMsgs; +import org.onap.aai.babel.logging.LogHelper; +import org.springframework.stereotype.Component; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.ext.Provider; +import javax.ws.rs.core.PathSegment; +import javax.ws.rs.core.Response; + +import java.io.IOException; +import java.util.List; + +@Slf4j +@Component +@Provider +@RequiredArgsConstructor +public class AuthenticationRequestFilter implements ContainerRequestFilter { + + private static final LogHelper applicationLogger = LogHelper.INSTANCE; + private final AAIMicroServiceAuth authService; + private final HttpServletRequest servletRequest; + + @Override + public void filter(ContainerRequestContext requestContext) throws IOException { + List pathSegments = requestContext.getUriInfo().getPathSegments(); + String lastPathSegment = pathSegments.isEmpty() ? "" : pathSegments.get(pathSegments.size() - 1).getPath(); + + try { + HTTP_METHODS method = HTTP_METHODS.valueOf(requestContext.getMethod()); + boolean authorized = authService.validateRequest(null, servletRequest, + method, lastPathSegment); + if (!authorized) { + requestContext.abortWith(Response.status(Status.FORBIDDEN).build()); + } + } catch (Exception e) { + applicationLogger.error(ApplicationMsgs.PROCESS_REQUEST_ERROR, e); + applicationLogger.logAuditError(e); + requestContext.abortWith(Response.status(Status.FORBIDDEN).build()); + // log.warn("Authorization skipped for method: {}", requestContext.getMethod()); + } + } +} diff --git a/src/main/java/org/onap/aai/babel/filters/LoggingRequestFilter.java b/src/main/java/org/onap/aai/babel/filters/LoggingRequestFilter.java new file mode 100644 index 0000000..9699be4 --- /dev/null +++ b/src/main/java/org/onap/aai/babel/filters/LoggingRequestFilter.java @@ -0,0 +1,85 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2024 Deutsche Telekom. 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. + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.aai.babel.filters; + +import org.onap.aai.babel.logging.ApplicationMsgs; +import org.onap.aai.babel.logging.LogHelper; +import org.onap.aai.babel.logging.LogHelper.MdcParameter; +import org.onap.aai.babel.request.RequestHeaders; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.core.UriInfo; +import javax.ws.rs.core.MultivaluedMap; + +import java.io.IOException; +import java.util.UUID; + +@Component +public class LoggingRequestFilter implements ContainerRequestFilter { + + private static final LogHelper applicationLogger = LogHelper.INSTANCE; + + @Autowired + private HttpServletRequest servletRequest; + + @Override + public void filter(ContainerRequestContext requestContext) throws IOException { + UriInfo uriInfo = requestContext.getUriInfo(); + String requestBody = requestContext.getEntityStream().toString(); + MultivaluedMap headers = requestContext.getHeaders(); + applicationLogger.startAudit(headers, servletRequest); + applicationLogger.info(ApplicationMsgs.BABEL_REQUEST_PAYLOAD, + "Received request: " + headers + requestBody); + applicationLogger.debug(String.format( + "Received request. UriInfo \"%s\", HttpHeaders \"%s\", ServletRequest \"%s\", Request \"%s\"", uriInfo, + headers, servletRequest, requestBody)); + + // Additional name/value pairs according to EELF guidelines + applicationLogger.setContextValue("Protocol", "https"); + applicationLogger.setContextValue("Method", requestContext.getMethod()); + applicationLogger.setContextValue("Path", uriInfo.getPath()); + applicationLogger.setContextValue("Query", uriInfo.getPathParameters().toString()); + + RequestHeaders requestHeaders = new RequestHeaders(headers); + applicationLogger.info(ApplicationMsgs.BABEL_REQUEST_PAYLOAD, requestHeaders.toString()); + + String requestId = requestHeaders.getCorrelationId(); + if (requestId == null || !isRequestIDValid(requestId)) { + requestId = UUID.randomUUID().toString(); + applicationLogger.info(ApplicationMsgs.MISSING_REQUEST_ID, requestId); + applicationLogger.setContextValue(MdcParameter.REQUEST_ID, requestId); + } + + } + + private boolean isRequestIDValid(String requestId) { + try { + UUID.fromString(requestId); + } catch (IllegalArgumentException e) { + return false; + } + return true; + } +} diff --git a/src/main/java/org/onap/aai/babel/logging/LogHelper.java b/src/main/java/org/onap/aai/babel/logging/LogHelper.java index 19ee25b..f96aff0 100644 --- a/src/main/java/org/onap/aai/babel/logging/LogHelper.java +++ b/src/main/java/org/onap/aai/babel/logging/LogHelper.java @@ -32,6 +32,7 @@ import java.util.function.Consumer; import javax.servlet.ServletRequest; import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.Response.Status; import org.apache.commons.lang3.time.StopWatch; @@ -158,7 +159,7 @@ public enum LogHelper implements Logger { * @param headers raw HTTP headers * @param servletRequest the request */ - public void startAudit(final HttpHeaders headers, ServletRequest servletRequest) { + public void startAudit(final MultivaluedMap headers, ServletRequest servletRequest) { auditStopwatch = new StopWatch(); auditStopwatch.start(); @@ -170,7 +171,7 @@ public enum LogHelper implements Logger { RequestHeaders requestHeaders = new RequestHeaders(headers); requestId = Optional.ofNullable(requestHeaders.getCorrelationId()); serviceInstanceId = requestHeaders.getInstanceId(); - partnerName = Optional.ofNullable(headers.getHeaderString(Headers.FROM_APP_ID)); + partnerName = Optional.ofNullable(headers.getFirst(Headers.FROM_APP_ID)); } String clientHost = null; diff --git a/src/main/java/org/onap/aai/babel/request/RequestHeaders.java b/src/main/java/org/onap/aai/babel/request/RequestHeaders.java index 1850d62..19d5425 100644 --- a/src/main/java/org/onap/aai/babel/request/RequestHeaders.java +++ b/src/main/java/org/onap/aai/babel/request/RequestHeaders.java @@ -23,6 +23,7 @@ package org.onap.aai.babel.request; import java.util.Optional; import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MultivaluedMap; /** Bean to represent the ECOMP request/transaction IDs required for EELF logging. */ public class RequestHeaders { @@ -42,6 +43,11 @@ public class RequestHeaders { instanceId = headers.getHeaderString(RequestHeaders.HEADER_SERVICE_INSTANCE_ID); transactionId = headers.getHeaderString(RequestHeaders.HEADER_X_TRANSACTION_ID); } + public RequestHeaders(MultivaluedMap headers) { + requestId = headers.getFirst(RequestHeaders.HEADER_REQUEST_ID); + instanceId = headers.getFirst(RequestHeaders.HEADER_SERVICE_INSTANCE_ID); + transactionId = headers.getFirst(RequestHeaders.HEADER_X_TRANSACTION_ID); + } public String getRequestId() { return requestId; diff --git a/src/main/java/org/onap/aai/babel/service/GenerateArtifactsController.java b/src/main/java/org/onap/aai/babel/service/GenerateArtifactsController.java new file mode 100644 index 0000000..67fc865 --- /dev/null +++ b/src/main/java/org/onap/aai/babel/service/GenerateArtifactsController.java @@ -0,0 +1,46 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 European Software Marketing Ltd. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.babel.service; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.Consumes; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; +import org.onap.aai.auth.AAIAuthException; + +/** Generate artifacts from the specified request content */ +@Path("/app") +@Consumes(MediaType.APPLICATION_JSON) +@Produces(MediaType.APPLICATION_JSON) +@FunctionalInterface +public interface GenerateArtifactsController { + + @POST + @Path("/generateArtifacts") + Response generateArtifacts(@Context UriInfo uriInfo, @Context HttpHeaders headers, + @Context HttpServletRequest servletRequest, String request) throws AAIAuthException; +} diff --git a/src/main/java/org/onap/aai/babel/service/GenerateArtifactsControllerImpl.java b/src/main/java/org/onap/aai/babel/service/GenerateArtifactsControllerImpl.java new file mode 100644 index 0000000..189aaf3 --- /dev/null +++ b/src/main/java/org/onap/aai/babel/service/GenerateArtifactsControllerImpl.java @@ -0,0 +1,165 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright (c) 2017-2019 AT&T Intellectual Property. All rights reserved. + * Copyright (c) 2017-2019 European Software Marketing Ltd. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.aai.babel.service; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonSyntaxException; + +import lombok.RequiredArgsConstructor; + +import java.util.Base64; +import java.util.List; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.core.*; +import javax.ws.rs.core.Response.Status; + +import org.apache.commons.lang3.time.StopWatch; +import org.onap.aai.auth.AAIAuthException; +import org.onap.aai.auth.AAIMicroServiceAuth; +import org.onap.aai.auth.AAIMicroServiceAuthCore; +import org.onap.aai.babel.csar.CsarConverterException; +import org.onap.aai.babel.csar.CsarToXmlConverter; +import org.onap.aai.babel.csar.vnfcatalog.ToscaToCatalogException; +import org.onap.aai.babel.csar.vnfcatalog.VnfVendorImageExtractor; +import org.onap.aai.babel.logging.ApplicationMsgs; +import org.onap.aai.babel.logging.LogHelper; +import org.onap.aai.babel.logging.LogHelper.MdcParameter; +import org.onap.aai.babel.logging.LogHelper.StatusCode; +import org.onap.aai.babel.service.data.BabelArtifact; +import org.onap.aai.babel.service.data.BabelRequest; +import org.onap.aai.babel.util.RequestValidationException; +import org.onap.aai.babel.util.RequestValidator; +import org.springframework.stereotype.Controller; + +/** + * Generate SDC Artifacts by passing in a CSAR payload, Artifact Name and Artifact version. + * + */ +@Controller +@RequiredArgsConstructor +public class GenerateArtifactsControllerImpl implements GenerateArtifactsController { + + private static final LogHelper applicationLogger = LogHelper.INSTANCE; + private final Gson gson; + + @Override + public Response generateArtifacts(UriInfo uriInfo, HttpHeaders headers, HttpServletRequest servletRequest, + String requestBody) { + Response response; + // try { + // Get last URI path segment to use for authentication + // List pathSegments = uriInfo.getPathSegments(); + // String lastPathSegment = pathSegments.isEmpty() ? "" : pathSegments.get(pathSegments.size() - 1).getPath(); + + // boolean authorized = aaiMicroServiceAuth.validateRequest(headers, servletRequest, + // AAIMicroServiceAuthCore.HTTP_METHODS.POST, lastPathSegment); + + response = generateArtifacts(requestBody); + // response = authorized ? generateArtifacts(requestBody) + // : buildResponse(Status.UNAUTHORIZED, "User not authorized to perform the operation."); + // } catch (AAIAuthException e) { + // applicationLogger.error(ApplicationMsgs.PROCESS_REQUEST_ERROR, e); + // applicationLogger.logAuditError(e); + // return buildResponse(Status.INTERNAL_SERVER_ERROR, + // "Error while processing request. Please check the Babel service logs for more details.\n"); + // } + + StatusCode statusDescription; + int statusCode = response.getStatus(); + if (statusCode / 100 == 2) { + statusDescription = StatusCode.COMPLETE; + } else { + statusDescription = StatusCode.ERROR; + } + applicationLogger.logAudit(statusDescription, Integer.toString(statusCode), + Response.Status.fromStatusCode(statusCode).getReasonPhrase(), response.getEntity().toString()); + + return response; + } + + /** + * Generate XML model artifacts from request body. + * + * @param requestBody + * the request body in JSON format + * @return response object containing the generated XML models + */ + protected Response generateArtifacts(String requestBody) { + StopWatch stopwatch = new StopWatch(); + stopwatch.start(); + + Response response; + + try { + BabelRequest babelRequest = gson.fromJson(requestBody, BabelRequest.class); + new RequestValidator().validateRequest(babelRequest); + byte[] csarFile = Base64.getDecoder().decode(babelRequest.getCsar()); + + List babelArtifacts = new CsarToXmlConverter().generateXmlFromCsar(csarFile, + babelRequest.getArtifactName(), babelRequest.getArtifactVersion()); + + BabelArtifact vendorImageConfiguration = new VnfVendorImageExtractor().extract(csarFile); + if (vendorImageConfiguration != null) { + babelArtifacts.add(vendorImageConfiguration); + } + + response = buildResponse(Status.OK, gson.toJson(babelArtifacts)); + applicationLogger.info(ApplicationMsgs.DISTRIBUTION_EVENT,LogHelper.getCallerMethodName(0)); + } catch (JsonSyntaxException e) { + response = processError(ApplicationMsgs.INVALID_REQUEST_JSON, Status.BAD_REQUEST, e, "Malformed request."); + } catch (CsarConverterException e) { + response = processError(ApplicationMsgs.INVALID_CSAR_FILE, Status.INTERNAL_SERVER_ERROR, e, + "Error converting CSAR artifact to XML model."); + } catch (ToscaToCatalogException e) { + response = processError(ApplicationMsgs.PROCESSING_VNF_CATALOG_ERROR, Status.INTERNAL_SERVER_ERROR, e, + "Error converting CSAR artifact to VNF catalog."); + } catch (RequestValidationException e) { + response = processError(ApplicationMsgs.PROCESS_REQUEST_ERROR, Status.BAD_REQUEST, // + e, e.getLocalizedMessage()); + } finally { + applicationLogger.debug(stopwatch + LogHelper.getCallerMethodName(0)); + } + + return response; + } + + private Response processError(ApplicationMsgs applicationMsgs, Status responseStatus, Exception e, String message) { + applicationLogger.setContextValue(MdcParameter.RESPONSE_CODE, String.valueOf(responseStatus.getStatusCode())); + applicationLogger.setContextValue(MdcParameter.RESPONSE_DESCRIPTION, responseStatus.getReasonPhrase()); + applicationLogger.error(applicationMsgs, e); + return buildResponse(responseStatus, message); + } + + /** + * Helper method to create a REST response object. + * + * @param status + * response status code + * @param entity + * response payload + * @return + */ + private Response buildResponse(Status status, String entity) { + return Response.status(status).entity(entity).type(MediaType.APPLICATION_JSON).build(); + } +} diff --git a/src/main/java/org/onap/aai/babel/service/GenerateArtifactsService.java b/src/main/java/org/onap/aai/babel/service/GenerateArtifactsService.java deleted file mode 100644 index 734bb1a..0000000 --- a/src/main/java/org/onap/aai/babel/service/GenerateArtifactsService.java +++ /dev/null @@ -1,46 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 European Software Marketing Ltd. - * ================================================================================ - * 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. - * ============LICENSE_END========================================================= - */ -package org.onap.aai.babel.service; - -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.Consumes; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriInfo; -import org.onap.aai.auth.AAIAuthException; - -/** Generate artifacts from the specified request content */ -@Path("/app") -@Consumes(MediaType.APPLICATION_JSON) -@Produces(MediaType.APPLICATION_JSON) -@FunctionalInterface -public interface GenerateArtifactsService { - - @POST - @Path("/generateArtifacts") - Response generateArtifacts(@Context UriInfo uriInfo, @Context HttpHeaders headers, - @Context HttpServletRequest servletRequest, String request) throws AAIAuthException; -} diff --git a/src/main/java/org/onap/aai/babel/service/GenerateArtifactsServiceImpl.java b/src/main/java/org/onap/aai/babel/service/GenerateArtifactsServiceImpl.java deleted file mode 100644 index 544d782..0000000 --- a/src/main/java/org/onap/aai/babel/service/GenerateArtifactsServiceImpl.java +++ /dev/null @@ -1,212 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright (c) 2017-2019 AT&T Intellectual Property. All rights reserved. - * Copyright (c) 2017-2019 European Software Marketing Ltd. - * ================================================================================ - * 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. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.babel.service; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonSyntaxException; -import java.util.Base64; -import java.util.List; -import java.util.UUID; -import javax.inject.Inject; -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.core.*; -import javax.ws.rs.core.Response.Status; - -import org.apache.commons.lang3.time.StopWatch; -import org.onap.aai.auth.AAIAuthException; -import org.onap.aai.auth.AAIMicroServiceAuth; -import org.onap.aai.auth.AAIMicroServiceAuthCore; -import org.onap.aai.babel.csar.CsarConverterException; -import org.onap.aai.babel.csar.CsarToXmlConverter; -import org.onap.aai.babel.csar.vnfcatalog.ToscaToCatalogException; -import org.onap.aai.babel.csar.vnfcatalog.VnfVendorImageExtractor; -import org.onap.aai.babel.logging.ApplicationMsgs; -import org.onap.aai.babel.logging.LogHelper; -import org.onap.aai.babel.logging.LogHelper.MdcParameter; -import org.onap.aai.babel.logging.LogHelper.StatusCode; -import org.onap.aai.babel.request.RequestHeaders; -import org.onap.aai.babel.service.data.BabelArtifact; -import org.onap.aai.babel.service.data.BabelRequest; -import org.onap.aai.babel.util.RequestValidationException; -import org.onap.aai.babel.util.RequestValidator; -import org.springframework.stereotype.Service; - -/** - * Generate SDC Artifacts by passing in a CSAR payload, Artifact Name and Artifact version. - * - */ -@Service -public class GenerateArtifactsServiceImpl implements GenerateArtifactsService { - private static final LogHelper applicationLogger = LogHelper.INSTANCE; - - private AAIMicroServiceAuth aaiMicroServiceAuth; - - /** - * @param authorization - * the auth module - */ - @Inject - public GenerateArtifactsServiceImpl(final AAIMicroServiceAuth authorization) { - this.aaiMicroServiceAuth = authorization; - } - - /* - * (non-Javadoc) - * - * @see org.onap.aai.babel.service.GenerateArtifactsService#generateArtifacts(javax.ws.rs.core.UriInfo, - * javax.ws.rs.core.HttpHeaders, javax.servlet.http.HttpServletRequest, java.lang.String) - */ - @Override - public Response generateArtifacts(UriInfo uriInfo, HttpHeaders headers, HttpServletRequest servletRequest, - String requestBody) { - applicationLogger.startAudit(headers, servletRequest); - applicationLogger.info(ApplicationMsgs.BABEL_REQUEST_PAYLOAD, - "Received request: " + headers.getRequestHeaders() + requestBody); - applicationLogger.debug(String.format( - "Received request. UriInfo \"%s\", HttpHeaders \"%s\", ServletRequest \"%s\", Request \"%s\"", uriInfo, - headers, servletRequest, requestBody)); - - // Additional name/value pairs according to EELF guidelines - applicationLogger.setContextValue("Protocol", "https"); - applicationLogger.setContextValue("Method", "POST"); - applicationLogger.setContextValue("Path", uriInfo.getPath()); - applicationLogger.setContextValue("Query", uriInfo.getPathParameters().toString()); - - RequestHeaders requestHeaders = new RequestHeaders(headers); - applicationLogger.info(ApplicationMsgs.BABEL_REQUEST_PAYLOAD, requestHeaders.toString()); - - String requestId = requestHeaders.getCorrelationId(); - if (requestId == null || !isRequestIDValid(requestId)) { - requestId = UUID.randomUUID().toString(); - applicationLogger.info(ApplicationMsgs.MISSING_REQUEST_ID, requestId); - applicationLogger.setContextValue(MdcParameter.REQUEST_ID, requestId); - } - - Response response; - try { - // Get last URI path segment to use for authentication - List pathSegments = uriInfo.getPathSegments(); - String lastPathSegment = pathSegments.isEmpty() ? "" : pathSegments.get(pathSegments.size() - 1).getPath(); - - boolean authorized = aaiMicroServiceAuth.validateRequest(headers, servletRequest, - AAIMicroServiceAuthCore.HTTP_METHODS.POST, lastPathSegment); - - response = authorized ? generateArtifacts(requestBody) - : buildResponse(Status.UNAUTHORIZED, "User not authorized to perform the operation."); - } catch (AAIAuthException e) { - applicationLogger.error(ApplicationMsgs.PROCESS_REQUEST_ERROR, e); - applicationLogger.logAuditError(e); - return buildResponse(Status.INTERNAL_SERVER_ERROR, - "Error while processing request. Please check the Babel service logs for more details.\n"); - } - - StatusCode statusDescription; - int statusCode = response.getStatus(); - if (statusCode / 100 == 2) { - statusDescription = StatusCode.COMPLETE; - } else { - statusDescription = StatusCode.ERROR; - } - applicationLogger.logAudit(statusDescription, Integer.toString(statusCode), - Response.Status.fromStatusCode(statusCode).getReasonPhrase(), response.getEntity().toString()); - - return response; - } - - private boolean isRequestIDValid(String requestId) { - try { - UUID.fromString(requestId); - } catch (IllegalArgumentException e) { - return false; - } - return true; - } - - /** - * Generate XML model artifacts from request body. - * - * @param requestBody - * the request body in JSON format - * @return response object containing the generated XML models - */ - protected Response generateArtifacts(String requestBody) { - StopWatch stopwatch = new StopWatch(); - stopwatch.start(); - - Response response; - - try { - Gson gson = new GsonBuilder().disableHtmlEscaping().create(); - - BabelRequest babelRequest = gson.fromJson(requestBody, BabelRequest.class); - new RequestValidator().validateRequest(babelRequest); - byte[] csarFile = Base64.getDecoder().decode(babelRequest.getCsar()); - - List babelArtifacts = new CsarToXmlConverter().generateXmlFromCsar(csarFile, - babelRequest.getArtifactName(), babelRequest.getArtifactVersion()); - - BabelArtifact vendorImageConfiguration = new VnfVendorImageExtractor().extract(csarFile); - if (vendorImageConfiguration != null) { - babelArtifacts.add(vendorImageConfiguration); - } - - response = buildResponse(Status.OK, gson.toJson(babelArtifacts)); - applicationLogger.info(ApplicationMsgs.DISTRIBUTION_EVENT,LogHelper.getCallerMethodName(0)); - } catch (JsonSyntaxException e) { - response = processError(ApplicationMsgs.INVALID_REQUEST_JSON, Status.BAD_REQUEST, e, "Malformed request."); - } catch (CsarConverterException e) { - response = processError(ApplicationMsgs.INVALID_CSAR_FILE, Status.INTERNAL_SERVER_ERROR, e, - "Error converting CSAR artifact to XML model."); - } catch (ToscaToCatalogException e) { - response = processError(ApplicationMsgs.PROCESSING_VNF_CATALOG_ERROR, Status.INTERNAL_SERVER_ERROR, e, - "Error converting CSAR artifact to VNF catalog."); - } catch (RequestValidationException e) { - response = processError(ApplicationMsgs.PROCESS_REQUEST_ERROR, Status.BAD_REQUEST, // - e, e.getLocalizedMessage()); - } finally { - applicationLogger.debug(stopwatch + LogHelper.getCallerMethodName(0)); - } - - return response; - } - - private Response processError(ApplicationMsgs applicationMsgs, Status responseStatus, Exception e, String message) { - applicationLogger.setContextValue(MdcParameter.RESPONSE_CODE, String.valueOf(responseStatus.getStatusCode())); - applicationLogger.setContextValue(MdcParameter.RESPONSE_DESCRIPTION, responseStatus.getReasonPhrase()); - applicationLogger.error(applicationMsgs, e); - return buildResponse(responseStatus, message); - } - - /** - * Helper method to create a REST response object. - * - * @param status - * response status code - * @param entity - * response payload - * @return - */ - private Response buildResponse(Status status, String entity) { - return Response.status(status).entity(entity).type(MediaType.APPLICATION_JSON).build(); - } -} diff --git a/src/main/resources/babel-beans.xml b/src/main/resources/babel-beans.xml index e979a2e..ab784c8 100644 --- a/src/main/resources/babel-beans.xml +++ b/src/main/resources/babel-beans.xml @@ -30,4 +30,7 @@ + + -- cgit