GCP の Workload Identity サービスについてのまとめ

認証系の初心者でサービス理解するための記事です。

### 課題概要

GithubのActions機能を使用して、mainブランチのマージされたコンテンツを自動的にGCPのバケットにアップロードし、コードデプロイを自動化したいと考えています。SAの認証情報を直接使用せずに、GCPリソースに安全にアクセスできるようにするため、このサービスを使用しています。しかし、不十分な理解に悩まされており、色々調べました。すべてを完全に理解しているとは思いませんが、どうぞよろしくお願いします。

### サービス概要

外部のアプリケーションが、GCP環境にアクセスするために、一般的にはサービスアカウント（SA）が必要です。 SAのキーを使用して、GCPのリソースにアクセスします。ただし、このキーの安全性を保証することはできません。外部のアプリケーションで使用されており、有効期限も切れていませんし、ローテーションしているかどうかもわからないです。このWorkloadIdentityサービスは、この問題の解決策を提供します。

説明するにはまず、次のようなものがあるとします：

- 外部アプリケーションにはIdPがあり、実行する必要があるワークロードもあります。
- クラウド内部にはSAと、SAを介して操作を実行する必要があるリソースがあります。これらをどのように関連付けますか。

WorkloadIdentity設定前のフローは以下の一般的なフローです：

- 認証：ワークロードはまず、自分のアプリケーションのアイデンティティプロバイダ（IdP）から認証を行います。これは、ワークロードがIdPに認証リクエストを送信し、ユーザーの資格情報（ユーザー名やパスワードなど）を提供することを意味しています。 IdPはユーザーの資格情報を検証し、ユーザーのアイデンティティ情報が含まれた認証トークン（IDトークン）またはアカウント資格情報を返します。
- 承認：次に、ワークロードはIdPから取得した認証資格情報（クレデンシャル）を使用して、Google Cloud Platform（GCP）のセキュリティトークンサービス（STS）に短期アクセストークン（Access Token）を要求します。このアクセストークンにより、ワークロードは特定のサービスアカウント（SA）をなりすましてリソースにアクセスできます。

そして、WorkloadIdentity設定後のフローは次のようになります。credentialsを使用して、STSにtokenを要求すると、STSはworkload identity poolでリクエスターのIDを検証します。検証ができたら、SAを成りすまして操作できます。

はい、STSで発行されたアクセストークンを使用してサービスアカウントを操作することもできますね、なぜこんなことをするのでしょうか？

Workload Identityの主な目的は、外部のアイデンティティとサービスアカウントを関連付けるより安全で管理しやすい方法を提供することです。直接STSで発行されたアクセストークンを使用する場合と比較して、Workload Identityを使用することの**利点と違い**は：

- セキュリティ：Workload Identityはより安全な認証メカニズムを提供します。外部のIdPとの統合により、ワークロードはOpenID Connect（OIDC）などの既存の認証メカニズムを利用して認証を行うことができます。これにより、キーまたは資格情報をコードにハードコードする必要がなくなり、キー管理のリスクが低減します。
- 管理上の便利性：Workload Identityを使用すると、サービスアカウントのアクセス権限をより効果的に管理できます。適切なWorkload Identity PoolとProviderをワークロードに設定することで、どのワークロードがどのサービスアカウントを代表して操作を実行できるか、およびどの操作を実行できるかを正確に制御できます。
- 監査追跡：Workload Identityは、より良い監査追跡機能を提供できます。外部のアイデンティティとサービス アカウントを関連付けることで、誰がいつどの操作を実行したかをより簡単に追跡および記録できるため、監査の追跡性と透明性が向上します。


### 設定に関して

詳しくは説明しない、公式参考してください。ここでは調べるとき公式動画で載ったコマンドライン方式のコマンドを載せます。

設定フロー：

- GCPプロジェクトでワークロードアイデンティティプールを作成します。idなどは自分で設定したものです。
```bash
gcloud iam workload-identity-pools create pool-id \
    --location='yourlocation' \
    --description='description' \
    --display-name='display-name'
```
この設定を行うには、SA、IAM、およびworkload-identityにアクセス権限が必要です。

- Workloadidentityは、多くのプールを設定し、それぞれの外部IDに対して承認および設定を行うことができます。workloadidentityでは、外部IDプロバイダに関するさまざまな内部情報を設定できます。属性を使用して設定します。
```bash
gcloud iam workload-identity-pools providers create-oidc provider-id \
    --workload-identity-pool='pool-id' \
    --issuer-uri='issuer-uri' \
    --location='yourlocation' \
    --attribute-mapping='google.subject=assertion.sub'
```

- SAに使用権限を設定する必要があります。これはコマンドラインでもGUIでも実行できます。実行する場合は、SAのページに移動し、権限をクリックして、SAに対する権限を追加します。ユーザーのiamプリンシパルはworkloadidentity画面で確認できます。

