0
0

GitHub AppsとAWS Secrets Managerを連携してTerraformのGitHub Providerをセキュアにする

Last updated at Posted at 2024-08-31

はじめに

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を自分で作って取得しているが、この方法であれば不要)。

キャプチャ1_1.png

image.png

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に接続することができるようになった!

  1. 方法をご存知の方がいたら是非教えていただきたい。

  2. こちらについても方法をご存知の方がいたら是非教えていただきたい。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0