👍

Terraform だけを使って GitHub Actions OIDC ID プロパイダの thumbprint を計算する方法

2022/01/13に公開約2,700字1件のコメント

GitHub Actions が提供する ID プロパイダのルート証明書が変更されて、OIDC を使った AWS への認証が通らなくなるという現象が起こりました。

https://github.com/aws-actions/configure-aws-credentials/issues/357

ドキュメントや多くのブログでは AWS 側の ID プロパイダに渡す thumbprint として固定値 a031c46782e6e6c662c2c87c76da9aa62ccabd8e が指定されていたので、新しい thumbprint を計算して更新する対応を迫られた方が多いのではないかと思います。

https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_roles_providers_create_oidc_verify-thumbprint.html

計算自体は上記公式ドキュメントに載っている通りに行えば問題ありませんが、せっかくなので Terraform だけを使って自動で thumbprint を取得する方法を紹介します。

なお、Terraform の実行結果は2022年1月13日時点のものです。

Terraform コード

data "http" "github_actions_openid_configuration" {
  url = "https://token.actions.githubusercontent.com/.well-known/openid-configuration"
}

data "tls_certificate" "github_actions" {
  url = jsondecode(data.http.github_actions_openid_configuration.body).jwks_uri
}

resource "aws_iam_openid_connect_provider" "github_actions" {
  url             = "https://token.actions.githubusercontent.com"
  client_id_list  = ["sts.amazonaws.com"]
  thumbprint_list = [data.tls_certificate.github_actions.certificates[0].sha1_fingerprint]
}

ポイントとしては、tls_certificate という data source を使って証明書の取得 → thumbprint の計算まで実現しているところです。

Plan 結果

Terraform will perform the following actions:

  # aws_iam_openid_connect_provider.github_actions will be updated in-place
~ resource "aws_iam_openid_connect_provider" "github_actions" {
        id              = "arn:aws:iam::xxxxxxxxxxxx:oidc-provider/token.actions.githubusercontent.com"
        tags            = {}
      ~ thumbprint_list = [
          - "a031c46782e6e6c662c2c87c76da9aa62ccabd8e",
          + "6938fd4d98bab03faadb97b34396831e3780aea1",
        ]
        # (4 unchanged attributes hidden)
    }

Plan: 0 to add, 1 to change, 0 to destroy.

Terraform 単体では Reconcile Loop が実現できないので thumbprint が自動で更新されることはない(= 何かしらのきっかけで terraform plan が走らないと差分が発覚しない)ですが、差分が出たタイミングで公式情報を確認することができる点はメリットと言えるかもしれません。

余談

公式ドキュメントでは openssl を使って一番下のルート証明書を取得していますが、Terraform だと data.tls_certificate.github_actions.certificates[0] とあるように配列の最初の要素を使っています。
これで確実にルート証明書を参照できると保証されているのか少し気になりましたが、特に問題ないようでした。

  • ドキュメント

    • with the root of the chain first. と書かれている
  • 実装

    • 証明書の配列を逆からループしている
      
        var certs []interface{}
        for i := len(state.PeerCertificates) - 1; i >= 0; i-- {
          certs = append(certs, parsePeerCertificate(state.PeerCertificates[i]))
        }
      
      

Discussion

有力な記事ありがとうございます!公式ドキュメントに書いて欲しい限りです。

一つだけ改善点があるかもしれません。記事にも書いてあるように[0]だともしかして正しい証明書を参照できない可能性があると思います。GitHubの約束はどれかの証明書を使っていることで、全部有効だという約束ではないはずです。事実上ほとんどの場合大丈夫ですけどね。

でもSplat Expressionを使えば簡単に全部の証明証を参照できて、より安心です。

resource "aws_iam_openid_connect_provider" "github-oidc" {
  url = "https://token.actions.githubusercontent.com"
  client_id_list  = [sts.amazonaws.com"]
  thumbprint_list = data.tls_certificate.github_actions.certificates[*].sha1_fingerprint
}
ログインするとコメントできます