本地Python代码访问S3遇权限拒绝,AWS控制台Lambda运行正常问题排查
AWS Lambda本地运行S3访问权限问题解答
问题描述
我是Python和AWS Lambda的新手,已在AWS控制台创建了一段Lambda函数代码(如下),该函数可列出S3桶demo-bucket内的文件,通过控制台测试完全正常。但在本地运行类似Python代码时,调用ListObjects操作出现botocore.exceptions.ClientError: An error occurred (AccessDenied) when calling the ListObjects operation: Access Denied错误。本地代码会先获取指定Lambda函数的配置,再访问S3桶demo-bucket,请问为何本地运行会出错?我哪里操作有误?
控制台Lambda函数代码
import boto3 import json def lambda_handler(event, context): s3 = boto3.resource('s3') bucket = s3.Bucket('demo-bucket') for file in bucket.objects.all(): print(file.key, file.last_modified) return { "statusCode": 200, "body": json.dumps('Hello from Lambda!') }
本地Python代码
import boto3 import json import os def lambda_handler(): lambda_client = boto3.client('lambda') role_response = (lambda_client.get_function_configuration( FunctionName = os.environ['LAMBDA_FUNCTION']) ) print(role_response['Role']) s3 = boto3.resource('s3') bucket = s3.Bucket('demo-bucket') for file in bucket.objects.all(): print(file.key, file.last_modified) return { "statusCode": 200, "body": json.dumps('Hello from Lambda!') } lambda_handler()
注:
FunctionName = os.environ['LAMBDA_FUNCTION']指定的是控制台中测试正常的Lambda函数。
原因及解决方法
核心原因
- 权限上下文不一致:控制台的Lambda函数运行时,使用的是你为该Lambda配置的IAM角色权限,这个角色已经被授予访问
demo-bucket的权限。而本地运行Python代码时,boto3会读取你本地环境的AWS凭证(比如~/.aws/credentials文件中的密钥、系统环境变量里的AWS密钥对,或者AWS CLI默认配置的用户),这些本地凭证没有被赋予访问demo-bucket的ListObjects权限,因此触发AccessDenied错误。 - 获取角色≠使用角色权限:你本地代码中只是调用
get_function_configuration拿到了Lambda角色的ARN,但这仅仅是获取角色的元数据,并没有让本地代码切换到该角色下运行。boto3不会自动使用这个角色的权限,仍然沿用本地默认凭证的权限。
解决方法
方法一:给本地凭证添加S3访问权限
在AWS IAM控制台找到你本地使用的AWS用户(即本地凭证对应的用户),创建并附加一条权限策略,允许该用户对demo-bucket执行s3:ListBucket操作。示例策略如下:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "s3:ListBucket", "Resource": "arn:aws:s3:::demo-bucket" } ] }
方法二:临时切换到Lambda的IAM角色运行
使用AWS STS的assume_roleAPI,让本地代码临时获取Lambda角色的临时凭证,再用这些凭证初始化S3客户端。修改后的本地代码示例如下:
import boto3 import json import os def lambda_handler(): lambda_client = boto3.client('lambda') role_response = lambda_client.get_function_configuration( FunctionName = os.environ['LAMBDA_FUNCTION'] ) role_arn = role_response['Role'] # 获取Lambda角色的临时凭证 sts_client = boto3.client('sts') assumed_role = sts_client.assume_role( RoleArn=role_arn, RoleSessionName='LocalLambdaSession' ) # 使用临时凭证初始化S3资源 s3 = boto3.resource( 's3', aws_access_key_id=assumed_role['Credentials']['AccessKeyId'], aws_secret_access_key=assumed_role['Credentials']['SecretAccessKey'], aws_session_token=assumed_role['Credentials']['SessionToken'] ) bucket = s3.Bucket('demo-bucket') for file in bucket.objects.all(): print(file.key, file.last_modified) return { "statusCode": 200, "body": json.dumps('Hello from Lambda!') } lambda_handler()
注意:使用此方法需要满足两个条件:
- 本地的AWS凭证拥有
sts:AssumeRole权限;- Lambda的IAM角色信任策略中,添加允许本地用户/角色进行角色切换的规则。
内容的提问来源于stack exchange,提问作者Metro
相关产品推荐
相关产品推荐

