guix-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

01/02: cdn: Move service configs into individual files.


From: Chris Marusich
Subject: 01/02: cdn: Move service configs into individual files.
Date: Sat, 5 Jan 2019 22:34:30 -0500 (EST)

marusich pushed a commit to branch master
in repository maintenance.

commit 1540978fda67e06766b21bcee09f4e3dcbb2ca66
Author: Chris Marusich <address@hidden>
Date:   Sat Jan 5 15:53:02 2019 -0800

    cdn: Move service configs into individual files.
    
    * cdn/terraform/main.tf: Remove all service-specific configuration.
    * cdn/terraform/acm.tf: New file.
    * cdn/terraform/cloudfront.tf: New file.
    * cdn/terraform/cloudwatch.tf: New file.
    * cdn/terraform/dynamodb.tf: New file.
    * cdn/terraform/iam.tf: New file.
    * cdn/terraform/s3.tf: New file.
---
 cdn/terraform/acm.tf        |  47 +++++
 cdn/terraform/cloudfront.tf |  94 ++++++++++
 cdn/terraform/cloudwatch.tf |  69 ++++++++
 cdn/terraform/dynamodb.tf   |  21 +++
 cdn/terraform/iam.tf        | 131 ++++++++++++++
 cdn/terraform/main.tf       | 421 +-------------------------------------------
 cdn/terraform/s3.tf         |  48 +++++
 7 files changed, 415 insertions(+), 416 deletions(-)

