moved infrastructure config out of this repo

This commit is contained in:
Jocelyn Badgley 2024-10-06 10:42:34 -07:00
parent 922e627fed
commit 16e00a195b
No known key found for this signature in database
GPG Key ID: 909059F0FFF842D8
16 changed files with 0 additions and 1195 deletions

View File

@ -1,83 +0,0 @@
# This file is maintained automatically by "terraform init".
# Manual edits may be lost in future updates.
provider "registry.terraform.io/hashicorp/archive" {
version = "2.3.0"
hashes = [
"h1:NaDbOqAcA9d8DiAS5/6+5smXwN3/+twJGb3QRiz6pNw=",
"zh:0869128d13abe12b297b0cd13b8767f10d6bf047f5afc4215615aabc39c2eb4f",
"zh:481ed837d63ba3aa45dd8736da83e911e3509dee0e7961bf5c00ed2644f807b3",
"zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
"zh:9f08fe2977e2166849be24fb9f394e4d2697414d463f7996fd0d7beb4e19a29c",
"zh:9fe566deeafd460d27999ca0bbfd85426a5fcfcb40007b23884deb76da127b6f",
"zh:a1bd9a60925d9769e0da322e4523330ee86af9dc2e770cba1d0247a999ef29cb",
"zh:bb4094c8149f74308b22a87e1ac19bcccca76e8ef021b571074d9bccf1c0c6f0",
"zh:c8984c9def239041ce41ec8e19bbd76a49e74ed2024ff736dad60429dee89bcc",
"zh:ea4bb5ae73db1de3a586e62f39106f5e56770804a55aa5e6b4f642df973e0e75",
"zh:f44a9d596ecc3a8c5653f56ba0cd202ad93b49f76767f4608daf7260b813289e",
"zh:f5c5e6cc9f7f070020ab7d95fcc9ed8e20d5cf219978295a71236e22cbb6d508",
"zh:fd2273f51dcc8f43403bf1e425ba9db08a57c3ddcba5ad7a51742ccde21ca611",
]
}
provider "registry.terraform.io/hashicorp/aws" {
version = "4.55.0"
hashes = [
"h1:vSVjfh4GIrca2Z3YPjWMaac5hOEBc1U3xOOwFmo7HZc=",
"zh:0866f25575bad3b9c313cd778c94fc65e79d335af2d20a3480f79d7731d93b7b",
"zh:2c05c16155cbc054622cf83e4b6614fef35935b00b238e4c21ee225e6c896770",
"zh:2efba66649fb12af0492c6cce4e2361fe9139df648734264f61a9a1ef754df53",
"zh:3c60bb53e3b65d7f86699fae0797a55a9aa41b8ba377aaff4daf23d1661393a9",
"zh:41f6dcd90b54b623d523df8fb4a30779cfe22e9ab59516bc05b29291a7af0946",
"zh:4b8330b154e9e2d035dd5488abcac25efec1fa6055d3a70894a8c0384f0579d6",
"zh:595f263706cf1fb6b8447e2ec343638de4360841a15e6bff6ccbb0ff86c7ce74",
"zh:5dfc5b858a43cf45fde5542eb673f6104c14cdc3d73843d1b87a9e44545cbad4",
"zh:7bbe05cf30521f0110603bb84995a4025ce7810626010276600e4b402143df27",
"zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425",
"zh:a490e68c63504d3301d6dcb700c95778d93bb2baa6632a46c5a1d62862a7067c",
"zh:c4f9f6659148528375c8a822163925c9aae490ccce2e6301cefbbab009531971",
"zh:ef66070f957408f1c924ddfd5dbd0d34bce16efd9e36ccecbf699de72beb131f",
"zh:f7ba5e3e62a2b51b24e326797a89fdd86bafaea7d1912738d514c9903c14d7f2",
"zh:ffc20b7d9f7bd331fb6451d0fc92c68196383d7115e69380de6566cc268cb9b9",
]
}
provider "registry.terraform.io/hashicorp/http" {
version = "3.2.1"
hashes = [
"h1:Q2YQZzEhHQVlkQCQVpMzFVs0Gg+eXzISbOwaOYqpflc=",
"zh:088b3b3128034485e11dff8da16e857d316fbefeaaf5bef24cceda34c6980641",
"zh:09ed1f2462ea4590b112e048c4af556f0b6eafc7cf2c75bb2ac21cd87ca59377",
"zh:39c6b0b4d3f0f65e783c467d3f634e2394820b8aef907fcc24493f21dcf73ca3",
"zh:47aab45327daecd33158a36c1a36004180a518bf1620cdd5cfc5e1fe77d5a86f",
"zh:4d70a990aa48116ab6f194eef393082c21cf58bece933b63575c63c1d2b66818",
"zh:65470c43fda950c7e9ac89417303c470146de984201fff6ef84299ea29e02d30",
"zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
"zh:842b4dd63e438f5cd5fdfba1c09b8fdf268e8766e6690988ee24e8b25bfd9e8d",
"zh:a167a057f7e2d80c78d4b4057538588131fceb983d5c93b07675ad9eb1aa5790",
"zh:d0ba69b62b6db788cfe3cf8f7dc6e9a0eabe2927dc119d7fe3fe6573ee559e66",
"zh:e28d24c1d5ff24b1d1cc6f0074a1f41a6974f473f4ff7a37e55c7b6dca68308a",
"zh:fde8a50554960e5366fd0e1ca330a7c1d24ae6bbb2888137a5c83d83ce14fd18",
]
}
provider "registry.terraform.io/namecheap/namecheap" {
version = "2.1.0"
constraints = ">= 2.0.0"
hashes = [
"h1:wYjp1Gs7wf2J+VtkLmTRO6mALieCFhS0HYsQUwAbAUI=",
"zh:3731f5f14a0958cd27a589ef7daa9be786b6490f2309c429eb2e9862aa4ac5f7",
"zh:3cbceb12ec3521d9dfbd890eee731a40f4e1f42de30d28fc1d1e524091148caa",
"zh:44095af1b1d1ee6d4b930e21e3c5bf0f81d9df65fe04f6f1e55d46713c240b21",
"zh:693e169228fe0c5fb1989425b1ad42c1206f8187c9932b4daee5a5c5e851a28e",
"zh:6b04c3c2666db3050f49bc85151496fe33cf852db9ad8fc6f455d1daf0a2bba6",
"zh:85fd126a573cc468f8d5d1b90f4a94f5977ea40623b1c5cd7c799bb95ef233bd",
"zh:99014437ef4e96161b0029efa12f05fa1ab63ff9bc0a255b0a249e17b4f8587a",
"zh:a4d8288ef01d4002a5aa07d1e64e4504757f07d6ada24fbf7d3670ceb24d2871",
"zh:d27f7798cbe1957294bb08459b1fbabe68721cc9cc50afee80bda87ce674dab8",
"zh:d85483f90380829d05b8a2725ce50bf2ee766d6c1cbef223b388d19c5a92dce2",
"zh:ddfecfbefd32e40386b482a2610e4173a52591afea3861f041041439d51d34da",
"zh:f9a10edfe11dbc4947cbb2f0db8935050693d5fff3b6559096288c689c2dd847",
"zh:fae14a74781a94bcaac07b6d533dd9eb1e40c1d152eb6ee49b2a44cdf5740cfe",
]
}

