mirror of
https://github.com/GenderDysphoria/GenderDysphoria.fyi.git
synced 2025-01-31 07:16:17 +00:00
moved infrastructure config out of this repo
This commit is contained in:
parent
922e627fed
commit
16e00a195b
83
terraform/.terraform.lock.hcl
generated
83
terraform/.terraform.lock.hcl
generated
@ -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",
|
||||
]
|
||||
}
|
@ -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]
|
||||
}
|
@ -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}:*"]
|
||||
}
|
||||
}
|
@ -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 |
@ -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;
|
||||
};
|
@ -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'
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
@ -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
|
||||
};
|
||||
};
|
@ -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
|
||||
}
|
||||
}
|
||||
|
131
terraform/src.tf
131
terraform/src.tf
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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."
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
128
terraform/www.tf
128
terraform/www.tf
@ -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
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user