Github Actions で OIDC を使ったクレデンシャルを取得する機能の Dependabot の挙動確認

先日 Github から OIDC を使用して AWSGCP などの Cloud Provider からクレデンシャルを取得する方法に関する発表がありました。
github.blog

これを使うことで今までのように Github Secrets に各 Cloud Provider のクレデンシャルを設定する必要がなくなりました。
また有効期限も Workflow ごとに設定され自動でローテートされるのでセキュリティ面の向上もあります。 参考

自分も AWS のクレデンシャルを Github Secrets に設定して使用していた部分があったので今回のやり方に変更しました。
しかし変更時に Dependabot によってコミットされた時のワークフローの挙動について疑問がわいたのでこのブログではその調査した結果をまとめています。

Github Actions における秘匿情報の扱い

下記の Github のブログにあるように今年の 2月頃に Dependabot によって起動した Workflow では通常の Secrets の情報が読み取れなくなりました。
これは依存パッケージに悪意のある変更が入って Secrets 情報が読み取られないようにするためです。 github.blog

どうしても設定したい場合は Dependabot 用のシークレットがあるのでそこに設定します。 docs.github.com

そのため今までは AWS のクレデンシャルを Secrets にいれていても意図せず Dependabot によって起動した Workflow に渡ることはありませんでした。

しかし今回の発表の機能を使うと何も Secrets に格納する必要がなくなります。 これを見た時にもしかしてこの機能を使うと Dependabot にもクレデンシャルが渡ってしまうのではと思いました。
今回はこれを調査します。

ドキュメントを見る

まずは公式のドキュメントを確認します。

下記の AWS での導入手順を読み進めると Workflow の permissions.id-tokenwrite を設定する箇所がでてきます。 docs.github.com

これは GITHUB_TOKEN に対するパーミッションになっており、ユーザーがコミットした時は通常下記の画像にある "Default access (permissive)" が使用されて read/write が設定できます。
しかし Dependabot は fork されたリポジトリとして扱われるので、一番右の "Maximum access by forked repos" が適用されて read のみとなり write を設定することができません。

f:id:hatappi1225:20211030133456p:plain Automatic token authentication - Permissions for the GITHUB_TOKEN

つまりこれにより Dependabot で起動した Workflow では今回の機能は使えないはずです。 せっかくなので、実際に挙動を確認してみます。

OIDC in AWS の動作確認

まずは動作する設定を作ります。

おおまかな手順としては下記になります。

  1. AWS で identity provider, IAM Role を作成
  2. Github Actions の Workflow を作成

1. AWS で identity provider, IAM Role を作成

AWS のリソースは今回 Terraform で作成します。

まずは identity provider を作ります。

resource "aws_iam_openid_connect_provider" "github_actions" {
  url = "https://token.actions.githubusercontent.com"

  client_id_list = [
    "sts.amazonaws.com"
  ]

  thumbprint_list = [
    "a031c46782e6e6c662c2c87c76da9aa62ccabd8e"
  ]
}

次に IAM Role を作成します。

resource "aws_iam_role" "github_actions" {
  name = "github-actions"

  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": {
    "Effect": "Allow",
    "Principal": {
      "Federated": "${aws_iam_openid_connect_provider.github_actions.arn}"
    },
    "Action": "sts:AssumeRoleWithWebIdentity",
    "Condition": {
      "StringLike": {
        "token.actions.githubusercontent.com:sub": "repo:{your github org}/{your repository name}:*"
      },
      "StringEquals": {
        "token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
      }
    }
  }
}
EOF
}

これで AWS 側の設定は完了です。

2. Github Actions の Workflow を作成

今回は公式のサンプルを参考にしつつ最低限の権限で動作確認をするために aws sts get-caller-identity を実行します。

name: AWS example workflow
on:
  push
permissions:
  id-token: write
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - name: configure aws credentials
        uses: aws-actions/configure-aws-credentials@master
        with:
          role-to-assume: arn:aws:iam::{your aws account id}:role/github-actions
          role-session-name: samplerolesession
          aws-region: ap-northeast-1
      - run: aws sts get-caller-identity

これをコミットして実行がうまくいけば下記のような結果が得られます。

{
    "UserId": "xxxxx:samplerolesession",
    "Account": "***",
    "Arn": "arn:aws:sts::***:assumed-role/github-actions/samplerolesession"
}

Dependabot で実行

さきほどの Workflow を Dependabot によるコミットで起動します。

結果は下記のようにエラーになりました🎉

f:id:hatappi1225:20211030132021p:plain

最後に

今回は OIDC を使ったクレデンシャルを取得する Github Actions の機能での Dependabot の挙動を確認しました。

結果としてはドキュメントにあるように Dependabot で起動した Workflow は fork されたリポジトリして扱われるため、権限が絞られて今回の機能を使うために必要な権限を得ることができず失敗しました。

これでスッキリしたので、安心して使うことができそうです 🍵