Skip to content

fix(iam): give per-team SSO sessions guardrails with their team written in - #145

Merged
Alexanderamiri merged 2 commits into
mainfrom
fix/sso-team-guardrails
Oct 24, 2026
Merged

Alexanderamiri merged 2 commits into
mainfrom
fix/sso-team-guardrails

Conversation

@Alexanderamiri

@Alexanderamiri Alexanderamiri commented Oct 24, 2026 •

Copy link
Copy Markdown
Member

Fixes #144.

Why

  • Verified in CloudTrail: every Identity Center session carries principalTags: {team: ""} on AssumeRoleWithSAML, for javabin-team-cupcake, javabin-team-jzwatch and javabin-admin alike.
  • Cause: the ABAC mapping reads ${path:enterprise.team}, and nothing ever sets that attribute on users.
  • Effect: the per-team permission sets attach javabin-developer-boundary as a policy, and its DenyXTeam compares each resource's team tag with that empty principal tag. So developers are denied everything team-scoped: their own app secrets (javabin secret list/set), /ecs/<team>/* logs, and their ECS services.

What changed

  • terraform/platform/iam/boundary.tf:
    • The boundary JSON moves into a local.
    • New javabin-team-{team}-guardrails per registered team: the same rules with ${aws:PrincipalTag/team} replaced by the team name.
    • The guardrails are tagged team=shared, and DenyBndMod now also covers javabin-team-*-guardrails, so team CI roles can't rewrite them.
    • Rendered size is 5,553 bytes, under 6,144.
  • team-provisioner, for javabin-team-{team}:
    • Attaches javabin-team-{team}-guardrails and detaches the shared boundary.
    • The inline policy now denies writes to platform-managed parameters (cognito-client-*, auth, db-master-password).
    • It also denies creating parameters that don't exist yet: an untagged parameter would break the app's next terraform apply.
    • It re-provisions the permission set so the change reaches the account.
  • IAM for the provisioner: Detach…, ProvisionPermissionSet, DescribePermissionSetProvisioningStatus, and iam:GetPolicy on the guardrail policies.
  • Docs: CLAUDE.md (known issue, naming) and app-yaml-reference (which SSO role to use for secrets).

The ABAC javabin-developer permission set in terraform/org is still unable to reach team resources. That's documented rather than fixed here, because the per-team sets are what people use. #139's terraform/org change targets that set, so it doesn't need applying for secrets self-service.

After merge

  1. Platform CI creates the guardrail policies.
  2. Run Provision Teams in javaBin/registry (manual run), which attaches them and re-provisions the permission sets.
  3. Sign in again with javabin-team-cupcake, then javabin secret list.

Checks

  • The Lambda tests pass, including a new one for attach/detach, the deny statements and reprovisioning.
  • terraform validate passes.
  • terraform console confirms the substitution renders the team name in both the conditions and the ARNs.

Guard overrides

  • aws route53 change-resource-record-sets --hosted-zone-id Z09335963LMV0Z5QB9L45 --change-batch file:///tmp/cupcake-cname-delete.json — deleted the old cupcake.javazone.no CNAME (→ d2cxhqskuuhit7.cloudfront.net) to cut frosting over to the platform, on the user's explicit instruction. Not part of this PR's code; listed because it ran from this session.

🤖 Generated with Claude Code

…en in

Identity Center sessions carry team='' (CloudTrail AssumeRoleWithSAML
principalTags, every session): the ABAC attribute ${path:enterprise.team}
is never set on users. The per-team permission sets attach the developer
boundary, whose DenyXTeam compares resource tags with that empty tag, so
developers were denied every team-scoped resource: their own secrets
(javabin secret list/set), logs and ECS services.

Platform Terraform now renders javabin-team-{team}-guardrails, the
developer boundary with the team name substituted, self-protected like the
boundary. team-provisioner attaches it to javabin-team-{team} instead of
the shared boundary, denies writes to platform-managed parameters and to
parameters that don't exist yet, and re-provisions the permission set so
existing sessions pick it up.

Fixes #144

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 24, 2026 09:24
@github-actions

Copy link
Copy Markdown

Terraform Plan

