AWS Lambda 尝试列出 DynamoDb 表时出错

Error when AWS Lambda trying to list DynamoDb tables

我无法使用 Java 使以下逻辑在 AWS Lambda 上运行:

1) 当S3 bucket中有新对象创建时,触发一个lambda函数(写在java)

2) 在此 lambda 函数中,列出所有 DynamoDB table。

3) 如果有none,则创建一个table。

4) 将 S3 对象的详细信息作为项目写入 DynamoDB。

我只让项目 #1 工作。当它到达第 2 项时,我在下面遇到了与权限相关的错误。

有什么帮助或建议吗?

我使用的权限是"Basic with DynamoDB",它有以下权限:

START RequestId: e9ab5aba-307b-11e5-9663-3188c327cf5e fileSize: 1024, DateTime:1970-01-01T00:00:00.000Zs3Key : HappyFace.jpgAWS credential profiles file not found in the given path: /home/sbx_user1052/.aws/credentials: java.lang.IllegalArgumentException java.lang.IllegalArgumentException: AWS credential profiles file not found in the given path: /home/sbx_user1052/.aws/credentials at com.amazonaws.auth.profile.internal.ProfilesConfigFileLoader.loadProfiles(ProfilesConfigFileLoader.java:45) at com.amazonaws.auth.profile.ProfilesConfigFile.loadProfiles(ProfilesConfigFile.java:176) at com.amazonaws.auth.profile.ProfilesConfigFile.(ProfilesConfigFile.java:112) at com.amazonaws.auth.profile.ProfilesConfigFile.(ProfilesConfigFile.java:92) at com.amazonaws.auth.profile.ProfileCredentialsProvider.getCredentials(ProfileCredentialsProvider.java:123) at com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient.invoke(AmazonDynamoDBClient.java:1763) at com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient.listTables(AmazonDynamoDBClient.java:1208) at com.amazonaws.services.dynamodbv2.document.internal.ListTablesCollection.firstPage(ListTablesCollection.java:46) at com.amazonaws.services.dynamodbv2.document.internal.PageIterator.next(PageIterator.java:45) at com.amazonaws.services.dynamodbv2.document.internal.IteratorSupport.nextResource(IteratorSupport.java:79) at com.amazonaws.services.dynamodbv2.document.internal.IteratorSupport.hasNext(IteratorSupport.java:47) at com.TriggerDynamoDB.handleRequest(TriggerDynamoDB.java:68) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:497)

END RequestId: e9ab5aba-307b-11e5-9663-3188c327cf5e REPORT RequestId: e9ab5aba-307b-11e5-9663-3188c327cf5e Duration: 3294.97 ms Billed Duration: 3300 ms Memory Size: 512 MB Max Memory Used: 51 MB

代码如下:

public class TriggerDynamoDB implements RequestHandler<S3Event, String> {

public String handleRequest(S3Event s3event, Context context) {
     LambdaLogger logger = context.getLogger();
     try {           
         S3EventNotificationRecord record = s3event.getRecords().get(0);
         // Object key may have spaces or unicode non-ASCII characters.
         String srcKey = record.getS3().getObject().getKey().replace('+', ' ');
            srcKey = URLDecoder.decode(srcKey, "UTF-8");

         long fileSize = record.getS3().getObject().getSizeAsLong();
         DateTime datetime = record.getEventTime(); 

         logger.log("fileSize: " + fileSize + ", DateTime:" + datetime);
         logger.log("s3Key   : " + srcKey);

         DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient(new ProfileCredentialsProvider()));
         //Table table = dynamoDB.getTable("dimensionFile");

         TableCollection<ListTablesResult> tables = dynamoDB.listTables();
         Iterator<Table> iterator = tables.iterator();

         while (iterator.hasNext()) { // this is where the error was thrown
             Table table = iterator.next();
             System.out.println(table.getTableName());
         }                    
         return "Ok";
     } catch (Exception e) {
         throw new RuntimeException(e);
     }
}
}

您需要 dynamoDb listTables 操作权限。
您还需要正确指定资源:如 "*" 而不是 ""

这是一个包含 ListTables 的有效策略:

{ "Version": "2012-10-17", "Statement": [ { "Sid": "Stmt1428341300017", "Action": [ "dynamodb:DeleteItem", "dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:Query", "dynamodb:Scan", "dynamodb:UpdateItem", "dynamodb:ListTables" ], "Effect": "Allow", "Resource": "" }, { "Sid": "", "Resource": "", "Action": [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents" ], "Effect": "Allow" } ] }

此外,为了将来参考,请阅读 through/try 以下内容: http://docs.aws.amazon.com/IAM/latest/UserGuide/policies_testing-policies.html

您传递给 AmazonDynamoDBClient 构造函数的 ProfileCredentialsProvider 尝试从 ~/.aws/credentials 文件加载凭据。该文件在您的 Lambda 函数 运行 所在的主机上不存在,因此出现异常。此提供程序主要用于 运行 在您的开发机器上进行集成测试并使用您的个人 IAM 用户凭据。

在 Lambda 上,您需要 EnvironmentVariableCredentialsProvider。此提供程序将从 Lambda 在调用您的代码之前设置的环境变量加载与您的 Lambda 函数关联的 IAM 角色的临时凭证。

如果您对 Am​​azonDynamoDBClient 使用无参数构造函数,它将默认使用 DefaultAWSCredentialsProviderChain 来提取凭据。此提供程序检查环境变量、Java 系统属性、~/.aws/credentials 和 EC2 实例元数据服务(按此顺序),并且无论您是 运行 在本地还是在λ.

转到控制台主页 > IAM > 组 > 您的组 > 权限 > 附加策略

添加 AmazonDynamoDBReadOnlyAccess,AWSLambdaInvocation-DynamoDB

转至控制台主页 > IAM > 群组 > 您的群组 > 用户 > 将用户添加到群组(在此处将您的用户添加到群组)

转到控制台主页 > IAM > 用户 > 您的用户 > 创建访问密钥

BasicAWSCredentials b = new BasicAWSCredentials("Access Key ID","Secret Access Key");           
AmazonDynamoDBClient client = new AmazonDynamoDBClient(b);

而是

new AmazonDynamoDBClient(new ProfileCredentialsProvider())

使用

AmazonDynamoDBClientBuilder.standard().build()

此函数本身将从环境中获取凭据