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

跨组织Lambda实现S3传输权限问题排查求助

跨组织Lambda传输

源组织的CloudWatch运行正常,但Lambda执行s3_assumed.copy_object命令时失败。目标组织的假定角色权限已通过文末测试Lambda验证无问题。

问题出在复制过程中假定身份无法访问源文件。已尝试配置源存储桶策略,但无效;也试过在源账号为目标账号添加信任策略,同样未解决。

源账号配置

S3存储桶

存储桶ARN:arn:aws:s3:::test-lambda-transfer
已为下方Lambda函数配置PUT和POST事件通知。

策略(部分内容非必需,用于排查权限问题):

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowLambdaGetObject",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::<source-account-id>:role/s3-cross-org-transfer-role"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::test-lambda-transfer/*"
        },
        {
            "Sid": "AllowLambdaListBucket",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::<source-account-id>:role/s3-cross-org-transfer-role"
            },
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::test-lambda-transfer"
        },
        {
            "Sid": "AllowAssumedRoleGetObject",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::<destination-account-id>:role/test-cross-org-transfer-role"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::test-lambda-transfer/*"
        }
    ]
}

Lambda函数

Lambda ARN:arn:aws:lambda:us-east-1::<source-account-id>:function:cross-account-s3-transfer
权限角色:arn:aws:iam::<source-account-id>:role/s3-cross-org-transfer-role
角色策略:arn:aws:iam::<source-account-id>:policy/s3-transfer-execution-policy

import boto3
import urllib.parse
import logging

# 初始化日志
logger = logging.getLogger()
logger.setLevel(logging.INFO)

def lambda_handler(event, context):
    sts_client = boto3.client('sts')
    destination_bucket = 's3-transfer-test-receiver-bucket'
    role_to_assume_arn = 'arn:aws:iam::<destination-account-id>:role/test-cross-org-transfer-role'

    try:
        for record in event['Records']:
            source_bucket = record['s3']['bucket']['name']
            key = urllib.parse.unquote_plus(record['s3']['object']['key'])
            logger.info(f"检测到新对象: {key},位于存储桶 {source_bucket}")

            # 尝试从源存储桶获取对象元数据
            s3_source = boto3.client('s3')
            try:
                response = s3_source.head_object(Bucket=source_bucket, Key=key)
                logger.info(f"成功获取 {key} 在 {source_bucket} 的元数据")
            except Exception as e:
                logger.error(f"获取 {key} 在 {source_bucket} 的元数据失败: {str(e)}")
                raise e

            logger.info("正在扮演目标角色...")
            assumed_role = sts_client.assume_role(RoleArn=role_to_assume_arn, RoleSessionName="S3CopySession")
            logger.info(f"已扮演角色ARN: {assumed_role['AssumedRoleUser']['Arn']}")

            credentials = assumed_role['Credentials']
            s3_assumed = boto3.client('s3',
                                      aws_access_key_id=credentials['AccessKeyId'],
                                      aws_secret_access_key=credentials['SecretAccessKey'],
                                      aws_session_token=credentials['SessionToken'])

            copy_source = {'Bucket': source_bucket, 'Key': key}
            logger.info(f"正在复制 {key} 从 {source_bucket} 到 {destination_bucket}")
            s3_assumed.copy_object(Bucket=destination_bucket, Key=key, CopySource=copy_source)
            logger.info(f"成功复制 {key} 到 {destination_bucket}")

    except Exception as e:
        logger.error(f"复制操作失败: {str(e)}")
        raise e

Lambda函数策略

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::test-lambda-transfer",
                "arn:aws:s3:::test-lambda-transfer/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": "arn:aws:logs:*:*:*"
        },
        {
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Resource": "arn:aws:iam::<destination-account-id>:role/test-cross-org-transfer-role"
        }
    ]
}

目标账号配置

S3存储桶

存储桶ARN:arn:aws:s3:::s3-transfer-test-receiver-bucket

IAM配置

角色:arn:aws:iam::<destination-account-id>:role/test-cross-org-transfer-role
策略:arn:aws:iam::<destination-account-id>:policy/put-object-s3-cross-account-test-policy

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::s3-transfer-test-receiver-bucket/*"
        }
    ]
}

信任关系 - 可信实体:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "lambda.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        },
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::<source-account-id>:role/s3-cross-org-transfer-role",
                    "arn:aws:iam::<destination-account-id>:role/test-cross-org-transfer-role"
                ]
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

测试

可正常运行的Python Lambda测试代码

import boto3
import logging

# 配置日志
logger = logging.getLogger()
logger.setLevel(logging.INFO)

def lambda_handler(event, context):
    try:
        sts_client = boto3.client('sts')
        logger.info("正在扮演目标角色...")
        assumed_role = sts_client.assume_role(
            RoleArn="arn:aws:iam::<destination-account-id>:role/test-cross-org-transfer-role",
            RoleSessionName="CrossAccountSession"
        )
        logger.info(f"已扮演角色ARN: {assumed_role['AssumedRoleUser']['Arn']}")
        logger.info("角色扮演成功")

        credentials = assumed_role['Credentials']
        s3 = boto3.client(
            's3',
            aws_access_key_id=credentials['AccessKeyId'],
            aws_secret_access_key=credentials['SecretAccessKey'],
            aws_session_token=credentials['SessionToken'],
        )

        destination_bucket = 's3-transfer-test-receiver-bucket'

        # 尝试直接上传一个测试对象
        test_key = 'test-object.txt'
        test_body = '这是一个测试对象。'
        logger.info(f"正在直接上传测试对象到 {destination_bucket}...")
        s3.put_object(Bucket=destination_bucket, Key=test_key, Body=test_body)
        logger.info("直接上传成功")

    except Exception as e:
        logger.error(f"直接上传操作失败: {e}")
        raise e

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 03:14:52