Skip to content

fix(iam): close cross-team secret, security group and CI-identity holes - #134

Merged
Alexanderamiri merged 6 commits into
mainfrom
fix/team-isolation
Oct 23, 2026
Merged

Alexanderamiri merged 6 commits into
mainfrom
fix/team-isolation

Conversation

@Alexanderamiri

@Alexanderamiri Alexanderamiri commented Oct 23, 2026 •

Copy link
Copy Markdown
Member

Closes three of the isolation holes found while exploring app-to-app support. All of them matter before cupcake stores real credentials. Its sleepingpill credentials can read every talk submission.

Why

  1. Cross-team secret access. The shared javabin-ecs-execution role could read every /javabin/apps/* parameter, and every team was allowed to pass it. Any team could mount another team's secrets, or since fix(ci): make app.yaml deploys work end to end without app secrets #132 their Cognito client secrets, in its own task definition.
  2. Shared security group editable by teams. DenyShared blocked ec2:Delete*/Modify* but not ec2:AuthorizeSecurityGroupIngress/Revoke*. The IAM policy simulator confirms javabin-ci-team-testteam may edit javabin-ecs-tasks-sg. Any team could open every app to every other app, or remove the ALB rule and take all apps offline.
  3. Broker and gate trusted the payload. ci-broker and apply-gate took the repo from the request. The gate's sign action (approve a HIGH-risk plan) accepted any caller. Code running in an app's platform job (a Terraform external data source, say) could claim another repo's team credentials or sign its own override.

What changed

  • Execution roles: per-team javabin-ecs-exec-{team}, reading only /javabin/apps/{team}/*. They are tagged team=shared, so teams can't edit them. platform-data takes team and returns that role. The boundary's DenyPassRole only allows javabin-ecs-exec-${PrincipalTag/team}. The shared role loses its secrets policy.
  • Boundary: DenyShared now covers ec2:AuthorizeSecurityGroup*, ec2:RevokeSecurityGroup* and iam:UpdateAssumeRolePolicy. Without the last one, a team could make another team's execution role trust its own CI role. Size goes up about 110 bytes, to roughly 5,835 of 6,144.
  • Broker and gate: callers send a GitHub OIDC token (scripts/github-oidc-token.sh). The Lambdas verify it against GitHub's JWKS (shared/github_oidc.py, RS256 verified in plain Python, no dependencies or binaries) and take the repo from its signed repository claim.
    • check also requires the plan key to be under plans/javaBin/<repo>/.
    • sign requires a token from approve-override.yml in javaBin/platform, in the override-approval environment. The approver is the token's actor.
  • approve-override.yml: passes inputs through env instead of interpolating them into shell.

Switching team roles to registry teams was split out into #135, because it destroys unused roles and plans HIGH. Until that merges, execution roles are created for every GitHub org team, like the CI roles today.

Not in this PR

  • service-rds still allows ingress from the shared tasks SG, so team databases share a network path (password still required). Fixing that needs per-app SGs; recorded in CLAUDE.md. cupcake has no database.
  • Team roles can still write other repos' objects in the plan bucket. fix(ci): review app plans in a platform Lambda instead of with team roles #137 denies writing risk.json/review.json/override.json. Overwriting another repo's tfplan only makes its apply fail the SHA256 check, so it's a nuisance, not an escalation. Prefix-scoping the bucket per repo is follow-up work.

Checks

  • python3 -m unittest discover -s terraform/lambda-src/tests: 20 tests pass. The new ones sign real RS256 tokens: tampered payload, wrong audience/org/workflow/branch, the override-signing workflow and environment pin, non-object claims, and verification without any subprocess.
  • Reviewed by an independent agent. Its blockers are fixed in the last commit: the exec-role trust takeover, and the openssl dependency (the live runtime does have openssl, but verification no longer needs it).
  • Generator tests pass.
  • terraform validate on terraform/platform.
  • actionlint.

Rollout

  • Scripts are read from main, so they send id_token from the moment this merges. The old Lambdas ignore it until the apply replaces them. The override script still sends approved_by, which the old gate needs.
  • The apply creates the exec roles before apps regenerate against the new platform-data.
  • platform-test-app has no running tasks, so dropping the shared role's secrets policy affects nothing live.

🤖 Generated with Claude Code

Alexanderamiri and others added 3 commits October 23, 2026 16:09
- The shared javabin-ecs-execution role could read every /javabin/apps/*
  parameter and every team could pass it, so any team could mount another
  team's secrets in its own task definition. Each registered team now gets
  javabin-ecs-exec-{team}, reading only its own path; the developer
  boundary only lets a team pass its own. The shared role keeps image pull
  and logs only.
- DenyShared did not cover ec2:AuthorizeSecurityGroup*/RevokeSecurityGroup*,
  so any team CI role could open every app to every other or remove the
  ALB rule on the shared ECS tasks SG (confirmed with the IAM simulator).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Both Lambdas took the repo from the request payload, and the gate's sign
action (approve a HIGH-risk plan) was open to any caller. Code running in
an app's platform job (a Terraform external data source, say) could claim
another repo's team credentials or sign its own override.

