【问题标题】:Error creating cloudfront distribution with terraform. InvalidViewerCertificate使用 terraform 创建云端分发时出错。无效的查看器证书
【发布时间】:2020-05-13 23:42:40
【问题描述】:

我正在尝试使用 Terraform 将 ReactJS 项目静态部署到 s3

我的 s3 存储桶 terraform 配置以使用策略创建存储桶:

resource "aws_s3_bucket" "site" {
  bucket = var.domain
  acl = "public-read"

  policy = <<EOF
{
  "Version":"2012-10-17",
  "Statement":[{
        "Sid":"PublicReadForGetBucketObjects",
        "Effect":"Allow",
          "Principal": "*",
      "Action":["s3:GetObject"],
      "Resource":["arn:aws:s3:::${var.domain}/*"]
    }
  ]
}
  EOF

  website {
      index_document = "index.html"
      error_document = "404.html"
  }
}

route53 配置必要的 dns:

resource "aws_route53_zone" "main" {
  name = var.domain
}

resource "aws_route53_record" "root_domain" {
  zone_id = aws_route53_zone.main.zone_id
  name = var.domain
  type = "A"

  alias {
    name = aws_cloudfront_distribution.cdn.domain_name
    zone_id = aws_cloudfront_distribution.cdn.hosted_zone_id
    evaluate_target_health = false
  }
}

云端配置:

resource "aws_cloudfront_distribution" "cdn" {
  origin {
    origin_id   = var.domain
    domain_name = aws_s3_bucket.site.bucket_regional_domain_name

    custom_origin_config {
      http_port = 80
      https_port = 443
      origin_protocol_policy = "match-viewer"
      origin_ssl_protocols = ["TLSv1", "TLSv1.1", "TLSv1.2"]
    }
  }

  aliases = [var.domain]

  enabled             = true
  wait_for_deployment = false
  default_root_object = "index.html"

  custom_error_response {
      error_caching_min_ttl = 0
      error_code = 404
      response_code = 200
      response_page_path = "/index.html"
  }

  default_cache_behavior {
    allowed_methods  = ["GET", "HEAD", "OPTIONS"]
    cached_methods   = ["GET", "HEAD"]
    target_origin_id = var.domain

    forwarded_values {
      query_string = true
      cookies {
        forward = "none"
      }
    }

    viewer_protocol_policy = "allow-all"
    min_ttl                = 0
    default_ttl            = 3600
    max_ttl                = 86400
  }

  price_class = "PriceClass_100"

  restrictions {
    geo_restriction {
      restriction_type = "none"
    }
  }

  viewer_certificate {
    cloudfront_default_certificate = true
  }
}

即使我尝试使用 cloudfront 默认证书,在运行 terraform apply 后我仍然收到以下错误:

Error: error creating CloudFront Distribution: InvalidViewerCertificate: To add an alternate domain name (CNAME) to a CloudFront distribution, you must attach a trusted certificate that validates your authorization to use the domain name.

【问题讨论】:

    标签: amazon-web-services amazon-s3 amazon-cloudfront amazon-route53 terraform-provider-aws


    【解决方案1】:

    最后修复它,如果您想使用默认证书,您无法将备用域名添加到 CloudFront 分配,您需要使用 Amazon 证书管理器生成 SSL 证书。换句话说,要完成这项工作,您需要在 CloudFront 配置部分中注释掉 aliases = [var.domain]

    【讨论】:

    • 你不能只是别名的通配符吗?比如别名 = [ var.domain, *.${var.domain} ]
    【解决方案2】:

    这个问题当然和 Terraform 无关。

    正如How do I resolve the "InvalidViewerCertificate" error exception while creating or updating a CloudFront distribution 中提到的:

    这个错误信息:

    要将备用域名 (CNAME) 添加到 CloudFront 分配, 您必须附上一个可信的证书来验证您的 授权使用域名。

    表示分发中的备用域名 (CNAME) 未包含在您提供的证书的主题备用名称 (SAN) 中。
    您可以向 ACM 申请公共证书,也可以联系您的证书颁发机构 (CA) 以获取涵盖分发中备用域名的更新证书。

    (*) 关于上面提供的答案 - 请注意,您不必强制使用 Amazon 证书管理器 - 只要您遵循上述规则,您就可以使用外部提供商(例如免费的 LetsEncrypt)。

    【讨论】:

      【解决方案3】:

      @RtmY 回复的 Terraform 版本可能看起来像这样。 为了获得证书并对其进行验证,您必须在 us-east-1 区域进行,因此我们需要在您的设置中引入它:

      provider "aws" {
        version = "~> 2.46.0"
      }
      
      provider "aws" {
        version = "~> 2.46.0"
        region = "us-east-1"
        alias = "us-east-1"
      }
      

      然后我们要创建一个证书:

      resource "aws_acm_certificate" "cert" {
        provider = aws.us-east-1
        domain_name       = local.bucket_name
        validation_method = "DNS"
      
        lifecycle {
          create_before_destroy = true
        }
      }
      

      要验证证书,我们必须使用 Route53 创建一个 DNS 条目:

      resource "aws_route53_record" "cert_validation" {
        name = "${aws_acm_certificate.cert.domain_validation_options.0.resource_record_name}"
        type = "${aws_acm_certificate.cert.domain_validation_options.0.resource_record_type}"
        zone_id = var.zone-id-of-your-route-53
        records = ["${aws_acm_certificate.cert.domain_validation_options.0.resource_record_value}"]
        ttl = 60
      } 
      

      最后一步,我们必须再次在 us-east-1 区域验证新创建的证书:

      resource "aws_acm_certificate_validation" "cert" {
        provider = aws.us-east-1
        certificate_arn         = aws_acm_certificate.cert.arn
        validation_record_fqdns = ["${aws_route53_record.cert_validation.fqdn}"]
      }
      

      现在,在我们的 aws_cloudfront_distribution 中,我们将别名保留在它们所在的位置,并且必须为查看器证书添加另一个配置:

      viewer_certificate {
          acm_certificate_arn = aws_acm_certificate_validation.cert.certificate_arn
          ssl_support_method = "sni-only"
      }
      

      我认为,这样的验证仅适用于一个别名,而不适用于许多别名。如果有许多别名,文档中的示例可能更适合: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/acm_certificate_validation

      解决方案是从这里借来的:

      Terraform AWS ACM certificates in us-east-1 for resources in eu-west-1

      【讨论】:

        【解决方案4】:

        我也遇到了这个问题,发现我不小心通过 ACM 在错误的区域创建了证书。证书必须与发行版在同一地区

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-05-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-09-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多