View File

@ -1,45 +0,0 @@
# -----------------------------------------------------------------------------------------------------------
# Website SSL Certificate
resource "aws_acm_certificate" "cert" {
domain_name = var.domain
validation_method = "DNS"
subject_alternative_names = formatlist("%s.%s",
var.subdomains,
var.domain,
)
tags = {
Name = "Site Certificate"
Site = var.site
Category = "SSL"
}
lifecycle {
create_before_destroy = true
}
}
resource "aws_route53_record" "cert_validation" {
for_each = {
for dvo in aws_acm_certificate.cert.domain_validation_options : dvo.domain_name => {
name = dvo.resource_record_name
record = dvo.resource_record_value
type = dvo.resource_record_type
}
}
allow_overwrite = true
name = each.value.name
records = [each.value.record]
ttl = 60
type = each.value.type
zone_id = aws_route53_zone.zone.id
}
resource "aws_acm_certificate_validation" "cert" {
certificate_arn = aws_acm_certificate.cert.arn
validation_record_fqdns = [for record in aws_route53_record.cert_validation : record.fqdn]
}

View File

@ -1,49 +0,0 @@
data "aws_caller_identity" "current" {}
data "aws_region" "current" {}
resource "aws_cloudwatch_log_group" "ipixel_results" {
name = "/aws/ipixel/${var.site}"
retention_in_days = 90
tags = {
Site = var.site,
Role = "ipixel"
}
}
data "aws_iam_policy_document" "logs_cloudwatch_log_group" {
statement {
actions = ["logs:DescribeLogStreams"]
resources = ["arn:aws:logs:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:*"]
}
statement {
actions = ["logs:CreateLogStream", "logs:PutLogEvents"]
resources = ["${aws_cloudwatch_log_group.ipixel_results.arn}:*"]
}
}
resource "aws_cloudwatch_log_group" "ipixel_parser_logs" {
name = "/aws/ipixel_parser/${var.site}"
retention_in_days = 3
tags = {
Site = var.site,
Role = "ipixel"
}
}
data "aws_iam_policy_document" "ipixel_parser_cloudwatch_log_group" {
statement {
actions = ["logs:DescribeLogStreams"]
resources = ["arn:aws:logs:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:*"]
}
statement {
actions = ["logs:CreateLogStream", "logs:PutLogEvents"]
resources = ["${aws_cloudwatch_log_group.ipixel_parser_logs.arn}:*"]
}
}

