Workload Identity 認証を使って Github Actions を実行する

# Workload Identity 認証を使って Github Actions を実行する
## はじめに
社内で Google Cloud リソース作成の自動化に取り組んでおり、Terraform のコードを Github で管理・Github Actions を使って Google Cloud リソースの作成を行っております。
Github Actions や Terraform が Google Cloud に連携する際サービスアカウントのアカウントキーを使っていたのですが、それを Workload Identity に置き換えたので、その設定方法などをまとめます。


## 手順
### Workload Identity 専用のプロジェクトを作成する
Google Cloud のベストプラクティスによると、Workload Identity を専用のプロジェクトで作成・管理することが推奨されています。

https://cloud.google.com/iam/docs/best-practices-for-using-workload-identity-federation?hl=ja#dedicated-project

なので専用プロジェクトを新規で作成しました。後述のサービスアカウントや tfstate ファイルを管理する Cloud Storage バケットとは別プロジェクトです。

### Workload Identity のプールとプロバイダを作成する
公式ドキュメントの「Github Actions」に沿って作成していきます。

https://cloud.google.com/iam/docs/workload-identity-federation?hl=ja

Workload Identity のページの「＋プールを作成」より作成していきます。

![プール作成ボタン.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426544/b6bedc36-31f8-c209-c85a-2776cc4a781e.png)



任意の名前（必要であればプールIDも）を入力して「続行」をクリックします。

![IDプールを作成する.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426544/dae6023b-20d0-d86e-3af5-1aa228115c7c.png)

②でプロバイダを追加します。
公式ドキュメントの通り、使うパイプラインによって設定値が異なりますが、Github Actions の場合は、

 - プロバイダの選択 : OpenID Connect（OIDC）
 - プロバイダ名 : 任意の値
 - 発行元（URL） : `https://token.actions.githubusercontent.com/`
 - JWK ファイル（JSON） : 指定なし
 - オーディエンス : デフォルトのオーディエンス

![プールにプロバイダを追加する.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426544/b91b15f8-4dc4-b97f-6f80-23da2a1b1971.png)


③でプロバイダの属性を記載します。
以下の属性を指定しました。
 - google.subject : assertion.sub
 - attribute.aud : assertion.aud
 - attribute.actor : assertion.actor
 - attribute.repository : assertion.repository

属性条件には `assertion.repository_owner=='<Github　の Organization 名>'` を指定し、この Workload Identity を使うことができる Github Organization を限定しました。

![プロバイダの属性を構成.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426544/9ded7f63-a491-1fc3-9bec-8185c5a7cbd1.png)


Github の OIDCトークン は公式ドキュメントから確認できます。

https://docs.github.com/ja/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect#configuring-the-oidc-trust-with-the-cloud

#### Workload Identity のプールとサービスアカウントを紐づける
上記で作成した Workload Identity のプールと Google Cloud リソース作成を実行するサービスアカウントを紐づけます。
前述の通り、このサービスアカウントは Worklord Identity プールが存在するプロジェクトとは異なるプロジェクトで作成されたものなので、Cloud Shell から設定します。

Worklord Identity プールが存在するプロジェクトから Cloud Shell を開き、以下コマンドを実行します。

```
gcloud iam service-accounts add-iam-policy-binding "<サービスアカウント>" \
  --project="<サービスアカウントのプロジェクトID>" \
  --role="roles/iam.workloadIdentityUser" \
  --member="principalSet://iam.googleapis.com/projects/<Worklord Identity のプロジェクト番号>/locations/global/workloadIdentityPools/<Worklord Identity プールID>/attribute.repository/<Github の Organization名>/<Github のリポジトリ名>"
```

Worklord Identity プールの詳細ページで IAM プリンシパルが記載されていますが、コマンドの `--member=` で指定する値は以下の点が異なります。
 - 文字列の先頭は `principal` ではなく `principalSet`
 - 文字列の最後につける属性は `subject` ではなく `attribute.repository`

#### Workload Identity のプールが Cloud Storage バケットに接続できるようにする
Workload Identity プールが tfstate ファイルを管理する Cloud Storage バケットに書き込みできるようにアクセス権限を追加します。
コンソール画面から Cloud Storage バケットを開き、権限タブから Workload Identity の IAM プリンシパルを追加します。
このときに使う IAM プリンシパルの `Subject` 属性には Github の Organization名、リポジトリ名、ブランチ名を使います。
```
principal://iam.googleapis.com/projects/<Worklord Identity のプロジェクト番号>/locations/global/workloadIdentityPools/<Worklord Identity プールID>/subject/repo:<Github の Organization名>/<Github のリポジトリ名>:ref:refs/heads/<ブランチ名>
```

#### Workload Identity を使うように Terraform コードを修正
設定した Workload Identity 情報を Github Actions のワークフローファイルに追記します。一番最初のジョブに追記する必要があります。

``` ワークフロー.yaml
jobs:
  jobid:
    permissions:
      id-token: write
      contents: read

    steps:
      - uses: actions/checkout@v3

      - uses: 'google-github-actions/auth@v2'
        with:
          workload_identity_provider: 'projects/<Worklord Identity のプロジェクト番号>/locations/global/workloadIdentityPools/<Worklord Identity プールID>/providers/<Worklord Identity プロバイダID>'
          service_account: '<サービスアカウント>'
```

設定は以上です！
今まで使っていたサービスアカウントのアカウントキーファイルやそれを参照しているコードを削除すれば、Workload Identity への置き換え完了です。

## 参考

https://docs.github.com/ja/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect

https://docs.github.com/ja/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-google-cloud-platform

https://github.com/google-github-actions/auth

https://zenn.dev/miyajan/articles/github-actions-support-openid-connect#github-actions-%E3%81%AE-oidc-%E3%83%88%E3%83%BC%E3%82%AF%E3%83%B3%E3%81%AE-sub-%E3%81%AB%E3%81%AF%E3%81%AA%E3%81%AB%E3%81%8C%E5%85%A5%E3%82%8B%E3%81%AE%E3%81%8B%EF%BC%9F

https://zenn.dev/satohjohn/articles/1645be8e83eab6

https://qiita.com/satooshi/items/0c2f5a0e2b64a1d9a4b3

https://qiita.com/atsumjp/items/9e623edab1f7ab08fa6e

https://gomiba.co/archives/2024/04/990e289f-50be-4412-b44a-383434cbf956/