Skip to content

Latest commit

 

History

History
441 lines (395 loc) · 61.2 KB

File metadata and controls

441 lines (395 loc) · 61.2 KB

Terraform AWS Infrastructure Live CI

Terraform module that provisions an AWS serverless CI/CD pipeline used for managing live infrastructure defined in a trunk-based repository. The module features AWS account-level dependencies and approval flows for handling implicit and nested Terraform dependency changes.

  • For a deep-dive into the architecture, refer to DESIGN.MD
  • To see how to contribute to this project, refer to CONTRIBUTING.md

Requirements

Name Version
terraform >=1.3.0
aws >= 3.44
docker >=2.23.0
github >= 4.0
random >=3.2.0

Providers

Name Version
aws >= 3.44
docker >=2.23.0
github >= 4.0
null n/a
random >=3.2.0

Modules

Name Source Version
create_deploy_stack_role github.com/marshall7m/terraform-aws-iam//modules/iam-role v0.2.0
cw_event_rule_role github.com/marshall7m/terraform-aws-iam//modules/iam-role v0.2.0
cw_event_terra_run github.com/marshall7m/terraform-aws-iam//modules/iam-role v0.2.0
ecr_approval_response terraform-aws-modules/ecr/aws 1.5.0
ecr_ecs_tasks terraform-aws-modules/ecr/aws 1.5.0
ecr_receiver terraform-aws-modules/ecr/aws 1.5.0
ecs_execution_role github.com/marshall7m/terraform-aws-iam//modules/iam-role v0.2.0
lambda_approval_request terraform-aws-modules/lambda/aws 3.3.1
lambda_approval_response terraform-aws-modules/lambda/aws 3.3.1
lambda_trigger_sf terraform-aws-modules/lambda/aws 3.3.1
lambda_webhook_receiver terraform-aws-modules/lambda/aws 3.3.1
pr_plan_role github.com/marshall7m/terraform-aws-iam//modules/iam-role v0.2.0
sf_role github.com/marshall7m/terraform-aws-iam//modules/iam-role v0.2.0
terra_run_apply_role github.com/marshall7m/terraform-aws-iam//modules/iam-role v0.2.0
terra_run_plan_role github.com/marshall7m/terraform-aws-iam//modules/iam-role v0.2.0

Resources