View File

@ -1,74 +0,0 @@
# -----------------------------------------------------------------------------------------------------------
# Site DNS Zone and extra domains
resource "aws_route53_zone" "zone" {
name = var.domain
tags = {
Site = var.site
Category = "DNS"
}
}
# -----------------------------------------------------------------------------------------------------------
# Email Domains
resource "aws_route53_record" "mail_exchange" {
zone_id = aws_route53_zone.zone.zone_id
name = ""
type = "MX"
ttl = 86400
records = [
"1 ASPMX.L.GOOGLE.COM",
"5 ALT1.ASPMX.L.GOOGLE.COM",
"5 ALT2.ASPMX.L.GOOGLE.COM",
"10 ASPMX2.GOOGLEMAIL.COM",
"10 ASPMX3.GOOGLEMAIL.COM",
]
}
resource "aws_route53_record" "google_mail_verify" {
zone_id = aws_route53_zone.zone.zone_id
name = ""
type = "TXT"
ttl = 300
records = [
"google-site-verification=qidEaa68dfZvcMDRv-pQdLlTSUpF1TJWiwtaVoGK8s8",
]
}
resource "aws_route53_record" "google_mail_secure" {
zone_id = aws_route53_zone.zone.zone_id
name = ""
type = "SPF"
ttl = 86400
records = [
"v=spf1 include:_spf.google.com ~all"
]
}
resource "aws_route53_record" "dkim" {
zone_id = aws_route53_zone.zone.zone_id
name = "google._domainkey"
type = "TXT"
ttl = 300
records = [
"v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwwirvGkh1h1vMmlK1IEHgs6tlfvkGPv7OLT2yz8hppjTe+sIov8DcBsj3NwotlywotXXgibO5fRJfLHgz0t0eTGeY15c/3K75VnVtKTm4QQ80COU/dCQ1ZbdSmfthEA7w2r0rAEXf20/2J+s8JzCwUidPQfCoYDH+QfSSw\"\"LjOwzSrjBPn+gg2Weh75DxmPHvw1mxA1WD0s+QjZlrLs4hgv41LMJr68Jh5zy+FVRNJAFX1HHVumZDS0StbaDU6r7CvARODQjv+0YMHQRvhDN9LXPp+RGRIegF6ApUM4nEDhDAiM8a/ubUXacX3jMMrSuHgxwhKAk6l0m/LctiNZ943QIDAQAB"
]
}
resource "aws_route53_record" "github_validation" {
zone_id = aws_route53_zone.zone.zone_id
name = "_github-challenge-GenderDysphoria.genderdysphoria.fyi"
type = "TXT"
ttl = 300
records = ["9321b5e6e7"]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 B

View File

@ -1,22 +0,0 @@
// This is a solution for the problem with s3 websites and subfolders www.site.com/folder/ will not auto
// redirect to www.site.com/folder/index.html like most other modern web servers
// This should be deployed as a Lambda@Edge connected to the CloudFront Distribution
// Only Node.js 10.x Runtime supports Lambda@Edge for right now, we have to wait for AWS to support 12x and beyond
exports.handler = async (event) => {
/*
* Expand S3 request to have index.html if it ends in /
*/
const request = event.Records[0].cf.request;
if ((request.uri !== '/') /* Not the root object, which redirects properly */
&& (request.uri.endsWith('/') /* Folder with slash */
|| (request.uri.lastIndexOf('.') < request.uri.lastIndexOf('/')) /* Most likely a folder, it has no extension (heuristic) */
)) {
if (request.uri.endsWith('/')) {
request.uri = request.uri.concat('index.html');
} else {
request.uri = request.uri.concat('/index.html');
}
}
return request;
};

View File

@ -1,23 +0,0 @@
CREATE EXTERNAL TABLE gdbible.events (
dts TIMESTAMP,
page STRING,
client_start TIMESTAMP,
client_end TIMESTAMP,
duration INT,
useragent struct<
browser: struct< name:STRING, version:STRING, major: INT >,
os: struct< name:STRING, version:STRING >
>,
`query` struct<
tid: STRING,
page_height:INT,
viewport_height:INT,
max_scroll:INT,
viewed:INT,
language:STRING,
referrer:STRING
>,
original struct<c_ip: STRING>
)
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
LOCATION 's3://gdbible-analytics/Converted'

View File

@ -1,98 +0,0 @@
# -----------------------------------------------------------------------------------------------------------
# IAM Role for Redirect Lambda
data "aws_iam_policy_document" "lambda_redirect" {
statement {
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = [
"edgelambda.amazonaws.com",
"lambda.amazonaws.com"
]
}
}
}
resource "aws_iam_role" "lambda_redirect" {
name = "${var.site}-lambda-redirect-role"
assume_role_policy = data.aws_iam_policy_document.lambda_redirect.json
tags = {
Site = var.site
}
}
#######################################################
# LOGGING POLICY
data "aws_iam_policy_document" "lambda_logging" {
statement {
actions = [
"logs:CreateLogStream",
"logs:PutLogEvents",
"logs:CreateLogGroup"
]
resources = [ "arn:aws:logs:*:*:*" ]
}
}
resource "aws_iam_policy" "lambda_logging" {
name = "${var.site}_lambda_logging"
path = "/"
description = "IAM policy for logging from a lambda"
policy = data.aws_iam_policy_document.lambda_logging.json
}
resource "aws_iam_role_policy_attachment" "lambda_logs" {
role = aws_iam_role.lambda_redirect.name
policy_arn = aws_iam_policy.lambda_logging.arn
}
#######################################################
# REPLICATION POLICY
# aws_iam_policy_document.lambda_replication
data "aws_iam_policy_document" "lambda_replication" {
statement {
actions = [
"lambda:EnableReplication*",
]
resources = [
"*"
]
}
statement {
actions = [
"iam:CreateServiceLinkedRole"
]
resources = [
"arn:aws:iam::*:role/aws-service-role/events.amazonaws.com/AWSServiceRoleForCloudWatchEvents*"
]
condition {
test = "StringLike"
variable = "iam:AWSServiceName"
values = ["events.amazonaws.com"]
}
}
}
resource "aws_iam_policy" "lambda_replication" {
name = "${var.site}_lambda_replication"
path = "/"
description = "IAM policy for replication by lambda@edge"
policy = data.aws_iam_policy_document.lambda_replication.json
}
resource "aws_iam_role_policy_attachment" "lambda_replication" {
role = aws_iam_role.lambda_redirect.name
policy_arn = aws_iam_policy.lambda_replication.arn
}