このiamプリンシパルは以下のmemberの後ろのものです。それぞれの設定で違うのでご確認の上設定ください。

```bash
gcloud iam service-accounts add-iam-policy-binding service-account-email \
    --role roles/iam.workloadIdentityUser \
    --member 'principal://iam.googleapis.com/projects/project-number/locations \
                /global/workloadIdentityPools/pool-id/subject/subject'
```

- SAに対応する作業アクセス許可を設定する必要があります。たとえば、特定のGCSバケットにファイルのアップロード操作を実行する必要がある場合は、SAに対応するIAMロール権限を設定する必要があります。

設定はGUI画面を使用しても設定できます。

設定時の要点ピックアップ：

- 各OIDCプロバイダには、GitHubなどのサービス属性を設定できます。属性マッピングを次のように設定できます：（2行目参照、workloadのリポジトリでの作業を定義しています）
```
google.subject = assertion.sub 
attritube.repository = assertion.repository
```
- CEL式で属性条件を使用して、特定の条件下でのみ認証が行われるように設定します。たとえば、次のようにして、myrepoで発生した作業フローのみが許可されるように設定できます。

```
assertion.repository == 'xxx/myrepo'
```
### 追加概念説明

**OIDC**

OIDC（OpenID Connect）は、OAuth 2.0プロトコルの上に構築された認証プロトコルであり、認証（Authentication）およびユーザー情報（UserInfo）取得の機能を提供します。OIDCは、クライアントと認証サーバーの間に信頼関係を確立することで、ユーザーの身元認証を実現します。

上記の認証フローで、OIDCの役割は認証段階で表れます。ここでは、ワークロードがアイデンティティプロバイダとやり取りして、ユーザーの身元を検証し、ユーザーに関連する資格情報を取得します。OIDCは標準化された認証フローを提供し、ワークロードが自分のアプリケーションから安全にユーザーを認証し、GCPのセキュリティトークンサービスなど、他のIdPと統合できるようにします。OIDCを使用することで、ワークロードは認証が成功した後、リソースにアクセスするために必要なアクセストークンを取得できます。

**IdP**

IdPは、Identity Providerの略であり、ユーザーの身元を検証し、IDトークンなどの身元証明書を発行するサービスを指します。認証プロセスでは、ユーザーが認証情報（ユーザー名やパスワード、多要素認証情報など）を提供し、IdPがこれらの認証情報の有効性を検証し、ユーザーの身元が信頼できるかどうかを判断します。認証が成功すると、IdPはユーザーに

身元証明書を発行し、他のサービスが使用できるようにします。

IdPは、さまざまな形式の認証サービスで構成されており、組織内のユーザーやパートナー、顧客の身元を検証するために使用されます。

**STS**

STSは、Security Token Serviceの略であり、一時的なセキュリティ証明書を発行するサービスです。認証と承認プロセスで、STSはクライアントに一時的なアクセストークンなどのセキュリティ証明書を発行し、クライアントが保護されたリソースに安全にアクセスできるようにします。

STSの主な機能には次のものがあります：
- 一時的な証明書の発行：STSは一時的なセキュリティ証明書、例えば一時的なアクセストークンや身元証明書などを発行することができます。これらの一時的な証明書は一定期間有効であり、その期間中に特定のリソースにアクセスできます。
- ロールアサンプション：STSはロールアサンプションメカニズムをサポートし、クライアントが特定の役割（例：SAを借りての操作）を演じて、その役割が持つ権限を取得できるようにします。
- アクセス制御：STSはアクセスポリシーと権限ルールに基づいて、一時的な証明書の発行と使用を制御し、保護されたリソースへの安全なアクセスを確保します。

STSは、認証プロバイダーとリソースプロバイダーの間の中間層として機能し、認証およびアクセス制御プロセスを調整します。

**CEL**

CEL（Common Expression Language）は、異なるシステム間で論理式を共有するための標準化された言語です。さまざまな計算ロジック、フィルタリング、変換、計算などを記述するために使用できます。 CELはGoogleによって開発され、Google Cloud IAM（Identity and Access Management）など、さまざまな製品で安全な式評価を実行するために使用されます。

Google Cloudでは、CELは主にポリシーと条件式を記述するために使用され、リソースへのアクセス制御、監査、および変換を行います。柔軟な論理条件を定義し、特定の規則や要件に基づいてリソースを管理および操作することができます。 CELは基本的な数学演算、論理演算、文字列操作、リストやマップの処理など、豊富な構文と機能をサポートしています。

### まとめ

その他の詳細な設定は、公式ドキュメントや各IdPプロバイダーの説明を参照してください。問題解決の方法はさまざまですが、詳細なプロセスを知っていても全体の原理を理解していないと、毎回理解するのが難しいことになるのです。なので本記事でまとめました。

認証に関する私の理解はまだ断片的ですが、色々断片的な理解を組み立てることも重要です。この領域、認証、セキュリティーなどを体系的な学習も必要ですが、少しずつでいきます。