Skip to content

Commit

Permalink
Merge pull request #4 from terraform-modules/initial
Browse files Browse the repository at this point in the history
merge into master
  • Loading branch information
badra001 committed Jan 31, 2022
2 parents 399a3dd + 5bdcad6 commit de6bc3a
Show file tree
Hide file tree
Showing 24 changed files with 2,113 additions and 103 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "aws-lambda-ddns-function"]
path = aws-lambda-ddns-function
url = https://github.com/aws-samples/aws-lambda-ddns-function
File renamed without changes.
File renamed without changes.
9 changes: 5 additions & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
repos:
- repo: https://github.com/antonbabenko/pre-commit-terraform
rev: v1.48.0
rev: v1.62.3
hooks:
# - id: terraform_validate
- id: terraform_fmt
- id: terraform_docs_replace
args: ['table']
- id: terraform_docs
args:
- --args=--config=.terraform-docs.yml
exclude: common/*.tf
exclude: version.tf
exclude: examples/
- id: terraform_tflint
args: [ "--args=--config=__GIT_WORKING_DIR__/.tflint.hcl"]
exclude: examples/
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.4.0
rev: v4.1.0
hooks:
- id: check-symlinks
- id: detect-aws-credentials
Expand Down
45 changes: 45 additions & 0 deletions .terraform-docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
formatter: markdown table

header-from: main.tf
footer-from: ""

sections:
## hide: []
show:
- data-sources
- header
- footer
- inputs
- modules
- outputs
- providers
- requirements
- resources

output:
file: README.md
mode: replace
# mode: inject
# template: |-
# <!-- BEGIN_TF_DOCS -->
# {{ .Content }}
# <!-- END_TF_DOCS -->

## output-values:
## enabled: false
## from: ""
##
## sort:
## enabled: true
## by: name
##
## settings:
## anchor: true
## color: true
## default: true
## description: false
## escape: true
## indent: 2
## required: true
## sensitive: true
## type: true
6 changes: 6 additions & 0 deletions .tflint.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,9 @@ rule "aws_instance_invalid_type" {
plugin "aws" {
enabled = true
}

# https://github.com/terraform-linters/tflint/blob/v0.33.1/docs/rules/terraform_module_pinned_source.md
rule "terraform_module_pinned_source" {
enabled = false
}

2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Versions

* v1.0.0 -- {{ yyyy-mm-dd }}
* v1.0.0 -- 2022-01-21
- initial creation

152 changes: 56 additions & 96 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,96 +1,56 @@
# aws-dynamic-route53

## About

This module will construct all the resources to allow for automated C2 DNS registration in Route53. This is largely sourced from the
AWS blog on [DNS in a Multiaccount Environment with Route53](https://aws.amazon.com/blogs/security/simplify-dns-management-in-a-multiaccount-environment-with-route-53-resolver/) . We have added to it to also do PTR registration, as well as
making it IPv6 ready.

The [code](https://github.com/aws-samples/aws-lambda-ddns-function) from that blog is linked in as a submodule under [aws-lambda-ddns-function](aws-lambda-ddns-function/).

This code is intended to be deployed per region, and will handle all of the DNS registration for EC2
instances deployed, assumign specific tags exist.

It will create:

- DynamoDB Table (inf-dynamic-route53-{region})
- IAM Roles
- Lambda
- CloudWatch Events
- CloudWatch Log

## Operation

See the the [blog](#blog) for full details on how it works. The short version is:

- Cloudwatch event on instance (starting, started, terminated)
- Run lambda
- On startup
- Get instance details (id, region, ipv4, ipv6)
- Determine zone from tag(s)
- Find zone
- Add records if found
- Log action
- Record in DDB name and details
- On terminate
- Get instance detail (id)
- search DDB table for id
- Remove records, if in table
- Log action


## Tags

A number of tags will be used to affect behavior of the DNS entries.

### Tag: Name

The `Name` tag is the primary tag that will be used to determine the DNS name to create. It is expected to be a unique FQDN. If no Name
tag is provided, the hostname portion of the name will be constructed from the IP address:

* IPv4
* ip address: A.B.C.D
* hostname: ip-A-B-C-D
* IPv6 (TBD)

The domain portion of the `Name` tag must exist within Route53 in order for any records to be created.

### Tag: boc:dns:zone

The `boc:dns:zone` tag will be used in case we need to force a specific domain name on a host, either because it cannot obtain
the proper zone (domain) from the `Name` tag, of that a custom per-instance `Name` tag cannot be created. This latter condition
occurs for systems which work from a launch template, such as EMR or EKS.

### Tag: boc:dns:alias

The `boc:dns:alias` tag is used to create an alternate DNS name (CNAME), pointed to the primary name. It is an FQDN, and the same conditions
apply as with [Name](#tag--name).

# Links

## github aws-lambda-ddns-function
* https://github.com/aws-samples/aws-lambda-ddns-function
## Blog
* https://aws.amazon.com/blogs/security/simplify-dns-management-in-a-multiaccount-environment-with-route-53-resolver/


# Repository Setup Details

* One time

```script
git submodule add https://github.com/aws-samples/aws-lambda-ddns-function aws-lambda-ddns-function
git commit -m'add submodule' aws-lambda-ddns-function
```

* After first clone

```script
git submodule update --init
```

* Pull new stuff from submoduule

```script
git submodule foreach git pull origin master
```
<!-- BEGIN_TF_DOCS -->
## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 3.66.0 |

## Providers

| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 3.66.0 |

## Modules

No modules.

## Resources

| Name | Type |
|------|------|
| [aws_cloudwatch_event_rule.ec2_rule](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_rule) | resource |
| [aws_cloudwatch_event_target.ec2_target](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_target) | resource |
| [aws_cloudwatch_log_group.log](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource |
| [aws_dynamodb_table.table](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dynamodb_table) | resource |
| [aws_iam_role.role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
| [aws_iam_role_policy_attachment.role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
| [aws_lambda_alias.lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_alias) | resource |
| [aws_lambda_function.lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function) | resource |
| [aws_lambda_permission.allow_cloudwatch](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_permission) | resource |
| [aws_arn.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/arn) | data source |
| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source |
| [aws_iam_policy.lambda_policies](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy) | data source |
| [aws_iam_policy_document.lambda_assume](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.lambda_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_account_alias"></a> [account\_alias](#input\_account\_alias) | AWS Account Alias | `string` | `""` | no |
| <a name="input_account_id"></a> [account\_id](#input\_account\_id) | AWS Account ID (default will pull from current user) | `string` | `""` | no |
| <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": "TBD",<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 |
| <a name="input_tags"></a> [tags](#input\_tags) | AWS Tags to apply to appropriate resources | `map(string)` | `{}` | no |

## Outputs

No outputs.
<!-- END_TF_DOCS -->
63 changes: 63 additions & 0 deletions cloudwatch.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
locals {
cloudwatch_name = format("/aws/lambda/%v", local.lambda_name)
cloudwatch_event_pattern = {
"source" = ["aws.ec2"]
"detail-type" = ["EC2 Instance State-change Notification"]
"detail" = {
"state" = ["running", "shutting-down", "stopped"]
}
}
}

resource "aws_cloudwatch_log_group" "log" {
count = var.create ? 1 : 0
name = local.cloudwatch_name
# kms_key_id = var.kms_key_arn
retention_in_days = lookup(local._defaults["cloudwatch"], "retention_in_days", 7)

tags = merge(
local.base_tags,
var.tags,
map("Name", local.name),
)
}

# aws events put-targets --rule ec2_lambda_ddns_rule --targets Id=id123456789012,Arn=<enter-your-lambda-function-arn-here>

resource "aws_cloudwatch_event_rule" "ec2_rule" {
count = var.create ? 1 : 0
name = local.name
description = "Capture EC2 Events to hande dynamic Route53 registration"
event_pattern = jsonencode(local.cloudwatch_event_pattern)

tags = merge(
local.base_tags,
var.tags,
map("Name", local.name),
)
}

resource "aws_cloudwatch_event_target" "ec2_target" {
count = var.create ? 1 : 0
# target_id = local.name
target_id = var.create ? aws_lambda_function.lambda[0].function_name : null
arn = var.create ? aws_lambda_function.lambda[0].arn : null
rule = var.create ? aws_cloudwatch_event_rule.ec2_rule[0].name : null
# propagate_tags = true

# tags = merge(
# local.base_tags,
# var.tags,
# map("Name", local.name),
# )
}

resource "aws_lambda_permission" "allow_cloudwatch" {
count = var.create ? 1 : 0
statement_id = "AllowExecutionFromCloudWatch"
action = "lambda:InvokeFunction"
function_name = var.create ? aws_lambda_function.lambda[0].function_name : null
principal = "events.amazonaws.com"
source_arn = var.create ? aws_cloudwatch_event_rule.ec2_rule[0].arn : null
# qualifier = var.create ? aws_lambda_alias.lambda[0].name : null
}
Loading

0 comments on commit de6bc3a

Please sign in to comment.