如何通过NodeJS SDK让租户Lambda查询Control Tower根账号DynamoDB
跨账号访问DynamoDB的解决方案
绝对不要硬编码根账号的Access Key/Secret Key,这严重违反AWS安全最佳实践,正确的实现方式是通过IAM角色的跨账号信任关系来完成。以下是具体步骤:
步骤1:在Control Tower根账号创建跨账号访问角色
- 登录根账号IAM控制台,新建角色:
- 信任实体类型选择「另一个AWS账户」,填入租户账号ID
- 为角色添加权限策略,仅允许访问根账号的
Table_A,示例策略:{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "dynamodb:GetItem", "Resource": "arn:aws:dynamodb:【根账号区域】:【根账号ID】:table/Table_A" } ] } - 记录该角色的ARN,格式类似:
arn:aws:iam::【根账号ID】:role/AllowTenantAccessTableA
步骤2:给租户Lambda的执行角色添加权限
在租户账号IAM控制台,找到当前Lambda使用的执行角色,添加允许调用sts:AssumeRole的策略:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "sts:AssumeRole", "Resource": "arn:aws:iam::【根账号ID】:role/AllowTenantAccessTableA" } ] }
步骤3:修改Lambda代码实现跨账号访问
修改后的代码通过假定根账号角色获取临时凭证,再初始化对应DynamoDB客户端:
'use strict'; const AWS = require('aws-sdk'); const sts = new AWS.STS(); // 租户内的DynamoDB客户端(使用Lambda默认角色) const tenantDdbClient = new AWS.DynamoDB.DocumentClient(); // 根账号跨角色ARN const ROOT_ROLE_ARN = 'arn:aws:iam::【根账号ID】:role/AllowTenantAccessTableA'; module.exports.testDynamo = async event => { try { let result; let params; // 查询租户内的Table_B params = { TableName: 'Table_B', Key: { externalKey : 'CA6E03C' } }; result = await tenantDdbClient.get(params).promise(); console.log('🚀 租户Table_B查询结果 - ', result); // 假定根账号角色,获取临时凭证 const assumeRoleParams = { RoleArn: ROOT_ROLE_ARN, RoleSessionName: 'TenantAccessRootTableSession' // 自定义会话名,便于审计 }; const stsResp = await sts.assumeRole(assumeRoleParams).promise(); const rootCreds = stsResp.Credentials; // 初始化根账号的DynamoDB客户端 const rootDdbClient = new AWS.DynamoDB.DocumentClient({ accessKeyId: rootCreds.AccessKeyId, secretAccessKey: rootCreds.SecretAccessKey, sessionToken: rootCreds.SessionToken, region: '【根账号Table_A所在区域】' // 若与租户区域不同需指定 }); // 查询根账号内的Table_A params = { TableName: 'Table_A', Key: { externalKey : 'MAP_CA6E03C' } }; result = await rootDdbClient.get(params).promise(); console.log('🚀 根账号Table_A查询结果 - ', result); return { statusCode: 200, headers: { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Credentials': true }, body: JSON.stringify( { response: result }, // 修复原代码未定义的response变量 null, 2 ), }; } catch (error) { console.error('🚀 testDynamo - 错误栈:', error.stack); return { statusCode: 400, headers: { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Credentials': true }, body: JSON.stringify(error.stack) }; } };
关键注意点
- 临时凭证默认有效期1小时,最长可设置12小时,若Lambda执行时长接近上限需提前处理续期
- 确保根账号角色的信任策略仅包含目标租户账号ID,避免权限泄露
- 原代码中
response变量未定义,已替换为实际查询结果result
内容的提问来源于stack exchange,提问作者IgorAlves
相关产品推荐
相关产品推荐

