From fc6eedaf15285df6a053ce25d7c003a677b0bcb1 Mon Sep 17 00:00:00 2001 From: Alex Steel <130377221+asteel-gsa@users.noreply.github.com> Date: Fri, 26 Jul 2024 13:26:58 -0400 Subject: [PATCH] Manage cors headers in terraform (#4115) * Initial cors script test * add depends_on * Trying out the cors json via jsonencode * add var * testing * give interpreter and working_dir * add cf target command * add aws * trim space * give proper path for aws * force delete key * set the actual domain * trying decoded json * more testing * trying map * Testing decoded_json local * Testing moving the string json into module * typo fix * Undo the decode * Make executable * Test with json file * change script_path * add trigger * Fix the jq * Add env specific CORS files * Add info statements for logs * Add a small sleep for CF API * Quiet unzip output * rename resource * Add an informational comment on why the trigger={} was added --- terraform/shared/modules/cors/cors-script.sh | 24 +++++++++++++++++++ terraform/shared/modules/cors/cors.tf | 17 +++++++++++++ terraform/shared/modules/cors/dev-cors.json | 19 +++++++++++++++ .../shared/modules/cors/preview-cors.json | 19 +++++++++++++++ .../shared/modules/cors/production-cors.json | 19 +++++++++++++++ .../shared/modules/cors/staging-cors.json | 19 +++++++++++++++ terraform/shared/modules/cors/variables.tf | 12 ++++++++++ terraform/shared/modules/env/cors.tf | 6 +++++ terraform/shared/modules/env/variables.tf | 2 +- 9 files changed, 136 insertions(+), 1 deletion(-) create mode 100755 terraform/shared/modules/cors/cors-script.sh create mode 100644 terraform/shared/modules/cors/cors.tf create mode 100644 terraform/shared/modules/cors/dev-cors.json create mode 100644 terraform/shared/modules/cors/preview-cors.json create mode 100644 terraform/shared/modules/cors/production-cors.json create mode 100644 terraform/shared/modules/cors/staging-cors.json create mode 100644 terraform/shared/modules/cors/variables.tf create mode 100644 terraform/shared/modules/env/cors.tf diff --git a/terraform/shared/modules/cors/cors-script.sh b/terraform/shared/modules/cors/cors-script.sh new file mode 100755 index 000000000..792db9f91 --- /dev/null +++ b/terraform/shared/modules/cors/cors-script.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +curl -L "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" +unzip -q awscliv2.zip && rm awscliv2.zip +./aws/install -i ~/usr -b ~/bin +/github/home/bin/aws --version + +cf t -o "$1" -s "$2" +SERVICE_INSTANCE_NAME=fac-public-s3; +KEY_NAME=fac-public-s3-key; +cf create-service-key "${SERVICE_INSTANCE_NAME}" "${KEY_NAME}"; +echo "Sleeping for CF API" +sleep 10 +S3_CREDENTIALS=$(cf service-key "${SERVICE_INSTANCE_NAME}" "${KEY_NAME}" | tail -n +2); +export AWS_ACCESS_KEY_ID="$(echo "$S3_CREDENTIALS" | jq -r .credentials.access_key_id)"; +export AWS_SECRET_ACCESS_KEY="$(echo "$S3_CREDENTIALS" | jq -r .credentials.secret_access_key)"; +export BUCKET_NAME="$(echo "$S3_CREDENTIALS" | jq -r .credentials.bucket)"; +export AWS_DEFAULT_REGION="$(echo "$S3_CREDENTIALS" | jq -r .credentials.region)"; +echo "Bucket: $BUCKET_NAME"; +echo "INFO: Putting CORS config in bucket..." +/github/home/bin/aws s3api put-bucket-cors --bucket "$BUCKET_NAME" --cors-configuration file://"$3"; +echo "INFO: aws s3api get-bucket-cors output..." +/github/home/bin/aws s3api get-bucket-cors --bucket "$BUCKET_NAME"; +cf delete-service-key -f "${SERVICE_INSTANCE_NAME}" "${KEY_NAME}"; diff --git a/terraform/shared/modules/cors/cors.tf b/terraform/shared/modules/cors/cors.tf new file mode 100644 index 000000000..0b6a165b2 --- /dev/null +++ b/terraform/shared/modules/cors/cors.tf @@ -0,0 +1,17 @@ +locals { + script_path = "${var.cf_space_name}-cors.json" +} +resource "null_resource" "cors_header" { + provisioner "local-exec" { + working_dir = path.module + interpreter = ["/bin/bash", "-c"] + command = "./cors-script.sh ${var.cf_org_name} ${var.cf_space_name} ${local.script_path}" + } + # https://github.com/hashicorp/terraform/issues/8266#issuecomment-454377049 + # A clever way to get this to run every time, otherwise we would be relying on + # an md5 hash, which, once this goes into the system, will rarely (if ever) + # be updated + triggers = { + always_run = "${timestamp()}" + } +} diff --git a/terraform/shared/modules/cors/dev-cors.json b/terraform/shared/modules/cors/dev-cors.json new file mode 100644 index 000000000..c09962d06 --- /dev/null +++ b/terraform/shared/modules/cors/dev-cors.json @@ -0,0 +1,19 @@ +{ + "CORSRules": [ + { + "AllowedHeaders": [ + "Authorization" + ], + "AllowedMethods": [ + "HEAD", + "GET" + ], + "AllowedOrigins": [ + "https://fac-dev.app.cloud.gov" + ], + "ExposeHeaders": [ + "ETag" + ] + } + ] + } diff --git a/terraform/shared/modules/cors/preview-cors.json b/terraform/shared/modules/cors/preview-cors.json new file mode 100644 index 000000000..90aa60fa3 --- /dev/null +++ b/terraform/shared/modules/cors/preview-cors.json @@ -0,0 +1,19 @@ +{ + "CORSRules": [ + { + "AllowedHeaders": [ + "Authorization" + ], + "AllowedMethods": [ + "HEAD", + "GET" + ], + "AllowedOrigins": [ + "https://fac-preview.app.cloud.gov" + ], + "ExposeHeaders": [ + "ETag" + ] + } + ] + } diff --git a/terraform/shared/modules/cors/production-cors.json b/terraform/shared/modules/cors/production-cors.json new file mode 100644 index 000000000..d8ce983bd --- /dev/null +++ b/terraform/shared/modules/cors/production-cors.json @@ -0,0 +1,19 @@ +{ + "CORSRules": [ + { + "AllowedHeaders": [ + "Authorization" + ], + "AllowedMethods": [ + "HEAD", + "GET" + ], + "AllowedOrigins": [ + "https://app.cloud.gov" + ], + "ExposeHeaders": [ + "ETag" + ] + } + ] + } diff --git a/terraform/shared/modules/cors/staging-cors.json b/terraform/shared/modules/cors/staging-cors.json new file mode 100644 index 000000000..4c572e560 --- /dev/null +++ b/terraform/shared/modules/cors/staging-cors.json @@ -0,0 +1,19 @@ +{ + "CORSRules": [ + { + "AllowedHeaders": [ + "Authorization" + ], + "AllowedMethods": [ + "HEAD", + "GET" + ], + "AllowedOrigins": [ + "https://fac-staging.app.cloud.gov" + ], + "ExposeHeaders": [ + "ETag" + ] + } + ] + } diff --git a/terraform/shared/modules/cors/variables.tf b/terraform/shared/modules/cors/variables.tf new file mode 100644 index 000000000..ead47fc3c --- /dev/null +++ b/terraform/shared/modules/cors/variables.tf @@ -0,0 +1,12 @@ +variable "cf_org_name" { + type = string + description = "name of the organization to configure" + default = "gsa-tts-oros-fac" +} + +variable "cf_space_name" { + type = string + description = "name of the space to configure" + # No default... The calling module knows which env is for which space and we + # shouldn't assume it! +} diff --git a/terraform/shared/modules/env/cors.tf b/terraform/shared/modules/env/cors.tf new file mode 100644 index 000000000..652cafadf --- /dev/null +++ b/terraform/shared/modules/env/cors.tf @@ -0,0 +1,6 @@ +module "cors" { + source = "../cors" + cf_org_name = var.cf_org_name + cf_space_name = var.cf_space_name + depends_on = [module.s3-public] +} diff --git a/terraform/shared/modules/env/variables.tf b/terraform/shared/modules/env/variables.tf index dfb532a14..ce7c4d29e 100644 --- a/terraform/shared/modules/env/variables.tf +++ b/terraform/shared/modules/env/variables.tf @@ -109,4 +109,4 @@ variable "new_relic_account_id" { variable "new_relic_api_key" { type = string description = "New Relic API key" -} \ No newline at end of file +}