From a2adb6293dc4fbb3f18f5e1b1c68a4c2a7df5f7d Mon Sep 17 00:00:00 2001 From: badra001 Date: Sat, 29 Apr 2023 16:52:03 -0400 Subject: [PATCH] upgrade docs --- README.md | 73 +++++-------------- USAGE.md | 204 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ main.tf | 77 +++++---------------- 3 files changed, 240 insertions(+), 114 deletions(-) create mode 100644 USAGE.md diff --git a/README.md b/README.md index f9bc045..6262002 100644 --- a/README.md +++ b/README.md @@ -1,52 +1,9 @@ # About :: aws-dynamic-route53 -This module sets up all the things one needs to enable the dynamic creation and removal of Route53 records. It requires -the VPC to have the following: - -* DHCP option for DNS enabled -* DHCP option for DNS domain name -* Route53 zone for the DNS domain name in the DHCP option -* Route53 zone for all of the PTR subnets for the VPC (x.y.z.in-addr.arpa) - -This module creates these resources: - -* DyanmoDB Table for tracking the instances -* CloudWatch Log -* Lambda Function -* IAM role and policy for Lambda -* SNS topic (if `enable_sns=true`) - -# Deployment - -This should be deployed per account in each region where the automated Route53 is desired. DNS entries are created on EC2 instance -startup (when running) and removed on shutdown or termination. The instance IDs are tracked in the DynamoDB Table. Here's how -DNS entries are handled: - -1. If the `Name` tags exists, it will take the host part of the name (up to the first dot) and create an A and PTR records for the -hostname with the DHCP options domain. -1. If there is no `Name` tag, it will use the _IP Address Format_ (ip-x-x-x-x where the private IP is x.x.x.) with the domain from the DHCP options. -1. If the tag `boc:dns:name` exists on the EC2 instance, it will use this name to enter into DNS. This assumes the domain part of the name exists and is -associated to the VPC. Using this tag, you can create a completely different name from the `Name` tag. -1. If the tag `boc:dns:zone` exits on the EC2 instance, it will take the hostname part of the `Name` tag, and add the zone, and use this name -in DNS. This assumes the domain part of the name exists and is associated to the VPC. If there is no `Name` tag, it will use the _IP Address Format_ (ip-x-x-x-x where the private IP is x.x.x.). -Using this tag, you can create the host in a completely different zone from that of the DHCP options. -1. If the tag `boc:dns:cname` exists, that name will be entered in DNS in the zone indicated by the tag as a CNAME to the main name (as determined above), -assuming the domain part of the name exists and is associated to the VPC. - -We also add what is called a _heritage_ TXT record, associated with the instance. It looks like this: - -```script -"heritage=dynr53,dynr53/version=0.2.1,dynr53/account_id=252999262699,dynr53/region=us-gov-west-1,dynr53/instance_id=i-0e836a68e01f8b1c3,dynr53/create_time=1648143761" -``` - -This is createed as a TXT record on - -* the hostname, however it is determined from the above rules -* on the associated PTR resource record (RR), that is, `x.x.x.x.in-addr.arpa IN TXT ...` -* and with a default prefix of \_txt with the CNAME if using the `boc:dns:cname` tag, because, you cannot have more than one RR when using a CNAME +This module sets up all the things one needs to enable the dynamic creation and removal of Route53 records. -If SNS is enabled, any errors will cause a message to be published to the SNS topic. +We have moved the details of using the flags on instances into [USAGE](USAGE.md). # Usage @@ -68,22 +25,26 @@ module "dynamic-route53" { The folowing defualts are applied to the Lambda function. There is ordinarily no need to change these. -```hcl + ```hcl { - DebugLevel = "INFO" - SleepTime = 60 - DynamoDBName = null - TagKeyCname = "boc:dns:cname" - TagKeyZone = "boc:dns:zone" - TagKeyHostName = "boc:dns:name" + DebugLogLevel = "INFO" DNS_RR_TimeToLive = 60 + DynamoDBName = null + HeritageIdentifier = "dynr53" + HeritageTXTRecordPrefix = "_txt" MaxApiRetry = 10 - SnsTopicArn = "" + SleepTime = 60 SnsEnable = false - HeritageTXTRecordPrefix = "_txt" - HeritageIdentifier = "dynr53" + SnsTopicArn = "" + RemoteRoleArnFormat = "arn:%s:iam::%s:role/r-inf-dynamic-route53-actions" + EMRTagPrefix = "aws" + TagKeyCname = "boc:dns:cname" + TagKeyHostName = "boc:dns:name" + TagKeyZone = "boc:dns:zone" + TagKeyPtrname = "boc:dns:ptrname" + TagKeyFlags = "boc:dns:flags" } -``` + ``` ## Requirements diff --git a/USAGE.md b/USAGE.md new file mode 100644 index 0000000..fa244e6 --- /dev/null +++ b/USAGE.md @@ -0,0 +1,204 @@ +# About :: aws-dynamic-route53 + +This describes the new capabilities of the 2.0 version of the Dyanmic Route53 module. +It sets up all the things one needs to enable the dynamic creation and removal of Route53 records. It requires the VPC to have the following: + +* DHCP option for DNS enabled +* DHCP option for DNS domain name +* Route53 zone for the DNS domain name in the DHCP option +* Route53 zone for all of the PTR subnets for the VPC (x.y.z.in-addr.arpa) +* Route53 zone assocations for the VPC to all associated zones + +This module creates these resources: + +* DyanmoDB Table for tracking the instances +* CloudWatch Log +* Lambda Function +* IAM role and policy for Lambda +* SNS topic (if `enable_sns=true`) + +# Deployment + +This should be deployed per account in each region where the automated Route53 is desired. + +# Usage + +DNS entries are created **ONLY** on +EC2 instance start (when running) and removed on stop or terminate. If you change the tags which affect the naming, you must _stop_ and _start_ +the instance. Do not reboot, because that is not an EC2 action. You can stop and start from the CLI like this (sleep 60 is to give the instance +time to be properly shut down). + +```script +aws --profile PROFILE ec2 stop-instances --instance-ids i-xxxxxxxx +sleep 60 +aws --profile PROFILE ec2 start-instances --instance-ids i-xxxxxxxx +``` +The instance IDs and DNS records created are tracked in a DynamoDB Table. + +## Tags + +Here are the tags which affect the DNS name: + +### `Name` + +This should be a fully qualified valid DNS name. The domain (components after the first dot, typically) must exist and must be associated +the VPC where the instance resides. + +Do not use invalid DNS characters (no underscores, no spaces, no special other than dash). Legal characters: a-z 0-9 dash (-). + +It is possible, but not recommended, where this can a short non-FQDN name, that is, just a hostname. In this case, the DHCP options domain will be used, +if it exists, or a different zone will be used based on the `boc:dns:zone` flag. + +If the `Name` tag is missing, the IP address wil be used to construct the name in the form of `ip-X-X-X-X`. + +Examples: +* Name = cio-001-web.dev.csp1.census.gov + yields DNS of: cio-001-web.dev.csp1.census.gov +* Name = myhost + yields DNS of: myhost.{dhcp_domain_name} (if such a zone exists, or what was specified in `boc:dns:zone`) +* Name = + yields DNS of: ip-X-X-X-X.{dhcp_domain_name} + +### `boc:dns:name` + +It is possible to use a completely different name in DNS from the Name tag, if desired. Like the `Name` tag, this should be an FQDN, but a short +domain-less name will use the default DHCP options domain or the `boc:dns:zone` tag. + +Examples: +* boc:dns:name = myhost.qa.csp1.census.gov + yields DNS of: myhost.qa.csp1.census.gov, +* boc:dns:name = somotherhost + yields DNS of: someotherhost.{dhcp_domain_name} (if such a zone exists, or what was specified in `boc:dns:zone`) + +### `boc:dns:zone` + +If you want to use a zone other than what is defined in the DHCP options, or that zone in the DHCP options is not availble (as in the case +of `compute.csp1.census.gov`, which exist in BIND on a cloud DNS server), you can use the `boc:dns:zone` option. Setting this value +will cause the domains for foward entries (A), and reverse (PTR) to use the short hostname and the provided domain from `boc:dns:zone`. + +Examples: +* boc:dns:zone = uat.csp1.census.gov + yields DNS of: {hostname}.uat.csp1.census.gov, using the hostname part from the `Name` tag following the rules above for the A and PTR recors + +### `boc:dns:cname` + +If you need to set a second name for an instance, you can use an Alias/CNAME. This is another entry created in Route53, which points at the main +host FQDN. A CNAME cannot point to a CNAME. This may be an FQDN or a shortname. If an FQDN and the zone exist in Route53, it will add it. +If a shortname, it will append the default DHCP options domain or the value from the `boc:dns:zone` tag. + +Examples: +* Name = cio-014-app.stage.csp1.census.gov +* boc:dns:cname = myothername.stage.csp1.census.gov + yields DNS of: myothername.stage.csp1.census.gov pointing to cio-014-app.stage.csp1.census.gov + +### `boc:dns:ptrname` + +Sometimes, we need to set a different name from the `Name` tag on the PTR record. This is the record that lets you lookup an IP and get a name, by +taking the IP and reversing the dotted quad and adding `.in-addr.arpa`. An IP of 10.193.14.78 would have a PTR name of +78.14.193.10.in-addr.arpa. Normally, you set the value of this to the same name as the registered hostname, `Name` or `boc:dns:name`, as many security +checks are performed to make sure the host resolves _"forward and backward"_. + +However, in the case of a Windows host, we cannot use the `Name` or `boc:dns:name` tag, because the Active Directory (AD) domain name is not capable +of running on Route53. Windows adds hosts dynamically on registration to the domain to the Forest or child AD domain. The windows server cannot +make the corresponding PTR entry, because Route53 does not speak the DDNS protocol. + +We can solve this using the `boc:dns:ptrname` tag and using one of the _flag_ settings. For a Windows host, you will want to set +the `boc:dns:ptrname` to the Windows FQDN. For example, `cio003web.ead.census.gov`. The domain of this host is not checked to be present in the +VPC, because we are not writing to that omain. + +YOu will also want to use the `boc:dns:flags=noforward` with this option, as registering a differname in some zone defined in Route53 causes +confusion. As AD will update the forward name, you do not need Route53 to set the forward name. + +### `boc:dns:flags` + +We do need to control the settings a bit more than we do with the tags above. Fortunately, we have some flags available. This tag `boc:dns:flags` may +be set to one or more (as a CSV list, no spaces) of the following values: + +* noforward + This does **NOT** create the A (and AAAA, when IPv6 is available) and associated heritage record (see [below](#additional-heritage-txt-records)) in + the zone (DHCP options or from `boc:dns:zone`) or the name from `boc:dns:name`. This is most often used with the `boc:dns:ptrname` and Windows hosts. + +* noptrname + This does **NOT** create the PTR and associated heritage record (see [below](#additional-heritage-txt-records)) in the + PTR zone (x.x.x.in-addr.arpa). We are not sure why you would do this. + +* nocname + This does **NOT** create the CNAME, if defined with `boc:dns:cname` and associated heritage record (see [below](#additional-heritage-txt-records)) in the + the zone (DHCP options or from `boc:dns:zone`) or the name from `boc:dns:name`. It is easier to simply not set the tag `boc:dns:cname`, but there could be + a reason somewhere out there. + +* noheritage + This will not create any of the heritage records, which are TXT records in the same zone as their respective record. You can look this name up with + a `txt` query, like: + + ```script + # A record + host -t txt myhost.dev.csp1.census.gov + # PTR record + host -t txt 14.107.193.10.in-addr.arpa + # CNAME record + host -t txt _txt.myalias.services.csp1.census.gov + ``` + + Note that for aliases (CNAMES), we can not add a TXT record because a CNAME references the defined name for EVERY record type. Looking up the TXT + on a CNAME is the same as looking up the TXT on the pointed-to name. + +## Additional Heritage TXT records + +We also add what is called a _heritage_ TXT record, associated with the instance. It looks like this: + +```script +"heritage=dynr53,dynr53/version=2.0.1,dynr53/account_id=252999262699,dynr53/region=us-gov-west-1,dynr53/instance_id=i-0e836a68e01f8b1c3,dynr53/create_time=1648143761" +``` + +This is createed as a TXT record on + +* the hostname, however it is determined from the above rules +* on the associated PTR resource record (RR), that is, `x.x.x.x.in-addr.arpa IN TXT ...` +* and with a default prefix of `_txt` with the CNAME if using the `boc:dns:cname` tag, because, you cannot have more than one RR when using a CNAME + +## Additional Features + +This release also includes _EMR detection_. What that means if an instance is created as part of an EMR cluster, a special tag will be added +by EMR to indicate this. That tag is + +`aws:elasticmapreduce:job-flow-id = j-xxxxxxxx` + +where the vallue of this is the EMR cluster id. + +A second tag is added if the instance happens to be the master node: + +`aws:elasticmapreduce:group-instance-role = MASTER` + +This is ONLY on the master node. + +EMR does not allow you to tag individual instances. You can create a tag for EMR, but it gets added to every instance in the cluster. Since we can detect +an EMR clsuter, and specifically the master node, we can couple that with the `boc:dns:cname` tag to create an alias to the master node, to simplify use. + +It is **imperitive** that the cluster master alias you create be unique, as if some other name already exists in the zone, the creation will fail. + +Here is how you can use this capability: + +1. create a tag `boc:dns:cname=mynewcluster.master` + - This will create a CNAME mynewclsuter.master.{dhpc_domain_name} to the FQDN of the master instance +1. launch the cluster + - non-master noes will have only the _job-flow-id_ tag + - the master node will have the _MASTER_ role +1. if the instance is an EMR cluster, and the instance is labelled as MASTER, and the CNAME tag is defined, the CNAME will be set. It may fail + if it already exist. + + +# Notes + +To register a name in a zone, the VPC where the instance runs must be associated to the zone, whever the zone is created, whether it is the +same account as the instance, or some other account. + +If the zone is created in another account, the Lambda will execute an assume role `r-inf-dynamic-route53-actions` to gain the permissions to create, +modify and delete the records in the zone. This, and a Terraform-supporting role, is created in the `aws-vpc-setup` submoduiels: + +* terraform-modules/aws-vpc-setup/route53-zone-association/lambda-role +* terraform-modules/aws-vpc-setup/route53-zone-association/terraform-role + +and are instantiated with a `dynroute53-role.tf` and `terraform-role.tf` (to be wrapped up into an INF script soon). + +These must be created in the target account if the zone is in a different account. diff --git a/main.tf b/main.tf index a866d27..86690b9 100644 --- a/main.tf +++ b/main.tf @@ -1,53 +1,10 @@ /* * # About :: aws-dynamic-route53 +* +* This module sets up all the things one needs to enable the dynamic creation and removal of Route53 records. * -* This module sets up all the things one needs to enable the dynamic creation and removal of Route53 records. It requires -* the VPC to have the following: -* -* * DHCP option for DNS enabled -* * DHCP option for DNS domain name -* * Route53 zone for the DNS domain name in the DHCP option -* * Route53 zone for all of the PTR subnets for the VPC (x.y.z.in-addr.arpa) -* -* This module creates these resources: -* -* * DyanmoDB Table for tracking the instances -* * CloudWatch Log -* * Lambda Function -* * IAM role and policy for Lambda -* * SNS topic (if `enable_sns=true`) -* -* # Deployment -* -* This should be deployed per account in each region where the automated Route53 is desired. DNS entries are created on EC2 instance -* startup (when running) and removed on shutdown or termination. The instance IDs are tracked in the DynamoDB Table. Here's how -* DNS entries are handled: -* -* 1. If the `Name` tags exists, it will take the host part of the name (up to the first dot) and create an A and PTR records for the -* hostname with the DHCP options domain. -* 1. If there is no `Name` tag, it will use the _IP Address Format_ (ip-x-x-x-x where the private IP is x.x.x.) with the domain from the DHCP options. -* 1. If the tag `boc:dns:name` exists on the EC2 instance, it will use this name to enter into DNS. This assumes the domain part of the name exists and is -* associated to the VPC. Using this tag, you can create a completely different name from the `Name` tag. -* 1. If the tag `boc:dns:zone` exits on the EC2 instance, it will take the hostname part of the `Name` tag, and add the zone, and use this name -* in DNS. This assumes the domain part of the name exists and is associated to the VPC. If there is no `Name` tag, it will use the _IP Address Format_ (ip-x-x-x-x where the private IP is x.x.x.). -* Using this tag, you can create the host in a completely different zone from that of the DHCP options. -* 1. If the tag `boc:dns:cname` exists, that name will be entered in DNS in the zone indicated by the tag as a CNAME to the main name (as determined above), -* assuming the domain part of the name exists and is associated to the VPC. -* -* We also add what is called a _heritage_ TXT record, associated with the instance. It looks like this: -* -* ```script -* "heritage=dynr53,dynr53/version=0.2.1,dynr53/account_id=252999262699,dynr53/region=us-gov-west-1,dynr53/instance_id=i-0e836a68e01f8b1c3,dynr53/create_time=1648143761" -* ``` -* -* This is createed as a TXT record on -* -* * the hostname, however it is determined from the above rules -* * on the associated PTR resource record (RR), that is, `x.x.x.x.in-addr.arpa IN TXT ...` -* * and with a default prefix of _txt with the CNAME if using the `boc:dns:cname` tag, because, you cannot have more than one RR when using a CNAME -* -* If SNS is enabled, any errors will cause a message to be published to the SNS topic. -* +* We have moved the details of using the flags on instances into [USAGE](USAGE.md). +* * # Usage * * This is a simmple call. With no arguments, it will setup everything besides the SNS topic. @@ -68,20 +25,24 @@ * The folowing defualts are applied to the Lambda function. There is ordinarily no need to change * these. * -* ```hcl +* ```hcl * { -* DebugLevel = "INFO" -* SleepTime = 60 -* DynamoDBName = null -* TagKeyCname = "boc:dns:cname" -* TagKeyZone = "boc:dns:zone" -* TagKeyHostName = "boc:dns:name" +* DebugLogLevel = "INFO" * DNS_RR_TimeToLive = 60 +* DynamoDBName = null +* HeritageIdentifier = "dynr53" +* HeritageTXTRecordPrefix = "_txt" * MaxApiRetry = 10 -* SnsTopicArn = "" +* SleepTime = 60 * SnsEnable = false -* HeritageTXTRecordPrefix = "_txt" -* HeritageIdentifier = "dynr53" +* SnsTopicArn = "" +* RemoteRoleArnFormat = "arn:%s:iam::%s:role/r-inf-dynamic-route53-actions" +* EMRTagPrefix = "aws" +* TagKeyCname = "boc:dns:cname" +* TagKeyHostName = "boc:dns:name" +* TagKeyZone = "boc:dns:zone" +* TagKeyPtrname = "boc:dns:ptrname" +* TagKeyFlags = "boc:dns:flags" * } -* ``` +* ``` */