Integration with AWS Secrets Manager (#1638)
EnvironmentRepository for AWS Secrets Manager Co-authored-by: Tejas Pandilwar <tejas.pandilwar@gs.com> Co-authored-by: Spencer Gibb <sgibb@pivotal.io>
This commit is contained in:
@@ -802,6 +802,38 @@ credhub set --name "/my-app/default/master/more-shared" --type=json
|
||||
value: {"shared.word1": "hello", "shared.word2": "world"}
|
||||
----
|
||||
|
||||
==== AWS Secrets Manager
|
||||
When using AWS Secrets Manager as a backend, you can share configuration with all applications by placing configuration in `/application/` or by placing it in the `default` profile for the application.
|
||||
For example, if you add secrets with the following keys, all application using the config server will have the properties `shared.foo` and `shared.bar` available to them:
|
||||
|
||||
[source]
|
||||
----
|
||||
secret name = /secret/application-default/
|
||||
----
|
||||
[source,json]
|
||||
----
|
||||
secret value =
|
||||
{
|
||||
shared.foo: foo,
|
||||
shared.bar: bar
|
||||
}
|
||||
----
|
||||
or
|
||||
[source]
|
||||
----
|
||||
secret name = /secret/application/
|
||||
----
|
||||
[source,json]
|
||||
----
|
||||
secret value =
|
||||
{
|
||||
shared.foo: foo,
|
||||
shared.bar: bar
|
||||
}
|
||||
----
|
||||
|
||||
----
|
||||
|
||||
==== JDBC Backend
|
||||
|
||||
Spring Cloud Config Server supports JDBC (relational database) as a backend for configuration properties.
|
||||
@@ -900,6 +932,46 @@ Configuration files are stored in your bucket as `{application}-{profile}.proper
|
||||
|
||||
NOTE: When no profile is specified `default` will be used.
|
||||
|
||||
==== AWS Secrets Manager Backend
|
||||
|
||||
Spring Cloud Config Server supports link:https://aws.amazon.com/secrets-manager/[AWS Secrets Manager] as a backend for configuration properties.
|
||||
You can enable this feature by adding a dependency to link:https://github.com/aws/aws-sdk-java/tree/master/aws-java-sdk-secretsmanager[AWS Java SDK for Secrets Manager].
|
||||
|
||||
[source,xml,indent=0]
|
||||
.pom.xml
|
||||
----
|
||||
<dependency>
|
||||
<groupId>com.amazonaws</groupId>
|
||||
<artifactId>aws-java-sdk-secretsmanager</artifactId>
|
||||
</dependency>
|
||||
----
|
||||
|
||||
The following configuration uses the AWS Secrets Manager client to access secrets.
|
||||
|
||||
[source,yaml]
|
||||
----
|
||||
spring:
|
||||
profiles:
|
||||
active: awssecretsmanager
|
||||
cloud:
|
||||
config:
|
||||
server:
|
||||
aws-secretsmanager:
|
||||
region: us-east-1
|
||||
endpoint: https://us-east-1.console.aws.amazon.com/
|
||||
origin: aws:secrets:
|
||||
prefix: /secret/foo
|
||||
profileSeparator: _
|
||||
|
||||
----
|
||||
|
||||
AWS Secrets Manager API credentials are determined using link:https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/credentials.html#credentials-default[Default Credential Provider Chain].
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
- When no application is specified `application` is the default, and when no profile is specified `default` is used.
|
||||
====
|
||||
|
||||
==== CredHub Backend
|
||||
|
||||
Spring Cloud Config Server supports link:https://docs.cloudfoundry.org/credhub[CredHub] as a backend for configuration properties.
|
||||
|
||||
5
pom.xml
5
pom.xml
@@ -78,6 +78,11 @@
|
||||
<artifactId>aws-java-sdk-s3</artifactId>
|
||||
<version>${aws-java-sdk.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.amazonaws</groupId>
|
||||
<artifactId>aws-java-sdk-secretsmanager</artifactId>
|
||||
<version>${aws-java-sdk.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.apis</groupId>
|
||||
<artifactId>google-api-services-iam</artifactId>
|
||||
|
||||
@@ -99,6 +99,11 @@
|
||||
<artifactId>aws-java-sdk-s3</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.amazonaws</groupId>
|
||||
<artifactId>aws-java-sdk-secretsmanager</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-autoconfigure-processor</artifactId>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,6 +22,7 @@ import java.util.Optional;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import com.amazonaws.services.s3.AmazonS3;
|
||||
import com.amazonaws.services.secretsmanager.AWSSecretsManager;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.eclipse.jgit.api.TransportConfigCallback;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
@@ -41,6 +42,9 @@ import org.springframework.cloud.config.server.composite.ConditionalOnSearchPath
|
||||
import org.springframework.cloud.config.server.environment.AwsS3EnvironmentProperties;
|
||||
import org.springframework.cloud.config.server.environment.AwsS3EnvironmentRepository;
|
||||
import org.springframework.cloud.config.server.environment.AwsS3EnvironmentRepositoryFactory;
|
||||
import org.springframework.cloud.config.server.environment.AwsSecretsManagerEnvironmentProperties;
|
||||
import org.springframework.cloud.config.server.environment.AwsSecretsManagerEnvironmentRepository;
|
||||
import org.springframework.cloud.config.server.environment.AwsSecretsManagerEnvironmentRepositoryFactory;
|
||||
import org.springframework.cloud.config.server.environment.CompositeEnvironmentRepository;
|
||||
import org.springframework.cloud.config.server.environment.ConfigTokenProvider;
|
||||
import org.springframework.cloud.config.server.environment.ConfigurableHttpConnectionFactory;
|
||||
@@ -97,16 +101,23 @@ import org.springframework.vault.core.VaultTemplate;
|
||||
* @author Dylan Roberts
|
||||
* @author Alberto C. Ríos
|
||||
* @author Scott Frederick
|
||||
* @author Tejas Pandilwar
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties({ SvnKitEnvironmentProperties.class, CredhubEnvironmentProperties.class,
|
||||
JdbcEnvironmentProperties.class, NativeEnvironmentProperties.class, VaultEnvironmentProperties.class,
|
||||
RedisEnvironmentProperties.class, AwsS3EnvironmentProperties.class })
|
||||
@Import({ CompositeRepositoryConfiguration.class, JdbcRepositoryConfiguration.class, VaultConfiguration.class,
|
||||
VaultRepositoryConfiguration.class, SpringVaultRepositoryConfiguration.class, CredhubConfiguration.class,
|
||||
CredhubRepositoryConfiguration.class, SvnRepositoryConfiguration.class, NativeRepositoryConfiguration.class,
|
||||
GitRepositoryConfiguration.class, RedisRepositoryConfiguration.class, GoogleCloudSourceConfiguration.class,
|
||||
AwsS3RepositoryConfiguration.class, DefaultRepositoryConfiguration.class })
|
||||
@EnableConfigurationProperties({ SvnKitEnvironmentProperties.class,
|
||||
CredhubEnvironmentProperties.class, JdbcEnvironmentProperties.class,
|
||||
NativeEnvironmentProperties.class, VaultEnvironmentProperties.class,
|
||||
RedisEnvironmentProperties.class, AwsS3EnvironmentProperties.class,
|
||||
AwsSecretsManagerEnvironmentProperties.class })
|
||||
@Import({ CompositeRepositoryConfiguration.class, JdbcRepositoryConfiguration.class,
|
||||
VaultConfiguration.class, VaultRepositoryConfiguration.class,
|
||||
SpringVaultRepositoryConfiguration.class, CredhubConfiguration.class,
|
||||
CredhubRepositoryConfiguration.class, SvnRepositoryConfiguration.class,
|
||||
NativeRepositoryConfiguration.class, GitRepositoryConfiguration.class,
|
||||
RedisRepositoryConfiguration.class, GoogleCloudSourceConfiguration.class,
|
||||
AwsS3RepositoryConfiguration.class,
|
||||
AwsSecretsManagerRepositoryConfiguration.class,
|
||||
DefaultRepositoryConfiguration.class })
|
||||
public class EnvironmentRepositoryConfiguration {
|
||||
|
||||
@Bean
|
||||
@@ -202,6 +213,19 @@ public class EnvironmentRepositoryConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass(AWSSecretsManager.class)
|
||||
static class AwsSecretsManagerFactoryConfig {
|
||||
|
||||
@Bean
|
||||
public AwsSecretsManagerEnvironmentRepositoryFactory awsSecretsManagerEnvironmentRepositoryFactory(
|
||||
ConfigServerProperties configServerProperties) {
|
||||
return new AwsSecretsManagerEnvironmentRepositoryFactory(
|
||||
configServerProperties);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass(SVNException.class)
|
||||
static class SvnFactoryConfig {
|
||||
@@ -350,6 +374,20 @@ class AwsS3RepositoryConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@Profile("awssecretsmanager")
|
||||
class AwsSecretsManagerRepositoryConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(AwsSecretsManagerEnvironmentRepository.class)
|
||||
public AwsSecretsManagerEnvironmentRepository awsSecretsManagerEnvironmentRepository(
|
||||
AwsSecretsManagerEnvironmentRepositoryFactory factory,
|
||||
AwsSecretsManagerEnvironmentProperties environmentProperties) {
|
||||
return factory.build(environmentProperties);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@Profile("subversion")
|
||||
class SvnRepositoryConfiguration {
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright 2018-2020 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.config.server.environment;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Pattern;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.cloud.config.server.support.EnvironmentRepositoryProperties;
|
||||
import org.springframework.core.Ordered;
|
||||
|
||||
/**
|
||||
* @author Tejas Pandilwar
|
||||
*/
|
||||
@ConfigurationProperties("spring.cloud.config.server.aws-secretsmanager")
|
||||
public class AwsSecretsManagerEnvironmentProperties
|
||||
implements EnvironmentRepositoryProperties {
|
||||
|
||||
static final String DEFAULT_PATH_SEPARATOR = "/";
|
||||
|
||||
private static final String DEFAULT_PREFIX = DEFAULT_PATH_SEPARATOR + "secret";
|
||||
|
||||
private static final String DEFAULT_PROFILE_SEPARATOR = "-";
|
||||
|
||||
private static final String DEFAULT_ORIGIN = "aws:secrets:";
|
||||
|
||||
/**
|
||||
* The region to be used by AWS Secrets Manager client.
|
||||
*/
|
||||
private String region;
|
||||
|
||||
/**
|
||||
* The endpoint to be used by AWS Secrets Manager client.
|
||||
* This can be used to specify an alternate endpoint for the API requests.
|
||||
*/
|
||||
private String endpoint;
|
||||
|
||||
/**
|
||||
* The order of the environment repository.
|
||||
*/
|
||||
private int order = Ordered.LOWEST_PRECEDENCE;
|
||||
|
||||
/**
|
||||
* Prefix indicating first level for every property loaded from AWS Secrets Manager.
|
||||
* Value must start with a forward slash followed by a valid path segment or be empty.
|
||||
* Defaults to "/secret".
|
||||
*/
|
||||
@NotNull
|
||||
@Pattern(regexp = "(/[a-zA-Z0-9.\\-_]+)*")
|
||||
private String prefix = DEFAULT_PREFIX;
|
||||
|
||||
/**
|
||||
* String that separates profile from the application name.
|
||||
*/
|
||||
@NotNull
|
||||
@Pattern(regexp = "[a-zA-Z0-9.\\-_]+")
|
||||
private String profileSeparator = DEFAULT_PROFILE_SEPARATOR;
|
||||
|
||||
/**
|
||||
* Prefix which indicates the origin of the property. Defaults to "aws:secrets:".
|
||||
*/
|
||||
@NotNull
|
||||
private String origin = DEFAULT_ORIGIN;
|
||||
|
||||
public String getRegion() {
|
||||
return region;
|
||||
}
|
||||
|
||||
public void setRegion(String region) {
|
||||
this.region = region;
|
||||
}
|
||||
|
||||
public String getEndpoint() {
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
public void setEndpoint(String endpoint) {
|
||||
this.endpoint = endpoint;
|
||||
}
|
||||
|
||||
public int getOrder() {
|
||||
return order;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOrder(int order) {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
public String getPrefix() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
public void setPrefix(String prefix) {
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
public String getProfileSeparator() {
|
||||
return profileSeparator;
|
||||
}
|
||||
|
||||
public void setProfileSeparator(String profileSeparator) {
|
||||
this.profileSeparator = profileSeparator;
|
||||
}
|
||||
|
||||
public String getOrigin() {
|
||||
return origin;
|
||||
}
|
||||
|
||||
public void setOrigin(String origin) {
|
||||
this.origin = origin;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Copyright 2018-2020 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.config.server.environment;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.amazonaws.services.secretsmanager.AWSSecretsManager;
|
||||
import com.amazonaws.services.secretsmanager.model.GetSecretValueRequest;
|
||||
import com.amazonaws.services.secretsmanager.model.GetSecretValueResult;
|
||||
import com.amazonaws.services.secretsmanager.model.ResourceNotFoundException;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.cloud.config.environment.Environment;
|
||||
import org.springframework.cloud.config.environment.PropertySource;
|
||||
import org.springframework.cloud.config.server.config.ConfigServerProperties;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import static org.springframework.cloud.config.server.environment.AwsSecretsManagerEnvironmentProperties.DEFAULT_PATH_SEPARATOR;
|
||||
|
||||
/**
|
||||
* @author Tejas Pandilwar
|
||||
*/
|
||||
public class AwsSecretsManagerEnvironmentRepository implements EnvironmentRepository {
|
||||
|
||||
private static final Log log = LogFactory
|
||||
.getLog(AwsSecretsManagerEnvironmentRepository.class);
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
private final AWSSecretsManager awsSmClient;
|
||||
|
||||
private final ConfigServerProperties configServerProperties;
|
||||
|
||||
private final AwsSecretsManagerEnvironmentProperties environmentProperties;
|
||||
|
||||
public AwsSecretsManagerEnvironmentRepository(AWSSecretsManager awsSmClient,
|
||||
ConfigServerProperties configServerProperties,
|
||||
AwsSecretsManagerEnvironmentProperties environmentProperties) {
|
||||
this.awsSmClient = awsSmClient;
|
||||
this.configServerProperties = configServerProperties;
|
||||
this.environmentProperties = environmentProperties;
|
||||
this.objectMapper = new ObjectMapper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Environment findOne(String application, String profileList, String label) {
|
||||
final String defaultApplication = configServerProperties
|
||||
.getDefaultApplicationName();
|
||||
final String defaultProfile = configServerProperties.getDefaultProfile();
|
||||
|
||||
if (StringUtils.isEmpty(application)) {
|
||||
application = defaultApplication;
|
||||
}
|
||||
|
||||
if (StringUtils.isEmpty(profileList)) {
|
||||
profileList = defaultProfile;
|
||||
}
|
||||
|
||||
String[] profiles = StringUtils.trimArrayElements(
|
||||
StringUtils.commaDelimitedListToStringArray(profileList));
|
||||
Environment environment = new Environment(application, profiles, label, null,
|
||||
null);
|
||||
|
||||
Map<String, String> overrides = configServerProperties.getOverrides();
|
||||
if (!overrides.isEmpty()) {
|
||||
environment.add(new PropertySource("overrides", overrides));
|
||||
}
|
||||
|
||||
for (String profile : profiles) {
|
||||
addPropertySource(environment, application, profile);
|
||||
if (!defaultApplication.equals(application)) {
|
||||
addPropertySource(environment, defaultApplication, profile);
|
||||
}
|
||||
}
|
||||
|
||||
if (!Arrays.asList(profiles).contains(defaultProfile)) {
|
||||
addPropertySource(environment, application, defaultProfile);
|
||||
}
|
||||
|
||||
if (!Arrays.asList(profiles).contains(defaultProfile)
|
||||
&& !defaultApplication.equals(application)) {
|
||||
addPropertySource(environment, defaultApplication, defaultProfile);
|
||||
}
|
||||
|
||||
if (!defaultApplication.equals(application)) {
|
||||
addPropertySource(environment, application, null);
|
||||
}
|
||||
|
||||
addPropertySource(environment, defaultApplication, null);
|
||||
|
||||
return environment;
|
||||
}
|
||||
|
||||
private void addPropertySource(Environment environment, String application,
|
||||
String profile) {
|
||||
String path = buildPath(application, profile);
|
||||
|
||||
Map<Object, Object> properties = findProperties(path);
|
||||
if (!properties.isEmpty()) {
|
||||
environment.add(new PropertySource(environmentProperties.getOrigin() + path,
|
||||
properties));
|
||||
}
|
||||
}
|
||||
|
||||
private String buildPath(String application, String profile) {
|
||||
String prefix = environmentProperties.getPrefix();
|
||||
String profileSeparator = environmentProperties.getProfileSeparator();
|
||||
|
||||
if (profile == null || profile.isEmpty()) {
|
||||
return prefix + DEFAULT_PATH_SEPARATOR + application + DEFAULT_PATH_SEPARATOR;
|
||||
}
|
||||
else {
|
||||
return prefix + DEFAULT_PATH_SEPARATOR + application + profileSeparator
|
||||
+ profile + DEFAULT_PATH_SEPARATOR;
|
||||
}
|
||||
}
|
||||
|
||||
private Map<Object, Object> findProperties(String path) {
|
||||
Map<Object, Object> properties = new HashMap<>();
|
||||
|
||||
GetSecretValueRequest request = new GetSecretValueRequest().withSecretId(path);
|
||||
try {
|
||||
GetSecretValueResult response = awsSmClient.getSecretValue(request);
|
||||
|
||||
if (response != null) {
|
||||
Map<String, Object> secretMap = objectMapper.readValue(
|
||||
response.getSecretString(),
|
||||
new TypeReference<Map<String, Object>>() {
|
||||
});
|
||||
|
||||
for (Map.Entry<String, Object> secretEntry : secretMap.entrySet()) {
|
||||
properties.put(secretEntry.getKey(), secretEntry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ResourceNotFoundException | IOException e) {
|
||||
log.debug(String.format(
|
||||
"Skip adding propertySource. Unable to load secrets from AWS Secrets Manager for secretId=%s",
|
||||
path), e);
|
||||
}
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2018-2020 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.config.server.environment;
|
||||
|
||||
import com.amazonaws.client.builder.AwsClientBuilder;
|
||||
import com.amazonaws.regions.Regions;
|
||||
import com.amazonaws.services.secretsmanager.AWSSecretsManager;
|
||||
import com.amazonaws.services.secretsmanager.AWSSecretsManagerClientBuilder;
|
||||
|
||||
import org.springframework.cloud.config.server.config.ConfigServerProperties;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* @author Tejas Pandilwar
|
||||
*/
|
||||
public class AwsSecretsManagerEnvironmentRepositoryFactory implements
|
||||
EnvironmentRepositoryFactory<AwsSecretsManagerEnvironmentRepository, AwsSecretsManagerEnvironmentProperties> {
|
||||
|
||||
private final ConfigServerProperties configServerProperties;
|
||||
|
||||
public AwsSecretsManagerEnvironmentRepositoryFactory(
|
||||
ConfigServerProperties configServerProperties) {
|
||||
this.configServerProperties = configServerProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AwsSecretsManagerEnvironmentRepository build(
|
||||
AwsSecretsManagerEnvironmentProperties environmentProperties) {
|
||||
AWSSecretsManagerClientBuilder clientBuilder = AWSSecretsManagerClientBuilder
|
||||
.standard();
|
||||
String region = environmentProperties.getRegion();
|
||||
|
||||
if (!StringUtils.isEmpty(region)) {
|
||||
Regions awsRegion = Regions.fromName(region);
|
||||
clientBuilder.withRegion(awsRegion);
|
||||
|
||||
String endpoint = environmentProperties.getEndpoint();
|
||||
if (!StringUtils.isEmpty(endpoint)) {
|
||||
AwsClientBuilder.EndpointConfiguration endpointConfiguration = new AwsClientBuilder.EndpointConfiguration(
|
||||
endpoint, awsRegion.getName());
|
||||
clientBuilder.withEndpointConfiguration(endpointConfiguration);
|
||||
}
|
||||
}
|
||||
|
||||
AWSSecretsManager client = clientBuilder.build();
|
||||
return new AwsSecretsManagerEnvironmentRepository(client, configServerProperties,
|
||||
environmentProperties);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,897 @@
|
||||
/*
|
||||
* Copyright 2016-2020 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.config.server.environment;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.amazonaws.services.secretsmanager.AWSSecretsManager;
|
||||
import com.amazonaws.services.secretsmanager.model.GetSecretValueRequest;
|
||||
import com.amazonaws.services.secretsmanager.model.GetSecretValueResult;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import org.apache.commons.lang3.RandomUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.cloud.config.environment.Environment;
|
||||
import org.springframework.cloud.config.environment.PropertySource;
|
||||
import org.springframework.cloud.config.server.config.ConfigServerProperties;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* @author Tejas Pandilwar
|
||||
*/
|
||||
public class AwsSecretsManagerEnvironmentRepositoryTests {
|
||||
|
||||
private static final Log log = LogFactory
|
||||
.getLog(AwsSecretsManagerEnvironmentRepository.class);
|
||||
|
||||
private final AWSSecretsManager awsSmClientMock = mock(AWSSecretsManager.class,
|
||||
"aws-sm-client-mock");
|
||||
|
||||
private final ConfigServerProperties configServerProperties = new ConfigServerProperties();
|
||||
|
||||
private final AwsSecretsManagerEnvironmentProperties environmentProperties = new AwsSecretsManagerEnvironmentProperties();
|
||||
|
||||
private final AwsSecretsManagerEnvironmentRepository repository = new AwsSecretsManagerEnvironmentRepository(
|
||||
awsSmClientMock, configServerProperties, environmentProperties);
|
||||
|
||||
private final ObjectMapper objectMapper = new ObjectMapper()
|
||||
.configure(SerializationFeature.INDENT_OUTPUT, true);
|
||||
|
||||
@Test
|
||||
public void testFindOneWithNullApplicationAndNullProfile() {
|
||||
String application = null;
|
||||
String profile = null;
|
||||
String defaultApplication = configServerProperties.getDefaultApplicationName();
|
||||
String defaultProfile = configServerProperties.getDefaultProfile();
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(defaultProfile);
|
||||
|
||||
String applicationDefaultPropertiesName = "aws:secrets:/secret/application-default/";
|
||||
PropertySource applicationDefaultProperties = new PropertySource(
|
||||
applicationDefaultPropertiesName, getApplicationDefaultProperties());
|
||||
|
||||
String applicationPropertiesName = "aws:secrets:/secret/application/";
|
||||
PropertySource applicationProperties = new PropertySource(
|
||||
applicationPropertiesName, getApplicationProperties());
|
||||
|
||||
Environment expectedEnv = new Environment(defaultApplication, profiles, null,
|
||||
null, null);
|
||||
expectedEnv.addAll(
|
||||
Arrays.asList(applicationDefaultProperties, applicationProperties));
|
||||
|
||||
setupAwsSmClientMocks(expectedEnv);
|
||||
|
||||
Environment resultEnv = repository.findOne(application, profile, null);
|
||||
|
||||
assertThat(resultEnv).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expectedEnv);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOneWithNullApplicationAndNonExistingProfile() {
|
||||
String application = null;
|
||||
String profile = randomAlphabetic(RandomUtils.nextInt(3, 25));
|
||||
String defaultApplication = configServerProperties.getDefaultApplicationName();
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
|
||||
|
||||
String applicationDefaultPropertiesName = "aws:secrets:/secret/application-default/";
|
||||
PropertySource applicationDefaultProperties = new PropertySource(
|
||||
applicationDefaultPropertiesName, getApplicationDefaultProperties());
|
||||
|
||||
String applicationPropertiesName = "aws:secrets:/secret/application/";
|
||||
PropertySource applicationProperties = new PropertySource(
|
||||
applicationPropertiesName, getApplicationProperties());
|
||||
|
||||
Environment expectedEnv = new Environment(defaultApplication, profiles, null,
|
||||
null, null);
|
||||
expectedEnv.addAll(
|
||||
Arrays.asList(applicationDefaultProperties, applicationProperties));
|
||||
|
||||
setupAwsSmClientMocks(expectedEnv);
|
||||
|
||||
Environment resultEnv = repository.findOne(application, profile, null);
|
||||
|
||||
assertThat(resultEnv).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expectedEnv);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOneWithNullApplicationAndDefaultProfile() {
|
||||
String application = null;
|
||||
String profile = configServerProperties.getDefaultProfile();
|
||||
String defaultApplication = configServerProperties.getDefaultApplicationName();
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
|
||||
|
||||
String applicationDefaultPropertiesName = "aws:secrets:/secret/application-default/";
|
||||
PropertySource applicationDefaultProperties = new PropertySource(
|
||||
applicationDefaultPropertiesName, getApplicationDefaultProperties());
|
||||
|
||||
String applicationPropertiesName = "aws:secrets:/secret/application/";
|
||||
PropertySource applicationProperties = new PropertySource(
|
||||
applicationPropertiesName, getApplicationProperties());
|
||||
|
||||
Environment expectedEnv = new Environment(defaultApplication, profiles, null,
|
||||
null, null);
|
||||
expectedEnv.addAll(
|
||||
Arrays.asList(applicationDefaultProperties, applicationProperties));
|
||||
|
||||
setupAwsSmClientMocks(expectedEnv);
|
||||
|
||||
Environment resultEnv = repository.findOne(application, profile, null);
|
||||
|
||||
assertThat(resultEnv).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expectedEnv);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOneWithNullApplicationAndExistingProfile() {
|
||||
String application = null;
|
||||
String profile = "prod";
|
||||
String defaultApplication = configServerProperties.getDefaultApplicationName();
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
|
||||
|
||||
String applicationProdPropertiesName = "aws:secrets:/secret/application-prod/";
|
||||
PropertySource applicationProdProperties = new PropertySource(
|
||||
applicationProdPropertiesName, getApplicationProdProperties());
|
||||
|
||||
String applicationDefaultPropertiesName = "aws:secrets:/secret/application-default/";
|
||||
PropertySource applicationDefaultProperties = new PropertySource(
|
||||
applicationDefaultPropertiesName, getApplicationDefaultProperties());
|
||||
|
||||
String applicationPropertiesName = "aws:secrets:/secret/application/";
|
||||
PropertySource applicationProperties = new PropertySource(
|
||||
applicationPropertiesName, getApplicationProperties());
|
||||
|
||||
Environment expectedEnv = new Environment(defaultApplication, profiles, null,
|
||||
null, null);
|
||||
expectedEnv.addAll(Arrays.asList(applicationProdProperties,
|
||||
applicationDefaultProperties, applicationProperties));
|
||||
|
||||
setupAwsSmClientMocks(expectedEnv);
|
||||
|
||||
Environment resultEnv = repository.findOne(application, profile, null);
|
||||
|
||||
assertThat(resultEnv).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expectedEnv);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOneWithDefaultApplicationAndNullProfile() {
|
||||
String application = configServerProperties.getDefaultApplicationName();
|
||||
String profile = null;
|
||||
String defaultProfile = configServerProperties.getDefaultProfile();
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(defaultProfile);
|
||||
|
||||
String applicationDefaultPropertiesName = "aws:secrets:/secret/application-default/";
|
||||
PropertySource applicationDefaultProperties = new PropertySource(
|
||||
applicationDefaultPropertiesName, getApplicationDefaultProperties());
|
||||
|
||||
String applicationPropertiesName = "aws:secrets:/secret/application/";
|
||||
PropertySource applicationProperties = new PropertySource(
|
||||
applicationPropertiesName, getApplicationProperties());
|
||||
|
||||
Environment expectedEnv = new Environment(application, profiles, null, null,
|
||||
null);
|
||||
expectedEnv.addAll(
|
||||
Arrays.asList(applicationDefaultProperties, applicationProperties));
|
||||
|
||||
setupAwsSmClientMocks(expectedEnv);
|
||||
|
||||
Environment resultEnv = repository.findOne(application, profile, null);
|
||||
|
||||
assertThat(resultEnv).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expectedEnv);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOneWithDefaultApplicationAndDefaultProfile() {
|
||||
String application = configServerProperties.getDefaultApplicationName();
|
||||
String profile = configServerProperties.getDefaultProfile();
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
|
||||
|
||||
String applicationDefaultPropertiesName = "aws:secrets:/secret/application-default/";
|
||||
PropertySource applicationDefaultProperties = new PropertySource(
|
||||
applicationDefaultPropertiesName, getApplicationDefaultProperties());
|
||||
|
||||
String applicationPropertiesName = "aws:secrets:/secret/application/";
|
||||
PropertySource applicationProperties = new PropertySource(
|
||||
applicationPropertiesName, getApplicationProperties());
|
||||
|
||||
Environment expectedEnv = new Environment(application, profiles, null, null,
|
||||
null);
|
||||
expectedEnv.addAll(
|
||||
Arrays.asList(applicationDefaultProperties, applicationProperties));
|
||||
|
||||
setupAwsSmClientMocks(expectedEnv);
|
||||
|
||||
Environment resultEnv = repository.findOne(application, profile, null);
|
||||
|
||||
assertThat(resultEnv).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expectedEnv);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOneWithDefaultApplicationAndNonExistingProfile() {
|
||||
String application = configServerProperties.getDefaultApplicationName();
|
||||
String profile = randomAlphabetic(RandomUtils.nextInt(3, 25));
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
|
||||
|
||||
String applicationDefaultPropertiesName = "aws:secrets:/secret/application-default/";
|
||||
PropertySource applicationDefaultProperties = new PropertySource(
|
||||
applicationDefaultPropertiesName, getApplicationDefaultProperties());
|
||||
|
||||
String applicationPropertiesName = "aws:secrets:/secret/application/";
|
||||
PropertySource applicationProperties = new PropertySource(
|
||||
applicationPropertiesName, getApplicationProperties());
|
||||
|
||||
Environment expectedEnv = new Environment(application, profiles, null, null,
|
||||
null);
|
||||
expectedEnv.addAll(
|
||||
Arrays.asList(applicationDefaultProperties, applicationProperties));
|
||||
|
||||
setupAwsSmClientMocks(expectedEnv);
|
||||
|
||||
Environment resultEnv = repository.findOne(application, profile, null);
|
||||
|
||||
assertThat(resultEnv).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expectedEnv);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOneWithDefaultApplicationAndExistingProfile() {
|
||||
String application = configServerProperties.getDefaultApplicationName();
|
||||
String profile = "prod";
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
|
||||
|
||||
String applicationProdPropertiesName = "aws:secrets:/secret/application-prod/";
|
||||
PropertySource applicationProdProperties = new PropertySource(
|
||||
applicationProdPropertiesName, getApplicationProdProperties());
|
||||
|
||||
String applicationDefaultPropertiesName = "aws:secrets:/secret/application-default/";
|
||||
PropertySource applicationDefaultProperties = new PropertySource(
|
||||
applicationDefaultPropertiesName, getApplicationDefaultProperties());
|
||||
|
||||
String applicationPropertiesName = "aws:secrets:/secret/application/";
|
||||
PropertySource applicationProperties = new PropertySource(
|
||||
applicationPropertiesName, getApplicationProperties());
|
||||
|
||||
Environment expectedEnv = new Environment(application, profiles, null, null,
|
||||
null);
|
||||
expectedEnv.addAll(Arrays.asList(applicationProdProperties,
|
||||
applicationDefaultProperties, applicationProperties));
|
||||
|
||||
setupAwsSmClientMocks(expectedEnv);
|
||||
|
||||
Environment resultEnv = repository.findOne(application, profile, null);
|
||||
|
||||
assertThat(resultEnv).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expectedEnv);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOneWithNonExistingApplicationAndNullProfile() {
|
||||
String application = randomAlphabetic(RandomUtils.nextInt(3, 25));
|
||||
String profile = null;
|
||||
String defaultProfile = configServerProperties.getDefaultProfile();
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(defaultProfile);
|
||||
|
||||
String applicationDefaultPropertiesName = "aws:secrets:/secret/application-default/";
|
||||
PropertySource applicationDefaultProperties = new PropertySource(
|
||||
applicationDefaultPropertiesName, getApplicationDefaultProperties());
|
||||
|
||||
String applicationPropertiesName = "aws:secrets:/secret/application/";
|
||||
PropertySource applicationProperties = new PropertySource(
|
||||
applicationPropertiesName, getApplicationProperties());
|
||||
|
||||
Environment expectedEnv = new Environment(application, profiles, null, null,
|
||||
null);
|
||||
expectedEnv.addAll(
|
||||
Arrays.asList(applicationDefaultProperties, applicationProperties));
|
||||
|
||||
setupAwsSmClientMocks(expectedEnv);
|
||||
|
||||
Environment resultEnv = repository.findOne(application, profile, null);
|
||||
|
||||
assertThat(resultEnv).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expectedEnv);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOneWithNonExistingApplicationAndDefaultProfile() {
|
||||
String application = randomAlphabetic(RandomUtils.nextInt(3, 25));
|
||||
String profile = configServerProperties.getDefaultProfile();
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
|
||||
|
||||
String applicationDefaultPropertiesName = "aws:secrets:/secret/application-default/";
|
||||
PropertySource applicationDefaultProperties = new PropertySource(
|
||||
applicationDefaultPropertiesName, getApplicationDefaultProperties());
|
||||
|
||||
String applicationPropertiesName = "aws:secrets:/secret/application/";
|
||||
PropertySource applicationProperties = new PropertySource(
|
||||
applicationPropertiesName, getApplicationProperties());
|
||||
|
||||
Environment expectedEnv = new Environment(application, profiles, null, null,
|
||||
null);
|
||||
expectedEnv.addAll(
|
||||
Arrays.asList(applicationDefaultProperties, applicationProperties));
|
||||
|
||||
setupAwsSmClientMocks(expectedEnv);
|
||||
|
||||
Environment resultEnv = repository.findOne(application, profile, null);
|
||||
|
||||
assertThat(resultEnv).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expectedEnv);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOneWithNonExistingApplicationAndNonExistingProfile() {
|
||||
String application = randomAlphabetic(RandomUtils.nextInt(3, 25));
|
||||
String profile = randomAlphabetic(RandomUtils.nextInt(3, 25));
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
|
||||
|
||||
String applicationDefaultPropertiesName = "aws:secrets:/secret/application-default/";
|
||||
PropertySource applicationDefaultProperties = new PropertySource(
|
||||
applicationDefaultPropertiesName, getApplicationDefaultProperties());
|
||||
|
||||
String applicationPropertiesName = "aws:secrets:/secret/application/";
|
||||
PropertySource applicationProperties = new PropertySource(
|
||||
applicationPropertiesName, getApplicationProperties());
|
||||
|
||||
Environment expectedEnv = new Environment(application, profiles, null, null,
|
||||
null);
|
||||
expectedEnv.addAll(
|
||||
Arrays.asList(applicationDefaultProperties, applicationProperties));
|
||||
|
||||
setupAwsSmClientMocks(expectedEnv);
|
||||
|
||||
Environment resultEnv = repository.findOne(application, profile, null);
|
||||
|
||||
assertThat(resultEnv).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expectedEnv);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOneWithNonExistingApplicationAndExistingProfile() {
|
||||
String application = randomAlphabetic(RandomUtils.nextInt(3, 25));
|
||||
String profile = "prod";
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
|
||||
|
||||
String applicationProdPropertiesName = "aws:secrets:/secret/application-prod/";
|
||||
PropertySource applicationProdProperties = new PropertySource(
|
||||
applicationProdPropertiesName, getApplicationProdProperties());
|
||||
|
||||
String applicationDefaultPropertiesName = "aws:secrets:/secret/application-default/";
|
||||
PropertySource applicationDefaultProperties = new PropertySource(
|
||||
applicationDefaultPropertiesName, getApplicationDefaultProperties());
|
||||
|
||||
String applicationPropertiesName = "aws:secrets:/secret/application/";
|
||||
PropertySource applicationProperties = new PropertySource(
|
||||
applicationPropertiesName, getApplicationProperties());
|
||||
|
||||
Environment expectedEnv = new Environment(application, profiles, null, null,
|
||||
null);
|
||||
expectedEnv.addAll(Arrays.asList(applicationProdProperties,
|
||||
applicationDefaultProperties, applicationProperties));
|
||||
|
||||
setupAwsSmClientMocks(expectedEnv);
|
||||
|
||||
Environment resultEnv = repository.findOne(application, profile, null);
|
||||
|
||||
assertThat(resultEnv).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expectedEnv);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOneWithExistingApplicationAndNullProfile() {
|
||||
String application = "foo";
|
||||
String profile = null;
|
||||
String defaultProfile = configServerProperties.getDefaultProfile();
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(defaultProfile);
|
||||
|
||||
String fooPropertiesName = "aws:secrets:/secret/foo/";
|
||||
PropertySource fooProperties = new PropertySource(fooPropertiesName,
|
||||
getFooProperties());
|
||||
|
||||
String fooDefaultPropertiesName = "aws:secrets:/secret/foo-default/";
|
||||
PropertySource fooDefaultProperties = new PropertySource(fooDefaultPropertiesName,
|
||||
getFooDefaultProperties());
|
||||
|
||||
String applicationDefaultPropertiesName = "aws:secrets:/secret/application-default/";
|
||||
PropertySource applicationDefaultProperties = new PropertySource(
|
||||
applicationDefaultPropertiesName, getApplicationDefaultProperties());
|
||||
|
||||
String applicationPropertiesName = "aws:secrets:/secret/application/";
|
||||
PropertySource applicationProperties = new PropertySource(
|
||||
applicationPropertiesName, getApplicationProperties());
|
||||
|
||||
Environment expectedEnv = new Environment(application, profiles, null, null,
|
||||
null);
|
||||
expectedEnv.addAll(Arrays.asList(fooDefaultProperties,
|
||||
applicationDefaultProperties, fooProperties, applicationProperties));
|
||||
|
||||
setupAwsSmClientMocks(expectedEnv);
|
||||
|
||||
Environment resultEnv = repository.findOne(application, profile, null);
|
||||
|
||||
assertThat(resultEnv).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expectedEnv);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOneWithExistingApplicationAndDefaultProfile() {
|
||||
String application = "foo";
|
||||
String profile = configServerProperties.getDefaultProfile();
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
|
||||
|
||||
String fooPropertiesName = "aws:secrets:/secret/foo/";
|
||||
PropertySource fooProperties = new PropertySource(fooPropertiesName,
|
||||
getFooProperties());
|
||||
|
||||
String fooDefaultPropertiesName = "aws:secrets:/secret/foo-default/";
|
||||
PropertySource fooDefaultProperties = new PropertySource(fooDefaultPropertiesName,
|
||||
getFooDefaultProperties());
|
||||
|
||||
String applicationDefaultPropertiesName = "aws:secrets:/secret/application-default/";
|
||||
PropertySource applicationDefaultProperties = new PropertySource(
|
||||
applicationDefaultPropertiesName, getApplicationDefaultProperties());
|
||||
|
||||
String applicationPropertiesName = "aws:secrets:/secret/application/";
|
||||
PropertySource applicationProperties = new PropertySource(
|
||||
applicationPropertiesName, getApplicationProperties());
|
||||
|
||||
Environment expectedEnv = new Environment(application, profiles, null, null,
|
||||
null);
|
||||
expectedEnv.addAll(Arrays.asList(fooDefaultProperties,
|
||||
applicationDefaultProperties, fooProperties, applicationProperties));
|
||||
|
||||
setupAwsSmClientMocks(expectedEnv);
|
||||
|
||||
Environment resultEnv = repository.findOne(application, profile, null);
|
||||
|
||||
assertThat(resultEnv).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expectedEnv);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOneWithExistingApplicationAndNonExistingProfile() {
|
||||
String application = "foo";
|
||||
String profile = randomAlphabetic(RandomUtils.nextInt(2, 25));
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
|
||||
|
||||
String fooPropertiesName = "aws:secrets:/secret/foo/";
|
||||
PropertySource fooProperties = new PropertySource(fooPropertiesName,
|
||||
getFooProperties());
|
||||
|
||||
String fooDefaultPropertiesName = "aws:secrets:/secret/foo-default/";
|
||||
PropertySource fooDefaultProperties = new PropertySource(fooDefaultPropertiesName,
|
||||
getFooDefaultProperties());
|
||||
|
||||
String applicationDefaultPropertiesName = "aws:secrets:/secret/application-default/";
|
||||
PropertySource applicationDefaultProperties = new PropertySource(
|
||||
applicationDefaultPropertiesName, getApplicationDefaultProperties());
|
||||
|
||||
String applicationPropertiesName = "aws:secrets:/secret/application/";
|
||||
PropertySource applicationProperties = new PropertySource(
|
||||
applicationPropertiesName, getApplicationProperties());
|
||||
|
||||
Environment expectedEnv = new Environment(application, profiles, null, null,
|
||||
null);
|
||||
expectedEnv.addAll(Arrays.asList(fooDefaultProperties,
|
||||
applicationDefaultProperties, fooProperties, applicationProperties));
|
||||
|
||||
setupAwsSmClientMocks(expectedEnv);
|
||||
|
||||
Environment resultEnv = repository.findOne(application, profile, null);
|
||||
|
||||
assertThat(resultEnv).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expectedEnv);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOneWithExistingApplicationAndNonExistingProfileAndNoDefaultProfile() {
|
||||
String application = "foo";
|
||||
String profile = randomAlphabetic(RandomUtils.nextInt(2, 25));
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
|
||||
|
||||
String fooPropertiesName = "aws:secrets:/secret/foo/";
|
||||
PropertySource fooProperties = new PropertySource(fooPropertiesName,
|
||||
getFooProperties());
|
||||
|
||||
String applicationPropertiesName = "aws:secrets:/secret/application/";
|
||||
PropertySource applicationProperties = new PropertySource(
|
||||
applicationPropertiesName, getApplicationProperties());
|
||||
|
||||
Environment expectedEnv = new Environment(application, profiles, null, null,
|
||||
null);
|
||||
expectedEnv.addAll(Arrays.asList(fooProperties, applicationProperties));
|
||||
|
||||
setupAwsSmClientMocks(expectedEnv);
|
||||
|
||||
Environment resultEnv = repository.findOne(application, profile, null);
|
||||
|
||||
assertThat(resultEnv).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expectedEnv);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOneWithExistingApplicationAndNonExistingProfileAndNoDefaultProfileForFoo() {
|
||||
String application = "foo";
|
||||
String profile = randomAlphabetic(RandomUtils.nextInt(2, 25));
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
|
||||
|
||||
String fooPropertiesName = "aws:secrets:/secret/foo/";
|
||||
PropertySource fooProperties = new PropertySource(fooPropertiesName,
|
||||
getFooProperties());
|
||||
|
||||
String applicationDefaultPropertiesName = "aws:secrets:/secret/application-default/";
|
||||
PropertySource applicationDefaultProperties = new PropertySource(
|
||||
applicationDefaultPropertiesName, getApplicationDefaultProperties());
|
||||
|
||||
String applicationPropertiesName = "aws:secrets:/secret/application/";
|
||||
PropertySource applicationProperties = new PropertySource(
|
||||
applicationPropertiesName, getApplicationProperties());
|
||||
|
||||
Environment expectedEnv = new Environment(application, profiles, null, null,
|
||||
null);
|
||||
expectedEnv.addAll(Arrays.asList(applicationDefaultProperties, fooProperties,
|
||||
applicationProperties));
|
||||
|
||||
setupAwsSmClientMocks(expectedEnv);
|
||||
|
||||
Environment resultEnv = repository.findOne(application, profile, null);
|
||||
|
||||
assertThat(resultEnv).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expectedEnv);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOneWithExistingApplicationAndExistingProfile() {
|
||||
String application = "foo";
|
||||
String profile = "prod";
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
|
||||
|
||||
String fooProdPropertiesName = "aws:secrets:/secret/foo-prod/";
|
||||
PropertySource fooProdProperties = new PropertySource(fooProdPropertiesName,
|
||||
getFooProdProperties());
|
||||
|
||||
String fooPropertiesName = "aws:secrets:/secret/foo/";
|
||||
PropertySource fooProperties = new PropertySource(fooPropertiesName,
|
||||
getFooProperties());
|
||||
|
||||
String fooDefaultPropertiesName = "aws:secrets:/secret/foo-default/";
|
||||
PropertySource fooDefaultProperties = new PropertySource(fooDefaultPropertiesName,
|
||||
getFooDefaultProperties());
|
||||
|
||||
String applicationProdPropertiesName = "aws:secrets:/secret/application-prod/";
|
||||
PropertySource applicationProdProperties = new PropertySource(
|
||||
applicationProdPropertiesName, getApplicationProdProperties());
|
||||
|
||||
String applicationDefaultPropertiesName = "aws:secrets:/secret/application-default/";
|
||||
PropertySource applicationDefaultProperties = new PropertySource(
|
||||
applicationDefaultPropertiesName, getApplicationDefaultProperties());
|
||||
|
||||
String applicationPropertiesName = "aws:secrets:/secret/application/";
|
||||
PropertySource applicationProperties = new PropertySource(
|
||||
applicationPropertiesName, getApplicationProperties());
|
||||
|
||||
Environment expectedEnv = new Environment(application, profiles, null, null,
|
||||
null);
|
||||
expectedEnv.addAll(Arrays.asList(fooProdProperties, applicationProdProperties,
|
||||
fooDefaultProperties, applicationDefaultProperties, fooProperties,
|
||||
applicationProperties));
|
||||
|
||||
setupAwsSmClientMocks(expectedEnv);
|
||||
|
||||
Environment resultEnv = repository.findOne(application, profile, null);
|
||||
|
||||
assertThat(resultEnv).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expectedEnv);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOneWithExistingApplicationAndExistingProfileAndNoDefaultProfiles() {
|
||||
String application = "foo";
|
||||
String profile = "prod";
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
|
||||
|
||||
String fooProdPropertiesName = "aws:secrets:/secret/foo-prod/";
|
||||
PropertySource fooProdProperties = new PropertySource(fooProdPropertiesName,
|
||||
getFooProdProperties());
|
||||
|
||||
String fooPropertiesName = "aws:secrets:/secret/foo/";
|
||||
PropertySource fooProperties = new PropertySource(fooPropertiesName,
|
||||
getFooProperties());
|
||||
|
||||
String applicationProdPropertiesName = "aws:secrets:/secret/application-prod/";
|
||||
PropertySource applicationProdProperties = new PropertySource(
|
||||
applicationProdPropertiesName, getApplicationProdProperties());
|
||||
|
||||
String applicationPropertiesName = "aws:secrets:/secret/application/";
|
||||
PropertySource applicationProperties = new PropertySource(
|
||||
applicationPropertiesName, getApplicationProperties());
|
||||
|
||||
Environment expectedEnv = new Environment(application, profiles, null, null,
|
||||
null);
|
||||
expectedEnv.addAll(Arrays.asList(fooProdProperties, applicationProdProperties,
|
||||
fooProperties, applicationProperties));
|
||||
|
||||
setupAwsSmClientMocks(expectedEnv);
|
||||
|
||||
Environment resultEnv = repository.findOne(application, profile, null);
|
||||
|
||||
assertThat(resultEnv).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expectedEnv);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOneWithExistingApplicationAndMultipleExistingProfile() {
|
||||
String application = "foo";
|
||||
String profile = "prod,east";
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
|
||||
|
||||
String fooProdPropertiesName = "aws:secrets:/secret/foo-prod/";
|
||||
PropertySource fooProdProperties = new PropertySource(fooProdPropertiesName,
|
||||
getFooProdProperties());
|
||||
|
||||
String fooEastPropertiesName = "aws:secrets:/secret/foo-east/";
|
||||
PropertySource fooEastProperties = new PropertySource(fooEastPropertiesName,
|
||||
getFooEastProperties());
|
||||
|
||||
String fooPropertiesName = "aws:secrets:/secret/foo/";
|
||||
PropertySource fooProperties = new PropertySource(fooPropertiesName,
|
||||
getFooProperties());
|
||||
|
||||
String fooDefaultPropertiesName = "aws:secrets:/secret/foo-default/";
|
||||
PropertySource fooDefaultProperties = new PropertySource(fooDefaultPropertiesName,
|
||||
getFooDefaultProperties());
|
||||
|
||||
String applicationProdPropertiesName = "aws:secrets:/secret/application-prod/";
|
||||
PropertySource applicationProdProperties = new PropertySource(
|
||||
applicationProdPropertiesName, getApplicationProdProperties());
|
||||
|
||||
String applicationDefaultPropertiesName = "aws:secrets:/secret/application-default/";
|
||||
PropertySource applicationDefaultProperties = new PropertySource(
|
||||
applicationDefaultPropertiesName, getApplicationDefaultProperties());
|
||||
|
||||
String applicationPropertiesName = "aws:secrets:/secret/application/";
|
||||
PropertySource applicationProperties = new PropertySource(
|
||||
applicationPropertiesName, getApplicationProperties());
|
||||
|
||||
String applicationEastPropertiesName = "aws:secrets:/secret/application-east/";
|
||||
PropertySource applicationEastProperties = new PropertySource(
|
||||
applicationEastPropertiesName, getApplicationEastProperties());
|
||||
|
||||
Environment expectedEnv = new Environment(application, profiles, null, null,
|
||||
null);
|
||||
expectedEnv.addAll(Arrays.asList(fooProdProperties, applicationProdProperties,
|
||||
fooEastProperties, applicationEastProperties, fooDefaultProperties,
|
||||
applicationDefaultProperties, fooProperties, applicationProperties));
|
||||
|
||||
setupAwsSmClientMocks(expectedEnv);
|
||||
|
||||
Environment resultEnv = repository.findOne(application, profile, null);
|
||||
|
||||
assertThat(resultEnv).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expectedEnv);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOneWithExistingApplicationAndMultipleExistingProfileAndNoDefaults() {
|
||||
String application = "foo";
|
||||
String profile = "prod,east";
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
|
||||
|
||||
String fooProdPropertiesName = "aws:secrets:/secret/foo-prod/";
|
||||
PropertySource fooProdProperties = new PropertySource(fooProdPropertiesName,
|
||||
getFooProdProperties());
|
||||
|
||||
String fooEastPropertiesName = "aws:secrets:/secret/foo-east/";
|
||||
PropertySource fooEastProperties = new PropertySource(fooEastPropertiesName,
|
||||
getFooEastProperties());
|
||||
|
||||
String fooPropertiesName = "aws:secrets:/secret/foo/";
|
||||
PropertySource fooProperties = new PropertySource(fooPropertiesName,
|
||||
getFooProperties());
|
||||
|
||||
String applicationProdPropertiesName = "aws:secrets:/secret/application-prod/";
|
||||
PropertySource applicationProdProperties = new PropertySource(
|
||||
applicationProdPropertiesName, getApplicationProdProperties());
|
||||
|
||||
String applicationPropertiesName = "aws:secrets:/secret/application/";
|
||||
PropertySource applicationProperties = new PropertySource(
|
||||
applicationPropertiesName, getApplicationProperties());
|
||||
|
||||
String applicationEastPropertiesName = "aws:secrets:/secret/application-east/";
|
||||
PropertySource applicationEastProperties = new PropertySource(
|
||||
applicationEastPropertiesName, getApplicationEastProperties());
|
||||
|
||||
Environment expectedEnv = new Environment(application, profiles, null, null,
|
||||
null);
|
||||
expectedEnv.addAll(Arrays.asList(fooProdProperties, applicationProdProperties,
|
||||
fooEastProperties, applicationEastProperties, fooProperties,
|
||||
applicationProperties));
|
||||
|
||||
setupAwsSmClientMocks(expectedEnv);
|
||||
|
||||
Environment resultEnv = repository.findOne(application, profile, null);
|
||||
|
||||
assertThat(resultEnv).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expectedEnv);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOneWithOverrides() {
|
||||
String application = configServerProperties.getDefaultApplicationName();
|
||||
String profile = configServerProperties.getDefaultProfile();
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
|
||||
|
||||
Map<String, String> overrides = new HashMap<String, String>(4) {
|
||||
{
|
||||
put("s3.accessKey", "override-s3");
|
||||
put("s3.secretKey", "e7437a7d-dfa0-48a4-86d6-668fc0c157a7");
|
||||
}
|
||||
};
|
||||
|
||||
configServerProperties.setOverrides(overrides);
|
||||
PropertySource overrideProperties = new PropertySource("overrides", overrides);
|
||||
|
||||
String applicationDefaultPropertiesName = "aws:secrets:/secret/application-default/";
|
||||
PropertySource applicationDefaultProperties = new PropertySource(
|
||||
applicationDefaultPropertiesName, getApplicationDefaultProperties());
|
||||
|
||||
String applicationPropertiesName = "aws:secrets:/secret/application/";
|
||||
PropertySource applicationProperties = new PropertySource(
|
||||
applicationPropertiesName, getApplicationProperties());
|
||||
|
||||
Environment expectedEnv = new Environment(application, profiles, null, null,
|
||||
null);
|
||||
expectedEnv.addAll(Arrays.asList(overrideProperties, applicationDefaultProperties,
|
||||
applicationProperties));
|
||||
|
||||
setupAwsSmClientMocks(expectedEnv);
|
||||
|
||||
Environment resultEnv = repository.findOne(application, profile, null);
|
||||
|
||||
assertThat(resultEnv).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expectedEnv);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOneWithNoSecretsStored() {
|
||||
String application = configServerProperties.getDefaultApplicationName();
|
||||
String profile = configServerProperties.getDefaultProfile();
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
|
||||
|
||||
Environment expectedEnv = new Environment(application, profiles, null, null,
|
||||
null);
|
||||
setupAwsSmClientMocks(expectedEnv);
|
||||
|
||||
Environment resultEnv = repository.findOne(application, profile, null);
|
||||
|
||||
assertThat(resultEnv).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expectedEnv);
|
||||
}
|
||||
|
||||
private void setupAwsSmClientMocks(Environment environment) {
|
||||
for (PropertySource ps : environment.getPropertySources()) {
|
||||
String path = StringUtils.delete(ps.getName(),
|
||||
environmentProperties.getOrigin());
|
||||
GetSecretValueRequest request = new GetSecretValueRequest()
|
||||
.withSecretId(path);
|
||||
|
||||
String secrets = getSecrets(ps);
|
||||
GetSecretValueResult response = new GetSecretValueResult()
|
||||
.withSecretString(secrets);
|
||||
|
||||
when(awsSmClientMock.getSecretValue(eq(request))).thenReturn(response);
|
||||
}
|
||||
}
|
||||
|
||||
private String getSecrets(PropertySource ps) {
|
||||
Map<String, String> map = (Map<String, String>) ps.getSource();
|
||||
try {
|
||||
return objectMapper.writeValueAsString(map);
|
||||
}
|
||||
catch (JsonProcessingException e) {
|
||||
log.error("Unable to generate secret string", e);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private static Map<String, String> getApplicationProperties() {
|
||||
return new HashMap<String, String>() {
|
||||
{
|
||||
put("s3.accessKey", "application-shared-s3");
|
||||
put("s3.secretKey", "25300773-eb3b-4ace-b6fc-500c87331da7");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static Map<String, String> getApplicationDefaultProperties() {
|
||||
return new HashMap<String, String>() {
|
||||
{
|
||||
put("s3.accessKey", "application-shared-default-s3");
|
||||
put("s3.secretKey", "691972aa-68d2-4e55-8d9b-eedd4c63a998");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static Map<String, String> getApplicationProdProperties() {
|
||||
return new HashMap<String, String>() {
|
||||
{
|
||||
put("s3.accessKey", "application-shared-prod-s3");
|
||||
put("s3.secretKey", "90c1dd88-5b20-41fa-a4e9-e1d638188732");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static Map<String, String> getApplicationEastProperties() {
|
||||
return new HashMap<String, String>() {
|
||||
{
|
||||
put("s3.accessKey", "application-east-s3");
|
||||
put("s3.secretKey", "236e01a7-623b-40f4-88c1-eb4d89229dd6");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static Map<String, String> getFooProperties() {
|
||||
return new HashMap<String, String>() {
|
||||
{
|
||||
put("s3.accessKey", "foo-s3");
|
||||
put("s3.secretKey", "ce945da2-740a-4915-a090-2978428dad05");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static Map<String, String> getFooDefaultProperties() {
|
||||
return new HashMap<String, String>() {
|
||||
{
|
||||
put("s3.accessKey", "foo-default-s3");
|
||||
put("s3.secretKey", "8c3c58c9-daef-4d21-96b0-c2b68a7a8234");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static Map<String, String> getFooProdProperties() {
|
||||
return new HashMap<String, String>() {
|
||||
{
|
||||
put("s3.accessKey", "foo-prod-s3");
|
||||
put("s3.secretKey", "42ca062d-8e4b-435e-9e4a-d058835817c0");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static Map<String, String> getFooEastProperties() {
|
||||
return new HashMap<String, String>() {
|
||||
{
|
||||
put("s3.accessKey", "foo-east-s3");
|
||||
put("s3.secretKey", "657f6ac5-2e1c-487d-9d61-1df109b29edf");
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user