View File

@ -1,22 +0,0 @@
resource "aws_organizations_organization" "org" {
aws_service_access_principals = [
"cloudtrail.amazonaws.com",
"config.amazonaws.com",
]
feature_set = "ALL"
}
data "aws_organizations_organization" "gdb" {}
resource "aws_organizations_organizational_unit" "gdb" {
name = "Gender Dysphoria Bible"
parent_id = data.aws_organizations_organization.gdb.roots[0].id
}
resource "aws_organizations_account" "account" {
name = "gdb-manage"
email = "aws@genderdysphoria.fyi"
parent_id = aws_organizations_organizational_unit.gdb.id
}

View File

@ -1,29 +0,0 @@
exports.handler = async (event) => {
const { uri, querystring } = event?.Records?.[0]?.cf?.request || {};
const url = new URL(uri, `https://genderdysphoria.fyi`);
url.search = new URLSearchParams(querystring);
const body = `
<!DOCTYPE html>
<html lang="en">
<head><title>Gender Dysphoria Bible</title></head>
<body bgcolor="white">
<h1>Redirecting...</h1>
<a href="${url}">Click here if you are not redirected.</a>
</body>
</html>
`;
return {
status: '301',
statusDescription: `Redirecting to www domain`,
headers: {
location: [{
key: 'Location',
value: url.toString()
}],
},
body
};
};