Callers now send a GitHub OIDC token; the Lambdas verify it against
GitHub's JWKS (RS256 via openssl, no new dependencies) and read the repo
from its signed claims. check also requires the plan to be the repo's own,
and sign requires a token from approve-override.yml in javaBin/platform in
the override-approval environment, recording the token's actor. The
override workflow passes inputs via env instead of interpolating them.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
sync-registered-teams listed every GitHub org team, so non-app teams like
owners and developer got AWS CI and deploy roles. Use teams/*.yaml in
javaBin/registry, the documented source of truth.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@Alexanderamiri
Alexanderamiri requested a review from a team as a code owner October 23, 2026 14:10
@github-actions

Copy link
Copy Markdown

Terraform Plan

🚧 Changes detected — Plan: 9 to add, 6 to change, 148 to destroy.

Plan output
Acquiring state lock. This may take a few moments...
aws_ssm_parameter.atlassian_org_id: Refreshing state... [id=/javabin/platform/atlassian-org-id]
aws_ssm_parameter.atlassian_api_key: Refreshing state... [id=/javabin/platform/atlassian-api-key]

Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
  + create
  ~ update in-place
  - destroy

Terraform will perform the following actions:

  # module.iam.aws_iam_policy.developer_boundary will be updated in-place
  ~ resource "aws_iam_policy" "developer_boundary" {
        id               = "arn:aws:iam::553637109631:policy/javabin-developer-boundary"
        name             = "javabin-developer-boundary"
      ~ policy           = jsonencode(
          ~ {
              ~ Statement = [
                    # (9 unchanged elements hidden)
                    {
                        Action      = "*"
                        Condition   = {
                            Null            = {
                                "aws:ResourceTag/team" = "false"
                            }
                            StringNotEquals = {
                                "aws:ResourceTag/team" = [
                                    "${aws:PrincipalTag/team}",
                                    "shared",
                                ]
                            }
                        }
                        Effect      = "Deny"
                        NotResource = [
                            "arn:aws:s3:::javabin-terraform-state-553637109631",
                            "arn:aws:s3:::javabin-terraform-state-553637109631/*",
                            "arn:aws:dynamodb:eu-central-1:553637109631:table/javabin-terraform-app-locks",
                            "arn:aws:s3:::javabin-ci-plan-artifacts-553637109631",
                            "arn:aws:s3:::javabin-ci-plan-artifacts-553637109631/*",
                        ]
                        Sid         = "DenyXTeam"
                    },
                  ~ {
                      ~ Action    = [
                            # (15 unchanged elements hidden)
                            "sns:SetTopicAttributes",
                          + "ec2:AuthorizeSecurityGroup*",
                          + "ec2:RevokeSecurityGroup*",
                        ]
                        # (4 unchanged attributes hidden)
                    },
                    {
                        Action    = [
                            "ec2:DeleteTags",
                            "ec2:CreateTags",
                            "ecs:TagResource",
                            "ecs:UntagResource",
                            "elasticloadbalancing:AddTags",
                            "elasticloadbalancing:RemoveTags",
                            "iam:TagRole",
                            "iam:UntagRole",
                            "sns:TagResource",
                            "sns:UntagResource",
                        ]
                        Condition = {
                            StringEquals = {
                                "aws:ResourceTag/team" = [
                                    "shared",
                                    "platform",
                                ]
                            }
                        }
                        Effect    = "Deny"
                        Resource  = "*"
                        Sid       = "DenyTagStrip"
                    },
                    {
                        Action   = [
                            "ssm:GetParameter*",
                            "ssm:GetParametersByPath",
                        ]
                        Effect   = "Deny"
                        Resource = [
                            "arn:aws:ssm:*:*:parameter/javabin/platform/*",
                            "arn:aws:ssm:*:*:parameter/javabin/slack/*",
                            "arn:aws:ssm:*:*:parameter/javabin/platform-overrides/*",
                        ]
                        Sid      = "DenyPlatSSM"
                    },
                  ~ {
                      ~ NotResource = [
                            "arn:aws:iam::*:role/${aws:PrincipalTag/team}-*",
                          - "arn:aws:iam::*:role/javabin-ecs-execution",
                          + "arn:aws:iam::*:role/javabin-ecs-exec-${aws:PrincipalTag/team}",
                        ]
                        # (3 unchanged attributes hidden)
                    },
                    {
                        Action      = [
                            "logs:GetLogEvents",
                            "logs:FilterLogEvents",
                            "logs:StartQuery",
                            "logs:GetQueryResults",
                        ]
                        Effect      = "Deny"
                        NotResource = [
                            "arn:aws:logs:*:*:log-group:/ecs/${aws:PrincipalTag/team}/*",
                            "arn:aws:logs:*:*:log-group:/ecs/${aws:PrincipalTag/team}/*:*",
                        ]
                        Sid         = "DenyXLogs"
                    },
                    # (3 unchanged elements hidden)
                ]
                # (1 unchanged attribute hidden)
            }
        )
        tags             = {
            "Name" = "javabin-developer-boundary"
        }
        # (6 unchanged attributes hidden)
    }

  # module.iam.aws_iam_role.ci_deploy["cake"] will be destroyed
  # (because key ["cake"] is not in for_each map)
  - resource "aws_iam_role" "ci_deploy" {
      - arn                   = "arn:aws:iam::553637109631:role/javabin-ci-deploy-cake" -> null
      - assume_role_policy    = jsonencode(
            {
              - Statement = [
                  - {
                      - Action    = "sts:AssumeRole"
                      - Effect    = "Allow"
                      - Principal = {
                          - AWS = "arn:aws:iam::553637109631:role/javabin-ci-broker"
                        }
                      - Sid       = "AllowViaCIBroker"
                    },
                ]
              - Version   = "2012-10-17"
            }
        ) -> null
      - create_date           = "2026-10-23T13:50:08Z" -> null
      - force_detach_policies = false -> null
      - id                    = "javabin-ci-deploy-cake" -> null
      - managed_policy_arns   = [] -> null
      - max_session_duration  = 3600 -> null
      - name                  = "javabin-ci-deploy-cake" -> null
      - path                  = "/" -> null
      - permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-developer-boundary" -> null
      - tags                  = {
          - "Name" = "javabin-ci-deploy-cake"
          - "team" = "cake"
        } -> null
      - tags_all              = {
          - "Name"        = "javabin-ci-deploy-cake"
          - "environment" = "production"
          - "managed-by"  = "terraform"
          - "repo"        = "javaBin/platform"
          - "service"     = "platform"
          - "team"        = "cake"
        } -> null
      - unique_id             = "AROAYBZ2X3574IM43BNTE" -> null

      - inline_policy {
          - name   = "cloudwatch-logs" -> null
          - policy = jsonencode(
                {
                  - Statement = [
                      - {
                          - Action   = [
                              - "logs:CreateLogGroup",
                              - "logs:CreateLogStream",
                              - "logs:PutLogEvents",
                            ]
                          - Effect   = "Allow"
                          - Resource = [
                              - "arn:aws:logs:eu-central-1:553637109631:log-group:/ecs/cake/*",
                              - "arn:aws:logs:eu-central-1:553637109631:log-group:/ecs/cake/*:*",
                            ]
                        },
                    ]
                  - Version   = "2012-10-17"
                }
            ) -> null
        }
      - inline_policy {
          - name   = "ecr-push" -> null
          - policy = jsonencode(
                {
                  - Statement = [
                      - {
                          - Action   = [
                              - "ecr:GetAuthorizationToken",
                            ]
                          - Effect   = "Allow"
                          - Resource = "*"
                          - Sid      = "EcrAuth"
                        },
                      - {
                          - Action   = [
                              - "ecr:BatchCheckLayerAvailability",
                              - "ecr:PutImage",
                              - "ecr:InitiateLayerUpload",
                              - "ecr:UploadLayerPart",
                              - "ecr:CompleteLayerUpload",
                              - "ecr:GetDownloadUrlForLayer",
                              - "ecr:BatchGetImage",
                              - "ecr:CreateRepository",
                              - "ecr:DescribeRepositories",
                            ]
                          - Effect   = "Allow"
                          - Resource = "arn:aws:ecr:eu-central-1:553637109631:repository/cake-*"
                          - Sid      = "EcrPush"
                        },
                    ]
                  - Version   = "2012-10-17"
                }
            ) -> null
        }
      - inline_policy {
          - name   = "ecs-deploy" -> null
          - policy = jsonencode(
                {
                  - Statement = [
                      - {
                          - Action    = [
                              - "ecs:UpdateService",
                              - "ecs:DescribeServices",
                            ]
                          - Condition = {
                              - StringEquals = {
                                  - "aws:ResourceTag/team" = "cake"
                                }
                            }
                          - Effect    = "Allow"
                          - Resource  = "*"
                          - Sid       = "EcsServiceManagement"
                        },
                      - {
                          - Action   = [
                              - "ecs:DescribeTaskDefinition",
                              - "ecs:RegisterTaskDefinition",
                              - "ecs:DeregisterTaskDefinition",
                            ]
                          - Effect   = "Allow"
                          - Resource = "*"
                          - Sid      = "EcsTaskDefinitionManagement"
                        },
                      - {
                          - Action   = [
                              - "iam:PassRole",
                            ]
                          - Effect   = "Allow"
                          - Resource = [
                              - "arn:aws:iam::553637109631:role/javabin-ecs-execution",
                              - "arn:aws:iam::553637109631:role/cake-*",
                            ]
                          - Sid      = "PassRole"
                        },
                    ]
                  - Version   = "2012-10-17"
                }
            ) -> null
        }
      - inline_policy {
          - name   = "ssm-read-overrides" -> null
          - policy = jsonencode(
                {
                  - Statement = [
                      - {
                          - Action   = [
                              - "ssm:GetParameter",
                              - "ssm:GetParameters",
                            ]
                          - Effect   = "Allow"
                          - Resource = "arn:aws:ssm:eu-central-1:553637109631:parameter/javabin/platform-overrides/*"
                        },
                    ]
                  - Version   = "2012-10-17"
                }
            ) -> null
        }
    }

  # module.iam.aws_iam_role.ci_deploy["commandchimps"] will be destroyed
  # (because key ["commandchimps"] is not in for_each map)
  - resource "aws_iam_role" "ci_deploy" {
      - arn                   = "arn:aws:iam::553637109631:role/javabin-ci-deploy-commandchimps" -> null
      - assume_role_policy    = jsonencode(
            {
              - Statement = [
                  - {
                      - Action    = "sts:AssumeRole"
                      - Effect    = "Allow"
                      - Principal = {
                          - AWS = "arn:aws:iam::553637109631:role/javabin-ci-broker"
                        }
                      - Sid       = "AllowViaCIBroker"
                    },
                ]
              - Version   = "2012-10-17"
            }
        ) -> null
      - create_date           = "2026-10-23T13:50:07Z" -> null
      - force_detach_policies = false -> null
      - id                    = "javabin-ci-deploy-commandchimps" -> null
      - managed_policy_arns   = [] -> null
      - max_session_duration  = 3600 -> null
      - name                  = "javabin-ci-deploy-commandchimps" -> null
      - path                  = "/" -> null
      - permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-developer-boundary" -> null
      - tags                  = {
          - "Name" = "javabin-ci-deploy-commandchimps"
          - "team" = "commandchimps"
        } -> null
      - tags_all              = {
          - "Name"        = "javabin-ci-deploy-commandchimps"
          - "environment" = "production"
          - "managed-by"  = "terraform"
          - "repo"        = "javaBin/platform"
          - "service"     = "platform"
          - "team"        = "commandchimps"
        } -> null
      - unique_id             = "AROAYBZ2X357RK4KR5VYP" -> null

      - inline_policy {
          - name   = "cloudwatch-logs" -> null
          - policy = jsonencode(
                {
                  - Statement = [
                      - {
                          - Action   = [
                              - "logs:CreateLogGroup",
                              - "logs:CreateLogStream",
                              - "logs:PutLogEvents",
                            ]
                          - Effect   = "Allow"
                          - Resource = [
                              - "arn:aws:logs:eu-central-1:553637109631:log-group:/ecs/commandchimps/*",
                              - "arn:aws:logs:eu-central-1:553637109631:log-group:/ecs/commandchimps/*:*",
                            ]
                        },
                    ]
                  - Version   = "2012-10-17"
                }
            ) -> null
        }
      - inline_policy {
          - name   = "ecr-push" -> null
          - policy = jsonencode(
                {
                  - Statement = [
                      - {
                          - Action   = [
                              - "ecr:GetAuthorizationToken",
                            ]
                          - Effect   = "Allow"
                          - Resource = "*"
                          - Sid      = "EcrAuth"
                        },
                      - {
                          - Action   = [
                              - "ecr:BatchCheckLayerAvailability",
                              - "ecr:PutImage",
                              - "ecr:InitiateLayerUpload",
                              - "ecr:UploadLayerPart",
                              - "ecr:CompleteLayerUpload",
                              - "ecr:GetDownloadUrlForLayer",
                              - "ecr:BatchGetImage",
                              - "ecr:CreateRepository",
                              - "ecr:DescribeRepositories",
                            ]
                          - Effect   = "Allow"
                          - Resource = "arn:aws:ecr:eu-central-1:553637109631:repository/commandchimps-*"
                          - Sid      = "EcrPush"
                        },
                    ]
                  - Version   = "2012-10-17"
                }
            ) -> null
        }
      - inline_policy {
          - name   = "ecs-deploy" -> null
          - policy = jsonencode(
                {
                  - Statement = [
                      - {
                          - Action    = [
                              - "ecs:UpdateService",
                              - "ecs:DescribeServices",
                            ]
                          - Condition = {
                              - StringEquals = {
                                  - "aws:ResourceTag/team" = "commandchimps"
                                }
                            }
                          - Effect    = "Allow"
                          - Resource  = "*"
                          - Sid       = "EcsServiceManagement"
                        },
                      - {
                          - Action   = [
                              - "ecs:DescribeTaskDefinition",
                              - "ecs:RegisterTaskDefinition",
                              - "ecs:DeregisterTaskDefinition",
                            ]
                          - Effect   = "Allow"
                          - Resource = "*"
                          - Sid      = "EcsTaskDefinitionManagement"
                        },
                      - {
                          - Action   = [
                              - "iam:PassRole",
                            ]
                          - Effect   = "Allow"
                          - Resource = [
                              - "arn:aws:iam::553637109631:role/javabin-ecs-execution",
                              - "arn:aws:iam::553637109631:role/commandchimps-*",
                            ]
                          - Sid      = "PassRole"
                        },
                    ]
                  - Version   = "2012-10-17"
                }
            ) -> null
        }
      - inline_policy {
          - name   = "ssm-read-overrides" -> null
          - policy = jsonencode(
                {
                  - Statement = [
                      - {
                          - Action   = [
                              - "ssm:GetParameter",
                              - "ssm:GetParameters",
                            ]
                          - Effect   = "Allow"
                          - Resource = "arn:aws:ssm:eu-central-1:553637109631:parameter/javabin/platform-overrides/*"
                        },
                    ]
                  - Version   = "2012-10-17"
                }
            ) -> null
        }
    }

  # module.iam.aws_iam_role.ci_deploy["developer"] will be destroyed
  # (because key ["developer"] is not in for_each map)
  - resource "aws_iam_role" "ci_deploy" {
      - arn                   = "arn:aws:iam::553637109631:role/javabin-ci-deploy-developer" -> null
      - assume_role_policy    = jsonencode(
            {
              - Statement = [
                  - {
                      - Action    = "sts:AssumeRole"
                      - Effect    = "Allow"
                      - Principal = {
                          - AWS = "arn:aws:iam::553637109631:role/javabin-ci-broker"
                        }
                      - Sid       = "AllowViaCIBroker"
                    },
                ]
              - Version   = "2012-10-17"
            }
        ) -> null
      - create_date           = "2026-10-23T13:50:07Z" -> null
      - force_detach_policies = false -> null
      - id                    = "javabin-ci-deploy-developer" -> null
      - managed_policy_arns   = [] -> null
      - max_session_duration  = 3600 -> null
      - name                  = "javabin-ci-deploy-developer" -> null
      - path                  = "/" -> null
      - permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-developer-boundary" -> null
      - tags                  = {
          - "Name" = "javabin-ci-deploy-developer"
          - "team" = "developer"
        } -> null
      - tags_all              = {
          - "Name"        = "javabin-ci-deploy-developer"
          - "environment" = "production"
          - "managed-by"  = "terraform"
          - "repo"        = "javaBin/platform"
          - "service"     = "platform"
          - "team"        = "developer"
        } -> null
      - unique_id             = "AROAYBZ2X357YGNZIWO6E" -> null

      - inline_policy {
          - name   = "cloudwatch-logs" -> null
          - policy = jsonencode(
                {
                  - Statement = [
                      - {
                          - Action   = [
                              - "logs:CreateLogGroup",
                              - "logs:CreateLogStream",
                              - "logs:PutLogEvents",
                            ]
                          - Effect   = "Allow"
                          - Resource = [
                              - "arn:aws:logs:eu-central-1:553637109631:log-group:/ecs/developer/*",
                              - "arn:aws:logs:eu-central-1:553637109631:log-group:/ecs/developer/*:*",
                            ]
                        },
                    ]
                  - Version   = "2012-10-17"
                }
            ) -> null
        }
      - inline_policy {
          - name   = "ecr-push" -> null
          - policy = jsonencode(
                {
                  - Statement = [
                      - {
                          - Action   = [
                              - "ecr:GetAuthorizationToken",
                            ]
                          - Effect   = "Allow"
                          - Resource = "*"
                          - Sid      = "EcrAuth"
                        },
                      - {
                          - Action   = [
                              - "ecr:BatchCheckLayerAvailability",
                              - "ecr:PutImage",
                              - "ecr:InitiateLayerUpload",
                              - "ecr:UploadLayerPart",
                              - "ecr:CompleteLayerUpload",
                              - "ecr:GetDownloadUrlForLayer",
                              - "ecr:BatchGetImage",
                              - "ecr:CreateRepository",
                              - "ecr:DescribeRepositories",
                            ]
                          - Effect   = "Allow"
                          - Resource = "arn:aws:ecr:eu-central-1:553637109631:repository/developer-*"
                          - Sid      = "EcrPush"
                        },
                    ]
                  - Version   = "2012-10-17"
                }
            ) -> null
        }
      - inline_policy {
          - name   = "ecs-deploy" -> null
          - policy = jsonencode(
                {
                  - Statement = [
                      - {
                          - Action    = [
                              - "ecs:UpdateService",
                              - "ecs:DescribeServices",
                            ]
                          - Condition = {
                              - StringEquals = {
                                  - "aws:ResourceTag/team" = "developer"
                                }
                            }
                          - Effect    = "Allow"
                          - Resource  = "*"
                          - Sid       = "EcsServiceManagement"
                        },
                      - {
                          - Action   = [
                              - "ecs:DescribeTaskDefinition",
                              - "ecs:RegisterTaskDefinition",
                              - "ecs:DeregisterTaskDefinition",
                            ]
                          - Effect   = "Allow"
                          - Resource = "*"
                          - Sid      = "EcsTaskDefinitionManagement"
                        },
                      - {
                          - Action   = [
                              - "iam:PassRole",
                            ]
                          - Effect   = "Allow"
                          - Resource = [
                              - "arn:aws:iam::553637109631:role/javabin-ecs-execution",
                              - "arn:aws:iam::553637109631:role/developer-*",
                            ]
                          - Sid      = "PassRole"
                        },
                    ]
                  - Version   = "2012-10-17"
                }
            ) -> null
        }
      - inline_policy {
          - name   = "ssm-read-overrides" -> null
          - policy = jsonencode(
                {
                  - Statement = [
                      - {
                          - Action   = [
                              - "ssm:GetParameter",
                              - "ssm:GetParameters",
                            ]
                          - Effect   = "Allow"
                          - Resource = "arn:aws:ssm:eu-central-1:553637109631:parameter/javabin/platform-overrides/*"
                        },
                    ]
                  - Version   = "2012-10-17"
                }
            ) -> null
        }
    }

  # module.iam.aws_iam_role.ci_deploy["java-no"] will be destroyed
  # (because key ["java-no"] is not in for_each map)
  - resource "aws_iam_role" "ci_deploy" {
      - arn                   = "arn:aws:iam::553637109631:role/javabin-ci-deploy-java-no" -> null
      - assume_role_policy    = jsonencode(
            {
              - Statement = [
                  - {
                      - Action    = "sts:AssumeRole"
                      - Effect    = "Allow"
                      - Principal = {
                          - AWS = "arn:aws:iam::553637109631:role/javabin-ci-broker"
                        }
                      - Sid       = "AllowViaCIBroker"
                    },
                ]
              - Version   = "2012-10-17"
            }
        ) -> null
      - create_date           = "2026-10-23T13:50:07Z" -> null
      - force_detach_policies = false -> null
      - id                    = "javabin-ci-deploy-java-no" -> null
      - managed_policy_arns   = [] -> null
      - max_session_duration  = 3600 -> null
      - name                  = "javabin-ci-deploy-java-no" -> null
      - path                  = "/" -> null
      - permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-developer-boundary" -> null
      - tags                  = {
          - "Name" = "javabin-ci-deploy-java-no"
          - "team" = "java-no"
        } -> null
      - tags_all              = {
          - "Name"        = "javabin-ci-deploy-java-no"
          - "environment" = "production"
          - "managed-by"  = "terraform"
          - "repo"        = "javaBin/platform"
          - "service"     = "platform"
          - "team"        = "java-no"
        } -> null
      - unique_id             = "AROAYBZ2X357VKB5DVGLS" -> null

      - inline_policy {
          - name   = "cloudwatch-logs" -> null
          - policy = jsonencode(
                {
                  - Statement = [
                      - {
                          - Action   = [
                              - "logs:CreateLogGroup",
                              - "logs:CreateLogStream",
                              - "logs:PutLogEvents",
                            ]
                          - Effect   = "Allow"
                          - Resource = [
                              - "arn:aws:logs:eu-central-1:553637109631:log-group:/ecs/java-no/*",
                              - "arn:aws:logs:eu-central-1:553637109631:log-group:/ecs/java-no/*:*",
                            ]
                        },
                    ]
                  - Version   = "2012-10-17"
                }
            ) -> null
        }
      - inline_policy {
          - name   = "ecr-push" -> null
          - policy = jsonencode(
                {
                  - Statement = [
                      - {
                          - Action   = [
                              - "ecr:GetAuthorizationToken",
                            ]
                          - Effect   = "Allow"
                          - Resource = "*"
                          - Sid      = "EcrAuth"
                        },
                      - {
                          - Action   = [
                              - "ecr:BatchCheckLayerAvailability",
                              - "ecr:PutImage",
                              - "ecr:InitiateLayerUpload",
                              - "ecr:UploadLayerPart",
                              - "ecr:CompleteLayerUpload",
                              - "ecr:GetDownloadUrlForLayer",
                              - "ecr:BatchGetImage",
                              - "ecr:CreateRepository",
                              - "ecr:DescribeRepositories",
                            ]
                          - Effect   = "Allow"
                          - Resource = "arn:aws:ecr:eu-central-1:553637109631:repository/java-no-*"
                          - Sid      = "EcrPush"
                        },
                    ]
                  - Version   = "2012-10-17"
                }
            ) -> null
        }
      - inline_policy {
          - name   = "ecs-deploy" -> null
          - policy = jsonencode(
                {
                  - Statement = [
                      - {
                          - Action    = [
                              - "ecs:UpdateService",
                              - "ecs:DescribeServices",
                            ]
                          - Condition = {
                              - StringEquals = {
                                  - "aws:ResourceTag/team" = "java-no"
                                }
                            }
                          - Effect    = "Allow"
                          - Resource  = "*"
                          - Sid       = "EcsServiceManagement"
                        },
                      - {
                          - Action   = [
                              - "ecs:DescribeTaskDefinition",
                              - "ecs:RegisterTaskDefinition",
                              - "ecs:DeregisterTaskDefinition",
                            ]
                          - Effect   = "Allow"
                          - Resource = "*"
                          - Sid      = "EcsTaskDefinitionManagement"
                        },
                      - {
                          - Action   = [
                              - "iam:PassRole",
                            ]
                          - Effect   = "Allow"
                          - Resource = [
                              - "arn:aws:iam::553637109631:role/javabin-ecs-execution",
                              - "arn:aws:iam::553637109631:role/java-no-*",
                            ]
                          - Sid      = "PassRole"
                        },
                    ]
                  - Version   = "2012-10-17"
                }
            ) -> null
        }
      - inline_policy {
          - name   = "ssm-read-overrides" -> null
          - policy = jsonencode(
                {
                  - Statement = [
                      - {
                          - Action   = [
                              - "ssm:GetParameter",
                              - "ssm:GetParameters",
                            ]
                          - Effect   = "Allow"
                          - Resource = "arn:aws:ssm:eu-central-1:553637109631:parameter/javabin/platform-overrides/*"
                        },
                    ]
                  - Version   = "2012-10-17"
                }
            ) -> null
        }
    }

  # module.iam.aws_iam_role.ci_deploy["javazone-no"] will be destroyed
  # (because key ["javazone-no"] is not in for_each map)
  - resource "aws_iam_role" "ci_deploy" {
      - arn                   = "arn:aws:iam::553637109631:role/javabin-ci-deploy-javazone-no" -> null
      - assume_role_policy    = jsonencode(
            {
              - Statement = [
                  - {
                      - Action    = "sts:AssumeRole"
                      - Effect    = "Allow"
                      - Principal = {
                          - AWS = "arn:aws:iam::553637109631:role/javabin-ci-broker"
                        }
                      - Sid       = "AllowViaCIBroker"
                    },
                ]
              - Version   = "2012-10-17"
            }
        ) -> null
      - create_date           = "2026-10-23T13:50:07Z" -> null
      - force_detach_policies = false -> null
      - id                    = "javabin-ci-deploy-javazone-no" -> null
      - managed_policy_arns   = [] -> null
      - max_session_duration  = 3600 -> null
      - name                  = "javabin-ci-deploy-javazone-no" -> null
      - path                  = "/" -> null
      - permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-developer-boundary" -> null
      - tags                  = {
          - "Name" = "javabin-ci-deploy-javazone-no"
          - "team" = "javazone-no"
        } -> null
      - tags_all              = {
          - "Name"        = "javabin-ci-deploy-javazone-no"
          - "environment" = "production"
          - "managed-by"  = "terraform"
          - "repo"        = "javaBin/platform"
          - "service"     = "platform"
          - "team"        = "javazone-no"
        } -> null
      - unique_id             = "AROAYBZ2X3574JJ53X2NU" -> null

      - inline_policy {
          - name   = "cloudwatch-logs" -> null
          - policy = jsonencode(
                {
                  - Statement = [
                      - {
                          - Action   = [
                              - "logs:CreateLogGroup",
                              - "logs:CreateLogStream",
                              - "logs:PutLogEvents",
                            ]
                          - Effect   = "Allow"
                          - Resource = [
                              - "arn:aws:logs:eu-central-1:553637109631:log-group:/ecs/javazone-no/*",
                              - "arn:aws:logs:eu-central-1:553637109631:log-group:/ecs/javazone-no/*:*",
                            ]
                        },
                    ]
                  - Version   = "2012-10-17"
                }
            ) -> null
        }
      - inline_policy {
          - name   = "ecr-push" -> null
          - policy = jsonencode(
                {
                  - Statement = [
                      - {
                          - Action   = [
                              - "ecr:GetAuthorizationToken",
                            ]
                          - Effect   = "Allow"
                          - Resource = "*"
                          - Sid      = "EcrAuth"
                        },
                      - {
                          - Action   = [
                              - "ecr:BatchCheckLayerAvailability",
                              - "ecr:PutImage",
                              - "ecr:InitiateLayerUpload",
                              - "ecr:UploadLayerPart",
                              - "ecr:CompleteLayerUpload",
                              - "ecr:GetDownloadUrlForLayer",
                              - "ecr:BatchGetImage",
                              - "ecr:CreateRepository",
                              - "ecr:DescribeRepositories",
                            ]
                          - Effect   = "Allow"
                          - Resource = "arn:aws:ecr:eu-central-1:553637109631:repository/javazone-no-*"
                          - Sid      = "EcrPush"
                        },
                    ]
                  - Version   = "2012-10-17"
                }
            ) -> null
        }
      - inline_policy {
          - name   = "ecs-deploy" -> null
          - policy = jsonencode(
                {
                  - Statement = [
                      - {
                          - Action    = [
                              - "ecs:UpdateService",
                              - "ecs:DescribeServices",
                            ]
                          - Condition = {
                              - StringEquals = {
                                  - "aws:ResourceTag/team" = "javazone-no"
                                }
                            }
                          - Effect    = "Allow"
                          - Resource  = "*"
                          - Sid       = "EcsServiceManagement"
                        },
                      - {
                          - Action   = [
                              - "ecs:DescribeTaskDefinition",
                              - "ecs:RegisterTaskDefinition",
                              - "ecs:DeregisterTaskDefinition",
                            ]
                          - Effect   = "Allow"
                          - Resource = "*"
                          - Sid      = "EcsTaskDefinitionManagement"
                        },
                      - {
                          - Action   = [
                              - "iam:PassRole",
                            ]
                          - Effect   = "Allow"
                          - Resource = [
                              - "arn:aws:iam::553637109631:role/javabin-ecs-execution",
                              - "arn:aws:iam::553637109631:role/javazone-no-*",
                            ]
                          - Sid      = "PassRole"
                        },
                    ]
                  - Version   = "2012-10-17"
                }
            ) -> null
        }
      - inline_policy {
          - name   = "ssm-read-overrides" -> null
          - policy = jsonencode(
                {
                  - Statement = [
                      - {
                          - Action   = [
                              - "ssm:GetParameter",
                              - "ssm:GetParameters",
                            ]
                          - Effect   = "Allow"
                          - Resource = "arn:aws:ssm:eu-central-1:553637109631:parameter/javabin/platform-overrides/*"
                        },
                    ]
                  - Version   = "2012-10-17"
                }
            ) -> null
        }
    }

  # module.iam.aws_iam_role.ci_deploy["javazone-work"] will be destroyed
  # (because key ["javazone-work"] is not in for_each map)
  - resource "aws_iam_role" "ci_deploy" {
      - arn                   = "arn:aws:iam::553637109631:role/javabin-ci-deploy-javazone-work" -> null
      - assume_role_policy    = jsonencode(
            {
              - Statement = [
                  - {
                      - Action    = "sts:AssumeRole"
                      - Effect    = "Allow"
                      - Principal = {
                          - AWS = "arn:aws:iam::553637109631:role/javabin-ci-broker"
                        }
                      - Sid       = "AllowViaCIBroker"
                    },
                ]
              - Version   = "2012-10-17"
            }
        ) -> null
      - create_date           = "2026-10-23T13:50:08Z" -> null
      - force_detach_policies = false -> null
      - id                    = "javabin-ci-deploy-javazone-work" -> null
      - managed_policy_arns   = [] -> null
      - max_session_duration  = 3600 -> null
      - name                  = "javabin-ci-deploy-javazone-work" -> null
      - path                  = "/" -> null
      - permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-developer-boundary" -> null
      - tags                  = {
          - "Name" = "javabin-ci-deploy-javazone-work"
          - "team" = "javazone-work"
        } -> null
      - tags_all              = {
          - "Name"        = "javabin-ci-deploy-javazone-work"
          - "environment" = "production"
          - "managed-by"  = "terraform"
          - "repo"        = "javaBin/platform"
          - "service"     = "platform"
          - "team"        = "javazone-work"
        } -> null
      - unique_id             = "AROAYBZ2X357VING4C52E" -> null

      - inline_policy {
          - name   = "cloudwatch-logs" -> null
          - policy = jsonencode(
                {
                  - Statement = [
                      - {
                          - Action   = [
                              - "logs:CreateLogGroup",
                              - "logs:CreateLogStream",
                              - "logs:PutLogEvents",
                            ]
                          - Effect   = "Allow"
                          - Resource = [
                              - "arn:aws:logs:eu-central-1:553637109631:log-group:/ecs/javazone-work/*",
                              - "arn:aws:logs:eu-central-1:553637109631:log-group:/ecs/javazone-work/*:*",
                            ]
                        },
                    ]
                  - Version   = "2012-10-17"
                }
            ) -> null
        }
      - inline_policy {
          - name   = "ecr-push" -> null
          - policy = jsonencode(
                {
                  - Statement = [
                      - {
                          - Action   = [
                              - "ecr:GetAuthorizationToken",
                            ]
                          - Effect   = "Allow"
                          - Resource = "*"
                          - Sid      = "EcrAuth"
                        },
                      - {
                          - Action   = [
                              - "ecr:BatchCheckLayerAvailability",
                              - "ecr:PutImage",
                              - "ecr:InitiateLayerUpload",
                              - "ecr:UploadLayerPart",
                              - "ecr:CompleteLayerUpload",
                              - "ecr:GetDownloadUrlForLayer",
                              - "ecr:BatchGetImage",
                              - "ecr:CreateRepository",
                              - "ecr:DescribeRepositories",
                            ]
                          - Effect   = "Allow"
                          - Resource = "arn:aws:ecr:eu-central-1:553637109631:repository/javazone-work-*"
                          - Sid      = "EcrPush"
                        },
                    ]
                  - Version   = "2012-10-17"
                }
            ) -> null
        }
      - inline_policy {
          - name   = "ecs-deploy" -> null
          - policy = jsonencode(
                {
                  - Statement = [
                      - {
                          - Action    = [
                              - "ecs:UpdateService",
                              - "ecs:DescribeServices",
                            ]
                          - Condition = {
                              - StringEquals = {
                                  - "aws:ResourceTag/team" = "javazone-work"
                                }
                            }
                          - Effect    = "Allow"
                          - Resource  = "*"
                          - Sid       = "EcsServiceManagement"
                        },
                      - {
                          - Action   = [
                              - "ecs:DescribeTaskDefinition",
                              - "ecs:RegisterTaskDefinition",
                              - "ecs:DeregisterTaskDefinition",
                            ]
                          - Effect   = "Allow"
                          - Resource = "*"
                          - Sid      = "EcsTaskDefinitionManagement"
                        },
                      - {
                          - Action   = [
                              - "iam:PassRole",
                            ]
                          - Effect   = "Allow"
                          - Resource = [
                              - "arn:aws:iam::553637109631:role/javabin-ecs-execution",
                              - "arn:aws:iam::553637109631:role/javazone-work-*",
                            ]
                          - Sid      = "PassRole"
                        },
                    ]
                  - Version   = "2012-10-17"
                }
            ) -> null
        }
      - inline_policy {
          - name   = "ssm-read-overrides" -> null
          - policy = jsonencode(
                {
                  - Statement = [
                      - {
                          - Action   = [
                              - "ssm:GetParameter",
                              - "ssm:GetParameters",
                            ]
                          - Effect   = "Allow"
                          - Resource = "arn:aws:ssm:eu-central-1:553637109631:parameter/javabin/platform-overrides/*"
                        },
                    ]
                  - Version   = "2012-10-17"
                }
            ) -> null
        }
    }

  # module.iam.aws_iam_role.ci_deploy["owners"] will be destroyed
  # (because key ["owners"] is not in for_each map)
  - resource "aws_iam_role" "ci_deploy" {
      - arn                   = "arn:aws:iam::553637109631:role/javabin-ci-deploy-owners" -> null
      - assume_role_policy    = jsonencode(
            {
              - Statement = [
                  - {
                      - Action    = "sts:AssumeRole"
                      - Effect    = "Allow"
                      - Principal = {
                          - AWS = "arn:aws:iam::553637109631:role/javabin-ci-broker"
                        }
                      - Sid       = "AllowViaCIBroker"
                    },
                ]
              - Version   = "2012-10-17"
            }
        ) -> null
      - create_date           = "2026-10-23T13:50:07Z" -> null
      - force_detach_policies = false -> null
      - id                    = "javabin-ci-deploy-owners" -> null
      - managed_policy_arns   = [] -> null
      - max_session_duration  = 3600 -> null
      - name                  = "javabin-ci-deploy-owners" -> null
      - path                  = "/" -> null
      - permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-developer-boundary" -> null
      - tags                  = {
          - "Name" = "javabin-ci-deploy-owners"
          - "team" = "owners"
        } -> null
      - tags_all              = {
          - "Name"        = "javabin-ci-deploy-owners"
          - "environment" = "production"
          - "managed-by"  = "terraform"
          - "repo"        = "javaBin/platform"
          - "service"     = "platform"
          - "team"        = "owners"
        } -> null
      - unique_id             = "AROAYBZ2X3576ZFNZPELG" -> null

      - inline_policy {
          - name   = "cloudwatch-logs" -> null
          - policy = jsonencode(
                {
                  - Statement = [
                      - {
                          - Action   = [
                              - "logs:CreateLogGroup",
                              - "logs:CreateLogStream",
                              - "logs:PutLogEvents",
                            ]
                          - Effect   = "Allow"
                          - Resource = [
                              - "arn:aws:logs:eu-central-1:553637109631:log-group:/ecs/owners/*",
                              - "arn:aws:logs:eu-central-1:553637109631:log-group:/ecs/owners/*:*",
                            ]
                        },
                    ]
                  - Version   = "2012-10-17"
                }
            ) -> null
        }
      - inline_policy {
          - name   = "ecr-push" -> null
          - policy = jsonencode(
                {
                  - Statement = [
                      - {
                          - Action   = [
                              - "ecr:GetAuthorizationToken",
                            ]
                          - Effect   = "Allow"
                          - Resource = "*"
                          - Sid      = "EcrAuth"
                        },
                      - {
                          - Action   = [
                              - "ecr:BatchCheckLayerAvailability",
                              - "ecr:PutImage",
                              - "ecr:InitiateLayerUpload",
                              - "ecr:UploadLayerPart",
                              - "ecr:CompleteLayerUpload",
                              - "ecr:GetDownloadUrlForLayer",
                              - "ecr:BatchGetImage",
                              - "ecr:CreateRepository",
                              - "ecr:DescribeRepositories",
                            ]
                          - Effect   = "Allow"
                          - Resource = "arn:aws:ecr:eu-central-1:553637109631:repository/owners-*"
                          - Sid      = "EcrPush"
                        },
                    ]
                  - Version   = "2012-10-17"
                }
            ) -> null
        }
      - inline_policy {
          - name   = "ecs-deploy" -> null
          - policy = jsonencode(
                {
                  - Statement = [
                      - {
                          - Action    = [
                              - "ecs:UpdateService",
                              - "ecs:DescribeServices",
                            ]
                          - Condition = {
                              - StringEquals = {
                                  - "aws:ResourceTag/team" = "owners"
                                }
                            }
                          - Effect    = "Allow"
                          - Resource  = "*"
                          - Sid       = "EcsServiceManagement"
                        },
                      - {
                          - Action   = [
                              - "ecs:DescribeTaskDefinition",
                              - "ecs:RegisterTaskDefinition",
                              - "ecs:DeregisterTaskDefinition",
                            ]
                          - Effect   = "Allow"
                          - Resource = "*"
                          - Sid      = "EcsTaskDefinitionManagement"
                        },
                      - {
                          - Action   = [
                              - "iam:PassRole",
                            ]
                          - Effect   = "Allow"
                          - Resource = [
                              - "arn:aws:iam::553637109631:role/javabin-ecs-execution",
                              - "arn:aws:iam::553637109631:role/owners-*",
                            ]
                          - Sid      = "PassRole"
                        },
                    ]
                  - Version   = "2012-10-17"
                }
            ) -> null
        }
      - inline_policy {
          - name   = "ssm-read-overrides" -> null
          - policy = jsonencode(
                {
                  - Statement = [
                      - {
                          - Action   = [
                              - "ssm:GetParameter",
                              - "ssm:GetParameters",
                            ]
                          - Effect   = "Allow"
                          - Resource = "arn:aws:ssm:eu-central-1:553637109631:parameter/javabin/platform-overrides/*"
                        },
                    ]
                  - Version   = "2012-10-17"
                }
            ) -> null
        }
    }

  # module.iam.aws_iam_role.ci_deploy["partnermanagement"] will be destroyed
  # (because key ["partnermanagement"] is not in for_each map)
  - resource "aws_iam_role" "ci_deploy" {
      - arn                   = "arn:aws:iam::553637109631:role/javabin-ci-deploy-partnermanagement" -> null
      - assume_role_policy    = jsonencode(
            {
              - Statement = [
                  - {
                      - Action    = "sts:AssumeRole"
                      - Effect    = "Allow"
                      - Principal = {
                          - AWS = "arn:aws:iam::553637109631:role/javabin-ci-broker"
                        }
                      - Sid       = "AllowViaCIBroker"
                    },
                ]
              - Version   = "2012-10-17"
            }
        ) -> null
      - create_date           = "2026-10-23T13:50:08Z" -> null
      - force_detach_policies = false -> null
      - id                    = "javabin-ci-deploy-partnermanagement" -> null
      - managed_policy_arns   = [] -> null
      - max_session_duration  = 3600 -> null
      - name                  = "javabin-ci-deploy-partnermanagement" -> null
      - path                  = "/" -> null
      - permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-developer-boundary" -> null
      - tags                  = {
          - "Name" = "javabin-ci-deploy-partnermanagement"
          - "team" = "partnermanagement"
        } -> null
      - tags_all              = {
          - "Name"        = "javabin-ci-deploy-partnermanagement"
          - "environment" = "production"
          - "managed-by"  = "terraform"
          - "repo"        = "javaBin/platform"
          - "service"     = "platform"
          - "team"        = "partnermanagement"
        } -> null
      - unique_id             = "AROAYBZ2X3575MZEFVNYP" -> null

      - inline_policy {
          - name   = "cloudwatch-logs" -> null
          - policy = jsonencode(
                {
                  - Statement = [
                      - {
                          - Action   = [
                              - "logs:CreateLogGroup",
                              - "logs:CreateLogStream",
                              - "logs:PutLogEvents",
                            ]
                          - Effect   = "Allow"
                          - Resource = [
                              - "arn:aws:logs:eu-central-1:553637109631:log-group:/ecs/partnermanagement/*",
                              - "arn:aws:logs:eu-central-1:553637109631:log-group:/ecs/partnermanagement/*:*",
                            ]
                        },
                    ]
                  - Version   = "2012-10-17"
                }
            ) -> null
        }
      - inline_policy {
          - name   = "ecr-push" -> null
          - policy = jsonencode(
                {
                  - Statement = [
                      - {
                          - Action   = [
                              - "ecr:GetAuthorizationToken",
                            ]
                          - Effect   = "Allow"
                          - Resource = "*"
                          - Sid      = "EcrAuth"
                        },
                      - {
                          - Action   = [
                              - "ecr:BatchCheckLayerAvailability",
                              - "ecr:PutImage",
                              - "ecr:InitiateLayerUpload",
                              - "ecr:UploadLayerPart",
                              - "ecr:CompleteLayerUpload",
                              - "ecr:GetDownloadUrlForLayer",
                              - "ecr:BatchGetImage",
                              - "ecr:CreateRepository",
                              - "ecr:DescribeRepositories",
                            ]
                          - Effect   = "Allow"
                          - Resource = "arn:aws:ecr:eu-central-1:553637109631:repository/partnermanagement-*"
                          - Sid      = "EcrPush"
                        },
                    ]
                  - Version   = "2012-10-17"
                }
            ) -> null
        }
      - inline_policy {
          - name   = "ecs-deploy" -> null
          - policy = jsonencode(
                {
                  - Statement = [
                      - {
                          - Action    = [
                              - "ecs:UpdateService",
                              - "ecs:DescribeServices",
                            ]
                          - Condition = {
                              - StringEquals = {
                                  - "aws:ResourceTag/team" = "partnermanagement"
                                }
                            }
                          - Effect    = "Allow"
                          - Resource  = "*"
                          - Sid       = "EcsServiceManagement"
                        },
                      - {
                          - Action   = [
                              - "ecs:DescribeTaskDefinition",
                              - "ecs:RegisterTaskDefinition",
                              - "ecs:DeregisterTaskDefinition",
                            ]
                          - Effect   = "Allow"
                          - Resource = "*"
                          - Sid      = "EcsTaskDefinitionManagement"
                        },
                      - {
                          - Action   = [
                              - "iam:PassRole",
                            ]
                          - Effect   = "Allow"
                          - Resource = [
                              - "arn:aws:iam::553637109631:role/javabin-ecs-execution",
                              - "arn:aws:iam::553637109631:role/partnermanagement-*",
                            ]
                          - Sid      = "PassRole"
                        },
                    ]
                  - Version   = "2012-10-17"
                }
            ) -> null
        }
      - inline_policy {
          - name   = "ssm-read-overrides" -> null
          - policy = jsonencode(
                {
                  - Statement = [
                      - {
                          - Action   = [
                              - "ssm:GetParameter",
                              - "ssm:GetParameters",
                            ]
                          - Effect   = "Allow"
                          - Resource = "arn:aws:ssm:eu-central-1:553637109631:parameter/javabin/platform-overrides/*"
                        },
                    ]
                  - Version   = "2012-10-17"
                }
            ) -> null
        }
    }

  # module.iam.aws_iam_role.ci_deploy["team-apps"] will be destroyed
  # (because key ["team-apps"] is not in for_each map)
  - resource "aws_iam_role" "ci_deploy" {
      - arn                   = "arn:aws:iam::553637109631:role/javabin-ci-deploy-team-apps" -> null
      - assume_role_policy    = jsonencode(
            {
              - Statement = [
                  - {
                      - Action    = "sts:AssumeRole"
                      - Effect    = "Allow"
                      - Principal = {
                          - AWS = "arn:aws:iam::553637109631:role/javabin-ci-broker"
                        }
                      - Sid       = "AllowViaCIBroker"
                    },
                ]
              - Version   = "2012-10-17"
            }
        ) -> null
      - create_date           = "2026-10-23T13:50:07Z" -> null
      - force_detach_policies = false -> null
      - id                    = "javabin-ci-deploy-team-apps" -> null
      - managed_policy_arns   = [] -> null
      - max_session_duration  = 3600 -> null
      - name                  = "javabin-ci-deploy-team-apps" -> null
      - path                  = "/" -> null
      - permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-

LLM Review

Risk: 🔴 HIGH

Plan destroys multiple ci_deploy team IAM roles (cake, commandchimps, developer, java-no, and likely more truncated) and modifies the shared developer permissions boundary, which is high-impact for CI access across teams.

  • 💥 [destruction] Multiple module.iam.aws_iam_role.ci_deploy[...] resources (cake, commandchimps, developer, java-no, and others in the truncated output) will be destroyed because their keys are missing from the for_each map. Their inline policies (ECR push, ECS deploy, PassRole, SSM read) go with them, so those teams' CI deploy pipelines will break. Confirm whether the team removal is intentional; the output is truncated, so the full destroy list is unknown.
  • 🔒 [security] module.iam.aws_iam_policy.developer_boundary is updated in place. It adds ec2:AuthorizeSecurityGroup* and ec2:RevokeSecurityGroup* to an allowed action set, and changes the NotResource list for iam:PassRole, replacing javabin-ecs-execution with javabin-ecs-exec-${team}. Since this boundary is attached to all CI deploy roles, it widens what developer roles can do with security groups and changes which execution role they can pass. Review the intent carefully, because security group changes can expose services to the internet.
  • 🔒 [security] The DenyTagStrip statement is unchanged and protects shared and platform tags, but the new SG permissions sit alongside the existing boundary. Verify that the new ec2 SG actions do not bypass the DenyXTeam condition for resources without a team tag.
  • 🔒 [security] The boundary's DenyPlatSSM statement protects /javabin/platform/* and /javabin/slack/*. Only the PassRole and SG changes are in view, so confirm no SSM deny rules were removed in the truncated section.
  • ✅ [routine] Plan is truncated after the first destroy entries, so the complete set of changes (including any Lambda, networking, or DNS changes in the remaining output) cannot be verified. Obtain the full plan before applying.

Moved to its own PR: switching to registry teams destroys the roles of 21
non-app org teams (148 resources), which plans HIGH and needs a board
override. The security fixes here should not wait on that.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Terraform Plan

🚧 Changes detected — Plan: 72 to add, 27 to change, 1 to destroy.

Plan output
aws_ssm_parameter.atlassian_api_key: Refreshing state... [id=/javabin/platform/atlassian-api-key]
aws_ssm_parameter.atlassian_org_id: Refreshing state... [id=/javabin/platform/atlassian-org-id]

Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
  + create
  ~ update in-place
  - destroy

Terraform will perform the following actions:

  # module.iam.aws_iam_policy.developer_boundary will be updated in-place
  ~ resource "aws_iam_policy" "developer_boundary" {
        id               = "arn:aws:iam::553637109631:policy/javabin-developer-boundary"
        name             = "javabin-developer-boundary"
      ~ policy           = jsonencode(
          ~ {
              ~ Statement = [
                    # (9 unchanged elements hidden)
                    {
                        Action      = "*"
                        Condition   = {
                            Null            = {
                                "aws:ResourceTag/team" = "false"
                            }
                            StringNotEquals = {
                                "aws:ResourceTag/team" = [
                                    "${aws:PrincipalTag/team}",
                                    "shared",
                                ]
                            }
                        }
                        Effect      = "Deny"
                        NotResource = [
                            "arn:aws:s3:::javabin-terraform-state-553637109631",
                            "arn:aws:s3:::javabin-terraform-state-553637109631/*",
                            "arn:aws:dynamodb:eu-central-1:553637109631:table/javabin-terraform-app-locks",
                            "arn:aws:s3:::javabin-ci-plan-artifacts-553637109631",
                            "arn:aws:s3:::javabin-ci-plan-artifacts-553637109631/*",
                        ]
                        Sid         = "DenyXTeam"
                    },
                  ~ {
                      ~ Action    = [
                            # (15 unchanged elements hidden)
                            "sns:SetTopicAttributes",
                          + "ec2:AuthorizeSecurityGroup*",
                          + "ec2:RevokeSecurityGroup*",
                        ]
                        # (4 unchanged attributes hidden)
                    },
                    {
                        Action    = [
                            "ec2:DeleteTags",
                            "ec2:CreateTags",
                            "ecs:TagResource",
                            "ecs:UntagResource",
                            "elasticloadbalancing:AddTags",
                            "elasticloadbalancing:RemoveTags",
                            "iam:TagRole",
                            "iam:UntagRole",
                            "sns:TagResource",
                            "sns:UntagResource",
                        ]
                        Condition = {
                            StringEquals = {
                                "aws:ResourceTag/team" = [
                                    "shared",
                                    "platform",
                                ]
                            }
                        }
                        Effect    = "Deny"
                        Resource  = "*"
                        Sid       = "DenyTagStrip"
                    },
                    {
                        Action   = [
                            "ssm:GetParameter*",
                            "ssm:GetParametersByPath",
                        ]
                        Effect   = "Deny"
                        Resource = [
                            "arn:aws:ssm:*:*:parameter/javabin/platform/*",
                            "arn:aws:ssm:*:*:parameter/javabin/slack/*",
                            "arn:aws:ssm:*:*:parameter/javabin/platform-overrides/*",
                        ]
                        Sid      = "DenyPlatSSM"
                    },
                  ~ {
                      ~ NotResource = [
                            "arn:aws:iam::*:role/${aws:PrincipalTag/team}-*",
                          - "arn:aws:iam::*:role/javabin-ecs-execution",
                          + "arn:aws:iam::*:role/javabin-ecs-exec-${aws:PrincipalTag/team}",
                        ]
                        # (3 unchanged attributes hidden)
                    },
                    {
                        Action      = [
                            "logs:GetLogEvents",
                            "logs:FilterLogEvents",
                            "logs:StartQuery",
                            "logs:GetQueryResults",
                        ]
                        Effect      = "Deny"
                        NotResource = [
                            "arn:aws:logs:*:*:log-group:/ecs/${aws:PrincipalTag/team}/*",
                            "arn:aws:logs:*:*:log-group:/ecs/${aws:PrincipalTag/team}/*:*",
                        ]
                        Sid         = "DenyXLogs"
                    },
                    # (3 unchanged elements hidden)
                ]
                # (1 unchanged attribute hidden)
            }
        )
        tags             = {
            "Name" = "javabin-developer-boundary"
        }
        # (6 unchanged attributes hidden)
    }

  # module.iam.aws_iam_role.ecs_exec_team["cake"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-cake"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-cake"
          + "for-team" = "cake"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-cake"
          + "environment" = "production"
          + "for-team"    = "cake"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["commandchimps"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-commandchimps"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-commandchimps"
          + "for-team" = "commandchimps"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-commandchimps"
          + "environment" = "production"
          + "for-team"    = "commandchimps"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["cupcake"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-cupcake"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-cupcake"
          + "for-team" = "cupcake"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-cupcake"
          + "environment" = "production"
          + "for-team"    = "cupcake"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["developer"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-developer"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-developer"
          + "for-team" = "developer"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-developer"
          + "environment" = "production"
          + "for-team"    = "developer"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["java-no"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-java-no"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-java-no"
          + "for-team" = "java-no"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-java-no"
          + "environment" = "production"
          + "for-team"    = "java-no"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["javazone-no"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-javazone-no"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-javazone-no"
          + "for-team" = "javazone-no"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-javazone-no"
          + "environment" = "production"
          + "for-team"    = "javazone-no"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["javazone-work"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-javazone-work"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-javazone-work"
          + "for-team" = "javazone-work"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-javazone-work"
          + "environment" = "production"
          + "for-team"    = "javazone-work"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["jzwatch"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-jzwatch"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-jzwatch"
          + "for-team" = "jzwatch"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-jzwatch"
          + "environment" = "production"
          + "for-team"    = "jzwatch"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["owners"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-owners"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-owners"
          + "for-team" = "owners"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-owners"
          + "environment" = "production"
          + "for-team"    = "owners"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["partnermanagement"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-partnermanagement"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-partnermanagement"
          + "for-team" = "partnermanagement"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-partnermanagement"
          + "environment" = "production"
          + "for-team"    = "partnermanagement"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["team-apps"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-team-apps"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-team-apps"
          + "for-team" = "team-apps"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-team-apps"
          + "environment" = "production"
          + "for-team"    = "team-apps"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["team-cibus"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-team-cibus"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-team-cibus"
          + "for-team" = "team-cibus"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-team-cibus"
          + "environment" = "production"
          + "for-team"    = "team-cibus"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["team-cibus2"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-team-cibus2"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-team-cibus2"
          + "for-team" = "team-cibus2"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-team-cibus2"
          + "environment" = "production"
          + "for-team"    = "team-cibus2"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["team-ems"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-team-ems"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-team-ems"
          + "for-team" = "team-ems"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-team-ems"
          + "environment" = "production"
          + "for-team"    = "team-ems"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["team-incogito"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-team-incogito"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-team-incogito"
          + "for-team" = "team-incogito"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-team-incogito"
          + "environment" = "production"
          + "for-team"    = "team-incogito"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["team-javazone-badge"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-team-javazone-badge"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-team-javazone-badge"
          + "for-team" = "team-javazone-badge"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-team-javazone-badge"
          + "environment" = "production"
          + "for-team"    = "team-javazone-badge"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["team-javazone-video"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-team-javazone-video"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-team-javazone-video"
          + "for-team" = "team-javazone-video"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-team-javazone-video"
          + "environment" = "production"
          + "for-team"    = "team-javazone-video"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["team-jz-text-adventure"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-team-jz-text-adventure"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-team-jz-text-adventure"
          + "for-team" = "team-jz-text-adventure"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-team-jz-text-adventure"
          + "environment" = "production"
          + "for-team"    = "team-jz-text-adventure"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["team-portal"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-team-portal"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-team-portal"
          + "for-team" = "team-portal"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-team-portal"
          + "environment" = "production"
          + "for-team"    = "team-portal"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["team-scala-training-code"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-team-scala-training-code"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-team-scala-training-code"
          + "for-team" = "team-scala-training-code"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-team-scala-training-code"
          + "environment" = "production"
          + "for-team"    = "team-scala-training-code"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["team-submitit"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-team-submitit"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-team-submitit"
          + "for-team" = "team-submitit"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-team-submitit"
          + "environment" = "production"
          + "for-team"    = "team-submitit"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["teammoosehead"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-teammoosehead"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-teammoosehead"
          + "for-team" = "teammoosehead"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-teammoosehead"
          + "environment" = "production"
          + "for-team"    = "teammoosehead"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["teamteknologihuset"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-teamteknologihuset"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-teamteknologihuset"
          + "for-team" = "teamteknologihuset"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-teamteknologihuset"
          + "environment" = "production"
          + "for-team"    = "teamteknologihuset"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["testteam"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-testteam"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-testteam"
          + "for-team" = "testteam"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-testteam"
          + "environment" = "production"
          + "for-team"    = "testteam"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role_policy.ci_deploy_ecs["cake"] will be updated in-place
  ~ resource "aws_iam_role_policy" "ci_deploy_ecs" {
        id     = "javabin-ci-deploy-cake:ecs-deploy"
        name   = "ecs-deploy"
      ~ policy = jsonencode(
            {
              - Statement = [
                  - {
                      - Action    = [
                          - "ecs:UpdateService",
                          - "ecs:DescribeServices",
                        ]
                      - Condition = {
                          - StringEquals = {
                              - "aws:ResourceTag/team" = "cake"
                            }
                        }
                      - Effect    = "Allow"
                      - Resource  = "*"
                      - Sid       = "EcsServiceManagement"
                    },
                  - {
                      - Action   = [
                          - "ecs:DescribeTaskDefinition",
                          - "ecs:RegisterTaskDefinition",
                          - "ecs:DeregisterTaskDefinition",
                        ]
                      - Effect   = "Allow"
                      - Resource = "*"
                      - Sid      = "EcsTaskDefinitionManagement"
                    },
                  - {
                      - Action   = [
                          - "iam:PassRole",
                        ]
                      - Effect   = "Allow"
                      - Resource = [
                          - "arn:aws:iam::553637109631:role/javabin-ecs-execution",
                          - "arn:aws:iam::553637109631:role/cake-*",
                        ]
                      - Sid      = "PassRole"
                    },
                ]
              - Version   = "2012-10-17"
            }
        ) -> (known after apply)
        # (1 unchanged attribute hidden)
    }

  # module.iam.aws_iam_role_policy.ci_deploy_ecs["commandchimps"] will be updated in-place
  ~ resource "aws_iam_role_policy" "ci_deploy_ecs" {
        id     = "javabin-ci-deploy-commandchimps:ecs-deploy"
        name   = "ecs-deploy"
      ~ policy = jsonencode(
            {
              - Statement = [
                  - {
                      - Action    = [
                          - "ecs:UpdateService",
                          - "ecs:DescribeServices",
                        ]
                      - Condition = {
                          - StringEquals = {
                              - "aws:ResourceTag/team" = "commandchimps"
                            }
                        }
                      - Effect    = "Allow"
                      - Resource  = "*"
                      - Sid       = "EcsServiceManagement"
                    },
                  - {
                      - Action   = [
                          - "ecs:DescribeTaskDefinition",
                          - "ecs:RegisterTaskDefinition",
                          - "ecs:DeregisterTaskDefinition",
                        ]
                      - Effect   = "Allow"
                      - Resource = "*"
                      - Sid      = "EcsTaskDefinitionManagement"
                    },
                  - {
                      - Action   = [
                          - "iam:PassRole",
                        ]
                      - Effect   = "Allow"
                      - Resource = [
                          - "arn:aws:iam::553637109631:role/javabin-ecs-execution",
                          - "arn:aws:iam::553637109631:role/commandchimps-*",
                        ]
                      - Sid      = "PassRole"
                    },
                ]
              - Version   = "2012-10-17"
            }
        ) -> (known after apply)
        # (1 unchanged attribute hidden)
    }

  # module.iam.aws_iam_role_policy.ci_deploy_ecs["cupcake"] will be updated in-place
  ~ resource "aws_iam_role_policy" "ci_deploy_ecs" {
        id     = "javabin-ci-deploy-cupcake:ecs-deploy"
        name   = "ecs-deploy"
      ~ policy = jsonencode(
            {
              - Statement = [
                  - {
                      - Action    = [
                          - "ecs:UpdateService",
                          - "ecs:DescribeServices",
                        ]
                      - Condition = {
                          - StringEquals = {
                              - "aws:ResourceTag/team" = "cupcake"
                            }
                        }
                      - Effect    = "Allow"
                      - Resource  = "*"
                      - Sid       = "EcsServiceManagement"
                    },
                  - {
                      - Action   = [
                          - "ecs:DescribeTaskDefinition",
                          - "ecs:RegisterTaskDefinition",
                          - "ecs:DeregisterTaskDefinition",
                        ]
                      - Effect   = "Allow"
                      - Resource = "*"
                      - Sid      = "EcsTaskDefinitionManagement"
                    },
                  - {
                      - Action   = [
                          - "iam:PassRole",
                        ]
                      - Effect   = "Allow"
                      - Resource = [
                          - "arn:aws:iam::553637109631:role/javabin-ecs-execution",
                          - "arn:aws:iam::553637109631:role/cupcake-*",
                        ]
                      - Sid      = "PassRole"
                    },
                ]
              - Version   = "2012-10-17"
            }
        ) -> (known after apply)
        # (1 unchanged attribute hidden)
    }

  # module.iam.aws_iam_role_policy.ci_deploy_ecs["developer"] will be updated in-place
  ~ resource "aws_iam_role_policy" "ci_deploy_ecs" {
        id     = "javabin-ci-deploy-developer:ecs-deploy"
        name   = "ecs-deploy"
      ~ policy = jsonencode(
            {
              - Statement = [
                  - {
                      - Action    = [
                          - "ecs:UpdateService",
                          - "ecs:DescribeServices",
                        ]
                      - Condition = {
                          - StringEquals = {
                              - "aws:ResourceTag/team" = "developer"
                            }
                        }
                      - Effect    = "Allow"
                      - Resource  = "*"
                      - Sid       = "EcsServiceManagement"
                    },
                  - {
                      - Action   = [
                          - "ecs:DescribeTaskDefinition",
                          - "ecs:RegisterTaskDefinition",
                          - "ecs:DeregisterTaskDefinition",
                        ]
                      - Effect   = "Allow"
                      - Resource = "*"
                      - Sid      = "EcsTaskDefinitionManagement"
                    },
                  - {
                      - Action   = [
                          - "iam:PassRole",
                        ]
                      - Effect   = "Allow"
                      - Resource = [
                          - "arn:aws:iam::553637109631:role/javabin-ecs-execution",
                          - "arn:aws:iam::553637109631:role/developer-*",
                        ]
                      - Sid      = "PassRole"
                    },
                ]
              - Version   = "2012-10-17"
            }
        ) -> (known after apply)
        # (1 unchanged attribute hidden)
    }

  # module.iam.aws_iam_role_policy.ci_deploy_ecs["java-no"] will be updated in-place
  ~ resource "aws_iam_role_policy" "ci_deploy_ecs" {
        id     = "javabin-ci-deploy-java-no:ecs-deploy"
        name   = "ecs-deploy"
      ~ policy = jsonencode(
            {
              - Statement = [
                  - {
                      - Action    = [
                          - "ecs:UpdateService",
                          - "ecs:DescribeServices",
                        ]
                      - Condition = {
                          - StringEquals = {
                              - "aws:ResourceTag/team" = "java-no"
                            }
                        }
                      - Effect    = "Allow"
                      - Resource  = "*"
                      - Sid       = "EcsServiceManagement"
                    },
                  - {
                      - Action   = [
                          - "ecs:DescribeTaskDefinition",
                          - "ecs:RegisterTaskDefinition",
                          - "ecs:DeregisterTaskDefinition",
                        ]
                      - Effect   = "Allow"
                      - Resource = "*"
                      - Sid      = "EcsTaskDefinitionManagement"
                    },
                  - {
                      - Action   = [
                          - "iam:PassRole",
                        ]
                      - Effect   = "Allow"
                      - Resource = [
                          - "arn:aws:iam::553637109631:role/javabin-ecs-execution",
                          - "arn:aws:iam::553637109631:role/java-no-*",
                        ]
                      - Sid      = "PassRole"
                    },
                ]
              - Version   = "2012-10-17"
            }
        ) -> (known after apply)
        # (1 unchanged attribute hidden)
    }

  # module.iam.aws_iam_role_policy.ci_deploy_ecs["javazone-no"] will be updated in-place
  ~ resource "aws_iam_role_policy" "ci_deploy_ecs" {
        id     = "javabin-ci-deploy-javazone-no:ecs-deploy"
        name   = "ecs-deploy"
      ~ policy = jsonencode(
            {
              - Statement = [
                  - {
                      - Action    = [
                          - "ecs:UpdateService",
                          - "ecs:DescribeServices",
                        ]
                      - Condition = {
                          - StringEquals = {
                              - "aws:ResourceTag/team" = "javazone-no"
                            }
                        }
                      - Effect    = "Allow"
                      - Resource  = "*"
                      - Sid       = "EcsServiceManagement"
                    },
                  - {
                      - Action   = [
                          - "ecs:DescribeTaskDefinition",
                          - "ecs:RegisterTaskDefinition",
                          - "ecs:DeregisterTaskDefinition",
                        ]
                      - Effect   = "Allow"
                      - Resource = "*"
                      - Sid      = "EcsTaskDefinitionManagement"
                    },
                  - {
                      - Action   = [
                          - "iam:PassRole",
                        ]
                      - Effect   = "Allow"
                      - Resource = [
                          - "arn:aws:iam::553637109631:role/javabin-ecs-execution",
                          - "arn:aws:iam::553637109631:role/javazone-no-*",
                        ]
                      - Sid      = "PassRole"
                    },
                ]
              - Version   = "2012-10-17"
            }
        ) -> (known after apply)
        # (1 unchanged attribute hidden)
    }

  # module.iam.aws_iam_role_policy.ci_deploy_ecs["javazone-work"] will be updated in-place
  ~ resource "aws_iam_role_policy" "ci_deploy_ecs" {
        id     = "javabin-ci-deploy-javazone-work:ecs-deploy"
        name   = "ecs-deploy"
      ~ policy = jsonencode(
            {
              - Statement = [
                  - {
                      - Action    = [
                          - "ecs:UpdateService",
                          - "ecs:DescribeServices",
                        ]
                      - Condition = {
                          - StringEquals = {
                              - "aws:ResourceTag/team" = "javazone-work"
                            }
                        }
                      - Effect    = "Allow"
                      - Resource  = "*"
                      - Sid       = "EcsServiceManagement"
                    },
                  - {
                      - Action   = [
                          - "ecs:DescribeTaskDefinition",
                          - "ecs:RegisterTaskDefinition",
                          - "ecs:DeregisterTaskDefinition",
                        ]
                      - Effect   = "Allow"
                      - Resource = "*"
                      - Sid      = "EcsTaskDefinitionManagement"
                    },
                  - {
                      - Action   = [
                          - "iam:PassRole",
                        ]
                      - Effect   = "Allow"
                      - Resource = [
                          - "arn:aws:iam::553637109631:role/javabin-ecs-execution",
                          - "arn:aws:iam::553637109631:role/javazone-work-*",
                        ]
                      - Sid      = "PassRole"
                    },
                ]
              - Version   = "2012-10-17"
            }
        ) -> (known after apply)
        # (1 unchanged attribute hidden)
    }

  # module.iam.aws_iam_role_policy.ci_deploy_ecs["jzwatch"] will be updated in-place
  ~ resource "aws_iam_role_policy" "ci_deploy_ecs" {
        id     = "javabin-ci-deploy-jzwatch:ecs-deploy"
        name   = "ecs-deploy"
      ~ policy = jsonencode(
            {
              - Statement = [
                  - {
                      - Action    = [
                          - "ecs:UpdateService",
                          - "ecs:DescribeServices",
                        ]
                      - Condition = {
                          - StringEquals = {
                              - "aws:ResourceTag/team" = "jzwatch"
                            }
                        }
                      - Effect    = "Allow"
                      - Resource  = "*"
                      - Sid       = "EcsServiceManagement"
                    },
                  - {
                      - Action   = [
                          - "ecs:DescribeTaskDefinition",
                          - "ecs:RegisterTaskDefinition",
                          - "ecs:DeregisterTaskDefinition",
                        ]
                

LLM Review

Risk: 🟡 MEDIUM

Plan updates the developer permissions boundary (adds EC2 security group authorize/revoke actions and changes the ECS execution role exception), and creates per-team ECS execution roles, all carrying the org permissions boundary; no destruction or database changes are visible in the captured portion.

  • 🔒 [security] Developer permissions boundary adds ec2:AuthorizeSecurityGroup* and ec2:RevokeSecurityGroup* to an allowed action set. Developers may be able to open security groups, including to 0.0.0.0/0, which is a meaningful loosening. Confirm this is intended and that the DenyXTeam / tag conditions still prevent changes to platform-owned security groups.
  • 🔒 [security] The NotResource exception for the ECS execution role changes from the shared javabin-ecs-execution role to javabin-ecs-exec-${aws:PrincipalTag/team}. The per-team roles are created in this plan. Verify the new naming pattern cannot be used to reach other roles and that the existing javabin-ecs-execution role's protections are not silently lost.
  • 🔒 [security] Thirteen-plus per-team ECS execution roles (javabin-ecs-exec-) are created with the javabin-org-boundary permissions boundary, which is good. Their trust policy is ecs-tasks.amazonaws.com only. Review the attached policies (not visible in the truncated output) before apply.
  • ✅ [routine] The tags on the new roles set team = "shared" while for-team carries the actual team name. This may interact with the tag-based Deny conditions in the boundary (aws:ResourceTag/team) and should be checked for unintended effects.
  • 💥 [destruction] No resource destruction is visible in the captured portion of the plan. The output was truncated, so the full set of changes (including any replacements or deletions) cannot be confirmed. Review the complete plan before applying.

The previous revert also undid the CLAUDE.md entries for the execution
roles, the OIDC token script and the broker fix.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Terraform Plan

🚧 Changes detected — Plan: 72 to add, 27 to change, 1 to destroy.

Plan output
Acquiring state lock. This may take a few moments...
aws_ssm_parameter.atlassian_org_id: Refreshing state... [id=/javabin/platform/atlassian-org-id]
aws_ssm_parameter.atlassian_api_key: Refreshing state... [id=/javabin/platform/atlassian-api-key]

Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
  + create
  ~ update in-place
  - destroy

Terraform will perform the following actions:

  # module.iam.aws_iam_policy.developer_boundary will be updated in-place
  ~ resource "aws_iam_policy" "developer_boundary" {
        id               = "arn:aws:iam::553637109631:policy/javabin-developer-boundary"
        name             = "javabin-developer-boundary"
      ~ policy           = jsonencode(
          ~ {
              ~ Statement = [
                    # (9 unchanged elements hidden)
                    {
                        Action      = "*"
                        Condition   = {
                            Null            = {
                                "aws:ResourceTag/team" = "false"
                            }
                            StringNotEquals = {
                                "aws:ResourceTag/team" = [
                                    "${aws:PrincipalTag/team}",
                                    "shared",
                                ]
                            }
                        }
                        Effect      = "Deny"
                        NotResource = [
                            "arn:aws:s3:::javabin-terraform-state-553637109631",
                            "arn:aws:s3:::javabin-terraform-state-553637109631/*",
                            "arn:aws:dynamodb:eu-central-1:553637109631:table/javabin-terraform-app-locks",
                            "arn:aws:s3:::javabin-ci-plan-artifacts-553637109631",
                            "arn:aws:s3:::javabin-ci-plan-artifacts-553637109631/*",
                        ]
                        Sid         = "DenyXTeam"
                    },
                  ~ {
                      ~ Action    = [
                            # (15 unchanged elements hidden)
                            "sns:SetTopicAttributes",
                          + "ec2:AuthorizeSecurityGroup*",
                          + "ec2:RevokeSecurityGroup*",
                        ]
                        # (4 unchanged attributes hidden)
                    },
                    {
                        Action    = [
                            "ec2:DeleteTags",
                            "ec2:CreateTags",
                            "ecs:TagResource",
                            "ecs:UntagResource",
                            "elasticloadbalancing:AddTags",
                            "elasticloadbalancing:RemoveTags",
                            "iam:TagRole",
                            "iam:UntagRole",
                            "sns:TagResource",
                            "sns:UntagResource",
                        ]
                        Condition = {
                            StringEquals = {
                                "aws:ResourceTag/team" = [
                                    "shared",
                                    "platform",
                                ]
                            }
                        }
                        Effect    = "Deny"
                        Resource  = "*"
                        Sid       = "DenyTagStrip"
                    },
                    {
                        Action   = [
                            "ssm:GetParameter*",
                            "ssm:GetParametersByPath",
                        ]
                        Effect   = "Deny"
                        Resource = [
                            "arn:aws:ssm:*:*:parameter/javabin/platform/*",
                            "arn:aws:ssm:*:*:parameter/javabin/slack/*",
                            "arn:aws:ssm:*:*:parameter/javabin/platform-overrides/*",
                        ]
                        Sid      = "DenyPlatSSM"
                    },
                  ~ {
                      ~ NotResource = [
                            "arn:aws:iam::*:role/${aws:PrincipalTag/team}-*",
                          - "arn:aws:iam::*:role/javabin-ecs-execution",
                          + "arn:aws:iam::*:role/javabin-ecs-exec-${aws:PrincipalTag/team}",
                        ]
                        # (3 unchanged attributes hidden)
                    },
                    {
                        Action      = [
                            "logs:GetLogEvents",
                            "logs:FilterLogEvents",
                            "logs:StartQuery",
                            "logs:GetQueryResults",
                        ]
                        Effect      = "Deny"
                        NotResource = [
                            "arn:aws:logs:*:*:log-group:/ecs/${aws:PrincipalTag/team}/*",
                            "arn:aws:logs:*:*:log-group:/ecs/${aws:PrincipalTag/team}/*:*",
                        ]
                        Sid         = "DenyXLogs"
                    },
                    # (3 unchanged elements hidden)
                ]
                # (1 unchanged attribute hidden)
            }
        )
        tags             = {
            "Name" = "javabin-developer-boundary"
        }
        # (6 unchanged attributes hidden)
    }

  # module.iam.aws_iam_role.ecs_exec_team["cake"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-cake"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-cake"
          + "for-team" = "cake"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-cake"
          + "environment" = "production"
          + "for-team"    = "cake"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["commandchimps"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-commandchimps"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-commandchimps"
          + "for-team" = "commandchimps"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-commandchimps"
          + "environment" = "production"
          + "for-team"    = "commandchimps"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["cupcake"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-cupcake"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-cupcake"
          + "for-team" = "cupcake"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-cupcake"
          + "environment" = "production"
          + "for-team"    = "cupcake"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["developer"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-developer"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-developer"
          + "for-team" = "developer"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-developer"
          + "environment" = "production"
          + "for-team"    = "developer"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["java-no"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-java-no"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-java-no"
          + "for-team" = "java-no"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-java-no"
          + "environment" = "production"
          + "for-team"    = "java-no"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["javazone-no"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-javazone-no"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-javazone-no"
          + "for-team" = "javazone-no"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-javazone-no"
          + "environment" = "production"
          + "for-team"    = "javazone-no"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["javazone-work"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-javazone-work"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-javazone-work"
          + "for-team" = "javazone-work"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-javazone-work"
          + "environment" = "production"
          + "for-team"    = "javazone-work"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["jzwatch"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-jzwatch"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-jzwatch"
          + "for-team" = "jzwatch"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-jzwatch"
          + "environment" = "production"
          + "for-team"    = "jzwatch"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["owners"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-owners"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-owners"
          + "for-team" = "owners"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-owners"
          + "environment" = "production"
          + "for-team"    = "owners"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["partnermanagement"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-partnermanagement"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-partnermanagement"
          + "for-team" = "partnermanagement"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-partnermanagement"
          + "environment" = "production"
          + "for-team"    = "partnermanagement"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["team-apps"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-team-apps"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-team-apps"
          + "for-team" = "team-apps"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-team-apps"
          + "environment" = "production"
          + "for-team"    = "team-apps"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["team-cibus"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-team-cibus"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-team-cibus"
          + "for-team" = "team-cibus"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-team-cibus"
          + "environment" = "production"
          + "for-team"    = "team-cibus"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["team-cibus2"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-team-cibus2"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-team-cibus2"
          + "for-team" = "team-cibus2"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-team-cibus2"
          + "environment" = "production"
          + "for-team"    = "team-cibus2"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["team-ems"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-team-ems"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-team-ems"
          + "for-team" = "team-ems"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-team-ems"
          + "environment" = "production"
          + "for-team"    = "team-ems"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["team-incogito"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-team-incogito"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-team-incogito"
          + "for-team" = "team-incogito"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-team-incogito"
          + "environment" = "production"
          + "for-team"    = "team-incogito"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["team-javazone-badge"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-team-javazone-badge"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-team-javazone-badge"
          + "for-team" = "team-javazone-badge"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-team-javazone-badge"
          + "environment" = "production"
          + "for-team"    = "team-javazone-badge"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["team-javazone-video"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-team-javazone-video"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-team-javazone-video"
          + "for-team" = "team-javazone-video"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-team-javazone-video"
          + "environment" = "production"
          + "for-team"    = "team-javazone-video"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["team-jz-text-adventure"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-team-jz-text-adventure"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-team-jz-text-adventure"
          + "for-team" = "team-jz-text-adventure"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-team-jz-text-adventure"
          + "environment" = "production"
          + "for-team"    = "team-jz-text-adventure"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["team-portal"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-team-portal"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-team-portal"
          + "for-team" = "team-portal"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-team-portal"
          + "environment" = "production"
          + "for-team"    = "team-portal"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["team-scala-training-code"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-team-scala-training-code"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-team-scala-training-code"
          + "for-team" = "team-scala-training-code"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-team-scala-training-code"
          + "environment" = "production"
          + "for-team"    = "team-scala-training-code"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["team-submitit"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-team-submitit"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-team-submitit"
          + "for-team" = "team-submitit"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-team-submitit"
          + "environment" = "production"
          + "for-team"    = "team-submitit"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["teammoosehead"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-teammoosehead"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-teammoosehead"
          + "for-team" = "teammoosehead"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-teammoosehead"
          + "environment" = "production"
          + "for-team"    = "teammoosehead"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["teamteknologihuset"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-teamteknologihuset"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-teamteknologihuset"
          + "for-team" = "teamteknologihuset"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-teamteknologihuset"
          + "environment" = "production"
          + "for-team"    = "teamteknologihuset"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["testteam"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-testteam"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-testteam"
          + "for-team" = "testteam"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-testteam"
          + "environment" = "production"
          + "for-team"    = "testteam"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role_policy.ci_deploy_ecs["cake"] will be updated in-place
  ~ resource "aws_iam_role_policy" "ci_deploy_ecs" {
        id     = "javabin-ci-deploy-cake:ecs-deploy"
        name   = "ecs-deploy"
      ~ policy = jsonencode(
            {
              - Statement = [
                  - {
                      - Action    = [
                          - "ecs:UpdateService",
                          - "ecs:DescribeServices",
                        ]
                      - Condition = {
                          - StringEquals = {
                              - "aws:ResourceTag/team" = "cake"
                            }
                        }
                      - Effect    = "Allow"
                      - Resource  = "*"
                      - Sid       = "EcsServiceManagement"
                    },
                  - {
                      - Action   = [
                          - "ecs:DescribeTaskDefinition",
                          - "ecs:RegisterTaskDefinition",
                          - "ecs:DeregisterTaskDefinition",
                        ]
                      - Effect   = "Allow"
                      - Resource = "*"
                      - Sid      = "EcsTaskDefinitionManagement"
                    },
                  - {
                      - Action   = [
                          - "iam:PassRole",
                        ]
                      - Effect   = "Allow"
                      - Resource = [
                          - "arn:aws:iam::553637109631:role/javabin-ecs-execution",
                          - "arn:aws:iam::553637109631:role/cake-*",
                        ]
                      - Sid      = "PassRole"
                    },
                ]
              - Version   = "2012-10-17"
            }
        ) -> (known after apply)
        # (1 unchanged attribute hidden)
    }

  # module.iam.aws_iam_role_policy.ci_deploy_ecs["commandchimps"] will be updated in-place
  ~ resource "aws_iam_role_policy" "ci_deploy_ecs" {
        id     = "javabin-ci-deploy-commandchimps:ecs-deploy"
        name   = "ecs-deploy"
      ~ policy = jsonencode(
            {
              - Statement = [
                  - {
                      - Action    = [
                          - "ecs:UpdateService",
                          - "ecs:DescribeServices",
                        ]
                      - Condition = {
                          - StringEquals = {
                              - "aws:ResourceTag/team" = "commandchimps"
                            }
                        }
                      - Effect    = "Allow"
                      - Resource  = "*"
                      - Sid       = "EcsServiceManagement"
                    },
                  - {
                      - Action   = [
                          - "ecs:DescribeTaskDefinition",
                          - "ecs:RegisterTaskDefinition",
                          - "ecs:DeregisterTaskDefinition",
                        ]
                      - Effect   = "Allow"
                      - Resource = "*"
                      - Sid      = "EcsTaskDefinitionManagement"
                    },
                  - {
                      - Action   = [
                          - "iam:PassRole",
                        ]
                      - Effect   = "Allow"
                      - Resource = [
                          - "arn:aws:iam::553637109631:role/javabin-ecs-execution",
                          - "arn:aws:iam::553637109631:role/commandchimps-*",
                        ]
                      - Sid      = "PassRole"
                    },
                ]
              - Version   = "2012-10-17"
            }
        ) -> (known after apply)
        # (1 unchanged attribute hidden)
    }

  # module.iam.aws_iam_role_policy.ci_deploy_ecs["cupcake"] will be updated in-place
  ~ resource "aws_iam_role_policy" "ci_deploy_ecs" {
        id     = "javabin-ci-deploy-cupcake:ecs-deploy"
        name   = "ecs-deploy"
      ~ policy = jsonencode(
            {
              - Statement = [
                  - {
                      - Action    = [
                          - "ecs:UpdateService",
                          - "ecs:DescribeServices",
                        ]
                      - Condition = {
                          - StringEquals = {
                              - "aws:ResourceTag/team" = "cupcake"
                            }
                        }
                      - Effect    = "Allow"
                      - Resource  = "*"
                      - Sid       = "EcsServiceManagement"
                    },
                  - {
                      - Action   = [
                          - "ecs:DescribeTaskDefinition",
                          - "ecs:RegisterTaskDefinition",
                          - "ecs:DeregisterTaskDefinition",
                        ]
                      - Effect   = "Allow"
                      - Resource = "*"
                      - Sid      = "EcsTaskDefinitionManagement"
                    },
                  - {
                      - Action   = [
                          - "iam:PassRole",
                        ]
                      - Effect   = "Allow"
                      - Resource = [
                          - "arn:aws:iam::553637109631:role/javabin-ecs-execution",
                          - "arn:aws:iam::553637109631:role/cupcake-*",
                        ]
                      - Sid      = "PassRole"
                    },
                ]
              - Version   = "2012-10-17"
            }
        ) -> (known after apply)
        # (1 unchanged attribute hidden)
    }

  # module.iam.aws_iam_role_policy.ci_deploy_ecs["developer"] will be updated in-place
  ~ resource "aws_iam_role_policy" "ci_deploy_ecs" {
        id     = "javabin-ci-deploy-developer:ecs-deploy"
        name   = "ecs-deploy"
      ~ policy = jsonencode(
            {
              - Statement = [
                  - {
                      - Action    = [
                          - "ecs:UpdateService",
                          - "ecs:DescribeServices",
                        ]
                      - Condition = {
                          - StringEquals = {
                              - "aws:ResourceTag/team" = "developer"
                            }
                        }
                      - Effect    = "Allow"
                      - Resource  = "*"
                      - Sid       = "EcsServiceManagement"
                    },
                  - {
                      - Action   = [
                          - "ecs:DescribeTaskDefinition",
                          - "ecs:RegisterTaskDefinition",
                          - "ecs:DeregisterTaskDefinition",
                        ]
                      - Effect   = "Allow"
                      - Resource = "*"
                      - Sid      = "EcsTaskDefinitionManagement"
                    },
                  - {
                      - Action   = [
                          - "iam:PassRole",
                        ]
                      - Effect   = "Allow"
                      - Resource = [
                          - "arn:aws:iam::553637109631:role/javabin-ecs-execution",
                          - "arn:aws:iam::553637109631:role/developer-*",
                        ]
                      - Sid      = "PassRole"
                    },
                ]
              - Version   = "2012-10-17"
            }
        ) -> (known after apply)
        # (1 unchanged attribute hidden)
    }

  # module.iam.aws_iam_role_policy.ci_deploy_ecs["java-no"] will be updated in-place
  ~ resource "aws_iam_role_policy" "ci_deploy_ecs" {
        id     = "javabin-ci-deploy-java-no:ecs-deploy"
        name   = "ecs-deploy"
      ~ policy = jsonencode(
            {
              - Statement = [
                  - {
                      - Action    = [
                          - "ecs:UpdateService",
                          - "ecs:DescribeServices",
                        ]
                      - Condition = {
                          - StringEquals = {
                              - "aws:ResourceTag/team" = "java-no"
                            }
                        }
                      - Effect    = "Allow"
                      - Resource  = "*"
                      - Sid       = "EcsServiceManagement"
                    },
                  - {
                      - Action   = [
                          - "ecs:DescribeTaskDefinition",
                          - "ecs:RegisterTaskDefinition",
                          - "ecs:DeregisterTaskDefinition",
                        ]
                      - Effect   = "Allow"
                      - Resource = "*"
                      - Sid      = "EcsTaskDefinitionManagement"
                    },
                  - {
                      - Action   = [
                          - "iam:PassRole",
                        ]
                      - Effect   = "Allow"
                      - Resource = [
                          - "arn:aws:iam::553637109631:role/javabin-ecs-execution",
                          - "arn:aws:iam::553637109631:role/java-no-*",
                        ]
                      - Sid      = "PassRole"
                    },
                ]
              - Version   = "2012-10-17"
            }
        ) -> (known after apply)
        # (1 unchanged attribute hidden)
    }

  # module.iam.aws_iam_role_policy.ci_deploy_ecs["javazone-no"] will be updated in-place
  ~ resource "aws_iam_role_policy" "ci_deploy_ecs" {
        id     = "javabin-ci-deploy-javazone-no:ecs-deploy"
        name   = "ecs-deploy"
      ~ policy = jsonencode(
            {
              - Statement = [
                  - {
                      - Action    = [
                          - "ecs:UpdateService",
                          - "ecs:DescribeServices",
                        ]
                      - Condition = {
                          - StringEquals = {
                              - "aws:ResourceTag/team" = "javazone-no"
                            }
                        }
                      - Effect    = "Allow"
                      - Resource  = "*"
                      - Sid       = "EcsServiceManagement"
                    },
                  - {
                      - Action   = [
                          - "ecs:DescribeTaskDefinition",
                          - "ecs:RegisterTaskDefinition",
                          - "ecs:DeregisterTaskDefinition",
                        ]
                      - Effect   = "Allow"
                      - Resource = "*"
                      - Sid      = "EcsTaskDefinitionManagement"
                    },
                  - {
                      - Action   = [
                          - "iam:PassRole",
                        ]
                      - Effect   = "Allow"
                      - Resource = [
                          - "arn:aws:iam::553637109631:role/javabin-ecs-execution",
                          - "arn:aws:iam::553637109631:role/javazone-no-*",
                        ]
                      - Sid      = "PassRole"
                    },
                ]
              - Version   = "2012-10-17"
            }
        ) -> (known after apply)
        # (1 unchanged attribute hidden)
    }

  # module.iam.aws_iam_role_policy.ci_deploy_ecs["javazone-work"] will be updated in-place
  ~ resource "aws_iam_role_policy" "ci_deploy_ecs" {
        id     = "javabin-ci-deploy-javazone-work:ecs-deploy"
        name   = "ecs-deploy"
      ~ policy = jsonencode(
            {
              - Statement = [
                  - {
                      - Action    = [
                          - "ecs:UpdateService",
                          - "ecs:DescribeServices",
                        ]
                      - Condition = {
                          - StringEquals = {
                              - "aws:ResourceTag/team" = "javazone-work"
                            }
                        }
                      - Effect    = "Allow"
                      - Resource  = "*"
                      - Sid       = "EcsServiceManagement"
                    },
                  - {
                      - Action   = [
                          - "ecs:DescribeTaskDefinition",
                          - "ecs:RegisterTaskDefinition",
                          - "ecs:DeregisterTaskDefinition",
                        ]
                      - Effect   = "Allow"
                      - Resource = "*"
                      - Sid      = "EcsTaskDefinitionManagement"
                    },
                  - {
                      - Action   = [
                          - "iam:PassRole",
                        ]
                      - Effect   = "Allow"
                      - Resource = [
                          - "arn:aws:iam::553637109631:role/javabin-ecs-execution",
                          - "arn:aws:iam::553637109631:role/javazone-work-*",
                        ]
                      - Sid      = "PassRole"
                    },
                ]
              - Version   = "2012-10-17"
            }
        ) -> (known after apply)
        # (1 unchanged attribute hidden)
    }

  # module.iam.aws_iam_role_policy.ci_deploy_ecs["jzwatch"] will be updated in-place
  ~ resource "aws_iam_role_policy" "ci_deploy_ecs" {
        id     = "javabin-ci-deploy-jzwatch:ecs-deploy"
        name   = "ecs-deploy"
      ~ policy = jsonencode(
            {
              - Statement = [
                  - {
                      - Action    = [
                          - "ecs:UpdateService",
                          - "ecs:DescribeServices",
                        ]
                      - Condition = {
                          - StringEquals = {
                              - "aws:ResourceTag/team" = "jzwatch"
                            }
                        }
                      - Effect    = "Allow"
                      - Resource  = "*"
                      - Sid       = "EcsServiceManagement"
                    },
                  - {
                      - Action   = [
                          - "ecs:DescribeTaskDefinition",
                          - "ecs:RegisterTaskDefinition",
                          - "ecs:DeregisterTaskDe

LLM Review

Risk: 🔴 HIGH

The plan updates the developer permissions boundary and creates many per-team ECS execution IAM roles, with the visible portion showing security-relevant changes: the boundary now allows EC2 security group ingress/egress rule changes, and the ECS execution role path is being changed. The output is truncated, so the full scope is unknown.

  • 🔒 [security] module.iam.aws_iam_policy.developer_boundary adds ec2:AuthorizeSecurityGroup* and ec2:RevokeSecurityGroup* to an allow statement. Developers could modify security group rules, which could open ingress to the internet unless another deny blocks this. Confirm the DenyXTeam tag condition covers these actions for shared/platform security groups, or remove the additions.
  • 🔒 [security] The boundary's NotResource exception for the ECS execution role changes from javabin-ecs-execution to javabin-ecs-exec-${aws:PrincipalTag/team}. This widens which roles are reachable. The old shared role is removed from the exception list and per-team roles are added, so verify the new pattern cannot let one team reach another team's execution role.
  • 🔒 [security] New aws_iam_role.ecs_exec_team roles are created for many teams. Each has the org permissions boundary attached, which is good, but their tags set team=shared while for-team names the team. Their attached policies are not visible in the truncated output, so review what permissions they receive.
  • 💥 [destruction] The visible output shows only creates and one in-place update, with no destroy actions. The truncated remainder could contain destroys, so check the full plan before applying.
  • 💰 [cost] IAM roles, policies, and boundary updates have no direct cost. No NAT, RDS, or load balancer resources are visible in the shown portion.

Review feedback on #134:
- Blocker: teams could rewrite the trust policy of shared roles
  (iam:UpdateAssumeRolePolicy was not in DenyShared), so team A could make
  javabin-ecs-exec-B trust itself and read team B's secrets. Denied.
- RS256 verification no longer shells out to openssl: modular
  exponentiation plus an exact PKCS#1 v1.5 comparison, no temp files.
  Non-object JWT parts are a TokenError; unknown-kid JWKS refetches are
  limited to once a minute.
- invoke-override-sign.sh still sends approved_by, which the currently
  deployed gate requires, so overrides keep working during rollout.
- github-oidc-token.sh fails clearly when no token is returned; the gate
  no longer logs the id_token.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Terraform Plan

🚧 Changes detected — Plan: 72 to add, 27 to change, 1 to destroy.

Plan output
Acquiring state lock. This may take a few moments...
aws_ssm_parameter.atlassian_org_id: Refreshing state... [id=/javabin/platform/atlassian-org-id]
aws_ssm_parameter.atlassian_api_key: Refreshing state... [id=/javabin/platform/atlassian-api-key]

Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
  + create
  ~ update in-place
  - destroy

Terraform will perform the following actions:

  # module.iam.aws_iam_policy.developer_boundary will be updated in-place
  ~ resource "aws_iam_policy" "developer_boundary" {
        id               = "arn:aws:iam::553637109631:policy/javabin-developer-boundary"
        name             = "javabin-developer-boundary"
      ~ policy           = jsonencode(
          ~ {
              ~ Statement = [
                    # (9 unchanged elements hidden)
                    {
                        Action      = "*"
                        Condition   = {
                            Null            = {
                                "aws:ResourceTag/team" = "false"
                            }
                            StringNotEquals = {
                                "aws:ResourceTag/team" = [
                                    "${aws:PrincipalTag/team}",
                                    "shared",
                                ]
                            }
                        }
                        Effect      = "Deny"
                        NotResource = [
                            "arn:aws:s3:::javabin-terraform-state-553637109631",
                            "arn:aws:s3:::javabin-terraform-state-553637109631/*",
                            "arn:aws:dynamodb:eu-central-1:553637109631:table/javabin-terraform-app-locks",
                            "arn:aws:s3:::javabin-ci-plan-artifacts-553637109631",
                            "arn:aws:s3:::javabin-ci-plan-artifacts-553637109631/*",
                        ]
                        Sid         = "DenyXTeam"
                    },
                  ~ {
                      ~ Action    = [
                            # (9 unchanged elements hidden)
                            "iam:DeleteRolePolicy",
                          + "iam:UpdateAssumeRolePolicy",
                            "iam:PutRolePolicy",
                            # (4 unchanged elements hidden)
                            "sns:SetTopicAttributes",
                          + "ec2:AuthorizeSecurityGroup*",
                          + "ec2:RevokeSecurityGroup*",
                        ]
                        # (4 unchanged attributes hidden)
                    },
                    {
                        Action    = [
                            "ec2:DeleteTags",
                            "ec2:CreateTags",
                            "ecs:TagResource",
                            "ecs:UntagResource",
                            "elasticloadbalancing:AddTags",
                            "elasticloadbalancing:RemoveTags",
                            "iam:TagRole",
                            "iam:UntagRole",
                            "sns:TagResource",
                            "sns:UntagResource",
                        ]
                        Condition = {
                            StringEquals = {
                                "aws:ResourceTag/team" = [
                                    "shared",
                                    "platform",
                                ]
                            }
                        }
                        Effect    = "Deny"
                        Resource  = "*"
                        Sid       = "DenyTagStrip"
                    },
                    {
                        Action   = [
                            "ssm:GetParameter*",
                            "ssm:GetParametersByPath",
                        ]
                        Effect   = "Deny"
                        Resource = [
                            "arn:aws:ssm:*:*:parameter/javabin/platform/*",
                            "arn:aws:ssm:*:*:parameter/javabin/slack/*",
                            "arn:aws:ssm:*:*:parameter/javabin/platform-overrides/*",
                        ]
                        Sid      = "DenyPlatSSM"
                    },
                  ~ {
                      ~ NotResource = [
                            "arn:aws:iam::*:role/${aws:PrincipalTag/team}-*",
                          - "arn:aws:iam::*:role/javabin-ecs-execution",
                          + "arn:aws:iam::*:role/javabin-ecs-exec-${aws:PrincipalTag/team}",
                        ]
                        # (3 unchanged attributes hidden)
                    },
                    {
                        Action      = [
                            "logs:GetLogEvents",
                            "logs:FilterLogEvents",
                            "logs:StartQuery",
                            "logs:GetQueryResults",
                        ]
                        Effect      = "Deny"
                        NotResource = [
                            "arn:aws:logs:*:*:log-group:/ecs/${aws:PrincipalTag/team}/*",
                            "arn:aws:logs:*:*:log-group:/ecs/${aws:PrincipalTag/team}/*:*",
                        ]
                        Sid         = "DenyXLogs"
                    },
                    # (3 unchanged elements hidden)
                ]
                # (1 unchanged attribute hidden)
            }
        )
        tags             = {
            "Name" = "javabin-developer-boundary"
        }
        # (6 unchanged attributes hidden)
    }

  # module.iam.aws_iam_role.ecs_exec_team["cake"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-cake"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-cake"
          + "for-team" = "cake"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-cake"
          + "environment" = "production"
          + "for-team"    = "cake"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["commandchimps"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-commandchimps"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-commandchimps"
          + "for-team" = "commandchimps"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-commandchimps"
          + "environment" = "production"
          + "for-team"    = "commandchimps"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["cupcake"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-cupcake"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-cupcake"
          + "for-team" = "cupcake"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-cupcake"
          + "environment" = "production"
          + "for-team"    = "cupcake"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["developer"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-developer"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-developer"
          + "for-team" = "developer"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-developer"
          + "environment" = "production"
          + "for-team"    = "developer"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["java-no"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-java-no"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-java-no"
          + "for-team" = "java-no"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-java-no"
          + "environment" = "production"
          + "for-team"    = "java-no"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["javazone-no"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-javazone-no"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-javazone-no"
          + "for-team" = "javazone-no"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-javazone-no"
          + "environment" = "production"
          + "for-team"    = "javazone-no"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["javazone-work"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-javazone-work"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-javazone-work"
          + "for-team" = "javazone-work"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-javazone-work"
          + "environment" = "production"
          + "for-team"    = "javazone-work"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["jzwatch"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-jzwatch"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-jzwatch"
          + "for-team" = "jzwatch"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-jzwatch"
          + "environment" = "production"
          + "for-team"    = "jzwatch"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["owners"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-owners"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-owners"
          + "for-team" = "owners"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-owners"
          + "environment" = "production"
          + "for-team"    = "owners"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["partnermanagement"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-partnermanagement"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-partnermanagement"
          + "for-team" = "partnermanagement"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-partnermanagement"
          + "environment" = "production"
          + "for-team"    = "partnermanagement"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["team-apps"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-team-apps"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-team-apps"
          + "for-team" = "team-apps"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-team-apps"
          + "environment" = "production"
          + "for-team"    = "team-apps"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["team-cibus"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-team-cibus"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-team-cibus"
          + "for-team" = "team-cibus"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-team-cibus"
          + "environment" = "production"
          + "for-team"    = "team-cibus"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["team-cibus2"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-team-cibus2"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-team-cibus2"
          + "for-team" = "team-cibus2"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-team-cibus2"
          + "environment" = "production"
          + "for-team"    = "team-cibus2"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["team-ems"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-team-ems"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-team-ems"
          + "for-team" = "team-ems"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-team-ems"
          + "environment" = "production"
          + "for-team"    = "team-ems"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["team-incogito"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-team-incogito"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-team-incogito"
          + "for-team" = "team-incogito"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-team-incogito"
          + "environment" = "production"
          + "for-team"    = "team-incogito"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["team-javazone-badge"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-team-javazone-badge"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-team-javazone-badge"
          + "for-team" = "team-javazone-badge"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-team-javazone-badge"
          + "environment" = "production"
          + "for-team"    = "team-javazone-badge"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["team-javazone-video"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-team-javazone-video"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-team-javazone-video"
          + "for-team" = "team-javazone-video"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-team-javazone-video"
          + "environment" = "production"
          + "for-team"    = "team-javazone-video"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["team-jz-text-adventure"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-team-jz-text-adventure"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-team-jz-text-adventure"
          + "for-team" = "team-jz-text-adventure"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-team-jz-text-adventure"
          + "environment" = "production"
          + "for-team"    = "team-jz-text-adventure"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["team-portal"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-team-portal"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-team-portal"
          + "for-team" = "team-portal"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-team-portal"
          + "environment" = "production"
          + "for-team"    = "team-portal"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["team-scala-training-code"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-team-scala-training-code"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-team-scala-training-code"
          + "for-team" = "team-scala-training-code"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-team-scala-training-code"
          + "environment" = "production"
          + "for-team"    = "team-scala-training-code"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["team-submitit"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-team-submitit"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-team-submitit"
          + "for-team" = "team-submitit"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-team-submitit"
          + "environment" = "production"
          + "for-team"    = "team-submitit"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["teammoosehead"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-teammoosehead"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-teammoosehead"
          + "for-team" = "teammoosehead"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-teammoosehead"
          + "environment" = "production"
          + "for-team"    = "teammoosehead"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["teamteknologihuset"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-teamteknologihuset"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-teamteknologihuset"
          + "for-team" = "teamteknologihuset"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-teamteknologihuset"
          + "environment" = "production"
          + "for-team"    = "teamteknologihuset"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role.ecs_exec_team["testteam"] will be created
  + resource "aws_iam_role" "ecs_exec_team" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ecs-tasks.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "javabin-ecs-exec-testteam"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::553637109631:policy/javabin-org-boundary"
      + tags                  = {
          + "Name"     = "javabin-ecs-exec-testteam"
          + "for-team" = "testteam"
          + "team"     = "shared"
        }
      + tags_all              = {
          + "Name"        = "javabin-ecs-exec-testteam"
          + "environment" = "production"
          + "for-team"    = "testteam"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
      + unique_id             = (known after apply)
    }

  # module.iam.aws_iam_role_policy.ci_deploy_ecs["cake"] will be updated in-place
  ~ resource "aws_iam_role_policy" "ci_deploy_ecs" {
        id     = "javabin-ci-deploy-cake:ecs-deploy"
        name   = "ecs-deploy"
      ~ policy = jsonencode(
            {
              - Statement = [
                  - {
                      - Action    = [
                          - "ecs:UpdateService",
                          - "ecs:DescribeServices",
                        ]
                      - Condition = {
                          - StringEquals = {
                              - "aws:ResourceTag/team" = "cake"
                            }
                        }
                      - Effect    = "Allow"
                      - Resource  = "*"
                      - Sid       = "EcsServiceManagement"
                    },
                  - {
                      - Action   = [
                          - "ecs:DescribeTaskDefinition",
                          - "ecs:RegisterTaskDefinition",
                          - "ecs:DeregisterTaskDefinition",
                        ]
                      - Effect   = "Allow"
                      - Resource = "*"
                      - Sid      = "EcsTaskDefinitionManagement"
                    },
                  - {
                      - Action   = [
                          - "iam:PassRole",
                        ]
                      - Effect   = "Allow"
                      - Resource = [
                          - "arn:aws:iam::553637109631:role/javabin-ecs-execution",
                          - "arn:aws:iam::553637109631:role/cake-*",
                        ]
                      - Sid      = "PassRole"
                    },
                ]
              - Version   = "2012-10-17"
            }
        ) -> (known after apply)
        # (1 unchanged attribute hidden)
    }

  # module.iam.aws_iam_role_policy.ci_deploy_ecs["commandchimps"] will be updated in-place
  ~ resource "aws_iam_role_policy" "ci_deploy_ecs" {
        id     = "javabin-ci-deploy-commandchimps:ecs-deploy"
        name   = "ecs-deploy"
      ~ policy = jsonencode(
            {
              - Statement = [
                  - {
                      - Action    = [
                          - "ecs:UpdateService",
                          - "ecs:DescribeServices",
                        ]
                      - Condition = {
                          - StringEquals = {
                              - "aws:ResourceTag/team" = "commandchimps"
                            }
                        }
                      - Effect    = "Allow"
                      - Resource  = "*"
                      - Sid       = "EcsServiceManagement"
                    },
                  - {
                      - Action   = [
                          - "ecs:DescribeTaskDefinition",
                          - "ecs:RegisterTaskDefinition",
                          - "ecs:DeregisterTaskDefinition",
                        ]
                      - Effect   = "Allow"
                      - Resource = "*"
                      - Sid      = "EcsTaskDefinitionManagement"
                    },
                  - {
                      - Action   = [
                          - "iam:PassRole",
                        ]
                      - Effect   = "Allow"
                      - Resource = [
                          - "arn:aws:iam::553637109631:role/javabin-ecs-execution",
                          - "arn:aws:iam::553637109631:role/commandchimps-*",
                        ]
                      - Sid      = "PassRole"
                    },
                ]
              - Version   = "2012-10-17"
            }
        ) -> (known after apply)
        # (1 unchanged attribute hidden)
    }

  # module.iam.aws_iam_role_policy.ci_deploy_ecs["cupcake"] will be updated in-place
  ~ resource "aws_iam_role_policy" "ci_deploy_ecs" {
        id     = "javabin-ci-deploy-cupcake:ecs-deploy"
        name   = "ecs-deploy"
      ~ policy = jsonencode(
            {
              - Statement = [
                  - {
                      - Action    = [
                          - "ecs:UpdateService",
                          - "ecs:DescribeServices",
                        ]
                      - Condition = {
                          - StringEquals = {
                              - "aws:ResourceTag/team" = "cupcake"
                            }
                        }
                      - Effect    = "Allow"
                      - Resource  = "*"
                      - Sid       = "EcsServiceManagement"
                    },
                  - {
                      - Action   = [
                          - "ecs:DescribeTaskDefinition",
                          - "ecs:RegisterTaskDefinition",
                          - "ecs:DeregisterTaskDefinition",
                        ]
                      - Effect   = "Allow"
                      - Resource = "*"
                      - Sid      = "EcsTaskDefinitionManagement"
                    },
                  - {
                      - Action   = [
                          - "iam:PassRole",
                        ]
                      - Effect   = "Allow"
                      - Resource = [
                          - "arn:aws:iam::553637109631:role/javabin-ecs-execution",
                          - "arn:aws:iam::553637109631:role/cupcake-*",
                        ]
                      - Sid      = "PassRole"
                    },
                ]
              - Version   = "2012-10-17"
            }
        ) -> (known after apply)
        # (1 unchanged attribute hidden)
    }

  # module.iam.aws_iam_role_policy.ci_deploy_ecs["developer"] will be updated in-place
  ~ resource "aws_iam_role_policy" "ci_deploy_ecs" {
        id     = "javabin-ci-deploy-developer:ecs-deploy"
        name   = "ecs-deploy"
      ~ policy = jsonencode(
            {
              - Statement = [
                  - {
                      - Action    = [
                          - "ecs:UpdateService",
                          - "ecs:DescribeServices",
                        ]
                      - Condition = {
                          - StringEquals = {
                              - "aws:ResourceTag/team" = "developer"
                            }
                        }
                      - Effect    = "Allow"
                      - Resource  = "*"
                      - Sid       = "EcsServiceManagement"
                    },
                  - {
                      - Action   = [
                          - "ecs:DescribeTaskDefinition",
                          - "ecs:RegisterTaskDefinition",
                          - "ecs:DeregisterTaskDefinition",
                        ]
                      - Effect   = "Allow"
                      - Resource = "*"
                      - Sid      = "EcsTaskDefinitionManagement"
                    },
                  - {
                      - Action   = [
                          - "iam:PassRole",
                        ]
                      - Effect   = "Allow"
                      - Resource = [
                          - "arn:aws:iam::553637109631:role/javabin-ecs-execution",
                          - "arn:aws:iam::553637109631:role/developer-*",
                        ]
                      - Sid      = "PassRole"
                    },
                ]
              - Version   = "2012-10-17"
            }
        ) -> (known after apply)
        # (1 unchanged attribute hidden)
    }

  # module.iam.aws_iam_role_policy.ci_deploy_ecs["java-no"] will be updated in-place
  ~ resource "aws_iam_role_policy" "ci_deploy_ecs" {
        id     = "javabin-ci-deploy-java-no:ecs-deploy"
        name   = "ecs-deploy"
      ~ policy = jsonencode(
            {
              - Statement = [
                  - {
                      - Action    = [
                          - "ecs:UpdateService",
                          - "ecs:DescribeServices",
                        ]
                      - Condition = {
                          - StringEquals = {
                              - "aws:ResourceTag/team" = "java-no"
                            }
                        }
                      - Effect    = "Allow"
                      - Resource  = "*"
                      - Sid       = "EcsServiceManagement"
                    },
                  - {
                      - Action   = [
                          - "ecs:DescribeTaskDefinition",
                          - "ecs:RegisterTaskDefinition",
                          - "ecs:DeregisterTaskDefinition",
                        ]
                      - Effect   = "Allow"
                      - Resource = "*"
                      - Sid      = "EcsTaskDefinitionManagement"
                    },
                  - {
                      - Action   = [
                          - "iam:PassRole",
                        ]
                      - Effect   = "Allow"
                      - Resource = [
                          - "arn:aws:iam::553637109631:role/javabin-ecs-execution",
                          - "arn:aws:iam::553637109631:role/java-no-*",
                        ]
                      - Sid      = "PassRole"
                    },
                ]
              - Version   = "2012-10-17"
            }
        ) -> (known after apply)
        # (1 unchanged attribute hidden)
    }

  # module.iam.aws_iam_role_policy.ci_deploy_ecs["javazone-no"] will be updated in-place
  ~ resource "aws_iam_role_policy" "ci_deploy_ecs" {
        id     = "javabin-ci-deploy-javazone-no:ecs-deploy"
        name   = "ecs-deploy"
      ~ policy = jsonencode(
            {
              - Statement = [
                  - {
                      - Action    = [
                          - "ecs:UpdateService",
                          - "ecs:DescribeServices",
                        ]
                      - Condition = {
                          - StringEquals = {
                              - "aws:ResourceTag/team" = "javazone-no"
                            }
                        }
                      - Effect    = "Allow"
                      - Resource  = "*"
                      - Sid       = "EcsServiceManagement"
                    },
                  - {
                      - Action   = [
                          - "ecs:DescribeTaskDefinition",
                          - "ecs:RegisterTaskDefinition",
                          - "ecs:DeregisterTaskDefinition",
                        ]
                      - Effect   = "Allow"
                      - Resource = "*"
                      - Sid      = "EcsTaskDefinitionManagement"
                    },
                  - {
                      - Action   = [
                          - "iam:PassRole",
                        ]
                      - Effect   = "Allow"
                      - Resource = [
                          - "arn:aws:iam::553637109631:role/javabin-ecs-execution",
                          - "arn:aws:iam::553637109631:role/javazone-no-*",
                        ]
                      - Sid      = "PassRole"
                    },
                ]
              - Version   = "2012-10-17"
            }
        ) -> (known after apply)
        # (1 unchanged attribute hidden)
    }

  # module.iam.aws_iam_role_policy.ci_deploy_ecs["javazone-work"] will be updated in-place
  ~ resource "aws_iam_role_policy" "ci_deploy_ecs" {
        id     = "javabin-ci-deploy-javazone-work:ecs-deploy"
        name   = "ecs-deploy"
      ~ policy = jsonencode(
            {
              - Statement = [
                  - {
                      - Action    = [
                          - "ecs:UpdateService",
                          - "ecs:DescribeServices",
                        ]
                      - Condition = {
                          - StringEquals = {
                              - "aws:ResourceTag/team" = "javazone-work"
                            }
                        }
                      - Effect    = "Allow"
                      - Resource  = "*"
                      - Sid       = "EcsServiceManagement"
                    },
                  - {
                      - Action   = [
                          - "ecs:DescribeTaskDefinition",
                          - "ecs:RegisterTaskDefinition",
                          - "ecs:DeregisterTaskDefinition",
                        ]
                      - Effect   = "Allow"
                      - Resource = "*"
                      - Sid      = "EcsTaskDefinitionManagement"
                    },
                  - {
                      - Action   = [
                          - "iam:PassRole",
                        ]
                      - Effect   = "Allow"
                      - Resource = [
                          - "arn:aws:iam::553637109631:role/javabin-ecs-execution",
                          - "arn:aws:iam::553637109631:role/javazone-work-*",
                        ]
                      - Sid      = "PassRole"
                    },
                ]
              - Version   = "2012-10-17"
            }
        ) -> (known after apply)
        # (1 unchanged attribute hidden)
    }

  # module.iam.aws_iam_role_policy.ci_deploy_ecs["jzwatch"] will be updated in-place
  ~ resource "aws_iam_role_policy" "ci_deploy_ecs" {
        id     = "javabin-ci-deploy-jzwatch:ecs-deploy"
        name   = "ecs-deploy"
      ~ policy = jsonencode(
            {
              - Statement = [
                  - {
                      - Action    = [
                          - "ecs:UpdateService",
                          - "ecs:DescribeServices",
                        ]
                      - Condition = {
                          - StringEquals = {
                              - "aws:ResourceTag/team" = "jzwatch"
                            }
                        }
                      - Effect    = "Allow"
                      - Resource  = "*"
                      - Sid       = "EcsServiceManagement"
                    },
      

LLM Review

Risk: 🔴 HIGH

Plan modifies the developer permissions boundary (adds EC2 security group authorize/revoke and iam:UpdateAssumeRolePolicy to allowed actions, and swaps the ECS execution role exemption) and creates ~20+ per-team ECS execution roles, with the visible portion showing no destruction, but the boundary loosening is a security-relevant change that needs careful review.

  • 🔒 [security] developer_boundary policy is updated to ALLOW ec2:AuthorizeSecurityGroup* and ec2:RevokeSecurityGroup* (security group ingress/egress changes) and iam:UpdateAssumeRolePolicy. Previously these were not granted by the boundary. Opening SG rules and changing role trust policies are high-risk actions; this widens what developer roles can do and could allow exposing services to the internet or escalating privileges via trust policy changes. Confirm this is intended and consider restricting by team tag/resource condition.
  • 🔒 [security] The boundary's NotResource exemption for javabin-ecs-execution is replaced with javabin-ecs-exec-${aws:PrincipalTag/team}. This changes which IAM roles developers can modify/pass. Verify that the per-team naming cannot be abused (e.g., a team tag that matches another team's role name) and that the new roles are not overly permissive.
  • 🔒 [security] About 20+ new aws_iam_role.ecs_exec_team resources are created, each tagged team=shared with for-team set to a team name, and each carrying the org permissions boundary javabin-org-boundary. The boundary is correctly attached, which is good, but the team tag 'shared' combined with the team-based boundary conditions (DenyXTeam, DenyTagStrip) means behaviour under the boundary should be verified for these roles. Check the attached policies for each role in the truncated output.
  • ✅ [routine] Plan output was truncated; remaining create/update/destroy actions could not be reviewed. Destructive actions in the unseen portion must be checked before apply. Nothing in the visible portion destroys data or databases.
  • 💰 [cost] Creating IAM roles and policy updates has no direct billing cost. No NAT gateways, RDS, or load balancers are visible in the shown portion of the plan.

@Alexanderamiri
Alexanderamiri merged commit b7b2a4d into main Oct 23, 2026
4 checks passed
@Alexanderamiri
Alexanderamiri deleted the fix/team-isolation branch October 23, 2026 15:14
Alexanderamiri added a commit that referenced this pull request Oct 23, 2026
…oles (#137)

Fixes #136. **Stacked on #134** (it reuses that PR's GitHub OIDC
verification). The base is `fix/team-isolation`, so the diff shows only
this change; merge #134 first and GitHub retargets this to `main`.

## Why
- **Every review fails.** App `tf-plan` ran `review-plan.py` with
`javabin-ci-team-<team>`, and the developer boundary's `DenySecSvcs`
denies `bedrock:Invoke*`/`Converse*`. Every app review returned FAILED,
so every app apply needed a board override. That's what cupcake and
frosting hit.
- **The Slack alert can't work either.** The HIGH-risk alert read
`/javabin/slack/*`, which `DenyPlatSSM` also denies.
- **A plan job could set its own verdict.** The job wrote `risk.json`
itself, with team credentials, so it could mark its own plan LOW.

## What changed
Option 1 from the issue:
- **New Lambda `javabin-plan-review`:**
- verifies the job's GitHub OIDC token (aud `javabin-plan-review`), so
the plan must be the repo's own
- reviews `plan-output.txt` with the same `scripts/review-plan.py` as
platform CI, bundled into the zip; the Bedrock call is now injectable
  - retries transient errors up to 3 times with backoff
- writes `risk.json` and `review.json`, and posts HIGH/FAILED to the
override channel on pushes to main
  - returns the markdown for the PR comment
- **tf-plan:** re-assumes `javabin-ci-app-broker` via OIDC, which may
now invoke the Lambda, and calls `scripts/invoke-plan-review.sh`. The
job no longer uploads `risk.json` or sends the Slack alert itself.
- **Team roles:** an explicit Deny on `s3:PutObject`/`DeleteObject` for
`*/risk.json`, `*/review.json` and `*/override.json` in the plan bucket.
- **Bedrock stays out of team roles.** The developer boundary is
unchanged.

On the issue's second point: a review that can't run after retries is
still FAILED and blocked. The PR comment now says the review could not
run and to re-run the workflow, instead of looking like a risk verdict.

## Checks
- Lambda tests (23) pass. The new ones cover LOW/MEDIUM verdict written,
retry then success, persistent failure → FAILED, another repo's plan
refused, bad token refused.
- `terraform validate` and actionlint pass.

After merge and apply, re-run frosting and cupcake. tf-apply should get
a real verdict.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Alexanderamiri added a commit that referenced this pull request Oct 23, 2026
…ml (#138)

**Stacked on #134** (per-team execution roles). Merge #134 first and
GitHub retargets this to `main`.

What cupcake/frosting need for login to work.

## Why
- **Groups never reach tokens.** cupcake's backend requires `helter` in
`cognito:groups`. Federated (GoogleSAML) users arrive with only an
email, and team-provisioner only adds users who already signed in. The
internal pool has 0 users and empty groups, so every login would get a
401, and `auth.groups` did nothing.
- **The frontend needs a public client.** frosting does OIDC from the
browser (oidc-client-ts with PKCE). The platform only made confidential
clients with a secret, which a browser can't use.
- **The backend needs no client.** cupcake's backend only verifies
tokens. `auth: internal` would create a client it never uses.
- **The apps read their own env var names:**
`NUXT_PUBLIC_OIDC_CLIENT_ID`, `OIDC_WELL_KNOWN_URL`.

## What changed
- **Group claims:**
- team-provisioner records registry membership (`groups.yaml` groups
with `cognito: true`, plus `team-<name>`) in a new
`javabin-auth-memberships` table.
- A new pre-token-generation V2 trigger, `javabin-auth-claims` (internal
pool, ESSENTIALS tier), puts the user's groups into `cognito:groups` of
the ID and access token at every sign-in and refresh. Native Cognito
groups are kept.
- It refuses the token when the client has allowed groups and the user
is in none.
- **app-auth-sync:**
- `client_type` confidential/public; a type change replaces the client,
since the secret setting is immutable.
  - `allowed_groups` written to the table and removed with the client.
  - `http://localhost` callbacks allowed for local dev.
