Skip to content

Instantly share code, notes, and snippets.

@gbvanrenswoude
Last active November 14, 2022 12:35
Show Gist options
  • Save gbvanrenswoude/30127beff95cba812be83c4bd28a2536 to your computer and use it in GitHub Desktop.
Save gbvanrenswoude/30127beff95cba812be83c4bd28a2536 to your computer and use it in GitHub Desktop.
Script to remove all Route53 Hosted Zones with records from an AWS account
// Run with ts-node script.ts --no-cache
/* eslint-disable @typescript-eslint/no-non-null-assertion */
/* eslint-disable no-console */
import {
ChangeBatch,
ChangeResourceRecordSetsCommand,
DeleteHostedZoneCommand,
ListHostedZonesCommand,
ListResourceRecordSetsCommand,
Route53Client,
} from '@aws-sdk/client-route-53';
import { GetCallerIdentityCommand, STSClient } from '@aws-sdk/client-sts';
const main = async () => {
const protectedHostedZoneNames = [
'zone-you-want-to-protect-1.corp.com.',
];
const client = new Route53Client({ region: 'eu-west-1' });
const stsClient = new STSClient({ region: 'eu-west-1' });
const accountNumber = await stsClient.send(new GetCallerIdentityCommand({}));
if (accountNumber.Account !== '111111111111') {
console.error('This script can only be run in the AWS account 111111111111 (safeguard)');
process.exit(1);
}
const command = new ListHostedZonesCommand({
MaxItems: 100,
});
const response = await client.send(command);
if (response.HostedZones) {
for (const hostedZone of response.HostedZones) {
console.log(`Checking Hosted zone: ${hostedZone.Id} with name ${hostedZone.Name} for protected status`);
if (hostedZone.Name && protectedHostedZoneNames.includes(hostedZone.Name)) {
console.log(`Hosted zone: ${hostedZone.Id} with name ${hostedZone.Name} is protected, skipping`);
continue;
}
console.log(`Deleting Hosted Zone ${hostedZone.Id} with name ${hostedZone.Name}`);
console.log(`!!! Giving you the ability to kill the process now if you do NOT want THIS ZONE: ${hostedZone.Name} to be deleted... (5s) !!!`);
await new Promise((resolve) => setTimeout(resolve, 5000));
// Get every record set in the Hosted Zone, no <product> HostedZone has more than 100 record sets so I did not include pagination
const recordSetCommand = new ListResourceRecordSetsCommand({
HostedZoneId: hostedZone.Id!,
MaxItems: 100,
});
const recordSetResponse = await client.send(recordSetCommand);
if (recordSetResponse.ResourceRecordSets) {
const recordSets = recordSetResponse.ResourceRecordSets.filter((recordSet) => {
return recordSet.Type !== 'NS' && recordSet.Type !== 'SOA';
});
if (recordSets.length === 0) {
console.log(`Deleting Hosted Zone ${hostedZone.Id} with name ${hostedZone.Name}`);
const deleteHostedZoneCommand = new DeleteHostedZoneCommand({
Id: hostedZone.Id!,
});
await client.send(deleteHostedZoneCommand);
console.log(`Deleted Hosted Zone ${hostedZone.Id} with name ${hostedZone.Name}`);
} else {
const changeBatch: ChangeBatch = {
Changes: [],
};
for (const recordSet of recordSets) {
console.log(`Deleting record set ${recordSet.Name} of type ${recordSet.Type}`);
changeBatch.Changes!.push({
Action: 'DELETE',
ResourceRecordSet: recordSet,
});
}
const changeCommand = new ChangeResourceRecordSetsCommand({
HostedZoneId: hostedZone.Id!,
ChangeBatch: changeBatch,
});
await client.send(changeCommand);
await new Promise((resolve) => setTimeout(resolve, 2000));
console.log(`Deleting Hosted Zone ${hostedZone.Id}`);
const deleteHostedZoneCommand = new DeleteHostedZoneCommand({
Id: hostedZone.Id!,
});
await client.send(deleteHostedZoneCommand);
}
} else {
console.log(`No record sets found for Hosted Zone ${hostedZone.Id}`);
console.log(`Deleting Hosted Zone ${hostedZone.Id}`);
const deleteHostedZoneCommand = new DeleteHostedZoneCommand({
Id: hostedZone.Id!,
});
await client.send(deleteHostedZoneCommand);
}
}
} else {
console.log('No Hosted Zones to be deleted found, exiting');
}
};
main().catch((err) => console.error(err));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment