この記事は 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_REGION
、DEFAULT_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なので、webIdentityToken
とroleDurationSeconds
を取得。
各引数にはデフォルトの値が入る。
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を呼び出し、
// 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
を取得している。
// 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までお問い合わせください。また、優秀なアーキテクトからの応募も常時受け付けています。