- **cognito-app-client module:** `client_type` (`none` requests no
client), `allowed_groups`, and a `well_known_url` output.
- **app.yaml:**
  - `auth.client: confidential|public|none`
  - `auth.groups` now restricts sign-in
  - `auth.env` aliases injected values to the app's own names
  - `COGNITO_WELL_KNOWN_URL` is injected
- **Docs:** app-yaml-reference (client types, groups, aliases),
lambda-functions, reusable-modules, CLAUDE.md.

Cupcake's `app.yaml` after this:
```yaml
# frosting
auth:
  pool: internal
  client: public
  groups: [helter]
  callback_urls: [https://cupcake.javazone.no/, https://cupcake.javazone.no/auth/callback, http://localhost:3000/]
  env: {COGNITO_CLIENT_ID: NUXT_PUBLIC_OIDC_CLIENT_ID, COGNITO_ISSUER_URL: NUXT_PUBLIC_OIDC_AUTHORITY}
# cupcake backend
auth:
  pool: internal
  client: none
  env: {COGNITO_WELL_KNOWN_URL: OIDC_WELL_KNOWN_URL}
```

## Checks
- Generator tests (19) and Lambda tests (35) pass. New ones cover the
auth-claims group union, deny, and caching; public clients, type
switching, allowed groups, and localhost-vs-`localhost.evil.com`; and
generator client types and aliases.
- Generated configs for both cupcake apps pass `terraform validate`
against the changed modules, as does `terraform/platform`.

