【问题标题】:Cross-account IAM roles giving Service: Amazon S3; Status Code: 403; Error Code: AccessDenied跨账户 IAM 角色赋予服务:Amazon S3;状态码:403;错误代码:拒绝访问
【发布时间】:2022-12-11 15:51:45
【问题描述】:

您好,我正在尝试跨帐户移动文件,从存储桶帐户 S 到存储桶帐户,我收到以下错误

调用 o88.parquet 时出错。 dt/output1/parquet/_temporary/0/:在 dt/output1/parquet/_temporary/0/ 上放置 0 字节对象:com.amazonaws.services.s3.model.AmazonS3Exception:拒绝访问(服务:Amazon S3;状态代码: 403; Error Code: AccessDenied; Request ID: F99P5W0C8Q28BJ4R; S3 Extended Request ID: VpFGWR9JR7r2yae9v8ezB7HAgJu0uuwn4v3mBAG8CaaJ2q0+sOVFGdxsZ1GzMXhAifSCtdxJ0OM=; Proxy: null), S3 Extended Request ID: VpFGWR9JR7r2yae9v8ezB7HAgJu0uuwn4v3mBAG8CaaJ2q0+sOVFGdxsZ1GzMXhAifSCtdxJ0OM=:AccessDenied

我最后有以下设置。

账户 A 具有以下角色 cross-account-sample-role 和以下政策

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "s3:ListAllMyBuckets"
            ],
            "Effect": "Allow",
            "Resource": [
                "arn:aws:s3:::*"
            ]
        },
        {
            "Action": [
                "s3:ListBucket",
                "s3:GetBucketLocation"
            ],
            "Effect": "Allow",
            "Resource": "arn:aws:s3:::my-bucket"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:Get*",
                "s3:Put*",
                "s3:List*"
            ],
            "Resource": "arn:aws:s3:::my-bucket/*"
        }
    ]
}

账户A角色中的信任关系

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "s3.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        },
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::{accountBId}:role/{accountBrole}"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

账户 B 跨账户角色

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Resource": "arn:aws:iam::{accountAId}:role/{accountArole}"
        }
    ]
}

编辑账户 B 附加到角色的策略

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:*",
                "s3-object-lambda:*"
            ],
            "Resource": "*"
        }
    ]
}

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "glue:*",
                "s3:GetBucketLocation",
                "s3:ListBucket",
                "s3:ListAllMyBuckets",
                "s3:GetBucketAcl",
                "ec2:DescribeVpcEndpoints",
                "ec2:DescribeRouteTables",
                "ec2:CreateNetworkInterface",
                "ec2:DeleteNetworkInterface",
                "ec2:DescribeNetworkInterfaces",
                "ec2:DescribeSecurityGroups",
                "ec2:DescribeSubnets",
                "ec2:DescribeVpcAttribute",
                "iam:ListRolePolicies",
                "iam:GetRole",
                "iam:GetRolePolicy",
                "cloudwatch:PutMetricData"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:CreateBucket"
            ],
            "Resource": [
                "arn:aws:s3:::aws-glue-*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:PutObject",
                "s3:DeleteObject"
            ],
            "Resource": [
                "arn:aws:s3:::aws-glue-*/*",
                "arn:aws:s3:::*/*aws-glue-*/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:s3:::crawler-public*",
                "arn:aws:s3:::aws-glue-*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": [
                "arn:aws:logs:*:*:/aws-glue/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:CreateTags",
                "ec2:DeleteTags"
            ],
            "Condition": {
                "ForAllValues:StringEquals": {
                    "aws:TagKeys": [
                        "aws-glue-service-resource"
                    ]
                }
            },
            "Resource": [
                "arn:aws:ec2:*:*:network-interface/*",
                "arn:aws:ec2:*:*:security-group/*",
                "arn:aws:ec2:*:*:instance/*"
            ]
        }
    ]
}

几乎是多余的访问,但在这一点上我不再担心了。

