summaryrefslogtreecommitdiffstats
path: root/aai-schema-service/src/main/java/org/onap
diff options
context:
space:
mode:
authorKajur, Harish (vk250x) <vk250x@att.com>2018-11-26 00:07:25 -0500
committerKajur, Harish (vk250x) <vk250x@att.com>2018-11-27 07:04:01 -0500
commitd64d789ad789e950c3b5e5443fb418a722b917c4 (patch)
treeaf2a2f938963447cfcc72d20dc455c3a79b148f0 /aai-schema-service/src/main/java/org/onap
parentd943652dd8e2cdcb087cab16271cc0c4fd4a1385 (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')
-rw-r--r--aai-schema-service/src/main/java/org/onap/aai/schemaservice/Profiles.java32
-rw-r--r--aai-schema-service/src/main/java/org/onap/aai/schemaservice/SchemaServiceApp.java153
-rw-r--r--aai-schema-service/src/main/java/org/onap/aai/schemaservice/config/ErrorHandler.java143
-rw-r--r--aai-schema-service/src/main/java/org/onap/aai/schemaservice/config/JettyPasswordDecoder.java33
-rw-r--r--aai-schema-service/src/main/java/org/onap/aai/schemaservice/config/PasswordDecoder.java25
-rw-r--r--aai-schema-service/src/main/java/org/onap/aai/schemaservice/config/PropertyPasswordConfiguration.java78
-rw-r--r--aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/AAIContainerFilter.java41
-rw-r--r--aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/AAIHeaderProperties.java34
-rw-r--r--aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/package-info.java36
-rw-r--r--aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/post/AAIResponseFilterPriority.java38
-rw-r--r--aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/post/InvalidResponseStatus.java65
-rw-r--r--aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/post/ResetLoggingContext.java96
-rw-r--r--aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/post/ResponseHeaderManipulation.java64
-rw-r--r--aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/post/ResponseTransactionLogging.java124
-rw-r--r--aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/pre/AAIRequestFilterPriority.java34
-rw-r--r--aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/pre/HeaderValidation.java86
-rw-r--r--aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/pre/HttpHeaderInterceptor.java50
-rw-r--r--aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/pre/OneWaySslAuthorization.java82
-rw-r--r--aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/pre/RequestHeaderManipulation.java63
-rw-r--r--aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/pre/RequestTransactionLogging.java113
-rw-r--r--aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/pre/SetLoggingContext.java69
-rw-r--r--aai-schema-service/src/main/java/org/onap/aai/schemaservice/interceptors/pre/TwoWaySslAuthorization.java187
-rw-r--r--aai-schema-service/src/main/java/org/onap/aai/schemaservice/logging/LocalHostAccessLog.java68
-rw-r--r--aai-schema-service/src/main/java/org/onap/aai/schemaservice/service/AuthorizationService.java109
-rw-r--r--aai-schema-service/src/main/java/org/onap/aai/schemaservice/web/JerseyConfiguration.java122
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);
+ }
+}