diff options
author | Kajur, Harish (vk250x) <vk250x@att.com> | 2018-11-26 00:07:25 -0500 |
---|---|---|
committer | Kajur, Harish (vk250x) <vk250x@att.com> | 2018-11-27 07:04:01 -0500 |
commit | d64d789ad789e950c3b5e5443fb418a722b917c4 (patch) | |
tree | af2a2f938963447cfcc72d20dc455c3a79b148f0 /aai-schema-service/src/main/java/org/onap | |
parent | d943652dd8e2cdcb087cab16271cc0c4fd4a1385 (diff) |
Initial commit of the schema service
Issue-ID: AAI-1950
Change-Id: If2fd9e344d8c4ae1fa1b11e449b686035f55354f
Signed-off-by: Kajur, Harish (vk250x) <vk250x@att.com>
Diffstat (limited to 'aai-schema-service/src/main/java/org/onap')
25 files changed, 1945 insertions, 0 deletions
diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/Profiles.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/Profiles.java new file mode 100644 index 0000000..863d6c8 --- /dev/null +++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/Profiles.java @@ -0,0 +1,32 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 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. + * 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.schemaservice; + +public final class Profiles { + + public static final String ONE_WAY_SSL = "one-way-ssl"; + public static final String AAF_AUTHENTICATION = "aaf-auth"; + public static final String TWO_WAY_SSL = "two-way-ssl"; + public static final String DEV = "dev"; + public static final String AOP = "aop"; + + private Profiles() { + } +} diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/SchemaServiceApp.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/SchemaServiceApp.java new file mode 100644 index 0000000..8f36ac5 --- /dev/null +++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/SchemaServiceApp.java @@ -0,0 +1,153 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 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. + * 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.schemaservice; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.logging.LoggingContext; +import org.onap.aai.logging.LoggingContext.StatusCode; +import org.onap.aai.schemaservice.config.PropertyPasswordConfiguration; +import org.slf4j.MDC; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration; +import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; +import org.springframework.core.env.Environment; + +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; +import java.util.Map; +import java.util.UUID; + +@SpringBootApplication +// Component Scan provides a way to look for spring beans +// It only searches beans in the following packages +// Any method annotated with @Bean annotation or any class +// with @Component, @Configuration, @Service will be picked up +@EnableAutoConfiguration(exclude = { + DataSourceAutoConfiguration.class, + DataSourceTransactionManagerAutoConfiguration.class, + HibernateJpaAutoConfiguration.class +}) +public class SchemaServiceApp { + + private static final EELFLogger logger = EELFManager.getInstance().getLogger(SchemaServiceApp.class.getName()); + + private static final String APP_NAME = "aai-schema-service"; + private static Map<String, String> contextMap; + + @Autowired + private Environment env; + + public static void main(String[] args) throws AAIException { + + setDefaultProps(); + + LoggingContext.save(); + LoggingContext.component("init"); + LoggingContext.partnerName("NA"); + LoggingContext.targetEntity(APP_NAME); + LoggingContext.requestId(UUID.randomUUID().toString()); + LoggingContext.serviceName(APP_NAME); + LoggingContext.targetServiceName("contextInitialized"); + LoggingContext.statusCode(StatusCode.COMPLETE); + + + SpringApplication app = new SpringApplication(SchemaServiceApp.class); + app.setLogStartupInfo(false); + app.setRegisterShutdownHook(true); + app.addInitializers(new PropertyPasswordConfiguration()); + Environment env = app.run(args).getEnvironment(); + MDC.setContextMap(contextMap); + + logger.info( + "Application '{}' is running on {}!", + env.getProperty("spring.application.name"), + env.getProperty("server.port") + ); + + logger.info("SchemaService MicroService Started"); + + System.out.println("SchemaService Microservice Started"); + + LoggingContext.restoreIfPossible(); + } + + public static void setDefaultProps() { + + if (System.getProperty("file.separator") == null) { + System.setProperty("file.separator", "/"); + } + + String currentDirectory = System.getProperty("user.dir"); + + if (System.getProperty("AJSC_HOME") == null) { + System.setProperty("AJSC_HOME", "."); + } + + if (currentDirectory.contains(APP_NAME)) { + if (System.getProperty("BUNDLECONFIG_DIR") == null) { + System.setProperty("BUNDLECONFIG_DIR", "src/main/resources"); + } + } else { + if (System.getProperty("BUNDLECONFIG_DIR") == null) { + System.setProperty("BUNDLECONFIG_DIR", "aai-schema-service/src/main/resources"); + } + } + } + + @PostConstruct + private void init() throws AAIException { + System.setProperty("org.onap.aai.serverStarted", "false"); + setDefaultProps(); + + LoggingContext.save(); + LoggingContext.component("init"); + LoggingContext.partnerName("NA"); + LoggingContext.targetEntity(APP_NAME); + LoggingContext.requestId(UUID.randomUUID().toString()); + LoggingContext.serviceName(APP_NAME); + LoggingContext.targetServiceName("contextInitialized"); + LoggingContext.statusCode(StatusCode.COMPLETE); + + contextMap = MDC.getCopyOfContextMap(); + logger.info("SchemaService initialization started..."); + + // Setting this property to allow for encoded slash (/) in the path parameter + // This is only needed for tomcat keeping this as temporary + System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true"); + + + if (env.acceptsProfiles(Profiles.TWO_WAY_SSL) && env.acceptsProfiles(Profiles.ONE_WAY_SSL)) { + logger.warn("You have seriously misconfigured your application"); + } + + LoggingContext.restoreIfPossible(); + } + + @PreDestroy + public void cleanup() { + logger.info("SchemaService shutting down"); + } +} diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/config/ErrorHandler.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/config/ErrorHandler.java new file mode 100644 index 0000000..cb5416f --- /dev/null +++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/config/ErrorHandler.java @@ -0,0 +1,143 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 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. + * 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.schemaservice.config; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.logging.ErrorLogHelper; +import org.onap.aai.logging.ErrorObject; +import org.onap.aai.logging.ErrorObjectNotFoundException; +import org.onap.aai.logging.LogFormatTools; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.core.MediaType; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * Responsible for dealing with uri that doesn't start with basePath + * All of the other interceptors will handle any uri that starts with basePath + * So we need this to ensure that these cases are properly handled + */ +@Order(1) +@Component +public class ErrorHandler extends OncePerRequestFilter { + + private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(ErrorHandler.class); + private String basePath; + + public ErrorHandler(@Value("${schema.uri.base.path}") String basePath) { + this.basePath = basePath; + if (!basePath.endsWith("/")) { + this.basePath = basePath + "/"; + } + } + + @Override + protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException { + + String uri = httpServletRequest.getRequestURI(); + + if (uri != null && !(uri.startsWith(basePath))) { + + AAIException e = new AAIException("AAI_3012"); + ArrayList<String> templateVars = new ArrayList<>(); + + List<MediaType> mediaTypeList = new ArrayList<>(); + + String acceptHeader = httpServletRequest.getHeader("Accept"); + if (acceptHeader == null) { + mediaTypeList.add(MediaType.APPLICATION_XML_TYPE); + } else { + mediaTypeList.add(MediaType.valueOf(acceptHeader)); + } + + String message = ErrorLogHelper.getRESTAPIErrorResponse(mediaTypeList, e, templateVars); + + httpServletResponse.setStatus(400); + httpServletResponse.setContentType(mediaTypeList.get(0).toString()); + httpServletResponse.getWriter().print(message); + httpServletResponse.getWriter().close(); + return; + } + + try { + filterChain.doFilter(httpServletRequest, httpServletResponse); + } catch (ServletException ex) { + Throwable e = ex.getRootCause(); + if (e instanceof AAIException) { + List<MediaType> mediaTypeList = new ArrayList<>(); + String acceptHeader = httpServletRequest.getHeader("Accept"); + if (acceptHeader == null) { + mediaTypeList.add(MediaType.APPLICATION_XML_TYPE); + } else { + mediaTypeList.add(MediaType.valueOf(acceptHeader)); + } + + ArrayList<String> templateVars = new ArrayList<>(); + AAIException aaiException = (AAIException) e; + String message = ErrorLogHelper.getRESTAPIErrorResponse(mediaTypeList, aaiException, templateVars); + ErrorObject object = null; + try { + object = ErrorLogHelper.getErrorObject(aaiException.getCode()); + } catch (ErrorObjectNotFoundException e1) { + e1.printStackTrace(); + } + httpServletResponse.setStatus(object.getHTTPResponseCode().getStatusCode()); + httpServletResponse.setContentType(mediaTypeList.get(0).toString()); + httpServletResponse.getWriter().write(message); + httpServletResponse.getWriter().close(); + } else { + + List<MediaType> mediaTypeList = new ArrayList<>(); + String acceptHeader = httpServletRequest.getHeader("Accept"); + if (acceptHeader == null) { + mediaTypeList.add(MediaType.APPLICATION_XML_TYPE); + } else { + mediaTypeList.add(MediaType.valueOf(acceptHeader)); + } + ArrayList<String> templateVars = new ArrayList<>(); + AAIException aaiException = new AAIException("AAI_4000", e); + LOGGER.error("Encountered an internal exception {}", LogFormatTools.getStackTop(e)); + String message = ErrorLogHelper.getRESTAPIErrorResponse(mediaTypeList, aaiException, templateVars); + ErrorObject object = null; + try { + object = ErrorLogHelper.getErrorObject(aaiException.getCode()); + } catch (ErrorObjectNotFoundException e1) { + e1.printStackTrace(); + } + httpServletResponse.setStatus(object.getHTTPResponseCode().getStatusCode()); + httpServletResponse.setContentType(mediaTypeList.get(0).toString()); + httpServletResponse.getWriter().write(message); + httpServletResponse.getWriter().close(); + } + } + } + +} diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/config/JettyPasswordDecoder.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/config/JettyPasswordDecoder.java new file mode 100644 index 0000000..1b48753 --- /dev/null +++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/config/JettyPasswordDecoder.java @@ -0,0 +1,33 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 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. + * 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.schemaservice.config; + +import org.eclipse.jetty.util.security.Password; + +public class JettyPasswordDecoder implements PasswordDecoder { + + @Override + public String decode(String input) { + if (input.startsWith("OBF:")) { + return Password.deobfuscate(input); + } + return Password.deobfuscate("OBF:" + input); + } +} diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/config/PasswordDecoder.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/config/PasswordDecoder.java new file mode 100644 index 0000000..f0ae940 --- /dev/null +++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/config/PasswordDecoder.java @@ -0,0 +1,25 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 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. + * 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.schemaservice.config; + +public interface PasswordDecoder { + + String decode(String input); +} diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/config/PropertyPasswordConfiguration.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/config/PropertyPasswordConfiguration.java new file mode 100644 index 0000000..49cd1ed --- /dev/null +++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/config/PropertyPasswordConfiguration.java @@ -0,0 +1,78 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 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. + * 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.schemaservice.config; + +import org.springframework.context.ApplicationContextInitializer; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.EnumerablePropertySource; +import org.springframework.core.env.MapPropertySource; +import org.springframework.core.env.PropertySource; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class PropertyPasswordConfiguration implements ApplicationContextInitializer<ConfigurableApplicationContext> { + + private static final Pattern decodePasswordPattern = Pattern.compile("password\\((.*?)\\)"); + + private PasswordDecoder passwordDecoder = new JettyPasswordDecoder(); + + @Override + public void initialize(ConfigurableApplicationContext applicationContext) { + ConfigurableEnvironment environment = applicationContext.getEnvironment(); + for (PropertySource<?> propertySource : environment.getPropertySources()) { + Map<String, Object> propertyOverrides = new LinkedHashMap<>(); + decodePasswords(propertySource, propertyOverrides); + if (!propertyOverrides.isEmpty()) { + PropertySource<?> decodedProperties = new MapPropertySource("decoded " + propertySource.getName(), propertyOverrides); + environment.getPropertySources().addBefore(propertySource.getName(), decodedProperties); + } + } + } + + private void decodePasswords(PropertySource<?> source, Map<String, Object> propertyOverrides) { + if (source instanceof EnumerablePropertySource) { + EnumerablePropertySource<?> enumerablePropertySource = (EnumerablePropertySource<?>) source; + for (String key : enumerablePropertySource.getPropertyNames()) { + Object rawValue = source.getProperty(key); + if (rawValue instanceof String) { + String decodedValue = decodePasswordsInString((String) rawValue); + propertyOverrides.put(key, decodedValue); + } + } + } + } + + private String decodePasswordsInString(String input) { + if (input == null) return null; + StringBuffer output = new StringBuffer(); + Matcher matcher = decodePasswordPattern.matcher(input); + while (matcher.find()) { + String replacement = passwordDecoder.decode(matcher.group(1)); + matcher.appendReplacement(output, replacement); + } + matcher.appendTail(output); + return output.toString(); + } + +} diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/AAIContainerFilter.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/AAIContainerFilter.java new file mode 100644 index 0000000..e5588b6 --- /dev/null +++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/AAIContainerFilter.java @@ -0,0 +1,41 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 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. + * 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.schemaservice.interceptors; + +import org.onap.aai.util.FormatDate; + +import java.util.UUID; + +public abstract class AAIContainerFilter { + + protected String genDate() { + FormatDate fd = new FormatDate("YYMMdd-HH:mm:ss:SSS"); + return fd.getDateTime(); + } + + protected boolean isValidUUID(String transId) { + try { + UUID.fromString(transId); + } catch (IllegalArgumentException e) { + return false; + } + return true; + } +} diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/AAIHeaderProperties.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/AAIHeaderProperties.java new file mode 100644 index 0000000..8f08d3f --- /dev/null +++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/AAIHeaderProperties.java @@ -0,0 +1,34 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 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. + * 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.schemaservice.interceptors; + +public final class AAIHeaderProperties { + + public static final String REQUEST_CONTEXT = "aai-request-context"; + public static final String HTTP_METHOD_OVERRIDE = "X-HTTP-Method-Override"; + public static final String TRANSACTION_ID = "X-TransactionId"; + public static final String FROM_APP_ID = "X-FromAppId"; + public static final String AAI_TX_ID = "X-AAI-TXID"; + public static final String AAI_REQUEST = "X-REQUEST"; + public static final String AAI_REQUEST_TS = "X-REQUEST-TS"; + + private AAIHeaderProperties() { + } +} diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/package-info.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/package-info.java new file mode 100644 index 0000000..6cf55f0 --- /dev/null +++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/package-info.java @@ -0,0 +1,36 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 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. + * 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========================================================= + */ +/** + * <b>Interceptors</b> package is subdivided to pre and post interceptors + * If you want to add an additional interceptor you would need to add + * the priority level to AAIRequestFilterPriority or AAIResponsePriority + * to give a value which indicates the order in which the interceptor + * will be triggered and also you will add that value like here + * + * <pre> + * <code> + * @Priority(AAIRequestFilterPriority.YOUR_PRIORITY) + * public class YourInterceptor extends AAIContainerFilter implements ContainerRequestFilter { + * + * } + * </code> + * </pre> + */ +package org.onap.aai.schemaservice.interceptors; diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/post/AAIResponseFilterPriority.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/post/AAIResponseFilterPriority.java new file mode 100644 index 0000000..fceadeb --- /dev/null +++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/post/AAIResponseFilterPriority.java @@ -0,0 +1,38 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 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. + * 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.schemaservice.interceptors.post; + +/** + * Response Filter order is done reverse sorted + * so in the following case the first response filter would be + * HEADER_MANIPULATION, RESPONSE_TRANS_LOGGING, RESET_LOGGING_CONTEXT, + * and INVALID_RESPONSE_STATUS + */ +public final class AAIResponseFilterPriority { + + public static final int INVALID_RESPONSE_STATUS = 1000; + public static final int RESET_LOGGING_CONTEXT = 2000; + public static final int RESPONSE_TRANS_LOGGING = 3000; + public static final int HEADER_MANIPULATION = 4000; + + private AAIResponseFilterPriority() { + } + +} diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/post/InvalidResponseStatus.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/post/InvalidResponseStatus.java new file mode 100644 index 0000000..4fd3220 --- /dev/null +++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/post/InvalidResponseStatus.java @@ -0,0 +1,65 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 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. + * 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.schemaservice.interceptors.post; + +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.logging.ErrorLogHelper; +import org.onap.aai.schemaservice.interceptors.AAIContainerFilter; + +import javax.annotation.Priority; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerResponseContext; +import javax.ws.rs.container.ContainerResponseFilter; +import javax.ws.rs.core.MediaType; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +@Priority(AAIResponseFilterPriority.INVALID_RESPONSE_STATUS) +public class InvalidResponseStatus extends AAIContainerFilter implements ContainerResponseFilter { + + @Override + public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) + throws IOException { + + if (responseContext.getStatus() == 405) { + + responseContext.setStatus(400); + AAIException e = new AAIException("AAI_3012"); + ArrayList<String> templateVars = new ArrayList<>(); + + List<MediaType> mediaTypeList = new ArrayList<>(); + + String contentType = responseContext.getHeaderString("Content-Type"); + + if (contentType == null) { + mediaTypeList.add(MediaType.APPLICATION_XML_TYPE); + } else { + mediaTypeList.add(MediaType.valueOf(contentType)); + } + + String message = ErrorLogHelper.getRESTAPIErrorResponse(mediaTypeList, e, templateVars); + + responseContext.setEntity(message); + } + + } + +} diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/post/ResetLoggingContext.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/post/ResetLoggingContext.java new file mode 100644 index 0000000..420ee78 --- /dev/null +++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/post/ResetLoggingContext.java @@ -0,0 +1,96 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 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. + * 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.schemaservice.interceptors.post; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import org.onap.aai.logging.LoggingContext; +import org.onap.aai.logging.LoggingContext.StatusCode; +import org.onap.aai.schemaservice.interceptors.AAIContainerFilter; +import org.springframework.beans.factory.annotation.Autowired; + +import javax.annotation.Priority; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerResponseContext; +import javax.ws.rs.container.ContainerResponseFilter; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.core.Response.StatusType; +import java.io.IOException; + +@Priority(AAIResponseFilterPriority.RESET_LOGGING_CONTEXT) +public class ResetLoggingContext extends AAIContainerFilter implements ContainerResponseFilter { + + private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(ResetLoggingContext.class); + + @Autowired + private HttpServletRequest httpServletRequest; + + @Override + public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) + throws IOException { + + this.cleanLoggingContext(responseContext); + + } + + private void cleanLoggingContext(ContainerResponseContext responseContext) { + //String url = httpServletRequest.getRequestURL().toString(); + boolean success = true; + String uri = httpServletRequest.getRequestURI(); + String queryString = httpServletRequest.getQueryString(); + + if (queryString != null && !queryString.isEmpty()) { + uri = uri + "?" + queryString; + } + // For now, we use the the HTTP status code, + // This may change, once the requirements for response codes are defined + + int httpStatusCode = responseContext.getStatus(); + if (httpStatusCode < 100 || httpStatusCode > 599) { + httpStatusCode = Status.INTERNAL_SERVER_ERROR.getStatusCode(); + } + LoggingContext.responseCode(Integer.toString(httpStatusCode)); + + StatusType sType = responseContext.getStatusInfo(); + if (sType != null) { + Status.Family sFamily = sType.getFamily(); + if (!(Status.Family.SUCCESSFUL.equals(sFamily) || + (Status.NOT_FOUND.equals(Status.fromStatusCode(httpStatusCode))))) { + success = false; + } + } else { + if ((httpStatusCode < 200 || httpStatusCode > 299) && (!(Status.NOT_FOUND.equals(Status.fromStatusCode(httpStatusCode))))) { + success = false; + } + } + if (success) { + LoggingContext.statusCode(StatusCode.COMPLETE); + LOGGER.info(uri + " call succeeded"); + } else { + LoggingContext.statusCode(StatusCode.ERROR); + LOGGER.error(uri + " call failed with responseCode=" + httpStatusCode); + } + LoggingContext.clear(); + + + } + +} diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/post/ResponseHeaderManipulation.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/post/ResponseHeaderManipulation.java new file mode 100644 index 0000000..6e3848c --- /dev/null +++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/post/ResponseHeaderManipulation.java @@ -0,0 +1,64 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 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. + * 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.schemaservice.interceptors.post; + +import org.onap.aai.schemaservice.interceptors.AAIContainerFilter; +import org.onap.aai.schemaservice.interceptors.AAIHeaderProperties; + +import javax.annotation.Priority; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerResponseContext; +import javax.ws.rs.container.ContainerResponseFilter; +import javax.ws.rs.core.MediaType; +import java.io.IOException; + +@Priority(AAIResponseFilterPriority.HEADER_MANIPULATION) +public class ResponseHeaderManipulation extends AAIContainerFilter implements ContainerResponseFilter { + + private static final String DEFAULT_XML_TYPE = MediaType.APPLICATION_XML; + + @Override + public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) + throws IOException { + + updateResponseHeaders(requestContext, responseContext); + + } + + private void updateResponseHeaders(ContainerRequestContext requestContext, + ContainerResponseContext responseContext) { + + responseContext.getHeaders().add(AAIHeaderProperties.AAI_TX_ID, requestContext.getProperty(AAIHeaderProperties.AAI_TX_ID)); + + String responseContentType = responseContext.getHeaderString("Content-Type"); + + if (responseContentType == null) { + String acceptType = requestContext.getHeaderString("Accept"); + + if (acceptType == null || "*/*".equals(acceptType)) { + responseContext.getHeaders().putSingle("Content-Type", DEFAULT_XML_TYPE); + } else { + responseContext.getHeaders().putSingle("Content-Type", acceptType); + } + } + + } + +} diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/post/ResponseTransactionLogging.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/post/ResponseTransactionLogging.java new file mode 100644 index 0000000..cd6706d --- /dev/null +++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/post/ResponseTransactionLogging.java @@ -0,0 +1,124 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 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. + * 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.schemaservice.interceptors.post; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.google.gson.JsonObject; +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.logging.ErrorLogHelper; +import org.onap.aai.schemaservice.interceptors.AAIContainerFilter; +import org.onap.aai.schemaservice.interceptors.AAIHeaderProperties; +import org.onap.aai.util.AAIConfig; +import org.springframework.beans.factory.annotation.Autowired; + +import javax.annotation.Priority; +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.HttpMethod; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerResponseContext; +import javax.ws.rs.container.ContainerResponseFilter; +import java.io.IOException; +import java.util.Objects; +import java.util.Optional; + +@Priority(AAIResponseFilterPriority.RESPONSE_TRANS_LOGGING) +public class ResponseTransactionLogging extends AAIContainerFilter implements ContainerResponseFilter { + + private static final EELFLogger TRANSACTION_LOGGER = EELFManager.getInstance().getLogger(ResponseTransactionLogging.class); + + @Autowired + private HttpServletResponse httpServletResponse; + + @Override + public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) + throws IOException { + + this.transLogging(requestContext, responseContext); + + } + + private void transLogging(ContainerRequestContext requestContext, ContainerResponseContext responseContext) { + + String logValue; + String getValue; + + try { + logValue = AAIConfig.get("aai.transaction.logging"); + getValue = AAIConfig.get("aai.transaction.logging.get"); + } catch (AAIException e) { + return; + } + + String httpMethod = requestContext.getMethod(); + + if(Boolean.parseBoolean(logValue)){ + + if(!Boolean.parseBoolean(getValue) && HttpMethod.GET.equals(httpMethod)){ + return; + } + + String transId = requestContext.getHeaderString(AAIHeaderProperties.TRANSACTION_ID); + String fromAppId = requestContext.getHeaderString(AAIHeaderProperties.FROM_APP_ID); + String fullUri = requestContext.getUriInfo().getRequestUri().toString(); + String requestTs = (String) requestContext.getProperty(AAIHeaderProperties.AAI_REQUEST_TS); + + + String status = Integer.toString(responseContext.getStatus()); + + String request = (String) requestContext.getProperty(AAIHeaderProperties.AAI_REQUEST); + String response = this.getResponseString(responseContext); + + + JsonObject logEntry = new JsonObject(); + logEntry.addProperty("transactionId", transId); + logEntry.addProperty("status", status); + logEntry.addProperty("rqstDate", requestTs); + logEntry.addProperty("respDate", this.genDate()); + logEntry.addProperty("sourceId", fromAppId + ":" + transId); + logEntry.addProperty("resourceId", fullUri); + logEntry.addProperty("resourceType", httpMethod); + logEntry.addProperty("rqstBuf", Objects.toString(request, "")); + logEntry.addProperty("respBuf", Objects.toString(response, "")); + + try { + TRANSACTION_LOGGER.debug(logEntry.toString()); + } catch (Exception e) { + ErrorLogHelper.logError("AAI_4000", "Exception writing transaction log."); + } + } + } + + private String getResponseString(ContainerResponseContext responseContext) { + JsonObject response = new JsonObject(); + response.addProperty("ID", responseContext.getHeaderString(AAIHeaderProperties.AAI_TX_ID)); + response.addProperty("Content-Type", this.httpServletResponse.getContentType()); + response.addProperty("Response-Code", responseContext.getStatus()); + response.addProperty("Headers", responseContext.getHeaders().toString()); + Optional<Object> entityOptional = Optional.ofNullable(responseContext.getEntity()); + if (entityOptional.isPresent()) { + response.addProperty("Entity", entityOptional.get().toString()); + } else { + response.addProperty("Entity", ""); + } + return response.toString(); + } + +} diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/pre/AAIRequestFilterPriority.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/pre/AAIRequestFilterPriority.java new file mode 100644 index 0000000..0ecc0cf --- /dev/null +++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/pre/AAIRequestFilterPriority.java @@ -0,0 +1,34 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 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. + * 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.schemaservice.interceptors.pre; + +public final class AAIRequestFilterPriority { + + public static final int REQUEST_TRANS_LOGGING = 1000; + public static final int HEADER_VALIDATION = 2000; + public static final int SET_LOGGING_CONTEXT = 3000; + public static final int HTTP_HEADER = 4000; + public static final int AUTHORIZATION = 4500; + public static final int HEADER_MANIPULATION = 6000; + + private AAIRequestFilterPriority() { + } + +} diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/pre/HeaderValidation.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/pre/HeaderValidation.java new file mode 100644 index 0000000..85cb6be --- /dev/null +++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/pre/HeaderValidation.java @@ -0,0 +1,86 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 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. + * 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.schemaservice.interceptors.pre; + +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.logging.ErrorLogHelper; +import org.onap.aai.schemaservice.interceptors.AAIContainerFilter; +import org.onap.aai.schemaservice.interceptors.AAIHeaderProperties; + +import javax.annotation.Priority; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.container.PreMatching; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +@PreMatching +@Priority(AAIRequestFilterPriority.HEADER_VALIDATION) +public class HeaderValidation extends AAIContainerFilter implements ContainerRequestFilter { + + @Override + public void filter(ContainerRequestContext requestContext) throws IOException { + + Optional<Response> oResp; + + String transId = requestContext.getHeaderString(AAIHeaderProperties.TRANSACTION_ID); + String fromAppId = requestContext.getHeaderString(AAIHeaderProperties.FROM_APP_ID); + + List<MediaType> acceptHeaderValues = requestContext.getAcceptableMediaTypes(); + + oResp = this.validateHeaderValuePresence(fromAppId, "AAI_4009", acceptHeaderValues); + if (oResp.isPresent()) { + requestContext.abortWith(oResp.get()); + return; + } + oResp = this.validateHeaderValuePresence(transId, "AAI_4010", acceptHeaderValues); + if (oResp.isPresent()) { + requestContext.abortWith(oResp.get()); + return; + } + + if (!this.isValidUUID(transId)) { + transId = UUID.randomUUID().toString(); + requestContext.getHeaders().get(AAIHeaderProperties.TRANSACTION_ID).clear(); + requestContext.getHeaders().add(AAIHeaderProperties.TRANSACTION_ID, transId); + } + + } + + private Optional<Response> validateHeaderValuePresence(String value, String errorCode, + List<MediaType> acceptHeaderValues) { + Response response = null; + AAIException aaie; + if (value == null) { + aaie = new AAIException(errorCode); + return Optional.of(Response.status(aaie.getErrorObject().getHTTPResponseCode()) + .entity(ErrorLogHelper.getRESTAPIErrorResponse(acceptHeaderValues, aaie, new ArrayList<>())) + .build()); + } + + return Optional.ofNullable(response); + } + +} diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/pre/HttpHeaderInterceptor.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/pre/HttpHeaderInterceptor.java new file mode 100644 index 0000000..26765e5 --- /dev/null +++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/pre/HttpHeaderInterceptor.java @@ -0,0 +1,50 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 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. + * 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.schemaservice.interceptors.pre; + +import org.onap.aai.schemaservice.interceptors.AAIContainerFilter; +import org.onap.aai.schemaservice.interceptors.AAIHeaderProperties; + +import javax.annotation.Priority; +import javax.ws.rs.HttpMethod; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.container.PreMatching; +import java.io.IOException; + +/** + * The Class HttpHeaderInterceptor + */ +@PreMatching +@Priority(AAIRequestFilterPriority.HTTP_HEADER) +public class HttpHeaderInterceptor extends AAIContainerFilter implements ContainerRequestFilter { + public static final String patchMethod = "PATCH"; + + @Override + public void filter(ContainerRequestContext containerRequestContext) throws IOException { + String overrideMethod = containerRequestContext.getHeaderString(AAIHeaderProperties.HTTP_METHOD_OVERRIDE); + String httpMethod = containerRequestContext.getMethod(); + + if (HttpMethod.POST.equalsIgnoreCase(httpMethod) && patchMethod.equalsIgnoreCase(overrideMethod)) { + containerRequestContext.setMethod(patchMethod); + } + } + +} diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/pre/OneWaySslAuthorization.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/pre/OneWaySslAuthorization.java new file mode 100644 index 0000000..989e56a --- /dev/null +++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/pre/OneWaySslAuthorization.java @@ -0,0 +1,82 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 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. + * 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.schemaservice.interceptors.pre; + +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.logging.ErrorLogHelper; +import org.onap.aai.schemaservice.Profiles; +import org.onap.aai.schemaservice.interceptors.AAIContainerFilter; +import org.onap.aai.schemaservice.service.AuthorizationService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Profile; + +import javax.annotation.Priority; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.container.PreMatching; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +@Profile(Profiles.ONE_WAY_SSL) +@PreMatching +@Priority(AAIRequestFilterPriority.AUTHORIZATION) +public class OneWaySslAuthorization extends AAIContainerFilter implements ContainerRequestFilter { + + @Autowired + private AuthorizationService authorizationService; + + @Override + public void filter(ContainerRequestContext containerRequestContext) throws IOException { + + if (containerRequestContext.getUriInfo().getRequestUri().getPath().matches("^.*/util/echo$")) { + return; + } + + String basicAuth = containerRequestContext.getHeaderString("Authorization"); + List<MediaType> acceptHeaderValues = containerRequestContext.getAcceptableMediaTypes(); + + if (basicAuth == null || !basicAuth.startsWith("Basic ")) { + Optional<Response> responseOptional = errorResponse("AAI_3300", acceptHeaderValues); + containerRequestContext.abortWith(responseOptional.get()); + return; + } + + basicAuth = basicAuth.substring(6); + + if (!authorizationService.checkIfUserAuthorized(basicAuth)) { + Optional<Response> responseOptional = errorResponse("AAI_3300", acceptHeaderValues); + containerRequestContext.abortWith(responseOptional.get()); + return; + } + + } + + private Optional<Response> errorResponse(String errorCode, List<MediaType> acceptHeaderValues) { + AAIException aaie = new AAIException(errorCode); + return Optional.of(Response.status(aaie.getErrorObject().getHTTPResponseCode()) + .entity(ErrorLogHelper.getRESTAPIErrorResponse(acceptHeaderValues, aaie, new ArrayList<>())) + .build()); + + } +} diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/pre/RequestHeaderManipulation.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/pre/RequestHeaderManipulation.java new file mode 100644 index 0000000..211350a --- /dev/null +++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/pre/RequestHeaderManipulation.java @@ -0,0 +1,63 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 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. + * 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.schemaservice.interceptors.pre; + +import org.onap.aai.schemaservice.interceptors.AAIContainerFilter; +import org.onap.aai.schemaservice.interceptors.AAIHeaderProperties; + +import javax.annotation.Priority; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.container.PreMatching; +import javax.ws.rs.core.MultivaluedMap; +import java.util.Collections; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +@PreMatching +@Priority(AAIRequestFilterPriority.HEADER_MANIPULATION) +public class RequestHeaderManipulation extends AAIContainerFilter implements ContainerRequestFilter { + + public static final Pattern EXTRACT_VERSION_PATTERN = Pattern.compile("^(v[1-9][0-9]*).*$"); + + @Override + public void filter(ContainerRequestContext requestContext) { + + String uri = requestContext.getUriInfo().getPath(); + this.addRequestContext(uri, requestContext.getHeaders()); + + } + + private void addRequestContext(String uri, MultivaluedMap<String, String> requestHeaders) { + + String rc = ""; + + Matcher match = EXTRACT_VERSION_PATTERN.matcher(uri); + if (match.find()) { + rc = match.group(1); + } + + if (requestHeaders.containsKey(AAIHeaderProperties.REQUEST_CONTEXT)) { + requestHeaders.remove(AAIHeaderProperties.REQUEST_CONTEXT); + } + requestHeaders.put(AAIHeaderProperties.REQUEST_CONTEXT, Collections.singletonList(rc)); + } + +} diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/pre/RequestTransactionLogging.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/pre/RequestTransactionLogging.java new file mode 100644 index 0000000..4208649 --- /dev/null +++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/pre/RequestTransactionLogging.java @@ -0,0 +1,113 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 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. + * 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.schemaservice.interceptors.pre; + +import com.google.gson.JsonObject; +import org.glassfish.jersey.message.internal.ReaderWriter; +import org.glassfish.jersey.server.ContainerException; +import org.onap.aai.schemaservice.interceptors.AAIContainerFilter; +import org.onap.aai.schemaservice.interceptors.AAIHeaderProperties; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.StringUtils; + +import javax.annotation.Priority; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.container.PreMatching; +import javax.ws.rs.core.MediaType; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.UUID; + +@PreMatching +@Priority(AAIRequestFilterPriority.REQUEST_TRANS_LOGGING) +public class RequestTransactionLogging extends AAIContainerFilter implements ContainerRequestFilter { + + private static final String DEFAULT_CONTENT_TYPE = MediaType.APPLICATION_JSON; + private static final String DEFAULT_RESPONSE_TYPE = MediaType.APPLICATION_XML; + private static final String CONTENT_TYPE = "Content-Type"; + private static final String ACCEPT = "Accept"; + private static final String TEXT_PLAIN = "text/plain"; + @Autowired + private HttpServletRequest httpServletRequest; + + @Override + public void filter(ContainerRequestContext requestContext) { + + String currentTimeStamp = genDate(); + String fullId = this.getAAITxIdToHeader(); + this.addToRequestContext(requestContext, AAIHeaderProperties.AAI_TX_ID, fullId); + this.addToRequestContext(requestContext, AAIHeaderProperties.AAI_REQUEST, this.getRequest(requestContext, fullId)); + this.addToRequestContext(requestContext, AAIHeaderProperties.AAI_REQUEST_TS, currentTimeStamp); + this.addDefaultContentType(requestContext); + } + + private void addToRequestContext(ContainerRequestContext requestContext, String name, String aaiTxIdToHeader) { + requestContext.setProperty(name, aaiTxIdToHeader); + } + + private void addDefaultContentType(ContainerRequestContext requestContext) { + + String contentType = requestContext.getHeaderString(CONTENT_TYPE); + String acceptType = requestContext.getHeaderString(ACCEPT); + + if (contentType == null || contentType.contains(TEXT_PLAIN)) { + requestContext.getHeaders().putSingle(CONTENT_TYPE, DEFAULT_CONTENT_TYPE); + } + + if (StringUtils.isEmpty(acceptType) || acceptType.contains(TEXT_PLAIN)) { + requestContext.getHeaders().putSingle(ACCEPT, DEFAULT_RESPONSE_TYPE); + } + } + + private String getAAITxIdToHeader() { + String txId = UUID.randomUUID().toString(); + return txId; + } + + private String getRequest(ContainerRequestContext requestContext, String fullId) { + + JsonObject request = new JsonObject(); + request.addProperty("ID", fullId); + request.addProperty("Http-Method", requestContext.getMethod()); + request.addProperty(CONTENT_TYPE, httpServletRequest.getContentType()); + request.addProperty("Headers", requestContext.getHeaders().toString()); + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + InputStream in = requestContext.getEntityStream(); + + try { + if (in.available() > 0) { + ReaderWriter.writeTo(in, out); + byte[] requestEntity = out.toByteArray(); + request.addProperty("Payload", new String(requestEntity, "UTF-8")); + requestContext.setEntityStream(new ByteArrayInputStream(requestEntity)); + } + } catch (IOException ex) { + throw new ContainerException(ex); + } + + return request.toString(); + } + +} diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/pre/SetLoggingContext.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/pre/SetLoggingContext.java new file mode 100644 index 0000000..32802d1 --- /dev/null +++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/pre/SetLoggingContext.java @@ -0,0 +1,69 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 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. + * 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.schemaservice.interceptors.pre; + +import org.onap.aai.logging.LoggingContext; +import org.onap.aai.schemaservice.interceptors.AAIContainerFilter; +import org.onap.aai.schemaservice.interceptors.AAIHeaderProperties; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; + +import javax.annotation.Priority; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.container.PreMatching; +import java.io.IOException; + +@PreMatching +@Priority(AAIRequestFilterPriority.SET_LOGGING_CONTEXT) +public class SetLoggingContext extends AAIContainerFilter implements ContainerRequestFilter { + + @Autowired + private Environment environment; + + @Autowired + private HttpServletRequest httpServletRequest; + + @Override + public void filter(ContainerRequestContext requestContext) throws IOException { + + String uri = httpServletRequest.getRequestURI(); + String queryString = httpServletRequest.getQueryString(); + + if (queryString != null && !queryString.isEmpty()) { + uri = uri + "?" + queryString; + } + + String httpMethod = requestContext.getMethod(); + String transId = requestContext.getHeaderString(AAIHeaderProperties.TRANSACTION_ID); + String fromAppId = requestContext.getHeaderString(AAIHeaderProperties.FROM_APP_ID); + + LoggingContext.init(); + LoggingContext.requestId(transId); + LoggingContext.partnerName(fromAppId); + LoggingContext.targetEntity(environment.getProperty("spring.application.name")); + LoggingContext.component(fromAppId); + LoggingContext.serviceName(httpMethod + " " + uri); + LoggingContext.targetServiceName(httpMethod + " " + uri); + LoggingContext.statusCode(LoggingContext.StatusCode.COMPLETE); + } + +} diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/pre/TwoWaySslAuthorization.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/pre/TwoWaySslAuthorization.java new file mode 100644 index 0000000..4f69042 --- /dev/null +++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/pre/TwoWaySslAuthorization.java @@ -0,0 +1,187 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 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. + * 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.schemaservice.interceptors.pre; + +import org.onap.aai.auth.AAIAuthCore; +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.logging.ErrorLogHelper; +import org.onap.aai.restcore.HttpMethod; +import org.onap.aai.schemaservice.interceptors.AAIContainerFilter; +import org.onap.aai.schemaservice.interceptors.AAIHeaderProperties; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Profile; + +import javax.annotation.Priority; +import javax.security.auth.x500.X500Principal; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.container.PreMatching; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.security.cert.X509Certificate; +import java.util.*; +import java.util.stream.Collectors; + +@PreMatching +@Priority(AAIRequestFilterPriority.AUTHORIZATION) +@Profile("two-way-ssl") +public class TwoWaySslAuthorization extends AAIContainerFilter implements ContainerRequestFilter { + + private static final String PATCH = "PATCH"; + + @Autowired + private HttpServletRequest httpServletRequest; + + @Autowired + private AAIAuthCore aaiAuthCore; + + @Override + public void filter(ContainerRequestContext requestContext) { + + Optional<Response> oResp; + + String uri = requestContext.getUriInfo().getAbsolutePath().getPath(); + String httpMethod = getHttpMethod(requestContext); + + List<MediaType> acceptHeaderValues = requestContext.getAcceptableMediaTypes(); + + Optional<String> authUser = getUser(this.httpServletRequest); + + if (authUser.isPresent()) { + oResp = this.authorize(uri, httpMethod, acceptHeaderValues, authUser.get(), + this.getHaProxyUser(this.httpServletRequest), getCertIssuer(this.httpServletRequest)); + if (oResp.isPresent()) { + requestContext.abortWith(oResp.get()); + return; + } + } else { + AAIException aaie = new AAIException("AAI_9107"); + requestContext + .abortWith(Response + .status(aaie.getErrorObject().getHTTPResponseCode()).entity(ErrorLogHelper + .getRESTAPIErrorResponseWithLogging(acceptHeaderValues, aaie, new ArrayList<>())) + .build()); + } + + } + + private String getCertIssuer(HttpServletRequest hsr) { + String issuer = hsr.getHeader("X-AAI-SSL-Issuer"); + if (issuer != null && !issuer.isEmpty()) { + // the haproxy header replaces the ', ' with '/' and reverses on the '/' need to undo that. + List<String> broken = Arrays.asList(issuer.split("/")); + broken = broken.stream().filter(s -> !s.isEmpty()).collect(Collectors.toList()); + Collections.reverse(broken); + issuer = String.join(", ", broken); + } else { + if (hsr.getAttribute("javax.servlet.request.cipher_suite") != null) { + X509Certificate[] certChain = (X509Certificate[]) hsr.getAttribute("javax.servlet.request.X509Certificate"); + if (certChain != null && certChain.length > 0) { + X509Certificate clientCert = certChain[0]; + issuer = clientCert.getIssuerX500Principal().getName(); + } + } + } + return issuer; + } + + private String getHttpMethod(ContainerRequestContext requestContext) { + String httpMethod = requestContext.getMethod(); + if (javax.ws.rs.HttpMethod.POST.equalsIgnoreCase(httpMethod) + && PATCH.equals(requestContext.getHeaderString(AAIHeaderProperties.HTTP_METHOD_OVERRIDE))) { + httpMethod = HttpMethod.MERGE_PATCH.toString(); + } + if (httpMethod.equalsIgnoreCase(HttpMethod.MERGE_PATCH.toString()) || PATCH.equalsIgnoreCase(httpMethod)) { + httpMethod = HttpMethod.PUT.toString(); + } + return httpMethod; + } + + private Optional<String> getUser(HttpServletRequest hsr) { + String authUser = null; + if (hsr.getAttribute("javax.servlet.request.cipher_suite") != null) { + X509Certificate[] certChain = (X509Certificate[]) hsr.getAttribute("javax.servlet.request.X509Certificate"); + + /* + * If the certificate is null or the certificate chain length is zero Then + * retrieve the authorization in the request header Authorization Check that it + * is not null and that it starts with Basic and then strip the basic portion to + * get the base64 credentials Check if this is contained in the AAIBasicAuth + * Singleton class If it is, retrieve the username associated with that + * credentials and set to authUser Otherwise, get the principal from certificate + * and use that authUser + */ + + if (certChain == null || certChain.length == 0) { + + String authorization = hsr.getHeader("Authorization"); + + if (authorization != null && authorization.startsWith("Basic ")) { + authUser = authorization.substring(6); + } + + } else { + X509Certificate clientCert = certChain[0]; + X500Principal subjectDN = clientCert.getSubjectX500Principal(); + authUser = subjectDN.toString().toLowerCase(); + } + } + + return Optional.ofNullable(authUser); + } + + private String getHaProxyUser(HttpServletRequest hsr) { + String haProxyUser; + if (Objects.isNull(hsr.getHeader("X-AAI-SSL-Client-CN")) + || Objects.isNull(hsr.getHeader("X-AAI-SSL-Client-OU")) + || Objects.isNull(hsr.getHeader("X-AAI-SSL-Client-O")) + || Objects.isNull(hsr.getHeader("X-AAI-SSL-Client-L")) + || Objects.isNull(hsr.getHeader("X-AAI-SSL-Client-ST")) + || Objects.isNull(hsr.getHeader("X-AAI-SSL-Client-C"))) { + haProxyUser = ""; + } else { + haProxyUser = String.format("CN=%s, OU=%s, O=\"%s\", L=%s, ST=%s, C=%s", + Objects.toString(hsr.getHeader("X-AAI-SSL-Client-CN"), ""), + Objects.toString(hsr.getHeader("X-AAI-SSL-Client-OU"), ""), + Objects.toString(hsr.getHeader("X-AAI-SSL-Client-O"), ""), + Objects.toString(hsr.getHeader("X-AAI-SSL-Client-L"), ""), + Objects.toString(hsr.getHeader("X-AAI-SSL-Client-ST"), ""), + Objects.toString(hsr.getHeader("X-AAI-SSL-Client-C"), "")).toLowerCase(); + } + return haProxyUser; + } + + private Optional<Response> authorize(String uri, String httpMethod, List<MediaType> acceptHeaderValues, + String authUser, String haProxyUser, String issuer) { + Response response = null; + try { + if (!aaiAuthCore.authorize(authUser, uri, httpMethod, haProxyUser, issuer)) { + throw new AAIException("AAI_9101", "Request on " + httpMethod + " " + uri + " status is not OK"); + } + } catch (AAIException e) { + response = Response.status(e.getErrorObject().getHTTPResponseCode()) + .entity(ErrorLogHelper.getRESTAPIErrorResponseWithLogging(acceptHeaderValues, e, new ArrayList<>())) + .build(); + } + return Optional.ofNullable(response); + } + +} diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/logging/LocalHostAccessLog.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/logging/LocalHostAccessLog.java new file mode 100644 index 0000000..4da1122 --- /dev/null +++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/logging/LocalHostAccessLog.java @@ -0,0 +1,68 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 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. + * 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.schemaservice.logging; + +import ch.qos.logback.access.jetty.RequestLogImpl; +import org.eclipse.jetty.server.handler.HandlerCollection; +import org.eclipse.jetty.server.handler.RequestLogHandler; +import org.eclipse.jetty.util.thread.QueuedThreadPool; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory; +import org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainerFactory; +import org.springframework.boot.context.embedded.jetty.JettyServerCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.Arrays; + +@Configuration +public class LocalHostAccessLog { + + @Bean + public EmbeddedServletContainerFactory jettyConfigBean( + @Value("${jetty.threadPool.maxThreads:200}") final String maxThreads, + @Value("${jetty.threadPool.minThreads:8}") final String minThreads + ) { + + JettyEmbeddedServletContainerFactory jef = new JettyEmbeddedServletContainerFactory(); + jef.addServerCustomizers((JettyServerCustomizer) server -> { + + HandlerCollection handlers = new HandlerCollection(); + + Arrays.stream(server.getHandlers()).forEach(handlers::addHandler); + + RequestLogHandler requestLogHandler = new RequestLogHandler(); + requestLogHandler.setServer(server); + + RequestLogImpl requestLogImpl = new RequestLogImpl(); + requestLogImpl.setResource("/localhost-access-logback.xml"); + requestLogImpl.start(); + + requestLogHandler.setRequestLog(requestLogImpl); + handlers.addHandler(requestLogHandler); + server.setHandler(handlers); + + final QueuedThreadPool threadPool = server.getBean(QueuedThreadPool.class); + threadPool.setMaxThreads(Integer.valueOf(maxThreads)); + threadPool.setMinThreads(Integer.valueOf(minThreads)); + }); + return jef; + } +} diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/service/AuthorizationService.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/service/AuthorizationService.java new file mode 100644 index 0000000..1a83aa5 --- /dev/null +++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/service/AuthorizationService.java @@ -0,0 +1,109 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 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. + * 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.schemaservice.service; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import org.eclipse.jetty.util.security.Password; +import org.onap.aai.schemaservice.Profiles; +import org.onap.aai.util.AAIConstants; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +import javax.annotation.PostConstruct; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Base64; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Stream; + +@Profile(Profiles.ONE_WAY_SSL) +@Service +public class AuthorizationService { + + private static final EELFLogger logger = EELFManager.getInstance().getLogger(AuthorizationService.class); + + private final Map<String, String> authorizedUsers = new HashMap<>(); + + private static final Base64.Encoder ENCODER = Base64.getEncoder(); + + @PostConstruct + public void init(){ + + String basicAuthFile = getBasicAuthFilePath(); + + try(Stream<String> stream = Files.lines(Paths.get(basicAuthFile))){ + stream.filter(line -> !line.startsWith("#")).forEach(str -> { + byte [] bytes = null; + + String usernamePassword = null; + String accessType = null; + + try { + String [] userAccessType = str.split(","); + + if(userAccessType == null || userAccessType.length != 2){ + throw new RuntimeException("Please check the realm.properties file as it is not conforming to the basic auth"); + } + + usernamePassword = userAccessType[0]; + accessType = userAccessType[1]; + + String[] usernamePasswordArray = usernamePassword.split(":"); + + if(usernamePasswordArray == null || usernamePasswordArray.length != 3){ + throw new RuntimeException("Not a valid entry for the realm.properties entry: " + usernamePassword); + } + + String username = usernamePasswordArray[0]; + String password = null; + + if(str.contains("OBF:")){ + password = usernamePasswordArray[1] + ":" + usernamePasswordArray[2]; + password = Password.deobfuscate(password); + } + + bytes = ENCODER.encode((username + ":" + password).getBytes("UTF-8")); + + authorizedUsers.put(new String(bytes), accessType); + + } catch (UnsupportedEncodingException e) + { + logger.error("Unable to support the encoding of the file" + basicAuthFile); + } + + authorizedUsers.put(new String(ENCODER.encode(bytes)), accessType); + }); + } catch (IOException e) { + logger.error("IO Exception occurred during the reading of realm.properties", e); + } + } + + public boolean checkIfUserAuthorized(String authorization){ + return authorizedUsers.containsKey(authorization) && "admin".equals(authorizedUsers.get(authorization)); + } + + public String getBasicAuthFilePath(){ + return AAIConstants.AAI_HOME_ETC_AUTH + AAIConstants.AAI_FILESEP + "realm.properties"; + } +} diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/web/JerseyConfiguration.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/web/JerseyConfiguration.java new file mode 100644 index 0000000..fa2327a --- /dev/null +++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/web/JerseyConfiguration.java @@ -0,0 +1,122 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 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. + * 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.schemaservice.web; + +import org.glassfish.jersey.server.ResourceConfig; +import org.reflections.Reflections; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Profile; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Component; + +import javax.annotation.Priority; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.container.ContainerResponseFilter; +import java.util.List; +import java.util.Set; +import java.util.logging.Logger; +import java.util.stream.Collectors; + +@Component +public class JerseyConfiguration extends ResourceConfig { + + private static final Logger log = Logger.getLogger(JerseyConfiguration.class.getName()); + + private Environment env; + + @Autowired + public JerseyConfiguration(Environment env) { + + this.env = env; + + //Request Filters + registerFiltersForRequests(); + // Response Filters + registerFiltersForResponses(); + + } + + public void registerFiltersForRequests() { + + // Find all the classes within the interceptors package + Reflections reflections = new Reflections("org.onap.aai.schemaservice.interceptors"); + // Filter them based on the clazz that was passed in + Set<Class<? extends ContainerRequestFilter>> filters = reflections.getSubTypesOf(ContainerRequestFilter.class); + + + // Check to ensure that each of the filter has the @Priority annotation and if not throw exception + for (Class filterClass : filters) { + if (filterClass.getAnnotation(Priority.class) == null) { + throw new RuntimeException("Container filter " + filterClass.getName() + " does not have @Priority annotation"); + } + } + + // Turn the set back into a list + List<Class<? extends ContainerRequestFilter>> filtersList = filters + .stream() + .filter(f -> { + if (f.isAnnotationPresent(Profile.class) + && !env.acceptsProfiles(f.getAnnotation(Profile.class).value())) { + return false; + } + return true; + }) + .collect(Collectors.toList()); + + // Sort them by their priority levels value + filtersList.sort((c1, c2) -> Integer.valueOf(c1.getAnnotation(Priority.class).value()).compareTo(c2.getAnnotation(Priority.class).value())); + + // Then register this to the jersey application + filtersList.forEach(this::register); + } + + public void registerFiltersForResponses() { + + // Find all the classes within the interceptors package + Reflections reflections = new Reflections("org.onap.aai.schemaservice.interceptors"); + // Filter them based on the clazz that was passed in + Set<Class<? extends ContainerResponseFilter>> filters = reflections.getSubTypesOf(ContainerResponseFilter.class); + + + // Check to ensure that each of the filter has the @Priority annotation and if not throw exception + for (Class filterClass : filters) { + if (filterClass.getAnnotation(Priority.class) == null) { + throw new RuntimeException("Container filter " + filterClass.getName() + " does not have @Priority annotation"); + } + } + + // Turn the set back into a list + List<Class<? extends ContainerResponseFilter>> filtersList = filters.stream() + .filter(f -> { + if (f.isAnnotationPresent(Profile.class) + && !env.acceptsProfiles(f.getAnnotation(Profile.class).value())) { + return false; + } + return true; + }) + .collect(Collectors.toList()); + + // Sort them by their priority levels value + filtersList.sort((c1, c2) -> Integer.valueOf(c1.getAnnotation(Priority.class).value()).compareTo(c2.getAnnotation(Priority.class).value())); + + // Then register this to the jersey application + filtersList.forEach(this::register); + } +} |