Add support for the AWS Systems Manager Parameter Store
Fixes gh-1598 Fixes gh-850
This commit is contained in:
committed by
spencergibb
parent
64a28c476d
commit
39cb1a2104
@@ -337,7 +337,7 @@ To correct the above error the RSA key must be converted to PEM format. An examp
|
||||
Spring Cloud Config Server also supports https://docs.aws.amazon.com/codecommit/latest/userguide/welcome.html[AWS CodeCommit] authentication.
|
||||
AWS CodeCommit uses an authentication helper when using Git from the command line.
|
||||
This helper is not used with the JGit library, so a JGit CredentialProvider for AWS CodeCommit is created if the Git URI matches the AWS CodeCommit pattern.
|
||||
AWS CodeCommit URIs follow this pattern:
|
||||
AWS CodeCommit URIs follow this pattern:
|
||||
|
||||
```bash
|
||||
https//git-codecommit.${AWS_REGION}.amazonaws.com/v1/repos/${repo}.
|
||||
@@ -834,6 +834,18 @@ secret value =
|
||||
|
||||
----
|
||||
|
||||
===== AWS Parameter Store
|
||||
|
||||
When using AWS Parameter Store as a backend, you can share configuration with all applications by placing properties within the `/application` hierarchy.
|
||||
|
||||
For example, if you add parameters with the following names, all applications using the config server will have the properties `foo.bar` and `fred.baz` available to them:
|
||||
|
||||
[source]
|
||||
----
|
||||
/config/application/foo.bar
|
||||
/config/application-default/fred.baz
|
||||
----
|
||||
|
||||
==== JDBC Backend
|
||||
|
||||
Spring Cloud Config Server supports JDBC (relational database) as a backend for configuration properties.
|
||||
@@ -932,6 +944,99 @@ Configuration files are stored in your bucket as `{application}-{profile}.proper
|
||||
|
||||
NOTE: When no profile is specified `default` will be used.
|
||||
|
||||
==== AWS Parameter Store Backend
|
||||
|
||||
Spring Cloud Config Server supports AWS Parameter Store as a backend for configuration properties. You can enable this feature by adding a dependency to the link:https://github.com/aws/aws-sdk-java/tree/master/aws-java-sdk-ssm[AWS Java SDK for SSM].
|
||||
|
||||
[source,xml,indent=0]
|
||||
.pom.xml
|
||||
----
|
||||
<dependency>
|
||||
<groupId>com.amazonaws</groupId>
|
||||
<artifactId>aws-java-sdk-ssm</artifactId>
|
||||
</dependency>
|
||||
----
|
||||
|
||||
The following configuration uses the AWS SSM client to access parameters.
|
||||
|
||||
[source,yaml]
|
||||
----
|
||||
spring:
|
||||
profiles:
|
||||
active: awsparamstore
|
||||
cloud:
|
||||
config:
|
||||
server:
|
||||
awsparamstore:
|
||||
region: eu-west-2
|
||||
endpoint: https://ssm.eu-west-2.amazonaws.com
|
||||
origin: aws:parameter:
|
||||
prefix: /config/service
|
||||
profileSeparator: _
|
||||
recursive: true
|
||||
decryptValues: true
|
||||
maxResults: 5
|
||||
----
|
||||
|
||||
The following table describes the AWS Parameter Store configuration properties.
|
||||
|
||||
.AWS Parameter Store Configuration Properties
|
||||
|===
|
||||
|Property Name |Required |Default Value |Remarks
|
||||
|
||||
|*region*
|
||||
|no
|
||||
|
|
||||
|The region to be used by the AWS Parameter Store client. If it's not explicitly set, the SDK tries to determine the region to use by using the link:https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/java-dg-region-selection.html#default-region-provider-chain[Default Region Provider Chain].
|
||||
|
||||
|*endpoint*
|
||||
|no
|
||||
|
|
||||
|The URL of the entry point for the AWS SSM client. This can be used to specify an alternate endpoint for the API requests.
|
||||
|
||||
|*origin*
|
||||
|no
|
||||
|`aws:ssm:parameter:`
|
||||
|The prefix that is added to the property source's name to show their provenance.
|
||||
|
||||
|*prefix*
|
||||
|no
|
||||
|`/config`
|
||||
|Prefix indicating L1 level in the parameter hierarchy for every property loaded from the AWS Parameter Store.
|
||||
|
||||
|*profileSeparator*
|
||||
|no
|
||||
|`-`
|
||||
|String that separates an appended profile from the context name.
|
||||
|
||||
|*recursive*
|
||||
|no
|
||||
|`true`
|
||||
|Flag to indicate the retrieval of all AWS parameters within a hierarchy.
|
||||
|
||||
|*decryptValues*
|
||||
|no
|
||||
|`true`
|
||||
|Flag to indicate the retrieval of all AWS parameters with their value decrypted.
|
||||
|
||||
|*maxResults*
|
||||
|no
|
||||
|`10`
|
||||
|The maximum number of items to return for an AWS Parameter Store API call.
|
||||
|
||||
|===
|
||||
|
||||
AWS Parameter Store API credentials are determined using the link:https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/credentials.html#credentials-default[Default Credential Provider Chain].
|
||||
Versioned parameters are already supported with the default behaviour of returning the latest version.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
- When no application is specified `application` is the default, and when no profile is specified `default` is used.
|
||||
- Valid values for `awsparamstore.prefix` must start with a forward slash followed by one or more valid path segments or be empty.
|
||||
- Valid values for `awsparamstore.profileSeparator` can only contain dots, dashes and underscores.
|
||||
- Valid values for `awsparamstore.maxResults` must be within the *[1, 10]* range.
|
||||
====
|
||||
|
||||
==== 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.
|
||||
|
||||
7
pom.xml
7
pom.xml
@@ -28,7 +28,7 @@
|
||||
<properties>
|
||||
<bintray.package>config</bintray.package>
|
||||
<spring-cloud-commons.version>3.1.0-SNAPSHOT</spring-cloud-commons.version>
|
||||
<aws-java-sdk.version>1.11.903</aws-java-sdk.version>
|
||||
<aws-java-sdk.version>1.11.911</aws-java-sdk.version>
|
||||
<google-api-services-iam.version>v1-rev20201112-1.30.10</google-api-services-iam.version>
|
||||
<maven-checkstyle-plugin.failsOnError>true</maven-checkstyle-plugin.failsOnError>
|
||||
<maven-checkstyle-plugin.failsOnViolation>true
|
||||
@@ -83,6 +83,11 @@
|
||||
<artifactId>aws-java-sdk-secretsmanager</artifactId>
|
||||
<version>${aws-java-sdk.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.amazonaws</groupId>
|
||||
<artifactId>aws-java-sdk-ssm</artifactId>
|
||||
<version>${aws-java-sdk.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.apis</groupId>
|
||||
<artifactId>google-api-services-iam</artifactId>
|
||||
|
||||
@@ -104,6 +104,11 @@
|
||||
<artifactId>aws-java-sdk-secretsmanager</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.amazonaws</groupId>
|
||||
<artifactId>aws-java-sdk-ssm</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-autoconfigure-processor</artifactId>
|
||||
|
||||
@@ -23,6 +23,7 @@ import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import com.amazonaws.services.s3.AmazonS3;
|
||||
import com.amazonaws.services.secretsmanager.AWSSecretsManager;
|
||||
import com.amazonaws.services.simplesystemsmanagement.AWSSimpleSystemsManagement;
|
||||
import com.google.cloud.secretmanager.v1.SecretManagerServiceClient;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.eclipse.jgit.api.TransportConfigCallback;
|
||||
@@ -40,6 +41,9 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
|
||||
import org.springframework.cloud.config.server.composite.CompositeEnvironmentBeanFactoryPostProcessor;
|
||||
import org.springframework.cloud.config.server.composite.ConditionalOnMissingSearchPathLocator;
|
||||
import org.springframework.cloud.config.server.composite.ConditionalOnSearchPathLocator;
|
||||
import org.springframework.cloud.config.server.environment.AwsParameterStoreEnvironmentProperties;
|
||||
import org.springframework.cloud.config.server.environment.AwsParameterStoreEnvironmentRepository;
|
||||
import org.springframework.cloud.config.server.environment.AwsParameterStoreEnvironmentRepositoryFactory;
|
||||
import org.springframework.cloud.config.server.environment.AwsS3EnvironmentProperties;
|
||||
import org.springframework.cloud.config.server.environment.AwsS3EnvironmentRepository;
|
||||
import org.springframework.cloud.config.server.environment.AwsS3EnvironmentRepositoryFactory;
|
||||
@@ -106,18 +110,20 @@ import org.springframework.vault.core.VaultTemplate;
|
||||
* @author Alberto C. Ríos
|
||||
* @author Scott Frederick
|
||||
* @author Tejas Pandilwar
|
||||
* @author Iulian Antohe
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties({ SvnKitEnvironmentProperties.class, CredhubEnvironmentProperties.class,
|
||||
JdbcEnvironmentProperties.class, NativeEnvironmentProperties.class, VaultEnvironmentProperties.class,
|
||||
RedisEnvironmentProperties.class, AwsS3EnvironmentProperties.class,
|
||||
AwsSecretsManagerEnvironmentProperties.class, GoogleSecretManagerEnvironmentProperties.class })
|
||||
AwsSecretsManagerEnvironmentProperties.class, AwsParameterStoreEnvironmentProperties.class, GoogleSecretManagerEnvironmentProperties.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,
|
||||
GoogleSecretManagerRepositoryConfiguration.class, DefaultRepositoryConfiguration.class })
|
||||
AwsParameterStoreRepositoryConfiguration.class,,
|
||||
GoogleSecretManagerRepositoryConfiguration.class, DefaultRepositoryConfiguration.class })
|
||||
public class EnvironmentRepositoryConfiguration {
|
||||
|
||||
@Bean
|
||||
@@ -225,6 +231,18 @@ public class EnvironmentRepositoryConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass(AWSSimpleSystemsManagement.class)
|
||||
static class AwsParameterStoreFactoryConfig {
|
||||
|
||||
@Bean
|
||||
public AwsParameterStoreEnvironmentRepositoryFactory awsParameterStoreEnvironmentRepositoryFactory(
|
||||
ConfigServerProperties server) {
|
||||
return new AwsParameterStoreEnvironmentRepositoryFactory(server);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass(SVNException.class)
|
||||
static class SvnFactoryConfig {
|
||||
@@ -385,6 +403,20 @@ class AwsS3RepositoryConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@Profile("awsparamstore")
|
||||
class AwsParameterStoreRepositoryConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(AwsParameterStoreEnvironmentRepository.class)
|
||||
public AwsParameterStoreEnvironmentRepository awsParameterStoreEnvironmentRepository(
|
||||
AwsParameterStoreEnvironmentRepositoryFactory factory,
|
||||
AwsParameterStoreEnvironmentProperties environmentProperties) {
|
||||
return factory.build(environmentProperties);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@Profile("awssecretsmanager")
|
||||
class AwsSecretsManagerRepositoryConfiguration {
|
||||
@@ -516,8 +548,7 @@ class GoogleSecretManagerRepositoryConfiguration {
|
||||
@Bean
|
||||
public GoogleSecretManagerEnvironmentRepository googleSecretManagerEnvironmentRepository(
|
||||
GoogleSecretManagerEnvironmentRepositoryFactory factory,
|
||||
GoogleSecretManagerEnvironmentProperties environmentProperties)
|
||||
throws Exception {
|
||||
GoogleSecretManagerEnvironmentProperties environmentProperties) throws Exception {
|
||||
return factory.build(environmentProperties);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* 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.Max;
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
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;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
/**
|
||||
* @author Iulian Antohe
|
||||
*/
|
||||
@Validated
|
||||
@ConfigurationProperties("spring.cloud.config.server.awsparamstore")
|
||||
public class AwsParameterStoreEnvironmentProperties
|
||||
implements EnvironmentRepositoryProperties {
|
||||
|
||||
static final String DEFAULT_PATH_SEPARATOR = "/";
|
||||
|
||||
private static final String DEFAULT_ORIGIN = "aws:ssm:parameter:";
|
||||
|
||||
private static final String DEFAULT_PREFIX = DEFAULT_PATH_SEPARATOR + "config";
|
||||
|
||||
private static final String DEFAULT_PROFILE_SEPARATOR = "-";
|
||||
|
||||
/**
|
||||
* The order of the environment repository.
|
||||
*/
|
||||
private int order = Ordered.LOWEST_PRECEDENCE;
|
||||
|
||||
/**
|
||||
* The region to be used by the AWS Parameter Store client.
|
||||
*/
|
||||
private String region;
|
||||
|
||||
/**
|
||||
* The service endpoint to be used by the AWS Parameter Store client.
|
||||
*/
|
||||
private String endpoint;
|
||||
|
||||
/**
|
||||
* Prefix indicating the property's origin. Defaults to "aws:ssm:parameter:".
|
||||
*/
|
||||
@NotNull
|
||||
private String origin = DEFAULT_ORIGIN;
|
||||
|
||||
/**
|
||||
* Prefix indicating first level for every property loaded from the AWS Parameter
|
||||
* Store. Value must start with a forward slash followed by one or more valid path
|
||||
* segments or be empty. Defaults to "/config".
|
||||
*/
|
||||
@NotNull
|
||||
@Pattern(regexp = "(/[a-zA-Z0-9.\\-_]+)*")
|
||||
private String prefix = DEFAULT_PREFIX;
|
||||
|
||||
/**
|
||||
* String that separates an appended profile from the context name. Note that an AWS
|
||||
* parameter name can only contain dots, dashes and underscores next to alphanumeric
|
||||
* characters. Defaults to "-".
|
||||
*/
|
||||
@NotBlank
|
||||
@Pattern(regexp = "[a-zA-Z0-9.\\-_/]+")
|
||||
private String profileSeparator = DEFAULT_PROFILE_SEPARATOR;
|
||||
|
||||
/**
|
||||
* Flag to indicate the retrieval of all AWS parameters within a hierarchy. Defaults
|
||||
* to "true".
|
||||
*/
|
||||
private boolean recursive = true;
|
||||
|
||||
/**
|
||||
* Flag to indicate the retrieval of all AWS parameters in a hierarchy with their
|
||||
* value decrypted. Defaults to "true".
|
||||
*/
|
||||
private boolean decryptValues = true;
|
||||
|
||||
/**
|
||||
* The maximum number of items to return for an AWS Parameter Store API call. Defaults
|
||||
* to "10".
|
||||
*/
|
||||
@Min(1)
|
||||
@Max(10)
|
||||
private int maxResults = 10;
|
||||
|
||||
public int getOrder() {
|
||||
return order;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOrder(int order) {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
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 String getOrigin() {
|
||||
return origin;
|
||||
}
|
||||
|
||||
public void setOrigin(String origin) {
|
||||
this.origin = origin;
|
||||
}
|
||||
|
||||
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 boolean isRecursive() {
|
||||
return recursive;
|
||||
}
|
||||
|
||||
public void setRecursive(boolean recursive) {
|
||||
this.recursive = recursive;
|
||||
}
|
||||
|
||||
public boolean isDecryptValues() {
|
||||
return decryptValues;
|
||||
}
|
||||
|
||||
public void setDecryptValues(boolean decryptValues) {
|
||||
this.decryptValues = decryptValues;
|
||||
}
|
||||
|
||||
public int getMaxResults() {
|
||||
return maxResults;
|
||||
}
|
||||
|
||||
public void setMaxResults(int maxResults) {
|
||||
this.maxResults = maxResults;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.amazonaws.services.simplesystemsmanagement.AWSSimpleSystemsManagement;
|
||||
import com.amazonaws.services.simplesystemsmanagement.model.GetParametersByPathRequest;
|
||||
import com.amazonaws.services.simplesystemsmanagement.model.GetParametersByPathResult;
|
||||
import com.amazonaws.services.simplesystemsmanagement.model.Parameter;
|
||||
|
||||
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.AwsParameterStoreEnvironmentProperties.DEFAULT_PATH_SEPARATOR;
|
||||
|
||||
/**
|
||||
* @author Iulian Antohe
|
||||
*/
|
||||
public class AwsParameterStoreEnvironmentRepository implements EnvironmentRepository {
|
||||
|
||||
private final AWSSimpleSystemsManagement awsSsmClient;
|
||||
|
||||
private final ConfigServerProperties configServerProperties;
|
||||
|
||||
private final AwsParameterStoreEnvironmentProperties environmentProperties;
|
||||
|
||||
public AwsParameterStoreEnvironmentRepository(AWSSimpleSystemsManagement awsSsmClient,
|
||||
ConfigServerProperties configServerProperties,
|
||||
AwsParameterStoreEnvironmentProperties environmentProperties) {
|
||||
this.awsSsmClient = awsSsmClient;
|
||||
this.configServerProperties = configServerProperties;
|
||||
this.environmentProperties = environmentProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Environment findOne(String application, String profile, String label) {
|
||||
if (!StringUtils.hasLength(application)) {
|
||||
application = configServerProperties.getDefaultApplicationName();
|
||||
}
|
||||
|
||||
if (!StringUtils.hasLength(profile)) {
|
||||
profile = configServerProperties.getDefaultProfile();
|
||||
}
|
||||
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
|
||||
|
||||
Environment result = new Environment(application, profiles, label, null, null);
|
||||
|
||||
Set<String> paths = buildParameterPaths(application, profiles);
|
||||
List<PropertySource> propertySources = getPropertySources(paths);
|
||||
|
||||
result.addAll(propertySources);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private Set<String> buildParameterPaths(String application, String[] profiles) {
|
||||
Set<String> result = new LinkedHashSet<>();
|
||||
|
||||
String prefix = environmentProperties.getPrefix();
|
||||
String defaultApplication = configServerProperties.getDefaultApplicationName();
|
||||
String profileSeparator = environmentProperties.getProfileSeparator();
|
||||
String defaultProfile = configServerProperties.getDefaultProfile();
|
||||
|
||||
List<String> orderedProfiles = Stream
|
||||
.concat(Arrays.stream(profiles).filter(p -> !p.equals(defaultProfile)),
|
||||
Arrays.stream(new String[] { defaultProfile }))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (application.equals(defaultApplication)) {
|
||||
for (String profile : orderedProfiles) {
|
||||
result.add(prefix + DEFAULT_PATH_SEPARATOR + defaultApplication
|
||||
+ profileSeparator + profile + DEFAULT_PATH_SEPARATOR);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (String profile : orderedProfiles) {
|
||||
result.add(prefix + DEFAULT_PATH_SEPARATOR + application
|
||||
+ profileSeparator + profile + DEFAULT_PATH_SEPARATOR);
|
||||
|
||||
result.add(prefix + DEFAULT_PATH_SEPARATOR + defaultApplication
|
||||
+ profileSeparator + profile + DEFAULT_PATH_SEPARATOR);
|
||||
}
|
||||
|
||||
result.add(prefix + DEFAULT_PATH_SEPARATOR + application
|
||||
+ DEFAULT_PATH_SEPARATOR);
|
||||
}
|
||||
|
||||
result.add(prefix + DEFAULT_PATH_SEPARATOR + defaultApplication
|
||||
+ DEFAULT_PATH_SEPARATOR);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<PropertySource> getPropertySources(Set<String> parameterPaths) {
|
||||
List<PropertySource> result = new ArrayList<>();
|
||||
|
||||
for (String path : parameterPaths) {
|
||||
String name = environmentProperties.getOrigin() + path;
|
||||
Map<String, String> source = getPropertiesByParameterPath(path);
|
||||
|
||||
if (!source.isEmpty()) {
|
||||
result.add(new PropertySource(name, source));
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, String> overrides = configServerProperties.getOverrides();
|
||||
|
||||
if (!overrides.isEmpty()) {
|
||||
result.add(0, new PropertySource("overrides", overrides));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private Map<String, String> getPropertiesByParameterPath(String path) {
|
||||
Map<String, String> result = new HashMap<>();
|
||||
|
||||
GetParametersByPathRequest request = new GetParametersByPathRequest()
|
||||
.withPath(path).withRecursive(environmentProperties.isRecursive())
|
||||
.withWithDecryption(environmentProperties.isDecryptValues())
|
||||
.withMaxResults(environmentProperties.getMaxResults());
|
||||
|
||||
GetParametersByPathResult response = awsSsmClient.getParametersByPath(request);
|
||||
|
||||
if (response != null) {
|
||||
addParametersToProperties(path, response.getParameters(), result);
|
||||
|
||||
while (StringUtils.hasLength(response.getNextToken())) {
|
||||
response = awsSsmClient.getParametersByPath(request.withNextToken(response.getNextToken()));
|
||||
|
||||
addParametersToProperties(path, response.getParameters(), result);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void addParametersToProperties(String path, List<Parameter> parameters,
|
||||
Map<String, String> properties) {
|
||||
for (Parameter parameter : parameters) {
|
||||
String name = StringUtils.delete(parameter.getName(), path)
|
||||
.replace(DEFAULT_PATH_SEPARATOR, ".");
|
||||
|
||||
properties.put(name, parameter.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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.simplesystemsmanagement.AWSSimpleSystemsManagement;
|
||||
import com.amazonaws.services.simplesystemsmanagement.AWSSimpleSystemsManagementClientBuilder;
|
||||
|
||||
import org.springframework.cloud.config.server.config.ConfigServerProperties;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* @author Iulian Antohe
|
||||
*/
|
||||
public class AwsParameterStoreEnvironmentRepositoryFactory implements
|
||||
EnvironmentRepositoryFactory<AwsParameterStoreEnvironmentRepository, AwsParameterStoreEnvironmentProperties> {
|
||||
|
||||
private final ConfigServerProperties configServerProperties;
|
||||
|
||||
public AwsParameterStoreEnvironmentRepositoryFactory(
|
||||
ConfigServerProperties configServerProperties) {
|
||||
this.configServerProperties = configServerProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AwsParameterStoreEnvironmentRepository build(
|
||||
AwsParameterStoreEnvironmentProperties environmentProperties) {
|
||||
AWSSimpleSystemsManagementClientBuilder clientBuilder = AWSSimpleSystemsManagementClientBuilder
|
||||
.standard();
|
||||
|
||||
String region = environmentProperties.getRegion();
|
||||
|
||||
if (StringUtils.hasLength(region)) {
|
||||
Regions awsRegion = Regions.fromName(region);
|
||||
|
||||
clientBuilder.withRegion(awsRegion);
|
||||
|
||||
String endpoint = environmentProperties.getEndpoint();
|
||||
|
||||
if (StringUtils.hasLength(endpoint)) {
|
||||
AwsClientBuilder.EndpointConfiguration endpointConfiguration = new AwsClientBuilder.EndpointConfiguration(
|
||||
endpoint, awsRegion.getName());
|
||||
|
||||
clientBuilder.withEndpointConfiguration(endpointConfiguration);
|
||||
}
|
||||
}
|
||||
|
||||
AWSSimpleSystemsManagement client = clientBuilder.build();
|
||||
|
||||
return new AwsParameterStoreEnvironmentRepository(client, configServerProperties,
|
||||
environmentProperties);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -24,8 +24,7 @@ import org.springframework.core.Ordered;
|
||||
* @author Jose Maria Alvarez
|
||||
*/
|
||||
@ConfigurationProperties("spring.cloud.config.server.gcp-secret-manager")
|
||||
public class GoogleSecretManagerEnvironmentProperties
|
||||
implements EnvironmentRepositoryProperties {
|
||||
public class GoogleSecretManagerEnvironmentProperties implements EnvironmentRepositoryProperties {
|
||||
|
||||
private int order = Ordered.LOWEST_PRECEDENCE;
|
||||
|
||||
|
||||
@@ -49,14 +49,12 @@ public class GoogleSecretManagerEnvironmentRepository implements EnvironmentRepo
|
||||
|
||||
private GoogleConfigProvider configProvider;
|
||||
|
||||
public GoogleSecretManagerEnvironmentRepository(
|
||||
ObjectProvider<HttpServletRequest> request, RestTemplate rest,
|
||||
GoogleSecretManagerEnvironmentProperties properties) {
|
||||
public GoogleSecretManagerEnvironmentRepository(ObjectProvider<HttpServletRequest> request, RestTemplate rest,
|
||||
GoogleSecretManagerEnvironmentProperties properties) {
|
||||
this.applicationLabel = properties.getApplicationLabel();
|
||||
this.profileLabel = properties.getProfileLabel();
|
||||
this.configProvider = new HttpHeaderGoogleConfigProvider(request);
|
||||
this.accessStrategy = GoogleSecretManagerAccessStrategyFactory.forVersion(rest,
|
||||
configProvider, properties);
|
||||
this.accessStrategy = GoogleSecretManagerAccessStrategyFactory.forVersion(rest, configProvider, properties);
|
||||
this.tokenMandatory = properties.getTokenMandatory();
|
||||
}
|
||||
|
||||
@@ -72,7 +70,7 @@ public class GoogleSecretManagerEnvironmentRepository implements EnvironmentRepo
|
||||
profile = "default," + profile;
|
||||
}
|
||||
String[] profiles = org.springframework.util.StringUtils
|
||||
.trimArrayElements(org.springframework.util.StringUtils.commaDelimitedListToStringArray(profile));
|
||||
.trimArrayElements(org.springframework.util.StringUtils.commaDelimitedListToStringArray(profile));
|
||||
Environment result = new Environment(application, profile, label, null, null);
|
||||
if (tokenMandatory) {
|
||||
if (accessStrategy.checkRemotePermissions()) {
|
||||
@@ -85,13 +83,11 @@ public class GoogleSecretManagerEnvironmentRepository implements EnvironmentRepo
|
||||
return result;
|
||||
}
|
||||
|
||||
private void addPropertySource(String application, String[] profiles,
|
||||
Environment result) {
|
||||
private void addPropertySource(String application, String[] profiles, Environment result) {
|
||||
for (String profileUnit : profiles) {
|
||||
Map<?, ?> secrets = getSecrets(application, profileUnit);
|
||||
if (!secrets.isEmpty()) {
|
||||
result.add(new PropertySource("gsm:" + application + "-" + profileUnit,
|
||||
secrets));
|
||||
result.add(new PropertySource("gsm:" + application + "-" + profileUnit, secrets));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -103,23 +99,16 @@ public class GoogleSecretManagerEnvironmentRepository implements EnvironmentRepo
|
||||
*/
|
||||
private Map<?, ?> getSecrets(String application, String profile) {
|
||||
Map<String, String> result = new HashMap<>();
|
||||
String prefix = configProvider
|
||||
.getValue(HttpHeaderGoogleConfigProvider.PREFIX_HEADER, false);
|
||||
String prefix = configProvider.getValue(HttpHeaderGoogleConfigProvider.PREFIX_HEADER, false);
|
||||
for (Secret secret : accessStrategy.getSecrets()) {
|
||||
if (secret.getLabelsOrDefault(applicationLabel, "application")
|
||||
.equalsIgnoreCase(application)
|
||||
&& secret.getLabelsOrDefault(profileLabel, "profile")
|
||||
.equalsIgnoreCase(profile)) {
|
||||
result.put(accessStrategy.getSecretName(secret), accessStrategy
|
||||
.getSecretValue(secret, new GoogleSecretComparatorByVersion()));
|
||||
if (secret.getLabelsOrDefault(applicationLabel, "application").equalsIgnoreCase(application)
|
||||
&& secret.getLabelsOrDefault(profileLabel, "profile").equalsIgnoreCase(profile)) {
|
||||
result.put(accessStrategy.getSecretName(secret),
|
||||
accessStrategy.getSecretValue(secret, new GoogleSecretComparatorByVersion()));
|
||||
}
|
||||
else if (StringUtils.isNotBlank(prefix)
|
||||
&& accessStrategy.getSecretName(secret).startsWith(prefix)) {
|
||||
result.put(
|
||||
StringUtils.removeStart(accessStrategy.getSecretName(secret),
|
||||
prefix),
|
||||
accessStrategy.getSecretValue(secret,
|
||||
new GoogleSecretComparatorByVersion()));
|
||||
else if (StringUtils.isNotBlank(prefix) && accessStrategy.getSecretName(secret).startsWith(prefix)) {
|
||||
result.put(StringUtils.removeStart(accessStrategy.getSecretName(secret), prefix),
|
||||
accessStrategy.getSecretValue(secret, new GoogleSecretComparatorByVersion()));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
@@ -29,17 +29,14 @@ public class GoogleSecretManagerEnvironmentRepositoryFactory implements
|
||||
|
||||
private final ObjectProvider<HttpServletRequest> request;
|
||||
|
||||
public GoogleSecretManagerEnvironmentRepositoryFactory(
|
||||
ObjectProvider<HttpServletRequest> request) {
|
||||
public GoogleSecretManagerEnvironmentRepositoryFactory(ObjectProvider<HttpServletRequest> request) {
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GoogleSecretManagerEnvironmentRepository build(
|
||||
GoogleSecretManagerEnvironmentProperties environmentProperties)
|
||||
throws Exception {
|
||||
return new GoogleSecretManagerEnvironmentRepository(request, new RestTemplate(),
|
||||
environmentProperties);
|
||||
GoogleSecretManagerEnvironmentProperties environmentProperties) throws Exception {
|
||||
return new GoogleSecretManagerEnvironmentRepository(request, new RestTemplate(), environmentProperties);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -28,40 +28,33 @@ public final class GoogleSecretManagerAccessStrategyFactory {
|
||||
throw new IllegalStateException("Can't instantiate an utility class");
|
||||
}
|
||||
|
||||
public static GoogleSecretManagerAccessStrategy forVersion(RestTemplate rest,
|
||||
GoogleConfigProvider configProvider,
|
||||
GoogleSecretManagerEnvironmentProperties properties) {
|
||||
public static GoogleSecretManagerAccessStrategy forVersion(RestTemplate rest, GoogleConfigProvider configProvider,
|
||||
GoogleSecretManagerEnvironmentProperties properties) {
|
||||
|
||||
switch (properties.getVersion()) {
|
||||
case 1:
|
||||
try {
|
||||
return new GoogleSecretManagerV1AccessStrategy(rest, configProvider,
|
||||
properties.getServiceAccount());
|
||||
return new GoogleSecretManagerV1AccessStrategy(rest, configProvider, properties.getServiceAccount());
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RepositoryException("Cannot create service client", e);
|
||||
}
|
||||
default:
|
||||
throw new IllegalArgumentException(
|
||||
"No support for given Google Secret manager backend version "
|
||||
+ properties.getVersion());
|
||||
"No support for given Google Secret manager backend version " + properties.getVersion());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static GoogleSecretManagerAccessStrategy forVersion(RestTemplate rest,
|
||||
GoogleConfigProvider configProvider,
|
||||
GoogleSecretManagerEnvironmentProperties properties,
|
||||
SecretManagerServiceClient client) {
|
||||
public static GoogleSecretManagerAccessStrategy forVersion(RestTemplate rest, GoogleConfigProvider configProvider,
|
||||
GoogleSecretManagerEnvironmentProperties properties, SecretManagerServiceClient client) {
|
||||
|
||||
switch (properties.getVersion()) {
|
||||
case 1:
|
||||
return new GoogleSecretManagerV1AccessStrategy(rest, configProvider,
|
||||
client);
|
||||
return new GoogleSecretManagerV1AccessStrategy(rest, configProvider, client);
|
||||
default:
|
||||
throw new IllegalArgumentException(
|
||||
"No support for given Google Secret manager backend version "
|
||||
+ properties.getVersion());
|
||||
"No support for given Google Secret manager backend version " + properties.getVersion());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -55,8 +55,7 @@ import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
public class GoogleSecretManagerV1AccessStrategy
|
||||
implements GoogleSecretManagerAccessStrategy {
|
||||
public class GoogleSecretManagerV1AccessStrategy implements GoogleSecretManagerAccessStrategy {
|
||||
|
||||
private final SecretManagerServiceClient client;
|
||||
|
||||
@@ -68,19 +67,14 @@ public class GoogleSecretManagerV1AccessStrategy
|
||||
|
||||
private static final String ACCESS_SECRET_PERMISSION = "secretmanager.versions.access";
|
||||
|
||||
private static Log logger = LogFactory
|
||||
.getLog(GoogleSecretManagerV1AccessStrategy.class);
|
||||
private static Log logger = LogFactory.getLog(GoogleSecretManagerV1AccessStrategy.class);
|
||||
|
||||
public GoogleSecretManagerV1AccessStrategy(RestTemplate rest,
|
||||
GoogleConfigProvider configProvider, String serviceAccountFile)
|
||||
throws IOException {
|
||||
public GoogleSecretManagerV1AccessStrategy(RestTemplate rest, GoogleConfigProvider configProvider,
|
||||
String serviceAccountFile) throws IOException {
|
||||
if (StringUtils.isNotEmpty(serviceAccountFile)) {
|
||||
GoogleCredentials creds = GoogleCredentials
|
||||
.fromStream(new FileInputStream(new File(serviceAccountFile)));
|
||||
this.client = SecretManagerServiceClient.create(SecretManagerServiceSettings
|
||||
.newBuilder()
|
||||
.setCredentialsProvider(FixedCredentialsProvider.create(creds))
|
||||
.build());
|
||||
GoogleCredentials creds = GoogleCredentials.fromStream(new FileInputStream(new File(serviceAccountFile)));
|
||||
this.client = SecretManagerServiceClient.create(SecretManagerServiceSettings.newBuilder()
|
||||
.setCredentialsProvider(FixedCredentialsProvider.create(creds)).build());
|
||||
}
|
||||
else {
|
||||
this.client = SecretManagerServiceClient.create();
|
||||
@@ -89,8 +83,8 @@ public class GoogleSecretManagerV1AccessStrategy
|
||||
this.configProvider = configProvider;
|
||||
}
|
||||
|
||||
public GoogleSecretManagerV1AccessStrategy(RestTemplate rest,
|
||||
GoogleConfigProvider configProvider, SecretManagerServiceClient client) {
|
||||
public GoogleSecretManagerV1AccessStrategy(RestTemplate rest, GoogleConfigProvider configProvider,
|
||||
SecretManagerServiceClient client) {
|
||||
this.client = client;
|
||||
this.rest = rest;
|
||||
this.configProvider = configProvider;
|
||||
@@ -102,12 +96,11 @@ public class GoogleSecretManagerV1AccessStrategy
|
||||
ProjectName project = ProjectName.of(getProjectId());
|
||||
|
||||
// Create the request.
|
||||
ListSecretsRequest listSecretRequest = ListSecretsRequest.newBuilder()
|
||||
.setParent(project.toString()).build();
|
||||
ListSecretsRequest listSecretRequest = ListSecretsRequest.newBuilder().setParent(project.toString()).build();
|
||||
|
||||
// Get all secrets.
|
||||
SecretManagerServiceClient.ListSecretsPagedResponse pagedListSecretResponse = client
|
||||
.listSecrets(listSecretRequest);
|
||||
.listSecrets(listSecretRequest);
|
||||
|
||||
List<Secret> result = new ArrayList<Secret>();
|
||||
pagedListSecretResponse.iterateAll().forEach(result::add);
|
||||
@@ -120,12 +113,12 @@ public class GoogleSecretManagerV1AccessStrategy
|
||||
SecretName parent = SecretName.parse(secret.getName());
|
||||
|
||||
// Create the request.
|
||||
ListSecretVersionsRequest listVersionRequest = ListSecretVersionsRequest
|
||||
.newBuilder().setParent(parent.toString()).build();
|
||||
ListSecretVersionsRequest listVersionRequest = ListSecretVersionsRequest.newBuilder()
|
||||
.setParent(parent.toString()).build();
|
||||
|
||||
// Get all versions.
|
||||
SecretManagerServiceClient.ListSecretVersionsPagedResponse pagedListVersionResponse = client
|
||||
.listSecretVersions(listVersionRequest);
|
||||
.listSecretVersions(listVersionRequest);
|
||||
List<SecretVersion> result = new ArrayList<SecretVersion>();
|
||||
pagedListVersionResponse.iterateAll().forEach(result::add);
|
||||
return result;
|
||||
@@ -137,17 +130,16 @@ public class GoogleSecretManagerV1AccessStrategy
|
||||
List<SecretVersion> versions = getSecretVersions(secret);
|
||||
SecretVersion winner = null;
|
||||
for (SecretVersion secretVersion : versions) {
|
||||
if ((secretVersion.getState()
|
||||
.getNumber() == SecretVersion.State.ENABLED_VALUE)
|
||||
&& comparator.compare(secretVersion, winner) > 0) {
|
||||
if ((secretVersion.getState().getNumber() == SecretVersion.State.ENABLED_VALUE)
|
||||
&& comparator.compare(secretVersion, winner) > 0) {
|
||||
winner = secretVersion;
|
||||
}
|
||||
}
|
||||
if (winner != null) {
|
||||
SecretVersionName name = SecretVersionName.parse(winner.getName());
|
||||
// Access the secret version.
|
||||
AccessSecretVersionRequest request = AccessSecretVersionRequest.newBuilder()
|
||||
.setName(name.toString()).build();
|
||||
AccessSecretVersionRequest request = AccessSecretVersionRequest.newBuilder().setName(name.toString())
|
||||
.build();
|
||||
AccessSecretVersionResponse response = client.accessSecretVersion(request);
|
||||
result = response.getPayload().getData().toStringUtf8();
|
||||
}
|
||||
@@ -166,27 +158,22 @@ public class GoogleSecretManagerV1AccessStrategy
|
||||
try {
|
||||
AccessToken accessToken = new AccessToken(getAccessToken(), null);
|
||||
GoogleCredentials credential = new GoogleCredentials(accessToken);
|
||||
HttpRequestInitializer requestInitializer = new HttpCredentialsAdapter(
|
||||
credential);
|
||||
service = new CloudResourceManager.Builder(
|
||||
GoogleNetHttpTransport.newTrustedTransport(),
|
||||
JacksonFactory.getDefaultInstance(), requestInitializer)
|
||||
.setApplicationName(APPLICATION_NAME).build();
|
||||
HttpRequestInitializer requestInitializer = new HttpCredentialsAdapter(credential);
|
||||
service = new CloudResourceManager.Builder(GoogleNetHttpTransport.newTrustedTransport(),
|
||||
JacksonFactory.getDefaultInstance(), requestInitializer).setApplicationName(APPLICATION_NAME)
|
||||
.build();
|
||||
List<String> permissionsList = Arrays.asList(ACCESS_SECRET_PERMISSION);
|
||||
|
||||
TestIamPermissionsRequest requestBody = new TestIamPermissionsRequest()
|
||||
.setPermissions(permissionsList);
|
||||
TestIamPermissionsRequest requestBody = new TestIamPermissionsRequest().setPermissions(permissionsList);
|
||||
|
||||
TestIamPermissionsResponse testIamPermissionsResponse = service.projects()
|
||||
.testIamPermissions(getProjectId(), requestBody).execute();
|
||||
.testIamPermissions(getProjectId(), requestBody).execute();
|
||||
|
||||
if (testIamPermissionsResponse.getPermissions() != null
|
||||
&& testIamPermissionsResponse.size() >= 1) {
|
||||
if (testIamPermissionsResponse.getPermissions() != null && testIamPermissionsResponse.size() >= 1) {
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
else {
|
||||
logger.warn(
|
||||
"Access token has no permissions to access secrets in project");
|
||||
logger.warn("Access token has no permissions to access secrets in project");
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
}
|
||||
@@ -197,26 +184,22 @@ public class GoogleSecretManagerV1AccessStrategy
|
||||
}
|
||||
|
||||
private String getAccessToken() {
|
||||
return configProvider.getValue(HttpHeaderGoogleConfigProvider.ACCESS_TOKEN_HEADER,
|
||||
true);
|
||||
return configProvider.getValue(HttpHeaderGoogleConfigProvider.ACCESS_TOKEN_HEADER, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
* @return the Project Id.
|
||||
*/
|
||||
private String getProjectId() {
|
||||
String result = null;
|
||||
try {
|
||||
result = configProvider
|
||||
.getValue(HttpHeaderGoogleConfigProvider.PROJECT_ID_HEADER, true);
|
||||
result = configProvider.getValue(HttpHeaderGoogleConfigProvider.PROJECT_ID_HEADER, true);
|
||||
}
|
||||
catch (Exception e) {
|
||||
// not in GCP
|
||||
HttpEntity<String> entity = new HttpEntity<String>("parameters",
|
||||
getMetadataHttpHeaders());
|
||||
result = rest.exchange(
|
||||
GoogleSecretManagerEnvironmentProperties.GOOGLE_METADATA_PROJECT_URL,
|
||||
HttpMethod.GET, entity, String.class).getBody();
|
||||
HttpEntity<String> entity = new HttpEntity<String>("parameters", getMetadataHttpHeaders());
|
||||
result = rest.exchange(GoogleSecretManagerEnvironmentProperties.GOOGLE_METADATA_PROJECT_URL, HttpMethod.GET,
|
||||
entity, String.class).getBody();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -53,8 +53,7 @@ public class HttpHeaderGoogleConfigProvider implements GoogleConfigProvider {
|
||||
}
|
||||
String value = request.getHeader(key);
|
||||
if (!StringUtils.hasLength(value) && mandatory) {
|
||||
throw new IllegalArgumentException(
|
||||
"Missing required header in HttpServletRequest: " + key);
|
||||
throw new IllegalArgumentException("Missing required header in HttpServletRequest: " + key);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -32,6 +32,7 @@ import org.springframework.cloud.config.server.encryption.EncryptionControllerTe
|
||||
import org.springframework.cloud.config.server.encryption.EncryptionIntegrationTests;
|
||||
import org.springframework.cloud.config.server.encryption.EnvironmentPrefixHelperTests;
|
||||
import org.springframework.cloud.config.server.encryption.KeyStoreTextEncryptorLocatorTests;
|
||||
import org.springframework.cloud.config.server.environment.AwsParameterStoreEnvironmentRepositoryTests;
|
||||
import org.springframework.cloud.config.server.environment.AwsS3EnvironmentRepositoryTests;
|
||||
import org.springframework.cloud.config.server.environment.CompositeEnvironmentRepositoryTests;
|
||||
import org.springframework.cloud.config.server.environment.EnvironmentControllerIntegrationTests;
|
||||
@@ -86,7 +87,7 @@ import org.springframework.cloud.config.server.ssh.SshUriPropertyProcessorTest;
|
||||
SshPropertyValidatorTest.class, CompositeIntegrationTests.class, SubversionConfigServerIntegrationTests.class,
|
||||
ConfigServerHealthIndicatorTests.class, CustomCompositeEnvironmentRepositoryTests.class,
|
||||
CustomEnvironmentRepositoryTests.class, BootstrapConfigServerIntegrationTests.class,
|
||||
AwsS3EnvironmentRepositoryTests.class })
|
||||
AwsS3EnvironmentRepositoryTests.class, AwsParameterStoreEnvironmentRepositoryTests.class })
|
||||
@Ignore
|
||||
public class AdhocTestSuite {
|
||||
|
||||
|
||||
@@ -0,0 +1,856 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collector;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.amazonaws.services.simplesystemsmanagement.AWSSimpleSystemsManagement;
|
||||
import com.amazonaws.services.simplesystemsmanagement.model.GetParametersByPathRequest;
|
||||
import com.amazonaws.services.simplesystemsmanagement.model.GetParametersByPathResult;
|
||||
import com.amazonaws.services.simplesystemsmanagement.model.Parameter;
|
||||
import com.amazonaws.services.simplesystemsmanagement.model.ParameterType;
|
||||
import org.apache.commons.lang3.RandomUtils;
|
||||
import org.junit.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.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.cloud.config.server.environment.AwsParameterStoreEnvironmentProperties.DEFAULT_PATH_SEPARATOR;
|
||||
|
||||
/**
|
||||
* @author Iulian Antohe
|
||||
*/
|
||||
public class AwsParameterStoreEnvironmentRepositoryTests {
|
||||
|
||||
private static final Map<String, String> SHARED_PROPERTIES = new HashMap<String, String>() {
|
||||
{
|
||||
put("logging.level.root", "warn");
|
||||
put("spring.cache.redis.time-to-live", "0");
|
||||
}
|
||||
};
|
||||
|
||||
private static final Map<String, String> SHARED_DEFAULT_PROPERTIES = new HashMap<String, String>() {
|
||||
{
|
||||
put("logging.level.root", "error");
|
||||
put("spring.cache.redis.time-to-live", "1000");
|
||||
}
|
||||
};
|
||||
|
||||
private static final Map<String, String> SHARED_PRODUCTION_PROPERTIES = new HashMap<String, String>() {
|
||||
{
|
||||
put("logging.level.root", "fatal");
|
||||
put("spring.cache.redis.time-to-live", "5000");
|
||||
}
|
||||
};
|
||||
|
||||
private static final Map<String, String> APPLICATION_SPECIFIC_PROPERTIES = new HashMap<String, String>() {
|
||||
{
|
||||
put("logging.level.com.example.service", "trace");
|
||||
put("spring.cache.redis.time-to-live", "30000");
|
||||
}
|
||||
};
|
||||
|
||||
private static final Map<String, String> APPLICATION_SPECIFIC_DEFAULT_PROPERTIES = new HashMap<String, String>() {
|
||||
{
|
||||
put("logging.level.com.example.service", "debug");
|
||||
put("spring.cache.redis.time-to-live", "60000");
|
||||
}
|
||||
};
|
||||
|
||||
private static final Map<String, String> APPLICATION_SPECIFIC_PRODUCTION_PROPERTIES = new HashMap<String, String>() {
|
||||
{
|
||||
put("logging.level.com.example.service", "info");
|
||||
put("spring.cache.redis.time-to-live", "300000");
|
||||
}
|
||||
};
|
||||
|
||||
private final AWSSimpleSystemsManagement awsSsmClientMock = mock(
|
||||
AWSSimpleSystemsManagement.class, "aws-ssm-client-mock");
|
||||
|
||||
private final ConfigServerProperties configServerProperties = new ConfigServerProperties();
|
||||
|
||||
private final AwsParameterStoreEnvironmentProperties environmentProperties = new AwsParameterStoreEnvironmentProperties();
|
||||
|
||||
private final AwsParameterStoreEnvironmentRepository repository = new AwsParameterStoreEnvironmentRepository(
|
||||
awsSsmClientMock, configServerProperties, environmentProperties);
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public void testFindOneWithNullApplicationAndNullProfile() {
|
||||
// Arrange
|
||||
String application = null;
|
||||
String profile = null;
|
||||
String defaultApp = configServerProperties.getDefaultApplicationName();
|
||||
String defaultProfile = configServerProperties.getDefaultProfile();
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(defaultProfile);
|
||||
|
||||
String sharedDefaultParamsPsName = "aws:ssm:parameter:/config/application-default/";
|
||||
PropertySource sharedDefaultParamsPs = new PropertySource(
|
||||
sharedDefaultParamsPsName, SHARED_DEFAULT_PROPERTIES);
|
||||
|
||||
String sharedParamsPsName = "aws:ssm:parameter:/config/application/";
|
||||
PropertySource sharedParamsPs = new PropertySource(sharedParamsPsName,
|
||||
SHARED_PROPERTIES);
|
||||
|
||||
Environment expected = new Environment(defaultApp, profiles, null, null, null);
|
||||
expected.addAll(Arrays.asList(sharedDefaultParamsPs, sharedParamsPs));
|
||||
|
||||
setupAwsSsmClientMocks(expected);
|
||||
|
||||
// Act
|
||||
Environment result = repository.findOne(application, profile, null);
|
||||
|
||||
// Assert
|
||||
assertThat(result).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public void testFindOneWithNullApplicationAndDefaultProfile() {
|
||||
// Arrange
|
||||
String application = null;
|
||||
String profile = configServerProperties.getDefaultProfile();
|
||||
String defaultApp = configServerProperties.getDefaultApplicationName();
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
|
||||
|
||||
String sharedDefaultParamsPsName = "aws:ssm:parameter:/config/application-default/";
|
||||
PropertySource sharedDefaultParamsPs = new PropertySource(
|
||||
sharedDefaultParamsPsName, SHARED_DEFAULT_PROPERTIES);
|
||||
|
||||
String sharedParamsPsName = "aws:ssm:parameter:/config/application/";
|
||||
PropertySource sharedParamsPs = new PropertySource(sharedParamsPsName,
|
||||
SHARED_PROPERTIES);
|
||||
|
||||
Environment expected = new Environment(defaultApp, profiles, null, null, null);
|
||||
expected.addAll(Arrays.asList(sharedDefaultParamsPs, sharedParamsPs));
|
||||
|
||||
setupAwsSsmClientMocks(expected);
|
||||
|
||||
// Act
|
||||
Environment result = repository.findOne(application, profile, null);
|
||||
|
||||
// Assert
|
||||
assertThat(result).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public void testFindOneWithNullApplicationAndNonExistentProfile() {
|
||||
// Arrange
|
||||
String application = null;
|
||||
String profile = randomAlphabetic(RandomUtils.nextInt(3, 33));
|
||||
String defaultApp = configServerProperties.getDefaultApplicationName();
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
|
||||
|
||||
String name = "aws:ssm:parameter:/config/application/";
|
||||
PropertySource ps = new PropertySource(name, SHARED_PROPERTIES);
|
||||
|
||||
Environment expected = new Environment(defaultApp, profiles, null, null, null);
|
||||
expected.add(ps);
|
||||
|
||||
setupAwsSsmClientMocks(expected);
|
||||
|
||||
// Act
|
||||
Environment result = repository.findOne(application, profile, null);
|
||||
|
||||
// Assert
|
||||
assertThat(result).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public void testFindOneWithNullApplicationAndExistentProfile() {
|
||||
// Arrange
|
||||
String application = null;
|
||||
String profile = "production";
|
||||
String defaultApp = configServerProperties.getDefaultApplicationName();
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
|
||||
|
||||
String sharedProdParamsPsName = "aws:ssm:parameter:/config/application-production/";
|
||||
PropertySource sharedProdParamsPs = new PropertySource(sharedProdParamsPsName,
|
||||
SHARED_PRODUCTION_PROPERTIES);
|
||||
|
||||
String sharedParamsPsName = "aws:ssm:parameter:/config/application/";
|
||||
PropertySource sharedParamsPs = new PropertySource(sharedParamsPsName,
|
||||
SHARED_PROPERTIES);
|
||||
|
||||
Environment expected = new Environment(defaultApp, profiles, null, null, null);
|
||||
expected.addAll(Arrays.asList(sharedProdParamsPs, sharedParamsPs));
|
||||
|
||||
setupAwsSsmClientMocks(expected);
|
||||
|
||||
// Act
|
||||
Environment result = repository.findOne(application, profile, null);
|
||||
|
||||
// Assert
|
||||
assertThat(result).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public void testFindOneWithDefaultApplicationAndNullProfile() {
|
||||
// Arrange
|
||||
String application = configServerProperties.getDefaultApplicationName();
|
||||
String profile = null;
|
||||
String defaultProfile = configServerProperties.getDefaultProfile();
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(defaultProfile);
|
||||
|
||||
String sharedDefaultParamsPsName = "aws:ssm:parameter:/config/application-default/";
|
||||
PropertySource sharedDefaultParamsPs = new PropertySource(
|
||||
sharedDefaultParamsPsName, SHARED_DEFAULT_PROPERTIES);
|
||||
|
||||
String sharedParamsPsName = "aws:ssm:parameter:/config/application/";
|
||||
PropertySource sharedParamsPs = new PropertySource(sharedParamsPsName,
|
||||
SHARED_PROPERTIES);
|
||||
|
||||
Environment expected = new Environment(application, profiles, null, null, null);
|
||||
expected.addAll(Arrays.asList(sharedDefaultParamsPs, sharedParamsPs));
|
||||
|
||||
setupAwsSsmClientMocks(expected);
|
||||
|
||||
// Act
|
||||
Environment result = repository.findOne(application, profile, null);
|
||||
|
||||
// Assert
|
||||
assertThat(result).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOneWithDefaultApplicationAndDefaultProfile() {
|
||||
// Arrange
|
||||
String application = configServerProperties.getDefaultApplicationName();
|
||||
String profile = configServerProperties.getDefaultProfile();
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
|
||||
|
||||
String sharedDefaultParamsPsName = "aws:ssm:parameter:/config/application-default/";
|
||||
PropertySource sharedDefaultParamsPs = new PropertySource(
|
||||
sharedDefaultParamsPsName, SHARED_DEFAULT_PROPERTIES);
|
||||
|
||||
String sharedParamsPsName = "aws:ssm:parameter:/config/application/";
|
||||
PropertySource sharedParamsPs = new PropertySource(sharedParamsPsName,
|
||||
SHARED_PROPERTIES);
|
||||
|
||||
Environment expected = new Environment(application, profiles, null, null, null);
|
||||
expected.addAll(Arrays.asList(sharedDefaultParamsPs, sharedParamsPs));
|
||||
|
||||
setupAwsSsmClientMocks(expected);
|
||||
|
||||
// Act
|
||||
Environment result = repository.findOne(application, profile, null);
|
||||
|
||||
// Assert
|
||||
assertThat(result).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOneWithDefaultApplicationAndNonExistentProfile() {
|
||||
// Arrange
|
||||
String application = configServerProperties.getDefaultApplicationName();
|
||||
String profile = randomAlphabetic(RandomUtils.nextInt(3, 33));
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
|
||||
|
||||
String name = "aws:ssm:parameter:/config/application/";
|
||||
PropertySource ps = new PropertySource(name, SHARED_PROPERTIES);
|
||||
|
||||
Environment expected = new Environment(application, profiles, null, null, null);
|
||||
expected.add(ps);
|
||||
|
||||
setupAwsSsmClientMocks(expected);
|
||||
|
||||
// Act
|
||||
Environment result = repository.findOne(application, profile, null);
|
||||
|
||||
// Assert
|
||||
assertThat(result).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOneWithDefaultApplicationAndExistentProfile() {
|
||||
// Arrange
|
||||
String application = configServerProperties.getDefaultApplicationName();
|
||||
String profile = "production";
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
|
||||
|
||||
String sharedProdParamsPsName = "aws:ssm:parameter:/config/application-production/";
|
||||
PropertySource sharedProdParamsPs = new PropertySource(sharedProdParamsPsName,
|
||||
SHARED_PRODUCTION_PROPERTIES);
|
||||
|
||||
String sharedParamsPsName = "aws:ssm:parameter:/config/application/";
|
||||
PropertySource sharedParamsPs = new PropertySource(sharedParamsPsName,
|
||||
SHARED_PROPERTIES);
|
||||
|
||||
Environment expected = new Environment(application, profiles, null, null, null);
|
||||
expected.addAll(Arrays.asList(sharedProdParamsPs, sharedParamsPs));
|
||||
|
||||
setupAwsSsmClientMocks(expected);
|
||||
|
||||
// Act
|
||||
Environment result = repository.findOne(application, profile, null);
|
||||
|
||||
// Assert
|
||||
assertThat(result).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public void testFindOneWithNonExistentApplicationAndNullProfile() {
|
||||
// Arrange
|
||||
String application = randomAlphabetic(RandomUtils.nextInt(3, 33));
|
||||
String profile = null;
|
||||
String defaultProfile = configServerProperties.getDefaultProfile();
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(defaultProfile);
|
||||
|
||||
String sharedDefaultParamsPsName = "aws:ssm:parameter:/config/application-default/";
|
||||
PropertySource sharedDefaultParamsPs = new PropertySource(
|
||||
sharedDefaultParamsPsName, SHARED_DEFAULT_PROPERTIES);
|
||||
|
||||
String sharedParamsPsName = "aws:ssm:parameter:/config/application/";
|
||||
PropertySource sharedParamsPs = new PropertySource(sharedParamsPsName,
|
||||
SHARED_PROPERTIES);
|
||||
|
||||
Environment expected = new Environment(application, profiles, null, null, null);
|
||||
expected.addAll(Arrays.asList(sharedDefaultParamsPs, sharedParamsPs));
|
||||
|
||||
setupAwsSsmClientMocks(expected);
|
||||
|
||||
// Act
|
||||
Environment result = repository.findOne(application, profile, null);
|
||||
|
||||
// Assert
|
||||
assertThat(result).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOneWithNonExistentApplicationAndDefaultProfile() {
|
||||
// Arrange
|
||||
String application = randomAlphabetic(RandomUtils.nextInt(3, 33));
|
||||
String profile = configServerProperties.getDefaultProfile();
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
|
||||
|
||||
String sharedDefaultParamsPsName = "aws:ssm:parameter:/config/application-default/";
|
||||
PropertySource sharedDefaultParamsPs = new PropertySource(
|
||||
sharedDefaultParamsPsName, SHARED_DEFAULT_PROPERTIES);
|
||||
|
||||
String sharedParamsPsName = "aws:ssm:parameter:/config/application/";
|
||||
PropertySource sharedParamsPs = new PropertySource(sharedParamsPsName,
|
||||
SHARED_PROPERTIES);
|
||||
|
||||
Environment expected = new Environment(application, profiles, null, null, null);
|
||||
expected.addAll(Arrays.asList(sharedDefaultParamsPs, sharedParamsPs));
|
||||
|
||||
setupAwsSsmClientMocks(expected);
|
||||
|
||||
// Act
|
||||
Environment result = repository.findOne(application, profile, null);
|
||||
|
||||
// Assert
|
||||
assertThat(result).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOneWithNonExistentApplicationAndNonExistentProfile() {
|
||||
// Arrange
|
||||
String application = randomAlphabetic(RandomUtils.nextInt(3, 33));
|
||||
String profile = randomAlphabetic(RandomUtils.nextInt(3, 33));
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
|
||||
|
||||
String name = "aws:ssm:parameter:/config/application/";
|
||||
PropertySource ps = new PropertySource(name, SHARED_PROPERTIES);
|
||||
|
||||
Environment expected = new Environment(application, profiles, null, null, null);
|
||||
expected.add(ps);
|
||||
|
||||
setupAwsSsmClientMocks(expected);
|
||||
|
||||
// Act
|
||||
Environment result = repository.findOne(application, profile, null);
|
||||
|
||||
// Assert
|
||||
assertThat(result).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOneWithNonExistentApplicationAndExistentProfile() {
|
||||
// Arrange
|
||||
String application = randomAlphabetic(RandomUtils.nextInt(3, 33));
|
||||
String profile = "production";
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
|
||||
|
||||
String sharedProdParamsPsName = "aws:ssm:parameter:/config/application-production/";
|
||||
PropertySource sharedProdParamsPs = new PropertySource(sharedProdParamsPsName,
|
||||
SHARED_PRODUCTION_PROPERTIES);
|
||||
|
||||
String sharedParamsPsName = "aws:ssm:parameter:/config/application/";
|
||||
PropertySource sharedParamsPs = new PropertySource(sharedParamsPsName,
|
||||
SHARED_PROPERTIES);
|
||||
|
||||
Environment expected = new Environment(application, profiles, null, null, null);
|
||||
expected.addAll(Arrays.asList(sharedProdParamsPs, sharedParamsPs));
|
||||
|
||||
setupAwsSsmClientMocks(expected);
|
||||
|
||||
// Act
|
||||
Environment result = repository.findOne(application, profile, null);
|
||||
|
||||
// Assert
|
||||
assertThat(result).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public void testFindOneWithExistentApplicationAndNullProfile() {
|
||||
// Arrange
|
||||
String application = "service";
|
||||
String profile = null;
|
||||
String defaultProfile = configServerProperties.getDefaultProfile();
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(defaultProfile);
|
||||
|
||||
String appSpecificDefaultParamsPsName = "aws:ssm:parameter:/config/service-default/";
|
||||
PropertySource appSpecificDefaultParamsPs = new PropertySource(
|
||||
appSpecificDefaultParamsPsName, APPLICATION_SPECIFIC_DEFAULT_PROPERTIES);
|
||||
|
||||
String sharedDefaultParamsPsName = "aws:ssm:parameter:/config/application-default/";
|
||||
PropertySource sharedDefaultParamsPs = new PropertySource(
|
||||
sharedDefaultParamsPsName, SHARED_DEFAULT_PROPERTIES);
|
||||
|
||||
String appSpecificParamsPsName = "aws:ssm:parameter:/config/service/";
|
||||
PropertySource appSpecificParamsPs = new PropertySource(appSpecificParamsPsName,
|
||||
APPLICATION_SPECIFIC_PROPERTIES);
|
||||
|
||||
String sharedParamsPsName = "aws:ssm:parameter:/config/application/";
|
||||
PropertySource sharedParamsPs = new PropertySource(sharedParamsPsName,
|
||||
SHARED_PROPERTIES);
|
||||
|
||||
Environment expected = new Environment(application, profiles, null, null, null);
|
||||
|
||||
expected.addAll(Arrays.asList(appSpecificDefaultParamsPs, sharedDefaultParamsPs,
|
||||
appSpecificParamsPs, sharedParamsPs));
|
||||
|
||||
setupAwsSsmClientMocks(expected);
|
||||
|
||||
// Act
|
||||
Environment result = repository.findOne(application, profile, null);
|
||||
|
||||
// Assert
|
||||
assertThat(result).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOneWithExistentApplicationAndDefaultProfile() {
|
||||
// Arrange
|
||||
String application = "service";
|
||||
String profile = configServerProperties.getDefaultProfile();
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
|
||||
|
||||
String appSpecificDefaultParamsPsName = "aws:ssm:parameter:/config/service-default/";
|
||||
PropertySource appSpecificDefaultParamsPs = new PropertySource(
|
||||
appSpecificDefaultParamsPsName, APPLICATION_SPECIFIC_DEFAULT_PROPERTIES);
|
||||
|
||||
String sharedDefaultParamsPsName = "aws:ssm:parameter:/config/application-default/";
|
||||
PropertySource sharedDefaultParamsPs = new PropertySource(
|
||||
sharedDefaultParamsPsName, SHARED_DEFAULT_PROPERTIES);
|
||||
|
||||
String appSpecificParamsPsName = "aws:ssm:parameter:/config/service/";
|
||||
PropertySource appSpecificParamsPs = new PropertySource(appSpecificParamsPsName,
|
||||
APPLICATION_SPECIFIC_PROPERTIES);
|
||||
|
||||
String sharedParamsPsName = "aws:ssm:parameter:/config/application/";
|
||||
PropertySource sharedParamsPs = new PropertySource(sharedParamsPsName,
|
||||
SHARED_PROPERTIES);
|
||||
|
||||
Environment expected = new Environment(application, profiles, null, null, null);
|
||||
|
||||
expected.addAll(Arrays.asList(appSpecificDefaultParamsPs, sharedDefaultParamsPs,
|
||||
appSpecificParamsPs, sharedParamsPs));
|
||||
|
||||
setupAwsSsmClientMocks(expected);
|
||||
|
||||
// Act
|
||||
Environment result = repository.findOne(application, profile, null);
|
||||
|
||||
// Assert
|
||||
assertThat(result).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOneWithExistentApplicationAndNonExistentProfile() {
|
||||
// Arrange
|
||||
String application = "service";
|
||||
String profile = randomAlphabetic(RandomUtils.nextInt(3, 33));
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
|
||||
|
||||
String appSpecificParamsPsName = "aws:ssm:parameter:/config/service/";
|
||||
PropertySource appSpecificParamsPs = new PropertySource(appSpecificParamsPsName,
|
||||
APPLICATION_SPECIFIC_PROPERTIES);
|
||||
|
||||
String sharedParamsPsName = "aws:ssm:parameter:/config/application/";
|
||||
PropertySource sharedParamsPs = new PropertySource(sharedParamsPsName,
|
||||
SHARED_PROPERTIES);
|
||||
|
||||
Environment expected = new Environment(application, profiles, null, null, null);
|
||||
expected.addAll(Arrays.asList(appSpecificParamsPs, sharedParamsPs));
|
||||
|
||||
setupAwsSsmClientMocks(expected);
|
||||
|
||||
// Act
|
||||
Environment result = repository.findOne(application, profile, null);
|
||||
|
||||
// Assert
|
||||
assertThat(result).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOneWithExistentApplicationAndExistentProfile() {
|
||||
// Arrange
|
||||
String application = "service";
|
||||
String profile = "production";
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
|
||||
|
||||
String appSpecificProdParamsPsName = "aws:ssm:parameter:/config/service-production/";
|
||||
PropertySource appSpecificProdParamsPs = new PropertySource(
|
||||
appSpecificProdParamsPsName, APPLICATION_SPECIFIC_PRODUCTION_PROPERTIES);
|
||||
|
||||
String sharedProdParamsPsName = "aws:ssm:parameter:/config/application-production/";
|
||||
PropertySource sharedProdParamsPs = new PropertySource(sharedProdParamsPsName,
|
||||
SHARED_PRODUCTION_PROPERTIES);
|
||||
|
||||
String appSpecificParamsPsName = "aws:ssm:parameter:/config/service/";
|
||||
PropertySource appSpecificParamsPs = new PropertySource(appSpecificParamsPsName,
|
||||
APPLICATION_SPECIFIC_PROPERTIES);
|
||||
|
||||
String sharedParamsPsName = "aws:ssm:parameter:/config/application/";
|
||||
PropertySource sharedParamsPs = new PropertySource(sharedParamsPsName,
|
||||
SHARED_PROPERTIES);
|
||||
|
||||
Environment expected = new Environment(application, profiles, null, null, null);
|
||||
|
||||
expected.addAll(Arrays.asList(appSpecificProdParamsPs, sharedProdParamsPs,
|
||||
appSpecificParamsPs, sharedParamsPs));
|
||||
|
||||
setupAwsSsmClientMocks(expected);
|
||||
|
||||
// Act
|
||||
Environment result = repository.findOne(application, profile, null);
|
||||
|
||||
// Assert
|
||||
assertThat(result).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOneWithExistentApplicationAndMultipleExistentProfiles() {
|
||||
// Arrange
|
||||
String application = "service";
|
||||
String profile = configServerProperties.getDefaultProfile() + ",production";
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
|
||||
|
||||
String appSpecificProdParamsPsName = "aws:ssm:parameter:/config/service-production/";
|
||||
PropertySource appSpecificProdParamsPs = new PropertySource(
|
||||
appSpecificProdParamsPsName, APPLICATION_SPECIFIC_PRODUCTION_PROPERTIES);
|
||||
|
||||
String sharedProdParamsPsName = "aws:ssm:parameter:/config/application-production/";
|
||||
PropertySource sharedProdParamsPs = new PropertySource(sharedProdParamsPsName,
|
||||
SHARED_PRODUCTION_PROPERTIES);
|
||||
|
||||
String appSpecificDefaultParamsPsName = "aws:ssm:parameter:/config/service-default/";
|
||||
PropertySource appSpecificDefaultParamsPs = new PropertySource(
|
||||
appSpecificDefaultParamsPsName, APPLICATION_SPECIFIC_DEFAULT_PROPERTIES);
|
||||
|
||||
String sharedDefaultParamsPsName = "aws:ssm:parameter:/config/application-default/";
|
||||
PropertySource sharedDefaultParamsPs = new PropertySource(
|
||||
sharedDefaultParamsPsName, SHARED_DEFAULT_PROPERTIES);
|
||||
|
||||
String appSpecificParamsPsName = "aws:ssm:parameter:/config/service/";
|
||||
PropertySource appSpecificParamsPs = new PropertySource(appSpecificParamsPsName,
|
||||
APPLICATION_SPECIFIC_PROPERTIES);
|
||||
|
||||
String sharedParamsPsName = "aws:ssm:parameter:/config/application/";
|
||||
PropertySource sharedParamsPs = new PropertySource(sharedParamsPsName,
|
||||
SHARED_PROPERTIES);
|
||||
|
||||
Environment expected = new Environment(application, profiles, null, null, null);
|
||||
|
||||
expected.addAll(Arrays.asList(appSpecificProdParamsPs, sharedProdParamsPs,
|
||||
appSpecificDefaultParamsPs, sharedDefaultParamsPs, appSpecificParamsPs,
|
||||
sharedParamsPs));
|
||||
|
||||
setupAwsSsmClientMocks(expected);
|
||||
|
||||
// Act
|
||||
Environment result = repository.findOne(application, profile, null);
|
||||
|
||||
// Assert
|
||||
assertThat(result).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOneWithOverrides() {
|
||||
// Arrange
|
||||
String application = configServerProperties.getDefaultApplicationName();
|
||||
String profile = configServerProperties.getDefaultProfile();
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
|
||||
|
||||
Map<String, String> overrides = new HashMap<String, String>(4) {
|
||||
{
|
||||
put("logging.level.root", "boom");
|
||||
put("logging.level.com.example.service", "boom");
|
||||
put("spring.cache.redis.time-to-live", "-1");
|
||||
}
|
||||
};
|
||||
|
||||
configServerProperties.setOverrides(overrides);
|
||||
|
||||
PropertySource overridesPs = new PropertySource("overrides", overrides);
|
||||
|
||||
String sharedDefaultParamsPsName = "aws:ssm:parameter:/config/application-default/";
|
||||
PropertySource sharedDefaultParamsPs = new PropertySource(
|
||||
sharedDefaultParamsPsName, SHARED_DEFAULT_PROPERTIES);
|
||||
|
||||
String sharedParamsPsName = "aws:ssm:parameter:/config/application/";
|
||||
PropertySource sharedParamsPs = new PropertySource(sharedParamsPsName,
|
||||
SHARED_PROPERTIES);
|
||||
|
||||
Environment expected = new Environment(application, profiles, null, null, null);
|
||||
|
||||
expected.addAll(
|
||||
Arrays.asList(overridesPs, sharedDefaultParamsPs, sharedParamsPs));
|
||||
|
||||
setupAwsSsmClientMocks(expected);
|
||||
|
||||
// Act
|
||||
Environment result = repository.findOne(application, profile, null);
|
||||
|
||||
// Assert
|
||||
assertThat(result).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOneWithSlashesInTheParameterKeyPath() {
|
||||
// Arrange
|
||||
String application = configServerProperties.getDefaultApplicationName();
|
||||
String profile = configServerProperties.getDefaultProfile();
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
|
||||
|
||||
String sharedDefaultParamsPsName = "aws:ssm:parameter:/config/application-default/";
|
||||
PropertySource sharedDefaultParamsPs = new PropertySource(
|
||||
sharedDefaultParamsPsName, SHARED_DEFAULT_PROPERTIES);
|
||||
|
||||
String sharedParamsPsName = "aws:ssm:parameter:/config/application/";
|
||||
PropertySource sharedParamsPs = new PropertySource(sharedParamsPsName,
|
||||
SHARED_PROPERTIES);
|
||||
|
||||
Environment expected = new Environment(application, profiles, null, null, null);
|
||||
expected.addAll(Arrays.asList(sharedDefaultParamsPs, sharedParamsPs));
|
||||
|
||||
setupAwsSsmClientMocks(expected, true, false);
|
||||
|
||||
// Act
|
||||
Environment result = repository.findOne(application, profile, null);
|
||||
|
||||
// Assert
|
||||
assertThat(result).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOneWithPaginatedAwsSsmClientResponse() {
|
||||
// Arrange
|
||||
String application = configServerProperties.getDefaultApplicationName();
|
||||
String profile = configServerProperties.getDefaultProfile();
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
|
||||
|
||||
environmentProperties.setMaxResults(1);
|
||||
|
||||
String sharedDefaultParamsPsName = "aws:ssm:parameter:/config/application-default/";
|
||||
PropertySource sharedDefaultParamsPs = new PropertySource(
|
||||
sharedDefaultParamsPsName, SHARED_DEFAULT_PROPERTIES);
|
||||
|
||||
String sharedParamsPsName = "aws:ssm:parameter:/config/application/";
|
||||
PropertySource sharedParamsPs = new PropertySource(sharedParamsPsName,
|
||||
SHARED_PROPERTIES);
|
||||
|
||||
Environment expected = new Environment(application, profiles, null, null, null);
|
||||
expected.addAll(Arrays.asList(sharedDefaultParamsPs, sharedParamsPs));
|
||||
|
||||
setupAwsSsmClientMocks(expected, false, true);
|
||||
|
||||
// Act
|
||||
Environment result = repository.findOne(application, profile, null);
|
||||
|
||||
// Assert
|
||||
assertThat(result).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOneWithNoParametersInThePaths() {
|
||||
// Arrange
|
||||
String application = configServerProperties.getDefaultApplicationName();
|
||||
String profile = configServerProperties.getDefaultProfile();
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
|
||||
|
||||
Environment expected = new Environment(application, profiles, null, null, null);
|
||||
|
||||
when(awsSsmClientMock.getParametersByPath(any(GetParametersByPathRequest.class)))
|
||||
.thenReturn(new GetParametersByPathResult());
|
||||
|
||||
// Act
|
||||
Environment result = repository.findOne(application, profile, null);
|
||||
|
||||
// Assert
|
||||
assertThat(result).usingRecursiveComparison().withStrictTypeChecking()
|
||||
.isEqualTo(expected);
|
||||
}
|
||||
|
||||
private void setupAwsSsmClientMocks(Environment environment) {
|
||||
setupAwsSsmClientMocks(environment, false, false);
|
||||
}
|
||||
|
||||
private void setupAwsSsmClientMocks(Environment environment,
|
||||
boolean withSlashesForPropertyName, boolean paginatedResponse) {
|
||||
for (PropertySource ps : environment.getPropertySources()) {
|
||||
String path = StringUtils.delete(ps.getName(),
|
||||
environmentProperties.getOrigin());
|
||||
|
||||
GetParametersByPathRequest request = new GetParametersByPathRequest()
|
||||
.withPath(path).withRecursive(environmentProperties.isRecursive())
|
||||
.withWithDecryption(environmentProperties.isDecryptValues())
|
||||
.withMaxResults(environmentProperties.getMaxResults());
|
||||
|
||||
Set<Parameter> parameters = getParameters(ps, path,
|
||||
withSlashesForPropertyName);
|
||||
|
||||
GetParametersByPathResult response = new GetParametersByPathResult()
|
||||
.withParameters(parameters);
|
||||
|
||||
if (paginatedResponse
|
||||
&& environmentProperties.getMaxResults() < parameters.size()) {
|
||||
List<Set<Parameter>> chunks = splitParametersIntoChunks(parameters);
|
||||
|
||||
String nextToken = null;
|
||||
|
||||
for (int i = 0; i < chunks.size(); i++) {
|
||||
Set<Parameter> chunk = chunks.get(i);
|
||||
|
||||
if (i == 0) {
|
||||
nextToken = generateNextToken();
|
||||
|
||||
GetParametersByPathResult responseClone = response.clone()
|
||||
.withParameters(chunk).withNextToken(nextToken);
|
||||
|
||||
when(awsSsmClientMock.getParametersByPath(eq(request)))
|
||||
.thenReturn(responseClone);
|
||||
}
|
||||
else if (i == chunks.size() - 1) {
|
||||
GetParametersByPathRequest requestClone = request.clone().withNextToken(nextToken);
|
||||
GetParametersByPathResult responseClone = response.clone().withParameters(chunk);
|
||||
|
||||
when(awsSsmClientMock.getParametersByPath(eq(requestClone)))
|
||||
.thenReturn(responseClone);
|
||||
}
|
||||
else {
|
||||
String newNextToken = generateNextToken();
|
||||
|
||||
GetParametersByPathRequest requestClone = request.clone()
|
||||
.withNextToken(nextToken);
|
||||
|
||||
GetParametersByPathResult responseClone = response.clone()
|
||||
.withParameters(chunk).withNextToken(newNextToken);
|
||||
|
||||
when(awsSsmClientMock.getParametersByPath(eq(requestClone)))
|
||||
.thenReturn(responseClone);
|
||||
|
||||
nextToken = newNextToken;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
when(awsSsmClientMock.getParametersByPath(eq(request)))
|
||||
.thenReturn(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Set<Parameter> getParameters(PropertySource propertySource, String path,
|
||||
boolean withSlashesForPropertyName) {
|
||||
Function<Map.Entry<?, ?>, Parameter> mapper = p -> new Parameter()
|
||||
.withName(path + (withSlashesForPropertyName
|
||||
? ((String) p.getKey()).replace(".", DEFAULT_PATH_SEPARATOR)
|
||||
: p.getKey()))
|
||||
.withType(ParameterType.String).withValue((String) p.getValue())
|
||||
.withVersion(1L);
|
||||
|
||||
return propertySource.getSource().entrySet().stream().map(mapper)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
private List<Set<Parameter>> splitParametersIntoChunks(Set<Parameter> parameters) {
|
||||
AtomicInteger counter = new AtomicInteger();
|
||||
|
||||
Collector<Parameter, ?, Map<Integer, Set<Parameter>>> collector = Collectors
|
||||
.groupingBy(
|
||||
p -> counter.getAndIncrement()
|
||||
/ environmentProperties.getMaxResults(),
|
||||
Collectors.toSet());
|
||||
|
||||
return new ArrayList<>(parameters.stream().collect(collector).values());
|
||||
}
|
||||
|
||||
private String generateNextToken() {
|
||||
String random = randomAlphabetic(RandomUtils.nextInt(3, 33));
|
||||
|
||||
return Base64.getEncoder()
|
||||
.encodeToString(random.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -53,8 +53,8 @@ public class GoogleSecretManagerEnvironmentRepositoryTests {
|
||||
GoogleSecretManagerEnvironmentProperties properties = new GoogleSecretManagerEnvironmentProperties();
|
||||
SecretManagerServiceClient mock = mock(SecretManagerServiceClient.class);
|
||||
properties.setVersion(1);
|
||||
assertThat(GoogleSecretManagerAccessStrategyFactory.forVersion(null, null,
|
||||
properties, mock) instanceof GoogleSecretManagerV1AccessStrategy).isTrue();
|
||||
assertThat(GoogleSecretManagerAccessStrategyFactory.forVersion(null, null, properties,
|
||||
mock) instanceof GoogleSecretManagerV1AccessStrategy).isTrue();
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@@ -70,19 +70,16 @@ public class GoogleSecretManagerEnvironmentRepositoryTests {
|
||||
public void testGetSecrets() throws IOException {
|
||||
RestTemplate rest = mock(RestTemplate.class);
|
||||
GoogleConfigProvider provider = mock(HttpHeaderGoogleConfigProvider.class);
|
||||
when(provider.getValue(HttpHeaderGoogleConfigProvider.PROJECT_ID_HEADER, true))
|
||||
.thenReturn("test-project");
|
||||
when(provider.getValue(HttpHeaderGoogleConfigProvider.PROJECT_ID_HEADER, true)).thenReturn("test-project");
|
||||
SecretManagerServiceClient mock = mock(SecretManagerServiceClient.class);
|
||||
SecretManagerServiceClient.ListSecretsPagedResponse response = mock(
|
||||
SecretManagerServiceClient.ListSecretsPagedResponse.class);
|
||||
Secret secret = Secret.newBuilder().setName("projects/test-project/secrets/test")
|
||||
.build();
|
||||
Secret secret = Secret.newBuilder().setName("projects/test-project/secrets/test").build();
|
||||
List<Secret> secrets = new ArrayList<Secret>();
|
||||
secrets.add(secret);
|
||||
when(response.iterateAll()).thenReturn(secrets);
|
||||
Mockito.doReturn(response).when(mock).listSecrets(any(ListSecretsRequest.class));
|
||||
GoogleSecretManagerV1AccessStrategy strategy = new GoogleSecretManagerV1AccessStrategy(
|
||||
rest, provider, mock);
|
||||
GoogleSecretManagerV1AccessStrategy strategy = new GoogleSecretManagerV1AccessStrategy(rest, provider, mock);
|
||||
assertThat(strategy.getSecrets().size()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@@ -91,27 +88,21 @@ public class GoogleSecretManagerEnvironmentRepositoryTests {
|
||||
public void testGetSecretValues() throws IOException {
|
||||
RestTemplate rest = mock(RestTemplate.class);
|
||||
GoogleConfigProvider provider = mock(HttpHeaderGoogleConfigProvider.class);
|
||||
when(provider.getValue(HttpHeaderGoogleConfigProvider.PROJECT_ID_HEADER, true))
|
||||
.thenReturn("test-project");
|
||||
when(provider.getValue(HttpHeaderGoogleConfigProvider.PROJECT_ID_HEADER, true)).thenReturn("test-project");
|
||||
SecretManagerServiceClient mock = mock(SecretManagerServiceClient.class);
|
||||
SecretManagerServiceClient.ListSecretVersionsPagedResponse response = mock(
|
||||
SecretManagerServiceClient.ListSecretVersionsPagedResponse.class);
|
||||
SecretVersion secret1 = SecretVersion.newBuilder()
|
||||
.setName("projects/test-project/secrets/test/versions/1")
|
||||
SecretVersion secret1 = SecretVersion.newBuilder().setName("projects/test-project/secrets/test/versions/1")
|
||||
.setState(SecretVersion.State.ENABLED).build();
|
||||
SecretVersion secret2 = SecretVersion.newBuilder()
|
||||
.setName("projects/test-project/secrets/test/versions/2")
|
||||
SecretVersion secret2 = SecretVersion.newBuilder().setName("projects/test-project/secrets/test/versions/2")
|
||||
.setState(SecretVersion.State.DISABLED).build();
|
||||
List<SecretVersion> secrets = new ArrayList<SecretVersion>();
|
||||
secrets.add(secret1);
|
||||
secrets.add(secret2);
|
||||
when(response.iterateAll()).thenReturn(secrets);
|
||||
Mockito.doReturn(response).when(mock)
|
||||
.listSecretVersions(any(ListSecretVersionsRequest.class));
|
||||
GoogleSecretManagerV1AccessStrategy strategy = new GoogleSecretManagerV1AccessStrategy(
|
||||
rest, provider, mock);
|
||||
AccessSecretVersionResponse accessSecretVersionResponse = mock(
|
||||
AccessSecretVersionResponse.class);
|
||||
Mockito.doReturn(response).when(mock).listSecretVersions(any(ListSecretVersionsRequest.class));
|
||||
GoogleSecretManagerV1AccessStrategy strategy = new GoogleSecretManagerV1AccessStrategy(rest, provider, mock);
|
||||
AccessSecretVersionResponse accessSecretVersionResponse = mock(AccessSecretVersionResponse.class);
|
||||
SecretPayload payload = mock(SecretPayload.class);
|
||||
ByteString data = mock(ByteString.class);
|
||||
when(accessSecretVersionResponse.getPayload()).thenReturn(payload);
|
||||
@@ -119,19 +110,15 @@ public class GoogleSecretManagerEnvironmentRepositoryTests {
|
||||
when(data.toStringUtf8()).thenReturn("test-value");
|
||||
ArgumentMatcher<AccessSecretVersionRequest> matcher = new ArgumentMatcher<AccessSecretVersionRequest>() {
|
||||
@Override
|
||||
public boolean matches(
|
||||
AccessSecretVersionRequest accessSecretVersionRequest) {
|
||||
if (accessSecretVersionRequest.getName()
|
||||
.equals("projects/test-project/secrets/test/versions/1")) {
|
||||
public boolean matches(AccessSecretVersionRequest accessSecretVersionRequest) {
|
||||
if (accessSecretVersionRequest.getName().equals("projects/test-project/secrets/test/versions/1")) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
Mockito.doReturn(accessSecretVersionResponse).when(mock)
|
||||
.accessSecretVersion(ArgumentMatchers.argThat(matcher));
|
||||
assertThat(strategy.getSecretValue(
|
||||
Secret.newBuilder().setName("projects/test-project/secrets/test").build(),
|
||||
Mockito.doReturn(accessSecretVersionResponse).when(mock).accessSecretVersion(ArgumentMatchers.argThat(matcher));
|
||||
assertThat(strategy.getSecretValue(Secret.newBuilder().setName("projects/test-project/secrets/test").build(),
|
||||
new GoogleSecretComparatorByVersion())).isEqualTo("test-value");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user