Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is my Elastic Beanstalk app denied PutItem access to my DynamoDB, despite its role?

The goal

I want to programmatically add an item to a table in my DynamoDB from my Elastic Beanstalk application, using code similar to:

Item item = new Item()
    .withPrimaryKey(UserIdAttributeName, userId)
    .withString(UserNameAttributeName, userName);

table.putItem(item);

The unexpected result

Logs show the following error message, with the [bold parts] being my edits:

User: arn:aws:sts::[iam id?]:assumed-role/aws-elasticbeanstalk-ec2-role/i-[some number] is not authorized to perform: dynamodb:PutItem on resource: arn:aws:dynamodb:us-west-2:[iam id?]:table/PiggyBanks (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: AccessDeniedException; Request ID: [the request id])

I am able to get the table just fine, but things go awry when PutItem is called.

The configuration

I created a new Elastic Beanstalk application. According to the documentation, this automatically assigns the application a new role, called:

aws-elasticbeanstalk-service-role

That same documentation indicates that I can add access to my database as follows:

Add permissions for additional services to the default service role in the IAM console.

So, I found the aws-elasticbeanstalk-service-role role and added to it the managed policy, AmazonDynamoDBFullAccess. This policy looks like the following, with additional actions removed for brevity:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "dynamodb:*",
        [removed for brevity]
        "lambda:DeleteFunction"
      ],
      "Effect": "Allow",
      "Resource": "*"
    }
  ]
}

This certainly looks like it should grant the access I need. And, indeed, the policy simulator verifies this. With the following parameters, the action is allowed:

  • Role: aws-elasticbeanstalk-service-role
  • Service: DynamoDB
  • Action: PutItem
  • Simulation Resource: [Pulled from the above log] arn:aws:dynamodb:us-west-2:[iam id?]:table/PiggyBanks

Update

In answer to the good question by filipebarretto, I instantiate the DynamoDB object as follows:

private static DynamoDB createDynamoDB() {
    AmazonDynamoDBClient client = new AmazonDynamoDBClient();
    client.setRegion(Region.getRegion(Regions.US_WEST_2));

    DynamoDB result = new DynamoDB(client);
    return result;
}

According to this documentation, this should be the way to go about it, because it is using the default credentials provider chain and, in turn, the instance profile credentials,

which exist within the instance metadata associated with the IAM role for the EC2 instance.

[This option] in the default provider chain is available only when running your application on an EC2 instance, but provides the greatest ease of use and best security when working with EC2 instances.

Other things I tried

This related Stack Overflow question had an answer that indicated region might be the issue. I've tried tweaking the region with no additional success.

I have tried forcing the usage of the correct credentials using the following:

    AmazonDynamoDBClient client = new AmazonDynamoDBClient(new InstanceProfileCredentialsProvider());

I have also tried creating an entirely new environment from within Elastic Beanstalk.

In conclusion

By the error in the log, it certainly looks like my Elastic Beanstalk application is assuming the correct role.

And, by the results of the policy simulator, it looks like the role should have permission to do exactly what I want to do.

So...please help!

Thank you!

like image 208
Dan Avatar asked Jul 24 '16 19:07

Dan


People also ask

When should you not use Elastic Beanstalk?

Elastic Beanstalk isn't great if you need a lot of environment variables. The simple reason is that Elastic Beanstalk has a hard limit of 4KB to store all key-value pairs. The environment had accumulated 74 environment variables — a few of them had exceedingly verbose names.


1 Answers

Update the aws-elasticbeanstalk-ec2-role role, instead of the aws-elasticbeanstalk-service-role.

This salient documentation contains the key:

When you create an environment, AWS Elastic Beanstalk prompts you to provide two AWS Identity and Access Management (IAM) roles, a service role and an instance profile. The service role is assumed by Elastic Beanstalk to use other AWS services on your behalf. The instance profile is applied to the instances in your environment and allows them to upload logs to Amazon S3 and perform other tasks that vary depending on the environment type and platform.

In other words, one of these roles (-service-role) is used by the Beanstalk service itself, while the other (-ec2-role) is applied to the actual instance.

It's the latter that pertains to any permissions you need from within your application code.

like image 63
Dan Avatar answered Oct 13 '22 00:10

Dan