AWS_CONTAINER_CREDENTIALS_FULL_URI と AWS_CONTAINER_CREDENTIALS_RELATIVE_URI 環境変数に関する雑記

2021.01.08

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

しばたです。

割と誰得な話ではあるのですが自分がAWS CloudShellの認証周りで調べて気になったことについてつらつらと書いていきます。
公式に確定している情報以外に私の推測を含む部分もありますのでその点はご留意ください。

はじめに

この記事を書くきっかけとなったのは先日リリースされたAWS CloudShellを試しているときでした。

AWS CloudShellでAWS CLIを使う際はデフォルトでマネジメントコンソールを利用しているユーザーの認証情報を使う様になっているものの、AWS Tools for PowerShellではデフォルトで認証情報が連動せず、「AWS CloudShellでは認証情報をどの様に取り扱っているのか?」と気になったのが発端です。

AWS CloudShellの認証情報 (コンテナインスタンスプロファイル)

AWS CloudShellの具体的なアーキテクチャは非公開ですが、有志による調査やre:Invent 2020のセッションで公開された情報によればAWS管理のVPC上にあるコンテナ環境であろうと推測されています。

AWS CloudShell内部からはあたかもECS + Fargateの環境であるかの様に見え *1環境変数にもAWS_CONTAINER_CREDENTIALS_FULL_URIAWS_CONTAINER_AUTHORIZATION_TOKENといった"いかにも"なヤツが存在しています。

実際ECSのドキュメントではAWS_CONTAINER_CREDENTIALS_RELATIVE_URIを使ったコンテナインスタンスプロファイルの取得方法が記載されており、AWS CloudShellのユーザーガイドにも同様の手順で認証情報(アクセスキー・シークレットキーおよびセッショントークン)を取得する方法が記載されています。

ユーザーガイドの手順に従えば以下の手順で認証情報を取得できます。

# AWS_CONTAINER_AUTHORIZATION_TOKEN を使ってメタデータから認証情報を取得
curl -s -H "X-aws-ec2-metadata-token: $AWS_CONTAINER_AUTHORIZATION_TOKEN" $AWS_CONTAINER_CREDENTIALS_FULL_URI \
    | jq "{AccessKeyId: .AccessKeyId, SecretAccessKey: .SecretAccessKey, SessionToken: .Token, Expiration: .Expiration, Version: 1"}

AWS_CONTAINER_CREDENTIALS_FULL_URI と AWS_CONTAINER_CREDENTIALS_RELATIVE_URI

ここまでを踏まえてAWS CloudShellにおける認証情報はAWS_CONTAINER_CREDENTIALS_FULL_URI環境変数を使ってコンテナインスタンスプロファイルを取得していると考えて良さそうです。

ここでよく見るとAWS CloudShellで使われているのは「AWS_CONTAINER_CREDENTIALS_FULL_URI」であり、ECSの「AWS_CONTAINER_CREDENTIALS_RELATIVE_URI」と絶対パスか相対パスかの微妙な違いがあります。

通常のECSタスク(コンテナ)ではメタデータのエンドポイントが固定(基本169.254.170.2)のためパスの部分のみAWS_CONTAINER_CREDENTIALS_RELATIVE_URIで設定され、AWS CLIや各種言語のSDKがこれを利用します。

また、AWS CloudShellが登場する以前はAWS IoT Greengrass CoreのLambda(Greengrass Lambda)でAWS_CONTAINER_CREDENTIALS_FULL_URIが使われており、Greengrass LambdaはVPC外であるローカルデバイス上での実行となるため絶対URLを使っている様に見受けられます。(確証はありませんが...)
AWS CloudShellも通常のVPCとは異なるネットワークのため絶対URLを採用したのだと予想されます。

AWS_CONTAINER_CREDENTIALS_FULL_URI が使えるツール、SDK

なんとなくAWS_CONTAINER_CREDENTIALS_FULL_URIAWS_CONTAINER_CREDENTIALS_RELATIVE_URIの違いについて予測はついたのですが、問題となるのはAWS_CONTAINER_CREDENTIALS_FULL_URIは現時点ですべてのツールやSDKが対応していない点となります。

AWS_CONTAINER_CREDENTIALS_FULL_URIはGreengrass Lambdaで使われてきた経緯もあるため、Greengrass Lambdaが対応している

  • Python (botocore)
  • Java (AWS SDK for Java)
  • Node (AWS SDK for JavaScript )
  • C, C++ (AWS SDK for C++) : ドキュメントにないがGitHubのソースを見ると対応してるっぽい

のSDKでは既に利用可能の様です。

AWS CLIはPython製(botocore基盤)ですので特別な処理なくAWS_CONTAINER_CREDENTIALS_FULL_URIが使え認証情報が取得できていた模様です。
そしてAWS Tools for PowerShellはC#製(AWS SDK for .NET使用)であり、AWS SDK for .NETは2020年12月21日リリースのVer.3.5.78.1でAWS_CONTAINER_CREDENTIALS_FULL_URIをサポートしたばかりであり、AWS Tools for PowerShellには当時反映されていませんでした。

このためAWS CloudShellではAWS CLIはデフォルトで認証情報が連動するもののAWS Tools for PowerShellでは連動しないことになっていた模様です。

余談 : AWS Tools for PowerShellの対応状況

ちなみにAWS Tools for PowerShellではつい先日AWS_CONTAINER_CREDENTIALS_FULL_URIの対応がコミットされました。

現在最新のVer.4.1.7.0からAWS_CONTAINER_CREDENTIALS_FULL_URIに対応しています。
早速手元の環境のバージョンを更新しましたがAWS Tools for PowerShellもちゃんと認証情報が連動してくれました。

最後に

以上となります。

この記事で伝えたい主題は特に無いのですがそれなりの時間をかけて調べてたのでブログに記録しておくことにしました。
ちょっとしたトリビア程度に思っていただければ幸いです。

脚注

  1. あくまでもそう見えるだけであり実際に何であるかは不明