Merge branch 'terraform-0.12-upgrade' of rekahsoft/blog-rekahsoft-ca into master

This commit is contained in:
Collin J. Doering 2019-06-14 03:02:50 +00:00 committed by Gitea
commit a220c1efce
3 changed files with 120 additions and 90 deletions

View File

@ -1,4 +1,6 @@
terraform { terraform {
required_version = ">= 0.12"
backend "s3" { backend "s3" {
region = "ca-central-1" region = "ca-central-1"
bucket = "rekahsoft-terraform" bucket = "rekahsoft-terraform"
@ -8,102 +10,109 @@ terraform {
} }
provider "aws" { provider "aws" {
region = "${var.region}" region = var.region
version = "~> 1.9" version = "~> 2.15"
assume_role = [{ assume_role {
role_arn = "${var.workspace_iam_roles[terraform.workspace]}" role_arn = var.workspace_iam_roles[terraform.workspace]
}] }
} }
provider "aws" { provider "aws" {
alias = "us_east_1" alias = "us_east_1"
region = "us-east-1" region = "us-east-1"
version = "~> 1.9" version = "~> 2.1"
assume_role = [{ assume_role {
role_arn = "${var.workspace_iam_roles[terraform.workspace]}" role_arn = var.workspace_iam_roles[terraform.workspace]
}] }
} }
provider "null" { provider "null" {
version = "~> 1.0" version = "~> 2.1"
} }
provider "random" { provider "random" {
version = "~> 1.3" version = "~> 2.1"
} }
provider "template" { provider "template" {
version = "~> 1.0" version = "~> 2.1"
} }
# #
# Local values to be re-used throughout this template # Local values to be re-used throughout this template
locals { locals {
common_tags = "${map( common_tags = {
"Project", "${var.project}", "Project" = var.project
"Environment", "${terraform.workspace}" "Environment" = terraform.workspace
)}" }
cdn_origin_id = "${terraform.workspace}-origin-cdn"
www = "${var.enable_naked_domain ? "" : "www."}"
subdomain = "${var.subdomain == "" ? "" : "${var.subdomain}."}"
naked_domain = "${local.subdomain}${var.dns_apex}"
domain = "${local.www}${local.naked_domain}"
project_env = "${var.project}-${terraform.workspace}"
}
cdn_origin_id = "${terraform.workspace}-origin-cdn"
www = var.enable_naked_domain ? "" : "www."
subdomain = var.subdomain == "" ? "" : "${var.subdomain}."
naked_domain = "${local.subdomain}${var.dns_apex}"
domain = "${local.www}${local.naked_domain}"
project_env = "${var.project}-${terraform.workspace}"
}
# #
# Data Sources # Data Sources
data "template_file" "s3_origin_policy" { data "template_file" "s3_origin_policy" {
template = "${file("templates/s3_origin_policy.json")}" template = file("templates/s3_origin_policy.json")
vars { vars = {
bucket_arn = "${aws_s3_bucket.static.arn}" bucket_arn = aws_s3_bucket.static.arn
user_arn = "${aws_iam_user.app_deploy.arn}" user_arn = aws_iam_user.app_deploy.arn
cloudfront_arn = "${aws_cloudfront_origin_access_identity.origin_access_identity.iam_arn}" cloudfront_arn = aws_cloudfront_origin_access_identity.origin_access_identity.iam_arn
} }
} }
data "aws_route53_zone" "external" { data "aws_route53_zone" "external" {
name = "${var.dns_apex}." name = "${var.dns_apex}."
} }
# #
# Resources # Resources
resource "aws_acm_certificate" "cert" { resource "aws_acm_certificate" "cert" {
domain_name = "${local.domain}" domain_name = local.domain
subject_alternative_names = "${compact(list("${var.enable_naked_domain}" ? "" : "${local.naked_domain}"))}" subject_alternative_names = compact([var.enable_naked_domain ? "" : local.naked_domain])
validation_method = "DNS" validation_method = "DNS"
tags = "${local.common_tags}" tags = local.common_tags
provider = "aws.us_east_1" provider = aws.us_east_1
} }
resource "aws_route53_record" "cert_validation" { resource "aws_route53_record" "cert_validation" {
count = "${1 + "${var.enable_naked_domain ? 0 : 1}"}" count = 1 + (var.enable_naked_domain ? 0 : 1)
zone_id = "${data.aws_route53_zone.external.id}" zone_id = data.aws_route53_zone.external.id
name = "${lookup(aws_acm_certificate.cert.domain_validation_options[count.index], "resource_record_name")}" name = aws_acm_certificate.cert.domain_validation_options[count.index]["resource_record_name"]
type = "${lookup(aws_acm_certificate.cert.domain_validation_options[count.index], "resource_record_type")}" type = aws_acm_certificate.cert.domain_validation_options[count.index]["resource_record_type"]
ttl = 60 ttl = 60
records = ["${lookup(aws_acm_certificate.cert.domain_validation_options[count.index], "resource_record_value")}"] # TF-UPGRADE-TODO: In Terraform v0.10 and earlier, it was sometimes necessary to
# force an interpolation expression to be interpreted as a list by wrapping it
# in an extra set of list brackets. That form was supported for compatibilty in
# v0.11, but is no longer supported in Terraform v0.12.
#
# If the expression in the following list itself returns a list, remove the
# brackets to avoid interpretation as a list of lists. If the expression
# returns a single list item then leave it as-is and remove this TODO comment.
records = [aws_acm_certificate.cert.domain_validation_options[count.index]["resource_record_value"]]
} }
resource "aws_acm_certificate_validation" "cert" { resource "aws_acm_certificate_validation" "cert" {
certificate_arn = "${aws_acm_certificate.cert.arn}" certificate_arn = aws_acm_certificate.cert.arn
validation_record_fqdns = ["${aws_route53_record.cert_validation.*.fqdn}"] validation_record_fqdns = aws_route53_record.cert_validation.*.fqdn
provider = "aws.us_east_1" provider = aws.us_east_1
} }
resource "aws_s3_bucket" "static" { resource "aws_s3_bucket" "static" {
bucket_prefix = "${local.project_env}" bucket_prefix = local.project_env
acl = "private" acl = "private"
website { website {
@ -111,71 +120,71 @@ resource "aws_s3_bucket" "static" {
error_document = "error.html" error_document = "error.html"
} }
tags = "${local.common_tags}" tags = local.common_tags
} }
resource "aws_s3_bucket" "static_redirect" { resource "aws_s3_bucket" "static_redirect" {
count = "${var.enable_naked_domain ? 0 : 1}" count = var.enable_naked_domain ? 0 : 1
bucket_prefix = "${local.project_env}" bucket_prefix = local.project_env
acl = "private" acl = "private"
website { website {
redirect_all_requests_to = "https://${local.domain}" redirect_all_requests_to = "https://${local.domain}"
} }
tags = "${local.common_tags}" tags = local.common_tags
} }
resource "aws_s3_bucket" "static_logs" { resource "aws_s3_bucket" "static_logs" {
bucket_prefix = "${local.project_env}" bucket_prefix = local.project_env
acl = "private" acl = "private"
} }
resource "random_string" "app_deploy_username" { resource "random_string" "app_deploy_username" {
length = 16 length = 16
special = true special = true
override_special = "_+=,.@-" override_special = "_+=,.@-"
} }
resource "aws_iam_user" "app_deploy" { resource "aws_iam_user" "app_deploy" {
name = "${random_string.app_deploy_username.result}" name = random_string.app_deploy_username.result
} }
resource "aws_iam_access_key" "app_deploy" { resource "aws_iam_access_key" "app_deploy" {
user = "${aws_iam_user.app_deploy.name}" user = aws_iam_user.app_deploy.name
# pgp_key = "keybase:some_person_that_exists" # pgp_key = "keybase:some_person_that_exists"
} }
resource "aws_route53_record" "static" { resource "aws_route53_record" "static" {
zone_id = "${data.aws_route53_zone.external.zone_id}" zone_id = data.aws_route53_zone.external.zone_id
name = "${local.domain}." name = "${local.domain}."
type = "A" type = "A"
alias { alias {
name = "${aws_cloudfront_distribution.cdn.domain_name}" name = aws_cloudfront_distribution.cdn.domain_name
zone_id = "${aws_cloudfront_distribution.cdn.hosted_zone_id}" zone_id = aws_cloudfront_distribution.cdn.hosted_zone_id
evaluate_target_health = true evaluate_target_health = true
} }
} }
resource "aws_route53_record" "static_redirect" { resource "aws_route53_record" "static_redirect" {
count = "${var.enable_naked_domain ? 0 : 1}" count = var.enable_naked_domain ? 0 : 1
zone_id = "${data.aws_route53_zone.external.zone_id}" zone_id = data.aws_route53_zone.external.zone_id
name = "${local.naked_domain}." name = "${local.naked_domain}."
type = "A" type = "A"
alias { alias {
name = "${aws_cloudfront_distribution.cdn_redirect.domain_name}" name = aws_cloudfront_distribution.cdn_redirect[0].domain_name
zone_id = "${aws_cloudfront_distribution.cdn_redirect.hosted_zone_id}" zone_id = aws_cloudfront_distribution.cdn_redirect[0].hosted_zone_id
evaluate_target_health = true evaluate_target_health = true
} }
} }
resource "aws_s3_bucket_policy" "static_policy" { resource "aws_s3_bucket_policy" "static_policy" {
bucket = "${aws_s3_bucket.static.id}" bucket = aws_s3_bucket.static.id
policy = "${data.template_file.s3_origin_policy.rendered}" policy = data.template_file.s3_origin_policy.rendered
} }
resource "aws_cloudfront_origin_access_identity" "origin_access_identity" { resource "aws_cloudfront_origin_access_identity" "origin_access_identity" {
@ -185,11 +194,11 @@ resource "aws_cloudfront_origin_access_identity" "origin_access_identity" {
resource "aws_cloudfront_distribution" "cdn" { resource "aws_cloudfront_distribution" "cdn" {
# Static file origin # Static file origin
origin { origin {
domain_name = "${aws_s3_bucket.static.bucket_regional_domain_name}" domain_name = aws_s3_bucket.static.bucket_regional_domain_name
origin_id = "${local.cdn_origin_id}" origin_id = local.cdn_origin_id
s3_origin_config { s3_origin_config {
origin_access_identity = "${aws_cloudfront_origin_access_identity.origin_access_identity.cloudfront_access_identity_path}" origin_access_identity = aws_cloudfront_origin_access_identity.origin_access_identity.cloudfront_access_identity_path
} }
} }
@ -201,22 +210,30 @@ resource "aws_cloudfront_distribution" "cdn" {
# Return index.html for any route that is not found # Return index.html for any route that is not found
custom_error_response { custom_error_response {
error_caching_min_ttl = 0 error_caching_min_ttl = 0
error_code = 403 error_code = 403
response_code = 200 response_code = 200
response_page_path = "/index.html" response_page_path = "/index.html"
} }
logging_config { logging_config {
include_cookies = false include_cookies = false
bucket = "${aws_s3_bucket.static_logs.bucket_domain_name}" bucket = aws_s3_bucket.static_logs.bucket_domain_name
} }
aliases = ["${local.domain}"] # TF-UPGRADE-TODO: In Terraform v0.10 and earlier, it was sometimes necessary to
# force an interpolation expression to be interpreted as a list by wrapping it
# in an extra set of list brackets. That form was supported for compatibilty in
# v0.11, but is no longer supported in Terraform v0.12.
#
# If the expression in the following list itself returns a list, remove the
# brackets to avoid interpretation as a list of lists. If the expression
# returns a single list item then leave it as-is and remove this TODO comment.
aliases = [local.domain]
default_cache_behavior { default_cache_behavior {
allowed_methods = ["GET", "HEAD", "OPTIONS"] allowed_methods = ["GET", "HEAD", "OPTIONS"]
cached_methods = ["GET", "HEAD", "OPTIONS"] cached_methods = ["GET", "HEAD", "OPTIONS"]
target_origin_id = "${local.cdn_origin_id}" target_origin_id = local.cdn_origin_id
forwarded_values { forwarded_values {
query_string = false query_string = false
@ -237,11 +254,11 @@ resource "aws_cloudfront_distribution" "cdn" {
path_pattern = "index.html" path_pattern = "index.html"
allowed_methods = ["GET", "HEAD", "OPTIONS"] allowed_methods = ["GET", "HEAD", "OPTIONS"]
cached_methods = ["GET", "HEAD", "OPTIONS"] cached_methods = ["GET", "HEAD", "OPTIONS"]
target_origin_id = "${local.cdn_origin_id}" target_origin_id = local.cdn_origin_id
forwarded_values { forwarded_values {
query_string = false query_string = false
headers = ["Origin"] headers = ["Origin"]
cookies { cookies {
forward = "none" forward = "none"
} }
@ -262,25 +279,25 @@ resource "aws_cloudfront_distribution" "cdn" {
} }
} }
tags = "${local.common_tags}" tags = local.common_tags
viewer_certificate { viewer_certificate {
acm_certificate_arn = "${aws_acm_certificate_validation.cert.certificate_arn}" acm_certificate_arn = aws_acm_certificate_validation.cert.certificate_arn
ssl_support_method = "sni-only" ssl_support_method = "sni-only"
minimum_protocol_version = "TLSv1.1_2016" minimum_protocol_version = "TLSv1.1_2016"
} }
} }
resource "aws_cloudfront_distribution" "cdn_redirect" { resource "aws_cloudfront_distribution" "cdn_redirect" {
count = "${var.enable_naked_domain ? 0 : 1}" count = var.enable_naked_domain ? 0 : 1
# Static file origin # Static file origin
origin { origin {
domain_name = "${aws_s3_bucket.static_redirect.id}.${aws_s3_bucket.static_redirect.website_domain}" domain_name = "${aws_s3_bucket.static_redirect[0].id}.${aws_s3_bucket.static_redirect[0].website_domain}"
origin_id = "${local.cdn_origin_id}" origin_id = local.cdn_origin_id
custom_origin_config { custom_origin_config {
http_port = 80 http_port = 80
https_port = 443 https_port = 443
origin_ssl_protocols = ["TLSv1.1", "TLSv1.2"] origin_ssl_protocols = ["TLSv1.1", "TLSv1.2"]
@ -288,21 +305,29 @@ resource "aws_cloudfront_distribution" "cdn_redirect" {
} }
} }
enabled = true enabled = true
is_ipv6_enabled = true is_ipv6_enabled = true
comment = "CDN redirect for ${var.project} (environment ${terraform.workspace})" comment = "CDN redirect for ${var.project} (environment ${terraform.workspace})"
logging_config { logging_config {
include_cookies = false include_cookies = false
bucket = "${aws_s3_bucket.static_logs.bucket_domain_name}" bucket = aws_s3_bucket.static_logs.bucket_domain_name
} }
aliases = ["${local.naked_domain}"] # TF-UPGRADE-TODO: In Terraform v0.10 and earlier, it was sometimes necessary to
# force an interpolation expression to be interpreted as a list by wrapping it
# in an extra set of list brackets. That form was supported for compatibilty in
# v0.11, but is no longer supported in Terraform v0.12.
#
# If the expression in the following list itself returns a list, remove the
# brackets to avoid interpretation as a list of lists. If the expression
# returns a single list item then leave it as-is and remove this TODO comment.
aliases = [local.naked_domain]
default_cache_behavior { default_cache_behavior {
allowed_methods = ["GET", "HEAD", "OPTIONS"] allowed_methods = ["GET", "HEAD", "OPTIONS"]
cached_methods = ["GET", "HEAD", "OPTIONS"] cached_methods = ["GET", "HEAD", "OPTIONS"]
target_origin_id = "${local.cdn_origin_id}" target_origin_id = local.cdn_origin_id
forwarded_values { forwarded_values {
query_string = false query_string = false
@ -326,10 +351,10 @@ resource "aws_cloudfront_distribution" "cdn_redirect" {
} }
} }
tags = "${local.common_tags}" tags = local.common_tags
viewer_certificate { viewer_certificate {
acm_certificate_arn = "${aws_acm_certificate_validation.cert.certificate_arn}" acm_certificate_arn = aws_acm_certificate_validation.cert.certificate_arn
ssl_support_method = "sni-only" ssl_support_method = "sni-only"
minimum_protocol_version = "TLSv1.1_2016" minimum_protocol_version = "TLSv1.1_2016"
} }
@ -338,7 +363,7 @@ resource "aws_cloudfront_distribution" "cdn_redirect" {
resource "null_resource" "deploy_app" { resource "null_resource" "deploy_app" {
provisioner "local-exec" { provisioner "local-exec" {
interpreter = ["bash", "-c"] interpreter = ["bash", "-c"]
command = <<SCRIPT command = <<SCRIPT
: Create temporary aws config and credentials files : Create temporary aws config and credentials files
export AWS_CONFIG_FILE=$(mktemp); export AWS_CONFIG_FILE=$(mktemp);
export AWS_SHARED_CREDENTIALS_FILE=$(mktemp); export AWS_SHARED_CREDENTIALS_FILE=$(mktemp);
@ -354,5 +379,7 @@ aws --profile ${aws_iam_user.app_deploy.name} s3 sync --delete ../_site s3://${a
: Cleanup temporary aws config and credentials files : Cleanup temporary aws config and credentials files
rm $${AWS_CONFIG_FILE} $${AWS_SHARED_CREDENTIALS_FILE}; rm $${AWS_CONFIG_FILE} $${AWS_SHARED_CREDENTIALS_FILE};
SCRIPT SCRIPT
} }
} }

View File

@ -1,3 +1,4 @@
output "s3_bucket_static" { output "s3_bucket_static" {
value = "${aws_s3_bucket.static.id}" value = aws_s3_bucket.static.id
} }

View File

@ -14,7 +14,8 @@ variable "project" {
default = "blog-rekahsoft-ca" default = "blog-rekahsoft-ca"
} }
variable "dns_apex" {} variable "dns_apex" {
}
variable "subdomain" { variable "subdomain" {
default = "" default = ""
@ -23,3 +24,4 @@ variable "subdomain" {
variable "enable_naked_domain" { variable "enable_naked_domain" {
default = false default = false
} }