Search code examples
spring-bootamazon-ec2spring-dataamazon-dynamodb

AWS DynamoDb fails when accessed from EC2 instance with Spring data


Hy guys, when I run my Spring Boot 2 project from my local machine (Ubuntu) is all fine but when I tried to access DynamoDb tables from my Spring Boot 2 project running on EC 2 instance I received this error:

"The security token included in the request is invalid. (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: UnrecognizedClientException; Request ID: E0JP23I9DK11PE64OQV5MNLGR3VV4KQNSO5AEMVJF66Q9ASUAAJG)"

After compiling my project I run it (on EC2 or my local machine) with the command line :

java -Daws.accessKeyId=... -Daws.secretKey=... -jar myApp.jar 

To login into DynamoDB my code is :

@Configuration
@EnableDynamoDBRepositories(basePackages = "app.repositories")
public class DynamoDBConfig {

    @Autowired
    private ConfigProperties config;

    @Bean
    public AmazonDynamoDB amazonDynamoDB() {
        AWSCredentialsProvider credentialsProvider = buildCredentials();
        AmazonDynamoDBClient.builder().withCredentials(credentialsProvider).withRegion("");
        return AmazonDynamoDBClientBuilder.defaultClient();
    }

    private AWSCredentialsProvider buildCredentials() {
        AWSCredentialsProvider credentialsProvider = new AWSCredentialsProvider(){

            @Override
            public AWSCredentials getCredentials() {
                return new BasicAWSCredentials(config.getAwsAccessKey(), config.getAwsSecretKey());
            }

            @Override
            public void refresh() {
                // TODO Auto-generated method stub

            }

        };
        return credentialsProvider;
    }

}

To access tables I use this code :

@Getter
@Setter
@DynamoDBTable(tableName = "user")
public class UserModel {

    @DynamoDBHashKey
    @DynamoDBAutoGeneratedKey   
    private String id;

    @DynamoDBIndexHashKey(globalSecondaryIndexName = "idx_global_userMatricula")
    @DynamoDBAttribute  
    private String matricula;

    @DynamoDBAttribute
    private String nome;

    @DynamoDBAttribute
    private String senha;

    @DynamoDBIndexHashKey(globalSecondaryIndexName = "idx_global_userClinicaId")
    @DynamoDBAttribute
    private String clinicaId;

    @DynamoDBAttribute
    private boolean active;

    @DynamoDBAttribute
    private boolean grantCli;

    @DynamoDBAttribute
    private boolean grantUser;

    @DynamoDBAttribute
    private String collection;

}

And my repository class is :

@EnableScan
public interface UserRepository extends CrudRepository<UserModel,String>{

}

Tks ...


Solution

  • It is not a great practice to implement your own credentials provider. I am assuming that the issue is whatever custom way you are getting your credentials on your local machine is not setup on the EC2 instance.

    I would recommend to use the DefaultCredentialsProvider which goes through 5 different methods for finding credentials (see documentation).

    Some of those methods work well on your local machine for testing such as environment variables as well as the the ~/.aws/credentials file that is setup when you run the aws configure command locally.

    Some of the methods are more ideal for EC2 instances like using the instance profile IAM Role associated with the EC2 instance.

    Using the DefaultCredentialsProvider will allow you to use these different mechanisms without having to have different credentials providers for local vs EC2 deployments.