Name Type
aws_cloudwatch_event_rule.ecs_terra_run resource
aws_cloudwatch_event_rule.sf_execution resource
aws_cloudwatch_event_target.sf_execution resource
aws_cloudwatch_event_target.terra_run resource
aws_cloudwatch_log_group.ecs_tasks resource
aws_db_subnet_group.metadb resource
aws_ecs_cluster.this resource
aws_ecs_task_definition.create_deploy_stack resource
aws_ecs_task_definition.pr_plan resource
aws_ecs_task_definition.terra_run resource
aws_iam_policy.approval_response resource
aws_iam_policy.ci_metadb_access resource
aws_iam_policy.commit_status_config resource
aws_iam_policy.ecs_plan resource
aws_iam_policy.ecs_write_logs resource
aws_iam_policy.github_token_ssm_read_access resource
aws_iam_policy.lambda_approval_request resource
aws_iam_policy.merge_lock_ssm_param_full_access resource
aws_iam_policy.trigger_sf resource
aws_iam_policy.webhook_receiver resource
aws_rds_cluster.metadb resource
aws_secretsmanager_secret.ci_metadb_user resource
aws_secretsmanager_secret.master_metadb_user resource
aws_secretsmanager_secret.registry resource
aws_secretsmanager_secret_version.ci_metadb_user resource
aws_secretsmanager_secret_version.master_metadb_user resource
aws_secretsmanager_secret_version.registry resource
aws_security_group.ecs_tasks resource
aws_security_group.metadb resource
aws_ses_email_identity.approval resource
aws_ses_identity_policy.approval resource
aws_ses_template.approval resource
aws_sfn_state_machine.this resource
aws_sns_topic.approval resource
aws_sns_topic_subscription.ses_approval_request resource
aws_ssm_parameter.commit_status_config resource
aws_ssm_parameter.email_approval_secret resource
aws_ssm_parameter.github_token resource
aws_ssm_parameter.github_webhook_secret resource
aws_ssm_parameter.merge_lock resource
aws_ssm_parameter.metadb_ci_password resource
aws_ssm_parameter.scan_type resource
docker_image.ecr_approval_response resource
docker_image.ecr_ecs_tasks resource
docker_image.ecr_receiver resource
docker_registry_image.ecr_approval_response resource
docker_registry_image.ecr_ecs_tasks resource
docker_registry_image.ecr_receiver resource
docker_tag.ecr_approval_response resource
docker_tag.ecr_ecs_tasks resource
docker_tag.ecr_receiver resource
github_branch_protection.merge_lock resource
github_repository_webhook.this resource
null_resource.metadb_setup_account_dim resource
null_resource.metadb_setup_tables resource
null_resource.metadb_setup_user resource
random_id.metadb_users resource
random_password.email_approval_secret resource
random_password.github_webhook_secret resource
aws_caller_identity.current data source
aws_iam_policy_document.approval data source
aws_iam_policy_document.approval_response data source
aws_iam_policy_document.ci_metadb_access data source
aws_iam_policy_document.commit_status_config data source
aws_iam_policy_document.ecs_plan data source
aws_iam_policy_document.ecs_write_logs data source
aws_iam_policy_document.github_token_ssm_read_access data source
aws_iam_policy_document.lambda_approval_request data source
aws_iam_policy_document.merge_lock_ssm_param_full_access data source
aws_iam_policy_document.trigger_sf data source
aws_iam_policy_document.webhook_receiver data source
aws_kms_key.ssm_kms_key data source
aws_region.current data source
aws_ses_email_identity.approval data source
aws_ssm_parameter.github_token data source

Inputs

Name Description Type Default Required
account_parent_cfg AWS account-level configurations.
- name: AWS account name (e.g. dev, staging, prod, etc.)
- path: Parent account directory path relative to the repository's root directory path (e.g. infrastructure-live/dev-account)
- voters: List of email addresses that will be sent approval request to
- min_approval_count: Minimum approval count needed for CI pipeline to run deployment
- min_rejection_count: Minimum rejection count needed for CI pipeline to decline deployment
- dependencies: List of AWS account names that this account depends on before running any of it's deployments
- For example, if the dev account depends on the shared-services account and both accounts contain infrastructure changes within a PR (rare scenario but possible),
all deployments that resolve infrastructure changes within shared-services need to be applied before any dev deployments are executed. This is useful given a
scenario where resources within the dev account are explicitly dependent on resources within the shared-serives account.
- plan_role_arn: IAM role ARN within the account that the plan build will assume
- CAUTION: Do not give the plan role broad administrative permissions as that could lead to detrimental results if the build was compromised
- apply_role_arn: IAM role ARN within the account that the deploy build will assume
- Fine-grained permissions for each Terragrunt directory within the account can be used by defining a before_hook block that
conditionally defines that assume_role block within the directory dependant on the Terragrunt command. For example within prod/iam/terragrunt.hcl,
define a before hook block that passes a strict read-only role ARN for terragrunt plan commands and a strict write role ARN for terragrunt apply. Then
within the apply_role_arn attribute here, define a IAM role that can assume both of these roles.
list(object({
name = string
path = string
voters = list(string)
min_approval_count = number
min_rejection_count = number
dependencies = list(string)
plan_role_arn = string
apply_role_arn = string
}))
n/a yes
api_stage_name API deployment stage name string "prod" no
approval_request_sender_email Email address to use for sending approval requests string n/a yes
approval_response_image_address Docker registry image to use for the approval repsonse Lambda Function. If not specified, this Terraform module's GitHub registry image
will be used with the tag associated with the version of this module.
string null no
approval_sender_arn AWS SES identity ARN used to send approval emails string null no
base_branch Base branch for repository that all PRs will compare to string "master" no
commit_status_config Determines which commit statuses should be sent for each of the specified pipeline components.
The commit status will contain the current state (e.g pending, success, failure) and will link to
the component's associated AWS console page.