## Rollout notes
- Memberships fill on the next registry provisioning run. Re-run
`provision-groups` and `provision-teams` in javaBin/registry after
apply. Until then tokens carry no registry groups, as today.
- Adding the trigger modifies `aws_cognito_user_pool.internal` in place
(`lambda_config`). The GoogleSAML IdP, which was created outside
Terraform, is a separate resource and is not touched.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Alexanderamiri added a commit that referenced this pull request Oct 24, 2026
## Why
`sync-registered-teams.py` lists every GitHub org team, so applying #132
created AWS CI and deploy roles (`javabin-ci-team-*`,
`javabin-ci-deploy-*`) for 21 org teams that are not app teams:
`owners`, `developer`, `java-no`, `team-*` and others. Any repo in one
of those GitHub teams could request those roles through the broker.

## What changed
The sync reads `teams/*.yaml` from javaBin/registry, the documented
source of truth: cupcake, jzwatch, testteam. The committed tfvars are
updated to match.

## Expected plan: 148 to destroy, HIGH risk
21 teams × 7 role resources = 147, plus 1 that only appears if #134
hasn't merged yet. None belong to cupcake, jzwatch or testteam. The
roles were created hours ago by #132 and have never been used.

The apply needs a board override through approve-override.yml. That is
why this change is split out of #134.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Alexanderamiri added a commit that referenced this pull request Oct 24, 2026
…ole plan (#147)

## Why

Reviews kept saying "Plan is truncated; the remaining changes ... could
not be reviewed". Where the input was actually cut:

| Reviews | Cut by | Real? |
|---|---|---|
| #134, #135 (14:14, 14:31), #137, #138, #139 on 2026-10-23, before #141
merged at 15:43 | the old 80k cut in `review-plan.py` | yes. These
include the quoted "other roles, Lambdas, or networking" review (#135,
14:31) |
| #135 on 2026-10-24 09:53 (run 40083680062) | #141's 400k cap: the plan
was 830k chars, 231 destroys (destroy diffs print every attribute) |
yes. The model saw 28 of 231 changes and correctly said so |
| #145 (2026-10-24 09:25, 09:40), #146, app reviews (cupcake#258,
frosting#249/#250) | none | no truncation claims |

Ruled out:
- (a) The PR comment's 60k cut: the review reads `plan-output.txt`
itself. The cut was silent to humans, though, so the comment now says
when it is cut.
- (b) `run-plan.sh` writes the full `-no-color` output with no
head/tail.
- (c) platform-ci reviews `terraform/platform/plan-output.txt`, the full
file.
- (e) No reviews hit `max_tokens`. Converse is still called without
inferenceConfig (no maxTokens set, on purpose), but a `stopReason:
max_tokens` answer is now discarded instead of trusted.
- (f) The Lambda reads the whole S3 object.

## What changed

- `scripts/review-plan.py`: no default input cap. The whole plan goes to
Haiku 5.5, which has a 1M-token context. `REVIEW_MAX_PLAN_CHARS` still
turns on the existing notice + change-list mode if it is set.
- The prompt now opens with `COMPLETE PLAN` (change count + the `Plan:`
line) and says not to call the plan truncated. It also explains that
Terraform hides parts of every plan by design: `# (N unchanged
attributes/blocks/elements hidden)`, `(sensitive value)`, `(known after
apply)` and partial `jsonencode` diffs are not truncation.
- `stopReason == "max_tokens"` → returns None. Platform CI records
FAILED; the Lambda retries.
- `scripts/post-plan-comment.sh`: adds a notice when the plan is cut at
60k (GitHub's comment limit) and keeps the cut-off point configurable.
- Docs: `docs/ci-workflow.md`.

Trade-off: a plan larger than the model's context now fails the review
(FAILED, override available) instead of being cut.

## Checks

- `python3 -m unittest discover -s scripts/tests`: 38 OK. New tests: the
complete-plan declaration, the elision markers, no default cap (2M-char
plan), an 830k destroy plan sent whole, max_tokens discarded, and the
comment cut notice.
- `python3 -m unittest discover -s terraform/lambda-src/tests`: 63 OK.
New tests: COMPLETE PLAN reaches Bedrock, and a max_tokens answer is
retried.
- `terraform fmt -check -recursive terraform`: OK. `shellcheck
scripts/post-plan-comment.sh`: OK. No workflow changes.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.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.

1 participant