【发布时间】:2021-08-27 17:11:55
【问题描述】:
我正在尝试根据附加到 Amazon Cognito 用户的信息假设细粒度的 DynamoDB 访问。
目前的架构是这样的:
- React-Native 应用程序调用 http get,将 JWT 作为 Authorization 标头传递以通过 AWS Api 网关。
- 接收端的 lambda 函数对 JWT 进行解码并拉出附加到用户所属的 Cognito 组的 Role Arn。
在这组事件之后,我希望我对数据库调用的扫描会由于缺乏访问某些元素的权限而失败(稍后将使用查询而不是扫描,我只是想确保权限工作正常)。
但是扫描会继续从数据库中获取所有项目。
我一定是遗漏了一些简单的东西,这是我读到的用于执行此类操作的方法。
这是我们在 Lambda 函数中扮演的角色:
CognitoGroupRole:
Type: AWS::IAM::Role
Properties:
Description: Cognito Assets Group Role
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
AWS:
- !Sub 'arn:aws:iam::${AWS::AccountId}:root'
Action:
- 'sts:AssumeRole'
Policies:
- PolicyName: Database1AccessPolicy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- "dynamodb:Scan"
- "dynamodb:PutItem"
- "dynamodb:UpdateItem"
- "dynamodb:Query"
Resource: !GetAtt Database1.Arn
- PolicyName: Database2AccessPolicy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- "dynamodb:Query"
Resource: !GetAtt Database2.Arn
这是 Lambda 内部的函数,它承担角色并编写内联策略:
const assumeGroupRole = () => {
/* Get JWT from event.headers.Authorization */
const {
headers: { Authorization },
} = event;
/* Get the function name from context.functionName */
const { functionName } = context;
/* Decode the JWT */
const decodedToken = jwt_decode(Authorization);
const Policy = JSON.stringify({
Version: '2012-10-17',
Statement: {
Effect: 'Allow',
Action: ['dynamodb:Query', 'dynamodb:Scan'] /* Scan only for testing */,
Resource /* Device table ARN from environment variables */,
Condition: {
/* This condition *should* mean they can only access any row where the leading key is the AccountUniqueId */
'ForAllValues:StringEquals': {
'dynamodb:LeadingKeys': [decodedToken['custom:AccountUniqueId']],
},
},
},
});
console.info('Inline Policy', Policy);
/* ARN of the role attached to the cognito group */
const [RoleArn] = decodedToken['cognito:roles'];
/* Create session name from the email and function name */
const RoleSessionName = `${decodedToken.email}+${
functionName.split('-')[2]
}`;
return new Promise((resolve, reject) => {
sts.assumeRole({ RoleArn, RoleSessionName, Policy }, function (
err,
data,
) {
if (err) reject(console.error('Assume role error', err, err.stack));
else resolve(data);
});
});
};
我实际运行扫描的位置(在我得到这个工作后查询)以从 DynamoDB 中获取数据:
/* Create new DynamoDB Document client with Credentials from
assumeRole */
const docClient = new AWS.DynamoDB.DocumentClient({
accessKeyId: Credentials.AccessKeyId,
secretAccessKey: Credentials.SecretAccessKey,
sessionToken: Credentials.SessionToken,
});
const params = {
TableName,
};
try {
/* Query the database with the above parameters to fetch only the
items that match the conditions */
const { Items } = await docClient.scan(params).promise();
console.info('Queried Items', Items);
const statusCode = 200;
const body = JSON.stringify(Items);
logEvents(statusCode, body);
return {
statusCode,
body,
};
} catch (e) {
console.info('Error', e);
const statusCode = 400;
const body = JSON.stringify(e.message);
logEvents(statusCode, body);
return {
statusCode,
body,
};
}
【问题讨论】:
-
你实际在哪里运行查询,使用assumeRole返回的数据?
-
编辑了我的原始帖子以显示请求的信息。
-
如果你调用
sts:GetCallerIdentity,它会返回什么?它是什么 ARN/用户? -
可能是这样的,因为内联策略必须是主策略的子集。您的主要政策和内联政策的条件不同,因此内联政策可能会被忽略。我以前从未测试过它,但它可能值得检查。
标签: node.js aws-lambda amazon-cognito amazon-iam aws-sts