AWS Route 53 - Update DNS On Windows Instance Launch

Have you ever had to boot up an EC2 instance, only to manually go into Route 53 and assign the IP address to that EC2 instance? This can be a pain at scale.

In this post, we'll go over a powershell script that runs at launch of your windows EC2 instance. This script automatically assigns an A record to your domain that resolves to your EC2 instance IP.

This post assumes you have some knowledge of how DNS works.

Route 53 Setup

The first thing we need to do is figure out what domain we want to use and set it up in the Route 53 console.

  • Create a new hosted zone for your domain in Route 53.
  • Create an A record for where you want your EC2 instance to point. Set the IP to anything - it doesn't matter. It will be automatically updated in our script.
  • Take note of the "Hosted Zone ID" - this will be referenced later.

IAM Role Setup

In a later step, your EC2 instance needs to get information about itself. Notably, the tags. This is a privileged command, and needs programmatic access to EC2 to perform. Additionally, Route 53 needs access to edit the zone from your EC2 instance. Here is the JSON of the policy I used:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "ec2:DescribeTags",
                "ec2:DescribeVpcs",
                "ec2:DescribeRegions",
                "route53:GetHostedZone",
                "route53:ChangeResourceRecordSets",
                "route53:ListHostedZonesByName"
            ],
            "Resource": "*"
        }
    ]
}

Attach this policy to a role in the IAM console. This allows the EC2 instance to get tags assigned to it, and allows Route53 to update the zone as necessary.

EC2 Setup

Here is the more complicated part. You go through the instance launch setup, but there are three things you need to remember.

  • Assign the role you created in the previous step to the EC2 instance.
  • Use the below powershell script in userdata.
  • Assign the following tags:
    • AUTO_DNS_ZONE = your hosted zone ID referenced in the first step
    • AUTO_DNS_NAME = yourdomain.com

Below is the powershell script for your instance. Make sure if you're doing this from the web console you wrap it in a powershell tag!

<powershell>
    below script
</powershell>
$INSTANCE_ID = Invoke-WebRequest -Uri http://169.254.169.254/latest/meta-data/instance-id/ -UseBasicParsing | Select-Object -ExpandProperty Content
$AZ = Invoke-WebRequest -Uri http://169.254.169.254/latest/meta-data/placement/availability-zone/ -UseBasicParsing | Select-Object -ExpandProperty Content
$MYIP = Invoke-WebRequest -Uri http://169.254.169.254/latest/meta-data/public-ipv4/ -UseBasicParsing | Select-Object -ExpandProperty Content
$ZONE_TAG = get-ec2tag -filter @{Name="resource-id";Value="$INSTANCE_ID"},@{Name="key";Value="AUTO_DNS_ZONE"} | select -expand Value
$NAME_TAG = get-ec2tag -filter @{Name="resource-id";Value="$INSTANCE_ID"},@{Name="key";Value="AUTO_DNS_NAME"} | select -expand Value

$changeRequest = New-Object -TypeName Amazon.Route53.Model.Change
$changeRequest.Action = "UPSERT"

$changeRequest.ResourceRecordSet = New-Object -TypeName Amazon.Route53.Model.ResourceRecordSet
$changeRequest.ResourceRecordSet.Name = "$NAME_TAG"
$changeRequest.ResourceRecordSet.Type = "A"
$changeRequest.ResourceRecordSet.TTL = 60
$changeRequest.ResourceRecordSet.ResourceRecords.Add(@{Value = $MYIP})

Edit-R53ResourceRecordSet `
	-HostedZoneId $ZONE_TAG `
	-ChangeBatch_Change @($changeRequest)

If done correctly, upon launch of this EC2 instance your DNS in route 53 will be updated.