Skip to content

Commit

Permalink
Merge pull request #1 from K8sKween/init-001-vm
Browse files Browse the repository at this point in the history
Init module MVP
  • Loading branch information
K8sKween authored Nov 26, 2023
2 parents 0794bad + f66c5f7 commit c000e16
Show file tree
Hide file tree
Showing 13 changed files with 697 additions and 22 deletions.
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

0 comments on commit c000e16

Please sign in to comment.