TerraformでGitHubを管理する
はじめまして、InfraSec Dept.の key こと佐藤です。
InfraSec Dept.はクロステック・マネジメントが提供するサービスを中心に、インフラ構築や自動処理、情報セキュリティを確保するための業務を担当しています。
今回はTerraformからGitHubを管理する方法を簡単にまとめます。
導入の背景
組織で情報セキュリティをたもつ場合に気を付けることの1つとして、さまざまな機能やサービスの設定が適切に行われていることが挙げられます。Terraformはクラウドインフラをべき等性を維持した状態で操作するためのツールですが、プロバイダを追加することでGitHubやSendGridなどのSaaSを操作することができます。
クロステック・マネジメントでは、GitHubのレポジトリ管理やメンバーの追加・削除といったオペレーションを、履歴を維持した状態で明確な定義をもって行うことを目的として、Terraformで管理するようにしています。
手順
GitHubの準備
TerraformからGitHubを扱うには認証が必要です。認証方法はPAT=Personal Access TokenとGitHub Appの導入による方法を選ぶことが出来ます。
PATは文字通り個人に属するトークンのため、担当者が組織から削除されると使用できなくなる問題があるため、GitHub Appを導入して進めることにしました。
GitHub Appの作成方法はインターネットに存在する数多のエントリに任せるとして…要点を下記します。
- GitHub Appには必要最低限の権限をもたせる
- アプリID、インストールID、秘密鍵の3つの情報を取得、適切に管理する
権限の一部を抜粋すると次のようになっています。
- メンバー管理(とても強い権限なので、クレデンシャルの漏洩に注意!)
- GitHub Organization全体で使う秘密情報を扱えるように。共通化しておくと楽ですからね

Terraformの下準備
プロバイダの定義は次のように記述します。 integrations/github を使うこと、プロバイダの初期化時に app_auth を使ってGitHub Appの情報を渡す点がポイントです。
terraform {
required_version = "~> 1.13.3"
required_providers {
github = {
source = "integrations/github"
version = "~> 6.6"
}
}
# 省略
}
provider "github" {
owner = "example-organization"
app_auth {
id = var.app_id
installation_id = var.app_installation_id
pem_file = var.app_pem_file
}
}
app_auth に渡すパラメタは変数で定義しておくといいでしょう。
variable "app_id" {
type = string
description = "The GitHub App ID."
default = ""
}
variable "app_installation_id" {
type = string
description = "The GitHub App Installation ID."
default = ""
}
variable "app_pem_file" {
type = string
description = "PEM string of the GitHub App."
default = ""
sensitive = true
ephemeral = true
}
リソース定義
メンバー定義
メンバー定義を行うには github_membership リソースを使います。このリソースをapplyすると、指定したGitHubユーザアカウントが招待されます。ユーザが承認するとOrganizationに追加されるというわけですね。
resource "github_membership" "key" {
username = "key"
role = "admin"
}
GitHub Actions Environment Secrets定義
以下はAWSやGCPのクラウドリソースを定義し、その値をGitHub Actions Environment Secretsに登録するサンプルです。
resource "github_actions_environment_secret" "workload_identity_pool_id" {
repository = "repo_name"
environment = "dev"
secret_name = "WORKLOAD_IDENTITY_POOL_ID"
plaintext_value = data.tfe_outputs.example_project.values.iam_workload_identity_pool_id
}
resource "github_actions_environment_secret" "workload_identity_pool_provider_id" {
repository = "repo_name"
environment = "dev"
secret_name = "WORKLOAD_IDENTITY_POOL_PROVIDER_ID"
plaintext_value = data.tfe_outputs.example_project.values.iam_workload_identity_pool_provider_id
}
TerraformでGitHubを管理すると、クラウドリソースをプロビジョニングした値を、GitHub Actionsなどでシームレスに利用できる点は大きなメリットだと思います。
業務上の適用範囲
Terraform GitHubプロバイダで定義可能なリソースおよびGitHub Appの権限がある範囲であれば、どんなことでも設定することが出来ます。一方で、GitHub Appの権限は最小化しておく必要があり、2025年10月現在では次のリソースを管理するために使用しています。
- メンバー、チーム管理
- レポジトリの作成、初期化
- 業務で共通で使用するGitHub Actions Workflowファイルの追加
- GitHub Actions Environment / Secretsの管理
- Issueラベルの設定
組織ごとに「これがベスト」という形は異なるので、業務に対して適用範囲をうまく見極め、上手く扱えるようにするのが良いでしょう。
実装上のポイント
教訓その1 取り扱うリソース数を考慮する
メンバ数やレポジトリ数がある程度あると取り扱うリソース数はリニアに増えます。
例えば、1つのユーザーが3つのチームに所属する場合、1ユーザー増やすごとに4リソースずつ増えるわけですが、メンバーが100名存在すると400リソースになります。
Terraformが実行計画を作る際にGitHubのAPIを呼び出しますが、リソース数が多い=API呼び出し回数が増えることとなり、APIレートリミットにヒットする可能性が上がります。短時間に何度もTerraformを実行した結果、APIレートリミットにヒットし、エラー終了するという問題に当たります(当たりました)。
リソース量を見極めながら、作業ディレクトリとワークスペースを分割して管理することを強く推奨します。
教訓その2 リソースのドキュメントをよく読む
GitHubプロバイダのリソースにはいくつかクセのあるものが存在します。
github_repository リソースは文字通りGitHubのレポジトリを作成することが出来ます。組織によっては main と develop という複数のブランチを取り扱い、後者をデフォルトブランチにしたいケースがあると思うのですが、 github_repository リソースではデフォルトブランチを指定することが出来ません。
厳密に言えば default_branch 属性を指定することで可能なのですが、この属性は Deprecated なため将来的に利用できなくなる可能性があります。レポジトリの初期コミットを行う auto_init を指定すると、 main ブランチが自動作成するなど、ブランチの運用上やや混乱するケースがあるかも知れません。
今は次のように対応しています。
-
mainブランチは使おうと使わずとも、存在するものとして扱う - 追加のブランチは
github_branchリソースを使って作成する - デフォルトブランチは、ブランチが全て作成されたあとに
github_branch_defaultリソースで指定する
導入後の混乱とその後
さて、このような仕組みを導入してどうだったかというと、初期に混乱を生みましたがおおよそ良い結果が得られたように感じています。
初期の段階では、TerraformでGitHubを管理していることが伝わっておらず、Terraformでレポジトリ設定を更新する→レポジトリの管理者が手動で設定を変更する→Terraformの再実行で元に戻される…などの問題がありました。管理手法の周知や勉強会を行うことでこの問題は解決することが出来ました。
Terraformのリソース定義をコピペで作れるように作り込んだ結果、開発チームの方がメンバーの追加や削除、レポジトリの新規作成といった定義を含むPull Requestを作成してくれるようになり、インフラ担当者が確認を行う形で業務効率化できました。インフラ担当者は少なく、障害発生時はワークアラウンドにつきっきりになってしまうため、メンバーが並行で業務を進められるように鳴ったことは大きなメリットと感じています。

おわりに
もし興味を持ってくださったそこのあなた!
クロステック・マネジメントではInfraSec Dept.のインフラエンジニアを募集していますので、ぜひご応募ください。
京都芸術大学のテックブログです。採用情報:hrmos.co/pages/xtm/jobs 芸大など5校を擁する瓜生山学園は、通信教育で国内最大手、国内で唯一notionと戦略パートナー契約を結ぶなどDX領域でも躍進、EdTech領域でAIプロダクトを開発する子会社もあり、実は多くのエンジニアがいます。
Discussion