![](/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.