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

API Gateway IAM认证下,Lambda如何扮演Cognito Identity角色?

解决方案:让Lambda使用Cognito Identity角色实现用户级权限

针对你的两个需求,以下是具体实现方案:

1. 直接让Lambda以Cognito Identity角色执行?不行,但有替代方案

Lambda本身只能使用配置的执行角色运行,无法直接切换为调用API的Cognito Identity用户角色。但可以通过在Lambda内部临时扮演用户角色的方式,间接实现用用户权限访问资源——这也是你第二个需求的核心解决路径。

2. 在Lambda内扮演Cognito Identity角色的具体步骤

前提准备

  • 确保你的Cognito Identity池已配置好认证用户角色和未认证用户角色,默认配置的角色信任策略已经包含Cognito服务主体,无需额外修改。
  • 给Lambda的执行角色添加权限,允许调用sts:AssumeRoleWithWebIdentity,目标为Identity池的两个角色ARN。示例策略:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Resource": [
        "arn:aws:iam::ACCOUNT_ID:role/Cognito_AuthenticatedRole",
        "arn:aws:iam::ACCOUNT_ID:role/Cognito_UnauthenticatedRole"
      ]
    }
  ]
}

关键步骤:传递Web Identity Token到Lambda

客户端调用你的HTTP API时,除了用从Identity池获取的临时IAM凭证签名请求外,还需要将Web Identity Token(比如Cognito User Pool的ID Token,或第三方身份提供商的令牌)放在自定义请求头中(例如X-Web-Identity-Token)。这个令牌是用户身份的核心凭证,用于STS扮演角色。

Lambda内的代码实现

在Lambda中,你可以从请求头提取令牌,然后调用STS的AssumeRoleWithWebIdentity接口获取用户角色的临时凭证,再用这些凭证访问S3/DynamoDB等资源。示例Python代码:

import boto3

def lambda_handler(event, context):
    # 从请求头获取Web Identity Token
    web_identity_token = event['headers'].get('X-Web-Identity-Token')
    if not web_identity_token:
        return {'statusCode': 400, 'body': 'Missing web identity token'}
    
    # 根据用户认证状态确定要扮演的角色ARN
    cognito_auth_provider = event['requestContext']['identity'].get('cognitoAuthenticationProvider')
    role_arn = (
        'arn:aws:iam::ACCOUNT_ID:role/Cognito_AuthenticatedRole'
        if cognito_auth_provider
        else 'arn:aws:iam::ACCOUNT_ID:role/Cognito_UnauthenticatedRole'
    )
    
    # 调用STS获取用户角色凭证
    sts_client = boto3.client('sts')
    try:
        response = sts_client.assume_role_with_web_identity(
            RoleArn=role_arn,
            RoleSessionName=event['requestContext']['identity']['cognitoIdentityId'],
            WebIdentityToken=web_identity_token
        )
        user_credentials = response['Credentials']
    except Exception as e:
        return {'statusCode': 500, 'body': f'Failed to assume role: {str(e)}'}
    
    # 使用用户凭证访问资源(示例:S3)
    s3_client = boto3.client(
        's3',
        aws_access_key_id=user_credentials['AccessKeyId'],
        aws_secret_access_key=user_credentials['SecretAccessKey'],
        aws_session_token=user_credentials['SessionToken']
    )
    # 仅访问用户专属前缀下的S3对象
    s3_response = s3_client.list_objects_v2(
        Bucket='YOUR_BUCKET', 
        Prefix=f"user/{event['requestContext']['identity']['cognitoIdentityId']}/"
    )
    
    return {'statusCode': 200, 'body': str(s3_response)}

补充说明

  • HTTP API Gateway支持未认证用户:只要客户端从Cognito Identity池获取未认证用户的临时IAM凭证,就能调用启用IAM认证的HTTP API。Lambda会在event['requestContext']['identity']中拿到用户的cognitoIdentityId,且cognitoAuthenticationProvider为空,以此区分未认证用户。
  • 用户级权限控制:在Cognito Identity池的角色策略中,使用${cognito-identity.amazonaws.com:sub}变量限定资源访问范围,比如S3的前缀策略:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:*",
      "Resource": "arn:aws:s3:::YOUR_BUCKET/user/${cognito-identity.amazonaws.com:sub}/*"
    }
  ]
}

这样用户只能访问自己前缀下的S3对象,无需给Lambda赋予全桶权限。

内容的提问来源于stack exchange,提问作者drone-ah

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 06:20:54