如何通过AWS SAM实现Lambda与Mongo Atlas Serverless的IAM角色连通
从AWS视角实现Lambda与MongoDB Atlas无密码认证的完整流程
核心概念澄清
你混淆了两个关键IAM角色:
- Atlas扮演角色:MongoDB Atlas用来验证AWS身份的角色,信任策略需允许MongoDB的AWS账号扮演
- Lambda执行角色:Lambda运行时使用的角色,信任策略必须允许AWS Lambda服务扮演,同时需具备扮演Atlas角色的权限
步骤1:创建Atlas专用的IAM扮演角色
这个角色用于MongoDB Atlas验证你的AWS身份,信任策略配置为允许指定的MongoDB AWS账号扮演,同时绑定Atlas控制台生成的External ID:
MongoDBAtlasAssumeRole: Type: AWS::IAM::Role Properties: RoleName: MongoDBAtlasAssumeRole AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: AWS: arn:aws:iam::<Atlas_AWS_Account_ID>:root Action: sts:AssumeRole Condition: StringEquals: sts:ExternalId: <你的Atlas配置的External_ID> # 无需额外权限,仅用于身份验证
步骤2:创建Lambda执行角色
这个角色是Lambda运行时的身份,必须允许Lambda服务扮演,同时添加权限让它能调用sts:AssumeRole获取Atlas角色的临时凭证:
LambdaMongoDBExecutionRole: Type: AWS::IAM::Role Properties: RoleName: LambdaMongoDBExecutionRole AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: lambda.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole # 日志权限,必填 Policies: - PolicyName: AllowAssumeMongoDBRole PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: sts:AssumeRole Resource: !GetAtt MongoDBAtlasAssumeRole.Arn
步骤3:绑定Lambda与执行角色
在SAM模板中给Lambda指定上面创建的执行角色,而非Atlas扮演角色:
StepPlanCRUD: Type: AWS::Serverless::Function Properties: PackageType: Image Architectures: - x86_64 Role: !GetAtt LambdaMongoDBExecutionRole.Arn
步骤4:修正Lambda代码逻辑
不要直接使用Lambda默认的临时凭证,需主动扮演Atlas角色获取专用凭证后再连接MongoDB:
import boto3 import os from pymongo import MongoClient def lambda_handler(event, context): # 初始化STS客户端 sts_client = boto3.client('sts') # 扮演Atlas专用角色 assumed_role = sts_client.assume_role( RoleArn=os.getenv("MONGODB_ATLAS_ROLE_ARN"), # 配置为Lambda环境变量 RoleSessionName="LambdaMongoDBAtlasSession", ExternalId=os.getenv("MONGODB_ATLAS_EXTERNAL_ID") # 配置为Lambda环境变量 ) # 提取临时凭证 access_key = assumed_role['Credentials']['AccessKeyId'] secret_key = assumed_role['Credentials']['SecretAccessKey'] session_token = assumed_role['Credentials']['SessionToken'] # 生成MongoDB连接串 server_name = os.getenv("MONGODB_SERVER_NAME") url_connection = f"mongodb+srv://{access_key}:{secret_key}@{server_name}.ozmat.mongodb.net/?authSource=%24external&authMechanism=MONGODB-AWS&retryWrites=true&w=majority&authMechanismProperties=AWS_SESSION_TOKEN:{session_token}" # 建立连接并执行操作 client = MongoClient(url_connection) # 后续业务逻辑...
步骤5:配置Lambda环境变量
在SAM模板或Lambda控制台添加以下环境变量:
MONGODB_ATLAS_ROLE_ARN:步骤1创建的MongoDBAtlasAssumeRole的ARNMONGODB_ATLAS_EXTERNAL_ID:Atlas控制台生成的External IDMONGODB_SERVER_NAME:你的MongoDB Atlas集群服务器前缀
你之前的错误分析
- 角色信任策略错误:将Lambda执行角色的信任策略配置为允许MongoDB账号扮演,导致Lambda无法假设该角色,触发
The role defined for the function cannot be assumed by Lambda错误 - 凭证使用错误:直接使用Lambda默认执行凭证而非Atlas专用角色凭证,导致Atlas识别到的是Lambda默认角色ARN,而非你在Atlas配置的角色,触发
user arn:aws:sts::...:assumed-role/<incorrect_role_name> is not found错误
内容的提问来源于stack exchange,提问作者user12672705
相关产品推荐
相关产品推荐

