diff --git a/.gitignore b/.gitignore index 9b8a46e..30f86b0 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/README.md b/README.md index 8663409..7fecf43 100644 --- a/README.md +++ b/README.md @@ -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 @@ -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 diff --git a/api_gateway_main.tf b/api_gateway_main.tf new file mode 100644 index 0000000..ab5b3ac --- /dev/null +++ b/api_gateway_main.tf @@ -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" + } +} \ No newline at end of file diff --git a/api_gateway_role.tf b/api_gateway_role.tf new file mode 100644 index 0000000..75e32d8 --- /dev/null +++ b/api_gateway_role.tf @@ -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] + }, + ], + }) +} diff --git a/create_record.py b/create_record.py new file mode 100644 index 0000000..51c2c1e --- /dev/null +++ b/create_record.py @@ -0,0 +1,83 @@ +import boto3 +import json +from botocore.exceptions import ClientError +import os +import datetime + +def lambda_handler(event, context): + try: + # Extracting record details from the event + record_data = json.loads(event['body']) + record_name = record_data['name'] + record_type = record_data['type'] + record_value = record_data['value'] + delete_after = record_data['delete_after'] + record_ttl = record_data.get('ttl', 300) # Default TTL + + # Initialize the Route 53 client + route53 = boto3.client('route53') + dynamodb = boto3.resource('dynamodb') + # Replace with your hosted zone ID + + hosted_zone_id = os.environ.get('HOSTED_ZONE_ID') + if not hosted_zone_id: + raise ValueError('HOSTED_ZONE_ID environment variable is not set') + tablename = os.environ.get('DYNAMODB_TABLE') + if not tablename: + raise ValueError('DYNAMODB_TABLE environment variable is not set') + + # Create the DNS record + response = route53.change_resource_record_sets( + HostedZoneId=hosted_zone_id, + ChangeBatch={ + 'Changes': [{ + 'Action': 'UPSERT', + 'ResourceRecordSet': { + 'Name': record_name, + 'Type': record_type, + 'TTL': record_ttl, + 'ResourceRecords': [{'Value': record_value}] + } + }] + } + ) + + # Create the DynamoDB record + # Get a reference to the DynamoDB table + table = dynamodb.Table(tablename) + + # Add a new item to the table + response = table.put_item( + Item={ + 'RecordName': record_name, + 'RecordType': record_type, + 'ttl': record_ttl, + 'value': record_value, + 'delete_after': delete_after + } + ) + + return { + 'statusCode': 200, + 'body': json.dumps({'message': 'Record created/updated successfully', 'response': response}, cls=DateTimeEncoder) + } + + except ClientError as e: + return { + 'statusCode': 500, + 'body': json.dumps({'error': str(e)}) + } + except Exception as e: + print(f"Unexpected error: {str(e)}") + return { + 'statusCode': 500, + 'body': json.dumps({'error': 'An unexpected error occurred'}) + } + + +class DateTimeEncoder(json.JSONEncoder): + def default(self, o): + if isinstance(o, datetime.datetime): + return o.isoformat() + + return super().default(o) \ No newline at end of file diff --git a/delete_expired.py b/delete_expired.py new file mode 100644 index 0000000..bea8847 --- /dev/null +++ b/delete_expired.py @@ -0,0 +1,64 @@ +import boto3 +import json +import os +from datetime import datetime +from botocore.exceptions import ClientError + +def lambda_handler(event, context): + dynamodb = boto3.resource('dynamodb') + route53 = boto3.client('route53') + + + hosted_zone_id = os.environ.get('HOSTED_ZONE_ID') + if not hosted_zone_id: + raise ValueError('HOSTED_ZONE_ID environment variable is not set') + tablename = os.environ.get('DYNAMODB_TABLE') + if not tablename: + raise ValueError('DYNAMODB_TABLE environment variable is not set') + + # Current date for checking expiration + current_date = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ') + # Get a reference to the DynamoDB table + table = dynamodb.Table(tablename) + try: + # Scanning DynamoDB for expired records + expired_records = table.scan( + FilterExpression='delete_after <= :today', + ExpressionAttributeValues={':today': current_date} + )['Items'] + print(expired_records) + for record in expired_records: + try: + # Delete the record from Route 53 + response = route53.change_resource_record_sets( + HostedZoneId=hosted_zone_id, + ChangeBatch={ + 'Changes': [{ + 'Action': 'DELETE', + 'ResourceRecordSet': { + 'Name': record['RecordName'], + 'Type': record['RecordType'], + 'TTL': int(record['ttl']), + 'ResourceRecords': [{'Value': record['value']}] + } + }] + } + ) + print(f"Deleted record: {record['RecordName']}") + + # Optionally, delete the record from DynamoDB + table.delete_item(Key={'RecordName': record['RecordName'], 'RecordType': record['RecordType']}) + + except ClientError as e: + print(f"Error deleting record: {record['RecordName']}, Error: {str(e)}") + + return { + 'statusCode': 200, + 'body': json.dumps({'message': f'Processed {len(expired_records)} expired records'}) + } + + except ClientError as e: + return { + 'statusCode': 500, + 'body': json.dumps({'error': str(e)}) + } diff --git a/dynamodb_main.tf b/dynamodb_main.tf new file mode 100644 index 0000000..2a4e950 --- /dev/null +++ b/dynamodb_main.tf @@ -0,0 +1,29 @@ +resource "aws_dynamodb_table" "dns_records" { + name = "Route53FlashpointDNSRecords" + billing_mode = "PAY_PER_REQUEST" + hash_key = "RecordName" + range_key = "RecordType" + tags = var.common_tags + attribute { + name = "RecordName" + type = "S" + } + + attribute { + name = "RecordType" + type = "S" + } + + attribute { + name = "delete_after" + type = "S" + } + + // Define the Global Secondary Index + global_secondary_index { + name = "DeleteAfterIndex" + hash_key = "delete_after" + projection_type = "ALL" // or "KEYS_ONLY" or "INCLUDE" + + } +} \ No newline at end of file diff --git a/eventbridge_main.tf b/eventbridge_main.tf new file mode 100644 index 0000000..2f93f87 --- /dev/null +++ b/eventbridge_main.tf @@ -0,0 +1,22 @@ + + +resource "aws_cloudwatch_event_rule" "check_expired_records" { + name = "check-expired-route53-records" + description = "Trigger Lambda to check and delete expired Route53 DNS records" + schedule_expression = var.expired_records_check_rate_expression + tags = var.common_tags +} + +resource "aws_cloudwatch_event_target" "invoke_lambda" { + rule = aws_cloudwatch_event_rule.check_expired_records.name + target_id = "InvokeLambdaToDeleteExpiredRecords" + arn = aws_lambda_function.delete_expired_records_lambda.arn +} + +resource "aws_lambda_permission" "allow_eventbridge" { + statement_id = "AllowExecutionFromEventBridge" + action = "lambda:InvokeFunction" + function_name = aws_lambda_function.delete_expired_records_lambda.function_name + principal = "events.amazonaws.com" + source_arn = aws_cloudwatch_event_rule.check_expired_records.arn +} diff --git a/generate_report.py b/generate_report.py new file mode 100644 index 0000000..47aef0e --- /dev/null +++ b/generate_report.py @@ -0,0 +1,46 @@ +import boto3 +import json +import os +import datetime +from botocore.exceptions import ClientError +from decimal import Decimal + +def lambda_handler(event, context): + dynamodb = boto3.resource('dynamodb') + + # DynamoDB table name + tablename = os.environ.get('DYNAMODB_TABLE') + if not tablename: + raise ValueError('DYNAMODB_TABLE environment variable is not set') + table = dynamodb.Table(tablename) + + try: + # Scan the DynamoDB table for active records + response = table.scan() + records = response.get('Items', []) + + # Filter for active records (adjust the condition as per your data schema) + active_records = [record for record in records if record['delete_after'] > datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ')] + expired_records = [record for record in records if record['delete_after'] < datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ')] + + # Convert Decimal objects to float + active_records = [{k: float(v) if isinstance(v, Decimal) else v for k, v in record.items()} for record in active_records] + expired_records = [{k: float(v) if isinstance(v, Decimal) else v for k, v in record.items()} for record in expired_records] + + return { + 'statusCode': 200, + 'body': json.dumps({'active_records': active_records, 'expired_records': expired_records}, cls=DateTimeEncoder) + } + + except ClientError as e: + return { + 'statusCode': 500, + 'body': json.dumps({'error': str(e)}) + } + +class DateTimeEncoder(json.JSONEncoder): + def default(self, o): + if isinstance(o, datetime.datetime): + return o.isoformat() + + return super().default(o) \ No newline at end of file diff --git a/lambda.tf b/lambda.tf new file mode 100644 index 0000000..a1168b5 --- /dev/null +++ b/lambda.tf @@ -0,0 +1,146 @@ +###Create Record Lambda + +data "archive_file" "create_record_lambda_zip" { + type = "zip" + source_file = "${path.module}/create_record.py" + output_path = "${path.module}/create_record.zip" +} + + + +resource "aws_lambda_function" "create_record_lambda" { + filename = data.archive_file.create_record_lambda_zip.output_path + function_name = "create_record_lambda" + role = aws_iam_role.lambda_execution_role.arn + handler = "create_record.lambda_handler" + runtime = "python3.9" + source_code_hash = data.archive_file.create_record_lambda_zip.output_base64sha256 + tags = var.common_tags + environment { + variables = { + HOSTED_ZONE_ID = var.hosted_zone_id, + DYNAMODB_TABLE = aws_dynamodb_table.dns_records.name + } + } +} + + + +###Delete Record Lambda + +data "archive_file" "delete_expired_records_lambda_zip" { + type = "zip" + source_file = "${path.module}/delete_expired.py" + output_path = "${path.module}/delete_expired.zip" +} + + + +resource "aws_lambda_function" "delete_expired_records_lambda" { + filename = data.archive_file.delete_expired_records_lambda_zip.output_path + function_name = "delete_expired_records" + role = aws_iam_role.lambda_execution_role.arn + handler = "delete_expired.lambda_handler" + runtime = "python3.9" + source_code_hash = data.archive_file.delete_expired_records_lambda_zip.output_base64sha256 + tags = var.common_tags + environment { + variables = { + HOSTED_ZONE_ID = var.hosted_zone_id, + DYNAMODB_TABLE = aws_dynamodb_table.dns_records.name + } + } +} + +###Report Record Lambda + + +data "archive_file" "records_report_lambda_zip" { + type = "zip" + source_file = "${path.module}/generate_report.py" + output_path = "${path.module}/generate_report.zip" +} + + + +resource "aws_lambda_function" "records_report_lambda" { + filename = data.archive_file.records_report_lambda_zip.output_path + function_name = "generate_flashpoint_records_report" + role = aws_iam_role.lambda_execution_role.arn + handler = "generate_report.lambda_handler" + runtime = "python3.9" + source_code_hash = data.archive_file.records_report_lambda_zip.output_base64sha256 + tags = var.common_tags + environment { + variables = { + HOSTED_ZONE_ID = var.hosted_zone_id, + DYNAMODB_TABLE = aws_dynamodb_table.dns_records.name + } + } +} + + +###Lambda Execution Role + +resource "aws_iam_role" "lambda_execution_role" { + name = "lambda_execution_role" + tags = var.common_tags + assume_role_policy = jsonencode({ + Version = "2012-10-17", + Statement = [ + { + Action = "sts:AssumeRole", + Effect = "Allow", + Principal = { + Service = "lambda.amazonaws.com" + }, + }, + ], + }) +} + +resource "aws_iam_role_policy" "lambda_policy" { + name = "lambda_execution_policy" + role = aws_iam_role.lambda_execution_role.id + + policy = jsonencode({ + Version = "2012-10-17", + Statement = [ + { + Action = [ + "route53:ChangeResourceRecordSets", + "route53:ListResourceRecordSets" + ], + Effect = "Allow", + Resource = "arn:aws:route53:::hostedzone/${var.hosted_zone_id}" + }, + { + Action = [ + "route53:GetHostedZone", + "route53:ListHostedZones" + ], + Effect = "Allow", + Resource = "*" + }, + { + Action = [ + "dynamodb:PutItem", + "dynamodb:GetItem", + "dynamodb:UpdateItem", + "dynamodb:DeleteItem", + "dynamodb:Scan" + ], + Effect = "Allow", + Resource = aws_dynamodb_table.dns_records.arn + }, + { + Action = [ + "logs:*" + ], + Effect = "Allow", + Resource = "*" + } + ], + }) +} + diff --git a/main.tf b/main.tf new file mode 100644 index 0000000..2a5ccf3 --- /dev/null +++ b/main.tf @@ -0,0 +1,3 @@ +provider "aws" { + region = var.aws_region +} \ No newline at end of file diff --git a/output.tf b/output.tf new file mode 100644 index 0000000..2118ec1 --- /dev/null +++ b/output.tf @@ -0,0 +1,9 @@ +output "dns_record_endpoint" { + description = "API Gateway endpoint for DNS record resource" + value = aws_api_gateway_resource.dns_record_resource.id +} + +output "reports_endpoint" { + description = "API Gateway endpoint for reports resource" + value = aws_api_gateway_resource.reports_resource.id +} \ No newline at end of file diff --git a/variable.tf b/variable.tf new file mode 100644 index 0000000..d798a75 --- /dev/null +++ b/variable.tf @@ -0,0 +1,33 @@ +variable "aws_region" { + description = "AWS region to deploy resources" + type = string + default = "us-east-1" +} + +variable "expired_records_check_rate_expression" { + type = string + default = "rate(1 hour)" +} + +variable "hosted_zone_id" { + type = string + description = "The ID of the hosted zone in which to create the record." + + validation { + condition = length(regexall("^[A-Z0-9]{14}$", var.hosted_zone_id)) == 1 + error_message = "The hosted_zone_id must be a valid ID in the format of a 14-character string containing only uppercase letters and digits." + } +} + +variable "common_tags" { + type = map(string) + default = { + Terraform = "true" + } +} + +variable "force_deploy" { + type = bool + description = "Force deploy of api gateway" + default = false +} \ No newline at end of file