Each of the following descriptions specify where and what the commit status links to:

PrPlan: CloudWatch log stream displaying the Terraform plan for a directory within the open pull request
CreateDeployStack: CloudWatch log stream displaying the execution metadb records that were created for
the merged pull request
Plan: CloudWatch log stream displaying the Terraform plan for a directory within the merged pull request
Apply: CloudWatch log stream displaying the Terraform apply output for a directory within the merged pull request
Execution: AWS Step Function page for the deployment flow execution
object({
PrPlan = optional(bool, true)
CreateDeployStack = optional(bool, true)
Plan = optional(bool, true)
Apply = optional(bool, true)
Execution = optional(bool, true)
})
{} no
create_approval_sender_policy Determines if an identity policy should be attached to approval sender identity bool true no
create_deploy_stack_cpu Number of CPU units the create deploy stack task will use.
See for more info: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-cpu-memory-error.html
number 256 no
create_deploy_stack_memory Amount of memory (MiB) the create deploy stack task will use.
See for more info: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-cpu-memory-error.html
string 512 no
create_deploy_stack_scan_type If set to graph, the create_deploy_stack build will use the git detected differences to determine what directories to run Step Function executions for.
If set to plan, the build will use terragrunt run-all plan detected differences to determine the executions.
Set to plan if changes to the terraform resources are also being controlled outside of the repository (e.g AWS console, separate CI pipeline, etc.)
which results in need to refresh the terraform remote state to accurately detect changes.
Otherwise set to graph, given that collecting changes via git will be significantly faster than collecting changes via terragrunt run-all plan.
string "graph" no
create_deploy_stack_status_check_name Name of the create deploy stack GitHub status string "CreateDeployStack" no
create_github_token_ssm_param Determines if a AWS SSM Parameter Store value should be created for the GitHub token bool n/a yes
create_metadb_subnet_group Determines if a AWS RDS subnet group should be created for the metadb bool false no
create_private_registry_secret Determines if the module should create the AWS Secret Manager resource used for private registry authentification bool true no
ecs_assign_public_ip Determines if an public IP address will be associated with ECS tasks.
Value is required to be true if var.ecs_subnet_ids are public subnets.
Value can be false if var.ecs_subnet_ids are private subnets that have a route
to a NAT gateway.
bool false no
ecs_image_address Docker registry image to use for the ECS Fargate containers. If not specified, this Terraform module's GitHub registry image
will be used with the tag associated with the version of this module.
string null no
ecs_subnet_ids AWS VPC subnet IDs to host the ECS container instances within.
The subnets should allow the ECS containers to have internet access to pull the
container image and make API calls to Terraform provider resources.
The subnets should be associated with the VPC ID specified under var.vpc_id
list(string) n/a yes
ecs_task_logs_retention_in_days Number of days the ECS task logs will be retained number 14 no
ecs_tasks_common_env_vars Common env vars defined within all ECS tasks. Useful for setting Terragrunt specific env vars required to run Terragrunt commands.
list(object({
name = string
value = string
}))
[] no
enable_branch_protection Determines if the branch protection rule is created. If the repository is private (most likely), the GitHub account associated with
the GitHub provider must be registered as a GitHub Pro, GitHub Team, GitHub Enterprise Cloud, or GitHub Enterprise Server account. See here for details: https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/about-protected-branches
bool true no
enable_gh_comment_approval Determines if execution approval votes can be sent via GitHub comments.
This will also enable Terraform plans to be commented within merged PR page
bool false no
enable_gh_comment_pr_plan Determines if Terraform plans will be commented within open PR page bool false no
enforce_admin_branch_protection Determines if the branch protection rule is enforced for the GitHub repository's admins.
This essentially gives admins permission to force push to the trunk branch and can allow their infrastructure-related commits to bypass the CI pipeline.
bool false no
file_path_pattern Regex pattern to match webhook modified/new files to. Defaults to any file with .hcl or .tf extension. string `".+\.(hcl tf)$\n"`
github_token_ssm_description Github token SSM parameter description string "Github token used by Merge Lock Lambda Function" no
github_token_ssm_key AWS SSM Parameter Store key for sensitive Github personal token used by the Merge Lock Lambda Function string null no
github_token_ssm_tags Tags for Github token SSM parameter map(string) {} no
github_token_ssm_value Registered Github token associated with the Github provider. If not provided,
module looks for pre-existing SSM parameter via var.github_token_ssm_key".
GitHub token needs the repo permission to send commit statuses and write comments
for private repos (see more about OAuth scopes here:
https://docs.github.com/en/developers/apps/building-oauth-apps/scopes-for-oauth-apps)
string "" no
lambda_approval_request_vpc_config VPC configuration for Lambda approval request function.
Ensure that the configuration allows for outgoing HTTPS traffic.
object({
subnet_ids = list(string)
security_group_ids = list(string)
})
null no
lambda_approval_response_vpc_config VPC configuration for Lambda approval response function.
Ensure that the configuration allows for outgoing HTTPS traffic.
object({
subnet_ids = list(string)
security_group_ids = list(string)
})
null no
lambda_trigger_sf_vpc_config VPC configuration for Lambda trigger_sf function.
Ensure that the configuration allows for outgoing HTTPS traffic.
object({
subnet_ids = list(string)
security_group_ids = list(string)
})
null no
lambda_webhook_receiver_vpc_config VPC configuration for Lambda webhook_receiver function.
Ensure that the configuration allows for outgoing HTTPS traffic.
object({
subnet_ids = list(string)
security_group_ids = list(string)
})
null no
merge_lock_status_check_name Name of the merge lock GitHub status string "Merge Lock" no
metadb_availability_zones AWS availability zones that the metadb RDS cluster will be hosted in. Recommended to define atleast 3 zones. list(string) null no
metadb_ci_password Password for the metadb user used for the ECS tasks string n/a yes
metadb_ci_username Name of the metadb user used for the ECS tasks string "ci_user" no
metadb_cluster_arn Metadb cluster ARN that will be used for metadb setup queries (used for local metadb testing) string null no
metadb_endpoint_url Endpoint URL that metadb setup queries will be directed to (used for local metadb testing) string null no
metadb_name Name of the metadb string null no
metadb_password Master password for the metadb string n/a yes
metadb_port Port for AWS RDS Postgres db number 5432 no
metadb_schema Schema for AWS RDS Postgres db string "prod" no
metadb_secret_arn Metadb secret ARN that will be used for metadb setup queries (used for local metadb testing) string null no
metadb_security_group_ids Additional AWS VPC security group to associate the metadb with list(string) [] no
metadb_subnet_ids AWS VPC subnet IDs to host the metadb within list(string) n/a yes
metadb_username Master username of the metadb string "root" no
plan_cpu Number of CPU units the PR plan task will use.
See for more info: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-cpu-memory-error.html
number 256 no
plan_memory Amount of memory (MiB) the PR plan task will use.
See for more info: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-cpu-memory-error.html
string 512 no
pr_approval_count Number of GitHub approvals required to merge a PR with infrastructure changes number null no
pr_plan_env_vars Environment variables that will be provided to open PR's Terraform planning tasks
list(object({
name = string
value = string
type = optional(string)
}))
[] no
prefix Prefix to attach to all resources string null no
private_registry_auth Determines if authentification is required to pull the docker images used by the ECS tasks bool false no
private_registry_custom_kms_key_arn ARN of the custom AWS KMS key to use for decrypting private registry credentials hosted with AWS Secret Manager string null no
private_registry_secret_manager_arn Pre-existing AWS Secret Manager ARN used for private registry authentification string null no
registry_password Private Docker registry password used to authenticate ECS task to pull docker image string null no
registry_username Private Docker registry username used to authenticate ECS task to pull docker image string null no
repo_clone_url Clone URL of the repository (e.g. ssh://host.xz/path/to/repo.git, https://host.xz/path/to/repo.git) string n/a yes
send_verification_email Determines if an email verification should be sent to the var.approval_request_sender_email address. Set
to true if the email address is not already authorized to send emails via AWS SES.
bool true no
step_function_name Name of AWS Step Function machine string "deployment-flow" no
terra_run_cpu Number of CPU units the terra run task will use.
See for more info: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-cpu-memory-error.html
number 256 no
terra_run_env_vars Environment variables that will be provided for tf plan/apply tasks
list(object({
name = string
value = string
type = optional(string)
}))
[] no
terra_run_memory Amount of memory (MiB) the terra run task will use.
See for more info: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-cpu-memory-error.html
string 512 no
terraform_version Terraform version used for create_deploy_stack and terra_run tasks.
Version must be >= 0.13.0.
If repo contains a variety of version constraints, implementing a
version manager is recommended (e.g. tfenv).
string "" no
terragrunt_version Terragrunt version used for create_deploy_stack and terra_run tasks.
Version must be >= 0.31.0.
If repo contains a variety of version constraints, implementing a
version manager is recommended (e.g. tgswitch).
string "" no
tf_state_read_access_policy AWS IAM policy ARN that allows create deploy stack ECS task to read from Terraform remote state resource string n/a yes
vpc_id AWS VPC ID to host the ECS container instances within.
The VPC should be associated with the subnet IDs specified under var.ecs_subnet_ids
string n/a yes
webhook_receiver_image_address Docker registry image to use for the webhook receiver Lambda Function. If not specified, this Terraform module's GitHub registry image
will be used with the tag associated with the version of this module.
string null no

Outputs

Name Description
account_parent_cfg AWS account-level configurations
approval_request_function_name Name of the Lambda Function used for sending approval requests
approval_request_log_group_name Cloudwatch log group associated with the Lambda Function used for processing deployment approval responses
approval_response_function_name Name of the Lambda Function used for handling approval responses
approval_response_image_address Docker registry image used for the approval response Lambda Function
approval_response_role_arn IAM Role ARN of the Lambda Function used for handling approval responses
approval_response_ses_secret Secret value used for authenticating AWS SES approvals within the approval response Lambda Function
approval_url Lambda Function URL used for casting deployment approval votes
base_branch Base branch for repository that all PRs will compare to
commit_status_config Determines which commit statuses should be sent for each of the specified pipeline components
create_deploy_stack_log_stream_prefix Create Deploy Stack Cloudwatch log stream prefix
create_deploy_stack_status_check_name Name of the create deploy stack GitHub commit status
ecs_apply_role_arn IAM role ARN the AWS ECS terra run task can assume
ecs_cluster_arn AWS ECS cluster ARN
ecs_create_deploy_stack_container_name Name of the create deploy stack ECS task container
ecs_create_deploy_stack_definition_arn AWS ECS create deploy stack defintion ARN
ecs_create_deploy_stack_family AWS ECS task definition family for the create deploy stack task
ecs_create_deploy_stack_role_arn AWS ECS create deploy stack task IAM role ARN
ecs_log_group_name Cloudwatch log group name for all ECS tasks
ecs_network_config VPC network configurations for ECS tasks
ecs_pr_plan_container_name Name of the pr plan ECS task container
ecs_pr_plan_family AWS ECS task definition family for the PR plan task
ecs_pr_plan_role_arn IAM role ARN the AWS ECS pr plan task can assume
ecs_pr_plan_task_definition_arn AWS ECS terra run task defintion ARN
ecs_security_group_ids List of security groups IDs used ECS tasks
ecs_subnet_ids AWS VPC subnets IDs that the ECS tasks will be hosted in
ecs_terra_run_family AWS ECS task definition family for the Terra Run task
ecs_terra_run_plan_role_arn IAM role ARN the Terra Run AWS ECS plan task can assume
ecs_terra_run_task_container_name Name of the terra run ECS task container
ecs_terra_run_task_definition_arn AWS ECS terra run task defintion ARN
email_approval_secret Secret value used for authenticating email approval responses
file_path_pattern Regex pattern to match webhook modified/new files to
github_webhook_id GitHub webhook ID used for sending pull request activity to the Lambda Receiver Function
github_webhook_secret_ssm_key Key for the AWS SSM Parameter Store used to store GitHub webhook secret
lambda_trigger_sf_arn ARN of the Lambda Function used for triggering Step Function execution(s)
merge_lock_ssm_key SSM Parameter Store key used for storing the current PR ID that has been merged and is being process by the CI flow
merge_lock_status_check_name Context name of the merge lock GitHub commit status check
metadb_arn ARN for the metadb
metadb_ci_password Password used by CI services to connect to the metadb
metadb_ci_username Username used by CI services to connect to the metadb
metadb_endpoint AWS RDS endpoint for the metadb
metadb_name Name of the metadb
metadb_password Master password for the metadb
metadb_port Port used for the metadb
metadb_secret_manager_ci_arn Secret Manager ARN of the metadb CI user credentials
metadb_secret_manager_master_arn Secret Manager ARN of the metadb master user credentials
metadb_username Master username for the metadb
receiver_function_name Name of the Lambda Receiver Function
receiver_role_arn ARN of the Lambda Receiver Function
scan_type_ssm_param_name Name of the AWS SSM Parameter store value used to determine the scan type within the create deploy stack task
ses_approval_subject_template Template used for formulating SES approval email subject line
step_function_arn ARN of the Step Function
step_function_name Name of the Step Function
trigger_sf_function_name Name of the Lambda Function used for triggering Step Function execution(s)
trigger_sf_log_group_name Cloudwatch log group associated with the Lambda Function used for triggering Step Function execution(s)

Cost

Cost estimate in the us-west-2 region via Infracost:

 Name                                                                                            Monthly Qty  Unit                        Monthly Cost 
                                                                                                                                                       
 aws_api_gateway_rest_api.this                                                                                                                         
 └─ Requests (first 333M)                                                                Monthly cost depends on usage: $3.50 per 1M requests          
                                                                                                                                                       
 aws_cloudwatch_log_group.ecs_tasks                                                                                                                    
 ├─ Data ingested                                                                        Monthly cost depends on usage: $0.50 per GB                   
 ├─ Archival Storage                                                                     Monthly cost depends on usage: $0.03 per GB                   
 └─ Insights queries data scanned                                                        Monthly cost depends on usage: $0.005 per GB                  
                                                                                                                                                       
 aws_rds_cluster.metadb                                                                                                                                
 ├─ Aurora serverless                                                                    Monthly cost depends on usage: $0.06 per ACU-hours            
 ├─ Storage                                                                              Monthly cost depends on usage: $0.10 per GB                   
 ├─ I/O requests                                                                         Monthly cost depends on usage: $0.20 per 1M requests          
 └─ Snapshot export                                                                      Monthly cost depends on usage: $0.01 per GB                   
                                                                                                                                                       
 aws_secretsmanager_secret.ci_metadb_user                                                                                                              
 ├─ Secret                                                                                                 1  months                             $0.40 
 └─ API requests                                                                         Monthly cost depends on usage: $0.05 per 10k requests         
                                                                                                                                                       
 aws_secretsmanager_secret.master_metadb_user                                                                                                          
 ├─ Secret                                                                                                 1  months                             $0.40 
 └─ API requests                                                                         Monthly cost depends on usage: $0.05 per 10k requests         
                                                                                                                                                       
 aws_sfn_state_machine.this                                                                                                                            
 └─ Transitions                                                                          Monthly cost depends on usage: $0.025 per 1K transitions      
                                                                                                                                                       
 module.github_webhook_validator.aws_cloudwatch_log_group.agw[0]                                                                                       
 ├─ Data ingested                                                                        Monthly cost depends on usage: $0.50 per GB                   
 ├─ Archival Storage                                                                     Monthly cost depends on usage: $0.03 per GB                   
 └─ Insights queries data scanned                                                        Monthly cost depends on usage: $0.005 per GB                  
                                                                                                                                                       
 module.github_webhook_validator.module.lambda_function.aws_cloudwatch_log_group.lambda                                                                
 ├─ Data ingested                                                                        Monthly cost depends on usage: $0.50 per GB                   
 ├─ Archival Storage                                                                     Monthly cost depends on usage: $0.03 per GB                   
 └─ Insights queries data scanned                                                        Monthly cost depends on usage: $0.005 per GB                  
                                                                                                                                                       
 module.github_webhook_validator.module.lambda_function.aws_lambda_function.this                                                                       
 ├─ Requests                                                                             Monthly cost depends on usage: $0.20 per 1M requests          
 └─ Duration                                                                             Monthly cost depends on usage: $0.0000166667 per GB-seconds   
                                                                                                                                                       
 module.lambda_approval_request.aws_cloudwatch_log_group.this[0]                                                                                       
 ├─ Data ingested                                                                        Monthly cost depends on usage: $0.50 per GB                   
 ├─ Archival Storage                                                                     Monthly cost depends on usage: $0.03 per GB                   
 └─ Insights queries data scanned                                                        Monthly cost depends on usage: $0.005 per GB                  
                                                                                                                                                       
 module.lambda_approval_request.aws_lambda_function.this[0]                                                                                            
 ├─ Requests                                                                             Monthly cost depends on usage: $0.20 per 1M requests          
 └─ Duration                                                                             Monthly cost depends on usage: $0.0000166667 per GB-seconds   
                                                                                                                                                       
 module.lambda_approval_response.aws_cloudwatch_log_group.this[0]                                                                                      
 ├─ Data ingested                                                                        Monthly cost depends on usage: $0.50 per GB                   
 ├─ Archival Storage                                                                     Monthly cost depends on usage: $0.03 per GB                   
 └─ Insights queries data scanned                                                        Monthly cost depends on usage: $0.005 per GB                  
                                                                                                                                                       
 module.lambda_approval_response.aws_lambda_function.this[0]                                                                                           
 ├─ Requests                                                                             Monthly cost depends on usage: $0.20 per 1M requests          
 └─ Duration                                                                             Monthly cost depends on usage: $0.0000166667 per GB-seconds   
                                                                                                                                                       
 module.lambda_trigger_sf.aws_cloudwatch_log_group.this[0]                                                                                             
 ├─ Data ingested                                                                        Monthly cost depends on usage: $0.50 per GB                   
 ├─ Archival Storage                                                                     Monthly cost depends on usage: $0.03 per GB                   
 └─ Insights queries data scanned                                                        Monthly cost depends on usage: $0.005 per GB                  
                                                                                                                                                       
 module.lambda_trigger_sf.aws_lambda_function.this[0]                                                                                                  
 ├─ Requests                                                                             Monthly cost depends on usage: $0.20 per 1M requests          
 └─ Duration                                                                             Monthly cost depends on usage: $0.0000166667 per GB-seconds   
                                                                                                                                                       
 module.lambda_webhook_receiver.aws_cloudwatch_log_group.this[0]                                                                                       
 ├─ Data ingested                                                                        Monthly cost depends on usage: $0.50 per GB                   
 ├─ Archival Storage                                                                     Monthly cost depends on usage: $0.03 per GB                   
 └─ Insights queries data scanned                                                        Monthly cost depends on usage: $0.005 per GB                  
                                                                                                                                                       
 module.lambda_webhook_receiver.aws_lambda_function.this[0]                                                                                            
 ├─ Requests                                                                             Monthly cost depends on usage: $0.20 per 1M requests          
 └─ Duration                                                                             Monthly cost depends on usage: $0.0000166667 per GB-seconds   
                                                                                                                                                       
 OVERALL TOTAL                                                                                                                                   $0.80 
──────────────────────────────────
133 cloud resources were detected:
∙ 17 were estimated, all of which include usage-based costs, see https://infracost.io/usage-file
∙ 106 were free:
  ∙ 31 x aws_iam_role_policy_attachment
  ∙ 22 x aws_iam_policy
  ∙ 9 x aws_iam_role
  ∙ 7 x aws_ssm_parameter
  ∙ 5 x aws_lambda_permission
  ∙ 4 x aws_api_gateway_method_response
  ∙ 4 x aws_lambda_layer_version
  ∙ 3 x aws_ecs_task_definition
  ∙ 2 x aws_api_gateway_integration
  ∙ 2 x aws_api_gateway_method
  ∙ 2 x aws_api_gateway_method_settings
  ∙ 2 x aws_api_gateway_resource
  ∙ 2 x aws_cloudwatch_event_rule
  ∙ 2 x aws_cloudwatch_event_target
  ∙ 2 x aws_secretsmanager_secret_version
  ∙ 1 x aws_api_gateway_account
  ∙ 1 x aws_api_gateway_deployment
  ∙ 1 x aws_api_gateway_model
  ∙ 1 x aws_api_gateway_stage
  ∙ 1 x aws_ecs_cluster
  ∙ 1 x aws_lambda_event_source_mapping
  ∙ 1 x aws_lambda_function_event_invoke_config
∙ 10 are not supported yet, see https://infracost.io/requested-resources:
  ∙ 4 x aws_api_gateway_integration_response
  ∙ 1 x aws_lambda_function_url
  ∙ 1 x aws_lambda_provisioned_concurrency_config
  ∙ 1 x aws_s3_object
  ∙ 1 x aws_ses_email_identity
  ∙ 1 x aws_ses_identity_policy
  ∙ 1 x aws_ses_template

Deploy the Terraform Module

CLI Requirements

Requirements below are needed to run terraform apply on this module. This module contains null resources that run bash scripts to install pip packages, create zip files, and query the RDS database.

Name Version
awscli >= 1.22.5
python3 >= 3.9
pip >= 22.0.4

Steps

The steps below are meant for implementing the module into your current AWS ecosystem.

  1. Open a terragrunt .hcl or terraform .tf file
  2. Create a module block using this repo as the source
  3. Fill in the required module variables
  4. Run terraform init to download the module
  5. Run terraform plan to see what resources will be created
  6. Run terraform apply and enter yes to the approval prompt
  7. Refill coffee and wait for resources to be created
  8. Go to the var.approval_request_sender_email email address. Find the AWS SES verification email (subject should be something like "Amazon Web Services – Email Address Verification Request in region US West (Oregon)") and click on the verification link.
  9. Create a PR with changes to the target repo defined under var.repo_name that will create a difference in a Terraform configuration's tfstate file
  10. Merge the PR
  11. Wait for the approval email to be sent to the voter's email address
  12. Login into the voter's email address and open the approval request email (subject should be something like "${var.step_function_name} - Need Approval for Path: {{path}}")
  13. Choose either to approve or reject the deployment and click on the submit button
  14. Wait for the deployment build to finish
  15. Verify that the Terraform changes have been deployed

TODO:

Features:

  • Create a feature for handling deleted terragrunt folder using git diff commands
  • Create a feature for handling migrated terragrunt directories using git diff commands / tf state pull
  • Approval voter can choose to be notified when deployment stack and/or deployment execution is successful or failed
  • Use AWS SQS with Exactly-Once Processing to create a queue of pr tf plan tasks to run
    • User can then set a time range (such as after hours) that the PR plans are run so that the plan tasks are not run for every PR update event
  • create aesthetically pleasing approval request HTML template (Help appreciated!)
  • create an sns topic for failed terraform runs that notifies users
  • group ssm parameter via /var.prefix/param_name