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

huangapple go评论106阅读模式
英文:

Update bucket created in Terraform file results in BucketAlreadyOwnedByYou error

问题

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

但是,出现了以下错误:

创建S3存储桶时出错:BucketAlreadyOwnedByYou:您之前的
创建具有该名称的存储桶的请求成功,您已拥有它。

我如何修改我的.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}"
}
英文:

I need to add a policy to a bucket I create earlier on in my Terraform file.

However, this errors with

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

How can I amend my .tf file to create the bucket, then update it?

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}"
}

答案1

得分: 4

当首次配置 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 控制台 手动创建 S3 存储桶后,运行以下命令来更新 Terraform 状态,以通知它 S3 存储桶已经存在:

terraform import aws_s3_bucket.<bucket_label> <bucket_name>

S3 存储桶现在将包含在您的 Terraform 状态中,并将由 Terraform 管理。

英文:

When setting up terraform to use s3 as a backend for the first time with a config similar to below:

# backend.tf

terraform {
  backend &quot;s3&quot; {
    bucket            = &quot;&lt;bucket_name&gt;&quot;
    region            = &quot;eu-west-2&quot;
    key               = &quot;state&quot;
    dynamodb_endpoint = &quot;https://dynamodb.eu-west-2.amazonaws.com&quot;
    dynamodb_table    = &quot;&lt;table_name&gt;&quot;
  }
}
resource &quot;aws_s3_bucket&quot; &quot;&lt;bucket_label&gt;&quot; {
  bucket = &quot;&lt;bucket_name&gt;&quot;

  lifecycle {
    prevent_destroy = true
  }
}

After creating the s3 bucket manually in the AWS console, run the following command to update the terraform state to inform it that the s3 bucket already exists:

terraform import aws_s3_bucket.&lt;bucket_label&gt; &lt;bucket_name&gt;

The s3 bucket will now be in your Terraform state and will henceforth be managed by Terraform.

答案2

得分: 3

你应该使用aws_s3_bucket_policy资源来向现有的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目录列表一样,这不是大多数人想要的。

英文:

You should use the aws_s3_bucket_policy resource to add a bucket policy to an existing S3 bucket:

resource &quot;aws_s3_bucket&quot; &quot;b&quot; {
  bucket = &quot;my_tf_test_bucket&quot;
}

resource &quot;aws_s3_bucket_policy&quot; &quot;b&quot; {
  bucket = &quot;${aws_s3_bucket.b.id}&quot;

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

But if you are doing this at the same time then it's probably worth just inlining this into the original aws_s3_bucket resource like this:

locals {
  bucket_name = &quot;my-new-bucket-123&quot;
}

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

  region = &quot;eu-west-1&quot;

  website {
    index_document = &quot;index.html&quot;
  }
}

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

This builds the S3 ARN in the bucket policy by hand to avoid a potential cycle error from trying to reference the output arn from the aws_s3_bucket resource.

If you had created the bucket without the policy (by applying the Terraform without the policy resource) then adding the policy argument to the aws_s3_bucket resource will then cause Terraform to detect the drift and the plan will show an update to the bucket, adding the policy.


It's probably worth noting that your canned ACL used in the acl of the aws_s3_bucket resource is overlapping with your policy and is unnecessary. You could use either the policy or the canned ACL to allow your S3 bucket to be read by all but the public-read ACL also allows your bucket contents to be anonymously listed like old school Apache directory listings which isn't what most people want.

huangapple
  • 本文由 发表于 2020年1月4日 01:20:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/59582735.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定