のべラボ.blog

Tech Blog | AWS や サーバーレスやコンテナ などなど

今さらながら GitHub Actions をさわってみる: (AWS へのアクセス編)

前回、前々回に引き続き、GitHub Actions のワークフローを触っていきます。

今回は、ワークフローから AWS アカウントへアクセスする方法を整理しつつ、実際にアクセスを試していきます。

最終的には、GitHub Actions を使用して アプリケーションをビルドし、AWS アカウントにデプロイするワークフローを作成しようと思っているので、AWS アカウントへのアクセス方法の理解はその事前準備となります。

なお、この記事は 2023 年 3 月時点で検証した内容に基づいて記載しています。


目次


AWS アカウントへアクセスする方法の整理

まず、GitHub のドキュメントを参照して AWS アカウントへのアクセス方法を整理してみましたが、基本的には下記の 2パターンがあるようです。

  1. AWS のアクセスキー ID やシークレットアクセスキー を GitHub の Secret として保存してワークフローから使用する方法
  2. GitHubOpenID Connect (OIDC) プロバイダを使用し、AWS アカウントにアクセスできるトークンを使用する方法

セキュリティの観点から上記 2 の方法が推奨 のようですが、とりあえず両方の方法を試します。


方法 1. AWS のアクセスキー ID やシークレットアクセスキー を GitHub の Secret として保存してワークフローから使用する方法

GitHub の Secret については、次のドキュメントに記載があります。AWS アカウントのアクセスキーなど、秘匿すべき認証情報を保存する用途に使えそうです。

docs.github.com

この Secret を使ったワークフローのイメージ図を描いてみました。

上図のように、仕組みとしてはシンプルでわかりやすいですよね。

ただし、前述のようにこの方法はお薦めできません。

Secret という仕組みはあるにせよ、永続的に使用できるアクセスキー ID を発行してそれを一つの場所にずっと保管することはセキュリティ面での懸念があるからです。

後で説明する 2番目の方法のように、必要なタイミングで一時的に使用できるトークンを発行して使用する 方が望ましいのですが、今回は勉強の一環として試してみました。

まず、AWS アカウントで 下記の IAM ポリシーを作成します。(ここでは便宜上、s3-listAllMyBuckets-policy と名付けます。)

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "s3:ListAllMyBuckets",
            "Resource": "*"
        }
    ]
}

次に IAM ユーザーを作成して作成した s3-listAllMyBuckets-policy を設定し、アクセスキーID とシークレットアクセスキーを発行します。

そのアクセスキーID とシークレットアクセスキーを GitHub の Secret として設定します。

設定方法は、Web ブラウザからでも GitHub CLI からでも可能です。

Web ブラウザの場合は、対象リポジトリのページから [ Settings ] タブ、左側のメニューで [ Secrets and variables ] - [ Actions ] を選択して、右上の [ New repository secret ] を選択して設定します。設定した Secret の名前は後でワークフローの中で指定します。

では次にワークフローの YAML ファイルを作ります。

今回は、下記のドキュメントを参考にしました。

docs.aws.amazon.com

ただし、今回は AWS アカウントへのアクセスを試すのが目的なので、 AWS SAM は使用せず、AWS CLI のコマンドを aws s3 ls を発行するだけのシンプルなワークフロー(下記)に変えることにしました。

aws s3 ls が正常に実行され、Amazon S3 バケットの一覧が表示されれば AWS アカウントへアクセスできたという確認になります。

name: AWS access using secrets in GitHub
on:
  push:
    branches:
      - main
jobs:
  list-s3-buckets-using-Secret:
    runs-on: ubuntu-latest
    steps:
      - name: configure aws credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ap-northeast-1
      - name: execute AWS CLI
        run: aws s3 ls

上記の YAML でポイントになるのは、10 行目から 15 行目のステップです。

aws-actions/configure-aws-credentials というアクションを用いることで、AWS アカウントのアクセスするための認証情報をセットして、AWS CLI も利用できるようになります。

そのため、次の 16 行目からのステップでは、すぐに AWS CLIaws s3 ls を実行しています。

このワークフローを実行すると、正常に Amazon S3 バケットの一覧が表示されました。

GitHub のワークフローから AWS アカウントへアクセスを確認できたわけです。


方法 2. GitHubOpenID Connect (OIDC) プロバイダを使用し、AWS アカウントにアクセスできるトークンを使用する方法

ただ、(繰り返しになりますが)前述の方法 1 よりもお薦めなのが この OIDC を使用する方法です。

docs.github.com

下図は、この仕組みを図にしてみたものです。

方法 1 よりは複雑に感じるかもしれませんが、要するに AWS アカウントがGitHub の OIDC プロバイダを信頼する ことで、その OIDC プロバイダが発行した JWT (ジョット)トークンがあれば AWS の IAM ロールを使用できるようにする仕組みです。

GitHub の OIDC プロバイダが発行するJWTトークンがあれば、AWS 側からアクセストークンが発行されるので、そのアクセストークンで AWS アカウントにアクセスすれば、事前に設定した IAM ロールに紐づく IAM ポリシーの権限の範囲で AWS リソースを操作できます。

この仕組みを実現するには、まず GitHub の OIDC プロバイダを AWS アカウント側に登録します。

この方法は、GitHub の下記のドキュメントにも記載されています。

docs.github.com

