1
0

More than 1 year has passed since last update.

[Github Actions] configure-aws-credentialsを読み解く

Last updated at Posted at 2022-12-08

この記事は IDaaS Advent Calendar 2022 9日目の投稿です。

はじめに

Github ActionsでAWSリソースを操作する際、何も考えずに定義してしまうこのアクション。
実際これって内部で何してるのか気になったので調査。

  - uses: aws-actions/configure-aws-credentials@v1
    with:
      role-to-assume: ${{ inputs.aws_role_arn }}
      aws-region: ${{ inputs.aws_region }}

どれ?

これ

前提

  • actionの引数には以下のみ指定
    • role-to-assume
    • aws-region

actions.yml

とりあえず一番下をみてみる。index.jsを呼び出している模様。

#省略
runs:
  using: 'node12'
  main: 'dist/index.js'
  post: 'dist/cleanup/index.js'

index.js

run()がメイン関数になるようだ。

284: async function run() {
285:   try {
286:     // Get inputs
287:     const accessKeyId = core.getInput('aws-access-key-id', { required: false });
288:     const audience = core.getInput('audience', { required: false });
289:     const secretAccessKey = core.getInput('aws-secret-access-key', { required: false });

入力値に限定すると以下が該当、残りはデフォルトの値が入る。

290: const region = core.getInput('aws-region', { required: true });
293: const roleToAssume = core.getInput('role-to-assume', {required: false});

@actions/coreはgithub actions用のツールキットであり、
環境変数や引数を読み込んだり、次のステップに受け渡したりできる模様。


exportRegion

AWS_REGIONDEFAULT_AWS_REGIONを環境変数として出力している

308:  exportRegion(region);

useGithubOICDProvider

以下理由からTrueとなるはず

  • roleToAssumeは定義済み
  • ACTIONS_ID_TOKEN_REQUEST_TOKENはIDトークンを取得するためのトークンのようで、GithubActions起動時に自動で環境変数に設定される。
310: // This wraps the logic for deciding if we should rely on the GH OIDC provider since we may need to reference
311: // the decision in a few differennt places. Consolidating it here makes the logic clearer elsewhere.
312:  const useGitHubOIDCProvider = () => {
313:    // The assumption here is that self-hosted runners won't be populating the `ACTIONS_ID_TOKEN_REQUEST_TOKEN`
314:    // environment variable and they won't be providing a web idenity token file or access key either.
315:    // V2 of the action might relax this a bit and create an explicit precedence for these so that customers
316:    // can provide as much info as they want and we will follow the established credential loading precedence.
317:    return roleToAssume && process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN && !accessKeyId && !webIdentityTokenFile
318:   }

exportCredentials

exportReigonと同様、環境変数をセット。

330: exportCredentials({accessKeyId, secretAccessKey, sessionToken});

configureProxy

http_proxyの定義をしていない為、特に動作しない

334: configureProxy(proxyServer);

webIdentityToken

useGithubOIDCProviderはTrueなので、webIdentityTokenroleDurationSecondsを取得。
各引数にはデフォルトの値が入る。

audience: sts.amazonaws.com
roleDurationSeconds: 6 * 3600
341: if(useGitHubOIDCProvider()) {
342:   webIdentityToken = await core.getIDToken(audience);
343:   roleDurationSeconds = core.getInput('role-duration-seconds', {required: false}) || DEFAULT_ROLE_DURATION_FOR_OIDC_ROLES;
344:   // We don't validate the credentials here because we don't have them yet when using OIDC.
345: } 

core.getIDTokenは何をしているかというと、OidcClient.getIDTokenを呼び出し、

core/src/core.ts
// https://github.com/actions/toolkit/blob/main/packages/core/src/core.ts
export async function getIDToken(aud?: string): Promise<string> {
  return await OidcClient.getIDToken(aud)
}

getIdTokenURLによりACTIONS_ID_TOKEN_REQUEST_URLを取得、URLエンコードしたaudience(=sts.amazonaws.com)と組み合わせid_token_urlとした上で、getCallを呼び出し、id_tokenを取得している。

core/src/oidc-utils.ts
// https://github.com/actions/toolkit/blob/main/packages/core/src/oidc-utils.ts
  static async getIDToken(audience?: string): Promise<string> {
    try {
      // New ID Token is requested from action service
      let id_token_url: string = OidcClient.getIDTokenUrl()
      if (audience) {
        const encodedAudience = encodeURIComponent(audience)
        id_token_url = `${id_token_url}&audience=${encodedAudience}`
      }

      debug(`ID token url is ${id_token_url}`)

      const id_token = await OidcClient.getCall(id_token_url)
      setSecret(id_token)
      return id_token
    } catch (error) {
      throw new Error(`Error message: ${error.message}`)
    }
  }

roleCredentials

AWS STSから先ほど取得したid_tokenなどを利用して最終的に以下の情報を取得
エクスポテンシャルバックオフってこうやって使うのか・・

accessKeyId
secretAccessKey
sessionToken
356:   // Get role credentials if configured to do so
357:   if (roleToAssume) {
358:     const roleCredentials = await retryAndBackoff(
359:       async () => { return await assumeRole({
360:         sourceAccountId,
361:         region,
362:         roleToAssume,
363:         roleExternalId,
364:         roleDurationSeconds,
365:         roleSessionName,
366:         roleSkipSessionTagging,
367:         webIdentityTokenFile,
368:         webIdentityToken
369:       }) }, true);

exportCredentials

取得したcredentialを環境変数へ

370:   exportCredentials(roleCredentials);

exportAccountId

最後にアカウントIDをOutputとして設定

378: await exportAccountId(maskAccountId, region);

まとめ

普段何気なく使っているパッケージも中身を見てみると参考になります。
こういう機会がないと読んでる余裕ないんですけどね。

IDaaSを利用したアプリケーション開発にお悩みの方は弊社TC3までお問い合わせください。また、優秀なアーキテクトからの応募も常時受け付けています。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0