GitHub ActionsでOIDC認証してECRにDockerイメージをプッシュする

## 1. はじめに
本記事は以下の学習の続きです。

https://qiita.com/YasuhaF/items/8898b5fece72e78d099d

## ECRにリポジトリを作成

https://ap-northeast-1.console.aws.amazon.com/ecr/private-registry/repositories?region=ap-northeast-1

右上の`リポジトリを作成`をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494944/a8009d8a-e4b5-44b1-5c0b-467e05fd67a0.png)

次にリポジトリ名を入力し他の項目はそのままにしてそのまま`作成`をクリックします。
今回は練習ということで`イメージタグのイミュータビリティ`を`Mutable`を指定します。

[Amazon ECR でのイメージタグの上書きの防止](https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/image-tag-mutability.html)

![スクリーンショット 2024-11-24 13.50.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494944/5eb71edf-7bcc-dad4-8457-531670921bed.png)

これでリポジトリの作成は完了です。

### 作成リポジトリのイメージを確認
作成したリポジトリをクリックしてイメージを確認します。


![スクリーンショット 2024-11-24 13.59.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494944/6bf24ff8-6c9d-a3e9-a52c-9d9b367a591f.png)

当然ですがまだプッシュしてないのでイメージはひとつもありません。

![スクリーンショット 2024-11-24 14.06.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494944/799f26f7-5ccc-f087-d5aa-7984c6a285ca.png)

## IDプロバイダーを作成

今回AWSの認証は`OIDC認証`を利用するので、AWS IAMからIDプロバイダーを作成します。

https://docs.github.com/ja/actions/security-for-github-actions/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services

AWS IAM > IDプロバイダ で`プロバイダを追加`をクリックします。

![スクリーンショット 2024-11-24 14.54.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494944/6cac72e2-b16a-3d4e-9e8f-128c6d4d3e91.png)

