From ec9cc8929bf167bedf187dbecbbfac1c10892e88 Mon Sep 17 00:00:00 2001 From: Chris Wright Date: Wed, 24 Jul 2024 16:50:22 +0100 Subject: [PATCH] RDS backups to S3 * Conditonally create a scheduled Fargate task to backup RDS databases to S3 --- README.md | 35 +++ kms-infrastructure.tf | 12 ++ locals.tf | 17 +- .../secrets-manager-get-secret-value.json.tpl | 12 ++ rds-infrastructure-cloudwatch-logs.tf | 9 + rds-infrastructure-s3-backups-ecr.tf | 17 ++ rds-infrastructure-s3-backups-s3.tf | 87 ++++++++ ...nfrastructure-s3-backups-security-group.tf | 77 +++++++ ...frastructure-s3-backups-task-definition.tf | 199 ++++++++++++++++++ rds-infrastructure-security-group.tf | 12 ++ rds-infrastructure-tooling-ecs-cluster.tf | 26 +++ variables.tf | 15 ++ 12 files changed, 516 insertions(+), 2 deletions(-) create mode 100644 policies/secrets-manager-get-secret-value.json.tpl create mode 100644 rds-infrastructure-s3-backups-ecr.tf create mode 100644 rds-infrastructure-s3-backups-s3.tf create mode 100644 rds-infrastructure-s3-backups-security-group.tf create mode 100644 rds-infrastructure-s3-backups-task-definition.tf create mode 100644 rds-infrastructure-tooling-ecs-cluster.tf diff --git a/README.md b/README.md index 73d227a..8158662 100644 --- a/README.md +++ b/README.md @@ -63,15 +63,18 @@ This project creates and manages resources within an AWS account for infrastruct | [aws_cloudwatch_event_rule.ecs_cluster_infrastructure_pending_task_metric_1_min_cron](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_rule) | resource | | [aws_cloudwatch_event_rule.infrastructure_ecs_cluster_service_ecr_scan](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_rule) | resource | | [aws_cloudwatch_event_rule.infrastructure_ecs_cluster_service_scheduled_task](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_rule) | resource | +| [aws_cloudwatch_event_rule.infrastructure_rds_s3_backups_scheduled_task](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_rule) | resource | | [aws_cloudwatch_event_target.ecr_scan_event_target](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_target) | resource | | [aws_cloudwatch_event_target.ecs_cluster_infrastructure_ecs_asg_diff_metric_1_min_cron](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_target) | resource | | [aws_cloudwatch_event_target.ecs_cluster_infrastructure_pending_task_metric_1_min_cron](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_target) | resource | | [aws_cloudwatch_event_target.infrastructure_ecs_cluster_service_scheduled_task](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_target) | resource | +| [aws_cloudwatch_event_target.infrastructure_rds_s3_backups_scheduled_task](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_target) | resource | | [aws_cloudwatch_log_group.ecs_cluster_infrastructure_draining_lambda_log_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | | [aws_cloudwatch_log_group.ecs_cluster_infrastructure_ecs_asg_diff_metric_lambda_log_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | | [aws_cloudwatch_log_group.ecs_cluster_infrastructure_pending_task_metric_lambda_log_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | | [aws_cloudwatch_log_group.infrastructure_ecs_cluster_service](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | | [aws_cloudwatch_log_group.infrastructure_rds_exports](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | +| [aws_cloudwatch_log_group.infrastructure_rds_s3_backups](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | | [aws_cloudwatch_log_group.infrastructure_vpc_flow_logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | | [aws_cloudwatch_metric_alarm.infrastructure_ecs_cluster_asg_cpu](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_metric_alarm) | resource | | [aws_cloudwatch_metric_alarm.infrastructure_ecs_cluster_ecs_asg_diff](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_metric_alarm) | resource | @@ -87,10 +90,13 @@ This project creates and manages resources within an AWS account for infrastruct | [aws_db_subnet_group.infrastructure_rds](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_subnet_group) | resource | | [aws_default_network_acl.infrastructure](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/default_network_acl) | resource | | [aws_ecr_repository.infrastructure_ecs_cluster_service](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecr_repository) | resource | +| [aws_ecr_repository.infrastructure_rds_s3_backups](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecr_repository) | resource | | [aws_ecs_cluster.infrastructure](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_cluster) | resource | +| [aws_ecs_cluster.infrastrucutre_rds_tooling](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_cluster) | resource | | [aws_ecs_service.infrastructure_ecs_cluster_service](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_service) | resource | | [aws_ecs_task_definition.infrastructure_ecs_cluster_service](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_task_definition) | resource | | [aws_ecs_task_definition.infrastructure_ecs_cluster_service_scheduled_task](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_task_definition) | resource | +| [aws_ecs_task_definition.infrastructure_rds_s3_backups_scheduled_task](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_task_definition) | resource | | [aws_efs_file_system.infrastructure_ecs_cluster](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/efs_file_system) | resource | | [aws_efs_mount_target.infrastructure_ecs_cluster](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/efs_mount_target) | resource | | [aws_eip.infrastructure_nat](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eip) | resource | @@ -153,6 +159,11 @@ This project creates and manages resources within an AWS account for infrastruct | [aws_iam_policy.infrastructure_ecs_cluster_service_task_ssm_create_channels](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | | [aws_iam_policy.infrastructure_ecs_cluster_ssm_service_setting_rw](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | | [aws_iam_policy.infrastructure_rds_monitoring](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_policy.infrastructure_rds_s3_backups_task_execution_cloudwatch_logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_policy.infrastructure_rds_s3_backups_task_execution_ecr_pull](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_policy.infrastructure_rds_s3_backups_task_execution_get_secret_value](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_policy.infrastructure_rds_s3_backups_task_kms_encrypt](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_policy.infrastructure_rds_s3_backups_task_s3_write](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | | [aws_iam_role.ecs_cluster_infrastructure_draining_lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | [aws_iam_role.ecs_cluster_infrastructure_ecs_asg_diff_metric_lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | [aws_iam_role.ecs_cluster_infrastructure_pending_task_metric_lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | @@ -165,6 +176,8 @@ This project creates and manages resources within an AWS account for infrastruct | [aws_iam_role.infrastructure_ecs_cluster_service_task](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | [aws_iam_role.infrastructure_ecs_cluster_service_task_execution](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | [aws_iam_role.infrastructure_rds_monitoring](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role.infrastructure_rds_s3_backups_task](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role.infrastructure_rds_s3_backups_task_execution](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | [aws_iam_role.infrastructure_vpc_flow_logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | [aws_iam_role_policy.infrastructure_vpc_flow_logs_allow_cloudwatch_rw](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | | [aws_iam_role_policy_attachment.ecs_cluster_infrastructure_draining_ecs_container_instance_state_update_lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | @@ -208,6 +221,11 @@ This project creates and manages resources within an AWS account for infrastruct | [aws_iam_role_policy_attachment.infrastructure_ecs_cluster_service_task_ssm_create_channels](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_iam_role_policy_attachment.infrastructure_ecs_cluster_ssm_service_setting_rw](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_iam_role_policy_attachment.infrastructure_rds_monitoring](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_iam_role_policy_attachment.infrastructure_rds_s3_backups_task_execution_cloudwatch_logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_iam_role_policy_attachment.infrastructure_rds_s3_backups_task_execution_ecr_pull](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_iam_role_policy_attachment.infrastructure_rds_s3_backups_task_execution_get_secret_value](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_iam_role_policy_attachment.infrastructure_rds_s3_backups_task_kms_encrypt](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_iam_role_policy_attachment.infrastructure_rds_s3_backups_task_s3_write](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_iam_user.infrastructure_ecs_cluster_service_build_pipeline_buildspec_store](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_user) | resource | | [aws_internet_gateway.infrastructure_public](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/internet_gateway) | resource | | [aws_kms_alias.custom_s3_buckets](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_alias) | resource | @@ -266,17 +284,20 @@ This project creates and manages resources within an AWS account for infrastruct | [aws_s3_bucket.infrastructure_ecs_cluster_service_build_pipeline_buildspec_store](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | | [aws_s3_bucket.infrastructure_ecs_cluster_service_environment_files](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | | [aws_s3_bucket.infrastructure_logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | +| [aws_s3_bucket.infrastructure_rds_s3_backups](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | | [aws_s3_bucket.infrastructure_vpc_transfer](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | | [aws_s3_bucket_acl.infrastructure_logs_log_delivery_write](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_acl) | resource | | [aws_s3_bucket_lifecycle_configuration.custom](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_lifecycle_configuration) | resource | | [aws_s3_bucket_lifecycle_configuration.infrastructure_ecs_cluster_service_alb_logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_lifecycle_configuration) | resource | | [aws_s3_bucket_lifecycle_configuration.infrastructure_ecs_cluster_service_build_pipeline_artifact_store](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_lifecycle_configuration) | resource | +| [aws_s3_bucket_lifecycle_configuration.infrastructure_rds_s3_backups](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_lifecycle_configuration) | resource | | [aws_s3_bucket_lifecycle_configuration.logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_lifecycle_configuration) | resource | | [aws_s3_bucket_logging.cloudformation_custom_stack_template_store](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_logging) | resource | | [aws_s3_bucket_logging.custom](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_logging) | resource | | [aws_s3_bucket_logging.infrastructure_ecs_cluster_service_build_pipeline_artifact_store](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_logging) | resource | | [aws_s3_bucket_logging.infrastructure_ecs_cluster_service_build_pipeline_buildspec_store](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_logging) | resource | | [aws_s3_bucket_logging.infrastructure_ecs_cluster_service_environment_files](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_logging) | resource | +| [aws_s3_bucket_logging.infrastructure_rds_s3_backups](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_logging) | resource | | [aws_s3_bucket_logging.infrastructure_vpc_transfer](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_logging) | resource | | [aws_s3_bucket_ownership_controls.custom](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_ownership_controls) | resource | | [aws_s3_bucket_ownership_controls.infrastructure_logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_ownership_controls) | resource | @@ -287,6 +308,7 @@ This project creates and manages resources within an AWS account for infrastruct | [aws_s3_bucket_policy.infrastructure_ecs_cluster_service_build_pipeline_buildspec_store](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_policy) | resource | | [aws_s3_bucket_policy.infrastructure_ecs_cluster_service_environment_files](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_policy) | resource | | [aws_s3_bucket_policy.infrastructure_logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_policy) | resource | +| [aws_s3_bucket_policy.infrastructure_rds_s3_backups](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_policy) | resource | | [aws_s3_bucket_policy.infrastructure_vpc_transfer](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_policy) | resource | | [aws_s3_bucket_public_access_block.cloudformation_custom_stack_template_store](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block) | resource | | [aws_s3_bucket_public_access_block.custom](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block) | resource | @@ -295,6 +317,7 @@ This project creates and manages resources within an AWS account for infrastruct | [aws_s3_bucket_public_access_block.infrastructure_ecs_cluster_service_build_pipeline_buildspec_store](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block) | resource | | [aws_s3_bucket_public_access_block.infrastructure_ecs_cluster_service_environment_files](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block) | resource | | [aws_s3_bucket_public_access_block.infrastructure_logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block) | resource | +| [aws_s3_bucket_public_access_block.infrastructure_rds_s3_backups](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block) | resource | | [aws_s3_bucket_public_access_block.infrastructure_vpc_transfer](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block) | resource | | [aws_s3_bucket_server_side_encryption_configuration.cloudformation_custom_stack_template_store](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_server_side_encryption_configuration) | resource | | [aws_s3_bucket_server_side_encryption_configuration.custom](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_server_side_encryption_configuration) | resource | @@ -303,6 +326,7 @@ This project creates and manages resources within an AWS account for infrastruct | [aws_s3_bucket_server_side_encryption_configuration.infrastructure_ecs_cluster_service_build_pipeline_buildspec_store](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_server_side_encryption_configuration) | resource | | [aws_s3_bucket_server_side_encryption_configuration.infrastructure_ecs_cluster_service_environment_files](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_server_side_encryption_configuration) | resource | | [aws_s3_bucket_server_side_encryption_configuration.infrastructure_logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_server_side_encryption_configuration) | resource | +| [aws_s3_bucket_server_side_encryption_configuration.infrastructure_rds_s3_backups](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_server_side_encryption_configuration) | resource | | [aws_s3_bucket_server_side_encryption_configuration.infrastructure_vpc_transfer](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_server_side_encryption_configuration) | resource | | [aws_s3_bucket_versioning.cloudformation_custom_stack_template_store](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_versioning) | resource | | [aws_s3_bucket_versioning.custom](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_versioning) | resource | @@ -311,6 +335,7 @@ This project creates and manages resources within an AWS account for infrastruct | [aws_s3_bucket_versioning.infrastructure_ecs_cluster_service_build_pipeline_buildspec_store](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_versioning) | resource | | [aws_s3_bucket_versioning.infrastructure_ecs_cluster_service_environment_files](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_versioning) | resource | | [aws_s3_bucket_versioning.infrastructure_logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_versioning) | resource | +| [aws_s3_bucket_versioning.infrastructure_rds_s3_backups](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_versioning) | resource | | [aws_s3_bucket_versioning.infrastructure_vpc_transfer](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_versioning) | resource | | [aws_s3_object.infrastructure_ecs_cluster_service_build_pipeline_buildspec_store_files](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_object) | resource | | [aws_secretsmanager_secret.infrastructure_rds_root_password](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret) | resource | @@ -320,6 +345,7 @@ This project creates and manages resources within an AWS account for infrastruct | [aws_security_group.infrastructure_ecs_cluster_service_alb](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | | [aws_security_group.infrastructure_elasticache](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | | [aws_security_group.infrastructure_rds](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | +| [aws_security_group.infrastructure_rds_s3_backups_scheduled_task](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | | [aws_security_group_rule.infrastructure_ecs_cluster_container_instances_custom](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | | [aws_security_group_rule.infrastructure_ecs_cluster_container_instances_egress_dns_tcp](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | | [aws_security_group_rule.infrastructure_ecs_cluster_container_instances_egress_dns_udp](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | @@ -336,6 +362,12 @@ This project creates and manages resources within an AWS account for infrastruct | [aws_security_group_rule.infrastructure_ecs_cluster_service_alb_https](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | | [aws_security_group_rule.infrastructure_elasticache_ingress_tcp](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | | [aws_security_group_rule.infrastructure_rds_ingress_tcp](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | +| [aws_security_group_rule.infrastructure_rds_s3_backup_task_ingress_tcp](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | +| [aws_security_group_rule.infrastructure_rds_s3_backups_scheduled_task_egress_dns_tcp](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | +| [aws_security_group_rule.infrastructure_rds_s3_backups_scheduled_task_egress_dns_udp](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | +| [aws_security_group_rule.infrastructure_rds_s3_backups_scheduled_task_egress_https_tcp](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | +| [aws_security_group_rule.infrastructure_rds_s3_backups_scheduled_task_egress_https_udp](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | +| [aws_security_group_rule.infrastructure_rds_s3_backups_scheduled_task_egress_rds](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | | [aws_sns_topic.infrastructure_ecs_cluster_autoscaling_lifecycle_termination](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic) | resource | | [aws_sns_topic_subscription.ecs_cluster_infrastructure_draining_autoscaling_lifecycle_termination](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic_subscription) | resource | | [aws_ssm_document.infrastructure_vpc_transfer_s3_download](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssm_document) | resource | @@ -388,6 +420,7 @@ This project creates and manages resources within an AWS account for infrastruct | [enable\_infrastructure\_ecs\_cluster\_efs](#input\_enable\_infrastructure\_ecs\_cluster\_efs) | Conditionally create and mount EFS to the ECS cluster instances | `bool` | n/a | yes | | [enable\_infrastructure\_ecs\_cluster\_pending\_task\_alert](#input\_enable\_infrastructure\_ecs\_cluster\_pending\_task\_alert) | Enable the ECS Cluster pending task alert | `bool` | n/a | yes | | [enable\_infrastructure\_ecs\_cluster\_services\_alb\_logs](#input\_enable\_infrastructure\_ecs\_cluster\_services\_alb\_logs) | Enable Infrastructure ECS cluster services ALB logs | `bool` | n/a | yes | +| [enable\_infrastructure\_rds\_backup\_to\_s3](#input\_enable\_infrastructure\_rds\_backup\_to\_s3) | Enable Infrastructure RDS backups to S3. This will create a scheduled Fargate task to take SQL dumps and upload them to S3 | `bool` | n/a | yes | | [enable\_infrastructure\_route53\_hosted\_zone](#input\_enable\_infrastructure\_route53\_hosted\_zone) | Creates a Route53 hosted zone, where DNS records will be created for resources launched within this module. | `bool` | n/a | yes | | [enable\_infrastructure\_vpc\_transfer\_s3\_bucket](#input\_enable\_infrastructure\_vpc\_transfer\_s3\_bucket) | Enable VPC transfer S3 bucket. This allows uploading/downloading files from resources within the infrastructure VPC | `bool` | n/a | yes | | [environment](#input\_environment) | The environment name to be used as part of the resource prefix | `string` | n/a | yes | @@ -440,6 +473,8 @@ This project creates and manages resources within an AWS account for infrastruct | [infrastructure\_logging\_bucket\_retention](#input\_infrastructure\_logging\_bucket\_retention) | Retention in days for the infrasrtucture S3 logs. This is for the default S3 logs bucket, where all AWS service logs will be delivered | `number` | n/a | yes | | [infrastructure\_name](#input\_infrastructure\_name) | The infrastructure name to be used as part of the resource prefix | `string` | n/a | yes | | [infrastructure\_rds](#input\_infrastructure\_rds) | Map of RDSs (The key will be the rds name). Values in here will override `infrastructure_rds_defaults` values if set."
{
rds-name = {
type: Choose either `instance` for RDS instance, or `cluster` for RDS Aurora
engine: RDS engine (Either `mysql` or `postgres`)
engine\_version: RDS Engine version (Specify the major version only, to prevent terraform attempting to downgrade minor versions)
parameters: Map of Parameters for the DB parameter group ({ parameter-name = parameter-value, ... })
instance\_class: RDS instance class
allocated\_storage: RDS allocated storage
storage\_type: RDS storage type
iops: RDS iops (When `type` is `instance`, this is only required for storage type of `io1` or `gp3` - When `cluster`, this must be a multiple between .5 and 50 of the storage amount for the DB cluster.`)
storage_throughput: RDS storage throughput (Only required when `storage\_type` is `gp3`. Only applicable for `type` of `instance`)
multi_az: Enable Multi-AZ RDS (Not applicable for `type` of `cluster`. For `cluster - set `storage_type`, `allocated_storage`, `iops` and `instance_class`)
monitoring\_interval: The interval, in seconds, between points when Enhanced Monitoring metrics are collected for the DB instance. Valid Values: 0, 1, 5, 10, 15, 30, 60.
cloudwatch\_logs\_export\_types: List of log types to enable for exporting to CloudWatch Logs. See `EnableCloudwatchLogsExports.member.N` (https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_CreateDBInstance.html) for valid values.
cluster\_instance\_count: Number of instances to launch within the Aurora DB cluster
cluster\_serverlessv2\_min\_capacity: Minimum capacity for an Aurora DB cluster
cluster\_serverlessv2\_max\_capacity: Maximum capacity for an Aurora DB cluster
}
} |
map(object({
type = optional(string, null)
engine = optional(string, null)
engine_version = optional(string, null)
parameters = optional(map(string), null)
instance_class = optional(string, null)
allocated_storage = optional(number, null)
storage_type = optional(string, null)
iops = optional(number, null)
storage_throughput = optional(number, null)
multi_az = optional(bool, null)
monitoring_interval = optional(number, null)
cloudwatch_logs_export_types = optional(list(string), null)
cluster_instance_count = optional(number, null)
cluster_serverlessv2_min_capacity = optional(number, null)
cluster_serverlessv2_max_capacity = optional(number, null)
}))
| n/a | yes | +| [infrastructure\_rds\_backup\_to\_s3\_cron\_expression](#input\_infrastructure\_rds\_backup\_to\_s3\_cron\_expression) | Cron expression for when to trigger the SQL backups to S3 | `string` | n/a | yes | +| [infrastructure\_rds\_backup\_to\_s3\_retention](#input\_infrastructure\_rds\_backup\_to\_s3\_retention) | Retention in days to keep the S3 SQL backups and logs | `number` | n/a | yes | | [infrastructure\_rds\_defaults](#input\_infrastructure\_rds\_defaults) | Default values for RDSs |
object({
type = optional(string, null)
engine = optional(string, null)
engine_version = optional(string, null)
parameters = optional(map(string), null)
instance_class = optional(string, null)
allocated_storage = optional(number, null)
storage_type = optional(string, null)
iops = optional(number, null)
storage_throughput = optional(number, null)
multi_az = optional(bool, null)
monitoring_interval = optional(number, null)
cloudwatch_logs_export_types = optional(list(string), null)
cluster_instance_count = optional(number, null)
cluster_serverlessv2_min_capacity = optional(number, null)
cluster_serverlessv2_max_capacity = optional(number, null)
})
| n/a | yes | | [infrastructure\_vpc](#input\_infrastructure\_vpc) | Enable infrastructure VPC | `bool` | n/a | yes | | [infrastructure\_vpc\_assign\_generated\_ipv6\_cidr\_block](#input\_infrastructure\_vpc\_assign\_generated\_ipv6\_cidr\_block) | Assign generated IPv6 CIDR block on infrastructure VPC | `bool` | n/a | yes | diff --git a/kms-infrastructure.tf b/kms-infrastructure.tf index 6571c58..ed22a60 100644 --- a/kms-infrastructure.tf +++ b/kms-infrastructure.tf @@ -46,6 +46,18 @@ resource "aws_kms_key" "infrastructure" { for k, v in local.infrastructure_ecs_cluster_services : aws_iam_role.infrastructure_ecs_cluster_service_task_execution[k].arn if v["enable_execute_command"] == true && local.infrastructure_ecs_cluster_enable_execute_command_logging ]) } + )}${length(local.infrastructure_rds) > 0 && local.infrastructure_kms_encryption && local.enable_infrastructure_rds_backup_to_s3 ? "," : ""} + ${templatefile("${path.root}/policies/kms-key-policy-statements/role-allow-encrypt.json.tpl", + { + role_arns = jsonencode([ + for k, v in local.infrastructure_rds : aws_iam_role.infrastructure_rds_s3_backups_task[k].arn if local.enable_infrastructure_rds_backup_to_s3 + ]) + } + )}${length(local.infrastructure_rds) > 0 && local.infrastructure_kms_encryption && local.enable_infrastructure_rds_backup_to_s3 ? "," : ""} + ${templatefile("${path.root}/policies/kms-key-policy-statements/cloudwatch-logs-allow.json.tpl", + { + log_group_arn = length(local.infrastructure_rds) > 0 && local.infrastructure_kms_encryption && local.enable_infrastructure_rds_backup_to_s3 ? "arn:aws:logs:${local.aws_region}:${local.aws_account_id}:log-group:${local.resource_prefix}-infrastructure-rds-s3-backups-*" : "" + } )}${contains([for k, v in local.custom_s3_buckets : (v["cloudfront_dedicated_distribution"] == true || v["cloudfront_infrastructure_ecs_cluster_service"] != null) && v["create_dedicated_kms_key"] == false ? true : false], true) && local.infrastructure_kms_encryption ? "," : ""} ${templatefile("${path.root}/policies/kms-key-policy-statements/cloudfront-distribution-allow.json.tpl", { diff --git a/locals.tf b/locals.tf index 0b1cbe0..08bd7d6 100644 --- a/locals.tf +++ b/locals.tf @@ -30,12 +30,14 @@ locals { length(local.custom_s3_buckets) != 0 || local.enable_cloudformatian_s3_template_store || local.enable_infrastructure_vpc_transfer_s3_bucket || - local.infrastructure_ecs_cluster_enable_execute_command_logging + local.infrastructure_ecs_cluster_enable_execute_command_logging || + local.enable_infrastructure_rds_backup_to_s3 ) logs_bucket_s3_source_arns = concat( length(local.infrastructure_ecs_cluster_services) != 0 ? [aws_s3_bucket.infrastructure_ecs_cluster_service_build_pipeline_artifact_store[0].arn] : [], local.enable_infrastructure_vpc_transfer_s3_bucket ? [aws_s3_bucket.infrastructure_vpc_transfer[0].arn] : [], - [for k, v in local.custom_s3_buckets : aws_s3_bucket.custom[k].arn] + [for k, v in local.custom_s3_buckets : aws_s3_bucket.custom[k].arn], + local.enable_infrastructure_rds_backup_to_s3 ? [aws_s3_bucket.infrastructure_rds_s3_backups[0].arn] : [], ) logs_bucket_logs_source_arns = concat( local.infrastructure_vpc_flow_logs_s3_with_athena ? ["arn:aws:logs:${local.aws_region}:${local.aws_account_id}:*"] : [] @@ -232,6 +234,17 @@ locals { "mysql" = 3306 "postgres" = 5432 } + rds_s3_backups_container_entrypoint = { + "mysql" = "" + "postgres" = "" + } + enable_infrastructure_rds_backup_to_s3 = var.enable_infrastructure_rds_backup_to_s3 + infrastructure_rds_backup_to_s3_cron_expression = var.infrastructure_rds_backup_to_s3_cron_expression + infrastructure_rds_backup_to_s3_retention = var.infrastructure_rds_backup_to_s3_retention + enable_infrastructure_rds_tooling_ecs_cluster = anytrue([ + local.enable_infrastructure_rds_backup_to_s3, + ]) + infrastructure_rds_tooling_ecs_cluster_name = "${local.resource_prefix}-infrastructure-rds-tooling" infrastructure_elasticache_defaults = var.infrastructure_elasticache_defaults infrastructure_elasticache_keys = length(var.infrastructure_elasticache) > 0 ? keys(values(var.infrastructure_elasticache)[0]) : [] diff --git a/policies/secrets-manager-get-secret-value.json.tpl b/policies/secrets-manager-get-secret-value.json.tpl new file mode 100644 index 0000000..bb86b25 --- /dev/null +++ b/policies/secrets-manager-get-secret-value.json.tpl @@ -0,0 +1,12 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "secretsmanager:GetSecretValue" + ], + "Resource": ${secret_name_arns} + } + ] +} diff --git a/rds-infrastructure-cloudwatch-logs.tf b/rds-infrastructure-cloudwatch-logs.tf index 63641b4..c35954a 100644 --- a/rds-infrastructure-cloudwatch-logs.tf +++ b/rds-infrastructure-cloudwatch-logs.tf @@ -10,3 +10,12 @@ resource "aws_cloudwatch_log_group" "infrastructure_rds_exports" { retention_in_days = 30 kms_key_id = local.infrastructure_kms_encryption ? aws_kms_key.infrastructure[0].id : null } + +resource "aws_cloudwatch_log_group" "infrastructure_rds_s3_backups" { + for_each = local.enable_infrastructure_rds_backup_to_s3 ? local.infrastructure_rds : {} + + name = "${local.resource_prefix}-infrastructure-rds-s3-backups-${each.key}" + retention_in_days = local.infrastructure_rds_backup_to_s3_retention + kms_key_id = local.infrastructure_kms_encryption ? aws_kms_key.infrastructure[0].arn : null + skip_destroy = true +} diff --git a/rds-infrastructure-s3-backups-ecr.tf b/rds-infrastructure-s3-backups-ecr.tf new file mode 100644 index 0000000..4312164 --- /dev/null +++ b/rds-infrastructure-s3-backups-ecr.tf @@ -0,0 +1,17 @@ +resource "aws_ecr_repository" "infrastructure_rds_s3_backups" { + count = local.enable_infrastructure_rds_backup_to_s3 ? 1 : 0 + + name = "${local.resource_prefix}-rds-s3-backups" + + #tfsec:ignore:aws-ecr-enforce-immutable-repository + image_tag_mutability = "MUTABLE" + + encryption_configuration { + encryption_type = local.infrastructure_kms_encryption ? "KMS" : "AES256" + kms_key = local.infrastructure_kms_encryption ? aws_kms_key.infrastructure[0].arn : null + } + + image_scanning_configuration { + scan_on_push = true + } +} diff --git a/rds-infrastructure-s3-backups-s3.tf b/rds-infrastructure-s3-backups-s3.tf new file mode 100644 index 0000000..3698226 --- /dev/null +++ b/rds-infrastructure-s3-backups-s3.tf @@ -0,0 +1,87 @@ +resource "aws_s3_bucket" "infrastructure_rds_s3_backups" { + count = local.enable_infrastructure_rds_backup_to_s3 ? 1 : 0 + + bucket = "${local.resource_prefix_hash}-infrastructure-rds-s3-backups" +} + +resource "aws_s3_bucket_policy" "infrastructure_rds_s3_backups" { + count = local.enable_infrastructure_rds_backup_to_s3 ? 1 : 0 + + bucket = aws_s3_bucket.infrastructure_rds_s3_backups[0].id + policy = templatefile( + "${path.module}/policies/s3-bucket-policy.json.tpl", + { + statement = <