delegate dap.ps domain management to Route53
We have to use Route53 because it provides the option to use an ALIAS type record which works for apex records and can point to a CloudFront distribution in a dynamic way. Without this we'd have to use A records which are static unlike a CNAME, which would eventually become obsolete and take down the site when they do. Details: https://github.com/dap-ps/infra-dapps/issues/18 Signed-off-by: Jakub Sokołowski <jakub@status.im>
This commit is contained in:
parent
9a207dddbc
commit
f294580e31
22
Makefile
22
Makefile
|
@ -8,12 +8,6 @@ endif
|
|||
|
||||
PLUGIN_DIR = ~/.terraform.d/plugins
|
||||
|
||||
GANDI_PROVIDER_NAME = terraform-provider-gandi
|
||||
GANDI_PROVIDER_VERSION = 1.1.0
|
||||
GANDI_PROVIDER_ARCHIVE = $(GANDI_PROVIDER_NAME)-v$(GANDI_PROVIDER_VERSION).zip
|
||||
GANDI_PROVIDER_URL = https://github.com/tiramiseb/terraform-provider-gandi/archive/v$(GANDI_PROVIDER_VERSION).zip
|
||||
GANDI_PROVIDER_PATH = $(PLUGIN_DIR)/$(ARCH)/$(GANDI_PROVIDER_NAME)_v$(GANDI_PROVIDER_VERSION)
|
||||
|
||||
ANSIBLE_PROVIDER_NAME = terraform-provider-ansible
|
||||
ANSIBLE_PROVIDER_VERSION = v1.0.3
|
||||
ANSIBLE_PROVIDER_ARCHIVE = $(ANSIBLE_PROVIDER_NAME)-$(ARCH).zip
|
||||
|
@ -29,7 +23,7 @@ ANSIBLE_PROVISIO_PATH = $(PLUGIN_DIR)/$(ARCH)/$(ANSIBLE_PROVISIO_NAME)_$(ANSIBLE
|
|||
all: requirements plugins secrets init-terraform
|
||||
@echo "Success!"
|
||||
|
||||
plugins: install-ansible-provider install-gandi-provider install-ansible-provisioner
|
||||
plugins: install-ansible-provider install-ansible-provisioner
|
||||
|
||||
requirements:
|
||||
ansible-galaxy install --ignore-errors --force -r ansible/requirements.yml
|
||||
|
@ -48,19 +42,6 @@ install-ansible-provider: check-unzip
|
|||
echo "Already installed: $(ANSIBLE_PROVIDER_PATH)"; \
|
||||
fi
|
||||
|
||||
install-gandi-provider: check-unzip
|
||||
@if [ ! -e $(GANDI_PROVIDER_PATH) ]; then \
|
||||
mkdir -p $(PLUGIN_DIR); \
|
||||
wget $(GANDI_PROVIDER_URL) -O /tmp/$(GANDI_PROVIDER_ARCHIVE); \
|
||||
unzip -o /tmp/$(GANDI_PROVIDER_ARCHIVE) -d /tmp/; \
|
||||
cd /tmp/$(GANDI_PROVIDER_NAME)-$(GANDI_PROVIDER_VERSION) && \
|
||||
go build -o terraform-provider-gandi; \
|
||||
mv /tmp/$(GANDI_PROVIDER_NAME)-$(GANDI_PROVIDER_VERSION)/terraform-provider-gandi \
|
||||
$(PLUGIN_DIR)/$(ARCH)/$(GANDI_PROVIDER_NAME)_v$(GANDI_PROVIDER_VERSION); \
|
||||
else \
|
||||
echo "Already installed: $(GANDI_PROVIDER_PATH)"; \
|
||||
fi
|
||||
|
||||
install-ansible-provisioner:
|
||||
@if [ ! -e $(ANSIBLE_PROVISIO_PATH) ]; then \
|
||||
mkdir -p $(PLUGIN_DIR); \
|
||||
|
@ -79,7 +60,6 @@ secrets:
|
|||
# secrets extracted from password-store\n\
|
||||
aws_access_key = \"$(shell pass cloud/AWS/access-key)\"\n\
|
||||
aws_secret_key = \"$(shell pass cloud/AWS/secret-key)\"\n\
|
||||
gandi_api_token = \"$(shell pass cloud/Gandi/api-token)\"\n\
|
||||
dap_ps_smtp_user = \"$(shell pass cloud/AWS/ses/smtp-access-key)\"\n\
|
||||
dap_ps_smtp_pass = \"$(shell pass cloud/AWS/ses/smtp-password)\"\n\
|
||||
dap_ps_admin_user = \"$(shell pass service/dev/app/admin-user)\"\n\
|
||||
|
|
|
@ -20,11 +20,12 @@ The infrastructure is hosted on AWS and consists of 5 main elements:
|
|||
* [__EC2__](https://aws.amazon.com/ec2/) - [MongoDB](https://www.mongodb.com/) cluster
|
||||
* [__S3__](https://aws.amazon.com/s3/) - [MongoDB](https://www.mongodb.com/) backups & [Terraform](https://www.terraform.io/) state
|
||||
* [__SES__](https://aws.amazon.com/ses/) - Mail forwarding
|
||||
* [__CF__](https://aws.amazon.com/cloudfront/) - CDN
|
||||
* [__CF__](https://aws.amazon.com/cloudfront/) - [CDN](https://en.wikipedia.org/wiki/Content_delivery_network)
|
||||
* [__R53__](https://aws.amazon.com/route53/) - Route53 DNS
|
||||
|
||||
All the AWS parts are provisioned and managed with [Terraform](https://www.terraform.io/) and the MongoDB cluster configured with [Ansible](https://www.ansible.com/).
|
||||
|
||||
The only part that is not AWS is [Gandi](https://www.gandi.net/) DNS provider due to AWS [Route53](https://aws.amazon.com/route53/) not supporting the `.ps` [TLD](https://en.wikipedia.org/wiki/Top-level_domain).
|
||||
The `dap.ps` domain is registered via [Gandi](https://www.gandi.net/) DNS provider and is managed with AWS [Route53](https://aws.amazon.com/route53/) [Hosted Zone](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/hosted-zones-working-with.html) by changing the Name Servers with help from Gandi support. See `dns.tf` for more details.
|
||||
|
||||
# Usage
|
||||
|
||||
|
|
51
dev.tf
51
dev.tf
|
@ -34,7 +34,9 @@ module "dev_cert" {
|
|||
stage = "dev"
|
||||
domain = "dap.ps"
|
||||
sans = ["dap.ps", "raw.dev.dap.ps"]
|
||||
zone_id = gandi_zone.dap_ps_zone.id
|
||||
zone_id = aws_route53_zone.dap_ps.zone_id
|
||||
|
||||
route53_zone_id = aws_route53_zone.dap_ps.zone_id
|
||||
}
|
||||
|
||||
module "dev_db_bucket" {
|
||||
|
@ -58,8 +60,8 @@ module "dev_db" {
|
|||
subnet_id = module.dev_env.subnet_ids[0]
|
||||
sec_group = module.dev_env.security_group_id
|
||||
/* Plumbing */
|
||||
keypair_name = aws_key_pair.admin.key_name
|
||||
gandi_zone_id = gandi_zone.dap_ps_zone.id
|
||||
keypair_name = aws_key_pair.admin.key_name
|
||||
route53_zone_id = aws_route53_zone.dap_ps.zone_id
|
||||
}
|
||||
|
||||
module "dev_env" {
|
||||
|
@ -89,21 +91,34 @@ module "dev_cdn" {
|
|||
origin_fqdns = module.dev_env.elb_fqdns
|
||||
}
|
||||
|
||||
/* DNS ------------------------------------------*/
|
||||
|
||||
resource "gandi_zonerecord" "dev_dns" {
|
||||
zone = gandi_zone.dap_ps_zone.id
|
||||
name = "dev"
|
||||
type = "CNAME"
|
||||
ttl = 3600
|
||||
values = ["${module.dev_cdn.cf_domain_name}."]
|
||||
}
|
||||
/* AWS DNS --------------------------------------*/
|
||||
|
||||
/* raw subdomain for access without CDN */
|
||||
resource "gandi_zonerecord" "dev_dns_raw" {
|
||||
zone = gandi_zone.dap_ps_zone.id
|
||||
name = "raw.dev"
|
||||
type = "CNAME"
|
||||
ttl = 3600
|
||||
values = [for elb in module.dev_env.elb_fqdns: "${elb}."]
|
||||
resource "aws_route53_record" "dev_dns_raw" {
|
||||
zone_id = aws_route53_zone.dap_ps.zone_id
|
||||
name = "raw.dev"
|
||||
type = "CNAME"
|
||||
ttl = 3600
|
||||
records = [for elb in module.dev_env.elb_fqdns: "${elb}."]
|
||||
}
|
||||
|
||||
resource "aws_route53_record" "dev_dns_cdn" {
|
||||
zone_id = aws_route53_zone.dap_ps.zone_id
|
||||
name = "cdn.dev"
|
||||
type = "CNAME"
|
||||
ttl = 3600
|
||||
records = ["${module.dev_cdn.cf_domain_name}."]
|
||||
}
|
||||
|
||||
resource "aws_route53_record" "dev_dns" {
|
||||
zone_id = aws_route53_zone.dap_ps.zone_id
|
||||
name = "dev"
|
||||
type = "CNAME"
|
||||
|
||||
alias {
|
||||
name = aws_route53_record.dev_dns_cdn.fqdn
|
||||
zone_id = aws_route53_record.dev_dns_cdn.zone_id
|
||||
|
||||
evaluate_target_health = false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
/* DNS ------------------------------------*/
|
||||
|
||||
/** WARNING: The .ps TLD has special status.
|
||||
* Its registration took extra long time when it was purchased.
|
||||
* It required help from Gandi support to change the nameservers to AWS ones.
|
||||
* Make changes to it on Gandi side with that in mind.
|
||||
**/
|
||||
|
||||
/* Configure managing domain with Route53 Hosted Zone */
|
||||
resource "aws_route53_zone" "dap_ps" {
|
||||
name = "dap.ps"
|
||||
comment = "Domain for Dapp Discovery website."
|
||||
}
|
15
main.tf
15
main.tf
|
@ -8,10 +8,6 @@ provider "aws" {
|
|||
secret_key = var.aws_secret_key
|
||||
}
|
||||
|
||||
provider "gandi" {
|
||||
key = var.gandi_api_token
|
||||
}
|
||||
|
||||
/* DATA -----------------------------------------*/
|
||||
|
||||
terraform {
|
||||
|
@ -44,17 +40,6 @@ resource "aws_s3_bucket" "tf-state" {
|
|||
}
|
||||
}
|
||||
|
||||
/* Gandi DNS ------------------------------------*/
|
||||
|
||||
resource "gandi_zone" "dap_ps_zone" {
|
||||
name = "${var.public_domain} zone"
|
||||
}
|
||||
|
||||
resource "gandi_domainattachment" "dap_ps" {
|
||||
domain = var.public_domain
|
||||
zone = gandi_zone.dap_ps_zone.id
|
||||
}
|
||||
|
||||
/* ACCESS ---------------------------------------*/
|
||||
|
||||
resource "aws_key_pair" "admin" {
|
||||
|
|
|
@ -9,19 +9,19 @@ resource "aws_acm_certificate" "main" {
|
|||
}
|
||||
}
|
||||
|
||||
resource "gandi_zonerecord" "cert_verification" {
|
||||
zone = var.zone_id
|
||||
name = replace(aws_acm_certificate.main.domain_validation_options[count.index].resource_record_name, ".${var.domain}.", "")
|
||||
type = aws_acm_certificate.main.domain_validation_options[count.index].resource_record_type
|
||||
ttl = 300
|
||||
values = [aws_acm_certificate.main.domain_validation_options[count.index].resource_record_value]
|
||||
count = length(var.sans)+1
|
||||
resource "aws_route53_record" "cert_verification" {
|
||||
zone_id = var.zone_id
|
||||
name = replace(aws_acm_certificate.main.domain_validation_options[count.index].resource_record_name, ".${var.domain}.", "")
|
||||
type = aws_acm_certificate.main.domain_validation_options[count.index].resource_record_type
|
||||
ttl = 300
|
||||
records = [aws_acm_certificate.main.domain_validation_options[count.index].resource_record_value]
|
||||
count = length(var.sans)+1
|
||||
}
|
||||
|
||||
resource "aws_acm_certificate_validation" "main" {
|
||||
certificate_arn = aws_acm_certificate.main.arn
|
||||
validation_record_fqdns = [
|
||||
for verification in gandi_zonerecord.cert_verification:
|
||||
for verification in aws_route53_record.cert_verification:
|
||||
"${verification.name}.${var.domain}"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ variable "domain" {
|
|||
}
|
||||
|
||||
variable "zone_id" {
|
||||
description = "ID of the zone in Gandi DNS registrar."
|
||||
description = "ID of the zone in AWS Route53."
|
||||
type = string
|
||||
}
|
||||
|
||||
|
@ -18,3 +18,8 @@ variable "sans" {
|
|||
type = list(string)
|
||||
default = []
|
||||
}
|
||||
|
||||
variable "route53_zone_id" {
|
||||
description = "ID of the zone in AWS Route53."
|
||||
type = string
|
||||
}
|
||||
|
|
|
@ -3,6 +3,11 @@ output "cf_id" {
|
|||
description = "ID of AWS CloudFront distribution"
|
||||
}
|
||||
|
||||
output "cf_zone_id" {
|
||||
value = aws_cloudfront_distribution.default.hosted_zone_id
|
||||
description = "Zone ID of AWS CloudFront distribution"
|
||||
}
|
||||
|
||||
output "cf_arn" {
|
||||
value = aws_cloudfront_distribution.default.arn
|
||||
description = "ARN of AWS CloudFront distribution"
|
||||
|
|
|
@ -96,15 +96,16 @@ resource "aws_instance" "main" {
|
|||
}
|
||||
}
|
||||
|
||||
resource "gandi_zonerecord" "main" {
|
||||
zone = var.gandi_zone_id
|
||||
name = "${aws_instance.main[count.index].tags.Name}.${var.subdomain}"
|
||||
type = "A"
|
||||
ttl = 600
|
||||
values = [aws_instance.main[count.index].public_ip]
|
||||
count = length(aws_instance.main)
|
||||
resource "aws_route53_record" "main" {
|
||||
zone_id = var.route53_zone_id
|
||||
name = "${aws_instance.main[count.index].tags.Name}.${var.subdomain}"
|
||||
type = "A"
|
||||
ttl = 600
|
||||
records = [aws_instance.main[count.index].public_ip]
|
||||
count = length(aws_instance.main)
|
||||
}
|
||||
|
||||
|
||||
/* this adds the host to the Terraform state for Ansible inventory */
|
||||
resource "ansible_host" "main" {
|
||||
inventory_hostname = aws_instance.main[count.index].tags.Name
|
||||
|
|
|
@ -65,8 +65,8 @@ variable "sec_group" {
|
|||
|
||||
/* DNS ------------------------------------------*/
|
||||
|
||||
variable "gandi_zone_id" {
|
||||
description = "ID of the zone in Gandi DNS registrar."
|
||||
variable "route53_zone_id" {
|
||||
description = "ID of the zone in AWS Route53."
|
||||
type = string
|
||||
}
|
||||
|
||||
|
|
72
prod.tf
72
prod.tf
|
@ -38,7 +38,9 @@ module "prod_cert" {
|
|||
stage = "prod"
|
||||
domain = "dap.ps"
|
||||
sans = ["dap.ps", "raw.prod.dap.ps"]
|
||||
zone_id = gandi_zone.dap_ps_zone.id
|
||||
zone_id = aws_route53_zone.dap_ps.zone_id
|
||||
|
||||
route53_zone_id = aws_route53_zone.dap_ps.zone_id
|
||||
}
|
||||
|
||||
module "prod_db_bucket" {
|
||||
|
@ -63,8 +65,8 @@ module "prod_db" {
|
|||
sec_group = module.prod_env.security_group_id
|
||||
|
||||
/* Plumbing */
|
||||
keypair_name = aws_key_pair.admin.key_name
|
||||
gandi_zone_id = gandi_zone.dap_ps_zone.id
|
||||
keypair_name = aws_key_pair.admin.key_name
|
||||
route53_zone_id = aws_route53_zone.dap_ps.zone_id
|
||||
}
|
||||
|
||||
module "prod_env" {
|
||||
|
@ -94,34 +96,50 @@ module "prod_cdn" {
|
|||
origin_fqdns = module.prod_env.elb_fqdns
|
||||
}
|
||||
|
||||
/* DNS ------------------------------------------*/
|
||||
|
||||
resource "gandi_zonerecord" "prod_dns" {
|
||||
zone = gandi_zone.dap_ps_zone.id
|
||||
name = "prod"
|
||||
type = "CNAME"
|
||||
ttl = 3600
|
||||
values = ["${module.prod_cdn.cf_domain_name}."]
|
||||
}
|
||||
/* AWS DNS --------------------------------------*/
|
||||
|
||||
/* raw subdomain for access without CDN */
|
||||
resource "gandi_zonerecord" "prod_dns_raw" {
|
||||
zone = gandi_zone.dap_ps_zone.id
|
||||
name = "raw.prod"
|
||||
type = "CNAME"
|
||||
ttl = 3600
|
||||
values = [for elb in module.prod_env.elb_fqdns: "${elb}."]
|
||||
resource "aws_route53_record" "prod_dns_raw" {
|
||||
zone_id = aws_route53_zone.dap_ps.zone_id
|
||||
name = "raw.prod"
|
||||
type = "CNAME"
|
||||
ttl = 3600
|
||||
records = [for elb in module.prod_env.elb_fqdns: "${elb}."]
|
||||
}
|
||||
|
||||
/* Apex DNS records cannot be CNAMEs */
|
||||
data "dns_a_record_set" "prod_cdn" {
|
||||
host = module.prod_cdn.cf_domain_name
|
||||
resource "aws_route53_record" "prod_dns_cdn" {
|
||||
zone_id = aws_route53_zone.dap_ps.zone_id
|
||||
name = "cdn.prod"
|
||||
type = "CNAME"
|
||||
ttl = 3600
|
||||
records = ["${module.prod_cdn.cf_domain_name}."]
|
||||
}
|
||||
|
||||
resource "gandi_zonerecord" "prod_apex_dns" {
|
||||
zone = gandi_zone.dap_ps_zone.id
|
||||
name = "@"
|
||||
type = "A"
|
||||
ttl = 3600
|
||||
values = data.dns_a_record_set.prod_cdn.addrs
|
||||
resource "aws_route53_record" "prod_dns" {
|
||||
zone_id = aws_route53_zone.dap_ps.zone_id
|
||||
name = "prod"
|
||||
type = "CNAME"
|
||||
|
||||
alias {
|
||||
name = aws_route53_record.prod_dns_cdn.fqdn
|
||||
zone_id = aws_route53_record.prod_dns_cdn.zone_id
|
||||
|
||||
evaluate_target_health = false
|
||||
}
|
||||
}
|
||||
|
||||
/* Apex DNS Record ------------------------------*/
|
||||
|
||||
/* WARNING: Main site record for https://dap.ps/ */
|
||||
resource "aws_route53_record" "prod_dns_apex" {
|
||||
zone_id = aws_route53_zone.dap_ps.zone_id
|
||||
name = ""
|
||||
type = "A"
|
||||
|
||||
alias {
|
||||
name = module.prod_cdn.cf_domain_name
|
||||
zone_id = module.prod_cdn.cf_zone_id
|
||||
|
||||
evaluate_target_health = false
|
||||
}
|
||||
}
|
||||
|
|
63
ses.tf
63
ses.tf
|
@ -13,47 +13,47 @@ resource "aws_ses_domain_mail_from" "dap_ps" {
|
|||
mail_from_domain = "mail.${aws_ses_domain_identity.dap_ps.domain}"
|
||||
}
|
||||
|
||||
resource "gandi_zonerecord" "dap_ps_verification" {
|
||||
zone = gandi_zone.dap_ps_zone.id
|
||||
name = "_amazonses"
|
||||
type = "TXT"
|
||||
ttl = 3600
|
||||
values = ["\"${aws_ses_domain_identity.dap_ps.verification_token}\""]
|
||||
resource "aws_route53_record" "dap_ps_verification" {
|
||||
zone_id = aws_route53_zone.dap_ps.zone_id
|
||||
name = "_amazonses"
|
||||
type = "TXT"
|
||||
ttl = 3600
|
||||
records = ["${aws_ses_domain_identity.dap_ps.verification_token}"]
|
||||
}
|
||||
|
||||
resource "gandi_zonerecord" "dap_ps_mail_mx" {
|
||||
zone = gandi_zone.dap_ps_zone.id
|
||||
name = "mail"
|
||||
type = "MX"
|
||||
ttl = 3600
|
||||
values = ["10 feedback-smtp.us-east-1.amazonses.com."]
|
||||
resource "aws_route53_record" "dap_ps_mail_mx" {
|
||||
zone_id = aws_route53_zone.dap_ps.zone_id
|
||||
name = "mail"
|
||||
type = "MX"
|
||||
ttl = 3600
|
||||
records = ["10 feedback-smtp.us-east-1.amazonses.com."]
|
||||
}
|
||||
|
||||
resource "gandi_zonerecord" "dap_ps_mail_spf" {
|
||||
zone = gandi_zone.dap_ps_zone.id
|
||||
name = "mail"
|
||||
type = "TXT"
|
||||
ttl = 3600
|
||||
values = ["\"v= spf1 include:amazonses.com ~all\""]
|
||||
resource "aws_route53_record" "dap_ps_mail_spf" {
|
||||
zone_id = aws_route53_zone.dap_ps.zone_id
|
||||
name = "mail"
|
||||
type = "TXT"
|
||||
ttl = 3600
|
||||
records = ["v= spf1 include:amazonses.com ~all"]
|
||||
}
|
||||
|
||||
resource "gandi_zonerecord" "dap_ps_dkim" {
|
||||
zone = gandi_zone.dap_ps_zone.id
|
||||
ttl = 3600
|
||||
type = "CNAME"
|
||||
count = 3
|
||||
name = "${element(aws_ses_domain_dkim.dap_ps.dkim_tokens, count.index)}._domainkey"
|
||||
values = ["${element(aws_ses_domain_dkim.dap_ps.dkim_tokens, count.index)}.dkim.amazonses.com."]
|
||||
resource "aws_route53_record" "dap_ps_dkim" {
|
||||
zone_id = aws_route53_zone.dap_ps.zone_id
|
||||
ttl = 3600
|
||||
type = "CNAME"
|
||||
count = 3
|
||||
name = "${element(aws_ses_domain_dkim.dap_ps.dkim_tokens, count.index)}._domainkey"
|
||||
records = ["${element(aws_ses_domain_dkim.dap_ps.dkim_tokens, count.index)}.dkim.amazonses.com."]
|
||||
}
|
||||
|
||||
/* SES EMail Fowarding --------------------------*/
|
||||
|
||||
resource "gandi_zonerecord" "dap_ps_mx" {
|
||||
zone = gandi_zone.dap_ps_zone.id
|
||||
name = "@"
|
||||
type = "MX"
|
||||
ttl = 3600
|
||||
values = ["10 inbound-smtp.us-east-1.amazonaws.com."]
|
||||
resource "aws_route53_record" "dap_ps_mx" {
|
||||
zone_id = aws_route53_zone.dap_ps.zone_id
|
||||
name = "@"
|
||||
type = "MX"
|
||||
ttl = 3600
|
||||
records = ["10 inbound-smtp.us-east-1.amazonaws.com."]
|
||||
}
|
||||
|
||||
/* Validated Emails -----------------------------*/
|
||||
|
@ -65,4 +65,3 @@ resource "aws_ses_email_identity" "jakub" {
|
|||
resource "aws_ses_email_identity" "andy" {
|
||||
email = "andy@status.im"
|
||||
}
|
||||
|
||||
|
|
|
@ -8,10 +8,6 @@ variable "aws_secret_key" {
|
|||
description = "Secret key for the AWS API."
|
||||
}
|
||||
|
||||
variable "gandi_api_token" {
|
||||
description = "API token for Gandi DNS API"
|
||||
}
|
||||
|
||||
/* GENERAL --------------------------------------*/
|
||||
|
||||
variable "hosts_subdomain" {
|
||||
|
|
|
@ -3,6 +3,5 @@ terraform {
|
|||
required_version = ">= 0.12"
|
||||
required_providers {
|
||||
aws = "= 2.44.0"
|
||||
gandi = ">= 1.1.0"
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue