Skip to content
Menu
Tech Automation Blog
  • About Author
  • Contact
Tech Automation Blog

Backup AWS Route 53 DNS record using Powershell

Posted on August 17, 2019February 27, 2022

AWS Route 53 is the DNS service provided by Amazon. It stores all hosted zones for your organization and stores different DNS record types. It performs name resolution of devices and applications. A backup of these records is very important. Therefore, any issue or disaster, you can quickly restore those and keep your name resolution process running.

Recently, I came across a requirement where customer wanted to create an Azure Automation Runbook to take a backup of Route 53 DNS record. They also wanted to restore them on Microsoft Azure DNS as the they are using Azure as their main Cloud Platform.

This script is using Azure Blob to store the backup of AWS Route 53 in a JSON file format, and, this is the first part of the 2 step process. Here I am taking  backup of DNS records to Azure blob storage. For second part, refer to my blog post here.

We need to have following prerequisites to run this Runbook :

  1. AWS Credentials (Access Key, Secret Access Key with proper permissions on Route 53)
  2. An Azure Key Vault to store AWS credentials (This is a security Best Practice. Instead of hard coding credentials in script or passing as plain text parameter).
  3. Azure Blob storage container to store backup JSON file. You may refer Microsoft documentations on how to create Storage Account and Container
  4. An Azure Automation account with permission to the Key Vault and Storage Account
  5. AWS PowerShell and Azure RM PowerShell Modules configured

In the Second Part, I will share script to restore those records from Blob storage to Azure DNS. Whatever reason you might have, if you just want to backup AWS DNS records, you can use this script. However, if you want to use S3 Bucket or some other file server to store it, you may achieve this with small changes to the script.

Param(
	[Parameter(Mandatory=$true)]
	[String]$saResourceGroup,
	[Parameter(Mandatory=$true)]
	[String]$storageAccount,
	[Parameter(Mandatory=$true)]
	[String]$storageContainer,
	[Parameter(Mandatory=$true)]
	[String]$kvName
)

#region - Importing Powershell module if it is missing
if((Get-Module -Name AwsPowershell).count -gt 0){
	Write-Output "AWS Powershell module is already installed"
}else{
	Write-Output "AWS Powershell module missing.Installing the module now"
	Import-Module -Name AwsPowershell -Force
}
#endregion

#region - login to Azure from the Automation Account.Setup Automation account as prerequisite.
$connectionName = "AzureRunAsConnection"
try{
    #Get the connection 'AzureRunAsConnection'
    $servicePrincipalConnection = Get-AutomationConnection -Name $connectionName
    "Logging in to Azure..."
    Add-AzureRmAccount `
        -ServicePrincipal `
        -TenantId $servicePrincipalConnection.TenantId `
        -ApplicationId $servicePrincipalConnection.ApplicationId `
        -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint
}
catch{
    if(!$ServicePrincipalConnection){
        $ErrorMessage = "Connection $connectionName not found."
        throw $ErrorMessage
    }else{
        Write-Error -Message $_.Exception
        throw $_.Exception
    }
}
#endregion

#region - get AWS Route53 user credentials
$awsR53AccessKey = (Get-AzureKeyVaultSecret -VaultName $kvName -Name AWSR53AccessKey).SecretValueText
$awsR53SecretKey = (Get-AzureKeyVaultSecret -VaultName $kvName -Name AWSR53SecretKey).SecretValueText
$region = "US-EAST-2" # Set it to whatever region you have your AWS Region setup
#endregion

#region - Connecting to AWS Account
Set-AWSCredentials -AccessKey $awsR53AccessKey -SecretKey $awsR53SecretKey -StoreAs AWSProfile
Initialize-AWSDefaults -ProfileName AWSProfile -Region $region
#endregion

#region - Collect R53 Data from AWS Account and dump into JSON file

#Find All R53 Hosted Zones
$date = Get-Date -UFormat "%m-%d-%Y_%H%M%S"
$outFileName = "r53Backup-$($date).json"
$outJsonFile = "$($env:TEMP)\$outFileName"
if(Test-Path $outJsonFile){
	Remove-Item $outJsonFile -Force
}
New-Item -Path $outJsonFile -ItemType File

$jsonData = @{}
try{
	$Zones = Get-R53HostedZones -ProfileName AWSProfile
	foreach ($zone in $Zones) 
	{   
		#Iterate through each hosted zone and generate JSON file with each record
		$recordDataSets = @()
		foreach ($Recordset in (Get-R53ResourceRecordSet -ProfileName AWSProfile -HostedZoneId $zone.Id).ResourceRecordSets) 
		{
            $data = ""
			if ($Recordset.ResourceRecords.Count -gt 1) 
			{		  
			  foreach ($entry in $Recordset.ResourceRecords) 
			  {
				$data += $($entry.value) + ";"
			  }
			}
			else 
			{
			  $data = $Recordset.ResourceRecords.Value
			}
			if($data){$data = $data.TrimEnd(";")}
			#Generate Custom Object of record sets
			$recordDataSet = @{}
			$recordDataSet.Add('RecordSetName',$Recordset.Name)
			$recordDataSet.Add('CallerReference',$Recordset.CallerReference)
			$recordDataSet.Add('Type',$Recordset.Type)
			$recordDataSet.Add('SetIdentifier',$Recordset.SetIdentifier)
			$recordDataSet.Add('Weight',$Recordset.Weight)
			$recordDataSet.Add('Region',$Recordset.Region)
			$recordDataSet.Add('GeoLocation',$Recordset.GeoLocation)
			$recordDataSet.Add('TTL',$Recordset.TTL)
			$recordDataSet.Add('ResourceRecord',$data)
			$recordDataSet.Add('AliasTarget',$Recordset.AliasTarget)
			$recordDataSet.Add('TrafficPolicyInstanceID',$Recordset.TrafficPolicyInstanceId)
			$recordDataSets += $recordDataSet
		}
		$jsonData | Add-Member -Type NoteProperty -Name $zone.Name -Value $recordDataSets		
	}	
	$jsonData | ConvertTo-Json | Out-File $outJsonFile
}
catch{
	Write-Error -Message $_.Exception
    throw $_.Exception
}
#endregion

#region - Connect to a storage account and dump R53 backup JSON to a blob

try{
	$saContext = (Get-AzureRmStorageAccount -ResourceGroupName $saResourceGroup -Name $storageAccount).Context
	if(!(Get-AzureStorageContainer -Container $storageContainer -Context $saContext -ErrorAction 'SilentlyContinue')){
		New-AzureStorageContainer -Name $storageContainer -Permission Container -Context $saContext
	}
	Set-AzureStorageBlobContent -Container $storageContainer -Context $saContext -File $outJsonFile -Blob "route53\$outFileName" -Force
}
catch{
	Write-Error -Message $_.Exception
    throw $_.Exception
}
#endregion

Login to Azure Portal using https://portal.azure.com and open Azure Automation Accounts from left pane.

This image has an empty alt attribute; its file name is image-14.png
Login to Azure portal

Once logged in, open configured Azure Automation account and select Runbooks from Process Automation option in the left pane.

This image has an empty alt attribute; its file name is image-15.png
Create new Runbook

Create a new Runbook using the script above and save it. Once, it is saved run the Runbook from the list.

Execute Runbook

Share this:

  • Click to share on X (Opens in new window) X
  • Click to share on Facebook (Opens in new window) Facebook
  • Click to share on LinkedIn (Opens in new window) LinkedIn
May 2025
M T W T F S S
 1234
567891011
12131415161718
19202122232425
262728293031  
« May    

Recent Posts

  • Monitor and alert Azure Service Health issues May 5, 2020
  • AWS IAM User access review May 3, 2020
  • Integrate Azure Security Center with Event Hub April 28, 2020
  • Add Tags to Azure Subscription April 24, 2020
  • Automate Azure billing report in Excel March 6, 2020

Categories

©2025 Tech Automation Blog | Powered by SuperbThemes