Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Init module MVP #1

Merged
merged 3 commits into from
Nov 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ crash.*.log
# to change depending on the environment.
*.tfvars
*.tfvars.json

*.zip
# Ignore override files as they are usually used to override resources locally and so
# are not checked in
override.tf
Expand Down
113 changes: 92 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,73 @@ Route53Flashpoint is a Terraform module designed to dynamically manage ephemeral

## Features

- **Automated DNS Record Management**: Create, update, and delete AWS Route53 DNS records across multiple AWS accounts.
- **Expiration Tracking**: Utilize DynamoDB for tracking record expirations and automated deletion.
- **Automated DNS Record Management**: Create, update, and delete AWS Route53 DNS records.

- **Expiration Tracking**: Utilize DynamoDB for tracking record expiration and automated deletion.

- **API Endpoints**: Securely add new DNS records and generate reports of active records through API Gateway.

- **Event-Driven Architecture**: Leverage AWS Lambda and EventBridge for efficient, scalable operations.

- **Security and Scalability**: Built with security and scalability in mind, ensuring robust and efficient DNS management.

## Usage

### Terraform

```hcl

module "route53_flashpoint" {
source = "path/to/route53flashpoint"
source = "path/to/route53flashpoint"

// Define necessary variables
aws_region = "us-east-1"
hosted_zone_id = "ABCDEF1234"
expired_records_check_rate_expression = "rate(1 hour)"
common_tags = {
Terraform = "true",
}

```

### API

Create a new DNS record with expiration date:

```
curl -X POST https://{{API_ID}}.execute-api.{{REGION}}.amazonaws.com/v1/route53dnsrecord \
-H "Authorization: AWS4-HMAC-SHA256 Credential=YOUR_ACCESS_KEY/20231126/region/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=YOUR_SIGNATURE" \
-H "x-amz-date: 20231126T000000Z" \
-H "Content-Type: application/json" \
-d '{
"name": "temp_domain.example.com",
"type": "A",
"value": "192.0.2.44",
"ttl": 600,
"delete_after": "2023-11-28T16:43:59Z"
}'

```

Check for expired records and delete if found:

```
curl -X DELETE https://{{API_ID}}.execute-api.{{REGION}}.amazonaws.com/v1/route53dnsrecord \
-H "Authorization: AWS4-HMAC-SHA256 Credential=YOUR_ACCESS_KEY/20231126/region/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=YOUR_SIGNATURE" \
-H "x-amz-date: 20231126T000000Z" \
-H "Content-Type: application/json"
```

Get a report on domains and expiration:

```
curl -X POST https://{{API_ID}}.execute-api.{{REGION}}.amazonaws.com/v1/reports \
-H "Authorization: AWS4-HMAC-SHA256 Credential=YOUR_ACCESS_KEY/20231126/region/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=YOUR_SIGNATURE" \
-H "x-amz-date: 20231126T000000Z" \
-H "Content-Type: application/json"
```

## Prerequisites

- AWS Account with necessary permissions.
- Terraform installed (version 0.14 or higher).

