如何利用Cognito自定义属性限制API Gateway触发的Lambda资源访问权限
问题描述
我有一个基于Cognito用户池的应用,用户池包含名为Tenant的自定义属性。我希望通过该属性控制用户对所属租户的DynamoDB表的访问权限,确保用户仅能访问其租户对应的表。
我的应用调用API Gateway资源,再由API Gateway触发Lambda向DynamoDB表发起PutItem请求。我尝试通过Principal标签实现该需求:在用户池关联的身份池的身份提供商中配置属性映射,但发现当API Gateway调用Lambda时,Lambda无法获取调用会话中的Principal标签值,导致该方案不可行。
我在Lambda的权限策略中添加了如下验证条件作为概念验证,但触发了未授权错误,推测是上述限制导致的:
"Condition": { "StringEquals": { "aws:PrincipalTag/TenantValue": "myTenantValue" } }
请问该用例是否可行?如何基于调用API Gateway的Cognito用户属性,限制API触发的Lambda的访问权限?
解决方案
这个用例完全可行,核心是让Lambda获取到用户的Tenant属性,并以此为依据实现DynamoDB访问隔离。以下是几种实用的实现方案:
方案1:Lambda内部逻辑直接控制(简单易实现)
- 配置API Gateway使用Lambda代理集成,这样API Gateway会将包含Cognito用户信息的完整
event对象传递给Lambda。 - 在Lambda代码中,从
event.requestContext.authorizer.claims中提取用户的自定义Tenant属性(注意Cognito自定义属性的键名格式为custom:Tenant)。 - 根据获取到的
Tenant值构造目标DynamoDB表名(例如Tenant-${TenantValue}),然后发起PutItem请求,确保仅访问用户所属租户的表。 - 这种方式无需依赖IAM复杂配置,直接在业务层实现隔离,适合快速落地。
方案2:IAM策略结合身份标签实现细粒度控制
- 首先在Cognito身份池的身份提供商设置中,将用户池的
custom:Tenant属性映射到身份池的Tenant标签(映射时保持键名一致)。 - 配置API Gateway使用Cognito用户池授权,并在集成请求中开启传递身份上下文,确保Lambda执行时能获取到身份池的标签信息。
- 为Lambda的执行角色配置DynamoDB权限策略,使用
aws:PrincipalTag条件键限制访问:{ "Effect": "Allow", "Action": "dynamodb:PutItem", "Resource": "arn:aws:dynamodb:你的区域:你的账号ID:table/*", "Condition": { "StringEquals": { "dynamodb:LeadingKeys": "${aws:PrincipalTag/Tenant}" } } } - 这里的
dynamodb:LeadingKeys要求DynamoDB表的分区键值与用户的Tenant标签一致,确保用户只能操作自己租户的数据。
方案3:Cognito用户组+IAM角色映射(适合多租户规模化场景)
- 为每个租户创建一个Cognito用户组,将对应租户的用户分配到该组。
- 为每个租户组创建专属IAM角色,该角色的权限策略仅允许访问对应租户的DynamoDB表。
- 在Cognito身份池设置中,将用户组映射到对应的IAM角色,用户登录后会自动获取所属租户的角色权限,Lambda执行时继承该角色权限,自动实现租户隔离。
内容的提问来源于stack exchange,提问作者RupturingFarms
相关产品推荐
相关产品推荐

