Shogo's Blog

Sep 24, 2021 - 3 minute read - aws github

GitHub Actions + OIDC Token の情報をAWSのセッションタグに設定してみた

GitHub Actions で ID Token が使えるようになったと話題ですね。

AWS IAM が OpenID Connect (OIDC) を使った認証 (sts:AssumeRoleWithWebIdentity) に対応しているので、認証プロバイダ(IdP)を用意してあげればシークレットの登録が不要になるということらしいです。 これは便利!

セッションタグを渡したい

これはまさに「AWS_SECRET_ACCESS_KEY を GitHub Actions secrets へ突っ込むのに疲れた俺達は」で実現したかったことですね。 このままだとせっかく作ったアクションが不要になりそうで悔しいので このアクションにずっと追加したかった機能があるのですが、OIDCトークンを使うと簡単に実装できそうだったので、お試しで追加してみました。

actions-aws-assume-role アクションはセッションタギングに対応しています。 これを利用するとアクションを実行したレポジトリ、ブランチ、実行したユーザー等がわかります。

Key Value
GitHub “Actions”
Repository GITHUB_REPOSITORY
Workflow GITHUB_WORKFLOW
RunId GITHUB_RUN_ID
Actor GITHUB_ACTOR
Branch GITHUB_REF
Commit GITHUB_SHA

しかしこれらの情報は、レポジトリへの書き込み権限を持っているユーザーであれば容易に偽装可能です。 そのため100%正しい情報が入っているとは言えない状態でした。

OIDC が利用可能になるとこれが変わります。 以下はOIDCのIDトークンの Claim 部分をデコードしたものです。 ここにもレポジトリ、ブランチ、実行したユーザー等が入っていますね。

{
  "jti": "73e91482-a3d5-408a-98ea-b91de4733605",
  "sub": "repo:shogo82148/github-action-test:ref:refs/heads/main",
  "aud": "https://github.com/shogo82148/github-action-test",
  "ref": "refs/heads/main",
  "sha": "6dfcf89b39ebf8046a9e72d93eda07c22214dde9",
  "repository": "shogo82148/github-action-test",
  "repository_owner": "shogo82148",
  "run_id": "1250487318",
  "run_number": "32",
  "run_attempt": "1",
  "actor": "shogo82148",
  "workflow": "token permission",
  "head_ref": "",
  "base_ref": "",
  "event_name": "workflow_dispatch",
  "ref_type": "branch",
  "job_workflow_ref": "shogo82148/github-action-test/.github/workflows/workflow_dispatch.yml@refs/heads/main",
  "iss": "https://vstoken.actions.githubusercontent.com",
  "nbf": 1632045829,
  "exp": 1632046729,
  "iat": 1632046429
}

GitHub Actions 上の環境変数と違うのは、これらの情報が 電子署名によって保護されているという点 です。 改ざんしても署名でバレてしまうので、信頼できる情報として扱うことができます。

セッションタグは IAM Role の信頼ポリシーの Condition に設定する条件として使用可能です。 例えば以下のように "aws:RequestTag/Branch": "refs/heads/main" を追加することで、 actions-aws-assume-role アクションの使用を main ブランチに制限することができます。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::053160724612:root"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "sts:ExternalId": "shogo82148/github-action-test",
          "aws:RequestTag/IdToken": "true",
          "aws:RequestTag/GitHub": "Actions",
          "aws:RequestTag/Branch": "refs/heads/main"
        }
      }
    },
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::053160724612:root"
      },
      "Action": "sts:TagSession"
    }
  ]
}

Environment が取得できる

OIDCの利用にはもうひとつ嬉しい点があって、Environments を指定すると、IDトークンに Environment に関する情報が入ります。

{
  "jti": "f409168e-6bec-42bb-9cef-73d86a0a01da",
  "sub": "repo:shogo82148/github-action-test:environment:test",
  "aud": "https://github.com/shogo82148/github-action-test",
  "ref": "refs/heads/main",
  "sha": "edbf00b96304d9ce2434f3daed59dd847ffd449b",
  "repository": "shogo82148/github-action-test",
  "repository_owner": "shogo82148",
  "run_id": "1268676048",
  "run_number": "34",
  "run_attempt": "1",
  "actor": "shogo82148",
  "workflow": "token permission",
  "head_ref": "",
  "base_ref": "",
  "event_name": "workflow_dispatch",
  "ref_type": "branch",
  "environment": "test",
  "job_workflow_ref": "shogo82148/github-action-test/.github/workflows/workflow_dispatch.yml@refs/heads/main",
  "iss": "https://vstoken.actions.githubusercontent.com",
  "nbf": 1632462508,
  "exp": 1632463407,
  "iat": 1632463108
}

GitHub Actions のジョブの中からこの情報が取れなくて困ってたんですよね。 これが使えると デプロイ内容のレビュー を受けて Approve されたワークフローにのみ権限を付与する、 などといった高度なアクセス制御か可能となります。

各社へのお願い

AWS

実は sts:AssumeRoleWithWebIdentity でもIDトークンの情報を信頼ポリシーの条件とすることが可能です。

しかし、簡単に試してみた限り vstoken.actions.githubusercontent.com:audvstoken.actions.githubusercontent.com:sub といった OIDC の一般的なキーしか参照できないようです。

一方、Google や Facebook は設定済みのIdPが用意されており、graph.facebook.com:app_id, accounts.google.com:oaud といったプロバイダ特有のキーが利用できるようです。

設定済みのIdPに GitHub Actions を追加して、利用可能なキーを追加してもらうことってできないですかね・・・?

GitHub

sts:AssumeRoleWithWebIdentity でも一応セッションタグを利用することはできるのですが、 IDトークンの Claim に "https://aws.amazon.com/tags" という特殊なキーを埋め込む必要があります。

{
    "sub": "johndoe",
    "aud": "ac_oic_client",
    "jti": "ZYUCeRMQVtqHypVPWAN3VB",
    "iss": "https://xyz.com",
    "iat": 1566583294,
    "exp": 1566583354,
    "auth_time": 1566583292,
    "https://aws.amazon.com/tags": {
        "principal_tags": {
            "Project": ["Automation"],
            "CostCenter": ["987654"],
            "Department": ["Engineering"]
        },
        "transitive_tag_keys": [
            "Project",
            "CostCenter"
        ]
    }
}

これを使えば GitHub 側でも対応可能だと思うので、何卒・・・

まとめ

GitHub Actions の ID Token の情報を AWSのセッションタグに設定してみました。 actions-aws-assume-role アクションにも組み込んでみましたが、 マーケットへの公開はしていません。

というのも、2021-09-24時点 OpenID Connect に関して GitHub の公式ドキュメントには一切記載がなく、 今後どうなるのか全くわからないからです。 非常に便利そうな機能なので、公開されるのが待ち遠しいですね。

参考