Skip to content

Give the ECS task role project-scoped S3 and Cognito access - #242

Merged
ale210 merged 2 commits into
mainfrom
204-project-scoped-s3-cognito-task-role
Sep 18, 2026
Merged

ale210 merged 2 commits into
mainfrom
204-project-scoped-s3-cognito-task-role

Conversation

@ale210

@ale210 ale210 commented Sep 18, 2026

Copy link
Copy Markdown
Member

Closes #204.

Adds two statements to the ECS task role's policy in modules/container, both scoped by the resource's project tag per decision 5 of DR-Machine-to-machine-IAM-scoping:

  • ProjectBucketAccess — s3:ListBucket, s3:GetObject, s3:PutObject, s3:DeleteObject on the project's own buckets.
  • ProjectCognitoAdmin — cognito-idp:AdminGetUser, AdminCreateUser, AdminAddUserToGroup, AdminDeleteUser on the project's own user pools.

This is the task role (aws_iam_role.instance), not the execution role — the identity application code runs as.

What to look for in the plan

Ten aws_iam_policy.<project>-<app>-<env>-task-policy resources updated in place. No adds, no destroys, no replacements. description is deliberately left as "" because it is ForceNew on aws_iam_policy and changing it would recreate all ten.

The existing ssmmessages statement is restyled to the unquoted HCL form used by execution_policy below it and given a Sid. That is cosmetic in IAM terms but does change the rendered policy document, so it shows up in the diff.

Why aws:ResourceTag and not s3:BucketTag

#194 left this open. Both work, and on an object ARN both read the bucket's tags. They differ only when access points are involved, and this account has none. aws:ResourceTag matches the decision record and the existing EcrPullProjectImages statement, so consistency decides it.

The S3 half grants nothing yet, by design

There is no per-project application bucket in the account today. S3 does not evaluate tag conditions against a bucket that has not opted in to ABAC, so ProjectBucketAccess is inert until a bucket is created, tagged, and given an aws_s3_bucket_abac resource. The module's header comment now documents those three steps, and that prose is injected into the README by the terraform-docs job.

ABAC was deliberately not enabled on any existing bucket. The two Terraform state buckets and two CloudTrail log buckets belong to no single project and correctly carry no project tag — leaving ABAC off is what keeps them out of reach. civictechindex.org is tagged, but it is a public static-website bucket that no container reads or writes, so opting it in would change how its tags are managed for no benefit.

Terraform can still manage tags after ABAC is enabled

