![](/img/trans.png)
[英]Can I get information on an S3 Bucket's public access bucket Settings from boto3?
[英]Can't access S3 bucket from within Fargate container (Bad Request and unable to locate credentials)
我使用一个简单的任务创建了一个私有 s3 存储桶和一个 fargate 集群,该任务尝试使用python 3
和boto3
从该存储桶中读取数据。 我已经在 2 个不同的 docker 图像上尝试过这个,在一个图像上我从 boto 得到一个ClientError
说HeadObject Bad request (400)
和另一个我得到NoCredentialsError: Unable to locate credentials
。
图像中唯一真正不同的是,一个说错误请求正在正常运行,另一个是由我通过 ssh 手动运行到任务容器。 所以我不确定为什么一张图片说“请求错误”而另一张图片说“无法找到凭据”。
我尝试了几种不同的 IAM 策略,包括 ( terraform
) 以下策略:
data "aws_iam_policy_document" "access_s3" {
statement {
effect = "Allow"
actions = ["s3:ListBucket"]
resources = ["arn:aws:s3:::bucket_name"]
}
statement {
effect = "Allow"
actions = [
"s3:GetObject",
"s3:GetObjectVersion",
"s3:GetObjectTagging",
"s3:GetObjectVersionTagging",
]
resources = ["arn:aws:s3:::bucket_name/*"]
}
}
第二次尝试:
data "aws_iam_policy_document" "access_s3" {
statement {
effect = "Allow"
actions = ["s3:*"]
resources = ["arn:aws:s3:::*"]
}
}
我尝试的最后一个是内置策略:
resource "aws_iam_role_policy_attachment" "access_s3" {
role = "${aws_iam_role.ecstasks.name}"
policy_arn = "arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess"
}
桶定义非常简单:
resource "aws_s3_bucket" "bucket" {
bucket = "${var.bucket_name}"
acl = "private"
region = "${var.region}"
}
用于访问 s3 存储桶的代码:
try:
s3 = boto3.client('s3')
tags = s3.head_object(Bucket='bucket_name', Key='filename')
print(tags['ResponseMetadata']['HTTPHeaders']['etag'])
except ClientError:
traceback.print_exc()
无论我做什么,我都无法使用boto3
从Fargate
容器任务中访问 AWS 资源。 我能够在EC2
实例上使用boto3
访问相同的 s3 存储桶,而无需提供任何类型的凭据并且仅使用 IAM 角色/策略。 我究竟做错了什么? 从 Fargate 容器以同样的方式访问 AWS 资源是不可能的吗?
忘记提及我正在将 IAM 角色分配给任务定义执行策略和任务策略。
更新:事实证明,我遇到的unable to find credentials
错误是一个转移注意力的问题。 我无法获取凭据的原因是因为我的直接 ssh session 没有设置AWS_CONTAINER_CREDENTIALS_RELATIVE_URI
环境变量。
AWS Fargate 将代表您注入一个名为AWS_CONTAINER_CREDENTIALS_RELATIVE_URI
的环境变量,其中包含 url 到 boto 应该用于获取 API 访问凭证的内容。 所以Bad request
错误是我实际遇到的错误,需要帮助解决。 我检查了容器内的环境变量,Fargate 正在设置AWS_CONTAINER_CREDENTIALS_RELATIVE_URI
值。
我在这个问题上苦苦挣扎,并不断将AWS_CONTAINER_CREDENTIALS_RELATIVE_URI
错误地设置为None
,直到我在当前任务执行角色之外添加了自定义任务角色。
1)任务执行角色负责访问 ECR 中的容器并授予运行任务本身的访问权限,而2)任务角色负责您的 docker 容器向其他授权的 AWS 服务发出 API 请求。
1) 对于我的任务执行角色,我使用AmazonECSTaskExecutionRolePolicy
和以下 JSON;
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ecr:GetAuthorizationToken",
"ecr:BatchCheckLayerAvailability",
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "*"
}
]
}
2)我终于摆脱了NoCredentialsError: Unable to locate credentials
当我在任务执行角色之外添加了一个任务角色时,例如负责从某个bucket中读取;
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": "arn:aws:s3:::bucket_name/*"
}
]
}
总之; 确保两者都有一个角色,用于1) executionRoleArn用于访问以运行任务和2) taskRoleArn用于访问以向任务定义中设置的授权 AWS 服务发出 API 请求。
允许对您的容器实例角色进行 Amazon S3 只读访问
在https://console.aws.amazon.com/iam/打开 IAM 控制台。
在导航窗格中,选择角色。
选择要用于您的容器实例的 IAM 角色(此角色可能名为 ecsInstanceRole)。 有关更多信息,请参阅 Amazon ECS 容器实例 IAM 角色。
在托管策略下,选择附加策略。
在附加策略页面上,对于过滤器,键入 S3 以缩小策略结果的范围。
选中 AmazonS3ReadOnlyAccess 策略左侧的框,然后选择附加策略。
您应该需要一个 IAM 角色才能从您的 ecs-task 访问您的 S3 存储桶。
resource "aws_iam_role" "AmazonS3ServiceForECSTask" {
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": [
"ecs-tasks.amazonaws.com"
]
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
data "aws_iam_policy_document" "bucket_policy" {
statement {
principals {
type = "AWS"
identifiers = [aws_iam_role.AmazonS3ServiceForECSTask.arn]
}
actions = [
"s3:ListBucket",
]
resources = [
"arn:aws:s3:::${var.your_bucket_name}",
]
}
statement {
principals {
type = "AWS"
identifiers = [aws_iam_role.AmazonS3ServiceForECSTask.arn]
}
actions = [
"s3:GetObject",
]
resources = [
"arn:aws:s3:::${var.your_bucket_name}/*",
]
}
}
您应该需要在任务定义的task_role_arn中添加您的 IAM 角色。
resource "aws_ecs_task_definition" "_ecs_task_definition" {
task_role_arn = aws_iam_role.AmazonS3ServiceForECSTask.arn
execution_role_arn = aws_iam_role.ECS-TaskExecution.arn
family = "${var.family}"
network_mode = var.network_mode[var.launch_type]
requires_compatibilities = var.requires_compatibilities
cpu = var.task_cpu[terraform.workspace]
memory = var.task_memory[terraform.workspace]
container_definitions = module.ecs-container-definition.json
}
经过无数小时的挖掘这个参数终于为我解决了这个问题:
ecs服务上的 a.network_configuration 块内的auto_assign_public_ip = true 。
事实证明,这些服务运行的我的任务没有分配 IP,因此与外界没有联系。
Boto3 有一个凭证查找路线:https ://boto3.readthedocs.io/en/latest/guide/configuration.html。 当您使用 AWS 提供的映像创建 EC2 实例时,该实例会预安装 aws 命令和其他 AWS 凭证环境变量。 但是,Fargate 只是一个容器。 您需要手动将 AWS 凭证注入容器。 一种快速解决方案是将 AWS_ACCESS_KEY_ID 和 AWS_SECRET_ACCESS_KEY 添加到 fargate 容器。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.