You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

通过API Gateway+Lambda访问DynamoDB时如何配置Fine-Grained Access Control?

问题解答

疑问1:用户不直接访问DynamoDB时,是否无法使用Fine-Grained Access Control?

完全可以使用细粒度访问控制,只是你的访问路径是通过Lambda代理,不能直接套用用户直连DynamoDB的配置方案,需要调整身份传递和权限配置的逻辑。

疑问2:若可以使用,遗漏了哪些配置?

你遗漏了3个核心配置环节:

  • Lambda执行角色的权限逻辑错误:EndUser-Role的策略是针对Cognito身份池用户的,Lambda直接用该角色执行时,身份是Lambda的假设角色ARN,而非用户的Cognito身份,导致策略中的条件判断不通过
  • 未将用户的Cognito身份信息正确传递到Lambda并用于DynamoDB请求校验
  • 策略中的条件配置未匹配Lambda代理访问的场景

具体解决方案(两种可选方案)

方案一:基于IAM细粒度权限+Cognito临时凭证(推荐,符合最小权限原则)

该方案让Lambda使用用户的Cognito身份获取临时凭证访问DynamoDB,确保权限严格绑定到终端用户:

1. 修正EndUser-Role的IAM策略

移除多余的ForAllValues:前缀(仅需匹配单个用户sub),并添加临时凭证相关权限:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "dynamodb:GetItem",
                "dynamodb:PutItem",
                "dynamodb:Query"
            ],
            "Resource": "arn:aws:dynamodb:us-west-2:123456789111:table/lists",
            "Condition": {
                "StringEquals": {
                    "dynamodb:LeadingKeys": "${cognito-identity.amazonaws.com:sub}"
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Resource": "arn:aws:iam::123456789111:role/EndUser-Role"
        }
    ]
}

2. 配置API Gateway传递用户身份

在API Gateway的Cognito Authorizer设置中:

  • 勾选「Invoke with caller credentials」,确保用户的sub(Cognito唯一标识)和identityId(身份池ID)被传递到Lambda事件中
  • 或通过集成请求的映射模板,将$context.authorizer.claims.sub写入Lambda的输入事件

3. 修改Lambda代码,使用用户身份访问DynamoDB

在Lambda中通过Cognito身份池获取用户临时凭证,再初始化DynamoDB客户端:

import boto3
from botocore.credentials import Credentials

def lambda_handler(event, context):
    # 从API Gateway上下文提取用户身份信息
    user_sub = event['requestContext']['authorizer']['claims']['sub']
    identity_id = event['requestContext']['authorizer']['claims']['cognito:identity_id']
    
    # 获取用户临时凭证
    cognito_identity = boto3.client('cognito-identity')
    cred_response = cognito_identity.get_credentials_for_identity(IdentityId=identity_id)
    temp_creds = Credentials(
        access_key=cred_response['Credentials']['AccessKeyId'],
        secret_key=cred_response['Credentials']['SecretKey'],
        token=cred_response['Credentials']['SessionToken']
    )
    
    # 使用用户凭证操作DynamoDB
    dynamodb = boto3.client('dynamodb', credentials=temp_creds, region_name='us-west-2')
    list_name = event['queryStringParameters']['listName']
    
    try:
        db_response = dynamodb.get_item(
            TableName='lists',
            Key={'userId': {'S': user_sub}, 'listName': {'S': list_name}}
        )
        return {'statusCode': 200, 'body': db_response.get('Item', {})}
    except Exception as e:
        return {'statusCode': 500, 'body': str(e)}

4. 配置Lambda执行角色权限

给Lambda执行角色添加cognito-identity:GetCredentialsForIdentity权限,无需直接配置DynamoDB权限(操作权限由用户临时凭证提供)。


方案二:应用层数据过滤(简单易实现,依赖代码逻辑)

若不想使用临时凭证,可在Lambda代码中强制过滤用户数据,同时限制Lambda的DynamoDB权限:

1. 配置Lambda执行角色的IAM策略

给Lambda执行角色配置最小DynamoDB权限:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "dynamodb:GetItem",
                "dynamodb:PutItem",
                "dynamodb:Query"
            ],
            "Resource": "arn:aws:dynamodb:us-west-2:123456789111:table/lists"
        }
    ]
}

2. 修改Lambda代码,强制过滤用户数据

在代码中提取用户sub,仅查询当前用户的数据:

import boto3

dynamodb = boto3.resource('dynamodb', region_name='us-west-2')
table = dynamodb.Table('lists')

def lambda_handler(event, context):
    user_sub = event['requestContext']['authorizer']['claims']['sub']
    list_name = event['queryStringParameters']['listName']
    
    try:
        response = table.get_item(
            Key={'userId': user_sub, 'listName': list_name}
        )
        return {'statusCode': 200, 'body': response.get('Item', {})}
    except Exception as e:
        return {'statusCode': 500, 'body': str(e)}

502错误原因说明

当你将Lambda执行角色换成EndUser-Role时,权限被拒绝的核心原因是:
策略中的${cognito-identity.amazonaws.com:sub}是Cognito身份池用户的专属变量,但Lambda执行时使用的是角色ARN(arn:aws:sts::123456789111:assumed-role/EndUser-role/list-lambda),该身份没有cognito-identity.amazonaws.com:sub属性,导致IAM条件判断不通过,最终拒绝访问请求。

内容的提问来源于stack exchange,提问作者thedeepfield

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 09:57:22