Terraform 在 CI 中失败,但在创建 S3 存储桶和流日志时在本地正常工作

Terraform fails in CI while working fine locally when creating S3 bucket and flow logs

我编写了以下 Terraform 代码:​​

data "template_file" "external-bucket-policy" {
    template = "${file("${path.module}/policies/bucket-policy.tpl")}"

    vars {
        bucket-name = "${local.bucket_name}"
    }
}

resource "aws_s3_bucket" "vpc_logs_recordsyes" {
    bucket = "${local.bucket_name}"
    acl = "private"
    force_destroy = false
    versioning {
        enabled = true
    }


    policy = "${data.template_file.external-bucket-policy.rendered}"

}

然后我想创建 VPC 流日志:

resource "aws_flow_log" "example" {
    log_destination      = "arn:aws:s3:::${local.bucket_name}"
    log_destination_type = "${var.log_destination_type}"
    traffic_type         = "${var.traffic_type}"
    vpc_id               = "${var.vpc_id}"
}

当 运行 在 CI 时,我得到以下信息:

aws_s3_bucket.vpc_logs_recordsyes: Creating...
  acceleration_status:         "" => "<computed>"
  acl:                         "" => "private"
  arn:                         "" => "<computed>"
  bucket:                      "" => "xsight-logging-bucket-Dev-us-east-1"
  bucket_domain_name:          "" => "<computed>"
  bucket_regional_domain_name: "" => "<computed>"
  force_destroy:               "" => "false"
  hosted_zone_id:              "" => "<computed>"
  policy:                      "" => "{\r\n    \"Version\": \"2012-10-17\",\r\n    \"Statement\": [\r\n        {\r\n            \"Sid\": \"\",\r\n            \"Effect\": \"Deny\",\r\n            \"Principal\": {\r\n                \"AWS\": \"*\"\r\n            },\r\n            \"Action\": \"s3:DeleteBucket\",\r\n            \"Resource\": \"arn:aws:s3:::xsight-logging-bucket-Dev-us-east-1\"\r\n        },\r\n        {\r\n             \"Sid\": \"DenyIncorrectEncryptionHeader\",\r\n             \"Effect\": \"Deny\",\r\n             \"Principal\": \"*\",\r\n             \"Action\": \"s3:PutObject\",\r\n             \"Resource\": \"arn:aws:s3:::xsight-logging-bucket-Dev-us-east-1/*\",\r\n             \"Condition\": {\r\n                     \"StringNotEquals\": {\r\n                            \"s3:x-amz-server-side-encryption\": \"AES256\"\r\n                      }\r\n             }\r\n        },\r\n        {\r\n            \"Sid\": \"DenyUnEncryptedObjectUploads\",\r\n            \"Effect\": \"Deny\",\r\n            \"Principal\": \"*\",\r\n            \"Action\": \"s3:PutObject\",\r\n            \"Resource\": \"arn:aws:s3:::xsight-logging-bucket-Dev-us-east-1/*\",\r\n            \"Condition\": {\r\n                \"Null\": {\r\n                    \"s3:x-amz-server-side-encryption\": true\r\n                }\r\n            }\r\n        }\r\n    ]\r\n}"
  region:                      "" => "<computed>"
  request_payer:               "" => "<computed>"
  versioning.#:                "" => "1"
  versioning.0.enabled:        "" => "true"
  versioning.0.mfa_delete:     "" => "false"
  website_domain:              "" => "<computed>"
  website_endpoint:            "" => "<computed>"
aws_flow_log.example: Creating...
  log_destination:      "" => "arn:aws:s3:::xsight-logging-bucket-Dev-us-east-1"
  log_destination_type: "" => "s3"
  log_group_name:       "" => "<computed>"
  traffic_type:         "" => "ALL"
  vpc_id:               "" => "vpc-3e2ab845"

Error: Error applying plan:

2 error(s) occurred:

* aws_s3_bucket.vpc_logs_recordsyes: 1 error(s) occurred:

* aws_s3_bucket.vpc_logs_recordsyes: Error creating S3 bucket: InvalidBucketName: The specified bucket is not valid.
    status code: 400, request id: A2E94D42FF9CF218, host id: eD0zSCQ8+85kIIsctFeXcG4jLd4LDpeW0PRK01aq5JrWiW3qkyDKF76WeVKGgJVOcJT3gB2BBzk=
* aws_flow_log.example: 1 error(s) occurred:

* aws_flow_log.example: unexpected EOF

您的存储桶名称似乎不是 AWS User Guide 中提到的有效 S3 存储桶名称:

The following are the rules for naming S3 buckets in all AWS Regions:

  • Bucket names must be unique across all existing bucket names in Amazon S3.

  • Bucket names must comply with DNS naming conventions.

  • Bucket names must be at least 3 and no more than 63 characters long.

  • Bucket names must not contain uppercase characters or underscores.

  • Bucket names must start with a lowercase letter or number.

  • Bucket names must be a series of one or more labels. Adjacent labels are separated by a single period (.). Bucket names can contain lowercase letters, numbers, and hyphens. Each label must start and end with a lowercase letter or a number.

  • Bucket names must not be formatted as an IP address (for example, 192.168.5.4).

  • When you use virtual hosted–style buckets with Secure Sockets Layer (SSL), the SSL wildcard certificate only matches buckets that don't
    contain periods. To work around this, use HTTP or write your own
    certificate verification logic. We recommend that you do not use
    periods (".") in bucket names when using virtual hosted–style
    buckets.

特别注意我加粗的部分提到存储桶名称不能包含大写字符,而您的计划显示您在 S3 存储桶名称中使用大写字符:

  bucket:                      "" => "xsight-logging-bucket-Dev-us-east-1"

Terraform 通常可以在计划时捕获这些类型的错误,因为验证是提前知道的。不幸的是,它还必须向后兼容,并且在 2018 年 3 月 1 日之前,US-East-1 中的存储桶对存储桶的命名方案限制较少,因此在计划时验证这一点并不容易。


除此之外,您的流日志存在竞争条件,因为 Terraform 试图同时创建 S3 存储桶和 VPC 流日志。

要向 Terraform 提示资源的依赖顺序,您可以将一个资源的输出插入到另一个资源的参数中,或者在不可能的情况下使用 depends_on

在您的情况下,您应该只参考 VPC 流日志资源中的 S3 存储桶资源:

resource "aws_flow_log" "example" {
  log_destination      = "${aws_s3_bucket.vpc_logs.bucket}"
  log_destination_type = "${var.log_destination_type}"
  traffic_type         = "${var.traffic_type}"
  vpc_id               = "${var.vpc_id}"
}

您从 AWS 调用中收到错误,这意味着 AWS 端出现错误(并且 Terraform 代码没有问题)。 参考:https://github.com/terraform-providers/terraform-provider-aws/blob/master/aws/resource_aws_s3_bucket.go#L583

现在,查看错误,重要的关键字是 Error creating S3 bucket: InvalidBucketName
这表明您选择的存储桶名称不符合所有命名约定。 参考 AWS 文档(https://docs.aws.amazon.com/AmazonS3/latest/dev/BucketRestrictions.html)建议,存储桶名称应该 NOT 具有 Upper Case.

您可以将您的 Bucket 名称更新为 xsight-logging-bucket-dev-us-east-1 并试试吗?

此外,对于 vpc_flow 日志记录,您不需要附加 arn:aws:s3:::.
您可以定义为 log_destination = "${local.bucket_name}"。 参考:https://www.terraform.io/docs/providers/aws/r/flow_log.html