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 角色的临时凭证。
如果您对 AmazonDynamoDBClient 使用无参数构造函数,它将默认使用 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()
此函数本身将从环境中获取凭据
我无法使用 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 角色的临时凭证。
如果您对 AmazonDynamoDBClient 使用无参数构造函数,它将默认使用 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()
此函数本身将从环境中获取凭据