この登録ですが、AWS マネジメントコンソールでも AWS CLI でも行えますが、個人的には AWS マネジメントコンソール を使う方が簡単 でお薦めです。

その理由は、OIDC プロバイダ登録時には TLS 証明書のサムプリント ( thumbprint ) の値が必要なのですが、AWS CLI の場合は、事前に様々なコマンドを発行したり編集したりしてそのサムプリントの値を自分で導出したうえでパラメータに指定する必要があるのに対して、AWS マネジメントコンソール ではサムプリントの値は自動的に取得、設定可能なためです。

参考として下記のドキュメントを紹介しますので、興味があれば実施してみて下さい。

docs.aws.amazon.com

ここではシンプルに設定できる AWS マネジメントコンソールを使用する方法を紹介します。

まず IAM のコンソールの左側のメニューから [ アクセス管理 ] - [ ID プロバイダ ] を選択し、右側にある [ プロバイダを追加 ] を選択します。

[ プロバイダのタイプ ] に [ OpenID Connect ] を選択します。

[ プロバイダの URL ] に https://token.actions.githubusercontent.com を入力して [ サムプリントを取得 ] を選択します。

その後、その下にある [ 対象者 ] に sts.amazonaws.com と入力して、ページ右下にある [ プロバイダを追加 ] をクリックします。

これで OIDC プロバイダの登録は完了です。

次に、この OIDC プロバイダを信頼する IAM ロールを作成します。

AWS マネジメントコンソールで作成する場合は、IAM のページから左側のメニューで[ アクセス管理 ] - [ ロール ] を選択し、右側にある [ ロールを作成 ] を選択します。

[ 信頼されたエンティティを選択 ] のページで [ 信頼されたエンティティタイプ ] に [ ウェブアイデンティティ ] を選択します。

[ アイデンティティプロバイダー ] に [ token.actions.githubusercontent.com ] を選択します。

[ Audience ] に [ sts.amazonaws.com ] を選択して、[ 次へ ] を選択します。

その後は、方法 1 で作成した s3-listAllMyBuckets-policy の IAM ポリシー(下記)を許可ポリシーとして設定します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "s3:ListAllMyBuckets",
            "Resource": "*"
        }
    ]
}

ロールの名前は任意の値を入力してロールを作成します。今回の例では、s3-listAllMyBuckets-role とします。

これでロールは作成したのですが、ロールの信頼ポリシーで GitHubリポジトリを限定するように条件を追加しておきましょう。

作成したロールの名前をクリックして、[ 信頼関係 ] タブを選択して、[ 信頼ポリシーを編集 ] を選択します。

そしてポリシーの Condition に下記を追加します。

これは、GitHub の特定のリポジトリだけを対象に IAM ロールの引き受けを可能にするための条件設定です。

セキュリティの面から IAM ロールを引き受けを認める範囲を限定する必要があるため、必ず設定して下さい。

"StringLike": {
                    "token.actions.githubusercontent.com:sub": "repo:<GitHubのユーザーID>/<GitHubのリポジトリ名>:*"
}

下記は、条件を追記した信頼ポリシー全体の例です。

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

これで AWS アカウント側の事前準備は終わったので、GitHub のワークフローを作成していきます。

下記のドキュメントにワークフローの例があるので、これを参考に方法 1 と同じく AWS CLIaws s3 ls を実行するワークフローを作成します。

docs.github.com

ただ、上記のドキュメントの例をみて、おや❓ と感じました。

ワークフローの YAML には、引き受ける IAM ロールの ARN を指定する必要がありますが、この例では、ワークフローが引き受ける IAM ロールの ARN の値を YAML ファイルにそのまま記述しています。

しかし、ARN には AWS アカウント ID の 12桁の数字も含まれるので、YAML ファイルにそのまま記述するのは避けたいですよね。

ということで、IAM ロールの ARN は GitHub の Secret に保存し、それを参照することにしました。

OIDC の方法を用いれば Secret は使わなくてもいいかなと思っていたのですが、やはり AWS アカウントID は秘匿しておきたいですよね。

結果、完成した ワークフローの YAML が下記です。

name: AWS access using OIDC provider
on:
  push:
    branches:
      - main
env:
  AWS_REGION : "ap-northeast-1"
# permission can be added at job level or workflow level    
permissions:
      id-token: write   # This is required for requesting the JWT
      contents: read    # This is required for actions/checkout
jobs:
  list-s3-buckets-using-OIDC:
    runs-on: ubuntu-latest
    steps:
      - name: configure aws credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
          role-session-name: samplerolesession
          aws-region: ${{ env.AWS_REGION }}
      - name: execute AWS CLI
        run: aws s3 ls

19 行目では、Secret を使って IAM ロールの ARN を取得するようにしています。

実行してみると、下図のように aws s3 ls が正常に実行されたことを確認できました。


今回の所感

今回の記事の中で紹介した OIDC を使用する方法により、 AWS のアクセスキー ID を発行して GitHub 側に保存しなくても AWS アカウントへアクセスできるが確認できました。

この方法を理解できたことで、GitHub Actions を使用して AWS アカウントへ アプリケーション環境を構築するワークフローの作成方法のイメージが大きく膨らんできました!

次回は、今回の記事の内容をベースにしつつ、AWS アカウントへアプリケーション環境を構築するワークフローを作成したいと思います!


/* -----codeの行番号----- */