【问题讨论】:

  • 那么,您有账户 B 凭据,您正在使用它们在账户 A 中担任角色,然后使用这些凭据尝试将对象从账户 A 拉到账户 B?您使用的凭据需要同时允许 GetObject 从 A 和 PutObject 到 B。假设的角色只有前者,如果我理解正确的话。
  • @jarmod,担任角色不足以从帐户 A 中提取对象吗?如果我授予 S3 对帐户 B 的完全访问权限,是否可以解决问题?
  • 您也可以结合使用源 IAM 策略和目标存储桶策略来执行此操作。看看How can I copy S3 objects from another AWS account? 是否有帮助。
  • 当您承担一个角色时,您将获得一组与该角色关联的专用凭证。这些凭据也没有原始权限。
  • 您使用哪个 IAM 角色执行复制?在执行从存储桶 A(账户 A)到存储桶 B(账户 B)的复制时,您将使用单个 IAM 角色来访问这两个存储桶,并且该角色应该有足够的权限来访问这两个存储桶。您能否添加您运行的确切命令,以及之前 aws sts get-caller-identity 的输出(它不包含敏感信息,您可以删除帐户 ID 并将它们替换为 AccountA 和 AccountB 以实现匿名)

标签: amazon-web-services amazon-s3


【解决方案1】:

所以这是我的发现,也许不是一个理想的解决方案,但这对我有用。

我认为 AWS 没有很好地解释这个问题,如果有这样的解释我不知道。对我有用的是创建一个从账户 A 承担角色的政策,现在如果你在下面看到我的政策,我正在从账户 A 承担角色。我的理解是,一旦我们承担了这个角色,我们不需要做任何事情,就会有是一个 API 调用(内部),它将为我访问存储桶,因为附加到我的 Glue 作业的角色正在承担帐户 A 的角色。你猜怎么着,这个假设对我不起作用。

我实际上要做的更多的是STS 也假设从我的代码中调用,它授予我临时凭据,我必须使用临时凭据更新底层 Hadoop 配置。注意截至目前如果Glue Job Role(在账户 B 中)没有 STS assume Role 能力,glue job 将会失败。感谢这篇文章STS assume Role API,我能够进行跨账户 S3 访问。我希望这可以节省某人 1 秒的时间。

import sys
from awsglue.transforms import *
from awsglue.utils import getResolvedOptions
from pyspark.context import SparkContext
from awsglue.context import GlueContext
from awsglue.job import Job
import boto3
   
sts_connection = boto3.client('sts')
response = sts_connection.assume_role(RoleArn='arn:aws:iam::account_id_here:role/my_role_assumed_from_accountA', RoleSessionName='GlueTenantASession',DurationSeconds=3600)
credentials = response['Credentials']
   
args = getResolvedOptions(sys.argv, ["JOB_NAME"])
sc = SparkContext()
sc._jsc.hadoopConfiguration().set('fs.s3a.aws.credentials.provider', 'org.apache.hadoop.fs.s3a.TemporaryAWSCredentialsProvider')
sc._jsc.hadoopConfiguration().set('fs.s3a.access.key', credentials['AccessKeyId'])
sc._jsc.hadoopConfiguration().set('fs.s3a.secret.key', credentials['SecretAccessKey'])
sc._jsc.hadoopConfiguration().set('fs.s3a.session.token', credentials['SessionToken'])
   
glueContext = GlueContext(sc)
spark = glueContext.spark_session
   
job = Job(glueContext)
job.init(args["JOB_NAME"], args)
   
# Script generated for node S3 bucket
data_frame = glueContext.create_dynamic_frame.from_options(
    format_options={"multiline": False},
    connection_type="s3",
    format="parquet",
    connection_options={"paths": ["s3a://path_to_bucket_in_other_account"]},
    transformation_ctx="S3bucket_node1",
)
data_frame.show()

我的内联政策从账户 A 担任角色

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Resource":"arn:aws:iam::account_id:role/my_role_assumed_from_accountA"
        }
    ]
}

【讨论】:

    猜你喜欢
    • 2023-02-21
    • 2022-12-30
    • 1970-01-01
    • 2021-12-13
    • 1970-01-01
    • 2020-06-24
    • 1970-01-01
    • 2016-01-18
    • 1970-01-01
    相关资源
    最近更新 更多