View File

@ -1,227 +0,0 @@
# Site DNS Zone and extra domains
# -----------------------------------------------------------------------------------------------------------
# aws_route53_zone.zone
resource "aws_route53_zone" "short_redirect" {
name = var.shortdomain
tags = {
Site = var.site
Category = "DNS"
}
}
# namecheap_domain_records.zone
resource "namecheap_domain_records" "short_redirect" {
domain = var.shortdomain
mode = "OVERWRITE"
nameservers = aws_route53_zone.short_redirect.name_servers
}
# -----------------------------------------------------------------------------------------------------------
# SSL Certificate
# aws_acm_certificate.cert
resource "aws_acm_certificate" "shortcert" {
domain_name = var.shortdomain
validation_method = "DNS"
subject_alternative_names = [
"www.${var.shortdomain}",
]
tags = {
Name = "Site Certificate"
Site = var.site
Category = "SSL"
}
lifecycle {
create_before_destroy = true
}
depends_on = [
namecheap_domain_records.short_redirect,
]
}
resource "aws_route53_record" "shortcert" {
count = length(aws_acm_certificate.shortcert.domain_validation_options)
zone_id = aws_route53_zone.short_redirect.id
name = element(aws_acm_certificate.shortcert.domain_validation_options.*.resource_record_name, count.index)
type = element(aws_acm_certificate.shortcert.domain_validation_options.*.resource_record_type, count.index)
records = [element(aws_acm_certificate.shortcert.domain_validation_options.*.resource_record_value, count.index)]
ttl = 60
}
resource "aws_acm_certificate_validation" "shortcert" {
certificate_arn = aws_acm_certificate.shortcert.arn
validation_record_fqdns = aws_route53_record.shortcert.*.fqdn
}
# -----------------------------------------------------------------------------------------------------------
# Redirection Bucket
data "aws_iam_policy_document" "cloudfront_access" {
statement {
sid = "AllowCFOriginAccess"
actions = [
"s3:GetObject",
]
resources = [
"${aws_s3_bucket.short_redirect.arn}/*",
]
principals {
type = "*"
identifiers = ["*"]
}
}
}
resource "aws_s3_bucket_policy" "cloudfront_access" {
bucket = aws_s3_bucket.short_redirect.id
policy = data.aws_iam_policy_document.cloudfront_access.json
}
resource "aws_s3_bucket" "short_redirect" {
bucket = "${var.shortdomain}"
}
resource "aws_s3_bucket_acl" "short_redirect" {
bucket = aws_s3_bucket.short_redirect.id
acl = "public-read"
}
resource "aws_s3_bucket_website_configuration" "short_redirect" {
bucket = aws_s3_bucket.short_redirect.bucket
redirect_all_requests_to {
host_name = var.domain
protocol = "https"
}
}
resource "aws_cloudfront_distribution" "short_redirect" {
origin {
domain_name = aws_s3_bucket.short_redirect.bucket_regional_domain_name
origin_id = aws_s3_bucket.short_redirect.bucket
custom_origin_config {
http_port = 80
https_port = 443
origin_protocol_policy = "http-only"
origin_ssl_protocols = ["SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2"]
}
}
comment = aws_s3_bucket.short_redirect.bucket
enabled = true
is_ipv6_enabled = false
aliases = ["www.${var.shortdomain}", var.shortdomain]
restrictions {
geo_restriction {
restriction_type = "none"
}
}
default_cache_behavior {
allowed_methods = ["GET", "HEAD"]
cached_methods = ["GET", "HEAD"]
target_origin_id = aws_s3_bucket.short_redirect.bucket
compress = true
min_ttl = 31536000
max_ttl = 31536000
default_ttl = 31536000
forwarded_values {
query_string = false
cookies {
forward = "none"
}
}
lambda_function_association {
event_type = "viewer-request"
lambda_arn = aws_lambda_function.short_redirect.qualified_arn
include_body = false
}
viewer_protocol_policy = "allow-all"
}
viewer_certificate {
acm_certificate_arn = aws_acm_certificate.shortcert.arn
ssl_support_method = "sni-only"
}
wait_for_deployment = false
depends_on = [aws_acm_certificate_validation.shortcert]
}
resource "aws_route53_record" "short_redirect_site" {
name = var.shortdomain
zone_id = aws_route53_zone.short_redirect.zone_id
type = "A"
alias {
name = aws_cloudfront_distribution.short_redirect.domain_name
zone_id = aws_cloudfront_distribution.short_redirect.hosted_zone_id
evaluate_target_health = false
}
}
resource "aws_route53_record" "short_redirect_www" {
name = "www.${var.shortdomain}"
zone_id = aws_route53_zone.short_redirect.zone_id
type = "A"
alias {
name = aws_cloudfront_distribution.short_redirect.domain_name
zone_id = aws_cloudfront_distribution.short_redirect.hosted_zone_id
evaluate_target_health = false
}
}
# -----------------------------------------------------------------------------------------------------------
# Lambda Redirect
data "archive_file" "short_redirect" {
type = "zip"
output_path = ".terraform/tmp/lambda/shortdns.zip"
source_file = "${path.module}/shortdns.js"
}
resource "aws_lambda_function" "short_redirect" {
description = "index.html subdirectory redirect"
function_name = "${var.site}-short-redirect"
handler = "shortdns.handler"
filename = data.archive_file.short_redirect.output_path
source_code_hash = data.archive_file.short_redirect.output_base64sha256
publish = true
role = aws_iam_role.lambda_redirect.arn
runtime = "nodejs16.x"
tags = {
Name = "${var.site}-short"
Site = var.site
}
}

