2

I am writing a functional test case and connecting to a local DyanmoDB instance within it.

This is how I create the DynamoDB client:

private static final String table_name = "table-A";
private static String aws_region = "us-west-2";
private static AmazonDynamoDB amazonDynamoDBClient;
private static DynamoDB dynamoDB;


public static void initDB() {
    amazonDynamoDBClient = AmazonDynamoDBClientBuilder.standard().withEndpointConfiguration(
      new AwsClientBuilder.EndpointConfiguration("http://localhost:8000", aws_region)).build();
    dynamoDB = new DynamoDB(amazonDynamoDBClient);
}

And this is how I'm trying to create the table:

Table table = dynamoDB.createTable(table_name,
                Arrays.asList(new KeySchemaElement("row_name", KeyType.HASH),
                        new KeySchemaElement("row_id", KeyType.RANGE)),
                Arrays.asList(new AttributeDefinition("row_name", ScalarAttributeType.S),
                        new AttributeDefinition("row_id", ScalarAttributeType.S)),
                new ProvisionedThroughput(10L, 10L));

However, I get the below exception:

com.amazonaws.SdkClientException: Unable to load AWS credentials from any provider in the chain
        at com.amazonaws.auth.AWSCredentialsProviderChain.getCredentials(AWSCredentialsProviderChain.java:131)
        at com.amazonaws.http.AmazonHttpClient$RequestExecutor.getCredentialsFromContext(AmazonHttpClient.java:1115)
        at com.amazonaws.http.AmazonHttpClient$RequestExecutor.runBeforeRequestHandlers(AmazonHttpClient.java:764)
        at com.amazonaws.http.AmazonHttpClient$RequestExecutor.doExecute(AmazonHttpClient.java:728)
        at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeWithTimer(AmazonHttpClient.java:721)
        at com.amazonaws.http.AmazonHttpClient$RequestExecutor.execute(AmazonHttpClient.java:704)
        at com.amazonaws.http.AmazonHttpClient$RequestExecutor.access$500(AmazonHttpClient.java:672)
        at com.amazonaws.http.AmazonHttpClient$RequestExecutionBuilderImpl.execute(AmazonHttpClient.java:654)
        at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:518)
        at com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient.doInvoke(AmazonDynamoDBClient.java:1831)
        at com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient.invoke(AmazonDynamoDBClient.java:1807)
        at com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient.createTable(AmazonDynamoDBClient.java:636)
        at com.amazonaws.services.dynamodbv2.document.DynamoDB.createTable(DynamoDB.java:96)
        at com.amazonaws.services.dynamodbv2.document.DynamoDB.createTable(DynamoDB.java:108)
        at util.DBUtil.createAndInsertTestCases(DBUtil.java:24)
        at test.DocumentTest.createAndInsertDataInDB(DocumentTest.java:37)

What is the issue?

Ermiya Eskandary
  • 15,323
  • 3
  • 31
  • 44
N.Rajal
  • 105
  • 2
  • 17
  • Note that the issue here is largely unrelated to DynamoDB. It's simply that you have provided no credentials to the AWS SDK. See [Working with credentials](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/credentials.html). – jarmod Nov 03 '21 at 14:25
  • Thank you, I'm trying to run the tests inside a docker. I hope I can pass them as environment variables. – N.Rajal Nov 03 '21 at 15:07
  • Credentials supplied in environment variables is one of the supported mechanisms. – jarmod Nov 03 '21 at 15:17

1 Answers1

3

It looks like you never have set up any credentials for AWS on your machine for the SDK to use.


The DynamoDB SDK is oblivious to if you are using a local or remote cloud version of DynamoDB. This means it will still be checking if credentials are present before sending the request.

As most people will be using the remote cloud version of DDB, which requires credentials, this allows the client to not call the remote server when it knows the request will fail - faster error handling, no network cost, etc.

You can see that as the stack traces show that AmazonHttpClient.java is trying to get credentials using getCredentialsFromContext.


An access key ID & secret access key must be set for all requests but for the local DDB, these can be set to any dummy & fake values.

This should work, for example:

EndpointConfiguration endpointConfig = new EndpointConfiguration("http://localhost:8000", aws_region);

AWSStaticCredentialsProvider awsCredProvider = new AWSStaticCredentialsProvider(new BasicAWSCredentials("fakeMyKeyId", "fakeSecretAccessKey"));

AmazonDynamoDB ddb = AmazonDynamoDBClientBuilder
    .standard()
    .withCredentials(awsCredProvider)
    .withEndpointConfiguration(endpointConfig)
    .build();

As @jarmod also points out in the comments, if you cannot provide credentials for some reason, you may also be able to use AnonymousAWSCredentials (assuming that local DDB doesn't actually require signed API requests).

Specifying the credentials provider as AnonymousCredentialsProvider may work:

EndpointConfiguration endpointConfig = new EndpointConfiguration("http://localhost:8000", aws_region);

AnonymousCredentialsProvider awsCredProvider = new AnonymousCredentialsProvider();

AmazonDynamoDB ddb = AmazonDynamoDBClientBuilder
    .standard()
    .withCredentials(awsCredProvider)
    .withEndpointConfiguration(endpointConfig)
    .build();
Ermiya Eskandary
  • 15,323
  • 3
  • 31
  • 44
  • If no credentials are present, and cannot be provided for some reason, then it might be possible to use [AnonymousAWSCredentials](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/AnonymousAWSCredentials.html), assuming that DynamoDB Local doesn't actually require signed API requests. – jarmod Nov 03 '21 at 12:17
  • @jarmod Interesting, I wasn't aware! Added to question for visibility with attribution & sample, hope you don't mind :) – Ermiya Eskandary Nov 03 '21 at 12:29
  • The anonymous provider is [AnonymousCredentialsProvider](https://sdk.amazonaws.com/java/api/2.0.0-preview-11/software/amazon/awssdk/auth/credentials/AnonymousCredentialsProvider.html). – jarmod Nov 03 '21 at 12:34
  • type was correct but initialization wasn't, fixed typo – Ermiya Eskandary Nov 03 '21 at 13:32
  • 1
    Thanks, that worked. However, I was under the impression that while connecting to local, dynamoDB has nothing to do with credentials. Hence I was not giving any. – N.Rajal Nov 03 '21 at 15:03
  • Local DynamoDB doesn't, but the SDK checks regardless to account for 95%+ of requests (which won't be to a local version) - no worries! glad I could help – Ermiya Eskandary Nov 03 '21 at 15:04