更新在 Terraform 文件中创建的存储桶导致 BucketAlreadyOwnedByYou 错误

Update bucket created in Terraform file results in BucketAlreadyOwnedByYou error

我需要向我之前在 Terraform 文件中创建的存储桶添加策略。

然而,这个错误

Error creating S3 bucket: BucketAlreadyOwnedByYou: Your previous request to create the named bucket succeeded and you already own it.

如何修改我的 .tf 文件以创建存储桶,然后更新它?

resource "aws_s3_bucket" "bucket" {
  bucket = "my-new-bucket-123"
  acl    = "public-read"

  region = "eu-west-1"

  website {
    index_document = "index.html"
  }
}

data "aws_iam_policy_document" "s3_bucket_policy_document" {
  statement {
    actions   = ["s3:GetObject"]
    resources = ["${aws_s3_bucket.bucket.arn}/*"]
    principals {
      type        = "AWS"
      identifiers = ["*"]
    }
  }
}

resource "aws_s3_bucket" "s3_bucket_policy" {
  bucket = "${aws_s3_bucket.bucket.bucket}"
  policy = "${data.aws_iam_policy_document.s3_bucket_policy_document.json}"
}

您应该使用 aws_s3_bucket_policy resource 将存储桶策略添加到现有 S3 存储桶:

resource "aws_s3_bucket" "b" {
  bucket = "my_tf_test_bucket"
}

resource "aws_s3_bucket_policy" "b" {
  bucket = "${aws_s3_bucket.b.id}"

  policy = <<POLICY
{
  "Version": "2012-10-17",
  "Id": "MYBUCKETPOLICY",
  "Statement": [
    {
      "Sid": "IPAllow",
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:*",
      "Resource": "arn:aws:s3:::my_tf_test_bucket/*",
      "Condition": {
         "IpAddress": {"aws:SourceIp": "8.8.8.8/32"}
      }
    }
  ]
}
POLICY
}

但如果您同时执行此操作,那么将其内联到原始 aws_s3_bucket 资源中可能是值得的,如下所示:

locals {
  bucket_name = "my-new-bucket-123"
}

resource "aws_s3_bucket" "bucket" {
  bucket = "${local.bucket_name}"
  acl    = "public-read"
  policy = "${data.aws_iam_policy_document.s3_bucket_policy_document.json}"

  region = "eu-west-1"

  website {
    index_document = "index.html"
  }
}

data "aws_iam_policy_document" "s3_bucket_policy_document" {
  statement {
    actions   = ["s3:GetObject"]
    resources = ["arn:aws:s3:::${local.bucket_name}/*"]
    principals {
      type        = "AWS"
      identifiers = ["*"]
    }
  }
}

这会在存储桶策略中手动构建 S3 ARN,以避免尝试从 aws_s3_bucket 资源引用输出 arn 时出现潜在的循环错误。

如果您创建了没有策略的存储桶(通过在没有策略资源的情况下应用 Terraform),然后将 policy 参数添加到 aws_s3_bucket 资源将导致 Terraform 检测漂移和该计划将显示对存储桶的更新,添加策略。


可能值得注意的是,您在 aws_s3_bucket 资源的 acl 中使用的固定 ACL 与您的策略重叠并且是不必要的。您可以使用策略或固定 ACL 来允许所有人读取您的 S3 存储桶,但 public-read ACL 还允许您的存储桶内容像老式 Apache 目录列表一样匿名列出,这不是大多数人所希望的想要。

首次设置 Terraform 以使用 s3 作为后端时,配置类似于以下内容:

# backend.tf

terraform {
  backend "s3" {
    bucket            = "<bucket_name>"
    region            = "eu-west-2"
    key               = "state"
    dynamodb_endpoint = "https://dynamodb.eu-west-2.amazonaws.com"
    dynamodb_table    = "<table_name>"
  }
}
resource "aws_s3_bucket" "<bucket_label>" {
  bucket = "<bucket_name>"

  lifecycle {
    prevent_destroy = true
  }
}

AWS console 中手动创建 s3 存储桶后,运行 以下命令更新 terraform 状态以通知它 s3 存储桶已经存在:

terraform import aws_s3_bucket.<bucket_label> <bucket_name>

s3 存储桶现在将处于您的 Terraform 状态,并且此后将由 Terraform 管理。