View File

@ -1,131 +0,0 @@
# -----------------------------------------------------------------------------------------------------------
# IAM User for Uploading
resource "aws_iam_user" "s3" {
name = "${var.site}-s3"
path = "/${var.site}/"
tags = {
Site = var.site
Category = "S3"
}
}
resource "aws_iam_user_policy" "s3" {
name = "test"
user = aws_iam_user.s3.name
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"cloudfront:CreateInvalidation",
"cloudfront:GetInvalidation",
"s3:PutAccountPublicAccessBlock",
"s3:GetAccountPublicAccessBlock",
"s3:ListAllMyBuckets",
"s3:HeadBucket"
],
"Resource": [
"${aws_cloudfront_distribution.site.arn}"
]
}
]
}
EOF
}
# This writes the s3 access key and secret to the terraform state file
resource "aws_iam_access_key" "s3" {
user = aws_iam_user.s3.name
}
# output s3_access {
# description = "S3 Upload User AccessKey"
# value = "${aws_iam_access_key.s3.id}"
# }
# output s3_secret {
# description = "S3 Upload User Secret"
# value = "${aws_iam_access_key.s3.secret}"
# }
# -----------------------------------------------------------------------------------------------------------
# Site Source Code
resource "aws_s3_bucket" "src" {
bucket = var.domain
tags = {
Name = "Site Source"
Site = var.site
}
}
resource "aws_s3_bucket_acl" "src" {
bucket = aws_s3_bucket.src.id
acl = "public-read"
}
resource "aws_s3_bucket_website_configuration" "src" {
bucket = aws_s3_bucket.src.bucket
index_document {
suffix = "index.html"
}
error_document {
key = "404.html"
}
}
resource "aws_s3_bucket_policy" "src" {
bucket = aws_s3_bucket.src.bucket
policy = <<POLICY
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "${aws_iam_user.s3.arn}"
},
"Action": "s3:ListBucket",
"Resource": "${aws_s3_bucket.src.arn}"
},
{
"Effect": "Allow",
"Principal": {
"AWS": "${aws_iam_user.s3.arn}"
},
"Action": [
"s3:PutObject",
"s3:PutObjectAcl",
"s3:GetObject",
"s3:GetObjectAcl",
"s3:DeleteObject",
"s3:ListMultipartUploadParts",
"s3:AbortMultipartUpload"
],
"Resource": "${aws_s3_bucket.src.arn}/*"
},
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "${aws_s3_bucket.src.arn}/*"
}
]
}
POLICY
}

