はじめに
TerraformのGitHubプロバイダーには、Personal Access Token(PAT)を利用する方法と、GitHub AppsのJWTを使う方法の2通りがある。
PATにも、Classic版とFine-grained版があり、Classic版ではトークン期限を無制限にできるものの、将来はdeprecatedになる可能性がある。また、Fine-grained版はローテーションを前提にしているようで、無制限の設定はできない。セキュリティを考慮すると、定期的なローテーションをすることが重要であるため、思想としては正しいが、自動でローテートするためのAPIが存在しないように見える1。
ということで、定期的なローテーションが容易にできる仕組みを備えている、GitHub Appsの設定を今回はしていく。また、設定をするにあたり、秘密鍵を保持する必要があるため、ここはAWS Secrets Managerを使ってローカルで管理をしないようにする。
なお、PATを利用したアクセス方法については、以下の記事に記載している。
なお、GitHub AppsのJWTの方式の場合、権限を付与してもリポジトリの作成ができない2ようであるため、該当操作がある場合は、面倒でも手動でローテーションをしよう。
今回の記事では、tfstateに秘密鍵が平文で書かれてしまうため、AWS ProviderのバックエンドをS3にして、暗号化設定をして厳重にパーミッション管理をすることを強く推奨する。
GitHub Appsの設定
GitHub Appsは以下の記事の「GitHub Appsのセットアップ」の章に従って実施をしよう。
なお、権限は以下のように設定する。
区分 | 権限名 | 権限 | 必要な処理 |
---|---|---|---|
Repository permissions | Administration | Read and write | リポジトリの変更(作成はできないが変更は可能) |
Repository permissions | Metadata | Read-only | デフォルトで付与(外せない) |
AWS Secrets Managerの設定
上記で作成した秘密鍵は、他のHCLのファイルと同じパスにsecretkey.pemという名前で配置することを前提にしている。プレーンテキストでは、秘密鍵中の改行が消えてしまうため、バイナリで保持をする。バイナリ保持時はBase64エンコードが必要なので、組み込みの関数でエンコードしておこう。
それ以外特筆することは特にないが、秘密鍵に誰でもアクセスできるのは良くないため、必要に応じてaws_secretsmanager_secret_policy
を使ってアクセス制限をしておこう。
resource "aws_secretsmanager_secret" "example" {
name = local.secrets_manager_secrets_name
}
resource "aws_secretsmanager_secret_version" "example" {
secret_id = aws_secretsmanager_secret.example.id
secret_binary = base64encode(file("./secretkey.pem"))
}
resource "aws_secretsmanager_secret_policy" "example" {
secret_arn = aws_secretsmanager_secret.example.arn
policy = data.aws_iam_policy_document.example.json
}
data "aws_iam_policy_document" "example" {
statement {
effect = "Allow"
principals {
type = "AWS"
identifiers = [
data.aws_iam_role.example.arn
]
}
actions = [
"secretsmanager:GetSecretValue",
"secretsmanager:PutSecretValue",
]
resources = [
aws_secretsmanager_secret.example.arn,
]
}
}
GitHub Providerの設定
さて、AWS Secrets Managerへの設定が終わったら、次は利用するためのProviderの設定を行う。
リポジトリを分けている場合は以下のようにデータソースで秘密鍵を読み出せるようにしておく。
data "aws_secretsmanager_secret" "example" {
name = local.secrets_manager_secrets_name
}
data "aws_secretsmanager_secret_version" "example" {
secret_id = data.aws_secretsmanager_secret.example.id
}
あとは、公式のドキュメントに従い、設定を行う。
id
はGitHub Appsの作成後に表示されるが、installation_id
は分かりにくく、以下の画面遷移を辿った後のURLバーに表示される(上記の参考記事ではJWTを自分で作って取得しているが、この方法であれば不要)。
terraform {
required_providers {
github = {
source = "integrations/github"
}
}
}
provider "github" {
owner = local.github_owner
app_auth {
id = local.github_app_id
installation_id = local.github_app_installation_id
pem_file = data.aws_secretsmanager_secret_version.example.secret_binary
}
}
GitHubのリポジトリを管理したい場合
上述した通り、リポジトリの新規作成はGitHub Appsからはできないと思われる。
ただし、更新はできるため、リポジトリのガワだけ作り、Terraformのインポート機能を使えば取り込んですぐに属性を変更することは可能だ。
import {
id = "example"
to = github_repository.example
}
resource "github_repository" "example" {
name = "example"
description = "GitHubをGitHub Appsのトークンで設定するサンプル"
visibility = "private"
}
これで、より安全にGitHubに接続することができるようになった!