diff --git a/cdn/terraform/acm.tf b/cdn/terraform/acm.tf
new file mode 100644
index 0000000..19b6e74
--- /dev/null
+++ b/cdn/terraform/acm.tf
@@ -0,0 +1,47 @@
+# ACM
+
+# Terraform will create this certificate automatically.  However, to
+# validate it requires one-time manual action outside of Terraform.
+# This is because there don't seem to be any Terraform providers that
+# are compatible with our DNS registrar.  To create and validate the
+# certificate, you must do the following in order:
+#
+#   - Run "terraform apply" to create the certificate.
+#   - Run "terraform show" to view the CNAME record ACM needs you to
+#     create in order to prove domain ownership.
+#   - Manually create the CNAME record.
+#   - Run "terraform apply" or "terraform plan" again to ensure the
+#     resources are in their final, correct state.
+#   - Run "terraform show" to verify that the certificate is now
+#     listed as "validated".
+#   - Repeat the last two steps until the validation succeeds.
+#
+# This only has to be done once.  For more information, see:
+# https://docs.aws.amazon.com/acm/latest/userguide/gs-acm-validate-dns.html
+#
+# Finally, since we intend to use this certificate with our CloudFront
+# distribution, we must create it in the us-east-1 region.  See:
+# https://docs.aws.amazon.com/acm/latest/userguide/acm-services.html
+# 
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cnames-and-https-requirements.html
+resource "aws_acm_certificate" "berlin-mirror-certificate" {
+  domain_name       = "ci.guix.info"
+  validation_method = "DNS"
+  # The AWS provider documentation recommends setting
+  # create_before_destroy to true in a lifecycle block.  We probably
+  # won't need this, since we don't currently plan to replace the
+  # existing certificate using Terraform (ACM will just rotate it for
+  # us automatically), but it doesn't hurt to include this here.
+  lifecycle {
+    create_before_destroy = true
+  }
+}
+
+# SNS
+
+# Email subscriptions cannot be managed via Terraform.  Therefore, any
+# email subscriptions must be configured manually.  See:
+# https://www.terraform.io/docs/providers/aws/r/sns_topic_subscription.html
+# 
https://docs.aws.amazon.com/sns/latest/dg/sns-getting-started.html#SubscribeTopic
+resource "aws_sns_topic" "guix-billing-alarms" {
+  name = "guix-billing-alarms"
+}
diff --git a/cdn/terraform/cloudfront.tf b/cdn/terraform/cloudfront.tf
new file mode 100644
index 0000000..018b803
--- /dev/null
+++ b/cdn/terraform/cloudfront.tf
@@ -0,0 +1,94 @@
+# CloudFront
+
+resource "aws_cloudfront_distribution" "berlin-mirror" {
+  enabled = true
+  comment = "Distributed caching proxy for berlin.guixsd.org"
+  origin {
+    domain_name = "berlin.guixsd.org"
+    origin_id = "berlin.guixsd.org"
+    custom_origin_config {
+      http_port = 80 # Required, but not used.
+      https_port = 443
+      # Always use TLS when forwarding requests to the origin.
+      origin_protocol_policy = "https-only"
+      origin_ssl_protocols = ["TLSv1.2"]
+      origin_keepalive_timeout = 60
+      origin_read_timeout = 60
+    }
+  }
+  # The CNAME that will point to this CloudFront distribution.
+  aliases = ["ci.guix.info"]
+  is_ipv6_enabled = true
+  # This is actually the_maximum HTTP version to support. See:
+  # 
https://www.terraform.io/docs/providers/aws/r/cloudfront_distribution.html#http_version
+  http_version = "http2"
+  # Serve requests from all edge locations.
+  price_class = "PriceClass_All"
+  # Do not restrict access.
+  restrictions { geo_restriction { restriction_type = "none" }}
+  # When deleting the distribution, actually delete it.  See:
+  # 
https://www.terraform.io/docs/providers/aws/r/cloudfront_distribution.html#retain_on_delete
+  retain_on_delete = false
+  default_cache_behavior {
+    # Only allow "read" verbs.
+    allowed_methods = ["GET", "HEAD"]
+    cached_methods = ["GET", "HEAD"]
+    # The origin will compress data when necessary.
+    compress = false
+    # Cache responses that lack a Cache-Control header.
+    default_ttl = 86400 # 1 day
+    # When deciding whether or not to cache a response, ignore any
+    # cookies, headers, or query strings that the client included in
+    # their request.  This should increase the cache hit rate.  In
+    # addition, this also causes CloudFront to omit these values
+    # when forwarding the request to the custom origin. See:
+    # 
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/ConfiguringCaching.html
+    forwarded_values {
+      cookies { forward = "none" }
+      query_string = false
+    }
+    # Generally speaking, respect any Cache-Control or Expires
+    # headers that the origin includes in its responses.  The
+    # exception is that if a Cache-Control or Expires header says to
+    # cache the result for more than 1 year, we ignore that and only
+    # cache the result for 1 year at most.  Honestly, though, it
+    # seems unrealistic to expect CloudFront to actually keep the
+    # cached response for an entire year in that case.  See:
+    # 
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Expiration.html
+    max_ttl = 31536000 # 365 days
+    min_ttl = 0
+    target_origin_id = "berlin.guixsd.org"
+    # Before ci.guix.info pointed to this distribution, it allowed
+    # both HTTP and HTTPS.  We choose to maintain that policy here.
+    # In the future, we should consider changing this to "https-only".
+    viewer_protocol_policy = "allow-all"
+  }
+  # TODO: Maybe add more behaviors for specific paths/prefixes.
+  # ordered_cache_behavior {}
+  # TODO: Maybe set a caching behavior for error responses.
+  # custom_error_response {}
+  viewer_certificate {
+    # Note that "terraform apply" will fail until this certificate is
+    # valid.  See the comment in the definition of
+    # berlin-mirror-certificate for more information.
+    acm_certificate_arn = 
"${aws_acm_certificate.berlin-mirror-certificate.arn}"
+    # This is the recommended value as of 2018-12-28.  See:
+    # 
https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_ViewerCertificate.html
+    # 
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/secure-connections-supported-viewer-protocols-ciphers.html#secure-connections-supported-ciphers
+    minimum_protocol_version = "TLSv1.1_2016"
+    # Use SNI.  Don't use the "vip" (i.e., dedicated IP address)
+    # method, since it's expensive and unnecessary.  See:
+    # 
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cnames-https-dedicated-ip-or-sni.html
+    ssl_support_method = "sni-only"
+  }
+}
+
+output "berlin-mirror-id" {
+  value = "${aws_cloudfront_distribution.berlin-mirror.id}"
+}
+output "berlin-mirror-status" {
+  value = "${aws_cloudfront_distribution.berlin-mirror.status}"
+}
+output "berlin-mirror-domain-name" {
+  value = "${aws_cloudfront_distribution.berlin-mirror.domain_name}"
+}
diff --git a/cdn/terraform/cloudwatch.tf b/cdn/terraform/cloudwatch.tf
new file mode 100644
index 0000000..5f790d1
--- /dev/null
+++ b/cdn/terraform/cloudwatch.tf
@@ -0,0 +1,69 @@
+# CloudWatch
+
+resource "aws_cloudwatch_metric_alarm" "alarm-estimated-charges-150-usd" {
+  alarm_name = "alarm-estimated-charges-150-usd"
+  alarm_description = "Estimated charges have exceeded 150 USD"
+  namespace = "AWS/Billing"
+  metric_name = "EstimatedCharges"
+  statistic = "Maximum"
+  period = "21600" # 6 hours
+  evaluation_periods = "1"
+  comparison_operator = "GreaterThanThreshold"
+  threshold = "150"
+  actions_enabled = true
+  alarm_actions = ["${aws_sns_topic.guix-billing-alarms.arn}"]
+  dimensions {
+    Currency = "USD"
+  }
+}
+
+resource "aws_cloudwatch_metric_alarm" "alarm-estimated-charges-140-usd" {
+  alarm_name = "alarm-estimated-charges-140-usd"
+  alarm_description = "Estimated charges have exceeded 140 USD"
+  namespace = "AWS/Billing"
+  metric_name = "EstimatedCharges"
+  statistic = "Maximum"
+  period = "21600" # 6 hours
+  evaluation_periods = "1"
+  comparison_operator = "GreaterThanThreshold"
+  threshold = "140"
+  actions_enabled = true
+  alarm_actions = ["${aws_sns_topic.guix-billing-alarms.arn}"]
+  dimensions {
+    Currency = "USD"
+  }
+}
+
+resource "aws_cloudwatch_metric_alarm" "alarm-estimated-charges-100-usd" {
+  alarm_name = "alarm-estimated-charges-100-usd"
+  alarm_description = "Estimated charges have exceeded 100 USD"
+  namespace = "AWS/Billing"
+  metric_name = "EstimatedCharges"
+  statistic = "Maximum"
+  period = "21600" # 6 hours
+  evaluation_periods = "1"
+  comparison_operator = "GreaterThanThreshold"
+  threshold = "100"
+  actions_enabled = true
+  alarm_actions = ["${aws_sns_topic.guix-billing-alarms.arn}"]
+  dimensions {
+    Currency = "USD"
+  }
+}
+
+resource "aws_cloudwatch_metric_alarm" "alarm-free-tier-exceeded" {
+  alarm_name = "alarm-free-tier-exceeded"
+  alarm_description = "Free tier exceeded - further usage will cost money"
+  namespace = "AWS/Billing"
+  metric_name = "EstimatedCharges"
+  statistic = "Maximum"
+  period = "21600" # 6 hours
+  evaluation_periods = "1"
+  comparison_operator = "GreaterThanThreshold"
+  threshold = "0"
+  actions_enabled = true
+  alarm_actions = ["${aws_sns_topic.guix-billing-alarms.arn}"]
+  dimensions {
+    Currency = "USD"
+  }
+}
diff --git a/cdn/terraform/dynamodb.tf b/cdn/terraform/dynamodb.tf
new file mode 100644
index 0000000..4f5f17f
--- /dev/null
+++ b/cdn/terraform/dynamodb.tf
@@ -0,0 +1,21 @@
+# DynamoDB
+
+# DO NOT DELETE THIS TABLE!  It contains the Terraform locking state,
+# shared by all Terraform users in the Guix project.  In addition, the
+# s3 backend's locking feature will not function without it.
+resource "aws_dynamodb_table" "terraform-locking" {
+  name = "terraform-locking"
+  # This table will not receive a steady, predictable rate of
+  # requests.  In addition, the absolute number of requests will be
+  # low.  Therefore, pay-per-request will be the most cost-effective.
+  billing_mode = "PAY_PER_REQUEST"
+  hash_key = "LockID"
+  attribute {
+    name = "LockID"
+    type = "S"
+  }
+  # Always encrypt data at rest.
+  server_side_encryption {
+    enabled = true
+  }
+}
diff --git a/cdn/terraform/iam.tf b/cdn/terraform/iam.tf
new file mode 100644
index 0000000..28eb463
--- /dev/null
+++ b/cdn/terraform/iam.tf
@@ -0,0 +1,131 @@
+# IAM
+
+# A friendly name for our account.  This is displayed in various
+# places, such as the AWS Management Console.
+
+resource "aws_iam_account_alias" "alias" {
+  account_alias = "guix"
+}
+
+# Encourage good password hygiene.
+
+resource "aws_iam_account_password_policy" "strict" {
+  minimum_password_length = 20
+  require_lowercase_characters = true
+  require_numbers = true
+  require_uppercase_characters = true
+  require_symbols = true
+  allow_users_to_change_password = true
+  password_reuse_prevention = 1
+}
+
+# The administrators group.
+
+resource "aws_iam_group" "administrators" {
+  name = "administrators"
+}
+resource "aws_iam_group_policy_attachment" "administrators-policy-attachment" {
+  group      = "${aws_iam_group.administrators.name}"
+  # This is a "managed policy".  See:
+  # 
https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_job-functions.html#jf_administrator
+  policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
+}
+resource "aws_iam_group_membership" "administrators-membership" {
+  name = "administrators-membership"
+  users = [
+    "${aws_iam_user.marusich.name}",
+    "${aws_iam_user.civodul.name}",
+    "${aws_iam_user.rekado.name}",
+  ]
+  group = "${aws_iam_group.administrators.name}"
+}
+
+# The administrators themselves.
+
+# Note that if we don't set force_destroy to true, then Terraform
+# might fail to delete the user when we remove it: See:
+# https://github.com/hashicorp/terraform/issues/8621
+
+# Chris Marusich <address@hidden>
+
+resource "aws_iam_user" "marusich" {
+  name = "marusich"
+  force_destroy = true
+}
+resource "aws_iam_access_key" "marusich-access-key-1" {
+  user = "${aws_iam_user.marusich.name}"
+  pgp_key = "${var.pgp_key_marusich}"
+}
+resource "aws_iam_user_login_profile" "marusich-login-profile" {
+  user    = "${aws_iam_user.marusich.name}"
+  pgp_key = "${var.pgp_key_marusich}"
+}
+
+output "marusich-name" {
+  value = "${aws_iam_user.marusich.name}"
+}
+output "marusich-password" {
+  value = 
"${aws_iam_user_login_profile.marusich-login-profile.encrypted_password}"
+}
+output "marusich-access-key-1-id" {
+  value = "${aws_iam_access_key.marusich-access-key-1.id}"
+}
+output "marusich-access-key-1-secret" {
+  value = "${aws_iam_access_key.marusich-access-key-1.encrypted_secret}"
+}
+
+# Ludovic Courtès <address@hidden>
+
+resource "aws_iam_user" "civodul" {
+  name = "civodul"
+  force_destroy = true
+}
+resource "aws_iam_access_key" "civodul-access-key-1" {
+  user = "${aws_iam_user.civodul.name}"
+  pgp_key = "${var.pgp_key_civodul}"
+}
+resource "aws_iam_user_login_profile" "civodul-login-profile" {
+  user    = "${aws_iam_user.civodul.name}"
+  pgp_key = "${var.pgp_key_civodul}"
+}
+
+output "civodul-name" {
+  value = "${aws_iam_user.civodul.name}"
+}
+output "civodul-password" {
+  value = 
"${aws_iam_user_login_profile.civodul-login-profile.encrypted_password}"
+}
+output "civodul-access-key-1-id" {
+  value = "${aws_iam_access_key.civodul-access-key-1.id}"
+}
+output "civodul-access-key-1-secret" {
+  value = "${aws_iam_access_key.civodul-access-key-1.encrypted_secret}"
+}
+
+# Ricardo Wurmus <address@hidden>
+
+resource "aws_iam_user" "rekado" {
+  name = "rekado"
+  force_destroy = true
+}
+resource "aws_iam_access_key" "rekado-access-key-1" {
+  user = "${aws_iam_user.rekado.name}"
+  pgp_key = "${var.pgp_key_rekado}"
+}
+resource "aws_iam_user_login_profile" "rekado-login-profile" {
+  user    = "${aws_iam_user.rekado.name}"
+  pgp_key = "${var.pgp_key_rekado}"
+}
+
+output "rekado-name" {
+  value = "${aws_iam_user.rekado.name}"
+}
+output "rekado-password" {
+  value = 
"${aws_iam_user_login_profile.rekado-login-profile.encrypted_password}"
+}
+output "rekado-access-key-1-id" {
+  value = "${aws_iam_access_key.rekado-access-key-1.id}"
+}
+output "rekado-access-key-1-secret" {
+  value = "${aws_iam_access_key.rekado-access-key-1.encrypted_secret}"
+}
diff --git a/cdn/terraform/main.tf b/cdn/terraform/main.tf
index d61d2b7..f680d9e 100644
--- a/cdn/terraform/main.tf
+++ b/cdn/terraform/main.tf
@@ -1,3 +1,8 @@
+# This file defines our backend and provider.  The remaining resources
+# are defined in separate *.tf files in this directory.  Terraform
+# merges them all together when it runs, and the order doesn't matter.
+# See: https://www.terraform.io/docs/configuration/index.html
+
 # Backend documentation:
 # https://www.terraform.io/docs/backends/types/s3.html
 terraform {
@@ -42,419 +47,3 @@ provider "aws" {
   # berlin-mirror-certificate for details.
   region = "us-east-1"
 }
-
-# IAM
-
-# A friendly name for our account.  This is displayed in various
-# places, such as the AWS Management Console.
-
-resource "aws_iam_account_alias" "alias" {
-  account_alias = "guix"
-}
-
-# Encourage good password hygiene.
-
-resource "aws_iam_account_password_policy" "strict" {
-  minimum_password_length = 20
-  require_lowercase_characters = true
-  require_numbers = true
-  require_uppercase_characters = true
-  require_symbols = true
-  allow_users_to_change_password = true
-  password_reuse_prevention = 1
-}
-
-# The administrators group.
-
-resource "aws_iam_group" "administrators" {
-  name = "administrators"
-}
-resource "aws_iam_group_policy_attachment" "administrators-policy-attachment" {
-  group      = "${aws_iam_group.administrators.name}"
-  # This is a "managed policy".  See:
-  # 
https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_job-functions.html#jf_administrator
-  policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
-}
-resource "aws_iam_group_membership" "administrators-membership" {
-  name = "administrators-membership"
-  users = [
-    "${aws_iam_user.marusich.name}",
-    "${aws_iam_user.civodul.name}",
-    "${aws_iam_user.rekado.name}",
-  ]
-  group = "${aws_iam_group.administrators.name}"
-}
-
-# The administrators themselves.
-
-# Note that if we don't set force_destroy to true, then Terraform
-# might fail to delete the user when we remove it: See:
-# https://github.com/hashicorp/terraform/issues/8621
-
-# Chris Marusich <address@hidden>
-
-resource "aws_iam_user" "marusich" {
-  name = "marusich"
-  force_destroy = true
-}
-resource "aws_iam_access_key" "marusich-access-key-1" {
-  user = "${aws_iam_user.marusich.name}"
-  pgp_key = "${var.pgp_key_marusich}"
-}
-resource "aws_iam_user_login_profile" "marusich-login-profile" {
-  user    = "${aws_iam_user.marusich.name}"
-  pgp_key = "${var.pgp_key_marusich}"
-}
-
-output "marusich-name" {
-  value = "${aws_iam_user.marusich.name}"
-}
-output "marusich-password" {
-  value = 
"${aws_iam_user_login_profile.marusich-login-profile.encrypted_password}"
-}
-output "marusich-access-key-1-id" {
-  value = "${aws_iam_access_key.marusich-access-key-1.id}"
-}
-output "marusich-access-key-1-secret" {
-  value = "${aws_iam_access_key.marusich-access-key-1.encrypted_secret}"
-}
-
-# Ludovic Courtès <address@hidden>
-
-resource "aws_iam_user" "civodul" {
-  name = "civodul"
-  force_destroy = true
-}
-resource "aws_iam_access_key" "civodul-access-key-1" {
-  user = "${aws_iam_user.civodul.name}"
-  pgp_key = "${var.pgp_key_civodul}"
-}
-resource "aws_iam_user_login_profile" "civodul-login-profile" {
-  user    = "${aws_iam_user.civodul.name}"
-  pgp_key = "${var.pgp_key_civodul}"
-}
-
-output "civodul-name" {
-  value = "${aws_iam_user.civodul.name}"
-}
-output "civodul-password" {
-  value = 
"${aws_iam_user_login_profile.civodul-login-profile.encrypted_password}"
-}
-output "civodul-access-key-1-id" {
-  value = "${aws_iam_access_key.civodul-access-key-1.id}"
-}
-output "civodul-access-key-1-secret" {
-  value = "${aws_iam_access_key.civodul-access-key-1.encrypted_secret}"
-}
-
-# Ricardo Wurmus <address@hidden>
-
-resource "aws_iam_user" "rekado" {
-  name = "rekado"
-  force_destroy = true
-}
-resource "aws_iam_access_key" "rekado-access-key-1" {
-  user = "${aws_iam_user.rekado.name}"
-  pgp_key = "${var.pgp_key_rekado}"
-}
-resource "aws_iam_user_login_profile" "rekado-login-profile" {
-  user    = "${aws_iam_user.rekado.name}"
-  pgp_key = "${var.pgp_key_rekado}"
-}
-
-output "rekado-name" {
-  value = "${aws_iam_user.rekado.name}"
-}
-output "rekado-password" {
-  value = 
"${aws_iam_user_login_profile.rekado-login-profile.encrypted_password}"
-}
-output "rekado-access-key-1-id" {
-  value = "${aws_iam_access_key.rekado-access-key-1.id}"
-}
-output "rekado-access-key-1-secret" {
-  value = "${aws_iam_access_key.rekado-access-key-1.encrypted_secret}"
-}
-
-# CloudFront
-
-resource "aws_cloudfront_distribution" "berlin-mirror" {
-  enabled = true
-  comment = "Distributed caching proxy for berlin.guixsd.org"
-  origin {
-    domain_name = "berlin.guixsd.org"
-    origin_id = "berlin.guixsd.org"
-    custom_origin_config {
-      http_port = 80 # Required, but not used.
-      https_port = 443
-      # Always use TLS when forwarding requests to the origin.
-      origin_protocol_policy = "https-only"
-      origin_ssl_protocols = ["TLSv1.2"]
-      origin_keepalive_timeout = 60
-      origin_read_timeout = 60
-    }
-  }
-  # The CNAME that will point to this CloudFront distribution.
-  aliases = ["ci.guix.info"]
-  is_ipv6_enabled = true
-  # This is actually the_maximum HTTP version to support. See:
-  # 
https://www.terraform.io/docs/providers/aws/r/cloudfront_distribution.html#http_version
-  http_version = "http2"
-  # Serve requests from all edge locations.
-  price_class = "PriceClass_All"
-  # Do not restrict access.
-  restrictions { geo_restriction { restriction_type = "none" }}
-  # When deleting the distribution, actually delete it.  See:
-  # 
https://www.terraform.io/docs/providers/aws/r/cloudfront_distribution.html#retain_on_delete
-  retain_on_delete = false
-  default_cache_behavior {
-    # Only allow "read" verbs.
-    allowed_methods = ["GET", "HEAD"]
-    cached_methods = ["GET", "HEAD"]
-    # The origin will compress data when necessary.
-    compress = false
-    # Cache responses that lack a Cache-Control header.
-    default_ttl = 86400 # 1 day
-    # When deciding whether or not to cache a response, ignore any
-    # cookies, headers, or query strings that the client included in
-    # their request.  This should increase the cache hit rate.  In
-    # addition, this also causes CloudFront to omit these values
-    # when forwarding the request to the custom origin. See:
-    # 
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/ConfiguringCaching.html
-    forwarded_values {
-      cookies { forward = "none" }
-      query_string = false
-    }
-    # Generally speaking, respect any Cache-Control or Expires
-    # headers that the origin includes in its responses.  The
-    # exception is that if a Cache-Control or Expires header says to
-    # cache the result for more than 1 year, we ignore that and only
-    # cache the result for 1 year at most.  Honestly, though, it
-    # seems unrealistic to expect CloudFront to actually keep the
-    # cached response for an entire year in that case.  See:
-    # 
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Expiration.html
-    max_ttl = 31536000 # 365 days
-    min_ttl = 0
-    target_origin_id = "berlin.guixsd.org"
-    # Before ci.guix.info pointed to this distribution, it allowed
-    # both HTTP and HTTPS.  We choose to maintain that policy here.
-    # In the future, we should consider changing this to "https-only".
-    viewer_protocol_policy = "allow-all"
-  }
-  # TODO: Maybe add more behaviors for specific paths/prefixes.
-  # ordered_cache_behavior {}
-  # TODO: Maybe set a caching behavior for error responses.
-  # custom_error_response {}
-  viewer_certificate {
-    # Note that "terraform apply" will fail until this certificate is
-    # valid.  See the comment in the definition of
-    # berlin-mirror-certificate for more information.
-    acm_certificate_arn = 
"${aws_acm_certificate.berlin-mirror-certificate.arn}"
-    # This is the recommended value as of 2018-12-28.  See:
-    # 
https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_ViewerCertificate.html
-    # 
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/secure-connections-supported-viewer-protocols-ciphers.html#secure-connections-supported-ciphers
-    minimum_protocol_version = "TLSv1.1_2016"
-    # Use SNI.  Don't use the "vip" (i.e., dedicated IP address)
-    # method, since it's expensive and unnecessary.  See:
-    # 
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cnames-https-dedicated-ip-or-sni.html
-    ssl_support_method = "sni-only"
-  }
-}
-
-output "berlin-mirror-id" {
-  value = "${aws_cloudfront_distribution.berlin-mirror.id}"
-}
-output "berlin-mirror-status" {
-  value = "${aws_cloudfront_distribution.berlin-mirror.status}"
-}
-output "berlin-mirror-domain-name" {
-  value = "${aws_cloudfront_distribution.berlin-mirror.domain_name}"
-}
-
-# S3
-
-# DO NOT DELETE THIS BUCKET!  This bucket contains the Terraform
-# state, shared by all Terraform users in the Guix project.  In
-# addition, the s3 backend will not function without it.
-resource "aws_s3_bucket" "guix-terraform-state" {
-  bucket = "guix-terraform-state"
-  # Access should be granted via IAM policies.
-  acl = "private"
-  # This allows us to recover state if something ever goes wrong - as
-  # long as we do so within the time period specified by our lifecycle
-  # policy (see below).  For details, see:
-  # https://docs.aws.amazon.com/AmazonS3/latest/dev/DeletingObjectVersions.html
-  versioning {
-    enabled = true
-  }
-  # When we destroy the bucket, destroy all objects first so that the
-  # bucket deletion succeeds.  Of course, you should think twice
-  # before deleting this bucket!
-  force_destroy = true
-  # Encrypt data at rest using S3's server side encryption.  See:
-  # https://docs.aws.amazon.com/AmazonS3/latest/dev/serv-side-encryption.html
-  server_side_encryption_configuration {
-    rule {
-      apply_server_side_encryption_by_default {
-        sse_algorithm = "AES256"
-      }
-    }
-  }
-  # The intent of this rule is to retain the current version and zero
-  # or more recent non-current versions, while preventing the size of
-  # the bucket from growing out of hand.
-  lifecycle_rule {
-    id = "clean-up"
-    enabled = true
-    # It seems unlikely that Terraform would use multi-part uploads to
-    # upload the state, since the state is small, but just in case,
-    # let's automatically abort any stuck multi-part uploads.
-    abort_incomplete_multipart_upload_days = 7
-    # Clean up old non-current versions.
-    noncurrent_version_expiration {
-      days = 14
-    }
-  }
-  lifecycle {
-    prevent_destroy = true
-  }
-}
-
-# ACM
-
-# Terraform will create this certificate automatically.  However, to
-# validate it requires one-time manual action outside of Terraform.
-# This is because there don't seem to be any Terraform providers that
-# are compatible with our DNS registrar.  To create and validate the
-# certificate, you must do the following in order:
-#
-#   - Run "terraform apply" to create the certificate.
-#   - Run "terraform show" to view the CNAME record ACM needs you to
-#     create in order to prove domain ownership.
-#   - Manually create the CNAME record.
-#   - Run "terraform apply" or "terraform plan" again to ensure the
-#     resources are in their final, correct state.
-#   - Run "terraform show" to verify that the certificate is now
-#     listed as "validated".
-#   - Repeat the last two steps until the validation succeeds.
-#
-# This only has to be done once.  For more information, see:
-# https://docs.aws.amazon.com/acm/latest/userguide/gs-acm-validate-dns.html
-#
-# Finally, since we intend to use this certificate with our CloudFront
-# distribution, we must create it in the us-east-1 region.  See:
-# https://docs.aws.amazon.com/acm/latest/userguide/acm-services.html
-# 
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cnames-and-https-requirements.html
-resource "aws_acm_certificate" "berlin-mirror-certificate" {
-  domain_name       = "ci.guix.info"
-  validation_method = "DNS"
-  # The AWS provider documentation recommends setting
-  # create_before_destroy to true in a lifecycle block.  We probably
-  # won't need this, since we don't currently plan to replace the
-  # existing certificate using Terraform (ACM will just rotate it for
-  # us automatically), but it doesn't hurt to include this here.
-  lifecycle {
-    create_before_destroy = true
-  }
-}
-
-# SNS
-
-# Email subscriptions cannot be managed via Terraform.  Therefore, any
-# email subscriptions must be configured manually.  See:
-# https://www.terraform.io/docs/providers/aws/r/sns_topic_subscription.html
-# 
https://docs.aws.amazon.com/sns/latest/dg/sns-getting-started.html#SubscribeTopic
-resource "aws_sns_topic" "guix-billing-alarms" {
-  name = "guix-billing-alarms"
-}
-
-# CloudWatch
-
-resource "aws_cloudwatch_metric_alarm" "alarm-estimated-charges-150-usd" {
-  alarm_name = "alarm-estimated-charges-150-usd"
-  alarm_description = "Estimated charges have exceeded 150 USD"
-  namespace = "AWS/Billing"
-  metric_name = "EstimatedCharges"
-  statistic = "Maximum"
-  period = "21600" # 6 hours
-  evaluation_periods = "1"
-  comparison_operator = "GreaterThanThreshold"
-  threshold = "150"
-  actions_enabled = true
-  alarm_actions = ["${aws_sns_topic.guix-billing-alarms.arn}"]
-  dimensions {
-    Currency = "USD"
-  }
-}
-
-resource "aws_cloudwatch_metric_alarm" "alarm-estimated-charges-140-usd" {
-  alarm_name = "alarm-estimated-charges-140-usd"
-  alarm_description = "Estimated charges have exceeded 140 USD"
-  namespace = "AWS/Billing"
-  metric_name = "EstimatedCharges"
-  statistic = "Maximum"
-  period = "21600" # 6 hours
-  evaluation_periods = "1"
-  comparison_operator = "GreaterThanThreshold"
-  threshold = "140"
-  actions_enabled = true
-  alarm_actions = ["${aws_sns_topic.guix-billing-alarms.arn}"]
-  dimensions {
-    Currency = "USD"
-  }
-}
-
-resource "aws_cloudwatch_metric_alarm" "alarm-estimated-charges-100-usd" {
-  alarm_name = "alarm-estimated-charges-100-usd"
-  alarm_description = "Estimated charges have exceeded 100 USD"
-  namespace = "AWS/Billing"
-  metric_name = "EstimatedCharges"
-  statistic = "Maximum"
-  period = "21600" # 6 hours
-  evaluation_periods = "1"
-  comparison_operator = "GreaterThanThreshold"
-  threshold = "100"
-  actions_enabled = true
-  alarm_actions = ["${aws_sns_topic.guix-billing-alarms.arn}"]
-  dimensions {
-    Currency = "USD"
-  }
-}
-
-resource "aws_cloudwatch_metric_alarm" "alarm-free-tier-exceeded" {
-  alarm_name = "alarm-free-tier-exceeded"
-  alarm_description = "Free tier exceeded - further usage will cost money"
-  namespace = "AWS/Billing"
-  metric_name = "EstimatedCharges"
-  statistic = "Maximum"
-  period = "21600" # 6 hours
-  evaluation_periods = "1"
-  comparison_operator = "GreaterThanThreshold"
-  threshold = "0"
-  actions_enabled = true
-  alarm_actions = ["${aws_sns_topic.guix-billing-alarms.arn}"]
-  dimensions {
-    Currency = "USD"
-  }
-}
-
-# DynamoDB
-
-# DO NOT DELETE THIS TABLE!  It contains the Terraform locking state,
-# shared by all Terraform users in the Guix project.  In addition, the
-# s3 backend's locking feature will not function without it.
-resource "aws_dynamodb_table" "terraform-locking" {
-  name = "terraform-locking"
-  # This table will not receive a steady, predictable rate of
-  # requests.  In addition, the absolute number of requests will be
-  # low.  Therefore, pay-per-request will be the most cost-effective.
-  billing_mode = "PAY_PER_REQUEST"
-  hash_key = "LockID"
-  attribute {
-    name = "LockID"
-    type = "S"
-  }
-  # Always encrypt data at rest.
-  server_side_encryption {
-    enabled = true
-  }
-}
diff --git a/cdn/terraform/s3.tf b/cdn/terraform/s3.tf
new file mode 100644
index 0000000..caf6cbf
--- /dev/null
+++ b/cdn/terraform/s3.tf
@@ -0,0 +1,48 @@
+# S3
+
+# DO NOT DELETE THIS BUCKET!  This bucket contains the Terraform
+# state, shared by all Terraform users in the Guix project.  In
+# addition, the s3 backend will not function without it.
+resource "aws_s3_bucket" "guix-terraform-state" {
+  bucket = "guix-terraform-state"
+  # Access should be granted via IAM policies.
+  acl = "private"
+  # This allows us to recover state if something ever goes wrong - as
+  # long as we do so within the time period specified by our lifecycle
+  # policy (see below).  For details, see:
+  # https://docs.aws.amazon.com/AmazonS3/latest/dev/DeletingObjectVersions.html
+  versioning {
+    enabled = true
+  }
+  # When we destroy the bucket, destroy all objects first so that the
+  # bucket deletion succeeds.  Of course, you should think twice
+  # before deleting this bucket!
+  force_destroy = true
+  # Encrypt data at rest using S3's server side encryption.  See:
+  # https://docs.aws.amazon.com/AmazonS3/latest/dev/serv-side-encryption.html
+  server_side_encryption_configuration {
+    rule {
+      apply_server_side_encryption_by_default {
+        sse_algorithm = "AES256"
+      }
+    }
+  }
+  # The intent of this rule is to retain the current version and zero
+  # or more recent non-current versions, while preventing the size of
+  # the bucket from growing out of hand.
+  lifecycle_rule {
+    id = "clean-up"
+    enabled = true
+    # It seems unlikely that Terraform would use multi-part uploads to
+    # upload the state, since the state is small, but just in case,
+    # let's automatically abort any stuck multi-part uploads.
+    abort_incomplete_multipart_upload_days = 7
+    # Clean up old non-current versions.
+    noncurrent_version_expiration {
+      days = 14
+    }
+  }
+  lifecycle {
+    prevent_destroy = true
+  }
+}



reply via email to

[Prev in Thread] Current Thread [Next in Thread]