## Terraform Version
Expand All @@ -37,28 +85,51 @@ module "route53_flashpoint" {

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
// Define your input variables here
| Name | Description | Type | Default | Required |
| --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | ----------- | --------------------- | :------: |
| `aws_region` | AWS region to deploy resources | string | "us-east-1" | no |
| `expired_records_check_rate_expression` | Rate expression for checking expired records | string | "rate(1 hour)" | no |
| `hosted_zone_id` | The ID of the hosted zone in which to create the record. Must be a 14-character string containing only uppercase letters and digits. | string | - | yes |
| `common_tags` | Common tags to apply to all resources | map(string) | {"Terraform": "true"} | no |

## Outputs

| Name | Description |
|------|-------------|
// Define your outputs here
| Name | Description |
| --------------------- | -------------------------------------------- |
| `dns_record_endpoint` | API Gateway endpoint for DNS record resource |
| `reports_endpoint` | API Gateway endpoint for reports resource |

## Resources Created

- AWS Lambda Functions for DNS management.
- API Gateway for secure API endpoints.
- DynamoDB table for record tracking.
- IAM roles and policies for secure operation.

## Security

- Ensure API keys for API Gateway are securely managed.
- Review IAM roles and policies for least privilege access.

| Terraform Resources |
| ------------------------------------------------------------ |
| data.archive_file.create_record_lambda_zip |
| data.archive_file.delete_expired_records_lambda_zip |
| data.archive_file.records_report_lambda_zip |
| aws_api_gateway_deployment.route53_api_deployment |
| aws_api_gateway_integration.create_record_lambda_integration |
| aws_api_gateway_integration.delete_record_lambda_integration |
| aws_api_gateway_integration.reports_lambda_integration |
| aws_api_gateway_method.create_dns_record_post |
| aws_api_gateway_method.delete_dns_record_delete |
| aws_api_gateway_method.reports_post |
| aws_api_gateway_method_response.create_response_200 |
| aws_api_gateway_method_response.delete_response_200 |
| aws_api_gateway_method_response.reports_response_200 |
| aws_api_gateway_resource.dns_record_resource |
| aws_api_gateway_resource.reports_resource |
| aws_api_gateway_rest_api.route53_api |
| aws_cloudwatch_event_rule.check_expired_records |
| aws_cloudwatch_event_target.invoke_lambda |
| aws_dynamodb_table.dns_records |
| aws_iam_role.api_gateway_lambda_role |
| aws_iam_role.lambda_execution_role |
| aws_iam_role_policy.api_gateway_lambda_policy |
| aws_iam_role_policy.lambda_policy |
| aws_lambda_function.create_record_lambda |
| aws_lambda_function.delete_expired_records_lambda |
| aws_lambda_function.records_report_lambda |
| aws_lambda_permission.allow_eventbridge |

## Contributions

Expand Down
135 changes: 135 additions & 0 deletions api_gateway_main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
resource "aws_api_gateway_rest_api" "route53_api" {
name = "Route53FlashpointAPI"
description = "API for Route53Flashpoint DNS Management"
tags = var.common_tags
}

resource "aws_api_gateway_deployment" "route53_api_deployment" {
depends_on = [
aws_api_gateway_integration.create_record_lambda_integration,
aws_api_gateway_integration.delete_record_lambda_integration,
aws_api_gateway_integration.reports_lambda_integration,
]

rest_api_id = aws_api_gateway_rest_api.route53_api.id
stage_name = "v1"
#Forces a redeployment of the API Gateway when the Lambda functions are updated
triggers = {
redeployment = sha1(join("", tolist([
aws_api_gateway_integration.create_record_lambda_integration.id,
aws_api_gateway_integration.delete_record_lambda_integration.id,
aws_api_gateway_integration.reports_lambda_integration.id,
var.force_deploy
])))
}
}

resource "aws_api_gateway_resource" "dns_record_resource" {
rest_api_id = aws_api_gateway_rest_api.route53_api.id
parent_id = aws_api_gateway_rest_api.route53_api.root_resource_id
path_part = "route53dnsrecord"
}

resource "aws_api_gateway_resource" "reports_resource" {
rest_api_id = aws_api_gateway_rest_api.route53_api.id
parent_id = aws_api_gateway_rest_api.route53_api.root_resource_id
path_part = "reports"
}

##Create Route53 Records Endpoint

resource "aws_api_gateway_method" "create_dns_record_post" {
rest_api_id = aws_api_gateway_rest_api.route53_api.id
resource_id = aws_api_gateway_resource.dns_record_resource.id
http_method = "POST"
authorization = "AWS_IAM"
}

resource "aws_api_gateway_integration" "create_record_lambda_integration" {
rest_api_id = aws_api_gateway_rest_api.route53_api.id
resource_id = aws_api_gateway_resource.dns_record_resource.id
http_method = aws_api_gateway_method.create_dns_record_post.http_method

integration_http_method = "POST"
type = "AWS_PROXY"
uri = aws_lambda_function.create_record_lambda.invoke_arn

credentials = aws_iam_role.api_gateway_lambda_role.arn
}

resource "aws_api_gateway_method_response" "create_response_200" {
rest_api_id = aws_api_gateway_rest_api.route53_api.id
resource_id = aws_api_gateway_resource.dns_record_resource.id
http_method = aws_api_gateway_method.create_dns_record_post.http_method
status_code = "200"

response_models = {
"application/json" = "Empty"
}
}


##Delete Route53 Records Endpoint

resource "aws_api_gateway_method" "delete_dns_record_delete" {
rest_api_id = aws_api_gateway_rest_api.route53_api.id
resource_id = aws_api_gateway_resource.dns_record_resource.id
http_method = "DELETE"
authorization = "AWS_IAM"
}

resource "aws_api_gateway_integration" "delete_record_lambda_integration" {
rest_api_id = aws_api_gateway_rest_api.route53_api.id
resource_id = aws_api_gateway_resource.dns_record_resource.id
http_method = aws_api_gateway_method.delete_dns_record_delete.http_method

integration_http_method = "POST"
type = "AWS_PROXY"
uri = aws_lambda_function.delete_expired_records_lambda.invoke_arn

credentials = aws_iam_role.api_gateway_lambda_role.arn
}

resource "aws_api_gateway_method_response" "delete_response_200" {
rest_api_id = aws_api_gateway_rest_api.route53_api.id
resource_id = aws_api_gateway_resource.dns_record_resource.id
http_method = aws_api_gateway_method.delete_dns_record_delete.http_method
status_code = "200"

response_models = {
"application/json" = "Empty"
}
}


##Reports Endpoint

resource "aws_api_gateway_method" "reports_post" {
rest_api_id = aws_api_gateway_rest_api.route53_api.id
resource_id = aws_api_gateway_resource.reports_resource.id
http_method = "POST"
authorization = "AWS_IAM"
}

resource "aws_api_gateway_integration" "reports_lambda_integration" {
rest_api_id = aws_api_gateway_rest_api.route53_api.id
resource_id = aws_api_gateway_resource.reports_resource.id
http_method = aws_api_gateway_method.reports_post.http_method

integration_http_method = "POST"
type = "AWS_PROXY"
uri = aws_lambda_function.records_report_lambda.invoke_arn

credentials = aws_iam_role.api_gateway_lambda_role.arn
}

resource "aws_api_gateway_method_response" "reports_response_200" {
rest_api_id = aws_api_gateway_rest_api.route53_api.id
resource_id = aws_api_gateway_resource.reports_resource.id
http_method = aws_api_gateway_method.reports_post.http_method
status_code = "200"

response_models = {
"application/json" = "Empty"
}
}
34 changes: 34 additions & 0 deletions api_gateway_role.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
resource "aws_iam_role" "api_gateway_lambda_role" {
name = "api_gateway_lambda_role"
tags = var.common_tags
assume_role_policy = jsonencode({
Version = "2012-10-17",
Statement = [
{
Action = "sts:AssumeRole",
Effect = "Allow",
Principal = {
Service = "apigateway.amazonaws.com"
},
},
],
})
}

resource "aws_iam_role_policy" "api_gateway_lambda_policy" {
name = "api_gateway_lambda_policy"
role = aws_iam_role.api_gateway_lambda_role.id

policy = jsonencode({
Version = "2012-10-17",
Statement = [
{
Action = [
"lambda:InvokeFunction"
],
Effect = "Allow",
Resource = [aws_lambda_function.create_record_lambda.arn, aws_lambda_function.delete_expired_records_lambda.arn, aws_lambda_function.records_report_lambda.arn]
},
],
})
}
Loading