簡體   English   中英

無法從 Fargate 容器內訪問 S3 存儲桶(錯誤請求且無法找到憑據)

[英]Can't access S3 bucket from within Fargate container (Bad Request and unable to locate credentials)

我使用一個簡單的任務創建了一個私有 s3 存儲桶和一個 fargate 集群,該任務嘗試使用python 3boto3從該存儲桶中讀取數據。 我已經在 2 個不同的 docker 圖像上嘗試過這個,在一個圖像上我從 boto 得到一個ClientErrorHeadObject 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()

無論我做什么,我都無法使用boto3Fargate容器任務中訪問 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 Fargate 任務未應用角色

經過無數小時的挖掘這個參數終於為我解決了這個問題:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM