diff --git a/docs/src/main/asciidoc/spring-cloud-config.adoc b/docs/src/main/asciidoc/spring-cloud-config.adoc index b53317280..735d364a9 100644 --- a/docs/src/main/asciidoc/spring-cloud-config.adoc +++ b/docs/src/main/asciidoc/spring-cloud-config.adoc @@ -340,17 +340,17 @@ This helper is not used with the JGit library, so a JGit CredentialProvider for AWS CodeCommit URIs follow this pattern: ```bash -https//git-codecommit.${AWS_REGION}.amazonaws.com/v1/repos/${repo}. +https://git-codecommit.${AWS_REGION}.amazonaws.com/v1/repos/${repo} ``` If you provide a username and password with an AWS CodeCommit URI, they must be the https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSGettingStartedGuide/AWSCredentials.html[AWS accessKeyId and secretAccessKey] that provide access to the repository. -If you do not specify a username and password, the accessKeyId and secretAccessKey are retrieved by using the https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/credentials.html[AWS Default Credential Provider Chain]. +If you do not specify a username and password, the accessKeyId and secretAccessKey are retrieved by using the https://docs.aws.amazon.com/sdk-for-java/v2/developer-guide/credentials.html[Default Credential Provider Chain]. If your Git URI matches the CodeCommit URI pattern (shown earlier), you must provide valid AWS credentials in the username and password or in one of the locations supported by the default credential provider chain. AWS EC2 instances may use https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html[IAM Roles for EC2 Instances]. -NOTE: The `aws-java-sdk-core` jar is an optional dependency. -If the `aws-java-sdk-core` jar is not on your classpath, the AWS Code Commit credential provider is not created, regardless of the git server URI. +NOTE: The `software.amazon.awssdk:auth` jar is an optional dependency. +If the `software.amazon.awssdk:auth` jar is not on your classpath, the AWS Code Commit credential provider is not created, regardless of the git server URI. ===== Authentication with Google Cloud Source @@ -940,15 +940,15 @@ NOTE: When no profile is specified `default` will be used. ==== AWS S3 Backend Spring Cloud Config Server supports AWS S3 as a backend for configuration properties. -You can enable this feature by adding a dependency to the link:https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/examples-s3.html[AWS Java SDK For Amazon S3]. +You can enable this feature by adding a dependency to the link:https://docs.aws.amazon.com/sdk-for-java/v2/developer-guide/examples-s3.html[AWS Java SDK For Amazon S3]. [source,xml,indent=0] .pom.xml ---- - com.amazonaws - aws-java-sdk-s3 + software.amazon.awssdk + s3 ---- @@ -970,7 +970,7 @@ spring: It is also possible to specify an AWS URL to link:https://aws.amazon.com/blogs/developer/using-new-regions-and-endpoints/[override the standard endpoint] of your S3 service with `spring.cloud.config.server.awss3.endpoint`. This allows support for beta regions of S3, and other S3 compatible storage APIs. -Credentials are found using the link:https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/credentials.html[Default AWS Credential Provider Chain]. Versioned and encrypted buckets are supported without further configuration. +Credentials are found using the link:https://docs.aws.amazon.com/sdk-for-java/v2/developer-guide/credentials.html[Default Credential Provider Chain]. Versioned and encrypted buckets are supported without further configuration. Configuration files are stored in your bucket as `{application}-{profile}.properties`, `{application}-{profile}.yml` or `{application}-{profile}.json`. An optional label can be provided to specify a directory path to the file. @@ -978,14 +978,14 @@ 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]. +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://docs.aws.amazon.com/sdk-for-java/v2/developer-guide/examples-ssm.html[AWS Java SDK for SSM]. [source,xml,indent=0] .pom.xml ---- - com.amazonaws - aws-java-sdk-ssm + software.amazon.awssdk + ssm ---- @@ -1019,7 +1019,7 @@ The following table describes the AWS Parameter Store configuration properties. |*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]. +|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/v2/developer-guide/region-selection.html#default-region-provider-chain[Default Region Provider Chain]. |*endpoint* |no @@ -1058,7 +1058,7 @@ The following table describes the AWS Parameter Store configuration properties. |=== -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]. +AWS Parameter Store API credentials are determined using the link:https://docs.aws.amazon.com/sdk-for-java/v2/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] @@ -1072,14 +1072,14 @@ Versioned parameters are already supported with the default behaviour of returni ==== 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]. +You can enable this feature by adding a dependency to link:https://docs.aws.amazon.com/sdk-for-java/v2/developer-guide/examples-secretsmanager.html[AWS Java SDK for Secrets Manager]. [source,xml,indent=0] .pom.xml ---- - com.amazonaws - aws-java-sdk-secretsmanager + software.amazon.awssdk + secretsmanager ---- @@ -1102,7 +1102,7 @@ spring: ---- -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]. +AWS Secrets Manager API credentials are determined using link:https://docs.aws.amazon.com/sdk-for-java/v2/developer-guide/credentials.html#credentials-default[Default Credential Provider Chain]. [NOTE] ==== diff --git a/pom.xml b/pom.xml index 173f0a777..d78c7e99b 100644 --- a/pom.xml +++ b/pom.xml @@ -28,9 +28,10 @@ config 4.0.0-SNAPSHOT - 1.11.911 + 2.17.195 v1-rev20201112-1.30.10 1.16.2 + 1.12.220 2.31.0 true true @@ -71,23 +72,23 @@ ${spring-cloud-commons.version} - com.amazonaws - aws-java-sdk-core + software.amazon.awssdk + auth ${aws-java-sdk.version} - com.amazonaws - aws-java-sdk-s3 + software.amazon.awssdk + s3 ${aws-java-sdk.version} - com.amazonaws - aws-java-sdk-secretsmanager + software.amazon.awssdk + secretsmanager ${aws-java-sdk.version} - com.amazonaws - aws-java-sdk-ssm + software.amazon.awssdk + ssm ${aws-java-sdk.version} @@ -116,8 +117,13 @@ ${testcontainers.version} pom import - - + + + com.amazonaws + aws-java-sdk-core + ${aws-java-sdk-v1.version} + + com.github.tomakehurst wiremock-jre8 ${wiremock.version} diff --git a/spring-cloud-config-dependencies/pom.xml b/spring-cloud-config-dependencies/pom.xml index 7527edf82..1dce92968 100644 --- a/spring-cloud-config-dependencies/pom.xml +++ b/spring-cloud-config-dependencies/pom.xml @@ -16,7 +16,7 @@ Spring Cloud Config Dependencies 5.12.0.202106070339-r - 2.3.2 + 3.0.0-M1 2.1.1.RELEASE diff --git a/spring-cloud-config-sample/src/test/java/sample/ConfigDataOrderingVaultIntegrationTests.java b/spring-cloud-config-sample/src/test/java/sample/ConfigDataOrderingVaultIntegrationTests.java index 5a44345b2..46fafcfb1 100644 --- a/spring-cloud-config-sample/src/test/java/sample/ConfigDataOrderingVaultIntegrationTests.java +++ b/spring-cloud-config-sample/src/test/java/sample/ConfigDataOrderingVaultIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2022 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. @@ -21,6 +21,7 @@ import org.json.JSONException; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.testcontainers.containers.BindMode; import org.testcontainers.junit.jupiter.Container; @@ -42,6 +43,7 @@ * vaultordering/client-dev.yml */ @Testcontainers +@Tag("DockerRequired") public class ConfigDataOrderingVaultIntegrationTests { private static final int configServerPort = TestSocketUtils.findAvailableTcpPort(); diff --git a/spring-cloud-config-server/pom.xml b/spring-cloud-config-server/pom.xml index 63564e62b..2cf69b950 100644 --- a/spring-cloud-config-server/pom.xml +++ b/spring-cloud-config-server/pom.xml @@ -94,23 +94,23 @@ true - com.amazonaws - aws-java-sdk-core + software.amazon.awssdk + auth true - com.amazonaws - aws-java-sdk-s3 + software.amazon.awssdk + s3 true - com.amazonaws - aws-java-sdk-secretsmanager + software.amazon.awssdk + secretsmanager true - com.amazonaws - aws-java-sdk-ssm + software.amazon.awssdk + ssm true @@ -168,6 +168,16 @@ junit-jupiter test + + org.testcontainers + localstack + test + + + com.amazonaws + aws-java-sdk-core + test + com.github.tomakehurst wiremock-jre8 diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/config/EnvironmentRepositoryConfiguration.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/config/EnvironmentRepositoryConfiguration.java index 57cee54e6..7dc63d527 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/config/EnvironmentRepositoryConfiguration.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/config/EnvironmentRepositoryConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2022 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. @@ -19,14 +19,14 @@ import java.util.List; import java.util.Optional; -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 jakarta.servlet.http.HttpServletRequest; import org.apache.http.client.HttpClient; import org.eclipse.jgit.api.TransportConfigCallback; import org.tmatesoft.svn.core.SVNException; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; +import software.amazon.awssdk.services.ssm.SsmClient; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.actuate.health.AbstractHealthIndicator; @@ -210,7 +210,7 @@ public ConfigurableHttpConnectionFactory httpClientConnectionFactory() { } @Configuration(proxyBeanMethods = false) - @ConditionalOnClass(AmazonS3.class) + @ConditionalOnClass(S3Client.class) static class AwsS3FactoryConfig { @Bean @@ -221,7 +221,7 @@ public AwsS3EnvironmentRepositoryFactory awsS3EnvironmentRepositoryFactory(Confi } @Configuration(proxyBeanMethods = false) - @ConditionalOnClass(AWSSecretsManager.class) + @ConditionalOnClass(SecretsManagerClient.class) static class AwsSecretsManagerFactoryConfig { @Bean @@ -233,7 +233,7 @@ public AwsSecretsManagerEnvironmentRepositoryFactory awsSecretsManagerEnvironmen } @Configuration(proxyBeanMethods = false) - @ConditionalOnClass(AWSSimpleSystemsManagement.class) + @ConditionalOnClass(SsmClient.class) static class AwsParameterStoreFactoryConfig { @Bean diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsClientBuilderConfigurer.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsClientBuilderConfigurer.java index 46b4f4a0c..b47931bd7 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsClientBuilderConfigurer.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsClientBuilderConfigurer.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2022 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. @@ -16,8 +16,10 @@ package org.springframework.cloud.config.server.environment; -import com.amazonaws.client.builder.AwsClientBuilder; -import com.amazonaws.client.builder.AwsSyncClientBuilder; +import java.net.URI; + +import software.amazon.awssdk.awscore.client.builder.AwsClientBuilder; +import software.amazon.awssdk.regions.Region; import org.springframework.util.StringUtils; @@ -26,15 +28,11 @@ abstract class AwsClientBuilderConfigurer { private AwsClientBuilderConfigurer() { } - static void configureClientBuilder(AwsSyncClientBuilder clientBuilder, String region, String endpoint) { + static void configureClientBuilder(AwsClientBuilder clientBuilder, String region, String endpoint) { if (StringUtils.hasText(region)) { + clientBuilder.region(Region.of(region)); if (StringUtils.hasText(endpoint)) { - AwsClientBuilder.EndpointConfiguration endpointConfiguration = new AwsClientBuilder.EndpointConfiguration( - endpoint, region); - clientBuilder.withEndpointConfiguration(endpointConfiguration); - } - else { - clientBuilder.withRegion(region); + clientBuilder.endpointOverride(URI.create(endpoint)); } } } diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsParameterStoreEnvironmentRepository.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsParameterStoreEnvironmentRepository.java index 5bb5f0824..1b9532b63 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsParameterStoreEnvironmentRepository.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsParameterStoreEnvironmentRepository.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2022 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. @@ -26,10 +26,10 @@ 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 software.amazon.awssdk.services.ssm.SsmClient; +import software.amazon.awssdk.services.ssm.model.GetParametersByPathRequest; +import software.amazon.awssdk.services.ssm.model.GetParametersByPathResponse; +import software.amazon.awssdk.services.ssm.model.Parameter; import org.springframework.cloud.config.environment.Environment; import org.springframework.cloud.config.environment.PropertySource; @@ -43,14 +43,13 @@ */ public class AwsParameterStoreEnvironmentRepository implements EnvironmentRepository { - private final AWSSimpleSystemsManagement awsSsmClient; + private final SsmClient awsSsmClient; private final ConfigServerProperties configServerProperties; private final AwsParameterStoreEnvironmentProperties environmentProperties; - public AwsParameterStoreEnvironmentRepository(AWSSimpleSystemsManagement awsSsmClient, - ConfigServerProperties configServerProperties, + public AwsParameterStoreEnvironmentRepository(SsmClient awsSsmClient, ConfigServerProperties configServerProperties, AwsParameterStoreEnvironmentProperties environmentProperties) { this.awsSsmClient = awsSsmClient; this.configServerProperties = configServerProperties; @@ -137,20 +136,20 @@ private List getPropertySources(Set parameterPaths) { private Map getPropertiesByParameterPath(String path) { Map result = new HashMap<>(); - GetParametersByPathRequest request = new GetParametersByPathRequest().withPath(path) - .withRecursive(environmentProperties.isRecursive()) - .withWithDecryption(environmentProperties.isDecryptValues()) - .withMaxResults(environmentProperties.getMaxResults()); + GetParametersByPathRequest request = GetParametersByPathRequest.builder().path(path) + .recursive(environmentProperties.isRecursive()).withDecryption(environmentProperties.isDecryptValues()) + .maxResults(environmentProperties.getMaxResults()).build(); - GetParametersByPathResult response = awsSsmClient.getParametersByPath(request); + GetParametersByPathResponse response = awsSsmClient.getParametersByPath(request); if (response != null) { - addParametersToProperties(path, response.getParameters(), result); + addParametersToProperties(path, response.parameters(), result); - while (StringUtils.hasLength(response.getNextToken())) { - response = awsSsmClient.getParametersByPath(request.withNextToken(response.getNextToken())); + while (StringUtils.hasLength(response.nextToken())) { + response = awsSsmClient + .getParametersByPath(request.toBuilder().nextToken(response.nextToken()).build()); - addParametersToProperties(path, response.getParameters(), result); + addParametersToProperties(path, response.parameters(), result); } } @@ -159,9 +158,9 @@ private Map getPropertiesByParameterPath(String path) { private void addParametersToProperties(String path, List parameters, Map properties) { for (Parameter parameter : parameters) { - String name = StringUtils.delete(parameter.getName(), path).replace(DEFAULT_PATH_SEPARATOR, "."); + String name = StringUtils.delete(parameter.name(), path).replace(DEFAULT_PATH_SEPARATOR, "."); - properties.put(name, parameter.getValue()); + properties.put(name, parameter.value()); } } diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsParameterStoreEnvironmentRepositoryFactory.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsParameterStoreEnvironmentRepositoryFactory.java index 37117d170..ad0d37554 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsParameterStoreEnvironmentRepositoryFactory.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsParameterStoreEnvironmentRepositoryFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2022 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. @@ -16,8 +16,8 @@ package org.springframework.cloud.config.server.environment; -import com.amazonaws.services.simplesystemsmanagement.AWSSimpleSystemsManagement; -import com.amazonaws.services.simplesystemsmanagement.AWSSimpleSystemsManagementClientBuilder; +import software.amazon.awssdk.services.ssm.SsmClient; +import software.amazon.awssdk.services.ssm.SsmClientBuilder; import org.springframework.cloud.config.server.config.ConfigServerProperties; @@ -37,11 +37,11 @@ public AwsParameterStoreEnvironmentRepositoryFactory(ConfigServerProperties conf @Override public AwsParameterStoreEnvironmentRepository build(AwsParameterStoreEnvironmentProperties environmentProperties) { - AWSSimpleSystemsManagementClientBuilder clientBuilder = AWSSimpleSystemsManagementClientBuilder.standard(); + SsmClientBuilder clientBuilder = SsmClient.builder(); configureClientBuilder(clientBuilder, environmentProperties.getRegion(), environmentProperties.getEndpoint()); - AWSSimpleSystemsManagement client = clientBuilder.build(); + SsmClient client = clientBuilder.build(); return new AwsParameterStoreEnvironmentRepository(client, configServerProperties, environmentProperties); } diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsS3EnvironmentRepository.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsS3EnvironmentRepository.java index b3a528311..eb0a5dad0 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsS3EnvironmentRepository.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsS3EnvironmentRepository.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2022 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. @@ -20,10 +20,10 @@ import java.io.InputStream; import java.util.Properties; -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.model.GetObjectRequest; -import com.amazonaws.services.s3.model.S3Object; -import com.amazonaws.services.s3.model.S3ObjectIdBuilder; +import software.amazon.awssdk.core.ResponseInputStream; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.model.GetObjectRequest; +import software.amazon.awssdk.services.s3.model.GetObjectResponse; import org.springframework.beans.factory.config.YamlPropertiesFactoryBean; import org.springframework.cloud.config.environment.Environment; @@ -31,6 +31,7 @@ import org.springframework.cloud.config.server.config.ConfigServerProperties; import org.springframework.core.Ordered; import org.springframework.core.io.InputStreamResource; +import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; /** @@ -43,7 +44,7 @@ public class AwsS3EnvironmentRepository implements EnvironmentRepository, Ordere private static final String PATH_SEPARATOR = "/"; - private final AmazonS3 s3Client; + private final S3Client s3Client; private final String bucketName; @@ -51,7 +52,7 @@ public class AwsS3EnvironmentRepository implements EnvironmentRepository, Ordere protected int order = Ordered.LOWEST_PRECEDENCE; - public AwsS3EnvironmentRepository(AmazonS3 s3Client, String bucketName, ConfigServerProperties server) { + public AwsS3EnvironmentRepository(S3Client s3Client, String bucketName, ConfigServerProperties server) { this.s3Client = s3Client; this.bucketName = bucketName; this.serverProperties = server; @@ -68,11 +69,11 @@ public void setOrder(int order) { @Override public Environment findOne(String specifiedApplication, String specifiedProfiles, String specifiedLabel) { - final String application = StringUtils.isEmpty(specifiedApplication) + final String application = ObjectUtils.isEmpty(specifiedApplication) ? serverProperties.getDefaultApplicationName() : specifiedApplication; - final String profiles = StringUtils.isEmpty(specifiedProfiles) ? serverProperties.getDefaultProfile() + final String profiles = ObjectUtils.isEmpty(specifiedProfiles) ? serverProperties.getDefaultProfile() : specifiedProfiles; - final String label = StringUtils.isEmpty(specifiedLabel) ? serverProperties.getDefaultLabel() : specifiedLabel; + final String label = ObjectUtils.isEmpty(specifiedLabel) ? serverProperties.getDefaultLabel() : specifiedLabel; String[] profileArray = parseProfiles(profiles); String[] apps = new String[] { application }; @@ -113,41 +114,40 @@ private String[] parseProfiles(String profiles) { private S3ConfigFile getS3ConfigFile(String application, String profile, String label) { String objectKeyPrefix = buildObjectKeyPrefix(application, profile, label); - final S3ObjectIdBuilder s3ObjectIdBuilder = new S3ObjectIdBuilder().withBucket(bucketName); + final GetObjectRequest.Builder requestBuilder = GetObjectRequest.builder().bucket(bucketName); - return getS3ConfigFile(s3ObjectIdBuilder, objectKeyPrefix); + return getS3ConfigFile(requestBuilder, objectKeyPrefix); } private String buildObjectKeyPrefix(String application, String profile, String label) { StringBuilder objectKeyPrefix = new StringBuilder(); - if (!StringUtils.isEmpty(label)) { + if (StringUtils.hasLength(label)) { objectKeyPrefix.append(label).append(PATH_SEPARATOR); } objectKeyPrefix.append(application); - if (!StringUtils.isEmpty(profile)) { + if (StringUtils.hasLength(profile)) { objectKeyPrefix.append("-").append(profile); } return objectKeyPrefix.toString(); } - private S3ConfigFile getS3ConfigFile(S3ObjectIdBuilder s3ObjectIdBuilder, String keyPrefix) { + private S3ConfigFile getS3ConfigFile(GetObjectRequest.Builder requestBuilder, String keyPrefix) { try { - final S3Object properties = s3Client - .getObject(new GetObjectRequest(s3ObjectIdBuilder.withKey(keyPrefix + ".properties").build())); - return new PropertyS3ConfigFile(properties.getObjectMetadata().getVersionId(), - properties.getObjectContent()); + ResponseInputStream inputStream = s3Client + .getObject(requestBuilder.key(keyPrefix + ".properties").build()); + return new PropertyS3ConfigFile(inputStream.response().versionId(), inputStream); } catch (Exception eProperties) { try { - final S3Object yaml = s3Client - .getObject(new GetObjectRequest(s3ObjectIdBuilder.withKey(keyPrefix + ".yml").build())); - return new YamlS3ConfigFile(yaml.getObjectMetadata().getVersionId(), yaml.getObjectContent()); + ResponseInputStream inputStream = s3Client + .getObject(requestBuilder.key(keyPrefix + ".yml").build()); + return new YamlS3ConfigFile(inputStream.response().versionId(), inputStream); } catch (Exception eYaml) { try { - final S3Object json = s3Client - .getObject(new GetObjectRequest(s3ObjectIdBuilder.withKey(keyPrefix + ".json").build())); - return new JsonS3ConfigFile(json.getObjectMetadata().getVersionId(), json.getObjectContent()); + ResponseInputStream inputStream = s3Client + .getObject(requestBuilder.key(keyPrefix + ".json").build()); + return new JsonS3ConfigFile(inputStream.response().versionId(), inputStream); } catch (Exception eJson) { return null; diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsS3EnvironmentRepositoryFactory.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsS3EnvironmentRepositoryFactory.java index c79be96ac..e7efee3bd 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsS3EnvironmentRepositoryFactory.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsS3EnvironmentRepositoryFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2022 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. @@ -16,8 +16,8 @@ package org.springframework.cloud.config.server.environment; -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.AmazonS3ClientBuilder; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.S3ClientBuilder; import org.springframework.cloud.config.server.config.ConfigServerProperties; @@ -34,9 +34,9 @@ public AwsS3EnvironmentRepositoryFactory(ConfigServerProperties server) { @Override public AwsS3EnvironmentRepository build(AwsS3EnvironmentProperties environmentProperties) { - final AmazonS3ClientBuilder clientBuilder = AmazonS3ClientBuilder.standard(); + final S3ClientBuilder clientBuilder = S3Client.builder(); configureClientBuilder(clientBuilder, environmentProperties.getRegion(), environmentProperties.getEndpoint()); - final AmazonS3 client = clientBuilder.build(); + final S3Client client = clientBuilder.build(); AwsS3EnvironmentRepository repository = new AwsS3EnvironmentRepository(client, environmentProperties.getBucket(), server); diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsSecretsManagerEnvironmentRepository.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsSecretsManagerEnvironmentRepository.java index 02b9a626f..ef243c1d3 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsSecretsManagerEnvironmentRepository.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsSecretsManagerEnvironmentRepository.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2022 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. @@ -21,19 +21,20 @@ 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 software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; +import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest; +import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueResponse; +import software.amazon.awssdk.services.secretsmanager.model.ResourceNotFoundException; 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.core.Ordered; +import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; import static org.springframework.cloud.config.server.environment.AwsSecretsManagerEnvironmentProperties.DEFAULT_PATH_SEPARATOR; @@ -48,7 +49,7 @@ public class AwsSecretsManagerEnvironmentRepository implements EnvironmentReposi private final ObjectMapper objectMapper; - private final AWSSecretsManager awsSmClient; + private final SecretsManagerClient awsSmClient; private final ConfigServerProperties configServerProperties; @@ -56,7 +57,7 @@ public class AwsSecretsManagerEnvironmentRepository implements EnvironmentReposi private final int order; - public AwsSecretsManagerEnvironmentRepository(AWSSecretsManager awsSmClient, + public AwsSecretsManagerEnvironmentRepository(SecretsManagerClient awsSmClient, ConfigServerProperties configServerProperties, AwsSecretsManagerEnvironmentProperties environmentProperties) { this.awsSmClient = awsSmClient; @@ -71,11 +72,11 @@ public Environment findOne(String application, String profileList, String label) final String defaultApplication = configServerProperties.getDefaultApplicationName(); final String defaultProfile = configServerProperties.getDefaultProfile(); - if (StringUtils.isEmpty(application)) { + if (ObjectUtils.isEmpty(application)) { application = defaultApplication; } - if (StringUtils.isEmpty(profileList)) { + if (ObjectUtils.isEmpty(profileList)) { profileList = defaultProfile; } @@ -135,18 +136,15 @@ private String buildPath(String application, String profile) { private Map findProperties(String path) { Map properties = new HashMap<>(); - GetSecretValueRequest request = new GetSecretValueRequest().withSecretId(path); + GetSecretValueRequest request = GetSecretValueRequest.builder().secretId(path).build(); try { - GetSecretValueResult response = awsSmClient.getSecretValue(request); + GetSecretValueResponse response = awsSmClient.getSecretValue(request); if (response != null) { - Map secretMap = objectMapper.readValue(response.getSecretString(), - new TypeReference>() { - }); + Map secretMap = objectMapper.readValue(response.secretString(), new TypeReference<>() { + }); - for (Map.Entry secretEntry : secretMap.entrySet()) { - properties.put(secretEntry.getKey(), secretEntry.getValue()); - } + properties.putAll(secretMap); } } catch (ResourceNotFoundException | IOException e) { diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsSecretsManagerEnvironmentRepositoryFactory.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsSecretsManagerEnvironmentRepositoryFactory.java index ce7ecad1c..51728f877 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsSecretsManagerEnvironmentRepositoryFactory.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsSecretsManagerEnvironmentRepositoryFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2022 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. @@ -16,8 +16,8 @@ package org.springframework.cloud.config.server.environment; -import com.amazonaws.services.secretsmanager.AWSSecretsManager; -import com.amazonaws.services.secretsmanager.AWSSecretsManagerClientBuilder; +import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; +import software.amazon.awssdk.services.secretsmanager.SecretsManagerClientBuilder; import org.springframework.cloud.config.server.config.ConfigServerProperties; @@ -37,11 +37,11 @@ public AwsSecretsManagerEnvironmentRepositoryFactory(ConfigServerProperties conf @Override public AwsSecretsManagerEnvironmentRepository build(AwsSecretsManagerEnvironmentProperties environmentProperties) { - AWSSecretsManagerClientBuilder clientBuilder = AWSSecretsManagerClientBuilder.standard(); + SecretsManagerClientBuilder clientBuilder = SecretsManagerClient.builder(); configureClientBuilder(clientBuilder, environmentProperties.getRegion(), environmentProperties.getEndpoint()); - AWSSecretsManager client = clientBuilder.build(); + SecretsManagerClient client = clientBuilder.build(); return new AwsSecretsManagerEnvironmentRepository(client, configServerProperties, environmentProperties); } diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/vault/authentication/AwsIamClientAuthenticationProvider.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/vault/authentication/AwsIamClientAuthenticationProvider.java index 7f9d987b7..a6d7f5286 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/vault/authentication/AwsIamClientAuthenticationProvider.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/vault/authentication/AwsIamClientAuthenticationProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2022 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. @@ -18,9 +18,9 @@ import java.util.concurrent.atomic.AtomicReference; -import com.amazonaws.auth.AWSCredentials; -import com.amazonaws.auth.AWSCredentialsProvider; -import com.amazonaws.auth.DefaultAWSCredentialsProviderChain; +import software.amazon.awssdk.auth.credentials.AwsCredentials; +import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; +import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; import org.springframework.cloud.config.server.environment.VaultEnvironmentProperties; import org.springframework.cloud.config.server.environment.VaultEnvironmentProperties.AuthenticationMethod; @@ -41,12 +41,12 @@ public AwsIamClientAuthenticationProvider() { public ClientAuthentication getClientAuthentication(VaultEnvironmentProperties vaultProperties, RestOperations vaultRestOperations, RestOperations externalRestOperations) { - assertClassPresent("com.amazonaws.auth.AWSCredentials", - missingClassForAuthMethod("AWSCredentials", "aws-java-sdk-core", AuthenticationMethod.AWS_IAM)); + assertClassPresent("software.amazon.awssdk.auth.credentials.AwsCredentials", missingClassForAuthMethod( + "AwsCredentials", "software.amazon.awssdk:auth", AuthenticationMethod.AWS_IAM)); VaultEnvironmentProperties.AwsIamProperties awsIam = vaultProperties.getAwsIam(); - AWSCredentialsProvider credentialsProvider = AwsCredentialProvider.getAwsCredentialsProvider(); + AwsCredentialsProvider credentialsProvider = AwsCredentialProvider.getAwsCredentialsProvider(); AwsIamAuthenticationOptions.AwsIamAuthenticationOptionsBuilder builder = AwsIamAuthenticationOptions.builder(); @@ -72,32 +72,20 @@ public ClientAuthentication getClientAuthentication(VaultEnvironmentProperties v private static class AwsCredentialProvider { - private static AWSCredentialsProvider getAwsCredentialsProvider() { + private static AwsCredentialsProvider getAwsCredentialsProvider() { - DefaultAWSCredentialsProviderChain backingCredentialsProvider = DefaultAWSCredentialsProviderChain - .getInstance(); + AwsCredentialsProvider backingCredentialsProvider = DefaultCredentialsProvider.create(); // Eagerly fetch credentials preventing lag during the first, actual login. - AWSCredentials firstAccess = backingCredentialsProvider.getCredentials(); + AwsCredentials firstAccess = backingCredentialsProvider.resolveCredentials(); - AtomicReference once = new AtomicReference<>(firstAccess); + AtomicReference once = new AtomicReference<>(firstAccess); - return new AWSCredentialsProvider() { - - @Override - public AWSCredentials getCredentials() { - - if (once.compareAndSet(firstAccess, null)) { - return firstAccess; - } - - return backingCredentialsProvider.getCredentials(); - } - - @Override - public void refresh() { - backingCredentialsProvider.refresh(); + return () -> { + if (once.compareAndSet(firstAccess, null)) { + return firstAccess; } + return backingCredentialsProvider.resolveCredentials(); }; } diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/support/AwsCodeCommitCredentialProvider.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/support/AwsCodeCommitCredentialProvider.java index 88b972ed2..1606216c0 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/support/AwsCodeCommitCredentialProvider.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/support/AwsCodeCommitCredentialProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2022 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. @@ -27,18 +27,18 @@ import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; -import com.amazonaws.auth.AWSCredentials; -import com.amazonaws.auth.AWSCredentialsProvider; -import com.amazonaws.auth.AWSSessionCredentials; -import com.amazonaws.auth.BasicAWSCredentials; -import com.amazonaws.auth.DefaultAWSCredentialsProviderChain; -import com.amazonaws.util.ValidationUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.eclipse.jgit.errors.UnsupportedCredentialItem; import org.eclipse.jgit.transport.CredentialItem; import org.eclipse.jgit.transport.CredentialsProvider; import org.eclipse.jgit.transport.URIish; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.AwsCredentials; +import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; +import software.amazon.awssdk.auth.credentials.AwsSessionCredentials; +import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; import static org.springframework.util.StringUtils.hasText; @@ -76,20 +76,20 @@ public class AwsCodeCommitCredentialProvider extends CredentialsProvider { protected Log logger = LogFactory.getLog(getClass()); /** - * The AWSCredentialsProvider will be used to provide the access key and secret key if + * The AwsCredentialsProvider will be used to provide the access key and secret key if * they are not specified. */ - private AWSCredentialsProvider awsCredentialProvider; + private AwsCredentialsProvider awsCredentialProvider; /** - * If the access and secret keys are provided, then the AWSCredentialsProvider will - * not be used. The username is the awsAccessKeyId. + * If the access and secret keys are provided, then the AwsCredentialsProvider will + * not be used. The username is the accessKeyId. */ private String username; /** - * If the access and secret keys are provided, then the AWSCredentialsProvider will - * not be used. The password is the awsSecretKey. + * If the access and secret keys are provided, then the AwsCredentialsProvider will + * not be used. The password is the secretAccessKey. */ private String password; @@ -98,10 +98,10 @@ public class AwsCodeCommitCredentialProvider extends CredentialsProvider { * uses the algorithm published by AWS at * https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html * @param uri the codecommit repository uri - * @param awsSecretKey the aws secret key + * @param secretAccessKey the secret access key * @return the password to use in the git request */ - protected static String calculateCodeCommitPassword(URIish uri, String awsSecretKey) { + protected static String calculateCodeCommitPassword(URIish uri, String secretAccessKey) { String[] split = uri.getHost().split("\\."); if (split.length < 4) { throw new CredentialException("Cannot detect AWS region from URI", null); @@ -122,7 +122,7 @@ protected static String calculateCodeCommitPassword(URIish uri, String awsSecret .append(region).append("/codecommit/aws4_request\n") .append(bytesToHexString(canonicalRequestDigest(uri))); - byte[] signedRequest = sign(awsSecretKey, shortDateStamp, region, stringToSign.toString()); + byte[] signedRequest = sign(secretAccessKey, shortDateStamp, region, stringToSign.toString()); codeCommitPassword = dateStamp + "Z" + bytesToHexString(signedRequest); } catch (Exception e) { @@ -250,25 +250,25 @@ else if (i instanceof CredentialItem.Password) { } /** - * Get the AWSCredentials. If an AWSCredentialProvider was specified, use that, - * otherwise, create a new AWSCredentialsProvider. If the username and password are - * provided, then use those directly as AWSCredentials. Otherwise us the - * {@link DefaultAWSCredentialsProviderChain} as is standard with AWS applications. + * Get the AwsCredentials. If an AwsCredentialProvider was specified, use that, + * otherwise, create a new AwsCredentialsProvider. If the username and password are + * provided, then use those directly as AwsCredentials. Otherwise, use the + * {@link DefaultCredentialsProvider} as is standard with AWS applications. * @return the AWS credentials. */ - private AWSCredentials retrieveAwsCredentials() { + private AwsCredentials retrieveAwsCredentials() { if (this.awsCredentialProvider == null) { if (this.username != null && this.password != null) { - this.logger.debug("Creating a static AWSCredentialsProvider"); - this.awsCredentialProvider = new AWSStaticCredentialsProvider( - new BasicAWSCredentials(this.username, this.password)); + this.logger.debug("Creating a StaticCredentialsProvider"); + this.awsCredentialProvider = StaticCredentialsProvider + .create(AwsBasicCredentials.create(this.username, this.password)); } else { - this.logger.debug("Creating a default AWSCredentialsProvider"); - this.awsCredentialProvider = new DefaultAWSCredentialsProviderChain(); + this.logger.debug("Creating a DefaultCredentialsProvider"); + this.awsCredentialProvider = DefaultCredentialsProvider.create(); } } - return this.awsCredentialProvider.getCredentials(); + return this.awsCredentialProvider.resolveCredentials(); } /** @@ -280,16 +280,15 @@ private AWSCredentials retrieveAwsCredentials() { public boolean get(URIish uri, CredentialItem... items) throws UnsupportedCredentialItem { String codeCommitPassword; String awsAccessKey; - String awsSecretKey; + String secretAccessKey; try { - AWSCredentials awsCredentials = retrieveAwsCredentials(); + AwsCredentials awsCredentials = retrieveAwsCredentials(); StringBuilder awsKey = new StringBuilder(); - awsKey.append(awsCredentials.getAWSAccessKeyId()); - awsSecretKey = awsCredentials.getAWSSecretKey(); - if (awsCredentials instanceof AWSSessionCredentials) { - AWSSessionCredentials sessionCreds = (AWSSessionCredentials) awsCredentials; - if (sessionCreds.getSessionToken() != null) { - awsKey.append('%').append(sessionCreds.getSessionToken()); + awsKey.append(awsCredentials.accessKeyId()); + secretAccessKey = awsCredentials.secretAccessKey(); + if (awsCredentials instanceof AwsSessionCredentials sessionCreds) { + if (sessionCreds.sessionToken() != null) { + awsKey.append('%').append(sessionCreds.sessionToken()); } } awsAccessKey = awsKey.toString(); @@ -299,7 +298,7 @@ public boolean get(URIish uri, CredentialItem... items) throws UnsupportedCreden return false; } try { - codeCommitPassword = calculateCodeCommitPassword(uri, awsSecretKey); + codeCommitPassword = calculateCodeCommitPassword(uri, secretAccessKey); } catch (Throwable t) { this.logger.warn("Error calculating the AWS CodeCommit password", t); @@ -336,22 +335,22 @@ public boolean get(URIish uri, CredentialItem... items) throws UnsupportedCreden public void reset(URIish uri) { // Should throw out cached info. // Note that even though the credentials (password) we calculate here is - // valid for 15 minutes, we do not cache it. Instead we just re-calculate - // it each time we need it. However, the AWSCredentialProvider will cache - // its AWSCredentials object. + // valid for 15 minutes, we do not cache it. Instead, we just re-calculate + // it each time we need it. However, the AwsCredentialProvider will cache + // its AwsCredentials object. } /** * @return the awsCredentialProvider */ - public AWSCredentialsProvider getAwsCredentialProvider() { + public AwsCredentialsProvider getAwsCredentialProvider() { return this.awsCredentialProvider; } /** * @param awsCredentialProvider the awsCredentialProvider to set */ - public void setAwsCredentialProvider(AWSCredentialsProvider awsCredentialProvider) { + public void setAwsCredentialProvider(AwsCredentialsProvider awsCredentialProvider) { this.awsCredentialProvider = awsCredentialProvider; } @@ -383,26 +382,4 @@ public void setPassword(String password) { this.password = password; } - /** - * Simple implementation of AWSCredentialsProvider that just wraps static - * AWSCredentials. AWS Actually provides this class in newer versions of the AWS API. - */ - public class AWSStaticCredentialsProvider implements AWSCredentialsProvider { - - private final AWSCredentials credentials; - - public AWSStaticCredentialsProvider(AWSCredentials credentials) { - this.credentials = ValidationUtils.assertNotNull(credentials, "credentials"); - } - - public AWSCredentials getCredentials() { - return this.credentials; - } - - public void refresh() { - // Nothing to do for static credentials. - } - - } - } diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/support/GitCredentialsProviderFactory.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/support/GitCredentialsProviderFactory.java index dd7ea30b5..18ff444c3 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/support/GitCredentialsProviderFactory.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/support/GitCredentialsProviderFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2022 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. @@ -118,12 +118,13 @@ else if (hasText(passphrase)) { /** * Check to see if the AWS Authentication API is available. - * @return true if the com.amazonaws.auth.DefaultAWSCredentialsProviderChain is - * present, false otherwise. + * @return true if the + * software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider is present, + * false otherwise. */ private boolean awsAvailable() { return this.awsCodeCommitEnabled - && ClassUtils.isPresent("com.amazonaws.auth.DefaultAWSCredentialsProviderChain", null); + && ClassUtils.isPresent("software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider", null); } /** diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/credentials/AwsCodeCommitCredentialsProviderTests.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/credentials/AwsCodeCommitCredentialsProviderTests.java index 6828bf649..13a5d720d 100644 --- a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/credentials/AwsCodeCommitCredentialsProviderTests.java +++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/credentials/AwsCodeCommitCredentialsProviderTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2022 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. @@ -18,12 +18,13 @@ import java.net.URISyntaxException; -import com.amazonaws.auth.AWSCredentialsProvider; import org.eclipse.jgit.errors.UnsupportedCredentialItem; import org.eclipse.jgit.transport.CredentialItem; import org.eclipse.jgit.transport.URIish; import org.junit.Before; import org.junit.Test; +import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; import org.springframework.cloud.config.server.support.AwsCodeCommitCredentialProvider; import org.springframework.cloud.config.server.support.GitCredentialsProviderFactory; @@ -97,18 +98,18 @@ public void testNotSupportsOther() { @Test public void testAwsCredentialsProviderIsNullInitially() { - AWSCredentialsProvider awsProvider = this.provider.getAwsCredentialProvider(); + AwsCredentialsProvider awsProvider = this.provider.getAwsCredentialProvider(); assertThat(awsProvider).isNull(); } @Test public void testAwsCredentialsProviderIsDefinedAfterGet() throws URISyntaxException { - AWSCredentialsProvider awsProvider = this.provider.getAwsCredentialProvider(); + AwsCredentialsProvider awsProvider = this.provider.getAwsCredentialProvider(); assertThat(awsProvider).isNull(); assertThat(this.provider.get(new URIish(AWS_REPO), makeCredentialItems())).isTrue(); awsProvider = this.provider.getAwsCredentialProvider(); assertThat(awsProvider).isNotNull(); - assertThat(awsProvider instanceof AwsCodeCommitCredentialProvider.AWSStaticCredentialsProvider).isTrue(); + assertThat(awsProvider).isInstanceOf(StaticCredentialsProvider.class); } @Test diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/AwsParameterStoreEnvironmentRepositoryIntegrationTests.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/AwsParameterStoreEnvironmentRepositoryIntegrationTests.java new file mode 100644 index 000000000..812b57d32 --- /dev/null +++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/AwsParameterStoreEnvironmentRepositoryIntegrationTests.java @@ -0,0 +1,64 @@ +/* + * Copyright 2022-2022 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 org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.testcontainers.containers.localstack.LocalStackContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.utility.DockerImageName; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.ssm.SsmClient; + +import org.springframework.cloud.config.environment.Environment; +import org.springframework.cloud.config.server.config.ConfigServerProperties; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.testcontainers.containers.localstack.LocalStackContainer.Service.SSM; +import static software.amazon.awssdk.services.ssm.model.ParameterType.STRING; + +/** + * @author Henning Pöttker + */ +@Testcontainers +@Tag("DockerRequired") +class AwsParameterStoreEnvironmentRepositoryIntegrationTests { + + @Container + static LocalStackContainer localStack = new LocalStackContainer( + DockerImageName.parse("localstack/localstack:0.14.3.1")).withServices(SSM); + + @Test + void test() { + SsmClient ssmClient = SsmClient.builder().region(Region.of(localStack.getRegion())) + .endpointOverride(localStack.getEndpointOverride(SSM)) + .credentialsProvider(StaticCredentialsProvider + .create(AwsBasicCredentials.create(localStack.getAccessKey(), localStack.getSecretKey()))) + .build(); + ssmClient.putParameter((builder) -> builder.name("/config/foo-bar/tag").value("myapp").type(STRING)); + + Environment env = new AwsParameterStoreEnvironmentRepository(ssmClient, new ConfigServerProperties(), + new AwsParameterStoreEnvironmentProperties()).findOne("foo", "bar", ""); + assertThat(env.getName()).isEqualTo("foo"); + assertThat(env.getPropertySources()).hasSize(1); + assertThat(env.getPropertySources().get(0).getSource().get("tag")).isEqualTo("myapp"); + } + +} diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/AwsParameterStoreEnvironmentRepositoryTests.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/AwsParameterStoreEnvironmentRepositoryTests.java index f6bf2dda7..b4e3170f5 100644 --- a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/AwsParameterStoreEnvironmentRepositoryTests.java +++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/AwsParameterStoreEnvironmentRepositoryTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2022 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. @@ -29,13 +29,13 @@ 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 software.amazon.awssdk.services.ssm.SsmClient; +import software.amazon.awssdk.services.ssm.model.GetParametersByPathRequest; +import software.amazon.awssdk.services.ssm.model.GetParametersByPathResponse; +import software.amazon.awssdk.services.ssm.model.Parameter; +import software.amazon.awssdk.services.ssm.model.ParameterType; import org.springframework.cloud.config.environment.Environment; import org.springframework.cloud.config.environment.PropertySource; @@ -97,8 +97,7 @@ public class AwsParameterStoreEnvironmentRepositoryTests { } }; - private final AWSSimpleSystemsManagement awsSsmClientMock = mock(AWSSimpleSystemsManagement.class, - "aws-ssm-client-mock"); + private final SsmClient awsSsmClientMock = mock(SsmClient.class, "aws-ssm-client-mock"); private final ConfigServerProperties configServerProperties = new ConfigServerProperties(); @@ -686,7 +685,7 @@ public void testFindOneWithNoParametersInThePaths() { Environment expected = new Environment(application, profiles, null, null, null); when(awsSsmClientMock.getParametersByPath(any(GetParametersByPathRequest.class))) - .thenReturn(new GetParametersByPathResult()); + .thenReturn(GetParametersByPathResponse.builder().build()); // Act Environment result = repository.findOne(application, profile, null); @@ -725,14 +724,14 @@ private void setupAwsSsmClientMocks(Environment environment, boolean withSlashes 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()); + GetParametersByPathRequest request = GetParametersByPathRequest.builder().path(path) + .recursive(environmentProperties.isRecursive()) + .withDecryption(environmentProperties.isDecryptValues()) + .maxResults(environmentProperties.getMaxResults()).build(); Set parameters = getParameters(ps, path, withSlashesForPropertyName); - GetParametersByPathResult response = new GetParametersByPathResult().withParameters(parameters); + GetParametersByPathResponse response = GetParametersByPathResponse.builder().parameters(parameters).build(); if (paginatedResponse && environmentProperties.getMaxResults() < parameters.size()) { List> chunks = splitParametersIntoChunks(parameters); @@ -745,24 +744,24 @@ private void setupAwsSsmClientMocks(Environment environment, boolean withSlashes if (i == 0) { nextToken = generateNextToken(); - GetParametersByPathResult responseClone = response.clone().withParameters(chunk) - .withNextToken(nextToken); + GetParametersByPathResponse responseClone = response.toBuilder().parameters(chunk) + .nextToken(nextToken).build(); 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); + GetParametersByPathRequest requestClone = request.toBuilder().nextToken(nextToken).build(); + GetParametersByPathResponse responseClone = response.toBuilder().parameters(chunk).build(); when(awsSsmClientMock.getParametersByPath(eq(requestClone))).thenReturn(responseClone); } else { String newNextToken = generateNextToken(); - GetParametersByPathRequest requestClone = request.clone().withNextToken(nextToken); + GetParametersByPathRequest requestClone = request.toBuilder().nextToken(nextToken).build(); - GetParametersByPathResult responseClone = response.clone().withParameters(chunk) - .withNextToken(newNextToken); + GetParametersByPathResponse responseClone = response.toBuilder().parameters(chunk) + .nextToken(newNextToken).build(); when(awsSsmClientMock.getParametersByPath(eq(requestClone))).thenReturn(responseClone); @@ -778,10 +777,10 @@ else if (i == chunks.size() - 1) { private Set getParameters(PropertySource propertySource, String path, boolean withSlashesForPropertyName) { - Function, Parameter> mapper = p -> new Parameter() - .withName(path + (withSlashesForPropertyName + Function, Parameter> mapper = p -> Parameter + .builder().name(path + (withSlashesForPropertyName ? ((String) p.getKey()).replace(".", DEFAULT_PATH_SEPARATOR) : p.getKey())) - .withType(ParameterType.String).withValue((String) p.getValue()).withVersion(1L); + .type(ParameterType.STRING).value((String) p.getValue()).version(1L).build(); return propertySource.getSource().entrySet().stream().map(mapper).collect(Collectors.toSet()); } diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/AwsS3EnvironmentRepositoryIntegrationTests.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/AwsS3EnvironmentRepositoryIntegrationTests.java new file mode 100644 index 000000000..ad14a1993 --- /dev/null +++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/AwsS3EnvironmentRepositoryIntegrationTests.java @@ -0,0 +1,68 @@ +/* + * Copyright 2022-2022 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 org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.testcontainers.containers.localstack.LocalStackContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.utility.DockerImageName; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.core.sync.RequestBody; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.s3.S3Client; + +import org.springframework.cloud.config.environment.Environment; +import org.springframework.cloud.config.server.config.ConfigServerProperties; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.testcontainers.containers.localstack.LocalStackContainer.Service.S3; + +/** + * @author Henning Pöttker + */ +@Testcontainers +@Tag("DockerRequired") +class AwsS3EnvironmentRepositoryIntegrationTests { + + private static final String BUCKET = "bucket1"; + + @Container + static LocalStackContainer localStack = new LocalStackContainer( + DockerImageName.parse("localstack/localstack:0.14.3.1")).withServices(S3); + + @Test + void test() { + S3Client s3Client = S3Client.builder().region(Region.of(localStack.getRegion())) + .endpointOverride(localStack.getEndpointOverride(S3)) + .credentialsProvider(StaticCredentialsProvider + .create(AwsBasicCredentials.create(localStack.getAccessKey(), localStack.getSecretKey()))) + .build(); + s3Client.createBucket((builder) -> builder.bucket(BUCKET)); + s3Client.putObject((builder) -> builder.bucket(BUCKET).key("foo-bar.json"), + RequestBody.fromString("{\"tag\": \"myapp\"}")); + + Environment env = new AwsS3EnvironmentRepository(s3Client, BUCKET, new ConfigServerProperties()).findOne("foo", + "bar", ""); + assertThat(env.getName()).isEqualTo("foo"); + assertThat(env.getPropertySources()).hasSize(1); + assertThat(env.getPropertySources().get(0).getSource().get("tag")).isEqualTo("myapp"); + } + +} diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/AwsS3EnvironmentRepositoryTests.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/AwsS3EnvironmentRepositoryTests.java index d1213a19a..01fb7506e 100644 --- a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/AwsS3EnvironmentRepositoryTests.java +++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/AwsS3EnvironmentRepositoryTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2022 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. @@ -16,18 +16,19 @@ package org.springframework.cloud.config.server.environment; -import java.io.UnsupportedEncodingException; import java.util.Objects; import java.util.Properties; -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.model.GetObjectRequest; -import com.amazonaws.services.s3.model.ObjectMetadata; -import com.amazonaws.services.s3.model.S3Object; -import com.amazonaws.services.s3.model.S3ObjectId; -import com.amazonaws.util.StringInputStream; import org.junit.Test; import org.mockito.ArgumentMatcher; +import org.mockito.internal.stubbing.answers.ThrowsExceptionForClassType; +import software.amazon.awssdk.core.ResponseInputStream; +import software.amazon.awssdk.http.AbortableInputStream; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.model.GetObjectRequest; +import software.amazon.awssdk.services.s3.model.GetObjectResponse; +import software.amazon.awssdk.services.s3.model.NoSuchKeyException; +import software.amazon.awssdk.utils.StringInputStream; import org.springframework.cloud.config.environment.Environment; import org.springframework.cloud.config.environment.PropertySource; @@ -35,8 +36,8 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; /** * @author Clay McCoy @@ -45,7 +46,7 @@ public class AwsS3EnvironmentRepositoryTests { final ConfigServerProperties server = new ConfigServerProperties(); - final AmazonS3 s3Client = mock(AmazonS3.class, "config"); + final S3Client s3Client = mock(S3Client.class, new ThrowsExceptionForClassType(NoSuchKeyException.class)); final EnvironmentRepository envRepo = new AwsS3EnvironmentRepository(s3Client, "bucket1", server); @@ -91,7 +92,7 @@ public void failToFindNonexistentObject() { } @Test - public void findPropertiesObject() throws UnsupportedEncodingException { + public void findPropertiesObject() { setupS3("foo-bar.properties", propertyContent); // Pulling content from a .properties file forces a boolean into a String @@ -103,7 +104,7 @@ public void findPropertiesObject() throws UnsupportedEncodingException { } @Test - public void findJsonObject() throws UnsupportedEncodingException { + public void findJsonObject() { setupS3("foo-bar.json", jsonContent); final Environment env = envRepo.findOne("foo", "bar", null); @@ -112,7 +113,7 @@ public void findJsonObject() throws UnsupportedEncodingException { } @Test - public void findYamlObject() throws UnsupportedEncodingException { + public void findYamlObject() { setupS3("foo-bar.yml", yamlContent); final Environment env = envRepo.findOne("foo", "bar", null); @@ -121,7 +122,7 @@ public void findYamlObject() throws UnsupportedEncodingException { } @Test - public void findWithDefaultProfile() throws UnsupportedEncodingException { + public void findWithDefaultProfile() { setupS3("foo.yml", yamlContent); final Environment env = envRepo.findOne("foo", null, null); @@ -130,7 +131,7 @@ public void findWithDefaultProfile() throws UnsupportedEncodingException { } @Test - public void findWithDefaultProfileUsingSuffix() throws UnsupportedEncodingException { + public void findWithDefaultProfileUsingSuffix() { setupS3("foo-default.yml", yamlContent); final Environment env = envRepo.findOne("foo", null, null); @@ -139,7 +140,7 @@ public void findWithDefaultProfileUsingSuffix() throws UnsupportedEncodingExcept } @Test - public void findWithMultipleProfilesAllFound() throws UnsupportedEncodingException { + public void findWithMultipleProfilesAllFound() { setupS3("foo-profile1.yml", yamlContent); setupS3("foo-profile2.yml", jsonContent); @@ -149,7 +150,7 @@ public void findWithMultipleProfilesAllFound() throws UnsupportedEncodingExcepti } @Test - public void findWithMultipleProfilesOneFound() throws UnsupportedEncodingException { + public void findWithMultipleProfilesOneFound() { setupS3("foo-profile2.yml", jsonContent); final Environment env = envRepo.findOne("foo", "profile1,profile2", null); @@ -158,7 +159,7 @@ public void findWithMultipleProfilesOneFound() throws UnsupportedEncodingExcepti } @Test - public void findWithLabel() throws UnsupportedEncodingException { + public void findWithLabel() { setupS3("label1/foo-bar.yml", yamlContent); final Environment env = envRepo.findOne("foo", "bar", "label1"); @@ -167,7 +168,7 @@ public void findWithLabel() throws UnsupportedEncodingException { } @Test - public void findWithVersion() throws UnsupportedEncodingException { + public void findWithVersion() { setupS3("foo-bar.yml", "v1", yamlContent); final Environment env = envRepo.findOne("foo", "bar", null); @@ -176,7 +177,7 @@ public void findWithVersion() throws UnsupportedEncodingException { } @Test - public void findWithMultipleApplicationAllFound() throws UnsupportedEncodingException { + public void findWithMultipleApplicationAllFound() { setupS3("foo-profile1.yml", jsonContent); setupS3("bar-profile1.yml", jsonContent); @@ -195,24 +196,21 @@ public void factoryCustomizable() { assertThat(repository).isNotNull(); } - private void setupS3(String fileName, String propertyContent) throws UnsupportedEncodingException { + private void setupS3(String fileName, String propertyContent) { setupS3(fileName, null, propertyContent); } - private void setupS3(String fileName, String version, String propertyContent) throws UnsupportedEncodingException { - final S3ObjectId s3ObjectId = new S3ObjectId("bucket1", fileName); - final GetObjectRequest request = new GetObjectRequest(s3ObjectId); - - final S3Object s3Object = new S3Object(); - s3Object.setObjectContent(new StringInputStream(propertyContent)); + private void setupS3(String fileName, String version, String propertyContent) { + final GetObjectRequest request = GetObjectRequest.builder().bucket("bucket1").key(fileName).build(); + GetObjectResponse.Builder responseBuilder = GetObjectResponse.builder(); if (version != null) { - final ObjectMetadata metadata = new ObjectMetadata(); - metadata.setHeader("x-amz-version-id", version); - s3Object.setObjectMetadata(metadata); + responseBuilder.versionId(version); } + ResponseInputStream responseInputStream = new ResponseInputStream<>(responseBuilder.build(), + AbortableInputStream.create(new StringInputStream(propertyContent))); - when(s3Client.getObject(argThat(new GetObjectRequestMatcher(request)))).thenReturn(s3Object); + doReturn(responseInputStream).when(s3Client).getObject(argThat(new GetObjectRequestMatcher(request))); } private void assertExpectedEnvironment(Environment env, String applicationName, String label, String version, @@ -240,9 +238,8 @@ public boolean matches(GetObjectRequest actual) { if (actual == null) { return false; } - return Objects.equals(actual.getBucketName(), expected.getBucketName()) - && Objects.equals(actual.getKey(), expected.getKey()) - && Objects.equals(actual.getVersionId(), expected.getVersionId()); + return Objects.equals(actual.bucket(), expected.bucket()) && Objects.equals(actual.key(), expected.key()) + && Objects.equals(actual.versionId(), expected.versionId()); } } diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/AwsSecretsManagerEnvironmentRepositoryIntegrationTests.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/AwsSecretsManagerEnvironmentRepositoryIntegrationTests.java new file mode 100644 index 000000000..eb41da5fe --- /dev/null +++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/AwsSecretsManagerEnvironmentRepositoryIntegrationTests.java @@ -0,0 +1,63 @@ +/* + * Copyright 2022-2022 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 org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.testcontainers.containers.localstack.LocalStackContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.utility.DockerImageName; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; + +import org.springframework.cloud.config.environment.Environment; +import org.springframework.cloud.config.server.config.ConfigServerProperties; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.testcontainers.containers.localstack.LocalStackContainer.Service.SECRETSMANAGER; + +/** + * @author Henning Pöttker + */ +@Testcontainers +@Tag("DockerRequired") +class AwsSecretsManagerEnvironmentRepositoryIntegrationTests { + + @Container + static LocalStackContainer localStack = new LocalStackContainer( + DockerImageName.parse("localstack/localstack:0.14.3.1")).withServices(SECRETSMANAGER); + + @Test + void test() { + SecretsManagerClient client = SecretsManagerClient.builder().region(Region.of(localStack.getRegion())) + .endpointOverride(localStack.getEndpointOverride(SECRETSMANAGER)) + .credentialsProvider(StaticCredentialsProvider + .create(AwsBasicCredentials.create(localStack.getAccessKey(), localStack.getSecretKey()))) + .build(); + client.createSecret((builder) -> builder.name("/secret/foo-bar/").secretString("{\"tag\": \"myapp\"}")); + + Environment env = new AwsSecretsManagerEnvironmentRepository(client, new ConfigServerProperties(), + new AwsSecretsManagerEnvironmentProperties()).findOne("foo", "bar", ""); + assertThat(env.getName()).isEqualTo("foo"); + assertThat(env.getPropertySources()).hasSize(1); + assertThat(env.getPropertySources().get(0).getSource().get("tag")).isEqualTo("myapp"); + } + +} diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/AwsSecretsManagerEnvironmentRepositoryTests.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/AwsSecretsManagerEnvironmentRepositoryTests.java index 94cbc1a14..e4314cfca 100644 --- a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/AwsSecretsManagerEnvironmentRepositoryTests.java +++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/AwsSecretsManagerEnvironmentRepositoryTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2022 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. @@ -20,9 +20,6 @@ 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; @@ -30,6 +27,9 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.junit.jupiter.api.Test; +import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; +import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest; +import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueResponse; import org.springframework.cloud.config.environment.Environment; import org.springframework.cloud.config.environment.PropertySource; @@ -49,7 +49,7 @@ 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 SecretsManagerClient awsSmClientMock = mock(SecretsManagerClient.class, "aws-sm-client-mock"); private final ConfigServerProperties configServerProperties = new ConfigServerProperties(); @@ -739,10 +739,10 @@ public void factoryCustomizableWithRegionAndEndpoint() { private void setupAwsSmClientMocks(Environment environment) { for (PropertySource ps : environment.getPropertySources()) { String path = StringUtils.delete(ps.getName(), environmentProperties.getOrigin()); - GetSecretValueRequest request = new GetSecretValueRequest().withSecretId(path); + GetSecretValueRequest request = GetSecretValueRequest.builder().secretId(path).build(); String secrets = getSecrets(ps); - GetSecretValueResult response = new GetSecretValueResult().withSecretString(secrets); + GetSecretValueResponse response = GetSecretValueResponse.builder().secretString(secrets).build(); when(awsSmClientMock.getSecretValue(eq(request))).thenReturn(response); } diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/vault/SpringVaultClientConfigurationTests.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/vault/SpringVaultClientConfigurationTests.java index fd7f0974b..d404177d3 100644 --- a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/vault/SpringVaultClientConfigurationTests.java +++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/vault/SpringVaultClientConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2022 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. @@ -138,7 +138,7 @@ public void awsEc2Authentication() { @Test public void awsIamAuthentication() { System.setProperty("aws.accessKeyId", "access-key-id"); - System.setProperty("aws.secretKey", "secret-key"); + System.setProperty("aws.secretAccessKey", "secret-access-key"); properties.setAuthentication(AWS_IAM); properties.getAwsIam().setRole("server");