diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index a55a8c6..bc64382 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -41,10 +41,20 @@ jobs: steps: - uses: actions/checkout@v6 + - name: Resolve team from GitHub + id: team + env: + GH_TOKEN: ${{ github.token }} + run: | + TEAM=$(gh api "/repos/${{ github.repository }}/teams" \ + --jq '[.[] | select(.slug != "platform-owners")] | .[0].slug // empty' 2>/dev/null || true) + if [ -z "$TEAM" ]; then echo "ERROR: repo not in a team"; exit 1; fi + echo "team=$TEAM" >> "$GITHUB_OUTPUT" + - name: Configure AWS credentials via OIDC uses: aws-actions/configure-aws-credentials@v6 with: - role-to-assume: arn:aws:iam::${{ inputs.aws_account_id }}:role/javabin-ci-deploy-${{ github.event.repository.name }} + role-to-assume: arn:aws:iam::${{ inputs.aws_account_id }}:role/javabin-ci-deploy-${{ steps.team.outputs.team }} aws-region: ${{ inputs.aws_region }} - name: Login to ECR diff --git a/.github/workflows/ecs-deploy.yml b/.github/workflows/ecs-deploy.yml index a27d872..8f7f694 100644 --- a/.github/workflows/ecs-deploy.yml +++ b/.github/workflows/ecs-deploy.yml @@ -50,10 +50,20 @@ jobs: sparse-checkout: scripts path: .platform + - name: Resolve team from GitHub + id: team + env: + GH_TOKEN: ${{ github.token }} + run: | + TEAM=$(gh api "/repos/${{ github.repository }}/teams" \ + --jq '[.[] | select(.slug != "platform-owners")] | .[0].slug // empty' 2>/dev/null || true) + if [ -z "$TEAM" ]; then echo "ERROR: repo not in a team"; exit 1; fi + echo "team=$TEAM" >> "$GITHUB_OUTPUT" + - name: Configure AWS credentials via OIDC uses: aws-actions/configure-aws-credentials@v6 with: - role-to-assume: arn:aws:iam::${{ inputs.aws_account_id }}:role/javabin-ci-deploy-${{ github.event.repository.name }} + role-to-assume: arn:aws:iam::${{ inputs.aws_account_id }}:role/javabin-ci-deploy-${{ steps.team.outputs.team }} aws-region: ${{ inputs.aws_region }} - name: Deploy to ECS diff --git a/.github/workflows/platform-ci.yml b/.github/workflows/platform-ci.yml index 637e11a..88ea87a 100644 --- a/.github/workflows/platform-ci.yml +++ b/.github/workflows/platform-ci.yml @@ -73,11 +73,11 @@ jobs: aws-region: ${{ env.AWS_REGION }} role-session-name: javabin-platform-plan-${{ github.run_id }} - - name: Sync registered repos from GitHub teams + - name: Sync registered teams from GitHub org if: steps.changes.outputs.has_infra_changes == 'true' && github.ref == 'refs/heads/main' env: GH_TOKEN: ${{ github.token }} - run: python3 scripts/sync-registered-repos.py "${{ env.TF_ROOT }}/registered-apps.auto.tfvars" || echo "Sync skipped — will use existing tfvars" + run: python3 scripts/sync-registered-teams.py "${{ env.TF_ROOT }}/registered-teams.auto.tfvars" || echo "Sync skipped — will use existing tfvars" - name: Terraform Init if: steps.changes.outputs.has_infra_changes == 'true' diff --git a/.github/workflows/tf-plan.yml b/.github/workflows/tf-plan.yml index 631ce52..ce6f053 100644 --- a/.github/workflows/tf-plan.yml +++ b/.github/workflows/tf-plan.yml @@ -55,10 +55,25 @@ jobs: terraform_version: "1.7" terraform_wrapper: false + - name: Resolve team from GitHub + id: team + env: + GH_TOKEN: ${{ github.token }} + run: | + TEAM=$(gh api "/repos/${{ github.repository }}/teams" \ + --jq '[.[] | select(.slug != "platform-owners")] | .[0].slug // empty' 2>/dev/null || true) + if [ -z "$TEAM" ]; then + echo "ERROR: repo does not belong to any GitHub team" + echo "Add it at https://github.com/orgs/javaBin/teams" + exit 1 + fi + echo "Resolved team: $TEAM" + echo "team=$TEAM" >> "$GITHUB_OUTPUT" + - name: Configure AWS credentials via OIDC uses: aws-actions/configure-aws-credentials@v6 with: - role-to-assume: arn:aws:iam::${{ inputs.aws_account_id }}:role/javabin-ci-app-${{ github.event.repository.name }} + role-to-assume: arn:aws:iam::${{ inputs.aws_account_id }}:role/javabin-ci-team-${{ steps.team.outputs.team }} aws-region: ${{ inputs.aws_region }} - name: Generate GitHub App token diff --git a/scripts/resolve-team.sh b/scripts/resolve-team.sh new file mode 100644 index 0000000..a780121 --- /dev/null +++ b/scripts/resolve-team.sh @@ -0,0 +1,26 @@ +#!/bin/sh +# Resolve which team a repo belongs to via GitHub API. +# +# Usage: resolve-team.sh +# +# Env: GITHUB_REPOSITORY (org/repo), GH_TOKEN or GITHUB_TOKEN +# Output: team={slug} written to GITHUB_OUTPUT +# +# Queries /repos/{owner}/{repo}/teams and picks the first non-platform team. +# Fails if the repo doesn't belong to any team (no IAM role to assume). + +set -e + +REPO="${GITHUB_REPOSITORY:?GITHUB_REPOSITORY required}" + +TEAM=$(gh api "/repos/${REPO}/teams" \ + --jq '[.[] | select(.slug != "platform-owners")] | .[0].slug // empty' 2>/dev/null || true) + +if [ -z "$TEAM" ]; then + echo "ERROR: repo ${REPO} does not belong to any GitHub team." + echo "Add the repo to your team at https://github.com/orgs/javaBin/teams" + exit 1 +fi + +echo "Resolved team: ${TEAM}" +echo "team=${TEAM}" >> "${GITHUB_OUTPUT:-/dev/null}" diff --git a/scripts/sync-registered-repos.py b/scripts/sync-registered-repos.py deleted file mode 100755 index 83fc4f3..0000000 --- a/scripts/sync-registered-repos.py +++ /dev/null @@ -1,125 +0,0 @@ -#!/usr/bin/env python3 -"""Sync registered app repos from GitHub team memberships. - -Queries the GitHub API for all teams in the javaBin org, collects their repos, -and writes registered-apps.auto.tfvars. This replaces the manual list. - -Source of truth: GitHub team → repo membership. -Teams add repos via GitHub UI. This script syncs that to Terraform. - -Usage: sync-registered-repos.py - -Requires: GITHUB_TOKEN env var (with org:read scope) or GitHub App credentials -via GH_APP_ID + GH_APP_KEY env vars (read from SSM if not set). -""" - -import json -import logging -import os -import sys -import urllib.request - -logger = logging.getLogger(__name__) -logging.basicConfig(level=logging.INFO, format="%(message)s") - -GITHUB_ORG = os.environ.get("GITHUB_ORG", "javaBin") -GITHUB_API = "https://api.github.com" - -# Repos that are platform infrastructure, not apps -EXCLUDED_REPOS = {"platform", "registry", ".github"} - - -def github_get(path, token): - """Paginated GitHub API GET.""" - results = [] - url = f"{GITHUB_API}{path}" - while url: - req = urllib.request.Request(url) - req.add_header("Authorization", f"token {token}") - req.add_header("Accept", "application/vnd.github+json") - with urllib.request.urlopen(req) as resp: - results.extend(json.loads(resp.read())) - # Follow pagination - link = resp.headers.get("Link", "") - url = None - for part in link.split(","): - if 'rel="next"' in part: - url = part.split("<")[1].split(">")[0] - return results - - -def get_team_repos(token): - """Get all repos across all org teams, excluding platform repos.""" - teams = github_get(f"/orgs/{GITHUB_ORG}/teams", token) - logger.info("Found %d teams in %s", len(teams), GITHUB_ORG) - - repo_set = set() - for team in teams: - slug = team["slug"] - repos = github_get(f"/orgs/{GITHUB_ORG}/teams/{slug}/repos", token) - team_repo_names = {r["name"] for r in repos} - EXCLUDED_REPOS - if team_repo_names: - logger.info(" %s: %s", slug, ", ".join(sorted(team_repo_names))) - repo_set.update(team_repo_names) - - return sorted(repo_set) - - -def write_tfvars(repos, output_path): - """Write the registered-apps.auto.tfvars file.""" - lines = [ - "# GENERATED by sync-registered-repos.py — do not edit manually", - "# Source of truth: GitHub team repo memberships in javaBin org", - f"# Last synced: {__import__('datetime').datetime.now(__import__('datetime').timezone.utc).isoformat()}", - "", - "registered_app_repos = [", - ] - for repo in repos: - lines.append(f' "{repo}",') - lines.append("]") - lines.append("") - - content = "\n".join(lines) - - # Only write if changed - existing = "" - if os.path.exists(output_path): - with open(output_path) as f: - existing = f.read() - - # Compare ignoring the timestamp line - def strip_timestamp(s): - return "\n".join(l for l in s.splitlines() if not l.startswith("# Last synced:")) - - if strip_timestamp(content) == strip_timestamp(existing): - logger.info("No changes to registered repos") - return False - - with open(output_path, "w") as f: - f.write(content) - logger.info("Wrote %d repos to %s", len(repos), output_path) - return True - - -def main(): - if len(sys.argv) != 2: - print(f"Usage: {sys.argv[0]} ", file=sys.stderr) - sys.exit(1) - - output_path = sys.argv[1] - token = os.environ.get("GITHUB_TOKEN") or os.environ.get("GH_TOKEN") - if not token: - print("GITHUB_TOKEN or GH_TOKEN required", file=sys.stderr) - sys.exit(1) - - repos = get_team_repos(token) - logger.info("Total registered repos: %d", len(repos)) - - changed = write_tfvars(repos, output_path) - if changed: - logger.info("registered-apps.auto.tfvars updated") - sys.exit(0) - - -if __name__ == "__main__": - main() diff --git a/scripts/sync-registered-teams.py b/scripts/sync-registered-teams.py new file mode 100644 index 0000000..5b603d1 --- /dev/null +++ b/scripts/sync-registered-teams.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python3 +"""Sync registered teams from GitHub org teams. + +Queries the GitHub API for all teams in the javaBin org and writes +registered-teams.auto.tfvars. This drives team-scoped IAM role creation. + +Source of truth: GitHub teams (created by team-provisioner from registry). + +Usage: sync-registered-teams.py + +Requires: GITHUB_TOKEN env var (with org team read access). +""" + +import json +import logging +import os +import sys +import urllib.request + +logger = logging.getLogger(__name__) +logging.basicConfig(level=logging.INFO, format="%(message)s") + +GITHUB_ORG = os.environ.get("GITHUB_ORG", "javaBin") +GITHUB_API = "https://api.github.com" + +# Platform-internal teams that don't get app CI roles +EXCLUDED_TEAMS = {"platform-owners"} + + +def github_get(path, token): + """Paginated GitHub API GET.""" + results = [] + url = f"{GITHUB_API}{path}" + while url: + req = urllib.request.Request(url) + req.add_header("Authorization", f"token {token}") + req.add_header("Accept", "application/vnd.github+json") + with urllib.request.urlopen(req) as resp: + results.extend(json.loads(resp.read())) + link = resp.headers.get("Link", "") + url = None + for part in link.split(","): + if 'rel="next"' in part: + url = part.split("<")[1].split(">")[0] + return results + + +def get_teams(token): + """Get all org teams, excluding platform-internal ones.""" + teams = github_get(f"/orgs/{GITHUB_ORG}/teams", token) + slugs = sorted(t["slug"] for t in teams if t["slug"] not in EXCLUDED_TEAMS) + logger.info("Found %d teams (excluding %s)", len(slugs), ", ".join(EXCLUDED_TEAMS)) + for slug in slugs: + logger.info(" %s", slug) + return slugs + + +def write_tfvars(teams, output_path): + """Write the registered-teams.auto.tfvars file.""" + lines = [ + "# GENERATED by sync-registered-teams.py — do not edit manually", + "# Source of truth: GitHub teams in javaBin org", + "", + "registered_teams = [", + ] + for team in teams: + lines.append(f' "{team}",') + lines.append("]") + lines.append("") + + content = "\n".join(lines) + + existing = "" + if os.path.exists(output_path): + with open(output_path) as f: + existing = f.read() + + if content == existing: + logger.info("No changes to registered teams") + return False + + with open(output_path, "w") as f: + f.write(content) + logger.info("Wrote %d teams to %s", len(teams), output_path) + return True + + +def main(): + if len(sys.argv) != 2: + print(f"Usage: {sys.argv[0]} ", file=sys.stderr) + sys.exit(1) + + output_path = sys.argv[1] + token = os.environ.get("GITHUB_TOKEN") or os.environ.get("GH_TOKEN") + if not token: + print("GITHUB_TOKEN or GH_TOKEN required", file=sys.stderr) + sys.exit(1) + + teams = get_teams(token) + write_tfvars(teams, output_path) + + +if __name__ == "__main__": + main() diff --git a/terraform/platform/iam/main.tf b/terraform/platform/iam/main.tf index f96bc8d..9872ff4 100644 --- a/terraform/platform/iam/main.tf +++ b/terraform/platform/iam/main.tf @@ -256,31 +256,31 @@ resource "aws_iam_role_policy" "ci_infra_deny" { } ################################################################################ -# 2. javabin-ci-app-{repo} — Per-app Terraform role (plan + apply) +# 2. javabin-ci-team-{team} — Per-team Terraform role (plan + apply) # # Trust: GitHub OIDC with TWO conditions: -# - sub matches the repo (any ref, since plan runs on PRs too) +# - sub matches ANY repo in the org (team membership checked by workflow) # - job_workflow_ref pins to the platform's tf-plan.yml on main # -# This means: only workflows defined in javaBin/platform can assume this role, -# even though the workflow runs in the app repo's context. App repos cannot -# write their own workflows to assume this role. +# Security model: only our controlled workflows can assume these roles. +# The workflow resolves team from GitHub API and assumes the correct role. +# App repos cannot write their own workflows to assume this role. # -# Permissions: Allow *:* with tag-based isolation. The StringEqualsIfExists -# condition ensures apps can only touch resources tagged with their project. +# Permissions: Allow *:* with team-based tag isolation. Resources must be +# tagged with the correct team name. ################################################################################ -resource "aws_iam_role" "ci_app" { - for_each = toset(var.registered_app_repos) +resource "aws_iam_role" "ci_team" { + for_each = toset(var.registered_teams) - name = "${var.project}-ci-app-${each.key}" + name = "${var.project}-ci-team-${each.key}" permissions_boundary = aws_iam_policy.developer_boundary.arn assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [ { - Sid = "AllowPlanAndReviewViaOIDC" + Sid = "AllowPlanViaOIDC" Effect = "Allow" Principal = { Federated = data.aws_iam_openid_connect_provider.github.arn @@ -291,8 +291,8 @@ resource "aws_iam_role" "ci_app" { "token.actions.githubusercontent.com:aud" = "sts.amazonaws.com" } StringLike = { - "token.actions.githubusercontent.com:sub" = "repo:${var.github_org}/${each.key}:*" - # Plan + review (merged into tf-plan) — apply goes through the gate Lambda + # Any repo in the org — team membership enforced by the workflow + "token.actions.githubusercontent.com:sub" = "repo:${var.github_org}/*:*" "token.actions.githubusercontent.com:job_workflow_ref" = [ "${var.github_org}/platform/.github/workflows/tf-plan.yml@refs/heads/main", ] @@ -311,38 +311,39 @@ resource "aws_iam_role" "ci_app" { }) tags = { - Name = "${var.project}-ci-app-${each.key}" + Name = "${var.project}-ci-team-${each.key}" + team = each.key } } -resource "aws_iam_role_policy" "ci_app_allow" { - for_each = toset(var.registered_app_repos) +resource "aws_iam_role_policy" "ci_team_allow" { + for_each = toset(var.registered_teams) - name = "app-management" - role = aws_iam_role.ci_app[each.key].id + name = "team-management" + role = aws_iam_role.ci_team[each.key].id policy = jsonencode({ Version = "2012-10-17" Statement = [{ - Sid = "AllowWithTagIsolation" + Sid = "AllowWithTeamTagIsolation" Effect = "Allow" Action = "*" Resource = "*" Condition = { StringEqualsIfExists = { - "aws:ResourceTag/project" = "$${aws:PrincipalTag/project}" - "aws:RequestTag/project" = "$${aws:PrincipalTag/project}" + "aws:ResourceTag/team" = each.key + "aws:RequestTag/team" = each.key } } }] }) } -resource "aws_iam_role_policy" "ci_app_deny" { - for_each = toset(var.registered_app_repos) +resource "aws_iam_role_policy" "ci_team_deny" { + for_each = toset(var.registered_teams) name = "deny-platform-operations" - role = aws_iam_role.ci_app[each.key].id + role = aws_iam_role.ci_team[each.key].id policy = jsonencode({ Version = "2012-10-17" @@ -423,15 +424,15 @@ resource "aws_iam_role_policy" "ci_app_deny" { } ################################################################################ -# 3. javabin-ci-deploy-{repo} — Per-app deploy role (build + push + deploy) +# 3. javabin-ci-deploy-{team} — Per-team deploy role (build + push + deploy) # # Trust: GitHub OIDC pinned to docker-build and ecs-deploy workflows on main. -# Terraform operations use the app role instead. +# Any org repo can assume via our controlled workflows; team resolved at runtime. # Permissions: Scoped to ECR push, ECS update, CloudWatch logs, SSM read. ################################################################################ resource "aws_iam_role" "ci_deploy" { - for_each = toset(var.registered_app_repos) + for_each = toset(var.registered_teams) name = "${var.project}-ci-deploy-${each.key}" permissions_boundary = aws_iam_policy.developer_boundary.arn @@ -450,8 +451,7 @@ resource "aws_iam_role" "ci_deploy" { "token.actions.githubusercontent.com:aud" = "sts.amazonaws.com" } StringLike = { - "token.actions.githubusercontent.com:sub" = "repo:${var.github_org}/${each.key}:*" - # Deployment operations only — Terraform uses the app role + "token.actions.githubusercontent.com:sub" = "repo:${var.github_org}/*:*" "token.actions.githubusercontent.com:job_workflow_ref" = [ "${var.github_org}/platform/.github/workflows/docker-build.yml@refs/heads/main", "${var.github_org}/platform/.github/workflows/ecs-deploy.yml@refs/heads/main", @@ -464,11 +464,12 @@ resource "aws_iam_role" "ci_deploy" { tags = { Name = "${var.project}-ci-deploy-${each.key}" + team = each.key } } resource "aws_iam_role_policy" "ci_deploy_ecr" { - for_each = toset(var.registered_app_repos) + for_each = toset(var.registered_teams) name = "ecr-push" role = aws_iam_role.ci_deploy[each.key].id @@ -477,13 +478,10 @@ resource "aws_iam_role_policy" "ci_deploy_ecr" { Version = "2012-10-17" Statement = [ { - Sid = "EcrAuth" - Effect = "Allow" - Action = [ - "ecr:GetAuthorizationToken", - ] - # GetAuthorizationToken does not support resource-level permissions - Resource = "*" + Sid = "EcrAuth" + Effect = "Allow" + Action = ["ecr:GetAuthorizationToken"] + Resource = "*" # GetAuthorizationToken does not support resource-level permissions }, { Sid = "EcrPush" @@ -496,15 +494,18 @@ resource "aws_iam_role_policy" "ci_deploy_ecr" { "ecr:CompleteLayerUpload", "ecr:GetDownloadUrlForLayer", "ecr:BatchGetImage", + "ecr:CreateRepository", + "ecr:DescribeRepositories", ] - Resource = "arn:aws:ecr:${var.region}:${var.aws_account_id}:repository/${each.key}" + # Team can push to any repo tagged with their team + Resource = "arn:aws:ecr:${var.region}:${var.aws_account_id}:repository/*" } ] }) } resource "aws_iam_role_policy" "ci_deploy_ecs" { - for_each = toset(var.registered_app_repos) + for_each = toset(var.registered_teams) name = "ecs-deploy" role = aws_iam_role.ci_deploy[each.key].id @@ -522,7 +523,7 @@ resource "aws_iam_role_policy" "ci_deploy_ecs" { Resource = "*" Condition = { StringEquals = { - "aws:ResourceTag/project" = var.project + "aws:ResourceTag/team" = each.key } } }, @@ -540,9 +541,7 @@ resource "aws_iam_role_policy" "ci_deploy_ecs" { { Sid = "PassRole" Effect = "Allow" - Action = [ - "iam:PassRole", - ] + Action = ["iam:PassRole"] Resource = [ aws_iam_role.ecs_execution.arn, "arn:aws:iam::${var.aws_account_id}:role/${var.project}-*", @@ -553,45 +552,34 @@ resource "aws_iam_role_policy" "ci_deploy_ecs" { } resource "aws_iam_role_policy" "ci_deploy_logs" { - for_each = toset(var.registered_app_repos) + for_each = toset(var.registered_teams) name = "cloudwatch-logs" role = aws_iam_role.ci_deploy[each.key].id policy = jsonencode({ Version = "2012-10-17" - Statement = [ - { - Effect = "Allow" - Action = [ - "logs:CreateLogGroup", - "logs:CreateLogStream", - "logs:PutLogEvents", - ] - Resource = "arn:aws:logs:${var.region}:${var.aws_account_id}:log-group:/ecs/${var.project}/*" - } - ] + Statement = [{ + Effect = "Allow" + Action = ["logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents"] + Resource = "arn:aws:logs:${var.region}:${var.aws_account_id}:log-group:/ecs/${var.project}/*" + }] }) } resource "aws_iam_role_policy" "ci_deploy_ssm" { - for_each = toset(var.registered_app_repos) + for_each = toset(var.registered_teams) name = "ssm-read-overrides" role = aws_iam_role.ci_deploy[each.key].id policy = jsonencode({ Version = "2012-10-17" - Statement = [ - { - Effect = "Allow" - Action = [ - "ssm:GetParameter", - "ssm:GetParameters", - ] - Resource = "arn:aws:ssm:${var.region}:${var.aws_account_id}:parameter/${var.project}/platform-overrides/*" - } - ] + Statement = [{ + Effect = "Allow" + Action = ["ssm:GetParameter", "ssm:GetParameters"] + Resource = "arn:aws:ssm:${var.region}:${var.aws_account_id}:parameter/${var.project}/platform-overrides/*" + }] }) } diff --git a/terraform/platform/iam/outputs.tf b/terraform/platform/iam/outputs.tf index 1109988..ff6098e 100644 --- a/terraform/platform/iam/outputs.tf +++ b/terraform/platform/iam/outputs.tf @@ -8,14 +8,14 @@ output "ci_infra_role_arn" { value = aws_iam_role.ci_infra.arn } -output "ci_app_role_arns" { - description = "Map of repo name to CI app role ARN" - value = { for repo, role in aws_iam_role.ci_app : repo => role.arn } +output "ci_team_role_arns" { + description = "Map of team slug to CI team role ARN" + value = { for team, role in aws_iam_role.ci_team : team => role.arn } } output "ci_deploy_role_arns" { - description = "Map of repo name to CI deploy role ARN" - value = { for repo, role in aws_iam_role.ci_deploy : repo => role.arn } + description = "Map of team slug to CI deploy role ARN" + value = { for team, role in aws_iam_role.ci_deploy : team => role.arn } } output "ci_override_approver_role_arn" { diff --git a/terraform/platform/iam/variables.tf b/terraform/platform/iam/variables.tf index 3972d82..1c6797d 100644 --- a/terraform/platform/iam/variables.tf +++ b/terraform/platform/iam/variables.tf @@ -13,8 +13,8 @@ variable "aws_account_id" { type = string } -variable "registered_app_repos" { - description = "List of GitHub repo names (without org prefix) that get CI app + deploy roles" +variable "registered_teams" { + description = "List of GitHub team slugs that get CI team + deploy roles" type = list(string) default = [] } diff --git a/terraform/platform/main.tf b/terraform/platform/main.tf index 79198d5..231b360 100644 --- a/terraform/platform/main.tf +++ b/terraform/platform/main.tf @@ -29,13 +29,13 @@ module "ingress" { } module "iam" { - source = "./iam" - project = var.project - region = var.region - aws_account_id = var.aws_account_id - registered_app_repos = var.registered_app_repos - github_org = var.github_org - apply_gate_role_arn = module.lambdas.apply_gate_role_arn + source = "./iam" + project = var.project + region = var.region + aws_account_id = var.aws_account_id + registered_teams = var.registered_teams + github_org = var.github_org + apply_gate_role_arn = module.lambdas.apply_gate_role_arn } module "compute" { diff --git a/terraform/platform/registered-apps.auto.tfvars b/terraform/platform/registered-apps.auto.tfvars deleted file mode 100644 index 6f4279f..0000000 --- a/terraform/platform/registered-apps.auto.tfvars +++ /dev/null @@ -1,6 +0,0 @@ -# GENERATED by provision-app workflow — do not edit manually. -# Source of truth: javaBin/registry/apps/ - -registered_app_repos = [ - "platform-test-app", -] diff --git a/terraform/platform/registered-teams.auto.tfvars b/terraform/platform/registered-teams.auto.tfvars new file mode 100644 index 0000000..875054a --- /dev/null +++ b/terraform/platform/registered-teams.auto.tfvars @@ -0,0 +1,6 @@ +# GENERATED by sync-registered-teams.py — do not edit manually +# Source of truth: GitHub teams in javaBin org + +registered_teams = [ + "platform-test-team", +] diff --git a/terraform/platform/variables.tf b/terraform/platform/variables.tf index dc04dd2..dcf99c3 100644 --- a/terraform/platform/variables.tf +++ b/terraform/platform/variables.tf @@ -28,10 +28,10 @@ variable "domain" { default = "javazone.no" } -variable "registered_app_repos" { - description = "GitHub repo names (under javaBin/) registered for CI/CD access" +variable "registered_teams" { + description = "GitHub team slugs that get CI team + deploy roles (synced from GitHub teams API)" type = list(string) - default = ["platform-test-app"] + default = [] } variable "github_org" { @@ -76,7 +76,7 @@ variable "auto_tagger_identities" { type = list(string) default = [ "javabin-ci-infra", - "javabin-ci-app-", + "javabin-ci-team-", "javabin-ci-deploy-", "javabin-", "alexander.amiri"