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
相关产品推荐
相关产品推荐