View File

@ -1,182 +0,0 @@
# -----------------------------------------------------------------------------------------------------------
# Bucket for holding the tracking pixel file
resource "aws_s3_bucket" "pixel" {
bucket = "t.${var.domain}"
tags = {
Name = "Tracking Pixel"
Site = var.site
}
}
resource "aws_s3_bucket_acl" "pixel" {
bucket = aws_s3_bucket.pixel.id
acl = "public-read"
}
resource "aws_s3_bucket_cors_configuration" "pixel" {
bucket = aws_s3_bucket.pixel.id
cors_rule {
allowed_headers = ["*"]
allowed_methods = ["GET", "HEAD"]
allowed_origins = ["*"]
expose_headers = ["ETag"]
max_age_seconds = 3000
}
}
resource "aws_s3_object" "ipixel" {
bucket = aws_s3_bucket.pixel.bucket
key = "i"
source = "${path.module}/files/i.gif"
etag = filemd5("${path.module}/files/i.gif")
acl = "public-read"
content_type = "image/gif"
}
data "aws_canonical_user_id" "current" {}
resource "aws_s3_bucket" "ipixel_logs" {
bucket = "${var.site}-analytics"
tags = {
Name = "iPixel Logs Storage"
Site = var.site
}
}
resource "aws_s3_bucket_acl" "ipixel_logs" {
bucket = aws_s3_bucket.ipixel_logs.id
access_control_policy {
owner {
id = data.aws_canonical_user_id.current.id
}
grant {
grantee {
id = data.aws_canonical_user_id.current.id
type = "CanonicalUser"
}
permission = "FULL_CONTROL"
}
grant {
grantee {
uri = "http://acs.amazonaws.com/groups/s3/LogDelivery"
type = "Group"
}
permission = "FULL_CONTROL"
}
}
}
resource "aws_s3_bucket_lifecycle_configuration" "example" {
bucket = aws_s3_bucket.ipixel_logs.id
rule {
id = "logfiles"
filter {
prefix = "RAW/"
}
transition {
days = 30
storage_class = "STANDARD_IA" # or "ONEZONE_IA"
}
# ... other transition/expiration actions ...
status = "Enabled"
}
}
# -----------------------------------------------------------------------------------------------------------
# Cloudfront Configuration for the tracking pixel
resource "aws_cloudfront_distribution" "tracking" {
origin {
domain_name = aws_s3_bucket.pixel.bucket_regional_domain_name
origin_id = "S3-${aws_s3_bucket.pixel.bucket}"
}
enabled = true
is_ipv6_enabled = true
comment = "Cloudfront distribution for tracking pixel"
logging_config {
include_cookies = true
bucket = aws_s3_bucket.ipixel_logs.bucket_regional_domain_name
prefix = "RAW"
}
aliases = [
"t.${var.domain}"
]
default_cache_behavior {
allowed_methods = ["GET", "HEAD", "OPTIONS"]
cached_methods = ["GET", "HEAD"]
target_origin_id = "S3-${aws_s3_bucket.pixel.bucket}"
forwarded_values {
query_string = true
cookies {
forward = "all"
}
headers = [
"Origin",
"Access-Control-Request-Headers",
"Access-Control-Request-Method",
]
}
viewer_protocol_policy = "allow-all"
min_ttl = 0
default_ttl = 3600
max_ttl = 86400
}
restrictions {
geo_restriction {
restriction_type = "none"
}
}
viewer_certificate {
acm_certificate_arn = aws_acm_certificate.cert.arn
ssl_support_method = "sni-only"
}
tags = {
Name = "Tracking Site"
Site = var.site
}
}
resource "aws_route53_record" "tracking" {
name = "t.${var.domain}"
zone_id = aws_route53_zone.zone.zone_id
type = "A"
alias {
name = aws_cloudfront_distribution.tracking.domain_name
zone_id = aws_cloudfront_distribution.tracking.hosted_zone_id
evaluate_target_health = false
}
}

View File

@ -1,45 +0,0 @@
variable "region" {
type = string
description = "AWS Hosting Region"
default = "us-east-1"
}
variable "site" {
type = string
description = "The name of the site"
default = "gdbible"
}
variable "domain" {
type = string
description = "The base domain name of the site that all these belong to."
default = "genderdysphoria.fyi"
}
variable "shortdomain" {
type = string
default = "gdb.fyi"
}
variable "subdomains" {
type = list
default = [
"www",
"t"
]
}
variable "namecheap" {
type = map
description = "Namecheap Credentials"
default = {
username = ""
apikey = ""
}
validation {
condition = length(var.namecheap.username) > 0
error_message = "Must provide a namecheap configuration."
}
}

