GitHub Actions の OpenID Connector と AWS の OIDC Provider を使うことで、IAM Role を Assume できるというのは前回書きました。
tech.guitarrapc.com
構築中によく出るエラーに関しても書いたのですが、いざ実際に使おうとしたら別のエラーではまったので忘れないようにメモしておきます。
tl;dr;
- OpenID Connect で認証すると、AWS OIDC Provider の認証の上限に引っ掛かりやすい
- Composite Action の中で、 configure-aws-credentials を呼び出すときは注意
- 2021/12/10 追記: このPR が入れば自動的にリトライしてくれるで記事のプラクティスは不要になる予定
GitHub Actions で並列実行すると時々失敗する。
2022/2/4 本バグは https://github.com/aws-actions/configure-aws-credentials/issues/299 で修正されています。もう気にしなくともリトライもされます。
次のエラーがでることがあります。
エラーメッセージ Error: Couldn't retrieve verification key from your identity provider, please reference AssumeRoleWithWebIdentity documentation for requirements
対策: configure-aws-credentials で OIDC 認証を頻繁に呼び出す場合は、キャッシュかリトライしましょう。
並列でジョブを実行するなど、短時間に頻繁に認証を取得ようとすると、時々認証に失敗します。
IAM Userを使っていると当然でないのですが、OIDC Providerで認証をかけようとするとぐさっと刺さります。
これを回避するには、リトライかキャッシュ作戦をとる必要があります。
github.com
workflow で1回だけ認証ととって、キャッシュを使いまわす場合次のような workflow になります。
gist.github.com
ただ、GitHub Actions の cache は 「パブリックリポジトリのキャッシュには、センシティブな情報を保存しないことをおすすめします。」とある通り取扱いには注意だと思います。トークン自体 は 900sec (min) か 1 hour (default) で切れますが、時間の問題ではないという。
Warning: We recommend that you don't store any sensitive information in the cache of public repositories. For example, sensitive information can include access tokens or login credentials stored in a file in the cache path. Also, command line interface (CLI) programs like docker login can save access credentials in a configuration file. Anyone with read access can create a pull request on a repository and access the contents of the cache. Forks of a repository can also create pull requests on the base branch and access caches on the base branch.
https://docs.github.com/en/actions/advanced-guides/caching-dependencies-to-speed-up-workflows
対策: configure-aws-credentials の呼び出しは一回の composite action で行うか、workflow で呼び出しましょう。
通常 configure-aws-credentials は、呼び出しのたびに job 内の認証を後勝ちで上書きします。
ただし、composite action の中で、configure-aws-credentials を呼び出すと、意図しない結果になるパターンがあります。
configure-aws-credentials を呼び出す処理を composite action に書いて、1 job内で 別の IAM Role の Assume を呼びだすと 2 回目の configure-aws-credentials で上書きできないので避けましょう。
github.com
正常動作例1
次のように workflow 上で連続でconfigure-aws-credentialsを呼び出すと、2回目の configure-aws-credentials で myrole_Bに上書きできていることが確認できます。
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@master
with:
aws-region: ap-northeast-1
role-to-assume: arn:aws:iam::123456789012:role/myrole_A
role-session-name: GitHubActions-${{ github.run_id }}
- name: get-caller-identity shows myrole_A as expected
run: aws sts get-caller-identity
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@master
with:
aws-region: ap-northeast-1
role-to-assume: arn:aws:iam::123456789012:role/myrole_B
role-session-name: GitHubActions-${{ github.run_id }}
- name: get-caller-identity shows myrole_B as expected
run: aws sts get-caller-identity
1回目のget-caller-identity は myrole_A です。
{
"UserId": "AROASJXUOK5UM7XZKRYTB:GitHubActions-1426675663",
"Account": "***",
"Arn": "arn:aws:sts::***:assumed-role/myrole_A/GitHubActions-1426675663"
}
2回目のget-caller-identity は myrole_B です。
{
"UserId": "AROASJXUOK5UM7XZKRYTB:GitHubActions-1426675663",
"Account": "***",
"Arn": "arn:aws:sts::***:assumed-role/myrole_B/GitHubActions-1426675663"
}
意図通りの挙動です。
正常動作例2
Composite Action の中で configure-aws-credentials をまとめて2回呼び出すと、2回目の呼び出しで myrole_B に上書きできていることが確認できます。
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Configure AWS Credentials
uses: ./.github/actions/aws_oidc_auth_all
aws_oidc_auth_all
はこうなっています。
name: aws oidc auth
description: |
Get aws oidc auth.
runs:
using: "composite"
steps:
- name: Configure AWS Credentials (Role A)
uses: aws-actions/configure-aws-credentials@master
with:
aws-region: ap-northeast-1
role-to-assume: arn:aws:iam::123456789012:role/myrole_A
role-session-name: GitHubActions-${{ github.run_id }}
- name: get-caller-identity shows myrole_A as expected
run: aws sts get-caller-identity
shell: bash
- name: Configure AWS Credentials (Role B)
uses: aws-actions/configure-aws-credentials@master
with:
aws-region: ap-northeast-1
role-to-assume: arn:aws:iam::123456789012:role/myrole_B
role-session-name: GitHubActions-${{ github.run_id }}
- name: get-caller-identity shows myrole_B as expected
run: aws sts get-caller-identity
shell: bash
1回目のget-caller-identity は myrole_A です。
{
"UserId": "AROASJXUOK5UM7XZKRYTB:GitHubActions-1426687022",
"Account": "***",
"Arn": "arn:aws:sts::***:assumed-role/myrole_A/GitHubActions-1426687022"
}
2回目のget-caller-identity は myrole_B です。
{
"UserId": "AROASJXUOK5UHN4XWD3XF:GitHubActions-1426687022",
"Account": "***",
"Arn": "arn:aws:sts::***:assumed-role/myrole_B/GitHubActions-1426687022"
}
意図通りの挙動です。
問題の動作
Composite Action の中で configure-aws-credentials を それぞれのIAM Role について呼び出すと、2回目の呼び出しが myrole_A のままで myrole_B で上書きできていないことが確認できます。
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Configure AWS Credentials (Role A)
uses: ./.github/actions/aws_oidc_auth_single
with:
[https://docs.github.com/en/actions/creating-actions/creating-a-composite-action:embed:cite]
role-to-assume: arn:aws:iam::123456789012:role/myrole_A
- name: Configure AWS Credentials (Role B)
uses: ./.github/actions/aws_oidc_auth_single
with:
role-to-assume: arn:aws:iam::123456789012:role/myrole_B
aws_oidc_auth_single
はこうなっています。
name: aws oidc auth
description: |
Get aws oidc auth.
inputs:
role-to-assume:
description: "AWS IAM Role to assume 1"
required: true
runs:
using: "composite"
steps:
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@master
with:
aws-region: ap-northeast-1
role-to-assume: ${{ inputs.role-to-assume }}
role-session-name: GitHubActions-${{ github.run_id }}
- name: get-caller-identity shows myrole_A on both 1st and 2nd run. (2nd run must be myrole_B but incorrect result.)
run: aws sts get-caller-identity
shell: bash
1回目のget-caller-identity は myrole_A です。
{
"UserId": "AROASJXUOK5UM7XZKRYTB:GitHubActions-1426687028",
"Account": "***",
"Arn": "arn:aws:sts::***:assumed-role/myrole_A/GitHubActions-1426687028"
}
2回目のget-caller-identity も myrole_A です。myrole_B に上書きできていません。
{
"UserId": "AROASJXUOK5UHN4XWD3XF:GitHubActions-1426687028",
"Account": "***",
"Arn": "arn:aws:sts::***:assumed-role/myrole_A/GitHubActions-1426687028"
}
aws-actions/configure-aws-credentials の中身を見ても、composite action 特有の処理は当然存在しません。
composite action の仕様かと思いつつ、そういった記述もないので謎です。
仕方ないので、正常動作例1,2 のいずれかを用いることになるでしょう。
あるいは、両方の権限をもつ単一Roleでやるのも手でしょう。