アクセス権限

バケットの所有者とオブジェクトの所有者が違う場合に、オブジェクトの権限をバケットポリシーに合わせたい

やりたいこと

  • AWSアカウントA(以降A)が作成したバケットに、AWSアカウントB(以降B)がオブジェクトのPUTをする
  • オブジェクトの閲覧は、Aが所有するCloudFrontからのみ許可したい

バケットポリシーはこんな感じでやろうとした(これは正しく動かない)

data "aws_iam_policy_document" "this" {
  statement {
    effect = "Allow"

    principals {
      type = "AWS"

      // AWSアカウントBのfargateのロールに書き込みを許可する
      identifiers = [
        "arn:aws:iam::${var.AWS_ACCOUNT_B}:role/fargate-test-rails-app",
      ]
    }

    actions = [
      "s3:PutObject",
    ]

    resources = [
      "arn:aws:s3:::<TEST_BUCKET>/*"
    ]
  }

  // cloudfrontのOAIにGetを許可する
  // これだけでは実際にアクセスしてもAccess Denyになる!!!!
  statement {
    effect = "Allow"

    principals {
      type = "AWS"
      identifiers = [
        aws_cloudfront_origin_access_identity.this.iam_arn
      ]
    }

    actions = [
      "s3:GetObject",
    ]

    resources = [
      "arn:aws:s3:::<TEST_BUCKET>/*"
    ]
  }

}

色んな情報

バケットポリシーがアクセスを許可する場合、S3 バケットを所有する AWS アカウントもオブジェクトを所有する必要がある

https://aws.amazon.com/jp/premiumsupport/knowledge-center/s3-rest-api-cloudfront-error-403/

今回はオブジェクトの所有者がBだからこの問題が発生していた。

  1. オブジェクトにバケットオーナーへのフルアクセス権限を付与する
  2. オブジェクトを同名でcpする
  3. cpしたアカウントが所有者になるため、Aが所有者となる

これで所有者を変更すれば解決するが、都度cpが発生するので毎回変更するのはつらくないか‥?

バケットポリシーでBにPutObjectを許可する際に、bucket-owner-full-control が設定されている場合にのみ許可することができる

https://aws.amazon.com/jp/premiumsupport/knowledge-center/s3-require-object-ownership/

これでは所有者は変わらず、CloudFrontからのアクセスはできなかった。
今回はRails(Carrierwave/fog)からのアクセスを想定しているため、アップロード時にaclの設定ができるのかが気になっている(まだ調べきれていない)

AssumeRoleを付与する

これで解決した。よくあることだったらしい…
https://dev.classmethod.jp/etc/sugano-005-s3/

解決方法

バケットポリシーではCloudFrontからのアクセス権限のみ残し、Put権限は剥がす

data "aws_iam_policy_document" "this" {
  // put権限はバケットポリシーから削除し、Get権限だけ残す
  // cloudfrontのOAIにGetを許可する
  statement {
    effect = "Allow"

    principals {
      type = "AWS"
      identifiers = [
        aws_cloudfront_origin_access_identity.this.iam_arn
      ]
    }

    actions = [
      "s3:GetObject",
    ]

    resources = [
      "arn:aws:s3:::<TEST_BUCKET>/*"
    ]
  }
}

iam roleを作成し、AssumeRoleを付与する
今回はECSからのassumeを許可する

resource "aws_iam_role" "put-bucket" {
  name               = "put-bucket"
  assume_role_policy = data.aws_iam_policy_document.put-bucket-assume-.json
}

data "aws_iam_policy_document" "put-bucket-assume" {
  statement {
    effect  = "Allow"
    actions = ["sts:AssumeRole"]

    principals {
      type        = "Service"
      identifiers = ["ec2.amazonaws.com"]
    }
  }
}

iamポリシーをアタッチする
アカウントBのfargateに対しての許可と明示する

resource "aws_iam_role_policy" "put-bucket" {
  policy = data.aws_iam_policy_document.put-bucket.json
  role   = aws_iam_role.put-residency-certificates.id
}

data "aws_iam_policy_document" "put-bucket" {
  // fargate-test-rails-appからのassumeを許可
  statement {
    actions = [
      "sts:AssumeRole",
    ]

    resources = [
      "arn:aws:iam::${var.AWS_ACCOUNT_B}:role/fargate-test-rails-app",
    ]
  }

  statement {
    effect = "Allow"

    actions = [
      "s3:PutObject",
    ]

    resources = [
      "arn:aws:s3:::<TEST_BUCKET>/*"
    ]
  }
}

アカウントBのfargateに付与しているiam roleに対してiamポリシーをアタッチする アカウントAで作ったroleを指定する

resource "aws_iam_role_policy" "put-account-a-bucket" {
  name = "put-account-a-bucket"
  role = module.fargate-test-rails-app.iam_role_name

  policy = data.aws_iam_policy_document.put-account-a-bucket.json
}

data "aws_iam_policy_document" "put-account-a-bucket" {
  statement {
    effect = "Allow"

    actions = [
      "sts:AssumeRole",
    ]

    resources = [
        "arn:aws:iam::${var.AWS_ACCOUNT_A}:role/put-bucket",
    ]
  }
}

これで終了。誰しもが通る道っぽいので、いい経験だった、、、

results matching ""

    No results matching ""