diff --git a/code/ddns-lambda.py b/code/ddns-lambda.py index f4853e2..29fce56 100755 --- a/code/ddns-lambda.py +++ b/code/ddns-lambda.py @@ -970,7 +970,8 @@ def lambda_handler( f"hostname {cname_host_name} in zone {cname_domain_suffix} with value {heritage_value}" if create_response == 'success': - dns_data.append(dns_data_tuple(cname_domain_suffix_id, cname_host_name_txt, cname_domain_suffix, 'TXT', heritage_value) + dns_data.append(dns_data_tuple( + cname_domain_suffix_id, cname_host_name_txt, cname_domain_suffix, 'TXT', heritage_value)) LOGGER.info("instance: %s, Created %s", instance_id, append_msg + lineno()) caller_response.append('Created ' + append_msg) @@ -987,7 +988,7 @@ def lambda_handler( # not running, so process delete CNAME and associated TXT record else: # Process and delete CNAME record and associated TXT record - process_response=process_delete_records( + process_response = process_delete_records( route53, instance_id, cname_domain_suffix_id, @@ -999,9 +1000,9 @@ def lambda_handler( ) # only true if existing delete_records and the delete_success from the subroutine is true - delete_records=delete_records and process_response['delete_success'] + delete_records = delete_records and process_response['delete_success'] # append to the lsit - caller_response=caller_response + process_response['msg'] + caller_response = caller_response + process_response['msg'] # Clean up DynamoDB after deleting records if state != 'running': @@ -1025,8 +1026,8 @@ def lambda_handler( LOGGER.info(f"dns_data records written:\n{pformat(dns_data)}") - count['end']=datetime.datetime.now() - count['elapsed_ms']=(count['end'] - count['start']).total_seconds() * 1000.0 + count['end'] = datetime.datetime.now() + count['elapsed_ms'] = (count['end'] - count['start']).total_seconds() * 1000.0 LOGGER.info(f"{APPNAME} stats: source={event_source} state={state} " + ' '.join([f"{c}={count[c]}" for c in sorted(count.keys())])) return caller_response @@ -1044,7 +1045,7 @@ def get_cname_from_tags(tags): LOGGER.debug("tag: %s", str(tag)) if TAGKEY_CNAME.upper() in tag.get('Key', {}).lstrip().upper(): - cname=tag.get('Value').lstrip().lower() + cname = tag.get('Value').lstrip().lower() return cname return None @@ -1058,12 +1059,12 @@ def get_instances(client, instance_id): :return: """ - i=0 - instance_data={} + i = 0 + instance_data = {} while i < MAX_API_RETRY: try: - instance_data=client.describe_instances(InstanceIds=[instance_id]) + instance_data = client.describe_instances(InstanceIds=[instance_id]) LOGGER.debug("%s", str(instance_data) + lineno()) break except ClientError as err: @@ -1104,16 +1105,16 @@ def new_list_hosted_zones(client, instance_id): :return: """ - i=0 - hosted_zones={} + i = 0 + hosted_zones = {} # retry to handle errors in the possible API call while i < MAX_API_RETRY: try: - hosted_zones=client.list_hosted_zones() + hosted_zones = client.list_hosted_zones() LOGGER.debug("list_hosted_zones returned without error. %s", lineno()) break except ClientError as err: - error_message=str(err) + error_message = str(err) if "(Throttling)" in str(err): LOGGER.debug( "list_hosted_zones throttled due to API limit, retrying: %s", str(err) + lineno()) @@ -1133,12 +1134,12 @@ def new_list_hosted_zones(client, instance_id): instance_id, str(i) + lineno()) if SNS_ENABLE: try: - sns_msg={} - sns_msg['instance_id']=instance_id - sns_msg['account_id']=get_caller_account_id() - sns_msg['client']='route53' - sns_msg['boto3_method']='list_hosted_zones' - sns_msg['message']='list_hosted_zones timed out' + sns_msg = {} + sns_msg['instance_id'] = instance_id + sns_msg['account_id'] = get_caller_account_id() + sns_msg['client'] = 'route53' + sns_msg['boto3_method'] = 'list_hosted_zones' + sns_msg['message'] = 'list_hosted_zones timed out' publish_to_sns(get_sns_client(), json.dumps(sns_msg)) LOGGER.info("instance: %s, sending sns message %s", instance_id, json.dumps(sns_msg) + lineno()) @@ -1159,18 +1160,18 @@ def new_list_hosted_zones_by_vpc(client, instance_id, vpc_id, region): :return: """ - i=0 - hosted_zones={} + i = 0 + hosted_zones = {} # retry to handle errors in the possible API call while i < MAX_API_RETRY: try: - hosted_zones=client.list_hosted_zones_by_vpc( + hosted_zones = client.list_hosted_zones_by_vpc( VPCId=vpc_id, VPCRegion=region) LOGGER.debug( "list_hosted_zones_by_vpc returned without error. %s", lineno()) break except ClientError as err: - error_message=str(err) + error_message = str(err) if "(Throttling)" in str(err): LOGGER.debug( "list_hosted_zones_by_vpc throttled due to API limit, retrying: %s", str(err) + lineno()) @@ -1190,14 +1191,14 @@ def new_list_hosted_zones_by_vpc(client, instance_id, vpc_id, region): vpc_id, instance_id, str(i) + lineno()) if SNS_ENABLE: try: - sns_msg={} - sns_msg['instance_id']=instance_id - sns_msg['vpc_id']=vpc_id - sns_msg['region']=region - sns_msg['account_id']=get_caller_account_id() - sns_msg['client']='route53' - sns_msg['boto3_method']='list_hosted_zones_by_vpc' - sns_msg['message']='list_hosted_zones_by_vpc timed out' + sns_msg = {} + sns_msg['instance_id'] = instance_id + sns_msg['vpc_id'] = vpc_id + sns_msg['region'] = region + sns_msg['account_id'] = get_caller_account_id() + sns_msg['client'] = 'route53' + sns_msg['boto3_method'] = 'list_hosted_zones_by_vpc' + sns_msg['message'] = 'list_hosted_zones_by_vpc timed out' publish_to_sns(get_sns_client(), json.dumps(sns_msg)) LOGGER.info("vpc_id: %s, instance: %s, sending sns message %s", vpc_id, instance_id, json.dumps(sns_msg) + lineno()) @@ -1274,7 +1275,7 @@ def get_item_from_dynamodb_table(client, table, instance_id): """ try: # Fetch item from DynamoDB - item=client.get_item( + item = client.get_item( TableName=table, Key={ 'InstanceId': { @@ -1290,16 +1291,16 @@ def get_item_from_dynamodb_table(client, table, instance_id): LOGGER.debug("returned item:" " %s", str(item['Item']['InstanceAttributes']['S']) + lineno()) - instance_attribute=item['Item']['InstanceAttributes']['S'] + instance_attribute = item['Item']['InstanceAttributes']['S'] # these 7 lines are handling for legacy DDB items created prior how items were written - instance_attribute=instance_attribute.replace("'", '"') - instance_attribute=instance_attribute.replace(" True,", ' "True",') - instance_attribute=instance_attribute.replace(" True}", ' "True"}') - instance_attribute=instance_attribute.replace(" True,", ' "True",') - instance_attribute=instance_attribute.replace(" False,", ' "False",') - instance_attribute=instance_attribute.replace(" False,", ' "False",') - instance_attribute=instance_attribute.replace(" False,", ' "False",') + instance_attribute = instance_attribute.replace("'", '"') + instance_attribute = instance_attribute.replace(" True,", ' "True",') + instance_attribute = instance_attribute.replace(" True}", ' "True"}') + instance_attribute = instance_attribute.replace(" True,", ' "True",') + instance_attribute = instance_attribute.replace(" False,", ' "False",') + instance_attribute = instance_attribute.replace(" False,", ' "False",') + instance_attribute = instance_attribute.replace(" False,", ' "False",') LOGGER.debug("item: %s", str(instance_attribute) + lineno()) return json.loads(instance_attribute) @@ -1316,7 +1317,7 @@ def get_private_hosted_zone_collection(private_hosted_zones): :return: """ try: - private_hosted_zone_collection=[] + private_hosted_zone_collection = [] for item in private_hosted_zones: LOGGER.debug("item: %s", str(item) + lineno()) @@ -1334,11 +1335,11 @@ def get_private_hosted_zone_collection_by_vpc(private_hosted_zones): :return: """ try: - private_hosted_zone_collection=[] + private_hosted_zone_collection = [] for item in private_hosted_zones: LOGGER.debug("item: %s", str(item) + lineno()) - my_item={ + my_item = { 'name': item['Name'], 'zone_id': item['HostedZoneId'], 'owner_account': item['Owner'].get('OwningAccount', ''), @@ -1359,7 +1360,7 @@ def get_private_hosted_zones(hosted_zones): :return: """ try: - private_hosted_zones=[] + private_hosted_zones = [] for item in hosted_zones['HostedZones']: LOGGER.debug("item: %s", str(item) + lineno()) @@ -1381,7 +1382,7 @@ def get_private_hosted_zones_by_vpc(hosted_zones): :return: """ try: - private_hosted_zones=[] + private_hosted_zones = [] for item in hosted_zones['HostedZoneSummaries']: LOGGER.debug("item: %s", str(item) + lineno()) @@ -1401,19 +1402,19 @@ def get_dhcp_option_set_id_for_vpc(client, instance_id, vpc_id): :return: """ - i=0 + i = 0 while i < MAX_API_RETRY: try: - option_sets={} - results=client.describe_vpcs() + option_sets = {} + results = client.describe_vpcs() for item in results['Vpcs']: if 'DhcpOptionsId' in item: - option_sets[str(item['VpcId'])]=item['DhcpOptionsId'] + option_sets[str(item['VpcId'])] = item['DhcpOptionsId'] else: - option_sets[str(item['VpcId'])]=None - option_set_for_vpc=option_sets[vpc_id] + option_sets[str(item['VpcId'])] = None + option_set_for_vpc = option_sets[vpc_id] LOGGER.debug("option set for vpc: %s", str(option_set_for_vpc) + lineno()) break @@ -1517,24 +1518,24 @@ def new_change_resource_recordset(oclient, instance_id, zone_id, host_name, host # this ignores the client, and uses the session from sessions[account] with a new route53 client global phz_collection_by_vpc - zone_item=phz_collection_by_vpc[hosted_zone_name] + zone_item = phz_collection_by_vpc[hosted_zone_name] LOGGER.debug("Using zone %s, zone item %s: %s", str( hosted_zone_name), str(zone_item), lineno()) - zone_account=zone_item['owner_account'] + zone_account = zone_item['owner_account'] try: LOGGER.debug("Calling get_session_assume_role() on account %s: %s", zone_account, lineno()) - this_session=get_session_assume_role(zone_account) + this_session = get_session_assume_role(zone_account) except Exception as err: LOGGER.error("Unable to esablish assume_role session in account %s: %s", str(zone_account), str(err) + lineno()) - update_response="AssumeRoleFailed" + update_response = "AssumeRoleFailed" return update_response - client=this_session.client('route53') + client = this_session.client('route53') - i=0 - update_response={} + i = 0 + update_response = {} LOGGER.debug("Creating %s record %s in zone %s: %s", record_type, host_name, hosted_zone_name, lineno()) @@ -1544,7 +1545,7 @@ def new_change_resource_recordset(oclient, instance_id, zone_id, host_name, host try: LOGGER.debug("Try %s Creating %s record %s in zone %s: %s", str( i), record_type, host_name, hosted_zone_name, lineno()) - change_batch={ + change_batch = { "Comment": f"Updated by {APPNAME} v{VERSION} from {account_id} in {region}", "Changes": [ { @@ -1565,7 +1566,7 @@ def new_change_resource_recordset(oclient, instance_id, zone_id, host_name, host LOGGER.debug("change_resource_record_sets change_batch: %s", json.dumps(change_batch) + lineno()) - update_response=client.change_resource_record_sets( + update_response = client.change_resource_record_sets( HostedZoneId=zone_id, ChangeBatch=change_batch ) @@ -1576,12 +1577,12 @@ def new_change_resource_recordset(oclient, instance_id, zone_id, host_name, host except ClientError as err: if 'NoSuchHostedZone' in str(err) and 'No hosted zone found with ID' in str(err): LOGGER.error("Hosted zone not found error: %s", str(err) + lineno()) - update_response="NoSuchHostedZone" + update_response = "NoSuchHostedZone" break elif 'InvalidChangeBatch' in str(err) and 'is not permitted in zone' in str(err): LOGGER.error( "Cannot create record - most likely wrong zone name specified: %s", str(err) + lineno()) - update_response="InvalidChangeBatch-WrongZoneName" + update_response = "InvalidChangeBatch-WrongZoneName" break elif "(Throttling)" in str(err): LOGGER.debug("change_resource_record_sets UPSERT throttled due to API limit, retrying: %s", str( @@ -1605,13 +1606,13 @@ def new_change_resource_recordset(oclient, instance_id, zone_id, host_name, host if update_response == {}: if SNS_ENABLE: try: - sns_msg={} - sns_msg['instance_id']=instance_id - sns_msg['account_id']=get_caller_account_id() - sns_msg['client']='route53' - sns_msg['boto3_method']='change_resource_record_sets' - sns_msg['message']='change_resource_record_sets could not UPSERT record' - sns_msg['change_resource_record_sets']={ + sns_msg = {} + sns_msg['instance_id'] = instance_id + sns_msg['account_id'] = get_caller_account_id() + sns_msg['client'] = 'route53' + sns_msg['boto3_method'] = 'change_resource_record_sets' + sns_msg['message'] = 'change_resource_record_sets could not UPSERT record' + sns_msg['change_resource_record_sets'] = { 'HostedZoneId': zone_id, 'ChangeBatch': change_batch} publish_to_sns(get_sns_client(), json.dumps(sns_msg)) LOGGER.info("instance: %s, sending sns message %s", instance_id, @@ -1646,7 +1647,7 @@ def create_resource_record(client, instance_id, zone_id, host_name, hosted_zone_ # To prevent rate throttling # time.sleep(1) - create_response=new_change_resource_recordset( + create_response = new_change_resource_recordset( client, instance_id, zone_id, @@ -1658,19 +1659,19 @@ def create_resource_record(client, instance_id, zone_id, host_name, hosted_zone_ if create_response == 'NoSuchHostedZone': LOGGER.debug("DNS Record create failed: %s", str(create_response) + lineno()) - msg='NoSuchHostedZone: ' + str(create_response) + msg = 'NoSuchHostedZone: ' + str(create_response) elif create_response == 'InvalidChangeBatch-WrongZoneName': LOGGER.debug("DNS Record create failed: %s", str(create_response) + lineno()) - msg='InvalidChangeBatch-WrongZoneName: ' + str(create_response) + msg = 'InvalidChangeBatch-WrongZoneName: ' + str(create_response) elif create_response == {}: LOGGER.debug("DNS Record create failed: %s", str(create_response) + lineno()) - msg='DNS Recored Create Failed: ' + str(create_response) + msg = 'DNS Recored Create Failed: ' + str(create_response) else: LOGGER.debug("DNS Record create success: %s", str(create_response) + lineno()) - msg='success' + msg = 'success' LOGGER.debug("response: %s", str(create_response) + lineno()) return msg @@ -1738,24 +1739,24 @@ def new_get_resource_record(oclient, instance_id, zone_id, host_name, hosted_zon # this ignores the client, and uses the session from sessions[account] with a new route53 client global phz_collection_by_vpc - zone_item=phz_collection_by_vpc[hosted_zone_name] + zone_item = phz_collection_by_vpc[hosted_zone_name] LOGGER.debug("Using zone %s, zone item %s: %s", str( hosted_zone_name), str(zone_item), lineno()) - zone_account=zone_item['owner_account'] + zone_account = zone_item['owner_account'] try: LOGGER.debug("Calling get_session_assume_role() on account %s: %s", zone_account, lineno()) - this_session=get_session_assume_role(zone_account) + this_session = get_session_assume_role(zone_account) except Exception as err: LOGGER.error("Unable to esablish assume_role session in account %s: %s", str(zone_account), str(err) + lineno()) - update_response="AssumeRoleFailed" + update_response = "AssumeRoleFailed" return update_response - client=this_session.client('route53') + client = this_session.client('route53') - i=0 - value='' + i = 0 + value = '' while i < MAX_API_RETRY: try: @@ -1768,8 +1769,8 @@ def new_get_resource_record(oclient, instance_id, zone_id, host_name, hosted_zon LOGGER.debug("list_resource_record_sets looking for record %s in zone %s", str(host_name), str(hosted_zone_name) + lineno()) - fqdn=create_fqdn(host_name, hosted_zone_name) - response=client.list_resource_record_sets( + fqdn = create_fqdn(host_name, hosted_zone_name) + response = client.list_resource_record_sets( HostedZoneId=zone_id, # StartRecordName=host_name + hosted_zone_name, StartRecordName=fqdn, @@ -1780,12 +1781,12 @@ def new_get_resource_record(oclient, instance_id, zone_id, host_name, hosted_zon json.dumps(response) + lineno()) for rr_set in response['ResourceRecordSets']: - rr_name=rr_set['Name'] + rr_name = rr_set['Name'] # check if the return value matches the record, if not ignore # if the record isn't there, it returns the list_resource_record_sets returns the next record # if rr_name == (host_name + hosted_zone_name): if rr_name == fqdn: - value=rr_set['ResourceRecords'][0]['Value'] + value = rr_set['ResourceRecords'][0]['Value'] LOGGER.debug( f"list_resource_record_sets returned value {value}: {lineno()}") else: @@ -1821,12 +1822,12 @@ def new_get_resource_record(oclient, instance_id, zone_id, host_name, hosted_zon instance_id, str(MAX_API_RETRY) + lineno()) if SNS_ENABLE: try: - sns_msg={} - sns_msg['instance_id']=instance_id - sns_msg['account_id']=get_caller_account_id() - sns_msg['client']='route53' - sns_msg['boto3_method']='list_resource_record_sets' - sns_msg['message']='list_resource_record_sets timed out' + sns_msg = {} + sns_msg['instance_id'] = instance_id + sns_msg['account_id'] = get_caller_account_id() + sns_msg['client'] = 'route53' + sns_msg['boto3_method'] = 'list_resource_record_sets' + sns_msg['message'] = 'list_resource_record_sets timed out' publish_to_sns(get_sns_client(), json.dumps(sns_msg)) LOGGER.info("instance: %s, sending sns message %s", instance_id, json.dumps(sns_msg) + lineno()) @@ -1853,24 +1854,24 @@ def new_delete_resource_record(oclient, instance_id, zone_id, host_name, hosted_ # this ignores the client, and uses the session from sessions[account] with a new route53 client global phz_collection_by_vpc - zone_item=phz_collection_by_vpc[hosted_zone_name] + zone_item = phz_collection_by_vpc[hosted_zone_name] LOGGER.debug("Using zone %s, zone item %s: %s", str( hosted_zone_name), str(zone_item), lineno()) - zone_account=zone_item['owner_account'] + zone_account = zone_item['owner_account'] try: LOGGER.debug("Calling get_session_assume_role() on account %s: %s", zone_account, lineno()) - this_session=get_session_assume_role(zone_account) + this_session = get_session_assume_role(zone_account) except Exception as err: LOGGER.error("Unable to esablish assume_role session in account %s: %s", str(zone_account), str(err) + lineno()) - update_response="AssumeRoleFailed" + update_response = "AssumeRoleFailed" return update_response - client=this_session.client('route53') + client = this_session.client('route53') - i=0 - delete_response={} + i = 0 + delete_response = {} LOGGER.debug("Deleting %s record %s in zone %s: %s", record_type, host_name, hosted_zone_name, lineno()) @@ -1885,7 +1886,7 @@ def new_delete_resource_record(oclient, instance_id, zone_id, host_name, hosted_ try: LOGGER.debug("Try %s Deleting %s record %s in zone %s: %s", str( i), record_type, host_name, hosted_zone_name, lineno()) - change_batch={ + change_batch = { "Comment": f"Deleted by {APPNAME} v{VERSION} from {account_id} in {region}", "Changes": [ { @@ -1906,7 +1907,7 @@ def new_delete_resource_record(oclient, instance_id, zone_id, host_name, hosted_ LOGGER.debug("change_resource_record_sets change_batch: %s", json.dumps(change_batch) + lineno()) - delete_response=client.change_resource_record_sets( + delete_response = client.change_resource_record_sets( HostedZoneId=zone_id, ChangeBatch=change_batch ) @@ -1919,16 +1920,16 @@ def new_delete_resource_record(oclient, instance_id, zone_id, host_name, hosted_ if 'NoSuchHostedZone' in str(err) and 'No hosted zone found with ID' in str(err): LOGGER.debug("Hosted zone not found error: %s", str(err) + lineno()) - delete_response="NoSuchHostedZone" + delete_response = "NoSuchHostedZone" break elif 'InvalidChangeBatch' in str(err) and 'it was not found' in str(err): LOGGER.debug("Record not found error: %s", str(err) + lineno()) - delete_response="InvalidChangeBatch-RecordNotFound" + delete_response = "InvalidChangeBatch-RecordNotFound" break elif 'InvalidChangeBatch' in str(err) and 'values provided do not match the current values' in str(err): LOGGER.debug("Record do not match current value error: %s", str(err) + lineno()) - delete_response="InvalidChangeBatch-RecordDoNotMatch" + delete_response = "InvalidChangeBatch-RecordDoNotMatch" break elif '(Throttling)' in str(err): LOGGER.debug("change_resource_record_sets DELETE throttled due to API limit, retrying: %s", str( @@ -1951,13 +1952,13 @@ def new_delete_resource_record(oclient, instance_id, zone_id, host_name, hosted_ if (delete_response == {} or delete_response == "InvalidChangeBatch-RecordDoNotMatch"): if SNS_ENABLE: try: - sns_msg={} - sns_msg['instance_id']=instance_id - sns_msg['account_id']=get_caller_account_id() - sns_msg['client']='route53' - sns_msg['boto3_method']='change_resource_record_sets' - sns_msg['message']='change_resource_record_sets could not DELETE record' - sns_msg['change_resource_record_sets']={ + sns_msg = {} + sns_msg['instance_id'] = instance_id + sns_msg['account_id'] = get_caller_account_id() + sns_msg['client'] = 'route53' + sns_msg['boto3_method'] = 'change_resource_record_sets' + sns_msg['message'] = 'change_resource_record_sets could not DELETE record' + sns_msg['change_resource_record_sets'] = { 'HostedZoneId': zone_id, 'ChangeBatch': change_batch} publish_to_sns(get_sns_client(), json.dumps(sns_msg)) LOGGER.info("instance: %s, sending sns message %s", instance_id, @@ -1978,11 +1979,11 @@ def get_zone_id(zone_name, hosted_zones, private_zone=True): """ try: if zone_name[-1] != '.': - zone_name=zone_name + '.' + zone_name = zone_name + '.' LOGGER.debug("zone name: %s", str(zone_name) + lineno()) LOGGER.debug("hosted_zones: %s", str(hosted_zones) + lineno()) - zones=[] + zones = [] for record in hosted_zones['HostedZones']: LOGGER.debug("record: %s", str(record) + lineno()) if record['Config']['PrivateZone'] == private_zone: @@ -1991,9 +1992,9 @@ def get_zone_id(zone_name, hosted_zones, private_zone=True): LOGGER.debug("zones: %s", str(zones) + lineno()) try: - zone_id_long=zones[0]['Id'] + zone_id_long = zones[0]['Id'] LOGGER.debug("zone id: %s", str(zone_id_long) + lineno()) - zone_id=str.split(str(zone_id_long), '/')[2] + zone_id = str.split(str(zone_id_long), '/')[2] return zone_id except: return None @@ -2013,8 +2014,8 @@ def is_valid_hostname(hostname): if hostname is None or len(hostname) > 255: return False if hostname[-1] == ".": - hostname=hostname[:-1] - allowed=re.compile(r"(?!-)[A-Z\d-]{1,63}(? 1: # remove beginning quote if info[0] == '"': - info=info[1:] + info = info[1:] # remove ending quote if info[-1] == '"': - info=info[:-1] + info = info[:-1] - kv_results={} - kv=info.split(',') + kv_results = {} + kv = info.split(',') LOGGER.debug("heritage split result: %s", str(kv) + lineno()) - header=kv.pop(0).split('=') + header = kv.pop(0).split('=') if header[0] != 'heritage': LOGGER.debug("heritage analysis: does not contain heritage header, returning: %s", str(kv_results) + lineno()) return kv_results else: - appname=header[1] - kv_results['application_name']=appname + appname = header[1] + kv_results['application_name'] = appname LOGGER.debug("heritage analysis: assigning application_name: %s", str(appname) + lineno()) try: for item in kv: - k, v=item.split('=', 2) + k, v = item.split('=', 2) LOGGER.debug("heritage item: key: %s, value: %s", str(k), str(v) + lineno()) # print('appname',appname,'k',k,'v',v) if appname + '/' in k: - nk=k.replace(appname + '/', '') - kv_results[nk]=v + nk = k.replace(appname + '/', '') + kv_results[nk] = v # print('nk',nk) if kv_results.get('version') is None: # version=kv_result.pop('version') # else: - version='null' + version = 'null' # return initialize_heritage(appname,version,kv_results) LOGGER.debug("heritage parsed dictionary: %s", @@ -2628,7 +2629,7 @@ def get_heritage_item(data, key): str(data), str(type(data)) + lineno()) return None else: - result=data.get(key, None) + result = data.get(key, None) LOGGER.debug("get_heritage_item: getting key %s value %s", str(key), str(result) + lineno()) return result @@ -2674,7 +2675,7 @@ def publish_to_sns(client, message): if SNS_TOPIC_ARN != '': try: - response=client.publish( + response = client.publish( TopicArn=SNS_TOPIC_ARN, Message=str(message) ) @@ -2699,20 +2700,20 @@ def process_delete_records(route53, instance_id, zone_id, :return response: # dictionary of 'delete_success' and 'msg' """ - response={} - response_delete_success=True - response_msg=[] + response = {} + response_delete_success = True + response_msg = [] LOGGER.info("instance: %s, Delete %s Record. Checking TXT record association for %s in zone %s", instance_id, record_type, record_name, zone_name + lineno()) # if record type is CNAME, we need to add the TXT RR prefix if record_type == 'CNAME': - txt_record_name=TXT_RR_PREFIX + '.' + record_name + txt_record_name = TXT_RR_PREFIX + '.' + record_name else: - txt_record_name=record_name + txt_record_name = record_name - heritage_value=new_get_resource_record( + heritage_value = new_get_resource_record( route53, instance_id, zone_id, @@ -2723,25 +2724,25 @@ def process_delete_records(route53, instance_id, zone_id, ) # Return the dictionary of the value with comma separated - heritage=parse_heritage(heritage_value) + heritage = parse_heritage(heritage_value) LOGGER.debug("heritage parsed data in string format: %s", str(heritage) + lineno()) # check if the TXT record was created by the Lambda as match instance-id if verify_heritage_owner(heritage, HERITAGE_TAG): LOGGER.debug("TXT record was created by Lambda DDNS %s", HERITAGE_TAG + lineno()) - heritage_own=True + heritage_own = True else: LOGGER.info("TXT record was not created by Lambda DDNS %s", HERITAGE_TAG + lineno()) - heritage_own=False + heritage_own = False if compare_heritage(heritage, 'instance_id', instance_id): LOGGER.debug("TXT record matches instance_id: %s", instance_id + lineno()) - heritage_instance_match=True + heritage_instance_match = True else: LOGGER.info("TXT record does not match instance_id: %s", instance_id + lineno()) - heritage_instance_match=False + heritage_instance_match = False # delete A/PTR/AAAA/CNAME record if heritage_own and heritage_instance_match: @@ -2750,13 +2751,13 @@ def process_delete_records(route53, instance_id, zone_id, LOGGER.info("Deleting %s resource record %s, in zone %s, with a value of %s", record_type, record_name, zone_name, record_value + lineno()) - response_text='Delete ' + record_type + \ + response_text = 'Delete ' + record_type + \ ' record in zone id: ' + zone_id + \ ' for record ' + record_name + \ ' in zone named ' + zone_name + \ ' with value: ' + record_value - delete_response=new_delete_resource_record( + delete_response = new_delete_resource_record( route53, instance_id, zone_id, @@ -2767,7 +2768,7 @@ def process_delete_records(route53, instance_id, zone_id, ) if delete_response == 'NoSuchHostedZone': - response_delete_success=False + response_delete_success = False response_msg.append("Failed, no such zone: " + response_text) LOGGER.info("instance: %s, NoSuchHostedZone: %s", instance_id, response_text + lineno()) @@ -2776,13 +2777,13 @@ def process_delete_records(route53, instance_id, zone_id, LOGGER.info("instance: %s, InvalidChangeBatch-RecordNotFound: %s", instance_id, response_text + lineno()) elif delete_response == 'InvalidChangeBatch-RecordDoNotMatch': - response_delete_success=False + response_delete_success = False response_msg.append( "Failed, requested delete do not match existing record: " + response_text) LOGGER.info("instance: %s, InvalidChangeBatch-RecordDoNotMatch: %s", instance_id, response_text + lineno()) elif delete_response == {}: - response_delete_success=False + response_delete_success = False response_msg.append( "Failed, could NOT delete Record: " + response_text) LOGGER.info("instance: %s, Failed, could NOT delete Record: %s", @@ -2793,31 +2794,31 @@ def process_delete_records(route53, instance_id, zone_id, response_msg.append("Success: " + response_text) except BaseException as err: - response_delete_success=False + response_delete_success = False LOGGER.error("instance: %s, unexpected error. %s\n", instance_id, str(err) + lineno()) else: - response_delete_success=False + response_delete_success = False response_msg.append("Failed, the TXT record for the " + record_type + " record does not match expected value. Will not delete the " + record_type + " record.") LOGGER.error("instance: %s, the TXT record for the %s record does not match expected value. Will not delete the %s record. %s\n", instance_id, record_type, record_type, lineno()) if SNS_ENABLE: try: - sns_msg={} - sns_msg['instance_id']=instance_id - sns_msg['account_id']=get_caller_account_id() - sns_msg['message']='TXT record does not match. Will not delete the A/PTR/CNAME/AAAA record.' - - sns_heritage={} - sns_heritage['record_type']=record_type - sns_heritage['record_name']=record_name - sns_heritage['zone_name']=zone_name - sns_heritage['zone_id']=zone_id - sns_heritage['heritage_value']=heritage_value - - sns_msg['heritage']=sns_heritage + sns_msg = {} + sns_msg['instance_id'] = instance_id + sns_msg['account_id'] = get_caller_account_id() + sns_msg['message'] = 'TXT record does not match. Will not delete the A/PTR/CNAME/AAAA record.' + + sns_heritage = {} + sns_heritage['record_type'] = record_type + sns_heritage['record_name'] = record_name + sns_heritage['zone_name'] = zone_name + sns_heritage['zone_id'] = zone_id + sns_heritage['heritage_value'] = heritage_value + + sns_msg['heritage'] = sns_heritage publish_to_sns(get_sns_client(), json.dumps(sns_msg)) LOGGER.info("instance: %s, sending sns message %s", instance_id, json.dumps(sns_msg) + lineno()) @@ -2831,13 +2832,13 @@ def process_delete_records(route53, instance_id, zone_id, LOGGER.info("Deleting heritage TXT resource record %s, in the zone %s, with value of %s", txt_record_name, zone_name, str(heritage_value) + lineno()) - response_text='Delete ' + 'TXT' + \ + response_text = 'Delete ' + 'TXT' + \ ' record in zone id: ' + zone_id + \ ' for record ' + txt_record_name + \ ' in zone named ' + zone_name + \ ' with value: ' + str(heritage_value) - delete_response=new_delete_resource_record( + delete_response = new_delete_resource_record( route53, instance_id, zone_id, @@ -2847,7 +2848,7 @@ def process_delete_records(route53, instance_id, zone_id, str(heritage_value)) if delete_response == 'NoSuchHostedZone': - response_delete_success=False + response_delete_success = False response_msg.append("Failed, no such zone: " + response_text) LOGGER.info("instance: %s, NoSuchHostedZone: %s", instance_id, response_text + lineno()) @@ -2856,13 +2857,13 @@ def process_delete_records(route53, instance_id, zone_id, LOGGER.info("instance: %s, InvalidChangeBatch-RecordNotFound: %s", instance_id, response_text + lineno()) elif delete_response == 'InvalidChangeBatch-RecordDoNotMatch': - response_delete_success=False + response_delete_success = False response_msg.append( "Failed, requested delete do not match existing record: " + response_text) LOGGER.info("instance: %s, InvalidChangeBatch-RecordDoNotMatch: %s", instance_id, response_text + lineno()) elif delete_response == {}: - response_delete_success=False + response_delete_success = False response_msg.append( "Failed, could NOT delete Record: " + response_text) LOGGER.info("instance: %s, Failed Could NOT delete Record: %s", @@ -2872,11 +2873,11 @@ def process_delete_records(route53, instance_id, zone_id, LOGGER.info("instance: %s, Success: %s", instance_id, response_text + lineno()) except BaseException as err: - response_delete_success=False + response_delete_success = False LOGGER.error("instance: %s, unexpected error. %s\n", instance_id, str(err) + lineno()) else: - response_delete_success=False + response_delete_success = False response_msg.append("Failed, the TXT record for " + record_type + " does not match expected value. Will not delete the TXT record.") LOGGER.error("instance: %s, the TXT record for the %s does not match expected value. Will not delete TXT record. %s", @@ -2884,19 +2885,19 @@ def process_delete_records(route53, instance_id, zone_id, if SNS_ENABLE: try: - sns_msg={} - sns_msg['instance_id']=instance_id - sns_msg['account_id']=get_caller_account_id() - sns_msg['message']='TXT record does not match. Will not delete the TXT record.' - - sns_heritage={} - sns_heritage['record_type']='TXT' - sns_heritage['record_name']=txt_record_name - sns_heritage['zone_name']=zone_name - sns_heritage['zone_id']=zone_id - sns_heritage['heritage_value']=heritage_value - - sns_msg['heritage']=sns_heritage + sns_msg = {} + sns_msg['instance_id'] = instance_id + sns_msg['account_id'] = get_caller_account_id() + sns_msg['message'] = 'TXT record does not match. Will not delete the TXT record.' + + sns_heritage = {} + sns_heritage['record_type'] = 'TXT' + sns_heritage['record_name'] = txt_record_name + sns_heritage['zone_name'] = zone_name + sns_heritage['zone_id'] = zone_id + sns_heritage['heritage_value'] = heritage_value + + sns_msg['heritage'] = sns_heritage publish_to_sns(get_sns_client(), json.dumps(sns_msg)) LOGGER.info("instance: %s, sending sns message %s", instance_id, json.dumps(sns_msg) + lineno()) @@ -2906,8 +2907,8 @@ def process_delete_records(route53, instance_id, zone_id, str(sys.exc_info()[0]) + lineno()) # create a dictionary to return - response['delete_success']=response_delete_success - response['msg']=response_msg + response['delete_success'] = response_delete_success + response['msg'] = response_msg return response @@ -2920,13 +2921,13 @@ def process_tags_flags(tags): :return dict(string): flag settings in defaultdict for controlling which names are registered and when """ - tag_dict={tag['Key'].lstrip().lower(): tag['Value'] for tag in tags} - flags_dict=defaultdict(lambda: False) - flags=tag_dict.get(TAGKEY_FLAGS.lower(), '').split(',') + tag_dict = {tag['Key'].lstrip().lower(): tag['Value'] for tag in tags} + flags_dict = defaultdict(lambda: False) + flags = tag_dict.get(TAGKEY_FLAGS.lower(), '').split(',') for flag in flags: if flag != '': LOGGER.debug("Setting 'flags' to True: %s", str(flag) + lineno()) - flags_dict[flag]=True + flags_dict[flag] = True return flags_dict @@ -2942,7 +2943,7 @@ def process_tags_value(name): """ if name != '': - components=parse_hostname_to_components(name) + components = parse_hostname_to_components(name) if components: return (True, components[0], components[1]) return (False, None, None) @@ -2956,10 +2957,10 @@ def process_tags_option_cname(tags): : return tuple(bool, str, str): true | false if vaid, hostname, domainname """ - tag_dict={tag['Key'].lstrip().lower(): tag['Value'] for tag in tags} + tag_dict = {tag['Key'].lstrip().lower(): tag['Value'] for tag in tags} # value = tag_dict.get(TAGKEY_CNAME.lower(), '').split(',') # need additional work to handle a comma-separated list - value=tag_dict.get(TAGKEY_CNAME.lower(), '') + value = tag_dict.get(TAGKEY_CNAME.lower(), '') return process_tags_value(value) @@ -2971,8 +2972,8 @@ def process_tags_option_zone(tags): : return tuple(bool, str, str): true | false if vaid, hostname, domainname """ - tag_dict={tag['Key'].lstrip().lower(): tag['Value'] for tag in tags} - value=tag_dict.get(TAGKEY_ZONE.lower(), '') + tag_dict = {tag['Key'].lstrip().lower(): tag['Value'] for tag in tags} + value = tag_dict.get(TAGKEY_ZONE.lower(), '') return process_tags_value(value) @@ -2984,8 +2985,8 @@ def process_tags_option_name(tags): : return: """ - tag_dict={tag['Key'].lstrip().lower(): tag['Value'] for tag in tags} - value=tag_dict.get(TAGKEY_HOSTNAME.lower(), '') + tag_dict = {tag['Key'].lstrip().lower(): tag['Value'] for tag in tags} + value = tag_dict.get(TAGKEY_HOSTNAME.lower(), '') return process_tags_value(value) @@ -2997,8 +2998,8 @@ def process_tags_name(tags): : return: """ - tag_dict={tag['Key'].lstrip().lower(): tag['Value'] for tag in tags} - value=tag_dict.get('name', '') + tag_dict = {tag['Key'].lstrip().lower(): tag['Value'] for tag in tags} + value = tag_dict.get('name', '') return process_tags_value(value) @@ -3010,26 +3011,26 @@ def get_session_assume_role(account): : return: boto3.session corresonding to the assumed role """ - this_session=sessions.get(account, None) + this_session = sessions.get(account, None) try: if this_session is None: LOGGER.debug("Existing session not found for account %s: %s", account, lineno()) - role_arn=format(REMOTE_ROLE_ARN_FORMAT % (partition, account)) - response=sts_client.assume_role(RoleArn=role_arn, RoleSessionName=APPNAME) + role_arn = format(REMOTE_ROLE_ARN_FORMAT % (partition, account)) + response = sts_client.assume_role(RoleArn=role_arn, RoleSessionName=APPNAME) LOGGER.debug("Called sts:assumerole for arn %s: %s", str(role_arn), lineno()) - credentials=response['Credentials'] + credentials = response['Credentials'] LOGGER.info( f"Called assume_role for {account} ARN {role_arn}, got credentials with expiration {credentials['Expiration']}: {lineno()}") count['assumed_role.new'] += 1 - this_session=boto3.Session( + this_session = boto3.Session( aws_access_key_id=credentials["AccessKeyId"], aws_secret_access_key=credentials["SecretAccessKey"], aws_session_token=credentials["SessionToken"], region_name=region) - sessions[account]=this_session + sessions[account] = this_session LOGGER.debug("Crated new session for account %s: %s", str(account), lineno()) else: @@ -3055,10 +3056,10 @@ def parse_hostname_to_components(name): """ global phz_collection_by_vpc - names=name.rstrip('.').split('.') + names = name.rstrip('.').split('.') for i in range(len(names)): - host='.'.join(names[0:i]) - domain='.'.join(names[i:]) + '.' + host = '.'.join(names[0:i]) + domain = '.'.join(names[i:]) + '.' if phz_collection_by_vpc.get(domain): return (host, domain) LOGGER.error( @@ -3079,6 +3080,6 @@ def create_fqdn(host, zone): :return (str,str): Tuple containing hostname components (may include dot) and domain name for which a PHZ exists. None is returned if not found. """ - fqdn=host.replace(zone, '').rstrip('.') + '.' + zone + fqdn = host.replace(zone, '').rstrip('.') + '.' + zone fqdn += '.' if fqdn[-1] != '.' else '' return fqdn diff --git a/code/ddns-lambda.zip b/code/ddns-lambda.zip index bc571b7..f5d77dc 100644 Binary files a/code/ddns-lambda.zip and b/code/ddns-lambda.zip differ