CircleCIとAWSをOpenID Connect 認証で連携する

## はじめに

CircleCI カスタマーサクセスをしている鈴木です。 CircleCI が2022年3月下旬から OpenID Connect (OIDC) をサポートすることになりました。公式ドキュメントは[こちら](https://circleci.com/docs/ja/2.0/openid-connect-tokens/ "ジョブでの OpenID Connect トークンの使用")です。
また、CircleCIのエンジニアである水上さんが[リリースの数ヶ月前に書いた記事](https://qiita.com/makotom/items/56ed4ccf15a6f4d0b257 "CircleCI の OpenID Connect サポート")がありますので、そちらをお読みいただくと概要をつかめるのではと思います。

本記事では、 AWS の S3 バケットに index.html をアップロードするシナリオで利用方法を説明したいと思います。

## CircleCI が OIDC をサポートしたことで実現できること

CircleCI が OIDC をサポートしたことで何が嬉しいかというのは前述の水上さんの記事から引用します。

> "OIDC のおかげでパスワードがなくなって安全になったハッピー!" と考えるのはすこし短絡的です.
> *(中略)*
> むしろ, OIDC のサポートにより実現されるのは, 従来必要だったユーザーのみなさまご自身によるパスワード保管やキー ローテーションといったやっかいな作業の省略です.

ということで、これまで AWS や GCP などにデプロイを行い場合、ログインのクレデンシャルを CircleCI の Context に登録しておいて、定期的に、あるいはチームから離れるメンバーが出た際にそのクレデンシャルを更新するという作業を行っているケースなどで、OIDC認証での連携に変更すると便利になるかと思います。

## 簡単なデモ

それでは、CircleCI と AWS を OpenID Connect 認証で連携し S3 にデプロイして見たいと思います。

大まかな流れは以下です。
1. CircleCIで Context を設定する
2. AWS で ID プロバイダを設定し、IAMロールを割り当てる
3. CircleCIで config.yml や環境変数を設定する

### 1. CircleCIで Context を設定する

まず、Context を作成します。CircleCI の左メニューの "Organization Settings" をクリックすると Context の設定画面になります。 CircleCI の Context は、Organizartion内の複数のプロジェクト（リポジトリ）で共通して利用する環境変数を登録する機能です。
Context が存在すると、Organization ID というものが表示されます。後ほど使用します。
なお、 OIDC 連携だけなら Context に環境変数を設定していなくても問題ありません。

![context_org_id.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11243/f0050275-a34c-7d37-ba5b-2e17e56ad948.png)
 
今回のサンプルでは oidc-aws という名前の Context を作成しています。 

### 2. AWS で ID プロバイダを設定し、IAMロールを割り当てる

AWS の IAM > ID プロバイダ で、 ID プロバイダを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11243/f504c1c7-5d2b-5ef5-2bd9-1c5faf3ca54d.png)
上記の画面の設定項目は以下のように進めます。ここでさきほどの Organization ID を入力します。
- プロバイダのタイプ : Open ID Connect を選択
- プロバイダの URL : https://oidc.circleci.com/org/< Organization ID >
- 対象者 : < Organization ID > 

入力後、「サムプリントを取得」ボタンをクリックし、「プロバイダを追加」します。

追加を行うと、ID プロバイダのリストに切り替わります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11243/dfef8e1f-1024-a622-546a-a58af1053053.png)

ここで、ID プロバイダの URL 部分をクリックして IAM ロールの割り当てを行います。
対象者で表示されている < Organization ID > を選択肢、「アクション」というプルダウンメニューを開くと、ロールの割り当てができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11243/fb18578a-edfa-438e-d2be-3f2278ed7bef.png)

下図は新たにロールの作成を行う画面です。ID プロバイダ と Audience (対象者)を選択し、アクセス権限を付与します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11243/c418e2ff-68aa-549b-4d33-e775f7ffe907.png)

途中、ロールにポリシーをアタッチしています。今回のサンプルでは AmazonS3FullAccess をアタッチします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11243/650c3704-94a9-6b5b-484f-227b382eaa13.png)

ロールの作成の最後はロール名の指定です。サンプルでは circleci-oidc という名前にしています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11243/397d5471-d8c9-de2e-956b-a65452eb7caf.png)

作成したロールの ARN を確認します。サンプルプロジェクトではこの ARN を config.yml に直接書いてしまっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11243/bfebced3-c5a1-2807-eebc-66360a1d1658.png)

今回のサンプルでは AWS の S3 バケットに index.html をアップロードするのですが、S3 バケットの設定については割愛します。サンプルでは circleci-oidc-test という名前のバケットをデプロイ先にしています。

### 3. CircleCIの config.yml や環境変数を編集する

今回のサンプルプロジェクトのリポジトリはこちらです。
https://github.com/suzucir/sample-app-oidc-test

CircleCI でこのプロジェクトをフォローして、push を行います。設定に問題がなければ
以下のようにビルドが成功します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11243/8cd88873-a984-65df-4bb7-05657ea99865.png)

ちなみに、↑上図の "Preparing environment variables" の中身を見ると、CIRCLE_OIDC_TOKEN という環境変数が用意されているのがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11243/0502699e-0ea3-46f3-7502-ad412fa680f8.png)

## おわりに

というわけで OpenID Connect 認証で CircleCI と AWS の連携を行ってみましたが、すでに CircleCI ユーザーのみなさんが、より実践的な、よりセキュリティを意識した利用をブログ記事にまとめてくださっています。ぜひぜひそちらもご参考ください。