0
votes
@Configuration
public class SNSConfig {

     @Value("${aws.region}")
     private String awsRegion;

     @Bean
     public AmazonSNS snsClient() {
           return AmazonSNSClientBuilder.standard()
                     .withRegion(awsRegion)
                     .withCredentials(credentialsProvider)
                     .build();
     }
}

Credential Provider Factory

@Configuration
public class AWSCredentialsProviderFactory {

@Bean
@Profile("local")
public AWSCredentialsProvider awsStsCredentialsProvider(
        @Value("${aws.region}") String awsRegion,
        @Value("${aws.assumeRoleARN}") String roleArn,
        @Value("${aws.assumeRoleSessionName}") String sessionName) {
    
        AWSSecurityTokenService stsClient = AWSSecurityTokenServiceClientBuilder.standard().withRegion(awsRegion)
                .withCredentials(new DefaultAWSCredentialsProviderChain()).build();

        return new STSAssumeRoleSessionCredentialsProvider.Builder(roleArn, sessionName)
                .withStsClient(stsClient).build();
    
}


@Bean
@Profile("!local")
public AWSCredentialsProvider awsCredentialsProvider() {
    return new AWSCredentialsProvider() {

        @Override
        public AWSCredentials getCredentials() {
            
            DefaultAWSCredentialsProviderChain defaultAWSCredentialsProviderChain = new DefaultAWSCredentialsProviderChain();
            return defaultAWSCredentialsProviderChain.getCredentials();
        }

        @Override
        public void refresh() {
            // Refresh of Session credentials are not required
        }
    };

  }
}

SNS Publish

@Service
public class PublisherService {

  @Value("${awsTopic}")
  private String rmOutboundTopic;

  @Autowired 
  private AmazonSNS snsClient;

  void publish(String message) {
      PublishRequest publishRequest =
                new PublishRequest()
                        .withTopicArn(rmOutboundTopic)
                        .withMessage(message);
      snsClient.publish(publishRequest);
  }
}

Now, whenever request floods, my publisher complaints

com.amazonaws.SdkClientException: 
Unable to load AWS credentials from any provider in the chain: 
       [EnvironmentVariableCredentialsProvider: Unable to load AWS credentials from 
       environment variables (AWS_ACCESS_KEY_ID (or AWS_ACCESS_KEY) and AWS_SECRET_KEY (or 
       AWS_SECRET_ACCESS_KEY)), SystemPropertiesCredentialsProvider: Unable to load AWS 
       credentials from Java system properties (aws.accessKeyId and aws.secretKey), 
       com.amazonaws.auth.profile.ProfileCredentialsProvider@72cc5f01: Unable to load 
       credentials into profile [default]: AWS Access Key ID is not specified., 
       com.amazonaws.auth.EC2ContainerCredentialsProviderWrapper@4385f967: Too Many Requests 
       (Service: null; Status Code: 429; Error Code: null; Request ID: null)]\n\tat 
       com.amazonaws.auth.AWSCredentialsProviderChain.getCredentials 
       (AWSCredentialsProviderChain.java:136)\n\tat

When I remove withCredentials() while building from SNSClient using credentialProvider this issue is not coming. Could you please help me understand the connection between these two?

Note: If I remove, withCredentials() I am not able to run application in my local. So I am ending up creating 2 different beans (one for local & one for non local) for each sdk client.

Is there a better way to handle this?