From 5aa8aec689a399e7803e84e531532d0c61631ec1 Mon Sep 17 00:00:00 2001 From: Instrumental Date: Wed, 7 Nov 2018 20:52:15 -0600 Subject: Fix/Renable sidecar builds Issue-ID: AAF-613 Change-Id: Ic13411eebbf3c1c9b6d8492aff1b37db37a965e4 Signed-off-by: Instrumental --- sidecar/rproxy/.gitignore | 1 + sidecar/rproxy/pom.xml | 24 +- .../ReverseProxyEntryExitLoggingAspect.java | 45 ++++ .../rpoxy/logging/ReverseProxyMethodLogTime.java | 51 ++++ .../ReverseProxyMethodLogTimeAnnotation.java | 30 +++ .../sidecar/rproxy/ReverseProxyApplication.java | 182 ++++++++++++++ .../rproxy/ReverseProxyAuthorizationFilter.java | 216 +++++++++++++++++ .../cadi/sidecar/rproxy/ReverseProxyService.java | 167 +++++++++++++ .../cadi/sidecar/rproxy/config/CadiProperties.java | 41 ++++ .../rproxy/config/ForwardProxyProperties.java | 67 ++++++ .../rproxy/config/PrimaryServiceProperties.java | 58 +++++ .../rproxy/config/ReverseProxySSLProperties.java | 56 +++++ .../ReverseProxyURIAuthorizationProperties.java | 38 +++ .../rproxy/mocks/ReverseProxyMockCadiFilter.java | 143 +++++++++++ .../rproxy/utils/ReverseProxyAuthorization.java | 34 +++ .../sidecar/rproxy/utils/ReverseProxyUtils.java | 29 +++ .../onap/aaf/rproxy/ReverseProxyApplication.java | 182 -------------- .../rproxy/ReverseProxyAuthorizationFilter.java | 216 ----------------- .../org/onap/aaf/rproxy/ReverseProxyService.java | 166 ------------- .../org/onap/aaf/rproxy/config/CadiProperties.java | 41 ---- .../aaf/rproxy/config/ForwardProxyProperties.java | 67 ------ .../rproxy/config/PrimaryServiceProperties.java | 58 ----- .../rproxy/config/ReverseProxySSLProperties.java | 56 ----- .../ReverseProxyURIAuthorizationProperties.java | 38 --- .../ReverseProxyEntryExitLoggingAspect.java | 45 ---- .../rproxy/logging/ReverseProxyMethodLogTime.java | 51 ---- .../ReverseProxyMethodLogTimeAnnotation.java | 30 --- .../rproxy/mocks/ReverseProxyMockCadiFilter.java | 143 ----------- .../rproxy/utils/ReverseProxyAuthorization.java | 34 --- .../onap/aaf/rproxy/utils/ReverseProxyUtils.java | 29 --- .../rproxy/test/PermissionMatchingTest.java | 262 +++++++++++++++++++++ .../rproxy/test/ReverseProxyApplicationTest.java | 158 +++++++++++++ .../cadi/sidecar/rproxy/test/ReverseProxyIT.java | 49 ++++ .../rproxy/test/ReverseProxyTestConfig.java | 42 ++++ .../onap/aaf/rproxy/PermissionMatchingTest.java | 262 --------------------- .../aaf/rproxy/ReverseProxyApplicationTest.java | 158 ------------- .../java/org/onap/aaf/rproxy/ReverseProxyIT.java | 48 ---- .../onap/aaf/rproxy/ReverseProxyTestConfig.java | 42 ---- 38 files changed, 1682 insertions(+), 1677 deletions(-) create mode 100644 sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rpoxy/logging/ReverseProxyEntryExitLoggingAspect.java create mode 100644 sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rpoxy/logging/ReverseProxyMethodLogTime.java create mode 100644 sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rpoxy/logging/ReverseProxyMethodLogTimeAnnotation.java create mode 100644 sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/ReverseProxyApplication.java create mode 100644 sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/ReverseProxyAuthorizationFilter.java create mode 100644 sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/ReverseProxyService.java create mode 100644 sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/config/CadiProperties.java create mode 100644 sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/config/ForwardProxyProperties.java create mode 100644 sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/config/PrimaryServiceProperties.java create mode 100644 sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/config/ReverseProxySSLProperties.java create mode 100644 sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/config/ReverseProxyURIAuthorizationProperties.java create mode 100644 sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/mocks/ReverseProxyMockCadiFilter.java create mode 100644 sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/utils/ReverseProxyAuthorization.java create mode 100644 sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/utils/ReverseProxyUtils.java delete mode 100644 sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/ReverseProxyApplication.java delete mode 100644 sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/ReverseProxyAuthorizationFilter.java delete mode 100644 sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/ReverseProxyService.java delete mode 100644 sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/config/CadiProperties.java delete mode 100644 sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/config/ForwardProxyProperties.java delete mode 100644 sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/config/PrimaryServiceProperties.java delete mode 100644 sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/config/ReverseProxySSLProperties.java delete mode 100644 sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/config/ReverseProxyURIAuthorizationProperties.java delete mode 100644 sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/logging/ReverseProxyEntryExitLoggingAspect.java delete mode 100644 sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/logging/ReverseProxyMethodLogTime.java delete mode 100644 sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/logging/ReverseProxyMethodLogTimeAnnotation.java delete mode 100644 sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/mocks/ReverseProxyMockCadiFilter.java delete mode 100644 sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/utils/ReverseProxyAuthorization.java delete mode 100644 sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/utils/ReverseProxyUtils.java create mode 100644 sidecar/rproxy/src/test/java/org/onap/aaf/cadi/sidecar/rproxy/test/PermissionMatchingTest.java create mode 100644 sidecar/rproxy/src/test/java/org/onap/aaf/cadi/sidecar/rproxy/test/ReverseProxyApplicationTest.java create mode 100644 sidecar/rproxy/src/test/java/org/onap/aaf/cadi/sidecar/rproxy/test/ReverseProxyIT.java create mode 100644 sidecar/rproxy/src/test/java/org/onap/aaf/cadi/sidecar/rproxy/test/ReverseProxyTestConfig.java delete mode 100644 sidecar/rproxy/src/test/java/org/onap/aaf/rproxy/PermissionMatchingTest.java delete mode 100644 sidecar/rproxy/src/test/java/org/onap/aaf/rproxy/ReverseProxyApplicationTest.java delete mode 100644 sidecar/rproxy/src/test/java/org/onap/aaf/rproxy/ReverseProxyIT.java delete mode 100644 sidecar/rproxy/src/test/java/org/onap/aaf/rproxy/ReverseProxyTestConfig.java (limited to 'sidecar/rproxy') diff --git a/sidecar/rproxy/.gitignore b/sidecar/rproxy/.gitignore index 6028f0a..f3bad09 100644 --- a/sidecar/rproxy/.gitignore +++ b/sidecar/rproxy/.gitignore @@ -2,3 +2,4 @@ /.settings/ /target/ /.project +/logs/ diff --git a/sidecar/rproxy/pom.xml b/sidecar/rproxy/pom.xml index 6c32238..57f5f0d 100644 --- a/sidecar/rproxy/pom.xml +++ b/sidecar/rproxy/pom.xml @@ -40,6 +40,7 @@ org.springframework.boot spring-boot-starter-web + @@ -57,11 +60,6 @@ spring-boot-starter-jetty - - org.apache.httpcomponents - httpclient - - org.springframework.boot spring-boot-starter-aop @@ -70,7 +68,16 @@ org.springframework.boot spring-boot-starter-test - test + + + + org.apache.httpcomponents + httpclient + + + + org.aspectj + aspectjrt @@ -85,11 +92,6 @@ gson - - org.mockito - mockito-core - - diff --git a/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rpoxy/logging/ReverseProxyEntryExitLoggingAspect.java b/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rpoxy/logging/ReverseProxyEntryExitLoggingAspect.java new file mode 100644 index 0000000..b6e2f85 --- /dev/null +++ b/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rpoxy/logging/ReverseProxyEntryExitLoggingAspect.java @@ -0,0 +1,45 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aaf + * ================================================================================ + * Copyright © 2018 European Software Marketing Ltd. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aaf.cadi.sidecar.rpoxy.logging; + +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.After; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +@Aspect +@Component +public class ReverseProxyEntryExitLoggingAspect { + + private static final Logger LOGGER = LoggerFactory.getLogger(ReverseProxyEntryExitLoggingAspect.class); + + @Before("execution(* org.onap.platform.security.*.*(..))") + public void before(JoinPoint joinPoint) { + LOGGER.info("Entry of {}#{}", joinPoint.getTarget().getClass(), joinPoint.getSignature().getName()); + } + + @After("execution(* org.onap.platform.security.*.*(..))") + public void after(JoinPoint joinPoint) { + LOGGER.info("Exit of {}#{}", joinPoint.getTarget().getClass(), joinPoint.getSignature().getName()); + } +} diff --git a/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rpoxy/logging/ReverseProxyMethodLogTime.java b/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rpoxy/logging/ReverseProxyMethodLogTime.java new file mode 100644 index 0000000..bc3a489 --- /dev/null +++ b/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rpoxy/logging/ReverseProxyMethodLogTime.java @@ -0,0 +1,51 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aaf + * ================================================================================ + * Copyright © 2018 European Software Marketing Ltd. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aaf.cadi.sidecar.rpoxy.logging; + +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Configuration; + +@Aspect +@Configuration +public class ReverseProxyMethodLogTime { + + private static final Logger LOGGER = LoggerFactory.getLogger(ReverseProxyMethodLogTime.class); + + @Around("@annotation(org.onap.aaf.rproxy.logging.ReverseProxyMethodLogTimeAnnotation)") + public Object around(ProceedingJoinPoint joinPoint) throws Throwable { + + long startTime = System.currentTimeMillis(); + + Object object = joinPoint.proceed(); + + long duration = System.currentTimeMillis() - startTime; + + LOGGER.info("Time taken by {} is {} ms", joinPoint, duration); + + return object; + } + + + +} diff --git a/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rpoxy/logging/ReverseProxyMethodLogTimeAnnotation.java b/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rpoxy/logging/ReverseProxyMethodLogTimeAnnotation.java new file mode 100644 index 0000000..ddd6fe9 --- /dev/null +++ b/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rpoxy/logging/ReverseProxyMethodLogTimeAnnotation.java @@ -0,0 +1,30 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aaf + * ================================================================================ + * Copyright © 2018 European Software Marketing Ltd. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aaf.cadi.sidecar.rpoxy.logging; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface ReverseProxyMethodLogTimeAnnotation { +} diff --git a/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/ReverseProxyApplication.java b/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/ReverseProxyApplication.java new file mode 100644 index 0000000..3e36935 --- /dev/null +++ b/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/ReverseProxyApplication.java @@ -0,0 +1,182 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aaf + * ================================================================================ + * Copyright © 2018 European Software Marketing Ltd. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aaf.cadi.sidecar.rproxy; + +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.util.HashMap; +import java.util.Properties; +import javax.annotation.PostConstruct; +import javax.annotation.Resource; +import javax.net.ssl.SSLContext; +import org.apache.http.conn.ssl.NoopHostnameVerifier; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.ssl.SSLContextBuilder; +import org.eclipse.jetty.util.security.Password; +import org.onap.aaf.cadi.filter.CadiFilter; +import org.onap.aaf.cadi.sidecar.rproxy.config.ForwardProxyProperties; +import org.onap.aaf.cadi.sidecar.rproxy.config.PrimaryServiceProperties; +import org.onap.aaf.cadi.sidecar.rproxy.config.ReverseProxySSLProperties; +import org.onap.aaf.cadi.sidecar.rproxy.mocks.ReverseProxyMockCadiFilter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.boot.web.servlet.RegistrationBean; +import org.springframework.boot.web.servlet.ServletComponentScan; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Profile; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.util.ResourceUtils; +import org.springframework.web.client.RestTemplate; + +@SpringBootApplication +@ServletComponentScan +@EnableConfigurationProperties(ReverseProxySSLProperties.class) +@PropertySource("file:${CONFIG_HOME}/reverse-proxy.properties") +public class ReverseProxyApplication extends SpringBootServletInitializer { + + private static final String CADI_TRUSTSTORE_PASS = "cadi_truststore_password"; + + @Autowired + private Environment env; + + /** + * Spring Boot Initialisation. + * + * @param args main args + */ + public static void main(String[] args) { + String keyStorePassword = System.getProperty("KEY_STORE_PASSWORD"); + if (keyStorePassword == null || keyStorePassword.isEmpty()) { + throw new IllegalArgumentException("Env property KEY_STORE_PASSWORD not set"); + } + HashMap props = new HashMap<>(); + props.put("server.ssl.key-store-password", Password.deobfuscate(keyStorePassword)); + new ReverseProxyApplication() + .configure(new SpringApplicationBuilder(ReverseProxyApplication.class).properties(props)).run(args); + } + + /** + * Set required trust store system properties using values from application.properties + */ + @PostConstruct + public void setSystemProperties() { + String keyStorePath = env.getProperty("server.ssl.key-store"); + if (keyStorePath != null) { + String keyStorePassword = env.getProperty("server.ssl.key-store-password"); + + if (keyStorePassword != null) { + System.setProperty("javax.net.ssl.keyStore", keyStorePath); + System.setProperty("javax.net.ssl.keyStorePassword", keyStorePassword); + System.setProperty("javax.net.ssl.trustStore", keyStorePath); + System.setProperty("javax.net.ssl.trustStorePassword", keyStorePassword); + } else { + throw new IllegalArgumentException("Env property server.ssl.key-store-password not set"); + } + } + } + + @Resource + private ReverseProxySSLProperties reverseProxySSLProperties; + + @Resource + Properties cadiProps; + + @Bean(name = "ForwardProxyProperties") + public ForwardProxyProperties forwardProxyProperties() { + return new ForwardProxyProperties(); + } + + @Bean(name = "PrimaryServiceProperties") + public PrimaryServiceProperties primaryServiceProperties() { + return new PrimaryServiceProperties(); + } + + @Profile("secure") + @Bean + public RestTemplate restTemplate(RestTemplateBuilder builder) throws GeneralSecurityException, IOException { + return new RestTemplate(new HttpComponentsClientHttpRequestFactory(getClientBuilder().build())); + } + + @Profile("noHostVerification") + @Bean + public RestTemplate restTemplateNoHostVerification(RestTemplateBuilder builder) + throws GeneralSecurityException, IOException { + return new RestTemplate(new HttpComponentsClientHttpRequestFactory( + getClientBuilder().setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE).build())); + } + + private HttpClientBuilder getClientBuilder() throws GeneralSecurityException, IOException { + + SSLContext sslContext = SSLContextBuilder.create() + .loadKeyMaterial(ResourceUtils.getFile(reverseProxySSLProperties.getClientcert()), + reverseProxySSLProperties.getKeystorePassword().toCharArray(), + reverseProxySSLProperties.getKeystorePassword().toCharArray()) + .loadTrustMaterial(ResourceUtils.getFile(reverseProxySSLProperties.getKeystore()), + reverseProxySSLProperties.getKeystorePassword().toCharArray()) + .build(); + + return HttpClients.custom().setSSLContext(sslContext); + } + + @Profile("cadi") + @Bean + public FilterRegistrationBean registerCADIFilter() { + + FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean<>(); + + filterRegistrationBean.setFilter(new CadiFilter()); + filterRegistrationBean.addUrlPatterns("/*"); + filterRegistrationBean.setName("CADIFilter"); + filterRegistrationBean.setOrder(RegistrationBean.HIGHEST_PRECEDENCE); + + // Deobfuscate truststore password + String trustStorePassword = cadiProps.getProperty(CADI_TRUSTSTORE_PASS); + if (trustStorePassword != null) { + cadiProps.setProperty(CADI_TRUSTSTORE_PASS, Password.deobfuscate(trustStorePassword)); + } + + // Add filter init params + cadiProps.forEach((k, v) -> filterRegistrationBean.addInitParameter((String) k, (String) v)); + + return filterRegistrationBean; + } + + @Profile("mockCadi") + @Bean + public FilterRegistrationBean registerMockCADIFilter() { + + FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean<>(); + + filterRegistrationBean.setFilter(new ReverseProxyMockCadiFilter()); + filterRegistrationBean.addUrlPatterns("/*"); + filterRegistrationBean.setName("CADIFilter"); + filterRegistrationBean.setOrder(RegistrationBean.HIGHEST_PRECEDENCE); + + return filterRegistrationBean; + } +} diff --git a/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/ReverseProxyAuthorizationFilter.java b/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/ReverseProxyAuthorizationFilter.java new file mode 100644 index 0000000..2ef4cc0 --- /dev/null +++ b/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/ReverseProxyAuthorizationFilter.java @@ -0,0 +1,216 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aaf + * ================================================================================ + * Copyright © 2018 European Software Marketing Ltd. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aaf.cadi.sidecar.rproxy; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URI; +import java.net.URISyntaxException; +import java.security.Principal; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import javax.annotation.Resource; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.eclipse.jetty.http.HttpStatus; +import org.onap.aaf.cadi.CadiWrap; +import org.onap.aaf.cadi.Permission; +import org.onap.aaf.cadi.sidecar.rproxy.config.ReverseProxyURIAuthorizationProperties; +import org.onap.aaf.cadi.sidecar.rproxy.utils.ReverseProxyAuthorization; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +@Component +@Order(1) +@EnableConfigurationProperties(ReverseProxyURIAuthorizationProperties.class) +public class ReverseProxyAuthorizationFilter implements Filter { + + private static final Logger LOGGER = LoggerFactory.getLogger(ReverseProxyAuthorizationFilter.class); + + private List reverseProxyAuthorizations = new ArrayList<>(); + + @Resource + private ReverseProxyURIAuthorizationProperties reverseProxyURIAuthorizationProperties; + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + + // Read in the URI Authorisation configuration file + String authFilePath = reverseProxyURIAuthorizationProperties.getConfigurationFile(); + if (authFilePath != null) { + try (InputStream inputStream = + new FileInputStream(new File(reverseProxyURIAuthorizationProperties.getConfigurationFile())); + JsonReader jsonReader = new JsonReader(new InputStreamReader(inputStream))) { + List untrimmedList = new Gson().fromJson(jsonReader, + new TypeToken>() {}.getType()); + untrimmedList.removeAll(Collections.singleton(null)); + reverseProxyAuthorizations = untrimmedList; + } catch (IOException e) { + throw new ServletException("Authorizations config file not found.", e); + } + } + } + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) + throws IOException, ServletException { + + CadiWrap cadiWrap = (CadiWrap) servletRequest; + Principal principal = cadiWrap.getUserPrincipal(); + List grantedPermissions = new ArrayList<>(); + cadiWrap.getLur().fishAll(principal, grantedPermissions); + + if (LOGGER.isDebugEnabled()) { + logNeededPermissions(); + } + + String requestPath; + try { + requestPath = new URI(((HttpServletRequest) servletRequest).getRequestURI()).getPath(); + } catch (URISyntaxException e) { + throw new ServletException("Request URI not valid", e); + } + + if (authorizeRequest(grantedPermissions, requestPath)) { + LOGGER.info("Authorized"); + filterChain.doFilter(servletRequest, servletResponse); + } else { + LOGGER.info("Unauthorized"); + ((HttpServletResponse) servletResponse).setStatus(HttpStatus.FORBIDDEN_403); + ((HttpServletResponse) servletResponse).setContentType("application/json"); + ((HttpServletResponse) servletResponse).sendError(HttpStatus.FORBIDDEN_403, + "Sorry, the request is not allowed"); + } + } + + /** + * Check if the granted permissions for the request path matches the configured needed permissions. + * + * @param grantedPermissions The granted permissions for the request path + * @param requestPath The request path + * @return true if permissions match + */ + private boolean authorizeRequest(List grantedPermissions, String requestPath) { + boolean authorized = false; + for (ReverseProxyAuthorization reverseProxyAuthorization : reverseProxyAuthorizations) { + if (requestPath.matches(reverseProxyAuthorization.getUri())) { + LOGGER.debug("The URI:{} matches:{}", requestPath, reverseProxyAuthorization.getUri()); + if (checkPermissionsMatch(grantedPermissions, reverseProxyAuthorization)) { + authorized = true; + break; + } + } else { + LOGGER.debug("The URI:{} doesn't match any in the configuration:{}", requestPath, + reverseProxyAuthorization.getUri()); + } + } + return authorized; + } + + /** + * Check all needed permissions match the granted permissions. + * + * @param grantedPermissions the granted permissions + * @param reverseProxyAuthorization the bean that contains the needed permissions + * @return true if all needed permissions match + */ + private boolean checkPermissionsMatch(List grantedPermissions, + ReverseProxyAuthorization reverseProxyAuthorization) { + + boolean matchedAllPermissions = true; + for (String neededPermission : reverseProxyAuthorization.getPermissions()) { + + // Check needed permission is granted + boolean matchedNeededPermission = false; + for (Permission grantedPermission : grantedPermissions) { + if (checkGrantedPermission(neededPermission, grantedPermission.getKey())) { + LOGGER.debug("Permission match found - needed permission:{}, granted permission:{}", + neededPermission, grantedPermission.getKey()); + matchedNeededPermission = true; + break; + } + } + if (!matchedNeededPermission) { + matchedAllPermissions = false; + break; + } + } + return matchedAllPermissions; + } + + /** + * Check whether an AAF style permission matches a needed permission. Wildcards (*) are supported. + * + * @param neededPermission, the needed permission + * @param grantedPermission, the granted permission + * + * @return true if the needed permission matches a granted permission + */ + private boolean checkGrantedPermission(String neededPermission, String grantedPermission) { + boolean permissionMatch = false; + if (grantedPermission.matches(neededPermission)) { + permissionMatch = true; + } else if (grantedPermission.contains("*")) { + String[] splitNeededPermission = neededPermission.split("\\\\\\|"); + String[] splitGrantedPermission = grantedPermission.split("\\|"); + if ((splitGrantedPermission[0].matches(splitNeededPermission[0])) + && (splitGrantedPermission[1].equals("*") + || splitGrantedPermission[1].matches(splitNeededPermission[1])) + && (splitGrantedPermission[2].equals("*") + || splitGrantedPermission[2].matches(splitNeededPermission[2]))) { + permissionMatch = true; + } + } + return permissionMatch; + } + + /** + * Log the needed permissions for each URL configured. + */ + private void logNeededPermissions() { + for (ReverseProxyAuthorization reverseProxyAuthorization : reverseProxyAuthorizations) { + LOGGER.debug("URI For authorization: {}", reverseProxyAuthorization.getUri()); + for (String permission : reverseProxyAuthorization.getPermissions()) { + LOGGER.debug("\t Needed permission:{}", permission); + } + } + } + + @Override + public void destroy() { + // No op + } +} diff --git a/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/ReverseProxyService.java b/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/ReverseProxyService.java new file mode 100644 index 0000000..e15fb2a --- /dev/null +++ b/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/ReverseProxyService.java @@ -0,0 +1,167 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aaf + * ================================================================================ + * Copyright © 2018 European Software Marketing Ltd. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aaf.cadi.sidecar.rproxy; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Enumeration; +import java.util.UUID; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; + +import org.onap.aaf.cadi.sidecar.fproxy.data.CredentialCacheData; +import org.onap.aaf.cadi.sidecar.fproxy.data.CredentialCacheData.CredentialType; +import org.onap.aaf.cadi.sidecar.rpoxy.logging.ReverseProxyMethodLogTimeAnnotation; +import org.onap.aaf.cadi.sidecar.rproxy.config.ForwardProxyProperties; +import org.onap.aaf.cadi.sidecar.rproxy.config.PrimaryServiceProperties; +import org.onap.aaf.cadi.sidecar.rproxy.utils.ReverseProxyUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.RestTemplate; + +@RestController +@EnableConfigurationProperties({ForwardProxyProperties.class, PrimaryServiceProperties.class}) +public class ReverseProxyService { + + private static final Logger LOGGER = LoggerFactory.getLogger(ReverseProxyService.class); + + private String validatedTransactionId; + + @Resource(name = "ForwardProxyProperties") + private ForwardProxyProperties forwardProxyProperties; + + @Resource(name = "PrimaryServiceProperties") + private PrimaryServiceProperties primaryServiceProperties; + + @Autowired + private RestTemplate restTemplate; + + @Value("${transactionid.header.name}") + private String transactionIdHeader; + + @RequestMapping("/**") + @ReverseProxyMethodLogTimeAnnotation + public ResponseEntity handleRequest(HttpServletRequest request, + @RequestHeader(value = "${transactionid.header.name}", defaultValue = "") String transactionId, + @RequestBody(required = false) String requestBody, HttpMethod requestMethod) throws URISyntaxException { + validatedTransactionId = getValidTransactionId(transactionId); + + // Extract Request Permissions and store in Forward Proxy cache + CredentialCacheData credentialCacheData = getCredentialDataFromRequest(request); + if (credentialCacheData != null) { + postCredentialsToCache(credentialCacheData); + } + + // Call out to Primary Service & Return Response + URI requestURI = new URI(request.getRequestURI()); + + LOGGER.debug("Request URI: {}", request.getRequestURI()); + + // Get Request Endpoint & substitute in local values + URI primaryServiceURI = new URI(primaryServiceProperties.getProtocol(), requestURI.getUserInfo(), + primaryServiceProperties.getHost(), Integer.parseInt(primaryServiceProperties.getPort()), + requestURI.getPath(), requestURI.getQuery(), requestURI.getFragment()); + + LOGGER.debug("Primary Service URI:{}, HTTP Method: {}", primaryServiceURI, requestMethod); + + HttpHeaders requestHeaders = setForwardedRequestHeaders(request); + HttpEntity httpEntity = new HttpEntity<>(requestBody, requestHeaders); + + return restTemplate.exchange(primaryServiceURI, requestMethod, httpEntity, String.class); + } + + private String getValidTransactionId(String transactionId) { + LOGGER.debug("Request transaction ID: {}", transactionId); + if (transactionId == null || !ReverseProxyUtils.validTransactionId(transactionId)) { + transactionId = UUID.randomUUID().toString(); + } + LOGGER.debug("Validated transaction ID: {}", transactionId); + return transactionId; + } + + private HttpHeaders setForwardedRequestHeaders(HttpServletRequest httpServletRequest) { + HttpHeaders httpHeaders = new HttpHeaders(); + Enumeration headerNames = httpServletRequest.getHeaderNames(); + while (headerNames.hasMoreElements()) { + String headerName = headerNames.nextElement(); + if (!headerName.equals(transactionIdHeader)) { + httpHeaders.set(headerName, httpServletRequest.getHeader(headerName)); + } + } + // Always set transaction ID + httpHeaders.set(transactionIdHeader, validatedTransactionId); + + return httpHeaders; + } + + /** + * Retrieves credential data from request. + * + * @param request The request to retrieve credentials from + * @return The retrieved credential data, or null if no credentials are found in request + */ + private CredentialCacheData getCredentialDataFromRequest(HttpServletRequest request) { + CredentialCacheData credentialCacheData = null; + String authValue = request.getHeader(HttpHeaders.AUTHORIZATION); + if (authValue != null) { + credentialCacheData = new CredentialCacheData(HttpHeaders.AUTHORIZATION, authValue, CredentialType.HEADER); + } + return credentialCacheData; + } + + /** + * Posts credential data to credential cache endpoint + * + * @param credentialCacheData The credential data to post + * @throws URISyntaxException + */ + private void postCredentialsToCache(CredentialCacheData credentialCacheData) throws URISyntaxException { + URI forwardProxyURI = new URI(forwardProxyProperties.getProtocol(), null, forwardProxyProperties.getHost(), + forwardProxyProperties.getPort(), forwardProxyProperties.getCacheurl() + "/" + validatedTransactionId, + null, null); + + ResponseEntity response = + restTemplate.postForEntity(forwardProxyURI, credentialCacheData, String.class); + + if (!response.getStatusCode().is2xxSuccessful()) { + throw new HttpClientErrorException(response.getStatusCode(), + "Error posting to credential cache. Message: " + response.getBody()); + } + } + + @Override + public String toString() { + return this.getClass().getName() + ": Forward proxy host:" + forwardProxyProperties.getHost() + + ": Primary service host:" + primaryServiceProperties.getHost(); + + } +} diff --git a/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/config/CadiProperties.java b/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/config/CadiProperties.java new file mode 100644 index 0000000..841d8d8 --- /dev/null +++ b/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/config/CadiProperties.java @@ -0,0 +1,41 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aaf + * ================================================================================ + * Copyright © 2018 European Software Marketing Ltd. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aaf.cadi.sidecar.rproxy.config; + +import java.net.MalformedURLException; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.beans.factory.config.PropertiesFactoryBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.UrlResource; + +@Configuration +public class CadiProperties { + + @Value("${CONFIG_HOME}") + private String configHome; + + @Bean(name = "cadiProps") + public PropertiesFactoryBean mapper() throws MalformedURLException { + PropertiesFactoryBean bean = new PropertiesFactoryBean(); + bean.setLocation(new UrlResource("file:" + configHome + "/cadi.properties")); + return bean; + } +} diff --git a/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/config/ForwardProxyProperties.java b/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/config/ForwardProxyProperties.java new file mode 100644 index 0000000..5c0d2c8 --- /dev/null +++ b/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/config/ForwardProxyProperties.java @@ -0,0 +1,67 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aaf + * ================================================================================ + * Copyright © 2018 European Software Marketing Ltd. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aaf.cadi.sidecar.rproxy.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; + +@Configuration +@PropertySource("file:${CONFIG_HOME}/forward-proxy.properties") +@ConfigurationProperties(prefix = "forward-proxy") +public class ForwardProxyProperties { + + private String protocol; + private String host; + private int port; + private String cacheurl; + + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + + public String getProtocol() { + return protocol; + } + + public void setProtocol(String protocol) { + this.protocol = protocol; + } + + public String getCacheurl() { + return cacheurl; + } + + public void setCacheurl(String cacheurl) { + this.cacheurl = cacheurl; + } +} diff --git a/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/config/PrimaryServiceProperties.java b/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/config/PrimaryServiceProperties.java new file mode 100644 index 0000000..e201ae6 --- /dev/null +++ b/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/config/PrimaryServiceProperties.java @@ -0,0 +1,58 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aaf + * ================================================================================ + * Copyright © 2018 European Software Marketing Ltd. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aaf.cadi.sidecar.rproxy.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; + +@Configuration +@PropertySource("file:${CONFIG_HOME}/primary-service.properties") +@ConfigurationProperties(prefix = "primary-service") +public class PrimaryServiceProperties { + + private String protocol; + private String host; + private String port; + + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + + public String getPort() { + return port; + } + + public void setPort(String port) { + this.port = port; + } + + public String getProtocol() { + return protocol; + } + + public void setProtocol(String protocol) { + this.protocol = protocol; + } +} diff --git a/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/config/ReverseProxySSLProperties.java b/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/config/ReverseProxySSLProperties.java new file mode 100644 index 0000000..ee7a240 --- /dev/null +++ b/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/config/ReverseProxySSLProperties.java @@ -0,0 +1,56 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aaf + * ================================================================================ + * Copyright © 2018 European Software Marketing Ltd. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aaf.cadi.sidecar.rproxy.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ConfigurationProperties(prefix = "server.ssl") +public class ReverseProxySSLProperties { + + private String keystore; + private String keystorePassword; + private String clientcert; + + public String getKeystore() { + return keystore; + } + + public void setKeystore(String keystore) { + this.keystore = keystore; + } + + public String getClientcert() { + return clientcert; + } + + public void setClientcert(String clientcert) { + this.clientcert = clientcert; + } + + public String getKeystorePassword() { + return keystorePassword; + } + + public void setKeystorePassword(String keystorePassword) { + this.keystorePassword = keystorePassword; + } +} diff --git a/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/config/ReverseProxyURIAuthorizationProperties.java b/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/config/ReverseProxyURIAuthorizationProperties.java new file mode 100644 index 0000000..193d753 --- /dev/null +++ b/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/config/ReverseProxyURIAuthorizationProperties.java @@ -0,0 +1,38 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aaf + * ================================================================================ + * Copyright © 2018 European Software Marketing Ltd. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aaf.cadi.sidecar.rproxy.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ConfigurationProperties(prefix = "uri.authorization") +public class ReverseProxyURIAuthorizationProperties { + + private String configurationFile; + + public String getConfigurationFile() { + return configurationFile; + } + + public void setConfigurationFile(String configurationFile) { + this.configurationFile = configurationFile; + } +} diff --git a/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/mocks/ReverseProxyMockCadiFilter.java b/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/mocks/ReverseProxyMockCadiFilter.java new file mode 100644 index 0000000..1c4de92 --- /dev/null +++ b/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/mocks/ReverseProxyMockCadiFilter.java @@ -0,0 +1,143 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aaf + * ================================================================================ + * Copyright © 2018 European Software Marketing Ltd. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aaf.cadi.sidecar.rproxy.mocks; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.security.Principal; +import java.util.List; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import org.onap.aaf.cadi.CadiWrap; +import org.onap.aaf.cadi.Lur; +import org.onap.aaf.cadi.Permission; +import org.onap.aaf.cadi.aaf.AAFPermission; +import org.onap.aaf.cadi.principal.TaggedPrincipal; +import org.onap.aaf.cadi.taf.TafResp; + +public class ReverseProxyMockCadiFilter implements Filter { + + private FakeLur fakeLur = new FakeLur(); + + static class FakeLur implements Lur { + + @Override + public void fishAll(Principal bait, List permissions) { + + final String WildcardPermissionType = "test.wildcard.access"; + final String MultiplePermissionType = "test.multiple.access"; + final String TestAuthAccessPermissionType = "test.auth.access"; + final String PermissionAction = "permission"; + + String principalName = bait.getName(); + + if (principalName != null && principalName.equals("UserWithInstanceActionWildcardPermissionGranted")) { + permissions.add(new AAFPermission(null, WildcardPermissionType, "*", "*")); + } + else + if (principalName != null && principalName.equals("UserWithInstanceWildcardPermissionGranted")) { + permissions.add(new AAFPermission(null, WildcardPermissionType, "*", PermissionAction)); + } + else + if (principalName != null && principalName.equals("UserWithActionWildcardPermissionGranted")) { + permissions.add(new AAFPermission(null, WildcardPermissionType, "first", "*")); + } + else { + + // For single permission test + permissions.add(new AAFPermission(null, "test.single.access", "single", PermissionAction)); + + // For multiple permission test + permissions.add(new AAFPermission(null, MultiplePermissionType, "first", PermissionAction)); + permissions.add(new AAFPermission(null, MultiplePermissionType, "second", PermissionAction)); + permissions.add(new AAFPermission(null, MultiplePermissionType, "third", PermissionAction)); + + // For transaction id test + permissions.add(new AAFPermission(null, TestAuthAccessPermissionType, "rest", "write")); + permissions.add(new AAFPermission(null, TestAuthAccessPermissionType, "rpc", "write")); + } + } + + @Override + public Permission createPerm(String p) { + return null; + } + + @Override + public boolean fish(Principal bait, Permission... pond) { + return false; + } + + @Override + public void destroy() { + // Mock implementation + } + + @Override + public boolean handlesExclusively(Permission... pond) { + return false; + } + + @Override + public boolean handles(Principal principal) { + return false; + } + + @Override + public void clear(Principal p, StringBuilder report) { + // Mock implementation + } + + } + + @Override + public void destroy() { + // Mock implementation + } + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) + throws IOException, ServletException { + + String userName = ((HttpServletRequest)servletRequest).getHeader("PermissionsUser"); + + TaggedPrincipal mockTaggedPrincipal = mock(TaggedPrincipal.class); + when(mockTaggedPrincipal.getName()).thenReturn(userName); + + TafResp tafResponseMock = mock(TafResp.class); + when(tafResponseMock.getPrincipal()).thenReturn(mockTaggedPrincipal); + + CadiWrap cadiWrap = new CadiWrap((HttpServletRequest) servletRequest, tafResponseMock, fakeLur); + filterChain.doFilter(cadiWrap, servletResponse); + } + + @Override + public void init(FilterConfig arg0) throws ServletException { + // Mock implementation + } + +} diff --git a/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/utils/ReverseProxyAuthorization.java b/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/utils/ReverseProxyAuthorization.java new file mode 100644 index 0000000..fd9db8e --- /dev/null +++ b/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/utils/ReverseProxyAuthorization.java @@ -0,0 +1,34 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aaf + * ================================================================================ + * Copyright © 2018 European Software Marketing Ltd. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aaf.cadi.sidecar.rproxy.utils; + +public class ReverseProxyAuthorization { + + private String uri; + private String[] permissions; + + public String getUri() { + return uri; + } + + public String[] getPermissions() { + return permissions; + } +} diff --git a/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/utils/ReverseProxyUtils.java b/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/utils/ReverseProxyUtils.java new file mode 100644 index 0000000..495a78c --- /dev/null +++ b/sidecar/rproxy/src/main/java/org/onap/aaf/cadi/sidecar/rproxy/utils/ReverseProxyUtils.java @@ -0,0 +1,29 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aaf + * ================================================================================ + * Copyright © 2018 European Software Marketing Ltd. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aaf.cadi.sidecar.rproxy.utils; + +public class ReverseProxyUtils { + + public static boolean validTransactionId(String transactionId) { + return transactionId.matches("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"); + } + + private ReverseProxyUtils() {} +} diff --git a/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/ReverseProxyApplication.java b/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/ReverseProxyApplication.java deleted file mode 100644 index ebceceb..0000000 --- a/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/ReverseProxyApplication.java +++ /dev/null @@ -1,182 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aaf - * ================================================================================ - * Copyright © 2018 European Software Marketing Ltd. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ -package org.onap.aaf.rproxy; - -import java.io.IOException; -import java.security.GeneralSecurityException; -import java.util.HashMap; -import java.util.Properties; -import javax.annotation.PostConstruct; -import javax.annotation.Resource; -import javax.net.ssl.SSLContext; -import org.apache.http.conn.ssl.NoopHostnameVerifier; -import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.ssl.SSLContextBuilder; -import org.eclipse.jetty.util.security.Password; -import org.onap.aaf.cadi.filter.CadiFilter; -import org.onap.aaf.rproxy.config.ForwardProxyProperties; -import org.onap.aaf.rproxy.config.PrimaryServiceProperties; -import org.onap.aaf.rproxy.config.ReverseProxySSLProperties; -import org.onap.aaf.rproxy.mocks.ReverseProxyMockCadiFilter; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.web.client.RestTemplateBuilder; -import org.springframework.boot.web.servlet.FilterRegistrationBean; -import org.springframework.boot.web.servlet.RegistrationBean; -import org.springframework.boot.web.servlet.ServletComponentScan; -import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Profile; -import org.springframework.context.annotation.PropertySource; -import org.springframework.core.env.Environment; -import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; -import org.springframework.util.ResourceUtils; -import org.springframework.web.client.RestTemplate; - -@SpringBootApplication -@ServletComponentScan -@EnableConfigurationProperties(ReverseProxySSLProperties.class) -@PropertySource("file:${CONFIG_HOME}/reverse-proxy.properties") -public class ReverseProxyApplication extends SpringBootServletInitializer { - - private static final String CADI_TRUSTSTORE_PASS = "cadi_truststore_password"; - - @Autowired - private Environment env; - - /** - * Spring Boot Initialisation. - * - * @param args main args - */ - public static void main(String[] args) { - String keyStorePassword = System.getProperty("KEY_STORE_PASSWORD"); - if (keyStorePassword == null || keyStorePassword.isEmpty()) { - throw new IllegalArgumentException("Env property KEY_STORE_PASSWORD not set"); - } - HashMap props = new HashMap<>(); - props.put("server.ssl.key-store-password", Password.deobfuscate(keyStorePassword)); - new ReverseProxyApplication() - .configure(new SpringApplicationBuilder(ReverseProxyApplication.class).properties(props)).run(args); - } - - /** - * Set required trust store system properties using values from application.properties - */ - @PostConstruct - public void setSystemProperties() { - String keyStorePath = env.getProperty("server.ssl.key-store"); - if (keyStorePath != null) { - String keyStorePassword = env.getProperty("server.ssl.key-store-password"); - - if (keyStorePassword != null) { - System.setProperty("javax.net.ssl.keyStore", keyStorePath); - System.setProperty("javax.net.ssl.keyStorePassword", keyStorePassword); - System.setProperty("javax.net.ssl.trustStore", keyStorePath); - System.setProperty("javax.net.ssl.trustStorePassword", keyStorePassword); - } else { - throw new IllegalArgumentException("Env property server.ssl.key-store-password not set"); - } - } - } - - @Resource - private ReverseProxySSLProperties reverseProxySSLProperties; - - @Resource - Properties cadiProps; - - @Bean(name = "ForwardProxyProperties") - public ForwardProxyProperties forwardProxyProperties() { - return new ForwardProxyProperties(); - } - - @Bean(name = "PrimaryServiceProperties") - public PrimaryServiceProperties primaryServiceProperties() { - return new PrimaryServiceProperties(); - } - - @Profile("secure") - @Bean - public RestTemplate restTemplate(RestTemplateBuilder builder) throws GeneralSecurityException, IOException { - return new RestTemplate(new HttpComponentsClientHttpRequestFactory(getClientBuilder().build())); - } - - @Profile("noHostVerification") - @Bean - public RestTemplate restTemplateNoHostVerification(RestTemplateBuilder builder) - throws GeneralSecurityException, IOException { - return new RestTemplate(new HttpComponentsClientHttpRequestFactory( - getClientBuilder().setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE).build())); - } - - private HttpClientBuilder getClientBuilder() throws GeneralSecurityException, IOException { - - SSLContext sslContext = SSLContextBuilder.create() - .loadKeyMaterial(ResourceUtils.getFile(reverseProxySSLProperties.getClientcert()), - reverseProxySSLProperties.getKeystorePassword().toCharArray(), - reverseProxySSLProperties.getKeystorePassword().toCharArray()) - .loadTrustMaterial(ResourceUtils.getFile(reverseProxySSLProperties.getKeystore()), - reverseProxySSLProperties.getKeystorePassword().toCharArray()) - .build(); - - return HttpClients.custom().setSSLContext(sslContext); - } - - @Profile("cadi") - @Bean - public FilterRegistrationBean registerCADIFilter() { - - FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean<>(); - - filterRegistrationBean.setFilter(new CadiFilter()); - filterRegistrationBean.addUrlPatterns("/*"); - filterRegistrationBean.setName("CADIFilter"); - filterRegistrationBean.setOrder(RegistrationBean.HIGHEST_PRECEDENCE); - - // Deobfuscate truststore password - String trustStorePassword = cadiProps.getProperty(CADI_TRUSTSTORE_PASS); - if (trustStorePassword != null) { - cadiProps.setProperty(CADI_TRUSTSTORE_PASS, Password.deobfuscate(trustStorePassword)); - } - - // Add filter init params - cadiProps.forEach((k, v) -> filterRegistrationBean.addInitParameter((String) k, (String) v)); - - return filterRegistrationBean; - } - - @Profile("mockCadi") - @Bean - public FilterRegistrationBean registerMockCADIFilter() { - - FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean<>(); - - filterRegistrationBean.setFilter(new ReverseProxyMockCadiFilter()); - filterRegistrationBean.addUrlPatterns("/*"); - filterRegistrationBean.setName("CADIFilter"); - filterRegistrationBean.setOrder(RegistrationBean.HIGHEST_PRECEDENCE); - - return filterRegistrationBean; - } -} diff --git a/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/ReverseProxyAuthorizationFilter.java b/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/ReverseProxyAuthorizationFilter.java deleted file mode 100644 index f939249..0000000 --- a/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/ReverseProxyAuthorizationFilter.java +++ /dev/null @@ -1,216 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aaf - * ================================================================================ - * Copyright © 2018 European Software Marketing Ltd. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ -package org.onap.aaf.rproxy; - -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; -import com.google.gson.stream.JsonReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.URI; -import java.net.URISyntaxException; -import java.security.Principal; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import javax.annotation.Resource; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import org.eclipse.jetty.http.HttpStatus; -import org.onap.aaf.cadi.CadiWrap; -import org.onap.aaf.cadi.Permission; -import org.onap.aaf.rproxy.config.ReverseProxyURIAuthorizationProperties; -import org.onap.aaf.rproxy.utils.ReverseProxyAuthorization; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.core.annotation.Order; -import org.springframework.stereotype.Component; - -@Component -@Order(1) -@EnableConfigurationProperties(ReverseProxyURIAuthorizationProperties.class) -public class ReverseProxyAuthorizationFilter implements Filter { - - private static final Logger LOGGER = LoggerFactory.getLogger(ReverseProxyAuthorizationFilter.class); - - private List reverseProxyAuthorizations = new ArrayList<>(); - - @Resource - private ReverseProxyURIAuthorizationProperties reverseProxyURIAuthorizationProperties; - - @Override - public void init(FilterConfig filterConfig) throws ServletException { - - // Read in the URI Authorisation configuration file - String authFilePath = reverseProxyURIAuthorizationProperties.getConfigurationFile(); - if (authFilePath != null) { - try (InputStream inputStream = - new FileInputStream(new File(reverseProxyURIAuthorizationProperties.getConfigurationFile())); - JsonReader jsonReader = new JsonReader(new InputStreamReader(inputStream))) { - List untrimmedList = new Gson().fromJson(jsonReader, - new TypeToken>() {}.getType()); - untrimmedList.removeAll(Collections.singleton(null)); - reverseProxyAuthorizations = untrimmedList; - } catch (IOException e) { - throw new ServletException("Authorizations config file not found.", e); - } - } - } - - @Override - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) - throws IOException, ServletException { - - CadiWrap cadiWrap = (CadiWrap) servletRequest; - Principal principal = cadiWrap.getUserPrincipal(); - List grantedPermissions = new ArrayList<>(); - cadiWrap.getLur().fishAll(principal, grantedPermissions); - - if (LOGGER.isDebugEnabled()) { - logNeededPermissions(); - } - - String requestPath; - try { - requestPath = new URI(((HttpServletRequest) servletRequest).getRequestURI()).getPath(); - } catch (URISyntaxException e) { - throw new ServletException("Request URI not valid", e); - } - - if (authorizeRequest(grantedPermissions, requestPath)) { - LOGGER.info("Authorized"); - filterChain.doFilter(servletRequest, servletResponse); - } else { - LOGGER.info("Unauthorized"); - ((HttpServletResponse) servletResponse).setStatus(HttpStatus.FORBIDDEN_403); - ((HttpServletResponse) servletResponse).setContentType("application/json"); - ((HttpServletResponse) servletResponse).sendError(HttpStatus.FORBIDDEN_403, - "Sorry, the request is not allowed"); - } - } - - /** - * Check if the granted permissions for the request path matches the configured needed permissions. - * - * @param grantedPermissions The granted permissions for the request path - * @param requestPath The request path - * @return true if permissions match - */ - private boolean authorizeRequest(List grantedPermissions, String requestPath) { - boolean authorized = false; - for (ReverseProxyAuthorization reverseProxyAuthorization : reverseProxyAuthorizations) { - if (requestPath.matches(reverseProxyAuthorization.getUri())) { - LOGGER.debug("The URI:{} matches:{}", requestPath, reverseProxyAuthorization.getUri()); - if (checkPermissionsMatch(grantedPermissions, reverseProxyAuthorization)) { - authorized = true; - break; - } - } else { - LOGGER.debug("The URI:{} doesn't match any in the configuration:{}", requestPath, - reverseProxyAuthorization.getUri()); - } - } - return authorized; - } - - /** - * Check all needed permissions match the granted permissions. - * - * @param grantedPermissions the granted permissions - * @param reverseProxyAuthorization the bean that contains the needed permissions - * @return true if all needed permissions match - */ - private boolean checkPermissionsMatch(List grantedPermissions, - ReverseProxyAuthorization reverseProxyAuthorization) { - - boolean matchedAllPermissions = true; - for (String neededPermission : reverseProxyAuthorization.getPermissions()) { - - // Check needed permission is granted - boolean matchedNeededPermission = false; - for (Permission grantedPermission : grantedPermissions) { - if (checkGrantedPermission(neededPermission, grantedPermission.getKey())) { - LOGGER.debug("Permission match found - needed permission:{}, granted permission:{}", - neededPermission, grantedPermission.getKey()); - matchedNeededPermission = true; - break; - } - } - if (!matchedNeededPermission) { - matchedAllPermissions = false; - break; - } - } - return matchedAllPermissions; - } - - /** - * Check whether an AAF style permission matches a needed permission. Wildcards (*) are supported. - * - * @param neededPermission, the needed permission - * @param grantedPermission, the granted permission - * - * @return true if the needed permission matches a granted permission - */ - private boolean checkGrantedPermission(String neededPermission, String grantedPermission) { - boolean permissionMatch = false; - if (grantedPermission.matches(neededPermission)) { - permissionMatch = true; - } else if (grantedPermission.contains("*")) { - String[] splitNeededPermission = neededPermission.split("\\\\\\|"); - String[] splitGrantedPermission = grantedPermission.split("\\|"); - if ((splitGrantedPermission[0].matches(splitNeededPermission[0])) - && (splitGrantedPermission[1].equals("*") - || splitGrantedPermission[1].matches(splitNeededPermission[1])) - && (splitGrantedPermission[2].equals("*") - || splitGrantedPermission[2].matches(splitNeededPermission[2]))) { - permissionMatch = true; - } - } - return permissionMatch; - } - - /** - * Log the needed permissions for each URL configured. - */ - private void logNeededPermissions() { - for (ReverseProxyAuthorization reverseProxyAuthorization : reverseProxyAuthorizations) { - LOGGER.debug("URI For authorization: {}", reverseProxyAuthorization.getUri()); - for (String permission : reverseProxyAuthorization.getPermissions()) { - LOGGER.debug("\t Needed permission:{}", permission); - } - } - } - - @Override - public void destroy() { - // No op - } -} diff --git a/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/ReverseProxyService.java b/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/ReverseProxyService.java deleted file mode 100644 index 55fcdd1..0000000 --- a/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/ReverseProxyService.java +++ /dev/null @@ -1,166 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aaf - * ================================================================================ - * Copyright © 2018 European Software Marketing Ltd. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ -package org.onap.aaf.rproxy; - -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Enumeration; -import java.util.UUID; -import javax.annotation.Resource; -import javax.servlet.http.HttpServletRequest; -import org.onap.aaf.fproxy.data.CredentialCacheData; -import org.onap.aaf.fproxy.data.CredentialCacheData.CredentialType; -import org.onap.aaf.rproxy.config.ForwardProxyProperties; -import org.onap.aaf.rproxy.config.PrimaryServiceProperties; -import org.onap.aaf.rproxy.logging.ReverseProxyMethodLogTimeAnnotation; -import org.onap.aaf.rproxy.utils.ReverseProxyUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestHeader; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.client.HttpClientErrorException; -import org.springframework.web.client.RestTemplate; - -@RestController -@EnableConfigurationProperties({ForwardProxyProperties.class, PrimaryServiceProperties.class}) -public class ReverseProxyService { - - private static final Logger LOGGER = LoggerFactory.getLogger(ReverseProxyService.class); - - private String validatedTransactionId; - - @Resource(name = "ForwardProxyProperties") - private ForwardProxyProperties forwardProxyProperties; - - @Resource(name = "PrimaryServiceProperties") - private PrimaryServiceProperties primaryServiceProperties; - - @Autowired - private RestTemplate restTemplate; - - @Value("${transactionid.header.name}") - private String transactionIdHeader; - - @RequestMapping("/**") - @ReverseProxyMethodLogTimeAnnotation - public ResponseEntity handleRequest(HttpServletRequest request, - @RequestHeader(value = "${transactionid.header.name}", defaultValue = "") String transactionId, - @RequestBody(required = false) String requestBody, HttpMethod requestMethod) throws URISyntaxException { - validatedTransactionId = getValidTransactionId(transactionId); - - // Extract Request Permissions and store in Forward Proxy cache - CredentialCacheData credentialCacheData = getCredentialDataFromRequest(request); - if (credentialCacheData != null) { - postCredentialsToCache(credentialCacheData); - } - - // Call out to Primary Service & Return Response - URI requestURI = new URI(request.getRequestURI()); - - LOGGER.debug("Request URI: {}", request.getRequestURI()); - - // Get Request Endpoint & substitute in local values - URI primaryServiceURI = new URI(primaryServiceProperties.getProtocol(), requestURI.getUserInfo(), - primaryServiceProperties.getHost(), Integer.parseInt(primaryServiceProperties.getPort()), - requestURI.getPath(), requestURI.getQuery(), requestURI.getFragment()); - - LOGGER.debug("Primary Service URI:{}, HTTP Method: {}", primaryServiceURI, requestMethod); - - HttpHeaders requestHeaders = setForwardedRequestHeaders(request); - HttpEntity httpEntity = new HttpEntity<>(requestBody, requestHeaders); - - return restTemplate.exchange(primaryServiceURI, requestMethod, httpEntity, String.class); - } - - private String getValidTransactionId(String transactionId) { - LOGGER.debug("Request transaction ID: {}", transactionId); - if (transactionId == null || !ReverseProxyUtils.validTransactionId(transactionId)) { - transactionId = UUID.randomUUID().toString(); - } - LOGGER.debug("Validated transaction ID: {}", transactionId); - return transactionId; - } - - private HttpHeaders setForwardedRequestHeaders(HttpServletRequest httpServletRequest) { - HttpHeaders httpHeaders = new HttpHeaders(); - Enumeration headerNames = httpServletRequest.getHeaderNames(); - while (headerNames.hasMoreElements()) { - String headerName = headerNames.nextElement(); - if (!headerName.equals(transactionIdHeader)) { - httpHeaders.set(headerName, httpServletRequest.getHeader(headerName)); - } - } - // Always set transaction ID - httpHeaders.set(transactionIdHeader, validatedTransactionId); - - return httpHeaders; - } - - /** - * Retrieves credential data from request. - * - * @param request The request to retrieve credentials from - * @return The retrieved credential data, or null if no credentials are found in request - */ - private CredentialCacheData getCredentialDataFromRequest(HttpServletRequest request) { - CredentialCacheData credentialCacheData = null; - String authValue = request.getHeader(HttpHeaders.AUTHORIZATION); - if (authValue != null) { - credentialCacheData = new CredentialCacheData(HttpHeaders.AUTHORIZATION, authValue, CredentialType.HEADER); - } - return credentialCacheData; - } - - /** - * Posts credential data to credential cache endpoint - * - * @param credentialCacheData The credential data to post - * @throws URISyntaxException - */ - private void postCredentialsToCache(CredentialCacheData credentialCacheData) throws URISyntaxException { - URI forwardProxyURI = new URI(forwardProxyProperties.getProtocol(), null, forwardProxyProperties.getHost(), - forwardProxyProperties.getPort(), forwardProxyProperties.getCacheurl() + "/" + validatedTransactionId, - null, null); - - ResponseEntity response = - restTemplate.postForEntity(forwardProxyURI, credentialCacheData, String.class); - - if (!response.getStatusCode().is2xxSuccessful()) { - throw new HttpClientErrorException(response.getStatusCode(), - "Error posting to credential cache. Message: " + response.getBody()); - } - } - - @Override - public String toString() { - return this.getClass().getName() + ": Forward proxy host:" + forwardProxyProperties.getHost() - + ": Primary service host:" + primaryServiceProperties.getHost(); - - } -} diff --git a/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/config/CadiProperties.java b/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/config/CadiProperties.java deleted file mode 100644 index 0afb506..0000000 --- a/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/config/CadiProperties.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aaf - * ================================================================================ - * Copyright © 2018 European Software Marketing Ltd. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ -package org.onap.aaf.rproxy.config; - -import java.net.MalformedURLException; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.beans.factory.config.PropertiesFactoryBean; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.io.UrlResource; - -@Configuration -public class CadiProperties { - - @Value("${CONFIG_HOME}") - private String configHome; - - @Bean(name = "cadiProps") - public PropertiesFactoryBean mapper() throws MalformedURLException { - PropertiesFactoryBean bean = new PropertiesFactoryBean(); - bean.setLocation(new UrlResource("file:" + configHome + "/cadi.properties")); - return bean; - } -} diff --git a/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/config/ForwardProxyProperties.java b/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/config/ForwardProxyProperties.java deleted file mode 100644 index 3607797..0000000 --- a/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/config/ForwardProxyProperties.java +++ /dev/null @@ -1,67 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aaf - * ================================================================================ - * Copyright © 2018 European Software Marketing Ltd. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ -package org.onap.aaf.rproxy.config; - -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.PropertySource; - -@Configuration -@PropertySource("file:${CONFIG_HOME}/forward-proxy.properties") -@ConfigurationProperties(prefix = "forward-proxy") -public class ForwardProxyProperties { - - private String protocol; - private String host; - private int port; - private String cacheurl; - - public String getHost() { - return host; - } - - public void setHost(String host) { - this.host = host; - } - - public int getPort() { - return port; - } - - public void setPort(int port) { - this.port = port; - } - - public String getProtocol() { - return protocol; - } - - public void setProtocol(String protocol) { - this.protocol = protocol; - } - - public String getCacheurl() { - return cacheurl; - } - - public void setCacheurl(String cacheurl) { - this.cacheurl = cacheurl; - } -} diff --git a/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/config/PrimaryServiceProperties.java b/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/config/PrimaryServiceProperties.java deleted file mode 100644 index 994dc55..0000000 --- a/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/config/PrimaryServiceProperties.java +++ /dev/null @@ -1,58 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aaf - * ================================================================================ - * Copyright © 2018 European Software Marketing Ltd. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ -package org.onap.aaf.rproxy.config; - -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.PropertySource; - -@Configuration -@PropertySource("file:${CONFIG_HOME}/primary-service.properties") -@ConfigurationProperties(prefix = "primary-service") -public class PrimaryServiceProperties { - - private String protocol; - private String host; - private String port; - - public String getHost() { - return host; - } - - public void setHost(String host) { - this.host = host; - } - - public String getPort() { - return port; - } - - public void setPort(String port) { - this.port = port; - } - - public String getProtocol() { - return protocol; - } - - public void setProtocol(String protocol) { - this.protocol = protocol; - } -} diff --git a/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/config/ReverseProxySSLProperties.java b/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/config/ReverseProxySSLProperties.java deleted file mode 100644 index 31e8a0d..0000000 --- a/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/config/ReverseProxySSLProperties.java +++ /dev/null @@ -1,56 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aaf - * ================================================================================ - * Copyright © 2018 European Software Marketing Ltd. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ -package org.onap.aaf.rproxy.config; - -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Configuration; - -@Configuration -@ConfigurationProperties(prefix = "server.ssl") -public class ReverseProxySSLProperties { - - private String keystore; - private String keystorePassword; - private String clientcert; - - public String getKeystore() { - return keystore; - } - - public void setKeystore(String keystore) { - this.keystore = keystore; - } - - public String getClientcert() { - return clientcert; - } - - public void setClientcert(String clientcert) { - this.clientcert = clientcert; - } - - public String getKeystorePassword() { - return keystorePassword; - } - - public void setKeystorePassword(String keystorePassword) { - this.keystorePassword = keystorePassword; - } -} diff --git a/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/config/ReverseProxyURIAuthorizationProperties.java b/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/config/ReverseProxyURIAuthorizationProperties.java deleted file mode 100644 index da25d9c..0000000 --- a/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/config/ReverseProxyURIAuthorizationProperties.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aaf - * ================================================================================ - * Copyright © 2018 European Software Marketing Ltd. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ -package org.onap.aaf.rproxy.config; - -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Configuration; - -@Configuration -@ConfigurationProperties(prefix = "uri.authorization") -public class ReverseProxyURIAuthorizationProperties { - - private String configurationFile; - - public String getConfigurationFile() { - return configurationFile; - } - - public void setConfigurationFile(String configurationFile) { - this.configurationFile = configurationFile; - } -} diff --git a/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/logging/ReverseProxyEntryExitLoggingAspect.java b/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/logging/ReverseProxyEntryExitLoggingAspect.java deleted file mode 100644 index 174420c..0000000 --- a/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/logging/ReverseProxyEntryExitLoggingAspect.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aaf - * ================================================================================ - * Copyright © 2018 European Software Marketing Ltd. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ -package org.onap.aaf.rproxy.logging; - -import org.aspectj.lang.JoinPoint; -import org.aspectj.lang.annotation.After; -import org.aspectj.lang.annotation.Aspect; -import org.aspectj.lang.annotation.Before; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -@Aspect -@Component -public class ReverseProxyEntryExitLoggingAspect { - - private static final Logger LOGGER = LoggerFactory.getLogger(ReverseProxyEntryExitLoggingAspect.class); - - @Before("execution(* org.onap.platform.security.*.*(..))") - public void before(JoinPoint joinPoint) { - LOGGER.info("Entry of {}#{}", joinPoint.getTarget().getClass(), joinPoint.getSignature().getName()); - } - - @After("execution(* org.onap.platform.security.*.*(..))") - public void after(JoinPoint joinPoint) { - LOGGER.info("Exit of {}#{}", joinPoint.getTarget().getClass(), joinPoint.getSignature().getName()); - } -} diff --git a/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/logging/ReverseProxyMethodLogTime.java b/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/logging/ReverseProxyMethodLogTime.java deleted file mode 100644 index 00cfba6..0000000 --- a/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/logging/ReverseProxyMethodLogTime.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aaf - * ================================================================================ - * Copyright © 2018 European Software Marketing Ltd. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ -package org.onap.aaf.rproxy.logging; - -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.annotation.Around; -import org.aspectj.lang.annotation.Aspect; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.annotation.Configuration; - -@Aspect -@Configuration -public class ReverseProxyMethodLogTime { - - private static final Logger LOGGER = LoggerFactory.getLogger(ReverseProxyMethodLogTime.class); - - @Around("@annotation(org.onap.aaf.rproxy.logging.ReverseProxyMethodLogTimeAnnotation)") - public Object around(ProceedingJoinPoint joinPoint) throws Throwable { - - long startTime = System.currentTimeMillis(); - - Object object = joinPoint.proceed(); - - long duration = System.currentTimeMillis() - startTime; - - LOGGER.info("Time taken by {} is {} ms", joinPoint, duration); - - return object; - } - - - -} diff --git a/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/logging/ReverseProxyMethodLogTimeAnnotation.java b/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/logging/ReverseProxyMethodLogTimeAnnotation.java deleted file mode 100644 index 55f00f4..0000000 --- a/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/logging/ReverseProxyMethodLogTimeAnnotation.java +++ /dev/null @@ -1,30 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aaf - * ================================================================================ - * Copyright © 2018 European Software Marketing Ltd. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ -package org.onap.aaf.rproxy.logging; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Target(ElementType.METHOD) -@Retention(RetentionPolicy.RUNTIME) -public @interface ReverseProxyMethodLogTimeAnnotation { -} diff --git a/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/mocks/ReverseProxyMockCadiFilter.java b/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/mocks/ReverseProxyMockCadiFilter.java deleted file mode 100644 index 10bfc3e..0000000 --- a/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/mocks/ReverseProxyMockCadiFilter.java +++ /dev/null @@ -1,143 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aaf - * ================================================================================ - * Copyright © 2018 European Software Marketing Ltd. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ -package org.onap.aaf.rproxy.mocks; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import java.io.IOException; -import java.security.Principal; -import java.util.List; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import org.onap.aaf.cadi.CadiWrap; -import org.onap.aaf.cadi.Lur; -import org.onap.aaf.cadi.Permission; -import org.onap.aaf.cadi.aaf.AAFPermission; -import org.onap.aaf.cadi.principal.TaggedPrincipal; -import org.onap.aaf.cadi.taf.TafResp; - -public class ReverseProxyMockCadiFilter implements Filter { - - private FakeLur fakeLur = new FakeLur(); - - static class FakeLur implements Lur { - - @Override - public void fishAll(Principal bait, List permissions) { - - final String WildcardPermissionType = "test.wildcard.access"; - final String MultiplePermissionType = "test.multiple.access"; - final String TestAuthAccessPermissionType = "test.auth.access"; - final String PermissionAction = "permission"; - - String principalName = bait.getName(); - - if (principalName != null && principalName.equals("UserWithInstanceActionWildcardPermissionGranted")) { - permissions.add(new AAFPermission(null, WildcardPermissionType, "*", "*")); - } - else - if (principalName != null && principalName.equals("UserWithInstanceWildcardPermissionGranted")) { - permissions.add(new AAFPermission(null, WildcardPermissionType, "*", PermissionAction)); - } - else - if (principalName != null && principalName.equals("UserWithActionWildcardPermissionGranted")) { - permissions.add(new AAFPermission(null, WildcardPermissionType, "first", "*")); - } - else { - - // For single permission test - permissions.add(new AAFPermission(null, "test.single.access", "single", PermissionAction)); - - // For multiple permission test - permissions.add(new AAFPermission(null, MultiplePermissionType, "first", PermissionAction)); - permissions.add(new AAFPermission(null, MultiplePermissionType, "second", PermissionAction)); - permissions.add(new AAFPermission(null, MultiplePermissionType, "third", PermissionAction)); - - // For transaction id test - permissions.add(new AAFPermission(null, TestAuthAccessPermissionType, "rest", "write")); - permissions.add(new AAFPermission(null, TestAuthAccessPermissionType, "rpc", "write")); - } - } - - @Override - public Permission createPerm(String p) { - return null; - } - - @Override - public boolean fish(Principal bait, Permission... pond) { - return false; - } - - @Override - public void destroy() { - // Mock implementation - } - - @Override - public boolean handlesExclusively(Permission... pond) { - return false; - } - - @Override - public boolean handles(Principal principal) { - return false; - } - - @Override - public void clear(Principal p, StringBuilder report) { - // Mock implementation - } - - } - - @Override - public void destroy() { - // Mock implementation - } - - @Override - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) - throws IOException, ServletException { - - String userName = ((HttpServletRequest)servletRequest).getHeader("PermissionsUser"); - - TaggedPrincipal mockTaggedPrincipal = mock(TaggedPrincipal.class); - when(mockTaggedPrincipal.getName()).thenReturn(userName); - - TafResp tafResponseMock = mock(TafResp.class); - when(tafResponseMock.getPrincipal()).thenReturn(mockTaggedPrincipal); - - CadiWrap cadiWrap = new CadiWrap((HttpServletRequest) servletRequest, tafResponseMock, fakeLur); - filterChain.doFilter(cadiWrap, servletResponse); - } - - @Override - public void init(FilterConfig arg0) throws ServletException { - // Mock implementation - } - -} diff --git a/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/utils/ReverseProxyAuthorization.java b/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/utils/ReverseProxyAuthorization.java deleted file mode 100644 index 6c5baa2..0000000 --- a/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/utils/ReverseProxyAuthorization.java +++ /dev/null @@ -1,34 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aaf - * ================================================================================ - * Copyright © 2018 European Software Marketing Ltd. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ -package org.onap.aaf.rproxy.utils; - -public class ReverseProxyAuthorization { - - private String uri; - private String[] permissions; - - public String getUri() { - return uri; - } - - public String[] getPermissions() { - return permissions; - } -} diff --git a/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/utils/ReverseProxyUtils.java b/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/utils/ReverseProxyUtils.java deleted file mode 100644 index d2d1ba4..0000000 --- a/sidecar/rproxy/src/main/java/org/onap/aaf/rproxy/utils/ReverseProxyUtils.java +++ /dev/null @@ -1,29 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aaf - * ================================================================================ - * Copyright © 2018 European Software Marketing Ltd. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ -package org.onap.aaf.rproxy.utils; - -public class ReverseProxyUtils { - - public static boolean validTransactionId(String transactionId) { - return transactionId.matches("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"); - } - - private ReverseProxyUtils() {} -} diff --git a/sidecar/rproxy/src/test/java/org/onap/aaf/cadi/sidecar/rproxy/test/PermissionMatchingTest.java b/sidecar/rproxy/src/test/java/org/onap/aaf/cadi/sidecar/rproxy/test/PermissionMatchingTest.java new file mode 100644 index 0000000..e9dd95b --- /dev/null +++ b/sidecar/rproxy/src/test/java/org/onap/aaf/cadi/sidecar/rproxy/test/PermissionMatchingTest.java @@ -0,0 +1,262 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aaf + * ================================================================================ + * Copyright © 2018 European Software Marketing Ltd. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aaf.cadi.sidecar.rproxy.test; + +import static org.hamcrest.Matchers.equalTo; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.header; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.method; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; +import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import javax.annotation.Resource; +import org.eclipse.jetty.util.security.Password; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.onap.aaf.cadi.sidecar.rproxy.config.ForwardProxyProperties; +import org.onap.aaf.cadi.sidecar.rproxy.config.PrimaryServiceProperties; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.client.MockRestServiceServer; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.web.client.RestTemplate; + + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) +@AutoConfigureMockMvc + +@TestPropertySource(locations = {"classpath:primary-service.properties", "classpath:forward-proxy.properties"}) + +@ContextConfiguration(classes = ReverseProxyTestConfig.class) +public class PermissionMatchingTest { + + static { + System.setProperty("server.ssl.key-store-password", + Password.deobfuscate("OBF:1y0q1uvc1uum1uvg1pil1pjl1uuq1uvk1uuu1y10")); + } + + @Value("${transactionid.header.name}") + private String transactionIdHeaderName; + + @Resource(name = "PrimaryServiceProperties") + private PrimaryServiceProperties primaryServiceProps; + + @Resource(name = "ForwardProxyProperties") + private ForwardProxyProperties forwardProxyProps; + + @Autowired + private MockMvc mockMvc; + + @Autowired + private RestTemplate restTemplate; + + private MockRestServiceServer mockServer; + + private String primaryServiceBaseUrl; + + @Before + public void setUp() throws Exception { + mockServer = MockRestServiceServer.createServer(restTemplate); + primaryServiceBaseUrl = primaryServiceProps.getProtocol() + "://" + primaryServiceProps.getHost() + ":" + + primaryServiceProps.getPort(); + } + + @Test + public void testURIMismatch() throws Exception { + + String testUrl = "/uri/does/not/exist"; + String testResponse = "Sorry, the request is not allowed"; + + mockMvc + .perform(get(testUrl)) + .andExpect(status().isForbidden()) + .andExpect(status().reason(testResponse)); + + } + + @Test + public void testURINoPermission() throws Exception { + + String testUrl = "/not/allowed/at/all"; + String testResponse = "Sorry, the request is not allowed"; + + mockMvc + .perform(get(testUrl)) + .andExpect(status().isForbidden()) + .andExpect(status().reason(testResponse)); + + } + + @Test + public void testURIMatchSinglePermissionMatch() throws Exception { + + String transactionId = "63f88b50-6345-4a61-bc59-3a48cabb60a4"; + String testUrl = "/single/permission/required"; + String testResponse = "Response from MockRestService"; + + mockServer + .expect(requestTo(primaryServiceBaseUrl + testUrl)) + .andExpect(method(HttpMethod.GET)) + .andExpect(header(transactionIdHeaderName, transactionId)) + .andRespond(withSuccess(testResponse, MediaType.APPLICATION_JSON)); + + // Send request to mock server with transaction Id + mockMvc + .perform(MockMvcRequestBuilders.get(testUrl).accept(MediaType.APPLICATION_JSON).header(transactionIdHeaderName, transactionId)) + .andExpect(status().isOk()) + .andExpect(content().string(equalTo(testResponse))); + + mockServer.verify(); + + } + + @Test + public void testURIMatchMultiplePermissionMatch() throws Exception { + + String transactionId = "63f88b50-6345-4a61-bc59-3a48cabb60a4"; + String testUrl = "/multiple/permissions/required"; + String testResponse = "Response from MockRestService"; + + mockServer + .expect(requestTo(primaryServiceBaseUrl + testUrl)) + .andExpect(method(HttpMethod.GET)) + .andExpect(header(transactionIdHeaderName, transactionId)) + .andRespond(withSuccess(testResponse, MediaType.APPLICATION_JSON)); + + // Send request to mock server with transaction Id + mockMvc + .perform(MockMvcRequestBuilders.get(testUrl).accept(MediaType.APPLICATION_JSON).header(transactionIdHeaderName, transactionId)) + .andExpect(status().isOk()) + .andExpect(content().string(equalTo(testResponse))); + + mockServer.verify(); + + } + + @Test + public void testURIMatchMultipleMissingOnePermissionMatch() throws Exception { + + String testUrl = "/multiple/permissions/required/one/missing"; + String testResponse = "Sorry, the request is not allowed"; + + mockMvc + .perform(get(testUrl)) + .andExpect(status().isForbidden()) + .andExpect(status().reason(testResponse)); + } + + @Test + public void testURIInstanceActionWildCardPermissionMatch() throws Exception { + + String transactionId = "63f88b50-6345-4a61-bc59-3a48cabb60a4"; + String testUrl = "/wildcard/permission/granted"; + String testResponse = "Response from MockRestService"; + + mockServer + .expect(requestTo(primaryServiceBaseUrl + testUrl)) + .andExpect(method(HttpMethod.GET)) + .andExpect(header(transactionIdHeaderName, transactionId)) + .andRespond(withSuccess(testResponse, MediaType.APPLICATION_JSON)); + + // Send request to mock server with transaction Id + mockMvc + .perform(MockMvcRequestBuilders + .get(testUrl) + .accept(MediaType.APPLICATION_JSON) + .header(transactionIdHeaderName, transactionId) + .header("PermissionsUser", "UserWithInstanceActionWildcardPermissionGranted") + ) + .andExpect(status().isOk()) + .andExpect(content().string(equalTo(testResponse))); + + mockServer.verify(); + + } + + @Test + public void testURIInstanceWildCardPermissionMatch() throws Exception { + + String transactionId = "63f88b50-6345-4a61-bc59-3a48cabb60a4"; + String testUrl = "/instance/wildcard/permission/granted"; + String testResponse = "Response from MockRestService"; + + mockServer + .expect(requestTo(primaryServiceBaseUrl + testUrl)) + .andExpect(method(HttpMethod.GET)) + .andExpect(header(transactionIdHeaderName, transactionId)) + .andRespond(withSuccess(testResponse, MediaType.APPLICATION_JSON)); + + // Send request to mock server with transaction Id + mockMvc + .perform(MockMvcRequestBuilders + .get(testUrl) + .accept(MediaType.APPLICATION_JSON) + .header(transactionIdHeaderName, transactionId) + .header("PermissionsUser", "UserWithInstanceWildcardPermissionGranted") + ) + .andExpect(status().isOk()) + .andExpect(content().string(equalTo(testResponse))); + + mockServer.verify(); + + } + + @Test + public void testURIActionWildCardPermissionMatch() throws Exception { + + String transactionId = "63f88b50-6345-4a61-bc59-3a48cabb60a4"; + String testUrl = "/action/wildcard/permission/granted"; + String testResponse = "Response from MockRestService"; + + mockServer + .expect(requestTo(primaryServiceBaseUrl + testUrl)) + .andExpect(method(HttpMethod.GET)) + .andExpect(header(transactionIdHeaderName, transactionId)) + .andRespond(withSuccess(testResponse, MediaType.APPLICATION_JSON)); + + // Send request to mock server with transaction Id + mockMvc + .perform(MockMvcRequestBuilders + .get(testUrl) + .accept(MediaType.APPLICATION_JSON) + .header(transactionIdHeaderName, transactionId) + .header("PermissionsUser", "UserWithActionWildcardPermissionGranted") + ) + .andExpect(status().isOk()) + .andExpect(content().string(equalTo(testResponse))); + + mockServer.verify(); + + } + +} diff --git a/sidecar/rproxy/src/test/java/org/onap/aaf/cadi/sidecar/rproxy/test/ReverseProxyApplicationTest.java b/sidecar/rproxy/src/test/java/org/onap/aaf/cadi/sidecar/rproxy/test/ReverseProxyApplicationTest.java new file mode 100644 index 0000000..cff8f9b --- /dev/null +++ b/sidecar/rproxy/src/test/java/org/onap/aaf/cadi/sidecar/rproxy/test/ReverseProxyApplicationTest.java @@ -0,0 +1,158 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aaf + * ================================================================================ + * Copyright © 2018 European Software Marketing Ltd. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aaf.cadi.sidecar.rproxy.test; + +import static org.hamcrest.Matchers.equalTo; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.header; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.method; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; +import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import javax.annotation.Resource; +import org.eclipse.jetty.http.HttpHeader; +import org.eclipse.jetty.util.security.Password; +import org.hamcrest.Matchers; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.onap.aaf.cadi.sidecar.rproxy.config.ForwardProxyProperties; +import org.onap.aaf.cadi.sidecar.rproxy.config.PrimaryServiceProperties; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.client.MockRestServiceServer; +import org.springframework.test.web.client.match.MockRestRequestMatchers; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.web.client.RestTemplate; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) +@AutoConfigureMockMvc +@TestPropertySource(locations = {"classpath:primary-service.properties", "classpath:forward-proxy.properties"}) +@ContextConfiguration(classes = ReverseProxyTestConfig.class) +public class ReverseProxyApplicationTest { + + static { + System.setProperty("server.ssl.key-store-password", + Password.deobfuscate("OBF:1y0q1uvc1uum1uvg1pil1pjl1uuq1uvk1uuu1y10")); + } + + @Value("${transactionid.header.name}") + private String transactionIdHeaderName; + + @Resource(name = "PrimaryServiceProperties") + private PrimaryServiceProperties primaryServiceProps; + + @Resource(name = "ForwardProxyProperties") + private ForwardProxyProperties forwardProxyProps; + + @Autowired + private MockMvc mockMvc; + + @Autowired + private RestTemplate restTemplate; + + private MockRestServiceServer mockServer; + + private String primaryServiceBaseUrl; + private String forwardProxyBaseUrl; + + @Before + public void setUp() throws Exception { + mockServer = MockRestServiceServer.createServer(restTemplate); + primaryServiceBaseUrl = primaryServiceProps.getProtocol() + "://" + primaryServiceProps.getHost() + ":" + + primaryServiceProps.getPort(); + forwardProxyBaseUrl = forwardProxyProps.getProtocol() + "://" + forwardProxyProps.getHost() + ":" + + forwardProxyProps.getPort() + forwardProxyProps.getCacheurl() + "/"; + } + + @Test + public void checkForwardRequest() throws Exception { + + String transactionId = "63f88b50-6345-4a61-bc59-3a48cabb60a4"; + String testUrl = "/aai/v13/cloud-infrastructure/cloud-regions"; + String testResponse = "Response from MockRestService"; + + mockServer.expect(requestTo(primaryServiceBaseUrl + testUrl)).andExpect(method(HttpMethod.GET)) + .andExpect(header(transactionIdHeaderName, transactionId)) + .andRespond(withSuccess(testResponse, MediaType.APPLICATION_JSON)); + + // Send request to mock server with transaction Id + mockMvc.perform(MockMvcRequestBuilders.get(testUrl).accept(MediaType.APPLICATION_JSON) + .header(transactionIdHeaderName, transactionId)).andExpect(status().isOk()) + .andExpect(content().string(equalTo(testResponse))); + + mockServer.verify(); + } + + @Test + public void checkTransactionIdIsSetIfEmptyInRequest() throws Exception { + + String testUrl = "/aai/v13/cloud-infrastructure/cloud-regions"; + String testResponse = "Response from MockRestService"; + + mockServer.expect(requestTo(primaryServiceBaseUrl + testUrl)).andExpect(method(HttpMethod.GET)) + .andExpect(header(transactionIdHeaderName, Matchers.any(String.class))) + .andRespond(withSuccess(testResponse, MediaType.APPLICATION_JSON)); + + // Send request to mock server without transaction Id + mockMvc.perform(MockMvcRequestBuilders.get(testUrl).accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()).andExpect(content().string(equalTo(testResponse))); + + mockServer.verify(); + } + + @Test + public void checkBasicAuthCaching() throws Exception { + + String transactionId = "63f88b50-6345-4a61-bc59-3a48cabb60a4"; + String testUrl = "/aai/v13/cloud-infrastructure/cloud-regions"; + String testResponse = "Response from MockRestService"; + String testAuthValue = "testAuthValue"; + String testCachePayload = "{ \"credentialName\":" + HttpHeader.AUTHORIZATION + ", \"credentialValue\":" + + testAuthValue + ", \"credentialType\":\"HEADER\" }"; + + mockServer.expect(requestTo(forwardProxyBaseUrl + transactionId)).andExpect(method(HttpMethod.POST)) + .andExpect(MockRestRequestMatchers.content().json(testCachePayload)) + .andRespond(withSuccess(testResponse, MediaType.APPLICATION_JSON)); + + mockServer.expect(requestTo(primaryServiceBaseUrl + testUrl)).andExpect(method(HttpMethod.GET)) + .andExpect(header(transactionIdHeaderName, transactionId)) + .andRespond(withSuccess(testResponse, MediaType.APPLICATION_JSON)); + + // Send request to mock server with transaction Id + mockMvc.perform(MockMvcRequestBuilders.get(testUrl).accept(MediaType.APPLICATION_JSON) + .header(transactionIdHeaderName, transactionId) + .header(HttpHeader.AUTHORIZATION.asString(), testAuthValue)).andExpect(status().isOk()) + .andExpect(content().string(equalTo(testResponse))); + + mockServer.verify(); + } +} diff --git a/sidecar/rproxy/src/test/java/org/onap/aaf/cadi/sidecar/rproxy/test/ReverseProxyIT.java b/sidecar/rproxy/src/test/java/org/onap/aaf/cadi/sidecar/rproxy/test/ReverseProxyIT.java new file mode 100644 index 0000000..17f55f6 --- /dev/null +++ b/sidecar/rproxy/src/test/java/org/onap/aaf/cadi/sidecar/rproxy/test/ReverseProxyIT.java @@ -0,0 +1,49 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aaf + * ================================================================================ + * Copyright © 2018 European Software Marketing Ltd. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aaf.cadi.sidecar.rproxy.test; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.eclipse.jetty.util.security.Password; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.onap.aaf.cadi.sidecar.rproxy.ReverseProxyService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) +public class ReverseProxyIT { + + static { + System.setProperty("server.ssl.key-store-password", + Password.deobfuscate("OBF:1y0q1uvc1uum1uvg1pil1pjl1uuq1uvk1uuu1y10")); + } + + @Autowired + private ReverseProxyService rProxyService; + + @Test + public void contexLoads() throws Exception { + assertThat(rProxyService).isNotNull(); + } +} diff --git a/sidecar/rproxy/src/test/java/org/onap/aaf/cadi/sidecar/rproxy/test/ReverseProxyTestConfig.java b/sidecar/rproxy/src/test/java/org/onap/aaf/cadi/sidecar/rproxy/test/ReverseProxyTestConfig.java new file mode 100644 index 0000000..eada157 --- /dev/null +++ b/sidecar/rproxy/src/test/java/org/onap/aaf/cadi/sidecar/rproxy/test/ReverseProxyTestConfig.java @@ -0,0 +1,42 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aaf + * ================================================================================ + * Copyright © 2018 European Software Marketing Ltd. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aaf.cadi.sidecar.rproxy.test; + +import org.onap.aaf.cadi.sidecar.rproxy.mocks.ReverseProxyMockCadiFilter; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.boot.web.servlet.RegistrationBean; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; +import org.springframework.context.annotation.Bean; + +@TestConfiguration +public class ReverseProxyTestConfig extends SpringBootServletInitializer { + + @Bean + public FilterRegistrationBean registerCADIFilter() { + FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean<>(); + filterRegistrationBean.setFilter(new ReverseProxyMockCadiFilter()); + filterRegistrationBean.addUrlPatterns("/*"); + filterRegistrationBean.setName("CADIFilter"); + filterRegistrationBean.setOrder(RegistrationBean.HIGHEST_PRECEDENCE); + + return filterRegistrationBean; + } +} diff --git a/sidecar/rproxy/src/test/java/org/onap/aaf/rproxy/PermissionMatchingTest.java b/sidecar/rproxy/src/test/java/org/onap/aaf/rproxy/PermissionMatchingTest.java deleted file mode 100644 index 43e20fe..0000000 --- a/sidecar/rproxy/src/test/java/org/onap/aaf/rproxy/PermissionMatchingTest.java +++ /dev/null @@ -1,262 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aaf - * ================================================================================ - * Copyright © 2018 European Software Marketing Ltd. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ -package org.onap.aaf.rproxy; - -import static org.hamcrest.Matchers.equalTo; -import static org.springframework.test.web.client.match.MockRestRequestMatchers.header; -import static org.springframework.test.web.client.match.MockRestRequestMatchers.method; -import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; -import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import javax.annotation.Resource; -import org.eclipse.jetty.util.security.Password; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.onap.aaf.rproxy.config.ForwardProxyProperties; -import org.onap.aaf.rproxy.config.PrimaryServiceProperties; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.http.HttpMethod; -import org.springframework.http.MediaType; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.client.MockRestServiceServer; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; -import org.springframework.web.client.RestTemplate; - - -@RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) -@AutoConfigureMockMvc - -@TestPropertySource(locations = {"classpath:primary-service.properties", "classpath:forward-proxy.properties"}) - -@ContextConfiguration(classes = ReverseProxyTestConfig.class) -public class PermissionMatchingTest { - - static { - System.setProperty("server.ssl.key-store-password", - Password.deobfuscate("OBF:1y0q1uvc1uum1uvg1pil1pjl1uuq1uvk1uuu1y10")); - } - - @Value("${transactionid.header.name}") - private String transactionIdHeaderName; - - @Resource(name = "PrimaryServiceProperties") - private PrimaryServiceProperties primaryServiceProps; - - @Resource(name = "ForwardProxyProperties") - private ForwardProxyProperties forwardProxyProps; - - @Autowired - private MockMvc mockMvc; - - @Autowired - private RestTemplate restTemplate; - - private MockRestServiceServer mockServer; - - private String primaryServiceBaseUrl; - - @Before - public void setUp() throws Exception { - mockServer = MockRestServiceServer.createServer(restTemplate); - primaryServiceBaseUrl = primaryServiceProps.getProtocol() + "://" + primaryServiceProps.getHost() + ":" - + primaryServiceProps.getPort(); - } - - @Test - public void testURIMismatch() throws Exception { - - String testUrl = "/uri/does/not/exist"; - String testResponse = "Sorry, the request is not allowed"; - - mockMvc - .perform(get(testUrl)) - .andExpect(status().isForbidden()) - .andExpect(status().reason(testResponse)); - - } - - @Test - public void testURINoPermission() throws Exception { - - String testUrl = "/not/allowed/at/all"; - String testResponse = "Sorry, the request is not allowed"; - - mockMvc - .perform(get(testUrl)) - .andExpect(status().isForbidden()) - .andExpect(status().reason(testResponse)); - - } - - @Test - public void testURIMatchSinglePermissionMatch() throws Exception { - - String transactionId = "63f88b50-6345-4a61-bc59-3a48cabb60a4"; - String testUrl = "/single/permission/required"; - String testResponse = "Response from MockRestService"; - - mockServer - .expect(requestTo(primaryServiceBaseUrl + testUrl)) - .andExpect(method(HttpMethod.GET)) - .andExpect(header(transactionIdHeaderName, transactionId)) - .andRespond(withSuccess(testResponse, MediaType.APPLICATION_JSON)); - - // Send request to mock server with transaction Id - mockMvc - .perform(MockMvcRequestBuilders.get(testUrl).accept(MediaType.APPLICATION_JSON).header(transactionIdHeaderName, transactionId)) - .andExpect(status().isOk()) - .andExpect(content().string(equalTo(testResponse))); - - mockServer.verify(); - - } - - @Test - public void testURIMatchMultiplePermissionMatch() throws Exception { - - String transactionId = "63f88b50-6345-4a61-bc59-3a48cabb60a4"; - String testUrl = "/multiple/permissions/required"; - String testResponse = "Response from MockRestService"; - - mockServer - .expect(requestTo(primaryServiceBaseUrl + testUrl)) - .andExpect(method(HttpMethod.GET)) - .andExpect(header(transactionIdHeaderName, transactionId)) - .andRespond(withSuccess(testResponse, MediaType.APPLICATION_JSON)); - - // Send request to mock server with transaction Id - mockMvc - .perform(MockMvcRequestBuilders.get(testUrl).accept(MediaType.APPLICATION_JSON).header(transactionIdHeaderName, transactionId)) - .andExpect(status().isOk()) - .andExpect(content().string(equalTo(testResponse))); - - mockServer.verify(); - - } - - @Test - public void testURIMatchMultipleMissingOnePermissionMatch() throws Exception { - - String testUrl = "/multiple/permissions/required/one/missing"; - String testResponse = "Sorry, the request is not allowed"; - - mockMvc - .perform(get(testUrl)) - .andExpect(status().isForbidden()) - .andExpect(status().reason(testResponse)); - } - - @Test - public void testURIInstanceActionWildCardPermissionMatch() throws Exception { - - String transactionId = "63f88b50-6345-4a61-bc59-3a48cabb60a4"; - String testUrl = "/wildcard/permission/granted"; - String testResponse = "Response from MockRestService"; - - mockServer - .expect(requestTo(primaryServiceBaseUrl + testUrl)) - .andExpect(method(HttpMethod.GET)) - .andExpect(header(transactionIdHeaderName, transactionId)) - .andRespond(withSuccess(testResponse, MediaType.APPLICATION_JSON)); - - // Send request to mock server with transaction Id - mockMvc - .perform(MockMvcRequestBuilders - .get(testUrl) - .accept(MediaType.APPLICATION_JSON) - .header(transactionIdHeaderName, transactionId) - .header("PermissionsUser", "UserWithInstanceActionWildcardPermissionGranted") - ) - .andExpect(status().isOk()) - .andExpect(content().string(equalTo(testResponse))); - - mockServer.verify(); - - } - - @Test - public void testURIInstanceWildCardPermissionMatch() throws Exception { - - String transactionId = "63f88b50-6345-4a61-bc59-3a48cabb60a4"; - String testUrl = "/instance/wildcard/permission/granted"; - String testResponse = "Response from MockRestService"; - - mockServer - .expect(requestTo(primaryServiceBaseUrl + testUrl)) - .andExpect(method(HttpMethod.GET)) - .andExpect(header(transactionIdHeaderName, transactionId)) - .andRespond(withSuccess(testResponse, MediaType.APPLICATION_JSON)); - - // Send request to mock server with transaction Id - mockMvc - .perform(MockMvcRequestBuilders - .get(testUrl) - .accept(MediaType.APPLICATION_JSON) - .header(transactionIdHeaderName, transactionId) - .header("PermissionsUser", "UserWithInstanceWildcardPermissionGranted") - ) - .andExpect(status().isOk()) - .andExpect(content().string(equalTo(testResponse))); - - mockServer.verify(); - - } - - @Test - public void testURIActionWildCardPermissionMatch() throws Exception { - - String transactionId = "63f88b50-6345-4a61-bc59-3a48cabb60a4"; - String testUrl = "/action/wildcard/permission/granted"; - String testResponse = "Response from MockRestService"; - - mockServer - .expect(requestTo(primaryServiceBaseUrl + testUrl)) - .andExpect(method(HttpMethod.GET)) - .andExpect(header(transactionIdHeaderName, transactionId)) - .andRespond(withSuccess(testResponse, MediaType.APPLICATION_JSON)); - - // Send request to mock server with transaction Id - mockMvc - .perform(MockMvcRequestBuilders - .get(testUrl) - .accept(MediaType.APPLICATION_JSON) - .header(transactionIdHeaderName, transactionId) - .header("PermissionsUser", "UserWithActionWildcardPermissionGranted") - ) - .andExpect(status().isOk()) - .andExpect(content().string(equalTo(testResponse))); - - mockServer.verify(); - - } - -} diff --git a/sidecar/rproxy/src/test/java/org/onap/aaf/rproxy/ReverseProxyApplicationTest.java b/sidecar/rproxy/src/test/java/org/onap/aaf/rproxy/ReverseProxyApplicationTest.java deleted file mode 100644 index 61a0923..0000000 --- a/sidecar/rproxy/src/test/java/org/onap/aaf/rproxy/ReverseProxyApplicationTest.java +++ /dev/null @@ -1,158 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aaf - * ================================================================================ - * Copyright © 2018 European Software Marketing Ltd. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ -package org.onap.aaf.rproxy; - -import static org.hamcrest.Matchers.equalTo; -import static org.springframework.test.web.client.match.MockRestRequestMatchers.header; -import static org.springframework.test.web.client.match.MockRestRequestMatchers.method; -import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; -import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import javax.annotation.Resource; -import org.eclipse.jetty.http.HttpHeader; -import org.eclipse.jetty.util.security.Password; -import org.hamcrest.Matchers; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.onap.aaf.rproxy.config.ForwardProxyProperties; -import org.onap.aaf.rproxy.config.PrimaryServiceProperties; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.http.HttpMethod; -import org.springframework.http.MediaType; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.client.MockRestServiceServer; -import org.springframework.test.web.client.match.MockRestRequestMatchers; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; -import org.springframework.web.client.RestTemplate; - -@RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) -@AutoConfigureMockMvc -@TestPropertySource(locations = {"classpath:primary-service.properties", "classpath:forward-proxy.properties"}) -@ContextConfiguration(classes = ReverseProxyTestConfig.class) -public class ReverseProxyApplicationTest { - - static { - System.setProperty("server.ssl.key-store-password", - Password.deobfuscate("OBF:1y0q1uvc1uum1uvg1pil1pjl1uuq1uvk1uuu1y10")); - } - - @Value("${transactionid.header.name}") - private String transactionIdHeaderName; - - @Resource(name = "PrimaryServiceProperties") - private PrimaryServiceProperties primaryServiceProps; - - @Resource(name = "ForwardProxyProperties") - private ForwardProxyProperties forwardProxyProps; - - @Autowired - private MockMvc mockMvc; - - @Autowired - private RestTemplate restTemplate; - - private MockRestServiceServer mockServer; - - private String primaryServiceBaseUrl; - private String forwardProxyBaseUrl; - - @Before - public void setUp() throws Exception { - mockServer = MockRestServiceServer.createServer(restTemplate); - primaryServiceBaseUrl = primaryServiceProps.getProtocol() + "://" + primaryServiceProps.getHost() + ":" - + primaryServiceProps.getPort(); - forwardProxyBaseUrl = forwardProxyProps.getProtocol() + "://" + forwardProxyProps.getHost() + ":" - + forwardProxyProps.getPort() + forwardProxyProps.getCacheurl() + "/"; - } - - @Test - public void checkForwardRequest() throws Exception { - - String transactionId = "63f88b50-6345-4a61-bc59-3a48cabb60a4"; - String testUrl = "/aai/v13/cloud-infrastructure/cloud-regions"; - String testResponse = "Response from MockRestService"; - - mockServer.expect(requestTo(primaryServiceBaseUrl + testUrl)).andExpect(method(HttpMethod.GET)) - .andExpect(header(transactionIdHeaderName, transactionId)) - .andRespond(withSuccess(testResponse, MediaType.APPLICATION_JSON)); - - // Send request to mock server with transaction Id - mockMvc.perform(MockMvcRequestBuilders.get(testUrl).accept(MediaType.APPLICATION_JSON) - .header(transactionIdHeaderName, transactionId)).andExpect(status().isOk()) - .andExpect(content().string(equalTo(testResponse))); - - mockServer.verify(); - } - - @Test - public void checkTransactionIdIsSetIfEmptyInRequest() throws Exception { - - String testUrl = "/aai/v13/cloud-infrastructure/cloud-regions"; - String testResponse = "Response from MockRestService"; - - mockServer.expect(requestTo(primaryServiceBaseUrl + testUrl)).andExpect(method(HttpMethod.GET)) - .andExpect(header(transactionIdHeaderName, Matchers.any(String.class))) - .andRespond(withSuccess(testResponse, MediaType.APPLICATION_JSON)); - - // Send request to mock server without transaction Id - mockMvc.perform(MockMvcRequestBuilders.get(testUrl).accept(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()).andExpect(content().string(equalTo(testResponse))); - - mockServer.verify(); - } - - @Test - public void checkBasicAuthCaching() throws Exception { - - String transactionId = "63f88b50-6345-4a61-bc59-3a48cabb60a4"; - String testUrl = "/aai/v13/cloud-infrastructure/cloud-regions"; - String testResponse = "Response from MockRestService"; - String testAuthValue = "testAuthValue"; - String testCachePayload = "{ \"credentialName\":" + HttpHeader.AUTHORIZATION + ", \"credentialValue\":" - + testAuthValue + ", \"credentialType\":\"HEADER\" }"; - - mockServer.expect(requestTo(forwardProxyBaseUrl + transactionId)).andExpect(method(HttpMethod.POST)) - .andExpect(MockRestRequestMatchers.content().json(testCachePayload)) - .andRespond(withSuccess(testResponse, MediaType.APPLICATION_JSON)); - - mockServer.expect(requestTo(primaryServiceBaseUrl + testUrl)).andExpect(method(HttpMethod.GET)) - .andExpect(header(transactionIdHeaderName, transactionId)) - .andRespond(withSuccess(testResponse, MediaType.APPLICATION_JSON)); - - // Send request to mock server with transaction Id - mockMvc.perform(MockMvcRequestBuilders.get(testUrl).accept(MediaType.APPLICATION_JSON) - .header(transactionIdHeaderName, transactionId) - .header(HttpHeader.AUTHORIZATION.asString(), testAuthValue)).andExpect(status().isOk()) - .andExpect(content().string(equalTo(testResponse))); - - mockServer.verify(); - } -} diff --git a/sidecar/rproxy/src/test/java/org/onap/aaf/rproxy/ReverseProxyIT.java b/sidecar/rproxy/src/test/java/org/onap/aaf/rproxy/ReverseProxyIT.java deleted file mode 100644 index 615afd4..0000000 --- a/sidecar/rproxy/src/test/java/org/onap/aaf/rproxy/ReverseProxyIT.java +++ /dev/null @@ -1,48 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aaf - * ================================================================================ - * Copyright © 2018 European Software Marketing Ltd. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ -package org.onap.aaf.rproxy; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.eclipse.jetty.util.security.Password; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) -public class ReverseProxyIT { - - static { - System.setProperty("server.ssl.key-store-password", - Password.deobfuscate("OBF:1y0q1uvc1uum1uvg1pil1pjl1uuq1uvk1uuu1y10")); - } - - @Autowired - private ReverseProxyService rProxyService; - - @Test - public void contexLoads() throws Exception { - assertThat(rProxyService).isNotNull(); - } -} diff --git a/sidecar/rproxy/src/test/java/org/onap/aaf/rproxy/ReverseProxyTestConfig.java b/sidecar/rproxy/src/test/java/org/onap/aaf/rproxy/ReverseProxyTestConfig.java deleted file mode 100644 index c512e6a..0000000 --- a/sidecar/rproxy/src/test/java/org/onap/aaf/rproxy/ReverseProxyTestConfig.java +++ /dev/null @@ -1,42 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aaf - * ================================================================================ - * Copyright © 2018 European Software Marketing Ltd. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ -package org.onap.aaf.rproxy; - -import org.onap.aaf.rproxy.mocks.ReverseProxyMockCadiFilter; -import org.springframework.boot.test.context.TestConfiguration; -import org.springframework.boot.web.servlet.FilterRegistrationBean; -import org.springframework.boot.web.servlet.RegistrationBean; -import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; -import org.springframework.context.annotation.Bean; - -@TestConfiguration -public class ReverseProxyTestConfig extends SpringBootServletInitializer { - - @Bean - public FilterRegistrationBean registerCADIFilter() { - FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean<>(); - filterRegistrationBean.setFilter(new ReverseProxyMockCadiFilter()); - filterRegistrationBean.addUrlPatterns("/*"); - filterRegistrationBean.setName("CADIFilter"); - filterRegistrationBean.setOrder(RegistrationBean.HIGHEST_PRECEDENCE); - - return filterRegistrationBean; - } -} -- cgit 1.2.3-korg