View File

@ -1,37 +0,0 @@
terraform {
required_providers {
archive = {
source = "hashicorp/archive"
}
aws = {
source = "hashicorp/aws"
}
namecheap = {
source = "namecheap/namecheap"
version = ">= 2.0.0"
}
}
backend "s3" {
bucket = "twipped-terraform"
key = "gdb/terraform.tfstate"
region = "us-east-1"
}
required_version = ">= 0.13"
}
provider "aws" {
region = var.region
}
data "http" "externalip" {
url = "http://ipv4.icanhazip.com"
}
provider "namecheap" {
user_name = var.namecheap.username
api_user = var.namecheap.username
api_key = var.namecheap.apikey
client_ip = chomp(data.http.externalip.response_body)
use_sandbox = false
}

View File

@ -1,128 +0,0 @@
resource "aws_cloudfront_origin_access_identity" "origin_access_identity" {
}
# -----------------------------------------------------------------------------------------------------------
# Cloudfront Configuration
resource "aws_cloudfront_distribution" "site" {
origin {
domain_name = aws_s3_bucket_website_configuration.src.website_endpoint
origin_id = "S3-Website-${aws_s3_bucket_website_configuration.src.website_endpoint}"
custom_origin_config {
origin_protocol_policy = "http-only"
http_port = "80"
https_port = "443"
origin_ssl_protocols = ["SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2"]
}
}
enabled = true
is_ipv6_enabled = true
default_root_object = "index.html"
aliases = [
var.domain,
"www.${var.domain}"
]
default_cache_behavior {
allowed_methods = ["GET", "HEAD"]
cached_methods = ["GET", "HEAD"]
target_origin_id = "S3-Website-${aws_s3_bucket_website_configuration.src.website_endpoint}"
forwarded_values {
query_string = false
cookies {
forward = "none"
}
}
lambda_function_association {
event_type = "origin-request"
lambda_arn = aws_lambda_function.index_redirect.qualified_arn
include_body = false
}
viewer_protocol_policy = "redirect-to-https"
min_ttl = 0
default_ttl = 86400
max_ttl = 31536000
}
restrictions {
geo_restriction {
restriction_type = "none"
}
}
viewer_certificate {
acm_certificate_arn = aws_acm_certificate.cert.arn
ssl_support_method = "sni-only"
minimum_protocol_version = "TLSv1.1_2016"
}
# viewer_certificate {
# cloudfront_default_certificate = true
# }
tags = {
Name = "Main Site"
Site = var.site
}
}
# -----------------------------------------------------------------------------------------------------------
# Domains
resource "aws_route53_record" "site" {
name = var.domain
zone_id = aws_route53_zone.zone.zone_id
type = "A"
alias {
name = aws_cloudfront_distribution.site.domain_name
zone_id = aws_cloudfront_distribution.site.hosted_zone_id
evaluate_target_health = false
}
}
resource "aws_route53_record" "www" {
name = "www.${var.domain}"
zone_id = aws_route53_zone.zone.zone_id
type = "A"
alias {
name = aws_cloudfront_distribution.site.domain_name
zone_id = aws_cloudfront_distribution.site.hosted_zone_id
evaluate_target_health = false
}
}
# -----------------------------------------------------------------------------------------------------------
# Lambda Subdirectory index.html Redirect
data "archive_file" "index_redirect" {
type = "zip"
output_path = ".terraform/tmp/lambda/index_redirect.zip"
source_file = "${path.module}/files/index_redirect.js"
}
resource "aws_lambda_function" "index_redirect" {
description = "index.html subdirectory redirect"
filename = "${path.module}/files/index_redirect.js.zip"
function_name = "${var.site}-index-redirect"
handler = "index_redirect.handler"
# source_code_hash = data.archive_file.index_redirect.output_base64sha256
publish = true
role = aws_iam_role.lambda_redirect.arn
runtime = "nodejs16.x"
tags = {
Name = "${var.site}-index-redirect"
Site = var.site
}
}