awspring / spring-cloud-aws

The New Home for Spring Cloud AWS
http://awspring.io
Apache License 2.0
878 stars 299 forks source link

Unable to define custom AwsCredentialsProvider / AwsRegionProvider for config import #695

Closed jdolan-chwy closed 1 year ago

jdolan-chwy commented 1 year ago

Type: Bug

Component: Core / AutoConfiguration, Spring Boot 2.7.8, Spring Cloud AWS 3.0.0-RC

Describe the bug The documentation for 3.0.0 indicates that you can prevent Spring Cloud AWS from auto-configuring Credentials and Region by simply defining your own @Beans for them:

https://docs.awspring.io/spring-cloud-aws/docs/3.0.0-SNAPSHOT/reference/html/index.html#credentials

But I am finding this to not be the case. I have both AwsCredentialsProvider and AwsRegionProvider beans defined in my own @Configuration class. Other components within my application are using these beans without issue. But Spring Cloud AWS continues to auto-configure and therefore fails to bind to any AWS resources. Specifically, the secrets manager config import fails on startup Perhaps my beans are not initialized in time for Spring Cloud AWS to detect them? But.. can I influence that?

Sample

Here is an approximation of my Configuration class:

@Configuration
@ConfigurationProperties(prefix = "com.myco.aws")
public class AwsConfig {

  public static class Credentials {
    String accessKey;
    String secretKey;
    File file;

    boolean hasFile() {
      return file != null && file.exists();
    }
  }

  Region region;
  Credentials credentials;
  URI endpoint;

  @Bean
  public AwsCredentialsProvider credentialsProvider() {
    if (credentials.hasFile()) {
      return WebIdentityTokenFileCredentialsProvider.builder()
          .webIdentityTokenFile(credentials.getFile().toPath())
          .build();
    } else {
      return StaticCredentialsProvider.create(
          AwsBasicCredentials.create(credentials.accessKey, credentials.secretKey));
    }
  }

  @Bean
  public AwsRegionProvider regionProvider() {
    return new StaticRegionProvider(region.id());
  }
}

For application.yaml, assuming the Spring Cloud AWS docs are correct, I should not need to set anything besides the endpoint, because that is the only property not covered by an explicit Provider interface (unlike AwsCredentialsProvider and AwsRegionProvider):

# relevant portions of application.yaml
spring:
  cloud:
    aws:
      endpoint: ${stark.aws.endpoint}
  config:
    import: optional:aws-secretsmanager:/path/to/my/secret-name

And on startup:

2023-03-01 15:58:41 Picked up JAVA_TOOL_OPTIONS: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005
2023-03-01 15:58:41 Listening for transport dt_socket at address: 5005
2023-03-01 15:58:54 
2023-03-01 15:58:54   .   ____          _            __ _ _
2023-03-01 15:58:54  /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
2023-03-01 15:58:54 ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
2023-03-01 15:58:54  \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
2023-03-01 15:58:54   '  |____| .__|_| |_|_| |_\__, | / / / /
2023-03-01 15:58:54  =========|_|==============|___/=/_/_/_/
2023-03-01 15:58:54  :: Spring Boot ::                (v2.7.8)
2023-03-01 15:58:54 
2023-03-01 15:58:57 20:58:57.444 - ERROR [main] o.s.boot.SpringApplication               : Application run failed
2023-03-01 15:58:57 software.amazon.awssdk.core.exception.SdkClientException: Unable to load region from any of the providers in the chain software.amazon.awssdk.regions.providers.DefaultAwsRegionProviderChain@3eb738bb: [software.amazon.awssdk.regions.providers.SystemSettingsRegionProvider@3eb25e1a: Unable to load region from system settings. Region must be specified either via environment variable (AWS_REGION) or  system property (aws.region)., software.amazon.awssdk.regions.providers.AwsProfileRegionProvider@477b4cdf: No region provided in profile: default, software.amazon.awssdk.regions.providers.InstanceProfileRegionProvider@233795b6: Unable to contact EC2 metadata service.]
2023-03-01 15:58:57     at software.amazon.awssdk.core.exception.SdkClientException$BuilderImpl.build(SdkClientException.java:111)
2023-03-01 15:58:57     at software.amazon.awssdk.regions.providers.AwsRegionProviderChain.getRegion(AwsRegionProviderChain.java:70)
2023-03-01 15:58:57     at io.awspring.cloud.autoconfigure.config.AbstractAwsConfigDataLocationResolver.configure(AbstractAwsConfigDataLocationResolver.java:145)
2023-03-01 15:58:57     at io.awspring.cloud.autoconfigure.config.secretsmanager.SecretsManagerConfigDataLocationResolver.createAwsSecretsManagerClient(SecretsManagerConfigDataLocationResolver.java:93)
2023-03-01 15:58:57     at org.springframework.boot.DefaultBootstrapContext.getInstance(DefaultBootstrapContext.java:119)
2023-03-01 15:58:57     at org.springframework.boot.DefaultBootstrapContext.getOrElseThrow(DefaultBootstrapContext.java:111)
2023-03-01 15:58:57     at org.springframework.boot.DefaultBootstrapContext.get(DefaultBootstrapContext.java:88)
2023-03-01 15:58:57     at ....

Are the docs accurate? Is this problem unique to config: import.. because that happens at bootstrap? Is there a way around this?

maciejwalkowiak commented 1 year ago

For Secrets Manager and Parameter Store you need to configure bootstraps stage indeed. Look here https://docs.awspring.io/spring-cloud-aws/docs/3.0.0-RC1/reference/html/index.html#customizing-secretsmanagerclient

jdolan-chwy commented 1 year ago

Got it, thank you!