Skip to content

Commit

Permalink
Merge pull request #14 from terraform-modules/add-txt-records
Browse files Browse the repository at this point in the history
add heritage txt record support
  • Loading branch information
badra001 committed Feb 22, 2022
2 parents 80191c0 + f3529af commit d37ecd6
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 26 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,7 @@
* 0.0.22 -- 2022-02-22
- code 0.0.13
- fix typo

* 0.0.23 -- 2022-02-22
- code 0.1.0
- add heritage TXT record support
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ No modules.
| <a name="input_component_tags"></a> [component\_tags](#input\_component\_tags) | Additional tags for Components (s3, kms, ddb) | `map(map(string))` | <pre>{<br> "ddb": {},<br> "kms": {},<br> "s3": {}<br>}</pre> | no |
| <a name="input_create"></a> [create](#input\_create) | Flag to indicate whether to create the resources or not (default: true) | `bool` | `true` | no |
| <a name="input_dynamodb_table_name"></a> [dynamodb\_table\_name](#input\_dynamodb\_table\_name) | Different DynamoDB table name to override default of var.name) | `string` | `null` | no |
| <a name="input_lambda_environment_variables"></a> [lambda\_environment\_variables](#input\_lambda\_environment\_variables) | Map of lambda environment variables and values | `map(string)` | <pre>{<br> "DNS_RR_TimeToLive": 60,<br> "DynamoDBName": null,<br> "SleepTime": 60,<br> "TagKeyCname": "boc:dns:cname",<br> "TagKeyHostName": "boc:dns:name",<br> "TagKeyZone": "boc:dns:zone"<br>}</pre> | no |
| <a name="input_lambda_environment_variables"></a> [lambda\_environment\_variables](#input\_lambda\_environment\_variables) | Map of lambda environment variables and values | `map(string)` | <pre>{<br> "DNS_RR_TimeToLive": 60,<br> "DynamoDBName": null,<br> "HeritageIdentifier": "dynr53",<br> "HeritageTXTRecordPrefix": "_txt",<br> "SleepTime": 60,<br> "TagKeyCname": "boc:dns:cname",<br> "TagKeyHostName": "boc:dns:name",<br> "TagKeyZone": "boc:dns:zone"<br>}</pre> | no |
| <a name="input_lambda_name"></a> [lambda\_name](#input\_lambda\_name) | Different Lambda name to override default of var.name) | `string` | `null` | no |
| <a name="input_name"></a> [name](#input\_name) | Name to use within all the created resources (default: inf-dynamic-route53) | `string` | `"inf-dynamic-route53"` | no |
| <a name="input_override_prefixes"></a> [override\_prefixes](#input\_override\_prefixes) | Override built-in prefixes by component. This should be used primarily for common infrastructure things | `map(string)` | `{}` | no |
Expand Down
180 changes: 162 additions & 18 deletions code/ddns-lambda.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
LOGGER = logging.getLogger()
ACCOUNT = None
REGION = None
VERSION = '0.0.13'
VERSION = '0.1.0'

# Adjust the logging level [logging.INFO, logging.DEBUG, logging.WARNING, etc]
LOGGER.setLevel(logging.DEBUG)
Expand All @@ -86,6 +86,9 @@
DNS_RR_TTL = int(os.environ.get('DNS_RR_TimeToLive', '60'))
DNS_RR_TTL = 60 if DNS_RR_TTL == 0 else DNS_RR_TTL
TF_MODULE_VERSION = os.environ.get('tf_module_version', '(unknown)')
# for CNAMEs
TXT_RR_PREFIX = os.environ.get('HeritageTXTRecordPrefix', '_txt')
HERITAGE_TAG = os.environ.get('HeritageIdentifier', 'dynr53')

print('Loading function v{} tf_module_version {}: {}'.format(
VERSION, TF_MODULE_VERSION, datetime.datetime.now().time().isoformat()))
Expand Down Expand Up @@ -132,12 +135,25 @@ def get_dynamodb_client():
print("Unexpected error: %s" % err)


def get_caller_account_id():
"""
Get AWS Account ID from STS
:return str: AWS Account ID
"""
try:
return boto3.client('sts').get_caller_identity()['Account'])
except ClientError as err:
print("Unexpected error: %s" % err)


def lambda_handler(
event,
context,
dynamodb_client=get_dynamodb_client(),
compute=get_ec2_client(),
route53=get_route53_client()
dynamodb_client = get_dynamodb_client(),
compute = get_ec2_client(),
route53 = get_route53_client()


):
"""
Check to see whether a DynamoDB table already exists. If not, create it.
Expand All @@ -155,9 +171,9 @@ def lambda_handler(
LOGGER.info("event: %s", str(event) + lineno())
LOGGER.info("context: %s", str(context) + lineno())

caller_response = []
caller_response=[]
# Checking to make sure there is a dynamodb table named in the Env Variable
tables = list_tables(dynamodb_client)
tables=list_tables(dynamodb_client)

LOGGER.info("tables: %s", str(tables))
if DDBNAME in tables['TableNames']:
Expand All @@ -168,34 +184,36 @@ def lambda_handler(

# Set variables
# Get the state from the Event stream
state = event['detail']['state']
state=event['detail']['state']
LOGGER.debug("instance state: %s", str(state) + lineno())

# Get the instance id, region, and tag collection
instance_id = event['detail']['instance-id']
instance_id=event['detail']['instance-id']
LOGGER.debug("instance id: %s", str(instance_id) + lineno())
region = event['region']
region=event['region']
LOGGER.debug("region: %s", str(region) + lineno())
account_id=get_caller_account_id()
LOGGER.debug("account_id: %s", str(account_id) + lineno())

# Only doing something if the state is running
if state == 'running':
LOGGER.debug("sleeping for maximum {} seconds {}".format(SLEEPTIME, lineno()))

# wait increment and wait until maximum sleeptime
i = 1
i=1
while i < SLEEPTIME:
LOGGER.debug("waiting count: %s", str(i) + lineno())
time.sleep(1)
i += 1

try:
# Get instance information
instance = get_instances(compute, instance_id)
instance=get_instances(compute, instance_id)

t_private_ip = instance['Reservations'][0]['Instances'][0]['PrivateIpAddress']
t_private_dns_name = instance['Reservations'][0]['Instances'][0]['PrivateDnsName']
t_subnet_id = instance['Reservations'][0]['Instances'][0]['SubnetId']
t_vpc_id = instance['Reservations'][0]['Instances'][0]['VpcId']
t_private_ip=instance['Reservations'][0]['Instances'][0]['PrivateIpAddress']
t_private_dns_name=instance['Reservations'][0]['Instances'][0]['PrivateDnsName']
t_subnet_id=instance['Reservations'][0]['Instances'][0]['SubnetId']
t_vpc_id=instance['Reservations'][0]['Instances'][0]['VpcId']

# if key attributes are found, then break out of the loop
if all([t_private_ip, t_private_dns_name, t_subnet_id, t_vpc_id]):
Expand All @@ -211,9 +229,9 @@ def lambda_handler(
# Remove null values from the response. You cannot save a dict/JSON
# document in DynamoDB if it contains null values
LOGGER.debug("instance: %s", str(instance) + lineno())
instance = remove_empty_from_dict(instance)
instance_dump = json.dumps(instance, default=json_serial)
instance_attributes = json.loads(instance_dump)
instance=remove_empty_from_dict(instance)
instance_dump=json.dumps(instance, default = json_serial)
instance_attributes=json.loads(instance_dump)
LOGGER.debug("instance_attributes: %s", str(instance_attributes) + lineno())
LOGGER.debug("trying to put instance information in "
"dynamo table %s", str(instance_attributes) + lineno())
Expand Down Expand Up @@ -586,6 +604,17 @@ def lambda_handler(
LOGGER.debug("valid_dns_zones:"
" %s", str(valid_dns_zones) + lineno())

# create the TXT heritage record
heritage = initialize_heritage(HERITAGE_TAG,VERSION,
{
'instance_id': instance_id,
'account_id': account_id,
'region': region
} )
add_heritage_item_timestamp(heritage,'create_time')
heritage_value = format_heritage(heritage)
# txt=format_heritage(h)

# Create OR Delete the A / PTR Record
if state == 'running':
# create the records
Expand All @@ -608,6 +637,25 @@ def lambda_handler(
' with value: ' +
str(private_ip))

if len(heritage)>0:
LOGGER.debug("Creating heritage TXT resource records %s", lineno())
create_resource_record(
route53,
final_hosted_zone_id,
final_private_hostname,
final_hosted_zone_name,
'TXT',
heritage_value
)

caller_response.append('Created TXT record in zone id: ' +
str(final_hosted_zone_id) +
' for hosted zone ' +
str(final_private_hostname) + '.' +
str(final_hosted_zone_name) +
' with value: ' +
str(heritage_value))

if reverse_zone_associated:
create_resource_record(
route53,
Expand All @@ -625,6 +673,24 @@ def lambda_handler(
'in-addr.arpa with value: ' +
str(final_private_dns_name))

if len(heritage)>0:
create_resource_record(
route53,
reverse_lookup_zone_id,
reversed_ip_address,
'in-addr.arpa',
'TXT',
heritage_value
)

caller_response.append('Created TXT reverse record in zone id: ' +
str(reverse_lookup_zone_id) +
' for hosted zone ' +
str(reversed_ip_address) +
'in-addr.arpa with value: ' +
str(heritage_value))


except BaseException as err:
LOGGER.info("unexpected error. %s\n", str(err) + lineno())

Expand All @@ -650,6 +716,26 @@ def lambda_handler(
' with value: ' +
str(private_ip))

if len(heritage)>0:
# pause 1 before deleting to avoid API limit
time.sleep(1)
delete_resource_record(
route53,
final_hosted_zone_id,
final_private_hostname,
final_hosted_zone_name,
'TXT',
heritage_value
)

caller_response.append('Deleted TXT record in zone id: ' +
str(final_hosted_zone_id) +
' for hosted zone ' +
str(final_private_hostname) + '.' +
str(final_hosted_zone_name) +
' with value: ' +
str(heritage_value))

# pause 1 before deleting to avoid API limit
time.sleep(1)
delete_resource_record(
Expand All @@ -669,6 +755,26 @@ def lambda_handler(
' with value: ' +
str(final_private_dns_name))

if len(heritage)>0:
# pause 1 before deleting to avoid API limit
time.sleep(1)
delete_resource_record(
route53,
reverse_lookup_zone_id,
reversed_ip_address,
'in-addr.arpa',
'TXT',
heritage_value
)

caller_response.append('Deleted PTR record in zone id: ' +
str(reverse_lookup_zone_id) +
' for hosted zone ' +
str(reversed_ip_address) +
str(private_dns_name) +
' with value: ' +
str(heritage_value))

except BaseException as err:
LOGGER.debug("%s", str(err) + lineno())

Expand Down Expand Up @@ -708,6 +814,25 @@ def lambda_handler(
' with value: ' +
str(final_private_dns_name))

if len(heritage)>0:
create_resource_record(
route53,
cname_domain_suffix_id,
TXT_RR_PREFIX + '.' + cname_host_name,
cname_domain_suffix,
'TXT',
heritage_value
)

caller_response.append('Created TXT for CNAME record in zone id: ' +
str(cname_domain_suffix_id) +
' for hosted zone ' +
str(TXT_RR_PREFIX) + '.' +
str(cname_host_name) + '.' +
str(cname_domain_suffix) +
' with value: ' +
str(heritage_value))

except BaseException as err:
LOGGER.debug("%s", str(err) + lineno())
else:
Expand All @@ -733,6 +858,25 @@ def lambda_handler(
' with value: ' +
str(final_private_dns_name))

if len(heritage)>0:
delete_resource_record(
route53,
cname_domain_suffix_id,
TXT_RR_PREFIX + '.' + cname_host_name,
cname_domain_suffix,
'TXT',
heritage_value
)

caller_response.append('Deleted TXT for CNAME record in zone id: ' +
str(cname_domain_suffix_id) +
' for hosted zone ' +
str(TXT_RR_PREFIX) + '.' +
str(cname_host_name) + '.' +
str(cname_domain_suffix) +
' with value: ' +
str(heritage_value))

except BaseException as err:
LOGGER.debug("%s", str(err) + lineno())

Expand Down
Binary file modified code/ddns-lambda.zip
Binary file not shown.
14 changes: 8 additions & 6 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@ variable "lambda_environment_variables" {
description = "Map of lambda environment variables and values"
type = map(string)
default = {
SleepTime = 60
DynamoDBName = null
TagKeyCname = "boc:dns:cname"
TagKeyZone = "boc:dns:zone"
TagKeyHostName = "boc:dns:name"
DNS_RR_TimeToLive = 60
SleepTime = 60
DynamoDBName = null
TagKeyCname = "boc:dns:cname"
TagKeyZone = "boc:dns:zone"
TagKeyHostName = "boc:dns:name"
DNS_RR_TimeToLive = 60
HeritageTXTRecordPrefix = "_txt"
HeritageIdentifier = "dynr53"
}
}
2 changes: 1 addition & 1 deletion version.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
locals {
_module_version = "0.0.22"
_module_version = "0.0.23"
}

0 comments on commit d37ecd6

Please sign in to comment.