I didn't find anything useful in the docs. Can this be done with terraform somehow?
Can I register a domain in aws with terraform?
8.1k views Asked by deez AtThere are 3 answers
On
Below is a custom module to accomplish this using the AWS cli.
README.md
Description
This module will check if the AWS domain is already registered in your AWS account.
If the domain is not registered to your account then it will attempt to register it.
It will then validate that it was registered successfully.
Note
The registrant info provided by the variables is used only when registering the domain.
After the domain is registered, this module makes no attempt to keep the registration properties in sync.
This means that any changes will go undetected if you (1) register the domain and then (2) modify the registrant variables, e.g. organization_name.
Validation
When you register a new domain, you will need to confirm it via the email you provided.
After registration, you should receive an email from AWS with subject Verify your email address for <domain_name>
The domain will be registered immediately, and you have 14 days to verify the email before losing the domain.
variables.tf
variable "name" {
description = "Name of the project, e.g. my-project"
type = string
}
variable "environment" {
description = "The environment, e.g. prod"
type = string
}
variable "aws_region" {
description = "'This command runs only in the us-east-1 region' - https://awscli.amazonaws.com/v2/documentation/api/latest/reference/route53domains/register-domain.html"
type = string
default = "us-east-1"
}
variable "auto_renew" {
description = "Auto renew the domain when it expires, e.g. true"
type = bool
default = true
}
variable "duration_years" {
description = "Number of years until the domain expires, e.g. 1"
type = number
default = 1
}
variable "privacy_protect_contact" {
description = "Hide your contact details in the WHOIS record, e.g. true"
type = bool
default = true
}
variable "domain_name" {
description = "The domain name to register, e.g. website.com"
type = string
}
variable "first_name" {
description = "The first name for the registrar contact"
type = string
}
variable "last_name" {
description = "The last name for the registrar contact"
type = string
}
variable "organization_name" {
description = "The organization name for the registrar contact"
type = string
}
variable "address_line_1" {
description = "The address for the registrar contact, e.g. 1 Main Street"
type = string
}
variable "city" {
description = "The city for the registrar contact, e.g. New York City"
type = string
}
variable "state" {
description = "The state for the registrar contact, e.g. NY"
type = string
}
variable "country_code" {
description = "The country_code for the registrar contact, e.g. US"
type = string
}
variable "zip_code" {
description = "The zip_code for the registrar contact, e.g. 10001"
type = string
}
variable "phone" {
description = "The phone for the registrar contact, e.g. +1.8005551212"
type = string
}
variable "email" {
description = "The email for the registrar contact, e.g. [email protected]"
type = string
}
main.tf
locals {
cli_input_json_path = "${path.module}/cli_input_json/${var.name}-${var.environment}.json"
}
resource "local_file" "cli_input_json" {
filename = local.cli_input_json_path
content = <<-EOF
{
"DomainName": "${var.domain_name}",
"DurationInYears": ${var.duration_years},
"AutoRenew": ${var.auto_renew},
"PrivacyProtectAdminContact": ${var.privacy_protect_contact},
"PrivacyProtectRegistrantContact": ${var.privacy_protect_contact},
"PrivacyProtectTechContact": ${var.privacy_protect_contact},
"AdminContact": {
"ContactType": "PERSON",
"FirstName": "${var.first_name}",
"LastName": "${var.last_name}",
"OrganizationName": "${var.organization_name}",
"AddressLine1": "${var.address_line_1}",
"City": "${var.city}",
"State": "${var.state}",
"CountryCode": "${var.country_code}",
"ZipCode": "${var.zip_code}",
"PhoneNumber": "${var.phone}",
"Email": "${var.email}"
},
"RegistrantContact": {
"ContactType": "PERSON",
"FirstName": "${var.first_name}",
"LastName": "${var.last_name}",
"OrganizationName": "${var.organization_name}",
"AddressLine1": "${var.address_line_1}",
"City": "${var.city}",
"State": "${var.state}",
"CountryCode": "${var.country_code}",
"ZipCode": "${var.zip_code}",
"PhoneNumber": "${var.phone}",
"Email": "${var.email}"
},
"TechContact": {
"ContactType": "PERSON",
"FirstName": "${var.first_name}",
"LastName": "${var.last_name}",
"OrganizationName": "${var.organization_name}",
"AddressLine1": "${var.address_line_1}",
"City": "${var.city}",
"State": "${var.state}",
"CountryCode": "${var.country_code}",
"ZipCode": "${var.zip_code}",
"PhoneNumber": "${var.phone}",
"Email": "${var.email}"
}
}
EOF
}
resource "null_resource" "aws_register_domain" {
provisioner "local-exec" {
command = "${path.module}/aws_register_domain.sh"
environment = {
aws_region = var.aws_region
domain_name = var.domain_name
cli_input_json_path = local.cli_input_json_path
}
}
depends_on = [
local_file.cli_input_json
]
}
aws_register_domain.sh
#!/usr/bin/env bash
set -e
##
# Validate expected environment variables
##
if [[ -z "$aws_region" ]]; then
echo 'aws_register_domain: no value for $aws_region' >&2
exit 1
fi
if [[ -z "$domain_name" ]]; then
echo 'aws_register_domain: no value for $domain_name' >&2
exit 1
fi
if [[ -z "$cli_input_json_path" ]]; then
echo 'aws_register_domain: no value for $cli_input_json_path' >&2
exit 1
fi
##
# Check if domain is already registered to our account
##
echo "aws_register_domain: Checking if domain $domain_name is already registered in this AWS account"
registration_check=$(
(
aws route53domains get-domain-detail \
--region "$aws_region" \
--domain-name "$domain_name" \
2>&1 \
) || :
)
# https://stackoverflow.com/a/16951928
re_escape() {
sed 's/[][\.|$(){}?+*^]/\\&/g' <<< "$*"
}
domain_name_escaped=`re_escape "$domain_name"`
already_exists=`((echo "$registration_check" | grep -Eq 'Domain '"$domain_name_escaped"' not found in [0-9]+ account') && echo 'no') || echo 'yes'`
if [[ "$already_exists" == 'yes' ]]; then
echo "aws_register_domain: Domain $domain_name is already registered in this AWS account"
exit 0
elif [[ "$already_exists" == 'no' ]]; then
found_domain_name=`echo "$registration_check" | jq -r '.DomainName'`
if [[ "$found_domain_name" != "$domain_name" ]]; then
echo "aws_register_domain: Expected found_domain_name to be '$domain_name' but found '$found_domain_name'" >&2
exit 1
fi
else
echo "aws_register_domain: Expected already_exists to be 'yes' or 'no' but found '$already_exists'" >&2
exit 1
fi
##
# Register the domain
##
echo "aws_register_domain: Attempting to register domain defined in '$cli_input_json_path'"
operation_id=$(
aws route53domains register-domain \
--region "$aws_region" \
--cli-input-json "file://$cli_input_json_path" \
| jq -r '.OperationId'
)
if [[ -z "$operation_id" ]]; then
echo 'aws_register_domain: no OperationId returned' >&2
exit 1
fi
echo "aws_register_domain: Pending registration's OperationId = $operation_id"
##
# Wait while domain registration is IN_PROGRESS
##
while true; do
operation_info=$(
aws route53domains get-operation-detail \
--region "$aws_region" \
--operation-id "$operation_id"
)
operation_status=`echo "$operation_info" | jq -r '.Status'`
if [[ "$operation_status" != 'IN_PROGRESS' ]]; then
break
fi
sleep 10
end
##
# Validate successful domain registration
##
echo "aws_register_domain: Registration finished with $operation_info"
expected_status='SUCCESSFUL'
if [[ "$operation_status" != "$expected_status" ]]; then
echo "aws_register_domain: Expected final status of '$expected_status' but found '$operation_status'" >&2
exit 1
fi
On
The AWS provider in Terraform now supports registering and managing of domains: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53domains_registered_domain
resource "aws_route53domains_registered_domain" "example" {
domain_name = "example.com"
name_server {
name = "ns-195.awsdns-24.com"
}
name_server {
name = "ns-874.awsdns-45.net"
}
tags = {
Environment = "test"
}
}
Make sure to read the fine print on top of the documentation page. This resource behaves differently when deleted.
Registering a domain name involves a commitment from a Domain Name Registrar for a minimum of 12 months.
Tools like Terraform and AWS CloudFormation are used to create, update and delete infrastructure such as networks, EC2 instances and database.
While AWS does offer the ability to register domain names (which is done through gandi.net), this is not something you would do with tools like Terraform because you cannot simply "unregister" a domain name.
You could choose to use such tools to add sub-domains to an existing domain. They just aren't appropriate for the initial purchase of a domain name.