[AWS への ID プロバイダーの追加](https://docs.github.com/ja/actions/security-for-github-actions/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services#adding-the-identity-provider-to-aws)
を参考に以下の値を入力して作成します。
```
プロバイダのタイプ: OpenID Connect
プロバイダのURL: https://token.actions.githubusercontent.com
対象者: sts.amazonaws.com
```

![スクリーンショット 2024-11-24 15.00.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494944/41be7a6f-7699-3fd5-2f68-e4d2249470e3.png)

## ロール作成
こちらを参考にしてロールを作成します。

https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_roles_create_for-idp_oidc.html#idp_oidc_Create


画面右上の`ロールを作成`をクリックします。

![スクリーンショット 2024-11-25 22.21.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494944/fd0bf26b-abc4-e985-7903-7b2edc754440.png)

> GitHub Actions のロールを作成する場合は、〜(略)

上記の部分を参考に`信頼されたエンティティを選択`ページで選択、入力して、`次へ`をクリックします。

```
信頼されたエンティティタイプ: ウェブアイデンティティ
アイデンティティプロバイダー: https://token.actions.githubusercontent.com
Audience: sts.amazonaws.com
GitHub 組織: Organization Name *1
GitHub repository: GitHubのリポジトリ名 *2
Github branch: GitHubのブランチ名 *3

*1 Organizationがなければ自身のGitHubアカウント名でも良いようです。
*2 Organization内の任意のリポジトリにのみアクセスを許可したい場合は指定します
*3 Organization内の任意のリポジトリ内にある任意のブランチにのみアクセスを許可したい場合は指定します。
```

![スクリーンショット 2024-11-25 22.26.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494944/01bc88c4-e963-2b57-cffa-a697c7fac02c.png)

許可を追加(許可ポリシー選択)ステップはスキップして`次へ`をクリックします。


最後にロール名を入力して`ロールを作成`...する前に`信頼ポリシー`のJSONを確認してみます。

![スクリーンショット 2024-11-25 23.03.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494944/0751fd93-086c-c84c-e086-e8c89a7a408b.png)

`信頼されたエンティティを選択する`で入力した項目がきちんと反映されているか確認します。こちらに沿った内容で反映されていることがわかると思います。

https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_roles_create_for-idp_oidc.html#idp_oidc_Create_GitHub

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Principal": {
                "Federated": "arn:aws:iam::XXXXX:oidc-provider/token.actions.githubusercontent.com"
            },
            "Condition": {
                "StringEquals": {
                    "token.actions.githubusercontent.com:aud": [
                        "sts.amazonaws.com"
                    ]
                },
                "StringLike": {
                    "token.actions.githubusercontent.com:sub": [
                        "repo:yasuha-h/*"
                    ]
                }
            }
        }
    ]
}
```

問題なさそうなので`ロールを作成`をクリックしてロール作成は完了です。

## ロールにポリシーを追加

ロールを作成するとロール一覧に先ほど作成したロールが表示されているので検索してロールを選択しましょう。

![スクリーンショット 2024-11-25 23.31.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494944/7c25ee49-2581-a10b-7746-9dd248fb1ebf.png)

このようにまだ許可ポリシーを設定できていないので`許可を追加`→`インラインポリシーを作成`をクリックしてポリシーを追加します。

:::note
[IAM Policy Simulator](https://policysim.aws.amazon.com/home/index.jsp?#role/prac-github-actions-role) 
こんなものがあったのでIAM設定に自信がない方(筆者も)はこれを使って勉強するのも有りだと思います。
:::

![スクリーンショット 2024-11-25 23.32.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494944/139ddbf5-57c6-46c2-3c3c-37093682f0d2.png)


### アクセス許可を指定
`サービスを選択`今回はECRに対する許可ポリシーを作成するので`elastic container registry`と検索して`Elastic Container Registry`を選択します。

#### アクションを選択
以下のリファレンスから該当の許可アクションを選択します。

https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/image-push-iam.html

https://docs.aws.amazon.com/ja_jp/service-authorization/latest/reference/list_amazonelasticcontainerregistry.html

以下のJSONはすべてのリソースに対して認証トークンを取得を許可し、ARNで指定しているリソースにのみイメージのアップロードや詳細情報の取得等のアクションを許可していると伺えます。

```JSON
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ecr:CompleteLayerUpload",
                "ecr:UploadLayerPart",
                "ecr:InitiateLayerUpload",
                "ecr:BatchCheckLayerAvailability",
                "ecr:PutImage",
                "ecr:BatchGetImage"
            ],
            "Resource": "arn:aws:ecr:region:111122223333:repository/repository-name"
        },
        {
            "Effect": "Allow",
            "Action": "ecr:GetAuthorizationToken",
            "Resource": "*"
        }
    ]
}
```

今回はJSONではなくGUIで設定してみました。

![スクリーンショット 2024-11-26 18.37.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494944/57d3e03f-6b1e-1d1a-8997-6fa18928e46d.png)
![スクリーンショット 2024-11-26 18.37.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494944/776b7cf4-0688-5196-3a09-504d28815725.png)

`次へ`をクリックして、ポリシー名を入力して設定したECRの各アクションが正しいか確認して`ポリシーを作成`をクリックすればロール詳細ページに遷移するのでに許可ポリシーが付与されていることを確認できます。

![スクリーンショット 2024-11-26 18.50.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494944/ac05c3a3-3971-3ef8-c750-4a31b7b22571.png)

## Github Actionsのワークフロー作成

### AWS認証
やっとワークフローを触ることができます。以下を参考にしてワークフローを設定していきます。

https://docs.github.com/ja/actions/security-for-github-actions/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services#github-actions-%E3%83%AF%E3%83%BC%E3%82%AF%E3%83%95%E3%83%AD%E3%83%BC%E3%82%92%E6%9B%B4%E6%96%B0%E3%81%99%E3%82%8B

> この aws-actions/configure-aws-credentials アクションを使って、OIDC トークン (JWT) をクラウド アクセス トークンと交換します。

> ジョブまたはワークフローの実行には、GitHub の OIDC プロバイダーが実行ごとに JSON Web Token を作成できるようにするために、id-token: write を含む permissions 設定が必要です。 

```yml
permissions:
  id-token: write # This is required for requesting the JWT
  contents: read  # This is required for actions/checkout
```

さらに以下のドキュメントを確認します。

https://github.com/aws-actions/configure-aws-credentials?tab=readme-ov-file#oidc-audience

https://github.com/aws-actions/amazon-ecr-login?tab=readme-ov-file#login-to-amazon-ecr-private-then-build-and-push-a-docker-image

完成した`workflow`はこちら

https://github.com/yasuha-h/prac-cicd-on-github-actions/blob/main/.github/workflows/main.yaml

## git push!

git pushしたらさっそくリポジトリでactionsがうまく動いているか確認します。

![スクリーンショット 2024-11-30 21.07.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494944/24705665-819b-4370-bd1b-970c1f61c2a8.png)


うまくimageがpushされていることを確認できました！

![スクリーンショット 2024-11-30 20.50.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494944/04fc7d22-f046-7554-60ad-80fd09923b21.png)

## 最後に

### ちょっとつまずいたところ
- まずは何から手を付ければいいかの整理するところ
- `IAMロール`を作成 → `ポリシー`を作成の流れが不慣れであったことと、IAMとポリシー設定に苦手なイメージがついてしまっていたためドキュメントを探すまたは理解するところ
- GitHub Actionsのシークレットキーの読み込みは`env`で読み込んで利用しないと`null`になってしまうところ

CICDをこれから学習していくっていう方々の参考になれば嬉しいです。