The ticket asked for this to be checked before enabling ABAC anywhere. The provider handles it: aws_s3_bucket uses the S3 Control TagResource/UntagResource APIs when the caller holds s3:TagResource, s3:UntagResource and s3:ListTagsForResource (#45251). Simulated against a live bucket, incubator-tf-apply is allowed all three and incubator-tf-plan is allowed the read it needs. Nothing to grant.

Verification

The rendered policy was put through the IAM policy simulator:

Case Result
Bucket tagged project=vrms, bucket and object ARNs allowed
No project tag in context — an untagged bucket, or one with ABAC off — against the real hfla-incubator-terraform-state ARN implicitDeny on all four actions
Bucket tagged for a different project implicitDeny
Pool tagged project=vrms allowed
vrms-rendered policy against the Home Unite Us production pool implicitDeny on all four actions

The simulator uses supplied tag values, so this proves the policy logic rather than live tag state; live tags were checked separately with list-tags-for-resource.

terraform validate passes on the pinned 1.16.0 / provider 6.64.0, and terraform fmt reports no diff on the new code.

Post-merge

The negative test in the issue cannot be run from a branch and is an action item on #204 after this merges.

Worth knowing for whoever runs it: this changes nothing observable for Home Unite Us on its own. Both HUU environments pass COGNITO_ACCESS_ID/COGNITO_ACCESS_KEY as empty strings, but the deployed image (homeuniteus:2dc864ae50.20250220-172003, Feb 2025) predates the fallback that reaches for the task role when they are empty. That fallback is on HUU main but is not in the running image, so the Cognito grant takes effect only once that application ships a rebuild.

@github-actions

github-actions Bot commented Sep 18, 2026 •

Copy link
Copy Markdown
Contributor

Terraform plan in terraform
With backend config files: terraform/prod.backend.tfvars

Plan: 0 to add, 10 to change, 0 to destroy.
Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
!~  update in-place

Terraform will perform the following actions:

  # module.civic-tech-index.module.backend_prod_service.aws_iam_policy.container_policy will be updated in-place
!~  resource "aws_iam_policy" "container_policy" {
        id               = "arn:aws:iam::035866691871:policy/civic-tech-index-backend-prod-task-policy"
        name             = "civic-tech-index-backend-prod-task-policy"
!~      policy           = jsonencode(
!~          {
!~              Statement = [
!~                  {
+                       Sid      = "EcsExecuteCommand"
#                        (3 unchanged attributes hidden)
                    },
+                   {
+                       Action    = [
+                           "s3:ListBucket",
+                           "s3:GetObject",
+                           "s3:PutObject",
+                           "s3:DeleteObject",
                        ]
+                       Condition = {
+                           Null         = {
+                               "aws:ResourceTag/project" = "false"
                            }
+                           StringEquals = {
+                               "aws:ResourceTag/project" = "civic-tech-index"
                            }
                        }
+                       Effect    = "Allow"
+                       Resource  = [
+                           "arn:aws:s3:::*",
+                           "arn:aws:s3:::*/*",
                        ]
+                       Sid       = "ProjectBucketAccess"
                    },
+                   {
+                       Action    = [
+                           "cognito-idp:AdminGetUser",
+                           "cognito-idp:AdminCreateUser",
+                           "cognito-idp:AdminAddUserToGroup",
+                           "cognito-idp:AdminDeleteUser",
                        ]
+                       Condition = {
+                           StringEquals = {
+                               "aws:ResourceTag/project" = "civic-tech-index"
                            }
                        }
+                       Effect    = "Allow"
+                       Resource  = "arn:aws:cognito-idp:us-west-2:035866691871:userpool/*"
+                       Sid       = "ProjectCognitoAdmin"
                    },
                ]
#                (1 unchanged attribute hidden)
            }
        )
        tags             = {}
#        (7 unchanged attributes hidden)
    }

  # module.civic-tech-index.module.backend_stage_service.aws_iam_policy.container_policy will be updated in-place
!~  resource "aws_iam_policy" "container_policy" {
        id               = "arn:aws:iam::035866691871:policy/civic-tech-index-backend-stage-task-policy"
        name             = "civic-tech-index-backend-stage-task-policy"
!~      policy           = jsonencode(
!~          {
!~              Statement = [
!~                  {
+                       Sid      = "EcsExecuteCommand"
#                        (3 unchanged attributes hidden)
                    },
+                   {
+                       Action    = [
+                           "s3:ListBucket",
+                           "s3:GetObject",
+                           "s3:PutObject",
+                           "s3:DeleteObject",
                        ]
+                       Condition = {
+                           Null         = {
+                               "aws:ResourceTag/project" = "false"
                            }
+                           StringEquals = {
+                               "aws:ResourceTag/project" = "civic-tech-index"
                            }
                        }
+                       Effect    = "Allow"
+                       Resource  = [
+                           "arn:aws:s3:::*",
+                           "arn:aws:s3:::*/*",
                        ]
+                       Sid       = "ProjectBucketAccess"
                    },
+                   {
+                       Action    = [
+                           "cognito-idp:AdminGetUser",
+                           "cognito-idp:AdminCreateUser",
+                           "cognito-idp:AdminAddUserToGroup",
+                           "cognito-idp:AdminDeleteUser",
                        ]
+                       Condition = {
+                           StringEquals = {
+                               "aws:ResourceTag/project" = "civic-tech-index"
                            }
                        }
+                       Effect    = "Allow"
+                       Resource  = "arn:aws:cognito-idp:us-west-2:035866691871:userpool/*"
+                       Sid       = "ProjectCognitoAdmin"
                    },
                ]
#                (1 unchanged attribute hidden)
            }
        )
        tags             = {}
#        (7 unchanged attributes hidden)
    }

  # module.civic-tech-jobs.module.civic_tech_jobs_fullstack_stage_service.aws_iam_policy.container_policy will be updated in-place
!~  resource "aws_iam_policy" "container_policy" {
        id               = "arn:aws:iam::035866691871:policy/civic-tech-jobs-fullstack-stage-task-policy"
        name             = "civic-tech-jobs-fullstack-stage-task-policy"
!~      policy           = jsonencode(
!~          {
!~              Statement = [
!~                  {
+                       Sid      = "EcsExecuteCommand"
#                        (3 unchanged attributes hidden)
                    },
+                   {
+                       Action    = [
+                           "s3:ListBucket",
+                           "s3:GetObject",
+                           "s3:PutObject",
+                           "s3:DeleteObject",
                        ]
+                       Condition = {
+                           Null         = {
+                               "aws:ResourceTag/project" = "false"
                            }
+                           StringEquals = {
+                               "aws:ResourceTag/project" = "civic-tech-jobs"
                            }
                        }
+                       Effect    = "Allow"
+                       Resource  = [
+                           "arn:aws:s3:::*",
+                           "arn:aws:s3:::*/*",
                        ]
+                       Sid       = "ProjectBucketAccess"
                    },
+                   {
+                       Action    = [
+                           "cognito-idp:AdminGetUser",
+                           "cognito-idp:AdminCreateUser",
+                           "cognito-idp:AdminAddUserToGroup",
+                           "cognito-idp:AdminDeleteUser",
                        ]
+                       Condition = {
+                           StringEquals = {
+                               "aws:ResourceTag/project" = "civic-tech-jobs"
                            }
                        }
+                       Effect    = "Allow"
+                       Resource  = "arn:aws:cognito-idp:us-west-2:035866691871:userpool/*"
+                       Sid       = "ProjectCognitoAdmin"
                    },
                ]
#                (1 unchanged attribute hidden)
            }
        )
        tags             = {}
#        (7 unchanged attributes hidden)
    }

  # module.home-unite-us.module.prod_service.aws_iam_policy.container_policy will be updated in-place
!~  resource "aws_iam_policy" "container_policy" {
        id               = "arn:aws:iam::035866691871:policy/home-unite-us-fullstack-prod-task-policy"
        name             = "home-unite-us-fullstack-prod-task-policy"
!~      policy           = jsonencode(
!~          {
!~              Statement = [
!~                  {
+                       Sid      = "EcsExecuteCommand"
#                        (3 unchanged attributes hidden)
                    },
+                   {
+                       Action    = [
+                           "s3:ListBucket",
+                           "s3:GetObject",
+                           "s3:PutObject",
+                           "s3:DeleteObject",
                        ]
+                       Condition = {
+                           Null         = {
+                               "aws:ResourceTag/project" = "false"
                            }
+                           StringEquals = {
+                               "aws:ResourceTag/project" = "home-unite-us"
                            }
                        }
+                       Effect    = "Allow"
+                       Resource  = [
+                           "arn:aws:s3:::*",
+                           "arn:aws:s3:::*/*",
                        ]
+                       Sid       = "ProjectBucketAccess"
                    },
+                   {
+                       Action    = [
+                           "cognito-idp:AdminGetUser",
+                           "cognito-idp:AdminCreateUser",
+                           "cognito-idp:AdminAddUserToGroup",
+                           "cognito-idp:AdminDeleteUser",
                        ]
+                       Condition = {
+                           StringEquals = {
+                               "aws:ResourceTag/project" = "home-unite-us"
                            }
                        }
+                       Effect    = "Allow"
+                       Resource  = "arn:aws:cognito-idp:us-west-2:035866691871:userpool/*"
+                       Sid       = "ProjectCognitoAdmin"
                    },
                ]
#                (1 unchanged attribute hidden)
            }
        )
        tags             = {}
#        (7 unchanged attributes hidden)
    }

  # module.home-unite-us.module.qa_service.aws_iam_policy.container_policy will be updated in-place
!~  resource "aws_iam_policy" "container_policy" {
        id               = "arn:aws:iam::035866691871:policy/home-unite-us-fullstack-qa-task-policy"
        name             = "home-unite-us-fullstack-qa-task-policy"
!~      policy           = jsonencode(
!~          {
!~              Statement = [
!~                  {
+                       Sid      = "EcsExecuteCommand"
#                        (3 unchanged attributes hidden)
                    },
+                   {
+                       Action    = [
+                           "s3:ListBucket",
+                           "s3:GetObject",
+                           "s3:PutObject",
+                           "s3:DeleteObject",
                        ]
+                       Condition = {
+                           Null         = {
+                               "aws:ResourceTag/project" = "false"
                            }
+                           StringEquals = {
+                               "aws:ResourceTag/project" = "home-unite-us"
                            }
                        }
+                       Effect    = "Allow"
+                       Resource  = [
+                           "arn:aws:s3:::*",
+                           "arn:aws:s3:::*/*",
                        ]
+                       Sid       = "ProjectBucketAccess"
                    },
+                   {
+                       Action    = [
+                           "cognito-idp:AdminGetUser",
+                           "cognito-idp:AdminCreateUser",
+                           "cognito-idp:AdminAddUserToGroup",
+                           "cognito-idp:AdminDeleteUser",
                        ]
+                       Condition = {
+                           StringEquals = {
+                               "aws:ResourceTag/project" = "home-unite-us"
                            }
                        }
+                       Effect    = "Allow"
+                       Resource  = "arn:aws:cognito-idp:us-west-2:035866691871:userpool/*"
+                       Sid       = "ProjectCognitoAdmin"
                    },
                ]
#                (1 unchanged attribute hidden)
            }
        )
        tags             = {}
#        (7 unchanged attributes hidden)
    }

  # module.people-depot.module.backend_dev_service.aws_iam_policy.container_policy will be updated in-place
!~  resource "aws_iam_policy" "container_policy" {
        id               = "arn:aws:iam::035866691871:policy/people-depot-backend-dev-task-policy"
        name             = "people-depot-backend-dev-task-policy"
!~      policy           = jsonencode(
!~          {
!~              Statement = [
!~                  {
+                       Sid      = "EcsExecuteCommand"
#                        (3 unchanged attributes hidden)
                    },
+                   {
+                       Action    = [
+                           "s3:ListBucket",
+                           "s3:GetObject",
+                           "s3:PutObject",
+                           "s3:DeleteObject",
                        ]
+                       Condition = {
+                           Null         = {
+                               "aws:ResourceTag/project" = "false"
                            }
+                           StringEquals = {
+                               "aws:ResourceTag/project" = "people-depot"
                            }
                        }
+                       Effect    = "Allow"
+                       Resource  = [
+                           "arn:aws:s3:::*",
+                           "arn:aws:s3:::*/*",
                        ]
+                       Sid       = "ProjectBucketAccess"
                    },
+                   {
+                       Action    = [
+                           "cognito-idp:AdminGetUser",
+                           "cognito-idp:AdminCreateUser",
+                           "cognito-idp:AdminAddUserToGroup",
+                           "cognito-idp:AdminDeleteUser",
                        ]
+                       Condition = {
+                           StringEquals = {
+                               "aws:ResourceTag/project" = "people-depot"
                            }
                        }
+                       Effect    = "Allow"
+                       Resource  = "arn:aws:cognito-idp:us-west-2:035866691871:userpool/*"
+                       Sid       = "ProjectCognitoAdmin"
                    },
                ]
#                (1 unchanged attribute hidden)
            }
        )
        tags             = {}
#        (7 unchanged attributes hidden)
    }

  # module.vrms.module.backend_dev_service.aws_iam_policy.container_policy will be updated in-place
!~  resource "aws_iam_policy" "container_policy" {
        id               = "arn:aws:iam::035866691871:policy/vrms-backend-dev-task-policy"
        name             = "vrms-backend-dev-task-policy"
!~      policy           = jsonencode(
!~          {
!~              Statement = [
!~                  {
+                       Sid      = "EcsExecuteCommand"
#                        (3 unchanged attributes hidden)
                    },
+                   {
+                       Action    = [
+                           "s3:ListBucket",
+                           "s3:GetObject",
+                           "s3:PutObject",
+                           "s3:DeleteObject",
                        ]
+                       Condition = {
+                           Null         = {
+                               "aws:ResourceTag/project" = "false"
                            }
+                           StringEquals = {
+                               "aws:ResourceTag/project" = "vrms"
                            }
                        }
+                       Effect    = "Allow"
+                       Resource  = [
+                           "arn:aws:s3:::*",
+                           "arn:aws:s3:::*/*",
                        ]
+                       Sid       = "ProjectBucketAccess"
                    },
+                   {
+                       Action    = [
+                           "cognito-idp:AdminGetUser",
+                           "cognito-idp:AdminCreateUser",
+                           "cognito-idp:AdminAddUserToGroup",
+                           "cognito-idp:AdminDeleteUser",
                        ]
+                       Condition = {
+                           StringEquals = {
+                               "aws:ResourceTag/project" = "vrms"
                            }
                        }
+                       Effect    = "Allow"
+                       Resource  = "arn:aws:cognito-idp:us-west-2:035866691871:userpool/*"
+                       Sid       = "ProjectCognitoAdmin"
                    },
                ]
#                (1 unchanged attribute hidden)
            }
        )
        tags             = {}
#        (7 unchanged attributes hidden)
    }

  # module.vrms.module.backend_prod_service.aws_iam_policy.container_policy will be updated in-place
!~  resource "aws_iam_policy" "container_policy" {
        id               = "arn:aws:iam::035866691871:policy/vrms-backend-prod-task-policy"
        name             = "vrms-backend-prod-task-policy"
!~      policy           = jsonencode(
!~          {
!~              Statement = [
!~                  {
+                       Sid      = "EcsExecuteCommand"
#                        (3 unchanged attributes hidden)
                    },
+                   {
+                       Action    = [
+                           "s3:ListBucket",
+                           "s3:GetObject",
+                           "s3:PutObject",
+                           "s3:DeleteObject",
                        ]
+                       Condition = {
+                           Null         = {
+                               "aws:ResourceTag/project" = "false"
                            }
+                           StringEquals = {
+                               "aws:ResourceTag/project" = "vrms"
                            }
                        }
+                       Effect    = "Allow"
+                       Resource  = [
+                           "arn:aws:s3:::*",
+                           "arn:aws:s3:::*/*",
                        ]
+                       Sid       = "ProjectBucketAccess"
                    },
+                   {
+                       Action    = [
+                           "cognito-idp:AdminGetUser",
+                           "cognito-idp:AdminCreateUser",
+                           "cognito-idp:AdminAddUserToGroup",
+                           "cognito-idp:AdminDeleteUser",
                        ]
+                       Condition = {
+                           StringEquals = {
+                               "aws:ResourceTag/project" = "vrms"
                            }
                        }
+                       Effect    = "Allow"
+                       Resource  = "arn:aws:cognito-idp:us-west-2:035866691871:userpool/*"
+                       Sid       = "ProjectCognitoAdmin"
                    },
                ]
#                (1 unchanged attribute hidden)
            }
        )
        tags             = {}
#        (7 unchanged attributes hidden)
    }

  # module.vrms.module.frontend_dev_service.aws_iam_policy.container_policy will be updated in-place
!~  resource "aws_iam_policy" "container_policy" {
        id               = "arn:aws:iam::035866691871:policy/vrms-frontend-dev-task-policy"
        name             = "vrms-frontend-dev-task-policy"
!~      policy           = jsonencode(
!~          {
!~              Statement = [
!~                  {
+                       Sid      = "EcsExecuteCommand"
#                        (3 unchanged attributes hidden)
                    },
+                   {
+                       Action    = [
+                           "s3:ListBucket",
+                           "s3:GetObject",
+                           "s3:PutObject",
+                           "s3:DeleteObject",
                        ]
+                       Condition = {
+                           Null         = {
+                               "aws:ResourceTag/project" = "false"
                            }
+                           StringEquals = {
+                               "aws:ResourceTag/project" = "vrms"
                            }
                        }
+                       Effect    = "Allow"
+                       Resource  = [
+                           "arn:aws:s3:::*",
+                           "arn:aws:s3:::*/*",
                        ]
+                       Sid       = "ProjectBucketAccess"
                    },
+                   {
+                       Action    = [
+                           "cognito-idp:AdminGetUser",
+                           "cognito-idp:AdminCreateUser",
+                           "cognito-idp:AdminAddUserToGroup",
+                           "cognito-idp:AdminDeleteUser",
                        ]
+                       Condition = {
+                           StringEquals = {
+                               "aws:ResourceTag/project" = "vrms"
                            }
                        }
+                       Effect    = "Allow"
+                       Resource  = "arn:aws:cognito-idp:us-west-2:035866691871:userpool/*"
+                       Sid       = "ProjectCognitoAdmin"
                    },
                ]
#                (1 unchanged attribute hidden)
            }
        )
        tags             = {}
#        (7 unchanged attributes hidden)
    }

  # module.vrms.module.frontend_prod_service.aws_iam_policy.container_policy will be updated in-place
!~  resource "aws_iam_policy" "container_policy" {
        id               = "arn:aws:iam::035866691871:policy/vrms-frontend-prod-task-policy"
        name             = "vrms-frontend-prod-task-policy"
!~      policy           = jsonencode(
!~          {
!~              Statement = [
!~                  {
+                       Sid      = "EcsExecuteCommand"
#                        (3 unchanged attributes hidden)
                    },
+                   {
+                       Action    = [
+                           "s3:ListBucket",
+                           "s3:GetObject",
+                           "s3:PutObject",
+                           "s3:DeleteObject",
                        ]
+                       Condition = {
+                           Null         = {
+                               "aws:ResourceTag/project" = "false"
                            }
+                           StringEquals = {
+                               "aws:ResourceTag/project" = "vrms"
                            }
                        }
+                       Effect    = "Allow"
+                       Resource  = [
+                           "arn:aws:s3:::*",
+                           "arn:aws:s3:::*/*",
                        ]
+                       Sid       = "ProjectBucketAccess"
                    },
+                   {
+                       Action    = [
+                           "cognito-idp:AdminGetUser",
+                           "cognito-idp:AdminCreateUser",
+                           "cognito-idp:AdminAddUserToGroup",
+                           "cognito-idp:AdminDeleteUser",
                        ]
+                       Condition = {
+                           StringEquals = {
+                               "aws:ResourceTag/project" = "vrms"
                            }
                        }
+                       Effect    = "Allow"
+                       Resource  = "arn:aws:cognito-idp:us-west-2:035866691871:userpool/*"
+                       Sid       = "ProjectCognitoAdmin"
                    },
                ]
#                (1 unchanged attribute hidden)
            }
        )
        tags             = {}
#        (7 unchanged attributes hidden)
    }

Plan: 0 to add, 10 to change, 0 to destroy.

✅ Plan applied in Terraform apply (OIDC) #94

@ale210
ale210 merged commit 3d78944 into main Sep 18, 2026
ale210 added a commit that referenced this pull request Sep 18, 2026
Closes #205.

The documentation itself is the wiki page [Container
Permissions](https://github.com/hackforla/incubator/wiki/Container-Permissions),
published in wiki commit `26db1b4`. A wiki page is not delivered as a
pull request, so this PR is only the last action item: linking it from
the `container` module, whose `task_role_arn` output description said
"Good for setting up permissions like s3 access" without saying how.

## The change

One line in `terraform/modules/container/outputs.tf`. The new
description names the task role as the place project-specific
permissions go and links the page. The `terraform-docs` job regenerates
the module README from it.

## What the wiki page covers

Written for project teams rather than for DevOps:

- **The two roles and which one you want** — task role vs execution
role, including the trap that `incubator-prod-ecs-task-role` is an
*execution* role despite the name. No running container uses that role
any more; it survives only until `use_own_execution_role` is removed.
- **What the task role already grants** — `ecs execute-command`, S3 by
project tag and Cognito by project tag, all three delivered by #242.
This section exists so nobody files a request for access they already
have.
- **A walkthrough for giving a container an S3 bucket**, which after
#242 needs no policy change at all — just the bucket, the `project` tag
and `aws_s3_bucket_abac`. The page is explicit that omitting the ABAC
opt-in fails silently.
- **How to ask for a permission that is not covered**, with an SQS
statement as the worked example, the `aws:ResourceTag` pattern, and the
two exceptions from the tag standard: services that do not support
resource-level permissions or tag conditions, and actions like
`ecr:GetAuthorizationToken` that cannot be scoped at all.
- **How to file the request** — `hackforla/incubator`, Blank Issue Form
with No Dependency, with a warning that the picker is still cluttered
with website-inherited templates (#146).

## Verification

Both HCL snippets on the page `terraform validate` clean against the
pinned Terraform 1.16.0 and AWS provider 6.64.0, and are `fmt`-clean —
`aws_s3_bucket_abac` in particular takes `abac_status` as a nested block
rather than an attribute, which is easy to get wrong from prose. All
external links on the page return 200, and the rendered page was checked
live: headings, the role comparison table and both code blocks all
render.

The markdown link in the output description was tested against the
pinned terraform-docs v0.20.0 before committing. No existing generated
description in this repo contains a markdown link, so there was no
precedent for whether the brackets would be escaped into a dead string
in the README table; they are not, and the link renders clickable.

## Note

`terraform fmt` would also align the four `value =` lines in this file
with their `description =` lines. That misalignment predates this change
and is left alone rather than adding whitespace-only churn to a one-line
documentation change.

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Give the ECS task role project-scoped S3 and Cognito access

1 participant