From 0be26b272a9f9d93af590a625313c01cc851f23d Mon Sep 17 00:00:00 2001 From: N P Date: Sat, 7 May 2022 16:02:09 +0200 Subject: [PATCH 1/3] fix(healthcheck): Variablizes healthcheck --- ecs.tf | 37 +++++------ task-definitions/wordpress.json | 107 ++++++++++++++++---------------- variables.tf | 6 ++ 3 files changed, 79 insertions(+), 71 deletions(-) diff --git a/ecs.tf b/ecs.tf index 13a65e3..477c787 100644 --- a/ecs.tf +++ b/ecs.tf @@ -106,24 +106,25 @@ resource "aws_cloudwatch_log_group" "wordpress_container" { resource "aws_ecs_task_definition" "wordpress_container" { family = "${var.site_name}_wordpress" container_definitions = templatefile("${path.module}/task-definitions/wordpress.json", { - db_host = aws_rds_cluster.serverless_wordpress.endpoint, - db_user = aws_rds_cluster.serverless_wordpress.master_username, - db_password = random_password.serverless_wordpress_password.result, - db_name = aws_rds_cluster.serverless_wordpress.database_name, - wordpress_image = "${aws_ecr_repository.serverless_wordpress.repository_url}:latest", - wp_dest = "https://${var.site_prefix}.${var.site_domain}", - wp_region = var.s3_region, - wp_bucket = module.cloudfront.wordpress_bucket_id, - container_dns = "${var.wordpress_subdomain}.${var.site_domain}", - container_dns_zone = var.hosted_zone_id, - container_cpu = var.ecs_cpu, - container_memory = var.ecs_memory - efs_source_volume = "${var.site_name}_wordpress_persistent" - wordpress_admin_user = var.wordpress_admin_user - wordpress_admin_password = var.wordpress_admin_password - wordpress_admin_email = var.wordpress_admin_email - site_name = var.site_name - wordpress_memory_limit = var.wordpress_memory_limit + db_host = aws_rds_cluster.serverless_wordpress.endpoint + db_user = aws_rds_cluster.serverless_wordpress.master_username + db_password = random_password.serverless_wordpress_password.result + db_name = aws_rds_cluster.serverless_wordpress.database_name + wordpress_image = "${aws_ecr_repository.serverless_wordpress.repository_url}:latest" + wp_dest = "https://${var.site_prefix}.${var.site_domain}" + wp_region = var.s3_region + wp_bucket = module.cloudfront.wordpress_bucket_id + container_dns = "${var.wordpress_subdomain}.${var.site_domain}" + container_dns_zone = var.hosted_zone_id + container_cpu = var.ecs_cpu + container_memory = var.ecs_memory + container_healthcheck_enabled = var.ecs_healthcheck_enabled + efs_source_volume = "${var.site_name}_wordpress_persistent" + wordpress_admin_user = var.wordpress_admin_user + wordpress_admin_password = var.wordpress_admin_password + wordpress_admin_email = var.wordpress_admin_email + site_name = var.site_name + wordpress_memory_limit = var.wordpress_memory_limit }) runtime_platform { diff --git a/task-definitions/wordpress.json b/task-definitions/wordpress.json index 543e596..13b4b32 100644 --- a/task-definitions/wordpress.json +++ b/task-definitions/wordpress.json @@ -1,56 +1,57 @@ [ - ${jsonencode({ - "cpu": tonumber(container_cpu), - "environment": [ - {"name": "ECS_ENABLE_CONTAINER_METADATA", "value": "true"}, - {"name": "WORDPRESS_DB_HOST", "value": "${db_host}"}, - {"name": "WORDPRESS_DB_USER", "value": "${db_user}"}, - {"name": "WORDPRESS_DB_PASSWORD", "value": "${db_password}"}, - {"name": "WORDPRESS_DB_NAME", "value": "${db_name}"}, - {"name": "WPSTATIC_DEST", "value": "${wp_dest}"}, - {"name": "WPSTATIC_REGION", "value": "${wp_region}"}, - {"name": "WPSTATIC_BUCKET", "value": "${wp_bucket}"}, - {"name": "CONTAINER_DNS", "value": "${container_dns}"}, - {"name": "CONTAINER_DNS_ZONE", "value": "${container_dns_zone}"}, - {"name": "WORDPRESS_ADMIN_USER", "value": "${wordpress_admin_user}"}, - {"name": "WORDPRESS_ADMIN_PASSWORD", "value": "${wordpress_admin_password}"}, - {"name": "WORDPRESS_ADMIN_EMAIL", "value": "${wordpress_admin_email}"}, - {"name": "WP_MEMORY_LIMIT", "value": "${wordpress_memory_limit}"} - ], - "essential": true, - "image": "${wordpress_image}", - "memory": tonumber(container_memory), - "name": "wordpress", - "portMappings": [ - { - "containerPort": 80, - "hostPort": 80, - "protocol": "tcp" + { + "cpu": ${tonumber(container_cpu)}, + "environment": [ + {"name": "ECS_ENABLE_CONTAINER_METADATA", "value": "true"}, + {"name": "WORDPRESS_DB_HOST", "value": "${db_host}"}, + {"name": "WORDPRESS_DB_USER", "value": "${db_user}"}, + {"name": "WORDPRESS_DB_PASSWORD", "value": "${db_password}"}, + {"name": "WORDPRESS_DB_NAME", "value": "${db_name}"}, + {"name": "WPSTATIC_DEST", "value": "${wp_dest}"}, + {"name": "WPSTATIC_REGION", "value": "${wp_region}"}, + {"name": "WPSTATIC_BUCKET", "value": "${wp_bucket}"}, + {"name": "CONTAINER_DNS", "value": "${container_dns}"}, + {"name": "CONTAINER_DNS_ZONE", "value": "${container_dns_zone}"}, + {"name": "WORDPRESS_ADMIN_USER", "value": "${wordpress_admin_user}"}, + {"name": "WORDPRESS_ADMIN_PASSWORD", "value": "${wordpress_admin_password}"}, + {"name": "WORDPRESS_ADMIN_EMAIL", "value": "${wordpress_admin_email}"}, + {"name": "WP_MEMORY_LIMIT", "value": "${wordpress_memory_limit}"} + ], + "essential": true, + "image": "${wordpress_image}", + "memory": ${tonumber(container_memory)}, + "name": "wordpress", + "portMappings": [ + { + "containerPort": 80, + "hostPort": 80, + "protocol": "tcp" + } + ], + "mountPoints" : [ + { + "sourceVolume": "${efs_source_volume}", + "containerPath": "/var/www/html", + "readOnly": false + } + ], + %{if container_healthcheck_enabled } + "healthCheck": { + "retries": 10, + "command": [ "CMD-SHELL", "curl -f http://localhost:80/ || exit 1" ], + "timeout": 5, + "interval": 10, + "startPeriod": 60 + }, + %{ endif } + "volumesFrom" : [], + "logConfiguration": { + "logDriver": "awslogs", + "options": { + "awslogs-group": "/aws/ecs/${site_name}-serverless-wordpress-container", + "awslogs-region": "${wp_region}", + "awslogs-stream-prefix": "ecs" + } } - ], - "mountPoints" : [ - { - "sourceVolume": "${efs_source_volume}", - "containerPath": "/var/www/html", - "readOnly": false - } - ], - "healthCheck": { - "retries": 10, - "command": [ "CMD-SHELL", "curl -f http://localhost:80/ || exit 1" ], - "timeout": 5, - "interval": 10, - "startPeriod": 60 - }, - "volumesFrom" : [], - "logConfiguration": { - "logDriver": "awslogs", - "options": { - "awslogs-group": "/aws/ecs/${site_name}-serverless-wordpress-container", - "awslogs-region": "${wp_region}", - "awslogs-stream-prefix": "ecs" - } - } - })} - + } ] diff --git a/variables.tf b/variables.tf index b9f204e..43a4fee 100644 --- a/variables.tf +++ b/variables.tf @@ -79,6 +79,12 @@ variable "ecs_memory" { description = "The memory limit password to the Wordpress container definition." } +variable "ecs_healthcheck_enabled" { + default = true + description = "Runs an healtchcheck against the container." + type = bool +} + variable "snapshot_identifier" { description = "To create the RDS cluster from a previous snapshot in the same region, specify it by name." type = string From 5e34af3079e7713fb16444bcf0600280e31eaea6 Mon Sep 17 00:00:00 2001 From: N P Date: Sat, 7 May 2022 17:02:49 +0200 Subject: [PATCH 2/3] feat(ecs-exec): Enables ECS Exec support --- README.md | 7 +++++++ ecs.tf | 36 ++++++++++++++++++++++++++++----- task-definitions/wordpress.json | 3 +++ 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index beae3d8..d57c041 100644 --- a/README.md +++ b/README.md @@ -223,6 +223,13 @@ that generates this file and the crawl job can fail fast if it cannot locate it. relating to WP2Static, [raise an issue on their repo](https://github.com/leonstafford/wp2static/issues). For any issues relating to this module, [raise an issue against this repo.](https://github.com/TechToSpeech/terraform-aws-serverless-static-wordpress/issues) + +### Connecting to container with ECS Exec + +ECS Exec is supported to help troubleshooting container issues. Read to [AWS Docs](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-exec.html) for usage instructions. + +It's recommended that the `ecs_healthcheck_enabled` variable is set to `false` to prevent the container from being terminated and replaced while troubleshooting. + ## Inputs | Name | Description | Type | Default | Required | diff --git a/ecs.tf b/ecs.tf index 477c787..c1bf48e 100644 --- a/ecs.tf +++ b/ecs.tf @@ -44,6 +44,19 @@ data "aws_iam_policy_document" "wordpress_bucket_access" { } } +data "aws_iam_policy_document" "wordpress_ecs_exec" { + statement { + actions = [ + "ssmmessages:CreateControlChannel", + "ssmmessages:CreateDataChannel", + "ssmmessages:OpenControlChannel", + "ssmmessages:OpenDataChannel" + ] + effect = "Allow" + resources = ["*"] + } +} + resource "aws_iam_policy" "wordpress_bucket_access" { name = "${var.site_name}_WordpressBucketAccess" description = "The role that allows Wordpress task to do necessary operations" @@ -55,6 +68,17 @@ resource "aws_iam_role_policy_attachment" "wordpress_bucket_access" { policy_arn = aws_iam_policy.wordpress_bucket_access.arn } +resource "aws_iam_policy" "wordpress_ecs_exec" { + name = "${var.site_name}_WordpressECSExec" + description = "Allows ECS Exec to the Wordpress container" + policy = data.aws_iam_policy_document.wordpress_ecs_exec.json +} + +resource "aws_iam_role_policy_attachment" "wordpress_ecs_exec" { + role = aws_iam_role.wordpress_task.name + policy_arn = aws_iam_policy.wordpress_ecs_exec.arn +} + resource "aws_iam_role" "wordpress_task" { name = "${var.site_name}_WordpressTaskRole" assume_role_policy = data.aws_iam_policy_document.ecs_assume_role_policy.json @@ -221,10 +245,12 @@ resource "aws_security_group_rule" "wordpress_sg_egress_3306" { resource "aws_ecs_service" "wordpress_service" { - name = "${var.site_name}_wordpress" - task_definition = "${aws_ecs_task_definition.wordpress_container.family}:${aws_ecs_task_definition.wordpress_container.revision}" - cluster = aws_ecs_cluster.wordpress_cluster.arn - desired_count = var.launch + name = "${var.site_name}_wordpress" + task_definition = "${aws_ecs_task_definition.wordpress_container.family}:${aws_ecs_task_definition.wordpress_container.revision}" + cluster = aws_ecs_cluster.wordpress_cluster.arn + desired_count = var.launch + enable_execute_command = true + # iam_role = capacity_provider_strategy { capacity_provider = var.graviton_fargate_enabled ? (contains(local.graviton_fargate_regions_unsupported, data.aws_region.current) ? "FARGATE_SPOT" : "FARGATE") : "FARGATE_SPOT" @@ -234,7 +260,7 @@ resource "aws_ecs_service" "wordpress_service" { propagate_tags = "SERVICE" # Explicitly setting version here: https://stackoverflow.com/questions/62552562/one-or-more-of-the-requested-capabilities-are-not-supported-aws-fargate platform_version = "1.4.0" - + network_configuration { subnets = var.subnet_ids security_groups = [aws_security_group.wordpress_security_group.id] diff --git a/task-definitions/wordpress.json b/task-definitions/wordpress.json index 13b4b32..472c255 100644 --- a/task-definitions/wordpress.json +++ b/task-definitions/wordpress.json @@ -52,6 +52,9 @@ "awslogs-region": "${wp_region}", "awslogs-stream-prefix": "ecs" } + }, + "linuxParameters": { + "initProcessEnabled": true } } ] From 2f5f6938900ed741937688057c070cb91c4e54dc Mon Sep 17 00:00:00 2001 From: Linter Bot Date: Sat, 7 May 2022 15:05:43 +0000 Subject: [PATCH 3/3] Apply automatic changes --- README.md | 35 ++++++++++++++++++++++++++------- ecs.tf | 4 ++-- main.tf | 2 +- modules/codebuild/README.md | 2 +- task-definitions/wordpress.json | 4 ++-- variables.tf | 2 +- 6 files changed, 35 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index d57c041..bd0419c 100644 --- a/README.md +++ b/README.md @@ -210,6 +210,28 @@ in your module definition. Gentle reminder that no backup options are currently bundled with this module - the most effective means would be to generate and retain a backup from within Wordpress for maximum flexibility. We recommend the UpdraftPlus plugin. +## Permanent Redirects + +Basic url path based permanent redirects are supported via the CloudFront function. The variable `cloudfront_function_301_redirects` can be set with a custom map of match to destination mappings. + +Some aspects that need to be taken into consideration for the match: + +* It's a regular expression +* Group replacements are supported +* Runs in a Javascript function, escaping needs to be taken into consideration +* Passed through a TF var, so escaping that needs to be taking into account as well + +An example to match a path like `/category-name`, a suitable match would be `"^\\/(category-name)$"`. Breaking down the `\\/` part, the first `\` tells TF to escape the second `\`, which is the Regex escape for the `/` character. + +An example: + +``` +cloudfront_function_301_redirects = { + # Redirects /travel to /category/travel/ + "^\\/(travel)$": "/category/$1/", +} +``` + ## Troubleshooting If you experience issues with the publish element of WP2Static, you can retry. It can be more reliable to proceed to @@ -223,13 +245,6 @@ that generates this file and the crawl job can fail fast if it cannot locate it. relating to WP2Static, [raise an issue on their repo](https://github.com/leonstafford/wp2static/issues). For any issues relating to this module, [raise an issue against this repo.](https://github.com/TechToSpeech/terraform-aws-serverless-static-wordpress/issues) - -### Connecting to container with ECS Exec - -ECS Exec is supported to help troubleshooting container issues. Read to [AWS Docs](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-exec.html) for usage instructions. - -It's recommended that the `ecs_healthcheck_enabled` variable is set to `false` to prevent the container from being terminated and replaced while troubleshooting. - ## Inputs | Name | Description | Type | Default | Required | @@ -239,6 +254,7 @@ It's recommended that the `ecs_healthcheck_enabled` variable is set to `false` t | [cloudfront\_class](#input\_cloudfront\_class) | The [price class](https://aws.amazon.com/cloudfront/pricing/) for the distribution. One of: PriceClass\_All, PriceClass\_200, PriceClass\_100 | `string` | `"PriceClass_All"` | no | | [cloudfront\_function\_301\_redirects](#input\_cloudfront\_function\_301\_redirects) | A list of key value pairs of Regex match and destination for 301 redirects at CloudFront. | `map(any)` |
{
"^(.*)index\\.php$": "$1"
}
| no | | [ecs\_cpu](#input\_ecs\_cpu) | The CPU limit password to the Wordpress container definition. | `number` | `256` | no | +| [ecs\_healthcheck\_enabled](#input\_ecs\_healthcheck\_enabled) | Runs an healtchcheck against the container. | `bool` | `true` | no | | [ecs\_memory](#input\_ecs\_memory) | The memory limit password to the Wordpress container definition. | `number` | `512` | no | | [graviton\_codebuild\_enabled](#input\_graviton\_codebuild\_enabled) | Flag that controls whether CodeBuild should use Graviton-based build agents in [supported regions](https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-compute-types.html). | `bool` | `false` | no | | [graviton\_fargate\_enabled](#input\_graviton\_fargate\_enabled) | Flag that controls whether ECS Fargate should use Graviton-based containers in [supported regions]https://docs.aws.amazon.com/AmazonECS/latest/developerguide/AWS_Fargate-Regions.html). | `bool` | `false` | no | @@ -259,6 +275,8 @@ It's recommended that the `ecs_healthcheck_enabled` variable is set to `false` t | [wordpress\_admin\_user](#input\_wordpress\_admin\_user) | The username of the default wordpress admin user. | `string` | `"supervisor"` | no | | [wordpress\_memory\_limit](#input\_wordpress\_memory\_limit) | The memory to allow the Wordpress process to use (in M) | `string` | `"256M"` | no | | [wordpress\_subdomain](#input\_wordpress\_subdomain) | The subdomain used for the Wordpress container. | `string` | `"wordpress"` | no | +| [wp2static\_s3\_addon\_version](#input\_wp2static\_s3\_addon\_version) | Version of the WP2Static S3 Add-on to use from https://github.com/leonstafford/wp2static-addon-s3/releases/ | `string` | `"1.0"` | no | +| [wp2static\_version](#input\_wp2static\_version) | Version of WP2Static to use from https://github.com/WP2Static/wp2static/releases | `string` | `"7.1.7"` | no | ## Modules | Name | Source | Version | @@ -300,8 +318,10 @@ It's recommended that the `ecs_healthcheck_enabled` variable is set to `false` t | [aws_efs_file_system.wordpress_persistent](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/efs_file_system) | resource | | [aws_efs_mount_target.wordpress_efs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/efs_mount_target) | resource | | [aws_iam_policy.wordpress_bucket_access](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_policy.wordpress_ecs_exec](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | | [aws_iam_role.wordpress_task](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | [aws_iam_role_policy_attachment.wordpress_bucket_access](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_iam_role_policy_attachment.wordpress_ecs_exec](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_iam_role_policy_attachment.wordpress_role_attachment_cloudwatch](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_iam_role_policy_attachment.wordpress_role_attachment_ecs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_rds_cluster.serverless_wordpress](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster) | resource | @@ -322,5 +342,6 @@ It's recommended that the `ecs_healthcheck_enabled` variable is set to `false` t | [random_password.serverless_wordpress_password](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource | | [aws_iam_policy_document.ecs_assume_role_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.wordpress_bucket_access](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.wordpress_ecs_exec](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | diff --git a/ecs.tf b/ecs.tf index c1bf48e..75c217d 100644 --- a/ecs.tf +++ b/ecs.tf @@ -46,7 +46,7 @@ data "aws_iam_policy_document" "wordpress_bucket_access" { data "aws_iam_policy_document" "wordpress_ecs_exec" { statement { - actions = [ + actions = [ "ssmmessages:CreateControlChannel", "ssmmessages:CreateDataChannel", "ssmmessages:OpenControlChannel", @@ -260,7 +260,7 @@ resource "aws_ecs_service" "wordpress_service" { propagate_tags = "SERVICE" # Explicitly setting version here: https://stackoverflow.com/questions/62552562/one-or-more-of-the-requested-capabilities-are-not-supported-aws-fargate platform_version = "1.4.0" - + network_configuration { subnets = var.subnet_ids security_groups = [aws_security_group.wordpress_security_group.id] diff --git a/main.tf b/main.tf index be2e09b..572f1b5 100644 --- a/main.tf +++ b/main.tf @@ -31,7 +31,7 @@ module "cloudfront" { } depends_on = [aws_acm_certificate_validation.wordpress_site, module.waf] - + cloudfront_class = var.cloudfront_class waf_acl_arn = var.waf_enabled ? module.waf[0].waf_acl_arn : null cloudfront_function_301_redirects = var.cloudfront_function_301_redirects diff --git a/modules/codebuild/README.md b/modules/codebuild/README.md index 3797cc4..4ff068e 100644 --- a/modules/codebuild/README.md +++ b/modules/codebuild/README.md @@ -16,7 +16,7 @@ This module sets up the build to take a vanilla Wordpress image and bake customi | [site\_name](#input\_site\_name) | The unique name for this instance of the module. Required to deploy multiple wordpress instances to the same AWS account (if desired). | `string` | n/a | yes | | [wordpress\_ecr\_repository](#input\_wordpress\_ecr\_repository) | The ECR repository where the Wordpress image is stored. | `string` | n/a | yes | | [wp2static\_s3\_addon\_version](#input\_wp2static\_s3\_addon\_version) | Version of the WP2Static S3 Add-on to use from https://github.com/leonstafford/wp2static-addon-s3/releases/ | `string` | `"1.0"` | no | -| [wp2static\_version](#input\_wp2static\_version) | Version of WP2Static to use from https://github.com/leonstafford/wp2static/releases | `string` | `"7.1.7"` | no | +| [wp2static\_version](#input\_wp2static\_version) | Version of WP2Static to use from https://github.com/WP2Static/wp2static/releases | `string` | `"7.1.7"` | no | ## Modules No modules. diff --git a/task-definitions/wordpress.json b/task-definitions/wordpress.json index 472c255..64aa2d6 100644 --- a/task-definitions/wordpress.json +++ b/task-definitions/wordpress.json @@ -1,5 +1,5 @@ [ - { + { "cpu": ${tonumber(container_cpu)}, "environment": [ {"name": "ECS_ENABLE_CONTAINER_METADATA", "value": "true"}, @@ -42,7 +42,7 @@ "timeout": 5, "interval": 10, "startPeriod": 60 - }, + }, %{ endif } "volumesFrom" : [], "logConfiguration": { diff --git a/variables.tf b/variables.tf index 43a4fee..b8dc880 100644 --- a/variables.tf +++ b/variables.tf @@ -82,7 +82,7 @@ variable "ecs_memory" { variable "ecs_healthcheck_enabled" { default = true description = "Runs an healtchcheck against the container." - type = bool + type = bool } variable "snapshot_identifier" {