Commit a22668fb authored by ethiraj krishnamanaidu's avatar ethiraj krishnamanaidu
Browse files

Merge branch 'azure_multi_tenancy' into 'master'

adds support azure multi-tenancy

See merge request !58
parents c7cff651 b1063aa5
Pipeline #27274 failed with stages
in 67 minutes and 18 seconds
......@@ -52,6 +52,8 @@ spec:
env:
- name: spring_application_name
value: notification-azure
- name: LOG_PREFIX
value: "notification"
- name: server.servlet.contextPath
value: /api/notification/v1
- name: server_port
......@@ -61,21 +63,6 @@ spec:
configMapKeyRef:
name: osdu-svc-properties
key: ENV_KEYVAULT
- name: AZURE_TENANT_ID
valueFrom:
secretKeyRef:
name: active-directory
key: tenantid
- name: AZURE_CLIENT_ID
valueFrom:
secretKeyRef:
name: active-directory
key: principal-clientid
- name: AZURE_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: active-directory
key: principal-clientpassword
- name: aad_client_id
valueFrom:
secretKeyRef:
......@@ -92,5 +79,7 @@ spec:
value: http://entitlements-azure/entitlements/v1
- name: registeration_service_endpoint
value: http://register/api/register/v1
- name: partition_service_endpoint
value: http://partition/api/partition/v1
- name: maxCacheSize
value: "20"
\ No newline at end of file
......@@ -19,6 +19,7 @@ package org.opengroup.osdu.notification.auth;
import org.opengroup.osdu.core.common.entitlements.EntitlementsAPIConfig;
import org.opengroup.osdu.core.common.entitlements.EntitlementsFactory;
import org.opengroup.osdu.core.common.entitlements.IEntitlementsFactory;
import org.opengroup.osdu.core.common.http.json.HttpResponseBodyMapper;
import org.opengroup.osdu.notification.provider.interfaces.IAppProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AbstractFactoryBean;
......@@ -28,11 +29,14 @@ import org.springframework.stereotype.Component;
public class EntitlementsClientFactory extends AbstractFactoryBean<IEntitlementsFactory> {
@Autowired
private IAppProperties config;
private IAppProperties config;
@Autowired
private HttpResponseBodyMapper responseBodyMapper;
@Override
protected IEntitlementsFactory createInstance() {
return new EntitlementsFactory(EntitlementsAPIConfig.builder().rootUrl(config.getAuthorizeAPI()).build());
return new EntitlementsFactory(EntitlementsAPIConfig.builder().rootUrl(config.getAuthorizeAPI()).build(),
responseBodyMapper);
}
@Override
......
......@@ -25,7 +25,7 @@
<java.version>8</java.version>
<maven.compiler.target>${java.version}</maven.compiler.target>
<maven.compiler.source>${java.version}</maven.compiler.source>
<os-core-common.version>0.3.6</os-core-common.version>
<os-core-common.version>0.3.27</os-core-common.version>
</properties>
<licenses>
......
......@@ -48,7 +48,7 @@
<dependency>
<groupId>org.opengroup.osdu.core.aws</groupId>
<artifactId>os-core-lib-aws</artifactId>
<version>0.3.14</version>
<version>0.6.0-SNAPSHOT</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk-secretsmanager -->
......
......@@ -44,6 +44,8 @@ az keyvault secret show --vault-name $KEY_VAULT_NAME --name $KEY_VAULT_SECRET_NA
| `azure.activedirectory.AppIdUri` | `api://${azure.activedirectory.client-id}` | URI for AAD Application | no | -- |
| `azure.activedirectory.session-stateless` | `true` | Flag run in stateless mode (needed by AAD dependency) | no | -- |
| `KEYVAULT_URI` | ex `https://foo-keyvault.vault.azure.net/` | URI of KeyVault that holds application secrets | no | output of infrastructure deployment |
| `PARTITION_API` | ex `https://foo-partition.azurewebsites.net` | Partition Service API endpoint | no | output of infrastructure deployment |
| `azure.activedirectory.app-resource-id` | `********` | AAD client application ID | yes | output of infrastructure deployment |
### Configure Maven
......
......@@ -23,183 +23,168 @@
<description>Azure implementation for Notification service</description>
<packaging>jar</packaging>
<parent>
<groupId>org.opengroup.osdu</groupId>
<artifactId>os-notification</artifactId>
<version>0.6.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<parent>
<groupId>org.opengroup.osdu</groupId>
<artifactId>os-notification</artifactId>
<version>0.6.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<properties>
<java.version>8</java.version>
<maven.compiler.target>${java.version}</maven.compiler.target>
<maven.compiler.source>${java.version}</maven.compiler.source>
<azure.version>2.1.7</azure.version>
<springframework.version>4.3.0.RELEASE</springframework.version>
<reactor.netty.version>0.9.0.RELEASE</reactor.netty.version>
<reactor.core.version>3.3.0.RELEASE</reactor.core.version>
</properties>
<properties>
<java.version>8</java.version>
<maven.compiler.target>${java.version}</maven.compiler.target>
<maven.compiler.source>${java.version}</maven.compiler.source>
<jacoco-maven-plugin.version>0.8.2</jacoco-maven-plugin.version>
<osdu.notification-core.version>0.6.0-SNAPSHOT</osdu.notification-core.version>
<springframework.version>4.3.0.RELEASE</springframework.version>
<reactor.netty.version>0.9.0.RELEASE</reactor.netty.version>
<reactor.core.version>3.3.0.RELEASE</reactor.core.version>
<osdu.corelibazure.version>0.0.66</osdu.corelibazure.version>
<junit.version>5.6.0</junit.version>
<jjwt.version>3.8.1</jjwt.version>
<mockito.version>2.23.0</mockito.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-active-directory-spring-boot-starter</artifactId>
<version>${azure.version}</version>
</dependency>
<dependency>
<groupId>org.opengroup.osdu</groupId>
<artifactId>os-core-common</artifactId>
<version>0.3.6</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<exclusions>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.opengroup.osdu</groupId>
<artifactId>core-lib-azure</artifactId>
<version>0.0.22</version>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.8.1</version>
</dependency>
<dependency>
<groupId>org.opengroup.osdu</groupId>
<artifactId>notification-core</artifactId>
<version>0.6.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.3.0</version>
</dependency>
<!-- Inherit managed dependencies from core-lib-azure -->
<dependency>
<groupId>org.opengroup.osdu</groupId>
<artifactId>core-lib-azure</artifactId>
<version>${osdu.corelibazure.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!--
Override the spring-boot version of these dependencies to the ones
required by the azure-core library. This needs to be done for each
app that depends on this library
-->
<dependency>
<groupId>io.projectreactor.netty</groupId>
<artifactId>reactor-netty</artifactId>
<version>${reactor.netty.version}</version>
</dependency>
<dependencies>
<!-- OSDU Dependencies -->
<dependency>
<groupId>org.opengroup.osdu</groupId>
<artifactId>notification-core</artifactId>
<version>${osdu.notification-core.version}</version>
</dependency>
<dependency>
<groupId>org.opengroup.osdu</groupId>
<artifactId>os-core-common</artifactId>
</dependency>
<dependency>
<groupId>org.opengroup.osdu</groupId>
<artifactId>core-lib-azure</artifactId>
<version>${osdu.corelibazure.version}</version>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
<version>${reactor.core.version}</version>
</dependency>
<!-- Spring Dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<exclusions>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Test Dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
<version>2.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.6.0</version>
<scope>test</scope>
</dependency>
<!-- Azure Dependencies -->
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-active-directory-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>2.23.0</version>
<scope>test</scope>
</dependency>
</dependencies>
<!-- Test Dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.2</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>prepare-package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<classifier>spring-boot</classifier>
<mainClass>
org.opengroup.osdu.notification.provider.azure.Application
</mainClass>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.4.2</version>
<configuration>
<useSystemClassLoader>false</useSystemClassLoader>
<threadCount>1</threadCount>
</configuration>
</plugin>
</plugins>
</build>
<reporting>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<reportSets>
<reportSet>
<reports>
<!-- select non-aggregate reports -->
<report>report</report>
</reports>
</reportSet>
</reportSets>
</plugin>
</plugins>
</reporting>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco-maven-plugin.version}</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>prepare-package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<classifier>spring-boot</classifier>
<mainClass>org.opengroup.osdu.notification.provider.azure.Application</mainClass>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.4.2</version>
<configuration>
<useSystemClassLoader>false</useSystemClassLoader>
<threadCount>1</threadCount>
</configuration>
</plugin>
</plugins>
</build>
<reporting>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<reportSets>
<reportSet>
<reports>
<!-- select non-aggregate reports -->
<report>report</report>
</reports>
</reportSet>
</reportSets>
</plugin>
</plugins>
</reporting>
</project>
\ No newline at end of file
package org.opengroup.osdu.notification.provider.azure.util;
import com.azure.security.keyvault.secrets.SecretClient;
import com.azure.security.keyvault.secrets.models.KeyVaultSecret;
import javax.inject.Named;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.inject.Named;
@Configuration
public class AzureCosmosProperties {
@Value("${tenantinfo.container.name}")
private String tenantInfoContainerName;
@Value("${azure.cosmosdb.database}")
private String cosmosDBName;
// TODO : Move away from Named beans.
@Bean
@Named("COSMOS_ENDPOINT")
public String cosmosEndpoint(SecretClient kv) {
return getKeyVaultSecret(kv, "opendes-cosmos-endpoint");
}
@Bean
@Named("COSMOS_KEY")
public String cosmosKey(SecretClient kv) {
return getKeyVaultSecret(kv, "opendes-cosmos-primary-key");
}
@Bean
@Named("COSMOS_CONTAINER_NAME")
public String containerName() {
return tenantInfoContainerName;
}
@Bean
@Named("COSMOS_DB_NAME")
public String cosmosDBName() {
return cosmosDBName;
}
private String getKeyVaultSecret(SecretClient kv, String secretName) {
KeyVaultSecret secret = kv.getSecret(secretName);
if (secret == null) {
throw new IllegalStateException(String.format("No secret found with name %s", secretName));
}
String secretValue = secret.getValue();
if (secretValue == null) {
throw new IllegalStateException(String.format(
"Secret unexpectedly missing from KeyVault response for secret with name %s", secretName));
}
return secretValue;
}
@Value("${tenantinfo.container.name}")
private String tenantInfoContainerName;
@Value("${azure.cosmosdb.database}")
private String cosmosDBName;
@Bean
@Named("COSMOS_CONTAINER_NAME")
public String containerName() {
return tenantInfoContainerName;
}
@Bean
@Named("COSMOS_DB_NAME")
public String cosmosDBName() {
return cosmosDBName;
}
}
......@@ -14,62 +14,75 @@
package org.opengroup.osdu.notification.provider.azure.util;
import org.opengroup.osdu.notification.provider.interfaces.IPubsubHandshakeHandler;
import org.opengroup.osdu.notification.provider.interfaces.IPubsubRequestBodyExtractor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import static org.opengroup.osdu.core.common.http.ResponseHeaders.STANDARD_RESPONSE_HEADERS;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.Map;
import static org.opengroup.osdu.core.common.http.ResponseHeaders.STANDARD_RESPONSE_HEADERS;
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.opengroup.osdu.notification.provider.interfaces.IPubsubHandshakeHandler;
import org.opengroup.osdu.notification.provider.interfaces.IPubsubRequestBodyExtractor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
/**
* TODO: logic needs to be reviewed to avoid looping dependency happening in EventGridRequestBodyExtractor for RQs
* handshake if any other filters try to inject DpsHeaders before this filter, up for now set to lowest value for
* order
*/
@Component
@Order(0)
@Order(-104)
public class HandshakeFilter implements Filter {
@Autowired
private IPubsubRequestBodyExtractor requestBodyExtractor;
@Autowired
private IPubsubRequestBodyExtractor requestBodyExtractor;
@Autowired
private IPubsubHandshakeHandler handshakeHandler;
@Autowired
private IPubsubHandshakeHandler handshakeHandler;
@Override
public void init(FilterConfig filterConfig) {
//do nothing
}
@Override
public void init(FilterConfig filterConfig) {
//do nothing
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
if(request.getServletPath().contains("records-changed") && this.requestBodyExtractor.isHandshakeRequest()){
HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
httpServletResponse.setStatus(200);
httpServletResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);
setResponseHeaders(httpServletResponse);
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
if (request.getServletPath().contains("records-changed") && this.requestBodyExtractor.isHandshakeRequest()) {
HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
httpServletResponse.</