Last active
March 12, 2018 23:20
-
-
Save Snawoot/ca96a9685396e2a424877b0617d9c4bf to your computer and use it in GitHub Desktop.
Wipe zones in AWS Route53
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python | |
| import boto3 | |
| import sys | |
| import signal | |
| import itertools | |
| import pprint | |
| import logging | |
| def setup_logger(): | |
| logger = logging.getLogger() | |
| logger.setLevel(logging.INFO) | |
| log_handler = logging.StreamHandler(sys.stderr) | |
| log_handler.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')) | |
| logger.addHandler(log_handler) | |
| return logger | |
| def batches(it, size=1000): | |
| for _, g in itertools.groupby(enumerate(it), lambda (num, val): num / int(size)): | |
| yield (val for _, val in g) | |
| def iter_zones(client): | |
| params = { | |
| 'MaxItems': '100', | |
| } | |
| while True: | |
| resp = client.list_hosted_zones(**params) | |
| for zone in resp['HostedZones']: | |
| yield zone | |
| if resp['IsTruncated']: | |
| params['Marker'] = resp['NextMarker'] | |
| else: | |
| break | |
| def iter_record_sets(client, zone_id): | |
| params = { | |
| 'HostedZoneId': zone_id, | |
| 'MaxItems': '100', | |
| } | |
| while True: | |
| resp = client.list_resource_record_sets(**params) | |
| for rr in resp['ResourceRecordSets']: | |
| yield rr | |
| if resp['IsTruncated']: | |
| params['StartRecordName'] = resp['NextRecordName'] | |
| params['StartRecordType'] = resp['NextRecordType'] | |
| else: | |
| break | |
| def delete_zone(client, zone_id): | |
| logging.info('Gathering records of zone %s...', zone_id) | |
| records_to_delete = [(rrs['Name'], | |
| rrs['Type'], | |
| rrs['ResourceRecords'], | |
| rrs['TTL'] | |
| ) for rrs in iter_record_sets(client, zone_id) if rrs['Type'] not in ("SOA", "NS")] | |
| logging.info('Collected %d records in zone %s. Forming batches...', len(records_to_delete), zone_id) | |
| for gr in batches(records_to_delete, 100): | |
| changes = [{ | |
| 'Action': 'DELETE', | |
| 'ResourceRecordSet': { | |
| 'Name': rr_name, | |
| 'Type': rr_type, | |
| 'TTL': rr_ttl, | |
| 'ResourceRecords': rr_values, | |
| }} for rr_name, rr_type, rr_values, rr_ttl in gr] | |
| logging.info('Prepared batch with %d operations.', len(changes)) | |
| client.change_resource_record_sets(HostedZoneId=zone_id, ChangeBatch={'Comment': 'Zone purge', 'Changes': changes}) | |
| logging.info('Batch executed.') | |
| client.delete_hosted_zone(Id=zone_id) | |
| def usage(): | |
| print >> sys.stderr, "Usage: %s <domain> ..." % (sys.argv[0]) | |
| sys.exit(2) | |
| def main(): | |
| domains = sys.argv[1:] | |
| if not domains: | |
| usage() | |
| domains = set(map(lambda d: d if d.endswith('.') else d + '.', domains)) | |
| logger = setup_logger() | |
| client = boto3.client('route53') | |
| logging.info("Enumerating zones...") | |
| zones = iter_zones(client) | |
| zones_to_delete = [(zone['Id'], zone['Name']) for zone in iter_zones(client) if zone['Name'] in domains] | |
| logging.info("Enumeration finished. Ready to kill folliwing zones: %s", zones_to_delete) | |
| for zone_id, zone_name in zones_to_delete: | |
| logging.info("Wiping zone %s...", zone_name) | |
| try: | |
| delete_zone(client, zone_id) | |
| except Exception as e: | |
| logging.exception("Exception occured during zone deletion:") | |
| else: | |
| logging.info("Zone %s deleted.", zone_name) | |
| if __name__ == '__main__': | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment