🐢

GitHub ユーザ管理を Terraform で IaC 化して Base Permission=none に備える

に公開

こんにちは、secondz digital の SRE 兼情シス kame3t です。

背景

GitHub Organization を安全に運用するには least‑privilege(最小権限)が欠かせません。最終目標は Base Permissionnone に設定し、すべてのリポジトリ権限を コードで明示的に付与 できる状態にすることです。

まずは ユーザとチーム、外部コラボレーター の管理を Terraform で IaC 化し、段階的に Base Permission を none へ移行する土台を整えます(現時点の既定値は記事では公開しません)。

この記事のスコープ

  • ユーザ/チーム をコード化し、外部委託メンバー (Outside Collaborator) を プロジェクト単位で複数リポジトリへ付与 するパターンを紹介します。
  • 組織内メンバーのリポジトリ権限(github_team_repository など)は必要になった際に扱う予定です。

アーキテクチャの要点

要素 現状 目的
Base Permission 組織デフォルト値 (非公開) 段階的に none へ移行するための一次措置
管理対象 ユーザ / チーム / Outside Collaborator 変更履歴と監査証跡を確保し、GUI 操作を排除
Provider 構成 モジュール不使用・直書き 構成をシンプルに保つため
台帳形式 locals (HCL) 外部 YAML を増やさず HCL だけで完結
運用 GitHub Actions で planapply PR レビューで差分確認&自動反映

ディレクトリ構成

.
├── provider.tf          # backend & provider
├── user_list.tf         # 社員メンバー台帳
├── membership.tf        # github_membership
├── teams.tf             # チーム定義 & 所属付与
├── collaborator.tf      # Outside Collaborator 台帳 (projects 属性で束ねる)
├── prj_<project>.tf     # プロジェクトごとのリポジトリ × Collaborator
└── versions.tf          # required_version 等

provider.tf (抜粋)

terraform {
  required_version = ">= 1.10.0"

  # backend は S3 / Azure Storage などに合わせて設定

  required_providers {
    github = {
      source  = "integrations/github"
      version = "~> 6.6.0"
    }
  }
}

provider "github" {
  token = var.github_oauth_token
  owner = var.github_owner
}

1. ユーザ台帳 (user_list.tf)

locals {
  github_members = {
    "first_name.family_name" = {
      username = "dummy"   # GitHub username
      role     = "member"   # admin / member
      teams    = ["fulltime"]
    }
  }
}

resource "github_membership" "org_member" {
  for_each = local.github_members
  username = each.value.username
  role     = each.value.role
}

2. チーム定義 (teams.tf)

resource "github_team" "fulltime" {
  name    = "fulltime"
  privacy = "closed"
}

resource "github_team_membership" "fulltime_members" {
  for_each = {
    for id, v in local.github_members : id => v if contains(v.teams, "fulltime")
  }
  team_id  = github_team.fulltime.id
  username = each.value.username
}

3. Outside Collaborator 台帳 (collaborator.tf)

projects 配列に 論理プロジェクト名 を列挙し、複数リポジトリ へ権限を付与する設計です。

locals {
  outside_collaborator = {
    # key は社内 ID / 契約 ID など一意な値
    "first_name.family_name" = {
      username   = "dummy-ext-a" # GitHub username
      permission = "push"           # pull / triage / push / maintain / admin
      projects   = ["ai-native"]   # 関与するプロジェクト
    }
    "first_name.family_name" = {
      username   = "dummy-ext-b"
      permission = "read"
      projects   = ["search", "ai-sales"]
    }
  }
}

4. プロジェクトごとの Collaborator 付与 (prj_<project>.tf)

例: AI Native プロジェクトで 1 リポジトリだけ付与する場合

# prj_ai_native.tf
resource "github_repository_collaborator" "ai_native_pmo" {
  for_each = {
    for id, v in local.outside_collaborator : id => v
    if contains(v.projects, "ai-native")
  }
  repository = "ai-native-pmo"
  username   = each.value.username
  permission = each.value.permission
}

例: Search プロジェクトで複数リポジトリに同一 Collaborator を付与する場合

# prj_search.tf
locals {
  search_repos = [
    "doc-search",
    "doc-search-app",
    "list-search-dev",
  ]
}

resource "github_repository_collaborator" "search_collab" {
  for_each = {
    for repo in local.search_repos : repo => repo
  }

  repository = each.value
  username   = local.outside_collaborator["ext_b"].username
  permission = local.outside_collaborator["ext_b"].permission
}

ポイント

  • Collaborator 台帳 は一元管理、リポジトリ側は プロジェクト単位で疎結合 に記述
  • projects キーに論理名を付けることで オンボーディングも 1 行追加で完了

5. CI/CD フロー

  1. PR 作成で plan 差分をレビュー
  2. Merge すると apply が自動実行し、ユーザ/チーム/Collaborator が即時更新

今後のロードマップ

  1. 全リポジトリの権限を HCL 化 (github_team_repository 等)
  2. Plan で差分ゼロを確認後、Base Permission を none
  3. SAML/SCIM 連携でアイデンティティ管理を自動化

まとめ

  • Users / Teams / Outside Collaborator を IaC 化し、Base Permission none 移行を見据えた運用土台を整備

  • projects 配列 による “プロジェクト → 複数リポジトリ” 付与でスケールしやすい

  • 更新時に触るファイルは最小限

    • 正社員(fulltime) の入退社・異動: user_list.tf だけを編集
    • 外部委託 (Outside Collaborator) のオン/オフボーディング: collaborator.tf と該当プロジェクトの prj_*.tf を編集
  • PR + CI で差分を可視化し、監査性と安全性を両立

ご意見・ツッコミはコメントでお待ちしています 🙌

Discussion