🚧 Changes detected — Plan: 24 to add, 3 to change, 0 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

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 = [
                    {
                        Action   = "*"
                        Effect   = "Allow"
                        Resource = "*"
                        Sid      = "Allow"
                    },
                  ~ {
                      ~ Resource = "arn:aws:iam::553637109631:policy/javabin-developer-boundary" -> [
                          + "arn:aws:iam::553637109631:policy/javabin-developer-boundary",
                          + "arn:aws:iam::553637109631:policy/javabin-team-*-guardrails",
                        ]
                        # (3 unchanged attributes hidden)
                    },
                    {
                        Action    = [
                            "iam:CreateRole",
                            "iam:PutRolePermissionsBoundary",
                        ]
                        Condition = {
                            StringNotEquals = {
                                "iam:PermissionsBoundary" = "arn:aws:iam::553637109631:policy/javabin-developer-boundary"
                            }
                        }
                        Effect    = "Deny"
                        Resource  = "*"
                        Sid       = "DenyNoBnd"
                    },
                    # (15 unchanged elements hidden)
                ]
                # (1 unchanged attribute hidden)
            }
        )
        tags             = {
            "Name" = "javabin-developer-boundary"
        }
        # (6 unchanged attributes hidden)
    }

  # module.iam.aws_iam_policy.team_guardrails["cake"] will be created
  + resource "aws_iam_policy" "team_guardrails" {
      + arn              = (known after apply)
      + attachment_count = (known after apply)
      + description      = "Developer boundary rules for team cake, for its Identity Center permission set"
      + id               = (known after apply)
      + name             = "javabin-team-cake-guardrails"
      + name_prefix      = (known after apply)
      + path             = "/"
      + policy           = jsonencode(
            {
              + Statement = [
                  + {
                      + Action   = "*"
                      + Effect   = "Allow"
                      + Resource = "*"
                      + Sid      = "Allow"
                    },
                  + {
                      + Action   = [
                          + "iam:DeletePolicy",
                          + "iam:DeletePolicyVersion",
                          + "iam:CreatePolicyVersion",
                          + "iam:SetDefaultPolicyVersion",
                        ]
                      + Effect   = "Deny"
                      + Resource = [
                          + "arn:aws:iam::553637109631:policy/javabin-developer-boundary",
                          + "arn:aws:iam::553637109631:policy/javabin-team-*-guardrails",
                        ]
                      + Sid      = "DenyBndMod"
                    },
                  + {
                      + Action    = [
                          + "iam:CreateRole",
                          + "iam:PutRolePermissionsBoundary",
                        ]
                      + Condition = {
                          + StringNotEquals = {
                              + "iam:PermissionsBoundary" = "arn:aws:iam::553637109631:policy/javabin-developer-boundary"
                            }
                        }
                      + Effect    = "Deny"
                      + Resource  = "*"
                      + Sid       = "DenyNoBnd"
                    },
                  + {
                      + Action   = "iam:DeleteRolePermissionsBoundary"
                      + Effect   = "Deny"
                      + Resource = "*"
                      + Sid      = "DenyStripBnd"
                    },
                  + {
                      + Action   = [
                          + "iam:CreateUser",
                          + "iam:CreateLoginProfile",
                          + "iam:UpdateLoginProfile",
                          + "iam:CreateAccessKey",
                          + "iam:DeactivateMFADevice",
                        ]
                      + Effect   = "Deny"
                      + Resource = "*"
                      + Sid      = "DenyIAMUsers"
                    },
                  + {
                      + Action   = [
                          + "organizations:*",
                          + "sso:*",
                          + "sso-directory:*",
                          + "identitystore:*",
                          + "account:*",
                        ]
                      + Effect   = "Deny"
                      + Resource = "*"
                      + Sid      = "DenyOrgSSO"
                    },
                  + {
                      + Action   = [
                          + "ec2:CreateVpc",
                          + "ec2:DeleteVpc",
                          + "ec2:ModifyVpcAttribute",
                          + "ec2:CreateSubnet",
                          + "ec2:DeleteSubnet",
                          + "ec2:CreateInternetGateway",
                          + "ec2:DeleteInternetGateway",
                          + "ec2:AttachInternetGateway",
                          + "ec2:DetachInternetGateway",
                          + "ec2:CreateNatGateway",
                          + "ec2:DeleteNatGateway",
                          + "ec2:CreateRouteTable",
                          + "ec2:DeleteRouteTable",
                        ]
                      + Effect   = "Deny"
                      + Resource = "*"
                      + Sid      = "DenyNetwork"
                    },
                  + {
                      + Action   = [
                          + "ecs:DeleteCluster",
                          + "ecs:UpdateCluster",
                          + "elasticloadbalancing:DeleteLoadBalancer",
                          + "elasticloadbalancing:ModifyLoadBalancerAttributes",
                          + "s3:DeleteBucket",
                          + "s3:PutBucketPolicy",
                          + "s3:DeleteBucketPolicy",
                          + "s3:PutBucketVersioning",
                          + "s3:PutEncryptionConfiguration",
                          + "dynamodb:DeleteTable",
                          + "dynamodb:UpdateTable",
                        ]
                      + Effect   = "Deny"
                      + Resource = [
                          + "arn:aws:ecs:eu-central-1:553637109631:cluster/javabin-platform",
                          + "arn:aws:elasticloadbalancing:eu-central-1:553637109631:loadbalancer/app/javabin-*",
                          + "arn:aws:s3:::javabin-terraform-*",
                          + "arn:aws:s3:::javabin-ci-*",
                          + "arn:aws:dynamodb:eu-central-1:553637109631:table/javabin-terraform-*",
                        ]
                      + Sid      = "DenyPlatInfra"
                    },
                  + {
                      + Action   = [
                          + "guardduty:*",
                          + "securityhub:*",
                          + "config:*",
                          + "cloudtrail:*",
                          + "bedrock:Invoke*",
                          + "bedrock:Converse*",
                        ]
                      + Effect   = "Deny"
                      + Resource = "*"
                      + Sid      = "DenySecSvcs"
                    },
                  + {
                      + Action      = "*"
                      + Condition   = {
                          + Null            = {
                              + "aws:ResourceTag/team" = "false"
                            }
                          + StringNotEquals = {
                              + "aws:ResourceTag/team" = [
                                  + "cake",
                                  + "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    = [
                          + "ec2:Delete*",
                          + "ec2:Modify*",
                          + "elasticloadbalancing:Delete*",
                          + "elasticloadbalancing:Modify*",
                          + "ecs:DeleteCluster",
                          + "ecs:UpdateCluster",
                          + "ecs:UpdateClusterSettings",
                          + "iam:DeleteRole",
                          + "iam:UpdateRole",
                          + "iam:DeleteRolePolicy",
                          + "iam:UpdateAssumeRolePolicy",
                          + "iam:PutRolePolicy",
                          + "iam:AttachRolePolicy",
                          + "iam:DetachRolePolicy",
                          + "route53:DeleteHostedZone",
                          + "sns:DeleteTopic",
                          + "sns:SetTopicAttributes",
                          + "ec2:AuthorizeSecurityGroup*",
                          + "ec2:RevokeSecurityGroup*",
                        ]
                      + Condition = {
                          + StringEquals = {
                              + "aws:ResourceTag/team" = "shared"
                            }
                        }
                      + Effect    = "Deny"
                      + Resource  = "*"
                      + Sid       = "DenyShared"
                    },
                  + {
                      + 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"
                    },
                  + {
                      + Action      = "iam:PassRole"
                      + Effect      = "Deny"
                      + NotResource = [
                          + "arn:aws:iam::*:role/cake-*",
                          + "arn:aws:iam::*:role/javabin-ecs-exec-cake",
                        ]
                      + Sid         = "DenyPassRole"
                    },
                  + {
                      + Action      = [
                          + "logs:GetLogEvents",
                          + "logs:FilterLogEvents",
                          + "logs:StartQuery",
                          + "logs:GetQueryResults",
                        ]
                      + Effect      = "Deny"
                      + NotResource = [
                          + "arn:aws:logs:*:*:log-group:/ecs/cake/*",
                          + "arn:aws:logs:*:*:log-group:/ecs/cake/*:*",
                        ]
                      + Sid         = "DenyXLogs"
                    },
                  + {
                      + Action   = [
                          + "iam:PutRolePolicy",
                          + "iam:DeleteRolePolicy",
                          + "iam:AttachRolePolicy",
                          + "iam:DetachRolePolicy",
                          + "iam:DeleteRole",
                          + "iam:UpdateRole",
                          + "iam:UpdateAssumeRolePolicy",
                        ]
                      + Effect   = "Deny"
                      + Resource = "arn:aws:iam::553637109631:role/javabin-ci-*"
                      + Sid      = "DenyModCI"
                    },
                  + {
                      + Action    = "ec2:CreateSecurityGroup"
                      + Condition = {
                          + StringNotEqualsIfExists = {
                              + "aws:RequestTag/team" = "cake"
                            }
                        }
                      + Effect    = "Deny"
                      + Resource  = "*"
                      + Sid       = "DenyNoTag"
                    },
                  + {
                      + Action      = [
                          + "s3:CreateBucket",
                          + "dynamodb:CreateTable",
                          + "sqs:CreateQueue",
                          + "sns:CreateTopic",
                          + "rds:CreateDBInstance",
                          + "rds:CreateDBSubnetGroup",
                          + "ecs:CreateService",
                          + "ecs:RegisterTaskDefinition",
                          + "ecr:CreateRepository",
                          + "logs:CreateLogGroup",
                          + "ssm:PutParameter",
                          + "lambda:CreateFunction",
                          + "events:PutRule",
                          + "states:CreateStateMachine",
                        ]
                      + Effect      = "Deny"
                      + NotResource = [
                          + "arn:aws:s3:::cake-*",
                          + "arn:aws:dynamodb:*:*:table/cake-*",
                          + "arn:aws:sqs:*:*:cake-*",
                          + "arn:aws:sns:*:*:cake-*",
                          + "arn:aws:rds:*:*:db:cake-*",
                          + "arn:aws:rds:*:*:subgrp:cake-*",
                          + "arn:aws:ecs:*:*:service/*/cake-*",
                          + "arn:aws:ecs:*:*:task-definition/cake-*:*",
                          + "arn:aws:ecr:*:*:repository/cake-*",
                          + "arn:aws:logs:*:*:log-group:/ecs/cake/*",
                          + "arn:aws:ssm:*:*:parameter/javabin/apps/cake/*",
                          + "arn:aws:lambda:*:*:function:cake-*",
                          + "arn:aws:events:*:*:rule/cake-*",
                          + "arn:aws:states:*:*:stateMachine:cake-*",
                        ]
                      + Sid         = "DenyBadName"
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + policy_id        = (known after apply)
      + tags             = {
          + "Name"     = "javabin-team-cake-guardrails"
          + "for-team" = "cake"
          + "team"     = "shared"
        }
      + tags_all         = {
          + "Name"        = "javabin-team-cake-guardrails"
          + "environment" = "production"
          + "for-team"    = "cake"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
    }

  # module.iam.aws_iam_policy.team_guardrails["commandchimps"] will be created
  + resource "aws_iam_policy" "team_guardrails" {
      + arn              = (known after apply)
      + attachment_count = (known after apply)
      + description      = "Developer boundary rules for team commandchimps, for its Identity Center permission set"
      + id               = (known after apply)
      + name             = "javabin-team-commandchimps-guardrails"
      + name_prefix      = (known after apply)
      + path             = "/"
      + policy           = jsonencode(
            {
              + Statement = [
                  + {
                      + Action   = "*"
                      + Effect   = "Allow"
                      + Resource = "*"
                      + Sid      = "Allow"
                    },
                  + {
                      + Action   = [
                          + "iam:DeletePolicy",
                          + "iam:DeletePolicyVersion",
                          + "iam:CreatePolicyVersion",
                          + "iam:SetDefaultPolicyVersion",
                        ]
                      + Effect   = "Deny"
                      + Resource = [
                          + "arn:aws:iam::553637109631:policy/javabin-developer-boundary",
                          + "arn:aws:iam::553637109631:policy/javabin-team-*-guardrails",
                        ]
                      + Sid      = "DenyBndMod"
                    },
                  + {
                      + Action    = [
                          + "iam:CreateRole",
                          + "iam:PutRolePermissionsBoundary",
                        ]
                      + Condition = {
                          + StringNotEquals = {
                              + "iam:PermissionsBoundary" = "arn:aws:iam::553637109631:policy/javabin-developer-boundary"
                            }
                        }
                      + Effect    = "Deny"
                      + Resource  = "*"
                      + Sid       = "DenyNoBnd"
                    },
                  + {
                      + Action   = "iam:DeleteRolePermissionsBoundary"
                      + Effect   = "Deny"
                      + Resource = "*"
                      + Sid      = "DenyStripBnd"
                    },
                  + {
                      + Action   = [
                          + "iam:CreateUser",
                          + "iam:CreateLoginProfile",
                          + "iam:UpdateLoginProfile",
                          + "iam:CreateAccessKey",
                          + "iam:DeactivateMFADevice",
                        ]
                      + Effect   = "Deny"
                      + Resource = "*"
                      + Sid      = "DenyIAMUsers"
                    },
                  + {
                      + Action   = [
                          + "organizations:*",
                          + "sso:*",
                          + "sso-directory:*",
                          + "identitystore:*",
                          + "account:*",
                        ]
                      + Effect   = "Deny"
                      + Resource = "*"
                      + Sid      = "DenyOrgSSO"
                    },
                  + {
                      + Action   = [
                          + "ec2:CreateVpc",
                          + "ec2:DeleteVpc",
                          + "ec2:ModifyVpcAttribute",
                          + "ec2:CreateSubnet",
                          + "ec2:DeleteSubnet",
                          + "ec2:CreateInternetGateway",
                          + "ec2:DeleteInternetGateway",
                          + "ec2:AttachInternetGateway",
                          + "ec2:DetachInternetGateway",
                          + "ec2:CreateNatGateway",
                          + "ec2:DeleteNatGateway",
                          + "ec2:CreateRouteTable",
                          + "ec2:DeleteRouteTable",
                        ]
                      + Effect   = "Deny"
                      + Resource = "*"
                      + Sid      = "DenyNetwork"
                    },
                  + {
                      + Action   = [
                          + "ecs:DeleteCluster",
                          + "ecs:UpdateCluster",
                          + "elasticloadbalancing:DeleteLoadBalancer",
                          + "elasticloadbalancing:ModifyLoadBalancerAttributes",
                          + "s3:DeleteBucket",
                          + "s3:PutBucketPolicy",
                          + "s3:DeleteBucketPolicy",
                          + "s3:PutBucketVersioning",
                          + "s3:PutEncryptionConfiguration",
                          + "dynamodb:DeleteTable",
                          + "dynamodb:UpdateTable",
                        ]
                      + Effect   = "Deny"
                      + Resource = [
                          + "arn:aws:ecs:eu-central-1:553637109631:cluster/javabin-platform",
                          + "arn:aws:elasticloadbalancing:eu-central-1:553637109631:loadbalancer/app/javabin-*",
                          + "arn:aws:s3:::javabin-terraform-*",
                          + "arn:aws:s3:::javabin-ci-*",
                          + "arn:aws:dynamodb:eu-central-1:553637109631:table/javabin-terraform-*",
                        ]
                      + Sid      = "DenyPlatInfra"
                    },
                  + {
                      + Action   = [
                          + "guardduty:*",
                          + "securityhub:*",
                          + "config:*",
                          + "cloudtrail:*",
                          + "bedrock:Invoke*",
                          + "bedrock:Converse*",
                        ]
                      + Effect   = "Deny"
                      + Resource = "*"
                      + Sid      = "DenySecSvcs"
                    },
                  + {
                      + Action      = "*"
                      + Condition   = {
                          + Null            = {
                              + "aws:ResourceTag/team" = "false"
                            }
                          + StringNotEquals = {
                              + "aws:ResourceTag/team" = [
                                  + "commandchimps",
                                  + "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    = [
                          + "ec2:Delete*",
                          + "ec2:Modify*",
                          + "elasticloadbalancing:Delete*",
                          + "elasticloadbalancing:Modify*",
                          + "ecs:DeleteCluster",
                          + "ecs:UpdateCluster",
                          + "ecs:UpdateClusterSettings",
                          + "iam:DeleteRole",
                          + "iam:UpdateRole",
                          + "iam:DeleteRolePolicy",
                          + "iam:UpdateAssumeRolePolicy",
                          + "iam:PutRolePolicy",
                          + "iam:AttachRolePolicy",
                          + "iam:DetachRolePolicy",
                          + "route53:DeleteHostedZone",
                          + "sns:DeleteTopic",
                          + "sns:SetTopicAttributes",
                          + "ec2:AuthorizeSecurityGroup*",
                          + "ec2:RevokeSecurityGroup*",
                        ]
                      + Condition = {
                          + StringEquals = {
                              + "aws:ResourceTag/team" = "shared"
                            }
                        }
                      + Effect    = "Deny"
                      + Resource  = "*"
                      + Sid       = "DenyShared"
                    },
                  + {
                      + 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"
                    },
                  + {
                      + Action      = "iam:PassRole"
                      + Effect      = "Deny"
                      + NotResource = [
                          + "arn:aws:iam::*:role/commandchimps-*",
                          + "arn:aws:iam::*:role/javabin-ecs-exec-commandchimps",
                        ]
                      + Sid         = "DenyPassRole"
                    },
                  + {
                      + Action      = [
                          + "logs:GetLogEvents",
                          + "logs:FilterLogEvents",
                          + "logs:StartQuery",
                          + "logs:GetQueryResults",
                        ]
                      + Effect      = "Deny"
                      + NotResource = [
                          + "arn:aws:logs:*:*:log-group:/ecs/commandchimps/*",
                          + "arn:aws:logs:*:*:log-group:/ecs/commandchimps/*:*",
                        ]
                      + Sid         = "DenyXLogs"
                    },
                  + {
                      + Action   = [
                          + "iam:PutRolePolicy",
                          + "iam:DeleteRolePolicy",
                          + "iam:AttachRolePolicy",
                          + "iam:DetachRolePolicy",
                          + "iam:DeleteRole",
                          + "iam:UpdateRole",
                          + "iam:UpdateAssumeRolePolicy",
                        ]
                      + Effect   = "Deny"
                      + Resource = "arn:aws:iam::553637109631:role/javabin-ci-*"
                      + Sid      = "DenyModCI"
                    },
                  + {
                      + Action    = "ec2:CreateSecurityGroup"
                      + Condition = {
                          + StringNotEqualsIfExists = {
                              + "aws:RequestTag/team" = "commandchimps"
                            }
                        }
                      + Effect    = "Deny"
                      + Resource  = "*"
                      + Sid       = "DenyNoTag"
                    },
                  + {
                      + Action      = [
                          + "s3:CreateBucket",
                          + "dynamodb:CreateTable",
                          + "sqs:CreateQueue",
                          + "sns:CreateTopic",
                          + "rds:CreateDBInstance",
                          + "rds:CreateDBSubnetGroup",
                          + "ecs:CreateService",
                          + "ecs:RegisterTaskDefinition",
                          + "ecr:CreateRepository",
                          + "logs:CreateLogGroup",
                          + "ssm:PutParameter",
                          + "lambda:CreateFunction",
                          + "events:PutRule",
                          + "states:CreateStateMachine",
                        ]
                      + Effect      = "Deny"
                      + NotResource = [
                          + "arn:aws:s3:::commandchimps-*",
                          + "arn:aws:dynamodb:*:*:table/commandchimps-*",
                          + "arn:aws:sqs:*:*:commandchimps-*",
                          + "arn:aws:sns:*:*:commandchimps-*",
                          + "arn:aws:rds:*:*:db:commandchimps-*",
                          + "arn:aws:rds:*:*:subgrp:commandchimps-*",
                          + "arn:aws:ecs:*:*:service/*/commandchimps-*",
                          + "arn:aws:ecs:*:*:task-definition/commandchimps-*:*",
                          + "arn:aws:ecr:*:*:repository/commandchimps-*",
                          + "arn:aws:logs:*:*:log-group:/ecs/commandchimps/*",
                          + "arn:aws:ssm:*:*:parameter/javabin/apps/commandchimps/*",
                          + "arn:aws:lambda:*:*:function:commandchimps-*",
                          + "arn:aws:events:*:*:rule/commandchimps-*",
                          + "arn:aws:states:*:*:stateMachine:commandchimps-*",
                        ]
                      + Sid         = "DenyBadName"
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + policy_id        = (known after apply)
      + tags             = {
          + "Name"     = "javabin-team-commandchimps-guardrails"
          + "for-team" = "commandchimps"
          + "team"     = "shared"
        }
      + tags_all         = {
          + "Name"        = "javabin-team-commandchimps-guardrails"
          + "environment" = "production"
          + "for-team"    = "commandchimps"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
    }

  # module.iam.aws_iam_policy.team_guardrails["cupcake"] will be created
  + resource "aws_iam_policy" "team_guardrails" {
      + arn              = (known after apply)
      + attachment_count = (known after apply)
      + description      = "Developer boundary rules for team cupcake, for its Identity Center permission set"
      + id               = (known after apply)
      + name             = "javabin-team-cupcake-guardrails"
      + name_prefix      = (known after apply)
      + path             = "/"
      + policy           = jsonencode(
            {
              + Statement = [
                  + {
                      + Action   = "*"
                      + Effect   = "Allow"
                      + Resource = "*"
                      + Sid      = "Allow"
                    },
                  + {
                      + Action   = [
                          + "iam:DeletePolicy",
                          + "iam:DeletePolicyVersion",
                          + "iam:CreatePolicyVersion",
                          + "iam:SetDefaultPolicyVersion",
                        ]
                      + Effect   = "Deny"
                      + Resource = [
                          + "arn:aws:iam::553637109631:policy/javabin-developer-boundary",
                          + "arn:aws:iam::553637109631:policy/javabin-team-*-guardrails",
                        ]
                      + Sid      = "DenyBndMod"
                    },
                  + {
                      + Action    = [
                          + "iam:CreateRole",
                          + "iam:PutRolePermissionsBoundary",
                        ]
                      + Condition = {
                          + StringNotEquals = {
                              + "iam:PermissionsBoundary" = "arn:aws:iam::553637109631:policy/javabin-developer-boundary"
                            }
                        }
                      + Effect    = "Deny"
                      + Resource  = "*"
                      + Sid       = "DenyNoBnd"
                    },
                  + {
                      + Action   = "iam:DeleteRolePermissionsBoundary"
                      + Effect   = "Deny"
                      + Resource = "*"
                      + Sid      = "DenyStripBnd"
                    },
                  + {
                      + Action   = [
                          + "iam:CreateUser",
                          + "iam:CreateLoginProfile",
                          + "iam:UpdateLoginProfile",
                          + "iam:CreateAccessKey",
                          + "iam:DeactivateMFADevice",
                        ]
                      + Effect   = "Deny"
                      + Resource = "*"
                      + Sid      = "DenyIAMUsers"
                    },
                  + {
                      + Action   = [
                          + "organizations:*",
                          + "sso:*",
                          + "sso-directory:*",
                          + "identitystore:*",
                          + "account:*",
                        ]
                      + Effect   = "Deny"
                      + Resource = "*"
                      + Sid      = "DenyOrgSSO"
                    },
                  + {
                      + Action   = [
                          + "ec2:CreateVpc",
                          + "ec2:DeleteVpc",
                          + "ec2:ModifyVpcAttribute",
                          + "ec2:CreateSubnet",
                          + "ec2:DeleteSubnet",
                          + "ec2:CreateInternetGateway",
                          + "ec2:DeleteInternetGateway",
                          + "ec2:AttachInternetGateway",
                          + "ec2:DetachInternetGateway",
                          + "ec2:CreateNatGateway",
                          + "ec2:DeleteNatGateway",
                          + "ec2:CreateRouteTable",
                          + "ec2:DeleteRouteTable",
                        ]
                      + Effect   = "Deny"
                      + Resource = "*"
                      + Sid      = "DenyNetwork"
                    },
                  + {
                      + Action   = [
                          + "ecs:DeleteCluster",
                          + "ecs:UpdateCluster",
                          + "elasticloadbalancing:DeleteLoadBalancer",
                          + "elasticloadbalancing:ModifyLoadBalancerAttributes",
                          + "s3:DeleteBucket",
                          + "s3:PutBucketPolicy",
                          + "s3:DeleteBucketPolicy",
                          + "s3:PutBucketVersioning",
                          + "s3:PutEncryptionConfiguration",
                          + "dynamodb:DeleteTable",
                          + "dynamodb:UpdateTable",
                        ]
                      + Effect   = "Deny"
                      + Resource = [
                          + "arn:aws:ecs:eu-central-1:553637109631:cluster/javabin-platform",
                          + "arn:aws:elasticloadbalancing:eu-central-1:553637109631:loadbalancer/app/javabin-*",
                          + "arn:aws:s3:::javabin-terraform-*",
                          + "arn:aws:s3:::javabin-ci-*",
                          + "arn:aws:dynamodb:eu-central-1:553637109631:table/javabin-terraform-*",
                        ]
                      + Sid      = "DenyPlatInfra"
                    },
                  + {
                      + Action   = [
                          + "guardduty:*",
                          + "securityhub:*",
                          + "config:*",
                          + "cloudtrail:*",
                          + "bedrock:Invoke*",
                          + "bedrock:Converse*",
                        ]
                      + Effect   = "Deny"
                      + Resource = "*"
                      + Sid      = "DenySecSvcs"
                    },
                  + {
                      + Action      = "*"
                      + Condition   = {
                          + Null            = {
                              + "aws:ResourceTag/team" = "false"
                            }
                          + StringNotEquals = {
                              + "aws:ResourceTag/team" = [
                                  + "cupcake",
                                  + "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    = [
                          + "ec2:Delete*",
                          + "ec2:Modify*",
                          + "elasticloadbalancing:Delete*",
                          + "elasticloadbalancing:Modify*",
                          + "ecs:DeleteCluster",
                          + "ecs:UpdateCluster",
                          + "ecs:UpdateClusterSettings",
                          + "iam:DeleteRole",
                          + "iam:UpdateRole",
                          + "iam:DeleteRolePolicy",
                          + "iam:UpdateAssumeRolePolicy",
                          + "iam:PutRolePolicy",
                          + "iam:AttachRolePolicy",
                          + "iam:DetachRolePolicy",
                          + "route53:DeleteHostedZone",
                          + "sns:DeleteTopic",
                          + "sns:SetTopicAttributes",
                          + "ec2:AuthorizeSecurityGroup*",
                          + "ec2:RevokeSecurityGroup*",
                        ]
                      + Condition = {
                          + StringEquals = {
                              + "aws:ResourceTag/team" = "shared"
                            }
                        }
                      + Effect    = "Deny"
                      + Resource  = "*"
                      + Sid       = "DenyShared"
                    },
                  + {
                      + 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"
                    },
                  + {
                      + Action      = "iam:PassRole"
                      + Effect      = "Deny"
                      + NotResource = [
                          + "arn:aws:iam::*:role/cupcake-*",
                          + "arn:aws:iam::*:role/javabin-ecs-exec-cupcake",
                        ]
                      + Sid         = "DenyPassRole"
                    },
                  + {
                      + Action      = [
                          + "logs:GetLogEvents",
                          + "logs:FilterLogEvents",
                          + "logs:StartQuery",
                          + "logs:GetQueryResults",
                        ]
                      + Effect      = "Deny"
                      + NotResource = [
                          + "arn:aws:logs:*:*:log-group:/ecs/cupcake/*",
                          + "arn:aws:logs:*:*:log-group:/ecs/cupcake/*:*",
                        ]
                      + Sid         = "DenyXLogs"
                    },
                  + {
                      + Action   = [
                          + "iam:PutRolePolicy",
                          + "iam:DeleteRolePolicy",
                          + "iam:AttachRolePolicy",
                          + "iam:DetachRolePolicy",
                          + "iam:DeleteRole",
                          + "iam:UpdateRole",
                          + "iam:UpdateAssumeRolePolicy",
                        ]
                      + Effect   = "Deny"
                      + Resource = "arn:aws:iam::553637109631:role/javabin-ci-*"
                      + Sid      = "DenyModCI"
                    },
                  + {
                      + Action    = "ec2:CreateSecurityGroup"
                      + Condition = {
                          + StringNotEqualsIfExists = {
                              + "aws:RequestTag/team" = "cupcake"
                            }
                        }
                      + Effect    = "Deny"
                      + Resource  = "*"
                      + Sid       = "DenyNoTag"
                    },
                  + {
                      + Action      = [
                          + "s3:CreateBucket",
                          + "dynamodb:CreateTable",
                          + "sqs:CreateQueue",
                          + "sns:CreateTopic",
                          + "rds:CreateDBInstance",
                          + "rds:CreateDBSubnetGroup",
                          + "ecs:CreateService",
                          + "ecs:RegisterTaskDefinition",
                          + "ecr:CreateRepository",
                          + "logs:CreateLogGroup",
                          + "ssm:PutParameter",
                          + "lambda:CreateFunction",
                          + "events:PutRule",
                          + "states:CreateStateMachine",
                        ]
                      + Effect      = "Deny"
                      + NotResource = [
                          + "arn:aws:s3:::cupcake-*",
                          + "arn:aws:dynamodb:*:*:table/cupcake-*",
                          + "arn:aws:sqs:*:*:cupcake-*",
                          + "arn:aws:sns:*:*:cupcake-*",
                          + "arn:aws:rds:*:*:db:cupcake-*",
                          + "arn:aws:rds:*:*:subgrp:cupcake-*",
                          + "arn:aws:ecs:*:*:service/*/cupcake-*",
                          + "arn:aws:ecs:*:*:task-definition/cupcake-*:*",
                          + "arn:aws:ecr:*:*:repository/cupcake-*",
                          + "arn:aws:logs:*:*:log-group:/ecs/cupcake/*",
                          + "arn:aws:ssm:*:*:parameter/javabin/apps/cupcake/*",
                          + "arn:aws:lambda:*:*:function:cupcake-*",
                          + "arn:aws:events:*:*:rule/cupcake-*",
                          + "arn:aws:states:*:*:stateMachine:cupcake-*",
                        ]
                      + Sid         = "DenyBadName"
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + policy_id        = (known after apply)
      + tags             = {
          + "Name"     = "javabin-team-cupcake-guardrails"
          + "for-team" = "cupcake"
          + "team"     = "shared"
        }
      + tags_all         = {
          + "Name"        = "javabin-team-cupcake-guardrails"
          + "environment" = "production"
          + "for-team"    = "cupcake"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
    }

  # module.iam.aws_iam_policy.team_guardrails["developer"] will be created
  + resource "aws_iam_policy" "team_guardrails" {
      + arn              = (known after apply)
      + attachment_count = (known after apply)
      + description      = "Developer boundary rules for team developer, for its Identity Center permission set"
      + id               = (known after apply)
      + name             = "javabin-team-developer-guardrails"
      + name_prefix      = (known after apply)
      + path             = "/"
      + policy           = jsonencode(
            {
              + Statement = [
                  + {
                      + Action   = "*"
                      + Effect   = "Allow"
                      + Resource = "*"
                      + Sid      = "Allow"
                    },
                  + {
                      + Action   = [
                          + "iam:DeletePolicy",
                          + "iam:DeletePolicyVersion",
                          + "iam:CreatePolicyVersion",
                          + "iam:SetDefaultPolicyVersion",
                        ]
                      + Effect   = "Deny"
                      + Resource = [
                          + "arn:aws:iam::553637109631:policy/javabin-developer-boundary",
                          + "arn:aws:iam::553637109631:policy/javabin-team-*-guardrails",
                        ]
                      + Sid      = "DenyBndMod"
                    },
                  + {
                      + Action    = [
                          + "iam:CreateRole",
                          + "iam:PutRolePermissionsBoundary",
                        ]
                      + Condition = {
                          + StringNotEquals = {
                              + "iam:PermissionsBoundary" = "arn:aws:iam::553637109631:policy/javabin-developer-boundary"
                            }
                        }
                      + Effect    = "Deny"
                      + Resource  = "*"
                      + Sid       = "DenyNoBnd"
                    },
                  + {
                      + Action   = "iam:DeleteRolePermissionsBoundary"
                      + Effect   = "Deny"
                      + Resource = "*"
                      + Sid      = "DenyStripBnd"
                    },
                  + {
                      + Action   = [
                          + "iam:CreateUser",
                          + "iam:CreateLoginProfile",
                          + "iam:UpdateLoginProfile",
                          + "iam:CreateAccessKey",
                          + "iam:DeactivateMFADevice",
                        ]
                      + Effect   = "Deny"
                      + Resource = "*"
                      + Sid      = "DenyIAMUsers"
                    },
                  + {
                      + Action   = [
                          + "organizations:*",
                          + "sso:*",
                          + "sso-directory:*",
                          + "identitystore:*",
                          + "account:*",
                        ]
                      + Effect   = "Deny"
                      + Resource = "*"
                      + Sid      = "DenyOrgSSO"
                    },
                  + {
                      + Action   = [
                          + "ec2:CreateVpc",
                          + "ec2:DeleteVpc",
                          + "ec2:ModifyVpcAttribute",
                          + "ec2:CreateSubnet",
                          + "ec2:DeleteSubnet",
                          + "ec2:CreateInternetGateway",
                          + "ec2:DeleteInternetGateway",
                          + "ec2:AttachInternetGateway",
                          + "ec2:DetachInternetGateway",
                          + "ec2:CreateNatGateway",
                          + "ec2:DeleteNatGateway",
                          + "ec2:CreateRouteTable",
                          + "ec2:DeleteRouteTable",
                        ]
                      + Effect   = "Deny"
                      + Resource = "*"
                      + Sid      = "DenyNetwork"
                    },
                  + {
                      + Action   = [
                          + "ecs:DeleteCluster",
                          + "ecs:UpdateCluster",
                          + "elasticloadbalancing:DeleteLoadBalancer",
                          + "elasticloadbalancing:ModifyLoadBalancerAttributes",
                          + "s3:DeleteBucket",
                          + "s3:PutBucketPolicy",
                          + "s3:DeleteBucketPolicy",
                          + "s3:PutBucketVersioning",
                          + "s3:PutEncryptionConfiguration",
                          + "dynamodb:DeleteTable",
                          + "dynamodb:UpdateTable",
                        ]
                      + Effect   = "Deny"
                      + Resource = [
                          + "arn:aws:ecs:eu-central-1:553637109631:cluster/javabin-platform",
                          + "arn:aws:elasticloadbalancing:eu-central-1:553637109631:loadbalancer/app/javabin-*",
                          + "arn:aws:s3:::javabin-terraform-*",
                          + "arn:aws:s3:::javabin-ci-*",
                          + "arn:aws:dynamodb:eu-central-1:553637109631:table/javabin-terraform-*",
                        ]
                      + Sid      = "DenyPlatInfra"
                    },
                  + {
                      + Action   = [
                          + "guardduty:*",
                          + "securityhub:*",
                          + "config:*",
                          + "cloudtrail:*",
                          + "bedrock:Invoke*",
                          + "bedrock:Converse*",
                        ]
                      + Effect   = "Deny"
                      + Resource = "*"
                      + Sid      = "DenySecSvcs"
                    },
                  + {
                      + Action      = "*"
                      + Condition   = {
                          + Null            = {
                              + "aws:ResourceTag/team" = "false"
                            }
                          + StringNotEquals = {
                              + "aws:ResourceTag/team" = [
                                  + "developer",
                                  + "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    = [
                          + "ec2:Delete*",
                          + "ec2:Modify*",
                          + "elasticloadbalancing:Delete*",
                          + "elasticloadbalancing:Modify*",
                          + "ecs:DeleteCluster",
                          + "ecs:UpdateCluster",
                          + "ecs:UpdateClusterSettings",
                          + "iam:DeleteRole",
                          + "iam:UpdateRole",
                          + "iam:DeleteRolePolicy",
                          + "iam:UpdateAssumeRolePolicy",
                          + "iam:PutRolePolicy",
                          + "iam:AttachRolePolicy",
                          + "iam:DetachRolePolicy",
                          + "route53:DeleteHostedZone",
                          + "sns:DeleteTopic",
                          + "sns:SetTopicAttributes",
                          + "ec2:AuthorizeSecurityGroup*",
                          + "ec2:RevokeSecurityGroup*",
                        ]
                      + Condition = {
                          + StringEquals = {
                              + "aws:ResourceTag/team" = "shared"
                            }
                        }
                      + Effect    = "Deny"
                      + Resource  = "*"
                      + Sid       = "DenyShared"
                    },
                  + {
                      + 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"
                    },
                  + {
                      + Action      = "iam:PassRole"
                      + Effect      = "Deny"
                      + NotResource = [
                          + "arn:aws:iam::*:role/developer-*",
                          + "arn:aws:iam::*:role/javabin-ecs-exec-developer",
                        ]
                      + Sid         = "DenyPassRole"
                    },
                  + {
                      + Action      = [
                          + "logs:GetLogEvents",
                          + "logs:FilterLogEvents",
                          + "logs:StartQuery",
                          + "logs:GetQueryResults",
                        ]
                      + Effect      = "Deny"
                      + NotResource = [
                          + "arn:aws:logs:*:*:log-group:/ecs/developer/*",
                          + "arn:aws:logs:*:*:log-group:/ecs/developer/*:*",
                        ]
                      + Sid         = "DenyXLogs"
                    },
                  + {
                      + Action   = [
                          + "iam:PutRolePolicy",
                          + "iam:DeleteRolePolicy",
                          + "iam:AttachRolePolicy",
                          + "iam:DetachRolePolicy",
                          + "iam:DeleteRole",
                          + "iam:UpdateRole",
                          + "iam:UpdateAssumeRolePolicy",
                        ]
                      + Effect   = "Deny"
                      + Resource = "arn:aws:iam::553637109631:role/javabin-ci-*"
                      + Sid      = "DenyModCI"
                    },
                  + {
                      + Action    = "ec2:CreateSecurityGroup"
                      + Condition = {
                          + StringNotEqualsIfExists = {
                              + "aws:RequestTag/team" = "developer"
                            }
                        }
                      + Effect    = "Deny"
                      + Resource  = "*"
                      + Sid       = "DenyNoTag"
                    },
                  + {
                      + Action      = [
                          + "s3:CreateBucket",
                          + "dynamodb:CreateTable",
                          + "sqs:CreateQueue",
                          + "sns:CreateTopic",
                          + "rds:CreateDBInstance",
                          + "rds:CreateDBSubnetGroup",
                          + "ecs:CreateService",
        

LLM Review

Risk: 🟡 MEDIUM

Plan adds 22 team guardrail IAM policies (javabin-team-*-guardrails), updates the developer boundary policy to also cover the new guardrail policies, and updates the team provisioner Lambda and its IAM role policy; 0 destroys.

  • 🔒 [security] Developer boundary policy is updated so its Resource list also includes javabin-team-*-guardrails, which blocks developers from modifying or deleting guardrail policies. This is a tightening change, not a loosening one.
  • 🔒 [security] Team provisioner IAM role policy gains sso:ProvisionPermissionSet, sso:DescribePermissionSetProvisioningStatus, sso:Detach/AttachCustomerManagedPolicyReference, iam:GetPolicy/GetPolicyVersion on team guardrails, and new IAM role create/attach/put/delete actions scoped to aws-reserved SSO roles and AWSSSO_* SAML providers. Effect is Allow, so these are real grants. They are scoped to SSO-related resources but the IAM role-management permissions deserve a closer look at review.
  • 🔒 [security] Each new guardrail policy begins with an Allow * statement, with Deny statements layered on top. Team-tag conditions and NotResource exclusions appear to restrict each team to its own resources, and the DenyNoBnd and DenyStripBnd statements protect the permissions boundary. Confirm the team-tag enforcement actually works as intended, since it depends on resources being tagged.
  • ✅ [routine] 22 aws_iam_policy resources are created with no cost impact. The team list includes 'shared' tags on the policies and a few unusual team names (for example 'cake', 'cupcake', 'developer', 'testteam') that should be checked against the intended team roster.
  • ✅ [routine] Lambda team_provisioner gets a code update (source_code_hash change) and the in-place IAM policy update. No destruction, no networking or database resources changed. Nothing here is a cost-generating resource.

…e deny

Review feedback on #145:
- Blocker: anyone with the guardrails (or a team CI role) could create
  javabin-team-<new>-guardrails with Allow * before a team is
  registered; team-provisioner attaches it by name. DenyBndMod now also
  denies iam:CreatePolicy/TagPolicy/UntagPolicy on those names, and the
  provisioner only attaches a policy tagged managed-by=terraform from
  javaBin/platform.
- PutParameter has no aws:ResourceTag condition key, so the 'deny
  creating parameters' rule would have denied every secret write. Use
  ssm:Overwrite instead (creation requires Overwrite unset or false).
- When a team's guardrails don't exist yet (new team, or platform), leave
  the permission set untouched and report pending instead of detaching
  the boundary and failing provisioning.
- Provisioning status errors no longer escape.

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

Copy link
Copy Markdown

Terraform Plan

🚧 Changes detected — Plan: 24 to add, 3 to change, 0 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

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 = [
                    {
                        Action   = "*"
                        Effect   = "Allow"
                        Resource = "*"
                        Sid      = "Allow"
                    },
                  ~ {
                      ~ Action   = [
                            # (3 unchanged elements hidden)
                            "iam:SetDefaultPolicyVersion",
                          + "iam:CreatePolicy",
                          + "iam:TagPolicy",
                          + "iam:UntagPolicy",
                        ]
                      ~ Resource = "arn:aws:iam::553637109631:policy/javabin-developer-boundary" -> [
                          + "arn:aws:iam::553637109631:policy/javabin-developer-boundary",
                          + "arn:aws:iam::553637109631:policy/javabin-team-*-guardrails",
                        ]
                        # (2 unchanged attributes hidden)
                    },
                    {
                        Action    = [
                            "iam:CreateRole",
                            "iam:PutRolePermissionsBoundary",
                        ]
                        Condition = {
                            StringNotEquals = {
                                "iam:PermissionsBoundary" = "arn:aws:iam::553637109631:policy/javabin-developer-boundary"
                            }
                        }
                        Effect    = "Deny"
                        Resource  = "*"
                        Sid       = "DenyNoBnd"
                    },
                    # (15 unchanged elements hidden)
                ]
                # (1 unchanged attribute hidden)
            }
        )
        tags             = {
            "Name" = "javabin-developer-boundary"
        }
        # (6 unchanged attributes hidden)
    }

  # module.iam.aws_iam_policy.team_guardrails["cake"] will be created
  + resource "aws_iam_policy" "team_guardrails" {
      + arn              = (known after apply)
      + attachment_count = (known after apply)
      + description      = "Developer boundary rules for team cake, for its Identity Center permission set"
      + id               = (known after apply)
      + name             = "javabin-team-cake-guardrails"
      + name_prefix      = (known after apply)
      + path             = "/"
      + policy           = jsonencode(
            {
              + Statement = [
                  + {
                      + Action   = "*"
                      + Effect   = "Allow"
                      + Resource = "*"
                      + Sid      = "Allow"
                    },
                  + {
                      + Action   = [
                          + "iam:DeletePolicy",
                          + "iam:DeletePolicyVersion",
                          + "iam:CreatePolicyVersion",
                          + "iam:SetDefaultPolicyVersion",
                          + "iam:CreatePolicy",
                          + "iam:TagPolicy",
                          + "iam:UntagPolicy",
                        ]
                      + Effect   = "Deny"
                      + Resource = [
                          + "arn:aws:iam::553637109631:policy/javabin-developer-boundary",
                          + "arn:aws:iam::553637109631:policy/javabin-team-*-guardrails",
                        ]
                      + Sid      = "DenyBndMod"
                    },
                  + {
                      + Action    = [
                          + "iam:CreateRole",
                          + "iam:PutRolePermissionsBoundary",
                        ]
                      + Condition = {
                          + StringNotEquals = {
                              + "iam:PermissionsBoundary" = "arn:aws:iam::553637109631:policy/javabin-developer-boundary"
                            }
                        }
                      + Effect    = "Deny"
                      + Resource  = "*"
                      + Sid       = "DenyNoBnd"
                    },
                  + {
                      + Action   = "iam:DeleteRolePermissionsBoundary"
                      + Effect   = "Deny"
                      + Resource = "*"
                      + Sid      = "DenyStripBnd"
                    },
                  + {
                      + Action   = [
                          + "iam:CreateUser",
                          + "iam:CreateLoginProfile",
                          + "iam:UpdateLoginProfile",
                          + "iam:CreateAccessKey",
                          + "iam:DeactivateMFADevice",
                        ]
                      + Effect   = "Deny"
                      + Resource = "*"
                      + Sid      = "DenyIAMUsers"
                    },
                  + {
                      + Action   = [
                          + "organizations:*",
                          + "sso:*",
                          + "sso-directory:*",
                          + "identitystore:*",
                          + "account:*",
                        ]
                      + Effect   = "Deny"
                      + Resource = "*"
                      + Sid      = "DenyOrgSSO"
                    },
                  + {
                      + Action   = [
                          + "ec2:CreateVpc",
                          + "ec2:DeleteVpc",
                          + "ec2:ModifyVpcAttribute",
                          + "ec2:CreateSubnet",
                          + "ec2:DeleteSubnet",
                          + "ec2:CreateInternetGateway",
                          + "ec2:DeleteInternetGateway",
                          + "ec2:AttachInternetGateway",
                          + "ec2:DetachInternetGateway",
                          + "ec2:CreateNatGateway",
                          + "ec2:DeleteNatGateway",
                          + "ec2:CreateRouteTable",
                          + "ec2:DeleteRouteTable",
                        ]
                      + Effect   = "Deny"
                      + Resource = "*"
                      + Sid      = "DenyNetwork"
                    },
                  + {
                      + Action   = [
                          + "ecs:DeleteCluster",
                          + "ecs:UpdateCluster",
                          + "elasticloadbalancing:DeleteLoadBalancer",
                          + "elasticloadbalancing:ModifyLoadBalancerAttributes",
                          + "s3:DeleteBucket",
                          + "s3:PutBucketPolicy",
                          + "s3:DeleteBucketPolicy",
                          + "s3:PutBucketVersioning",
                          + "s3:PutEncryptionConfiguration",
                          + "dynamodb:DeleteTable",
                          + "dynamodb:UpdateTable",
                        ]
                      + Effect   = "Deny"
                      + Resource = [
                          + "arn:aws:ecs:eu-central-1:553637109631:cluster/javabin-platform",
                          + "arn:aws:elasticloadbalancing:eu-central-1:553637109631:loadbalancer/app/javabin-*",
                          + "arn:aws:s3:::javabin-terraform-*",
                          + "arn:aws:s3:::javabin-ci-*",
                          + "arn:aws:dynamodb:eu-central-1:553637109631:table/javabin-terraform-*",
                        ]
                      + Sid      = "DenyPlatInfra"
                    },
                  + {
                      + Action   = [
                          + "guardduty:*",
                          + "securityhub:*",
                          + "config:*",
                          + "cloudtrail:*",
                          + "bedrock:Invoke*",
                          + "bedrock:Converse*",
                        ]
                      + Effect   = "Deny"
                      + Resource = "*"
                      + Sid      = "DenySecSvcs"
                    },
                  + {
                      + Action      = "*"
                      + Condition   = {
                          + Null            = {
                              + "aws:ResourceTag/team" = "false"
                            }
                          + StringNotEquals = {
                              + "aws:ResourceTag/team" = [
                                  + "cake",
                                  + "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    = [
                          + "ec2:Delete*",
                          + "ec2:Modify*",
                          + "elasticloadbalancing:Delete*",
                          + "elasticloadbalancing:Modify*",
                          + "ecs:DeleteCluster",
                          + "ecs:UpdateCluster",
                          + "ecs:UpdateClusterSettings",
                          + "iam:DeleteRole",
                          + "iam:UpdateRole",
                          + "iam:DeleteRolePolicy",
                          + "iam:UpdateAssumeRolePolicy",
                          + "iam:PutRolePolicy",
                          + "iam:AttachRolePolicy",
                          + "iam:DetachRolePolicy",
                          + "route53:DeleteHostedZone",
                          + "sns:DeleteTopic",
                          + "sns:SetTopicAttributes",
                          + "ec2:AuthorizeSecurityGroup*",
                          + "ec2:RevokeSecurityGroup*",
                        ]
                      + Condition = {
                          + StringEquals = {
                              + "aws:ResourceTag/team" = "shared"
                            }
                        }
                      + Effect    = "Deny"
                      + Resource  = "*"
                      + Sid       = "DenyShared"
                    },
                  + {
                      + 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"
                    },
                  + {
                      + Action      = "iam:PassRole"
                      + Effect      = "Deny"
                      + NotResource = [
                          + "arn:aws:iam::*:role/cake-*",
                          + "arn:aws:iam::*:role/javabin-ecs-exec-cake",
                        ]
                      + Sid         = "DenyPassRole"
                    },
                  + {
                      + Action      = [
                          + "logs:GetLogEvents",
                          + "logs:FilterLogEvents",
                          + "logs:StartQuery",
                          + "logs:GetQueryResults",
                        ]
                      + Effect      = "Deny"
                      + NotResource = [
                          + "arn:aws:logs:*:*:log-group:/ecs/cake/*",
                          + "arn:aws:logs:*:*:log-group:/ecs/cake/*:*",
                        ]
                      + Sid         = "DenyXLogs"
                    },
                  + {
                      + Action   = [
                          + "iam:PutRolePolicy",
                          + "iam:DeleteRolePolicy",
                          + "iam:AttachRolePolicy",
                          + "iam:DetachRolePolicy",
                          + "iam:DeleteRole",
                          + "iam:UpdateRole",
                          + "iam:UpdateAssumeRolePolicy",
                        ]
                      + Effect   = "Deny"
                      + Resource = "arn:aws:iam::553637109631:role/javabin-ci-*"
                      + Sid      = "DenyModCI"
                    },
                  + {
                      + Action    = "ec2:CreateSecurityGroup"
                      + Condition = {
                          + StringNotEqualsIfExists = {
                              + "aws:RequestTag/team" = "cake"
                            }
                        }
                      + Effect    = "Deny"
                      + Resource  = "*"
                      + Sid       = "DenyNoTag"
                    },
                  + {
                      + Action      = [
                          + "s3:CreateBucket",
                          + "dynamodb:CreateTable",
                          + "sqs:CreateQueue",
                          + "sns:CreateTopic",
                          + "rds:CreateDBInstance",
                          + "rds:CreateDBSubnetGroup",
                          + "ecs:CreateService",
                          + "ecs:RegisterTaskDefinition",
                          + "ecr:CreateRepository",
                          + "logs:CreateLogGroup",
                          + "ssm:PutParameter",
                          + "lambda:CreateFunction",
                          + "events:PutRule",
                          + "states:CreateStateMachine",
                        ]
                      + Effect      = "Deny"
                      + NotResource = [
                          + "arn:aws:s3:::cake-*",
                          + "arn:aws:dynamodb:*:*:table/cake-*",
                          + "arn:aws:sqs:*:*:cake-*",
                          + "arn:aws:sns:*:*:cake-*",
                          + "arn:aws:rds:*:*:db:cake-*",
                          + "arn:aws:rds:*:*:subgrp:cake-*",
                          + "arn:aws:ecs:*:*:service/*/cake-*",
                          + "arn:aws:ecs:*:*:task-definition/cake-*:*",
                          + "arn:aws:ecr:*:*:repository/cake-*",
                          + "arn:aws:logs:*:*:log-group:/ecs/cake/*",
                          + "arn:aws:ssm:*:*:parameter/javabin/apps/cake/*",
                          + "arn:aws:lambda:*:*:function:cake-*",
                          + "arn:aws:events:*:*:rule/cake-*",
                          + "arn:aws:states:*:*:stateMachine:cake-*",
                        ]
                      + Sid         = "DenyBadName"
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + policy_id        = (known after apply)
      + tags             = {
          + "Name"     = "javabin-team-cake-guardrails"
          + "for-team" = "cake"
          + "team"     = "shared"
        }
      + tags_all         = {
          + "Name"        = "javabin-team-cake-guardrails"
          + "environment" = "production"
          + "for-team"    = "cake"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
    }

  # module.iam.aws_iam_policy.team_guardrails["commandchimps"] will be created
  + resource "aws_iam_policy" "team_guardrails" {
      + arn              = (known after apply)
      + attachment_count = (known after apply)
      + description      = "Developer boundary rules for team commandchimps, for its Identity Center permission set"
      + id               = (known after apply)
      + name             = "javabin-team-commandchimps-guardrails"
      + name_prefix      = (known after apply)
      + path             = "/"
      + policy           = jsonencode(
            {
              + Statement = [
                  + {
                      + Action   = "*"
                      + Effect   = "Allow"
                      + Resource = "*"
                      + Sid      = "Allow"
                    },
                  + {
                      + Action   = [
                          + "iam:DeletePolicy",
                          + "iam:DeletePolicyVersion",
                          + "iam:CreatePolicyVersion",
                          + "iam:SetDefaultPolicyVersion",
                          + "iam:CreatePolicy",
                          + "iam:TagPolicy",
                          + "iam:UntagPolicy",
                        ]
                      + Effect   = "Deny"
                      + Resource = [
                          + "arn:aws:iam::553637109631:policy/javabin-developer-boundary",
                          + "arn:aws:iam::553637109631:policy/javabin-team-*-guardrails",
                        ]
                      + Sid      = "DenyBndMod"
                    },
                  + {
                      + Action    = [
                          + "iam:CreateRole",
                          + "iam:PutRolePermissionsBoundary",
                        ]
                      + Condition = {
                          + StringNotEquals = {
                              + "iam:PermissionsBoundary" = "arn:aws:iam::553637109631:policy/javabin-developer-boundary"
                            }
                        }
                      + Effect    = "Deny"
                      + Resource  = "*"
                      + Sid       = "DenyNoBnd"
                    },
                  + {
                      + Action   = "iam:DeleteRolePermissionsBoundary"
                      + Effect   = "Deny"
                      + Resource = "*"
                      + Sid      = "DenyStripBnd"
                    },
                  + {
                      + Action   = [
                          + "iam:CreateUser",
                          + "iam:CreateLoginProfile",
                          + "iam:UpdateLoginProfile",
                          + "iam:CreateAccessKey",
                          + "iam:DeactivateMFADevice",
                        ]
                      + Effect   = "Deny"
                      + Resource = "*"
                      + Sid      = "DenyIAMUsers"
                    },
                  + {
                      + Action   = [
                          + "organizations:*",
                          + "sso:*",
                          + "sso-directory:*",
                          + "identitystore:*",
                          + "account:*",
                        ]
                      + Effect   = "Deny"
                      + Resource = "*"
                      + Sid      = "DenyOrgSSO"
                    },
                  + {
                      + Action   = [
                          + "ec2:CreateVpc",
                          + "ec2:DeleteVpc",
                          + "ec2:ModifyVpcAttribute",
                          + "ec2:CreateSubnet",
                          + "ec2:DeleteSubnet",
                          + "ec2:CreateInternetGateway",
                          + "ec2:DeleteInternetGateway",
                          + "ec2:AttachInternetGateway",
                          + "ec2:DetachInternetGateway",
                          + "ec2:CreateNatGateway",
                          + "ec2:DeleteNatGateway",
                          + "ec2:CreateRouteTable",
                          + "ec2:DeleteRouteTable",
                        ]
                      + Effect   = "Deny"
                      + Resource = "*"
                      + Sid      = "DenyNetwork"
                    },
                  + {
                      + Action   = [
                          + "ecs:DeleteCluster",
                          + "ecs:UpdateCluster",
                          + "elasticloadbalancing:DeleteLoadBalancer",
                          + "elasticloadbalancing:ModifyLoadBalancerAttributes",
                          + "s3:DeleteBucket",
                          + "s3:PutBucketPolicy",
                          + "s3:DeleteBucketPolicy",
                          + "s3:PutBucketVersioning",
                          + "s3:PutEncryptionConfiguration",
                          + "dynamodb:DeleteTable",
                          + "dynamodb:UpdateTable",
                        ]
                      + Effect   = "Deny"
                      + Resource = [
                          + "arn:aws:ecs:eu-central-1:553637109631:cluster/javabin-platform",
                          + "arn:aws:elasticloadbalancing:eu-central-1:553637109631:loadbalancer/app/javabin-*",
                          + "arn:aws:s3:::javabin-terraform-*",
                          + "arn:aws:s3:::javabin-ci-*",
                          + "arn:aws:dynamodb:eu-central-1:553637109631:table/javabin-terraform-*",
                        ]
                      + Sid      = "DenyPlatInfra"
                    },
                  + {
                      + Action   = [
                          + "guardduty:*",
                          + "securityhub:*",
                          + "config:*",
                          + "cloudtrail:*",
                          + "bedrock:Invoke*",
                          + "bedrock:Converse*",
                        ]
                      + Effect   = "Deny"
                      + Resource = "*"
                      + Sid      = "DenySecSvcs"
                    },
                  + {
                      + Action      = "*"
                      + Condition   = {
                          + Null            = {
                              + "aws:ResourceTag/team" = "false"
                            }
                          + StringNotEquals = {
                              + "aws:ResourceTag/team" = [
                                  + "commandchimps",
                                  + "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    = [
                          + "ec2:Delete*",
                          + "ec2:Modify*",
                          + "elasticloadbalancing:Delete*",
                          + "elasticloadbalancing:Modify*",
                          + "ecs:DeleteCluster",
                          + "ecs:UpdateCluster",
                          + "ecs:UpdateClusterSettings",
                          + "iam:DeleteRole",
                          + "iam:UpdateRole",
                          + "iam:DeleteRolePolicy",
                          + "iam:UpdateAssumeRolePolicy",
                          + "iam:PutRolePolicy",
                          + "iam:AttachRolePolicy",
                          + "iam:DetachRolePolicy",
                          + "route53:DeleteHostedZone",
                          + "sns:DeleteTopic",
                          + "sns:SetTopicAttributes",
                          + "ec2:AuthorizeSecurityGroup*",
                          + "ec2:RevokeSecurityGroup*",
                        ]
                      + Condition = {
                          + StringEquals = {
                              + "aws:ResourceTag/team" = "shared"
                            }
                        }
                      + Effect    = "Deny"
                      + Resource  = "*"
                      + Sid       = "DenyShared"
                    },
                  + {
                      + 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"
                    },
                  + {
                      + Action      = "iam:PassRole"
                      + Effect      = "Deny"
                      + NotResource = [
                          + "arn:aws:iam::*:role/commandchimps-*",
                          + "arn:aws:iam::*:role/javabin-ecs-exec-commandchimps",
                        ]
                      + Sid         = "DenyPassRole"
                    },
                  + {
                      + Action      = [
                          + "logs:GetLogEvents",
                          + "logs:FilterLogEvents",
                          + "logs:StartQuery",
                          + "logs:GetQueryResults",
                        ]
                      + Effect      = "Deny"
                      + NotResource = [
                          + "arn:aws:logs:*:*:log-group:/ecs/commandchimps/*",
                          + "arn:aws:logs:*:*:log-group:/ecs/commandchimps/*:*",
                        ]
                      + Sid         = "DenyXLogs"
                    },
                  + {
                      + Action   = [
                          + "iam:PutRolePolicy",
                          + "iam:DeleteRolePolicy",
                          + "iam:AttachRolePolicy",
                          + "iam:DetachRolePolicy",
                          + "iam:DeleteRole",
                          + "iam:UpdateRole",
                          + "iam:UpdateAssumeRolePolicy",
                        ]
                      + Effect   = "Deny"
                      + Resource = "arn:aws:iam::553637109631:role/javabin-ci-*"
                      + Sid      = "DenyModCI"
                    },
                  + {
                      + Action    = "ec2:CreateSecurityGroup"
                      + Condition = {
                          + StringNotEqualsIfExists = {
                              + "aws:RequestTag/team" = "commandchimps"
                            }
                        }
                      + Effect    = "Deny"
                      + Resource  = "*"
                      + Sid       = "DenyNoTag"
                    },
                  + {
                      + Action      = [
                          + "s3:CreateBucket",
                          + "dynamodb:CreateTable",
                          + "sqs:CreateQueue",
                          + "sns:CreateTopic",
                          + "rds:CreateDBInstance",
                          + "rds:CreateDBSubnetGroup",
                          + "ecs:CreateService",
                          + "ecs:RegisterTaskDefinition",
                          + "ecr:CreateRepository",
                          + "logs:CreateLogGroup",
                          + "ssm:PutParameter",
                          + "lambda:CreateFunction",
                          + "events:PutRule",
                          + "states:CreateStateMachine",
                        ]
                      + Effect      = "Deny"
                      + NotResource = [
                          + "arn:aws:s3:::commandchimps-*",
                          + "arn:aws:dynamodb:*:*:table/commandchimps-*",
                          + "arn:aws:sqs:*:*:commandchimps-*",
                          + "arn:aws:sns:*:*:commandchimps-*",
                          + "arn:aws:rds:*:*:db:commandchimps-*",
                          + "arn:aws:rds:*:*:subgrp:commandchimps-*",
                          + "arn:aws:ecs:*:*:service/*/commandchimps-*",
                          + "arn:aws:ecs:*:*:task-definition/commandchimps-*:*",
                          + "arn:aws:ecr:*:*:repository/commandchimps-*",
                          + "arn:aws:logs:*:*:log-group:/ecs/commandchimps/*",
                          + "arn:aws:ssm:*:*:parameter/javabin/apps/commandchimps/*",
                          + "arn:aws:lambda:*:*:function:commandchimps-*",
                          + "arn:aws:events:*:*:rule/commandchimps-*",
                          + "arn:aws:states:*:*:stateMachine:commandchimps-*",
                        ]
                      + Sid         = "DenyBadName"
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + policy_id        = (known after apply)
      + tags             = {
          + "Name"     = "javabin-team-commandchimps-guardrails"
          + "for-team" = "commandchimps"
          + "team"     = "shared"
        }
      + tags_all         = {
          + "Name"        = "javabin-team-commandchimps-guardrails"
          + "environment" = "production"
          + "for-team"    = "commandchimps"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
    }

  # module.iam.aws_iam_policy.team_guardrails["cupcake"] will be created
  + resource "aws_iam_policy" "team_guardrails" {
      + arn              = (known after apply)
      + attachment_count = (known after apply)
      + description      = "Developer boundary rules for team cupcake, for its Identity Center permission set"
      + id               = (known after apply)
      + name             = "javabin-team-cupcake-guardrails"
      + name_prefix      = (known after apply)
      + path             = "/"
      + policy           = jsonencode(
            {
              + Statement = [
                  + {
                      + Action   = "*"
                      + Effect   = "Allow"
                      + Resource = "*"
                      + Sid      = "Allow"
                    },
                  + {
                      + Action   = [
                          + "iam:DeletePolicy",
                          + "iam:DeletePolicyVersion",
                          + "iam:CreatePolicyVersion",
                          + "iam:SetDefaultPolicyVersion",
                          + "iam:CreatePolicy",
                          + "iam:TagPolicy",
                          + "iam:UntagPolicy",
                        ]
                      + Effect   = "Deny"
                      + Resource = [
                          + "arn:aws:iam::553637109631:policy/javabin-developer-boundary",
                          + "arn:aws:iam::553637109631:policy/javabin-team-*-guardrails",
                        ]
                      + Sid      = "DenyBndMod"
                    },
                  + {
                      + Action    = [
                          + "iam:CreateRole",
                          + "iam:PutRolePermissionsBoundary",
                        ]
                      + Condition = {
                          + StringNotEquals = {
                              + "iam:PermissionsBoundary" = "arn:aws:iam::553637109631:policy/javabin-developer-boundary"
                            }
                        }
                      + Effect    = "Deny"
                      + Resource  = "*"
                      + Sid       = "DenyNoBnd"
                    },
                  + {
                      + Action   = "iam:DeleteRolePermissionsBoundary"
                      + Effect   = "Deny"
                      + Resource = "*"
                      + Sid      = "DenyStripBnd"
                    },
                  + {
                      + Action   = [
                          + "iam:CreateUser",
                          + "iam:CreateLoginProfile",
                          + "iam:UpdateLoginProfile",
                          + "iam:CreateAccessKey",
                          + "iam:DeactivateMFADevice",
                        ]
                      + Effect   = "Deny"
                      + Resource = "*"
                      + Sid      = "DenyIAMUsers"
                    },
                  + {
                      + Action   = [
                          + "organizations:*",
                          + "sso:*",
                          + "sso-directory:*",
                          + "identitystore:*",
                          + "account:*",
                        ]
                      + Effect   = "Deny"
                      + Resource = "*"
                      + Sid      = "DenyOrgSSO"
                    },
                  + {
                      + Action   = [
                          + "ec2:CreateVpc",
                          + "ec2:DeleteVpc",
                          + "ec2:ModifyVpcAttribute",
                          + "ec2:CreateSubnet",
                          + "ec2:DeleteSubnet",
                          + "ec2:CreateInternetGateway",
                          + "ec2:DeleteInternetGateway",
                          + "ec2:AttachInternetGateway",
                          + "ec2:DetachInternetGateway",
                          + "ec2:CreateNatGateway",
                          + "ec2:DeleteNatGateway",
                          + "ec2:CreateRouteTable",
                          + "ec2:DeleteRouteTable",
                        ]
                      + Effect   = "Deny"
                      + Resource = "*"
                      + Sid      = "DenyNetwork"
                    },
                  + {
                      + Action   = [
                          + "ecs:DeleteCluster",
                          + "ecs:UpdateCluster",
                          + "elasticloadbalancing:DeleteLoadBalancer",
                          + "elasticloadbalancing:ModifyLoadBalancerAttributes",
                          + "s3:DeleteBucket",
                          + "s3:PutBucketPolicy",
                          + "s3:DeleteBucketPolicy",
                          + "s3:PutBucketVersioning",
                          + "s3:PutEncryptionConfiguration",
                          + "dynamodb:DeleteTable",
                          + "dynamodb:UpdateTable",
                        ]
                      + Effect   = "Deny"
                      + Resource = [
                          + "arn:aws:ecs:eu-central-1:553637109631:cluster/javabin-platform",
                          + "arn:aws:elasticloadbalancing:eu-central-1:553637109631:loadbalancer/app/javabin-*",
                          + "arn:aws:s3:::javabin-terraform-*",
                          + "arn:aws:s3:::javabin-ci-*",
                          + "arn:aws:dynamodb:eu-central-1:553637109631:table/javabin-terraform-*",
                        ]
                      + Sid      = "DenyPlatInfra"
                    },
                  + {
                      + Action   = [
                          + "guardduty:*",
                          + "securityhub:*",
                          + "config:*",
                          + "cloudtrail:*",
                          + "bedrock:Invoke*",
                          + "bedrock:Converse*",
                        ]
                      + Effect   = "Deny"
                      + Resource = "*"
                      + Sid      = "DenySecSvcs"
                    },
                  + {
                      + Action      = "*"
                      + Condition   = {
                          + Null            = {
                              + "aws:ResourceTag/team" = "false"
                            }
                          + StringNotEquals = {
                              + "aws:ResourceTag/team" = [
                                  + "cupcake",
                                  + "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    = [
                          + "ec2:Delete*",
                          + "ec2:Modify*",
                          + "elasticloadbalancing:Delete*",
                          + "elasticloadbalancing:Modify*",
                          + "ecs:DeleteCluster",
                          + "ecs:UpdateCluster",
                          + "ecs:UpdateClusterSettings",
                          + "iam:DeleteRole",
                          + "iam:UpdateRole",
                          + "iam:DeleteRolePolicy",
                          + "iam:UpdateAssumeRolePolicy",
                          + "iam:PutRolePolicy",
                          + "iam:AttachRolePolicy",
                          + "iam:DetachRolePolicy",
                          + "route53:DeleteHostedZone",
                          + "sns:DeleteTopic",
                          + "sns:SetTopicAttributes",
                          + "ec2:AuthorizeSecurityGroup*",
                          + "ec2:RevokeSecurityGroup*",
                        ]
                      + Condition = {
                          + StringEquals = {
                              + "aws:ResourceTag/team" = "shared"
                            }
                        }
                      + Effect    = "Deny"
                      + Resource  = "*"
                      + Sid       = "DenyShared"
                    },
                  + {
                      + 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"
                    },
                  + {
                      + Action      = "iam:PassRole"
                      + Effect      = "Deny"
                      + NotResource = [
                          + "arn:aws:iam::*:role/cupcake-*",
                          + "arn:aws:iam::*:role/javabin-ecs-exec-cupcake",
                        ]
                      + Sid         = "DenyPassRole"
                    },
                  + {
                      + Action      = [
                          + "logs:GetLogEvents",
                          + "logs:FilterLogEvents",
                          + "logs:StartQuery",
                          + "logs:GetQueryResults",
                        ]
                      + Effect      = "Deny"
                      + NotResource = [
                          + "arn:aws:logs:*:*:log-group:/ecs/cupcake/*",
                          + "arn:aws:logs:*:*:log-group:/ecs/cupcake/*:*",
                        ]
                      + Sid         = "DenyXLogs"
                    },
                  + {
                      + Action   = [
                          + "iam:PutRolePolicy",
                          + "iam:DeleteRolePolicy",
                          + "iam:AttachRolePolicy",
                          + "iam:DetachRolePolicy",
                          + "iam:DeleteRole",
                          + "iam:UpdateRole",
                          + "iam:UpdateAssumeRolePolicy",
                        ]
                      + Effect   = "Deny"
                      + Resource = "arn:aws:iam::553637109631:role/javabin-ci-*"
                      + Sid      = "DenyModCI"
                    },
                  + {
                      + Action    = "ec2:CreateSecurityGroup"
                      + Condition = {
                          + StringNotEqualsIfExists = {
                              + "aws:RequestTag/team" = "cupcake"
                            }
                        }
                      + Effect    = "Deny"
                      + Resource  = "*"
                      + Sid       = "DenyNoTag"
                    },
                  + {
                      + Action      = [
                          + "s3:CreateBucket",
                          + "dynamodb:CreateTable",
                          + "sqs:CreateQueue",
                          + "sns:CreateTopic",
                          + "rds:CreateDBInstance",
                          + "rds:CreateDBSubnetGroup",
                          + "ecs:CreateService",
                          + "ecs:RegisterTaskDefinition",
                          + "ecr:CreateRepository",
                          + "logs:CreateLogGroup",
                          + "ssm:PutParameter",
                          + "lambda:CreateFunction",
                          + "events:PutRule",
                          + "states:CreateStateMachine",
                        ]
                      + Effect      = "Deny"
                      + NotResource = [
                          + "arn:aws:s3:::cupcake-*",
                          + "arn:aws:dynamodb:*:*:table/cupcake-*",
                          + "arn:aws:sqs:*:*:cupcake-*",
                          + "arn:aws:sns:*:*:cupcake-*",
                          + "arn:aws:rds:*:*:db:cupcake-*",
                          + "arn:aws:rds:*:*:subgrp:cupcake-*",
                          + "arn:aws:ecs:*:*:service/*/cupcake-*",
                          + "arn:aws:ecs:*:*:task-definition/cupcake-*:*",
                          + "arn:aws:ecr:*:*:repository/cupcake-*",
                          + "arn:aws:logs:*:*:log-group:/ecs/cupcake/*",
                          + "arn:aws:ssm:*:*:parameter/javabin/apps/cupcake/*",
                          + "arn:aws:lambda:*:*:function:cupcake-*",
                          + "arn:aws:events:*:*:rule/cupcake-*",
                          + "arn:aws:states:*:*:stateMachine:cupcake-*",
                        ]
                      + Sid         = "DenyBadName"
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + policy_id        = (known after apply)
      + tags             = {
          + "Name"     = "javabin-team-cupcake-guardrails"
          + "for-team" = "cupcake"
          + "team"     = "shared"
        }
      + tags_all         = {
          + "Name"        = "javabin-team-cupcake-guardrails"
          + "environment" = "production"
          + "for-team"    = "cupcake"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "shared"
        }
    }

  # module.iam.aws_iam_policy.team_guardrails["developer"] will be created
  + resource "aws_iam_policy" "team_guardrails" {
      + arn              = (known after apply)
      + attachment_count = (known after apply)
      + description      = "Developer boundary rules for team developer, for its Identity Center permission set"
      + id               = (known after apply)
      + name             = "javabin-team-developer-guardrails"
      + name_prefix      = (known after apply)
      + path             = "/"
      + policy           = jsonencode(
            {
              + Statement = [
                  + {
                      + Action   = "*"
                      + Effect   = "Allow"
                      + Resource = "*"
                      + Sid      = "Allow"
                    },
                  + {
                      + Action   = [
                          + "iam:DeletePolicy",
                          + "iam:DeletePolicyVersion",
                          + "iam:CreatePolicyVersion",
                          + "iam:SetDefaultPolicyVersion",
                          + "iam:CreatePolicy",
                          + "iam:TagPolicy",
                          + "iam:UntagPolicy",
                        ]
                      + Effect   = "Deny"
                      + Resource = [
                          + "arn:aws:iam::553637109631:policy/javabin-developer-boundary",
                          + "arn:aws:iam::553637109631:policy/javabin-team-*-guardrails",
                        ]
                      + Sid      = "DenyBndMod"
                    },
                  + {
                      + Action    = [
                          + "iam:CreateRole",
                          + "iam:PutRolePermissionsBoundary",
                        ]
                      + Condition = {
                          + StringNotEquals = {
                              + "iam:PermissionsBoundary" = "arn:aws:iam::553637109631:policy/javabin-developer-boundary"
                            }
                        }
                      + Effect    = "Deny"
                      + Resource  = "*"
                      + Sid       = "DenyNoBnd"
                    },
                  + {
                      + Action   = "iam:DeleteRolePermissionsBoundary"
                      + Effect   = "Deny"
                      + Resource = "*"
                      + Sid      = "DenyStripBnd"
                    },
                  + {
                      + Action   = [
                          + "iam:CreateUser",
                          + "iam:CreateLoginProfile",
                          + "iam:UpdateLoginProfile",
                          + "iam:CreateAccessKey",
                          + "iam:DeactivateMFADevice",
                        ]
                      + Effect   = "Deny"
                      + Resource = "*"
                      + Sid      = "DenyIAMUsers"
                    },
                  + {
                      + Action   = [
                          + "organizations:*",
                          + "sso:*",
                          + "sso-directory:*",
                          + "identitystore:*",
                          + "account:*",
                        ]
                      + Effect   = "Deny"
                      + Resource = "*"
                      + Sid      = "DenyOrgSSO"
                    },
                  + {
                      + Action   = [
                          + "ec2:CreateVpc",
                          + "ec2:DeleteVpc",
                          + "ec2:ModifyVpcAttribute",
                          + "ec2:CreateSubnet",
                          + "ec2:DeleteSubnet",
                          + "ec2:CreateInternetGateway",
                          + "ec2:DeleteInternetGateway",
                          + "ec2:AttachInternetGateway",
                          + "ec2:DetachInternetGateway",
                          + "ec2:CreateNatGateway",
                          + "ec2:DeleteNatGateway",
                          + "ec2:CreateRouteTable",
                          + "ec2:DeleteRouteTable",
                        ]
                      + Effect   = "Deny"
                      + Resource = "*"
                      + Sid      = "DenyNetwork"
                    },
                  + {
                      + Action   = [
                          + "ecs:DeleteCluster",
                          + "ecs:UpdateCluster",
                          + "elasticloadbalancing:DeleteLoadBalancer",
                          + "elasticloadbalancing:ModifyLoadBalancerAttributes",
                          + "s3:DeleteBucket",
                          + "s3:PutBucketPolicy",
                          + "s3:DeleteBucketPolicy",
                          + "s3:PutBucketVersioning",
                          + "s3:PutEncryptionConfiguration",
                          + "dynamodb:DeleteTable",
                          + "dynamodb:UpdateTable",
                        ]
                      + Effect   = "Deny"
                      + Resource = [
                          + "arn:aws:ecs:eu-central-1:553637109631:cluster/javabin-platform",
                          + "arn:aws:elasticloadbalancing:eu-central-1:553637109631:loadbalancer/app/javabin-*",
                          + "arn:aws:s3:::javabin-terraform-*",
                          + "arn:aws:s3:::javabin-ci-*",
                          + "arn:aws:dynamodb:eu-central-1:553637109631:table/javabin-terraform-*",
                        ]
                      + Sid      = "DenyPlatInfra"
                    },
                  + {
                      + Action   = [
                          + "guardduty:*",
                          + "securityhub:*",
                          + "config:*",
                          + "cloudtrail:*",
                          + "bedrock:Invoke*",
                          + "bedrock:Converse*",
                        ]
                      + Effect   = "Deny"
                      + Resource = "*"
                      + Sid      = "DenySecSvcs"
                    },
                  + {
                      + Action      = "*"
                      + Condition   = {
                          + Null            = {
                              + "aws:ResourceTag/team" = "false"
                            }
                          + StringNotEquals = {
                              + "aws:ResourceTag/team" = [
                                  + "developer",
                                  + "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    = [
                          + "ec2:Delete*",
                          + "ec2:Modify*",
                          + "elasticloadbalancing:Delete*",
                          + "elasticloadbalancing:Modify*",
                          + "ecs:DeleteCluster",
                          + "ecs:UpdateCluster",
                          + "ecs:UpdateClusterSettings",
                          + "iam:DeleteRole",
                          + "iam:UpdateRole",
                          + "iam:DeleteRolePolicy",
                          + "iam:UpdateAssumeRolePolicy",
                          + "iam:PutRolePolicy",
                          + "iam:AttachRolePolicy",
                          + "iam:DetachRolePolicy",
                          + "route53:DeleteHostedZone",
                          + "sns:DeleteTopic",
                          + "sns:SetTopicAttributes",
                          + "ec2:AuthorizeSecurityGroup*",
                          + "ec2:RevokeSecurityGroup*",
                        ]
                      + Condition = {
                          + StringEquals = {
                              + "aws:ResourceTag/team" = "shared"
                            }
                        }
                      + Effect    = "Deny"
                      + Resource  = "*"
                      + Sid       = "DenyShared"
                    },
                  + {
                      + 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"
                    },
                  + {
                      + Action      = "iam:PassRole"
                      + Effect      = "Deny"
                      + NotResource = [
                          + "arn:aws:iam::*:role/developer-*",
                          + "arn:aws:iam::*:role/javabin-ecs-exec-developer",
                        ]
                      + Sid         = "DenyPassRole"
                    },
                  + {
                      + Action      = [
                          + "logs:GetLogEvents",
                          + "logs:FilterLogEvents",
                          + "logs:StartQuery",
                          + "logs:GetQueryResults",
                        ]
                      + Effect      = "Deny"
                      + NotResource = [
                          + "arn:aws:logs:*:*:log-group:/ecs/developer/*",
                          + "arn:aws:logs:*:*:log-group:/ecs/developer/*:*",
                        ]
                      + Sid         = "DenyXLogs"
                    },
                  + {
                      + Action   = [
                          + "iam:PutRolePolicy",
                          + "iam:DeleteRolePolicy",
                          + "iam:AttachRolePolicy",
                          + "iam:DetachRolePolicy",
                          + "iam:DeleteRole",
                          + "iam:UpdateRole",
                          + "iam:UpdateAssumeRolePolicy",
                        ]
                      + Effect   = "Deny"
                      + Resource = "arn:aws:iam::553637109631:role/javabin-ci-*"
          

LLM Review

Risk: 🟡 MEDIUM

Plan adds 24 team guardrail IAM policies (one per team), updates the developer boundary policy to let developers create and tag policies, extends the team-provisioner role's SSO and IAM permissions, and updates the provisioner Lambda code; nothing is destroyed.

  • 🔒 [security] The developer boundary change adds iam:CreatePolicy, iam:TagPolicy and iam:UntagPolicy to a statement whose Effect is Allow (the Allow statement's Action is '', and the Resource list is widened to include javabin-developer-boundary and javabin-team--guardrails). This is a permission grant on policies that the guardrails themselves depend on. Note the boundary's own Deny statements (DenyBndMod) block modifying these policies for team roles, but the new Allow on Resource should be reviewed to confirm it does not let developers alter the boundary itself.
  • 🔒 [security] The team-provisioner role gains sso:ProvisionPermissionSet, sso:DescribePermissionSetProvisioningStatus, sso:Attach/DetachCustomerManagedPolicyReferenceFromPermissionSet, plus iam:CreateRole, iam:AttachRolePolicy, iam:PutRolePolicy, iam:UpdateRole, iam:DeleteRole and related actions scoped to aws-reserved SSO roles and AWSSSO_* SAML providers. Effect is Allow. These are privilege-escalation-relevant and should be confirmed as intended, with the scope of the role's Resource ARNs reviewed.
  • 🔒 [security] All 24 team guardrail policies are new. Each has the same structure: an Allow * statement, plus Deny statements scoped by team tag and name prefix. Deny statements are the key guardrails (DenyNoBnd, DenyStripBnd, DenyOrgSSO, DenyPlatSSM, DenyBndMod). The policies appear consistent with each other and with the boundary, but the 'team' tags are set to 'shared' on the policy resources, which should be checked against the DenyShared and DenyTagStrip conditions.
  • ✅ [routine] The developer boundary policy diff shows only additions to the Allow-related Resource and action lists, plus new Deny statements in the guardrail policies. No IAM policy is destroyed. This is a non-destructive plan with 24 creations and 3 in-place updates.
  • ✅ [routine] The Lambda team-provisioner function code hash changes (source_code_hash and last_modified are known after apply). This is a routine code deployment, and the associated inline policy update is the main review item above.

@Alexanderamiri
Alexanderamiri merged commit f5ec341 into main Oct 24, 2026
4 checks passed
@Alexanderamiri
Alexanderamiri deleted the fix/sso-team-guardrails branch October 24, 2026 09:41
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.

Developer SSO sessions carry no team tag, so DenyXTeam blocks all access to their own team's resources (javabin secret list/set fails)

1 participant