为什么我的Elastic Beanstalk应用程序拒绝PutItem访问我的DynamoDB,尽管它的作用?

Dan*_*Dan 7 amazon-web-services amazon-dynamodb amazon-iam amazon-elastic-beanstalk

目标

我想以编程方式从我的Elastic Beanstalk应用程序向DynamoDB中的表添加项目,使用类似于以下的代码:

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

table.putItem(item);
Run Code Online (Sandbox Code Playgroud)

意外的结果

日志显示以下错误消息,[粗体部分]是我的编辑:

用户:arn:aws:sts :: [iam id?]:assume-role/aws-elasticbeanstalk-ec2-role/i- [some number]无权执行:dynamodb:PutItem on resource:arn:aws:dynamodb :us-west-2:[iam id?]:table/PiggyBanks(服务:AmazonDynamoDBv2;状态代码:400;错误代码:AccessDeniedException;请求ID:[请求ID])

我能够很好地获得表格,但是当调用PutItem时出现问题.

配置

我创建了一个新的Elastic Beanstalk应用程序.根据文档,这会自动为应用程序分配一个新角色,称为:

aws-elasticbeanstalk-service-role
Run Code Online (Sandbox Code Playgroud)

相同的文档表明我可以添加对我的数据库的访问,如下所示:

将其他服务的权限添加到IAM控制台中的默认服务角色.

所以,我找到了这个aws-elasticbeanstalk-service-role角色,并在其中添加了托管策略AmazonDynamoDBFullAccess.此策略如下所示,为简洁起见,删除了其他操作:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "dynamodb:*",
        [removed for brevity]
        "lambda:DeleteFunction"
      ],
      "Effect": "Allow",
      "Resource": "*"
    }
  ]
}
Run Code Online (Sandbox Code Playgroud)

这当然看起来应该授予我需要的访问权限.事实上,政策模拟器验证了这一点.使用以下参数,允许操作:

  • 角色:aws-elasticbeanstalk-service-role
  • 服务:DynamoDB
  • 行动:PutItem
  • 模拟资源:[从上面的日志中拉出] arn:aws:dynamodb:us-west-2:[iam id?]:table/PiggyBanks

更新

在回答好问题时filipebarretto,我按如下方式实例化DynamoDB对象:

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

    DynamoDB result = new DynamoDB(client);
    return result;
}
Run Code Online (Sandbox Code Playgroud)

根据这个文档,这应该是它的方法,因为它正在使用default credentials provider chain,反过来instance profile credentials,,

存在于与EC2实例的IAM角色关联的实例元数据中.

默认提供程序链中的[此选项]仅在EC2实例上运行应用程序时可用,但在使用EC2实例时提供最大的易用性和最佳安全性.

我试过的其他事情

这个相关的Stack Overflow问题有一个答案,表明区域可能是问题.我试过调整该地区没有额外的成功.

我尝试使用以下方法强制使用正确的凭据:

    AmazonDynamoDBClient client = new AmazonDynamoDBClient(new InstanceProfileCredentialsProvider());
Run Code Online (Sandbox Code Playgroud)

我也尝试在Elastic Beanstalk中创建一个全新的环境.

结论

通过日志中的错误,它看起来像我的Elastic Beanstalk应用程序正在承担正确的角色.

而且,根据策略模拟器的结果,该角色看起来应该有权执行我想要做的事情.

所以...请帮忙!

谢谢!

Dan*_*Dan 9

更新aws-elasticbeanstalk-ec2-role角色,而不是aws-elasticbeanstalk-service-role.

这个突出的文档包含密钥:

创建环境时,AWS Elastic Beanstalk会提示您提供两个AWS Identity and Access Management(IAM)角色,一个服务角色和一个实例配置文件.Elastic Beanstalk假定服务角色代表您使用其他AWS服务.实例配置文件应用于您环境中的实例,并允许它们将日志上载到Amazon S3并执行根据环境类型和平台而变化的其他任务.

换句话说,其中一个角色(-service-role)由Beanstalk服务本身使用,而另一个(-ec2-role)应用于实际实例.

后者与您在应用程序代码中需要的任何权限相关.

  • 哇......这很明显......最后忽略了这个问题= /很棒,你想出来了=) (2认同)

fil*_*tto 6

要加载凭据,请尝试:

InstanceProfileCredentialsProvider mInstanceProfileCredentialsProvider = new InstanceProfileCredentialsProvider();
AWSCredentials credentials = mInstanceProfileCredentialsProvider.getCredentials();

AmazonDynamoDBClient client = new AmazonDynamoDBClient(credentials);
Run Code Online (Sandbox Code Playgroud)

要么

AmazonDynamoDBClient client = new AmazonDynamoDBClient(new DefaultAWSCredentialsProviderChain());
Run Code Online (Sandbox Code Playgroud)