我有一张包含一些元素的表格。我试图在unauth上使用细粒度访问控制(限制对表中特定属性的访问)(我想将特定属性返回给尚未经过身份验证的用户)角色,其中用户根据以下URL {{ 3}}
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "LimitAccessToSpecificAttributes",
"Effect": "Allow",
"Action": [
"dynamodb:GetItem",
"dynamodb:Query",
"dynamodb:BatchGetItem",
"dynamodb:Scan"
],
"Resource": [
"arn:aws:dynamodb:us-west-2:AccountID:table/MyTable"
],
"Condition": {
"ForAllValues:StringEquals": {
"dynamodb:Attributes": [
"startDate",
"endDate"
]
},
"StringEqualsIfExists": {
"dynamodb:Select": "SPECIFIC_ATTRIBUTES",
"dynamodb:ReturnValues": [
"NONE",
"UPDATED_OLD",
"UPDATED_NEW"
]
}
}
}
]
}
当我删除以下角色时,它可以工作:
"Condition": {
"ForAllValues:StringEquals": {
"dynamodb:Attributes": [
"startDate",
"endDate"
]
},
"StringEqualsIfExists": {
"dynamodb:Select": "SPECIFIC_ATTRIBUTES",
"dynamodb:ReturnValues": [
"NONE",
"UPDATED_OLD",
"UPDATED_NEW"
]
}
问题是,当我运行我的代码(android)时,我得到以下异常:
用户:arn:aws:sts :: AccountID:assume-role / Cognito_XXXUnauth_Role / CognitoIdentityCredentials无权执行:dynamodb:扫描资源:arn:aws:dynamodb:us-east-1:AccountID:table / MyTable (服务:AmazonDynamoDB;状态代码:400;错误代码:AccessDeniedException;
我想知道我做错了什么导致异常。 有没有其他方法来获取特定属性?
我正在使用以下android代码:
CognitoCachingCredentialsProvider credentialsProvider = new CognitoCachingCredentialsProvider(getApplicationContext(),
"identityPoolId",
Regions.US_EAST_1
);
AmazonDynamoDBClient ddb = new AmazonDynamoDBClient(credentialsProvider);
ScanRequest scanRequest = new ScanRequest();
scanRequest = scanRequest.withProjectionExpression("startDate, endDate");
scanRequest.setTableName("MyTable");
try {
ScanResult scanResult = ddb.scan(scanRequest);
} catch (Exception ex) {
log(ex.getMessage());
}
任何帮助都将不胜感激。
答案 0 :(得分:1)
查看您的IAM策略,看起来资源上允许扫描操作:arn:aws:dynamodb:us-west-2:AccountID:table / MyTable。
请注意,该资源适用于us-west-2。 但是您正在尝试对us-east-1中的资源执行操作。
答案 1 :(得分:0)
确保标识池具有足够的DynamoDB权限(在本例中为执行扫描)。 以下是通过创建未经身份验证的角色并授予其DynamoDB访问权限来使用Cognito的示例: http://docs.aws.amazon.com/amazondynamodb/latest/gettingstartedguide/GettingStarted.Js.Summary.html
然后,正如另一个人所说,请确保您指向您授予权限的同一区域。在这种情况下,请确保US_EAST_1具有足够的Cognito和DDB访问权限。
答案 2 :(得分:0)
我找到了原因。角色中的属性应包括hashkey和range键。当用hashkey和range键替换属性时,我得到了它,也改变了Lisa回答的区域。
我会在这里发布政策和Android代码,以防将来有人想看看它应该如何完成:
{
"Statement": [
{
"Effect": "Allow",
"Action": [
"dynamodb:DeleteItem",
"dynamodb:GetItem",
"dynamodb:PutItem",
"dynamodb:Scan",
"dynamodb:Query",
"dynamodb:UpdateItem",
"dynamodb:BatchWriteItem"
],
"Resource": [
"arn:aws:dynamodb:us-east-1:AcountID:table/MyTable",
"arn:aws:dynamodb:us-east-1:AcountID:table/MyTable/index/*"
]
}
]}
未经身份验证的用户政策:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "LimitAccessToSpecificAttributes",
"Effect": "Allow",
"Action": [
"dynamodb:GetItem",
"dynamodb:Query",
"dynamodb:BatchGetItem",
"dynamodb:Scan"
],
"Resource": [
"arn:aws:dynamodb:us-east-1:AcountID:table/MyTable"
],
"Condition": {
"ForAllValues:StringEquals": {
"dynamodb:Attributes": [
"userId",
"startDate",
"endDate",
"Price"
]
},
"StringEqualsIfExists": {
"dynamodb:Select": "SPECIFIC_ATTRIBUTES"
}
}
}
]}
android代码包含经过身份验证和未经身份验证的用户(杂乱)的代码。
public PaginatedScanList<Book> scan() {
PaginatedScanList<Book> result = null;
AmazonDynamoDBClient ddb = new AmazonDynamoDBClient(_cognito.getCredentialsProvider());
if (_cognito.getJWTToken() != null) {
//Authenticated (SignedIn) user flow
_cognito.credentialsProviderSetLogIn();
mapper = new DynamoDBMapper(ddb);
DynamoDBScanExpression scanExpression = new DynamoDBScanExpression();
result = mapper.scan(Book.class, scanExpression);
if (result != null) {
for (int i = 0; i < result.size(); i++) {
log("UserId: " + result.get(i).getUserId());
log("Price: " + result.get(i).getPrice());
log("startDate: " + result.get(i).getPrice());
log("endDate: " + result.get(i).getPrice());
}
}
} else {
//UnAuthenticated user flow
ScanRequest scanRequest = new ScanRequest();
//Write attributes to be retreived. if Price is not exsits, items.get(i).get("Price").getS() will be null
//If Price is not exists in the policy, policy is null
scanRequest = scanRequest.withProjectionExpression("UserId, Price, startDate, endDate");//setter for projectionExpression
//scanRequest.setProjectionExpression("UserId, Price, startDate, endDate"); //not sure why this API exists. It does the same as withProjectionExpression. this is setter for projectionExpression
scanRequest.setSelect(Select.SPECIFIC_ATTRIBUTES); //Not usre this is needed. works well without it.
scanRequest.setTableName("MyTable");
try {
ScanResult scanResult = ddb.scan(scanRequest);
final List<Map<String, AttributeValue>> items = scanResult.getItems();
for (int i = 0; i < items.size(); i++) {
log("UserId: " + items.get(i).get("UserId").getS());
log("Price: " + items.get(i).get("Price").getS());
log("startDate: " + items.get(i).get("startDate").getS());
log("endDate: " + items.get(i).get("endDate").getS());
}
} catch (Exception ex) {
log(ex.getMessage());
}
}
return result;
}