AWS CloudShell上でaws configure export-credentialsを実行して取得した一時クレデンシャルをローカル端末で使ってみた
コンバンハ、千葉(幸)です。
AWS CloudShell、便利ですよね。
AWS CloudShellはAWSマネジメントコンソール上で操作可能なシェル実行環境です。AWS CloudShell上には「AWSマネジメントコンソールを操作しているIAMユーザーやIAMロールなど」のプリンシパルの一時クレデンシャルがあらかじめセットされています。[1]
AWS CLIやAWS SDKなどをローカル端末で操作したくない時に実行環境として便利です。「単発での作業のために専用のプロファイルを作りたくない」「IAMユーザーで永続的なクレデンシャルを払い出したくない」といったケースです。
一方で、AWS CloudShellを使うのも少し面倒だ、という場合もあります。AWS CloudShellとローカルの端末でデータのアップロード/ダウンロードを行うケースです。「スクリプトがローカルに用意してあるのでそれをそのまま使いたい」「処理の結果AWS CloudShell上に生成されたデータをダウンロードしてくるのが面倒」といったこともあるでしょう。
作業効率の観点で以下を両立したい時があります。
- 当該作業のためにローカル端末でAWS CLIの新規プロファイルを作成したくない
- ローカル端末とAWS CloudShell間でデータのやり取りをしたくない
それを実現すべく、今回は「AWS CloudShell上にセットされている一時クレデンシャルをローカルの操作端末にセットする」というアプローチを試してみます。なお。ローカル端末にはmacOSを想定しています。
先にまとめ
- AWS CloudShell上ではAWSマネジメントコンソールを操作するプリンシパルから生成された一時クレデンシャルがセットされている
- IAMユーザーの場合:GetSessionTokenによって生成されたセッション
- IAMロールの場合:AssumeRoleによって生成されたセッション
- AWS CloudShell上で以下操作を行うことで当該クレデンシャルを取得できる
curl -s \
-H "Authorization: $AWS_CONTAINER_AUTHORIZATION_TOKEN" \
"$AWS_CONTAINER_CREDENTIALS_FULL_URI"
- 以下のようにパイプで渡せばそのままローカル端末にペーストできる形式で結果が出力される
curl -s -H "Authorization: $AWS_CONTAINER_AUTHORIZATION_TOKEN" "$AWS_CONTAINER_CREDENTIALS_FULL_URI" | jq -r '
"export AWS_ACCESS_KEY_ID=\(.AccessKeyId)
export AWS_SECRET_ACCESS_KEY=\(.SecretAccessKey)
export AWS_SESSION_TOKEN=\(.Token)"
'
aws configure export-credentials
を使えばもっとシンプルに一時クレデンシャルを取得できる
$ aws configure export-credentials --format env
export AWS_ACCESS_KEY_ID=ASIAxxxx...
export AWS_SECRET_ACCESS_KEY=KiJwl....
export AWS_SESSION_TOKEN=IQoJ...
export AWS_CREDENTIAL_EXPIRATION=2025-07-07T02:49:04+00:00
- AWS CloudShell上で取得できる一時クレデンシャルの有効期間は4分〜15分程度
AWS CloudShellと一時クレデンシャルについておさらい
AWS CloudShellの裏側について少しおさらいしておきましょう。こちらのエントリに詳しいです。
画像は上記エントリより引用
セッションレポートの文章を引用します。
CloudShellがどのように動作するかの概要は次のとおりです。
まず、マネジメントコンソールにログインし、CloudShellセッションを開始します。 Web UI はCloudShellへのAPIコールを行います。 CloudShellが新しいCloudShell用のコンピュート環境をプロビジョニングします。
コンピュート環境はセッションごとにオンデマンドで作成されます。 これは Lambda Function のようなものと考えることができますが、CloudShellセッションが生きている限りコンピュート環境は存在し続けます。 コンピュート環境はVPC上で稼働しています。アウトバウンドのネットワークは許可されていますが、インバウンドのネットワークは許可されていません。
コンピュート環境が用意されると、 Systems Manager を利用して、Webブラウザ上のWeb UIとコンピュート環境との間に双方向の通信チャネルが作成されます。 Web UIにコマンドを入力すると、SSMのWebSocket接続を使ってバックエンドのコンピュート環境に通信し、コンピュート環境でコマンドが実行されます。
AWS CloudShellのコンピュート環境が(Amazonが管理する)VPC上で動いており、利用者はSystems Manager経由でそれにアクセスできる、ということですね。このコンピュート環境というのは環境変数などから見るにECSで動いていそうです。
いくつか環境変数を抜粋するとこのような情報が得られます。
~ $ env | grep AWS
AWS_CONTAINER_CREDENTIALS_FULL_URI=http://127.0.0.1:1338/latest/meta-data/container/security-credentials
AWS_EXECUTION_ENV=CloudShell
AWS_EC2_METADATA_DISABLED=true
AWS_DEFAULT_REGION=ap-northeast-1
AWS_REGION=ap-northeast-1
MDE_UPDATE_SCRIPT=env | grep -m 1 AWS_REGION | grep -Eo '[a-z0-9-]*' | sudo tee /etc/dnf/vars/awsregion && sudo dnf -y update --security
AWS_PAGER=less -K
AWS_SDK_JS_SUPPRESS_MAINTENANCE_MODE_MESSAGE=true
AWS_CONTAINER_AUTHORIZATION_TOKEN=mKBEHxxxxxxxxxxxx...
AWS_TOOLING_USER_AGENT=AWS-CloudShell/2025.04.17
ここで確認できるトークンやURIを使用し、curlでクレデンシャルを取得できます。
curl -s \
-H "Authorization: $AWS_CONTAINER_AUTHORIZATION_TOKEN" \
"$AWS_CONTAINER_CREDENTIALS_FULL_URI"
実行イメージは以下です。
$ curl -s \
> -H "Authorization: $AWS_CONTAINER_AUTHORIZATION_TOKEN" \
> "$AWS_CONTAINER_CREDENTIALS_FULL_URI"
{
"Type": "",
"AccessKeyId": "ASIA....",
"SecretAccessKey": "Rgfxxxxxxx....",
"Token": "CVA=z.......",
"Expiration": "2025-07-07T01:42:50Z",
"Code": "Success"
}
パイプで渡してjqで加工すれば、コピーペーストで環境変数にセット可能な形で出力されます。
curl -s -H "Authorization: $AWS_CONTAINER_AUTHORIZATION_TOKEN" "$AWS_CONTAINER_CREDENTIALS_FULL_URI" | jq -r '
"export AWS_ACCESS_KEY_ID=\(.AccessKeyId)
export AWS_SECRET_ACCESS_KEY=\(.SecretAccessKey)
export AWS_SESSION_TOKEN=\(.Token)"
'
~ $ curl -s -H "Authorization: $AWS_CONTAINER_AUTHORIZATION_TOKEN" "$AWS_CONTAINER_CREDENTIALS_FULL_URI" | jq -r '
> "export AWS_ACCESS_KEY_ID=\(.AccessKeyId)
> export AWS_SECRET_ACCESS_KEY=\(.SecretAccessKey)
> export AWS_SESSION_TOKEN=\(.Token)"
> '
export AWS_ACCESS_KEY_ID=ASIA....
export AWS_SECRET_ACCESS_KEY=gX6H....
export AWS_SESSION_TOKEN=IQoJb....
これをローカル端末で実行すれば、AWS CloudShell上で使用された一時クレデンシャルをローカルで利用できます。
~ % export AWS_ACCESS_KEY_ID=ASIA....
export AWS_SECRET_ACCESS_KEY=gX6H....
export AWS_SESSION_TOKEN=IQoJb....
~ % aws sts get-caller-identity
{
"UserId": "AROA....:cm-chiba.yukihiro",
"Account": "012345678910",
"Arn": "arn:aws:sts::012345678910:assumed-role/cm-chiba.yukihiro/cm-chiba.yukihiro"
}
今回はAWSマネジメントコンソールをIAMロールにスイッチして操作していたので、そのIAMロールから生成されたセッションプリンシパルとして操作可能な状態になっています。
ちなみに、AWS CloudShellを起動したプリンシパルがcloudshell:PutCredentials
アクションの許可を持っていないとコンピュート環境にクレデンシャル情報を転送できないようになっています。
IAMユーザーでAWS CloudShellを操作する時に使われているクレデンシャルは何?
IAMユーザーで一時クレデンシャルを発行する、となると手法は2つあります。
GetFederationToken
GetSessionToken
AWSマネジメントコンソールにIAMユーザーとしてサインインしてAWS CloudShellを起動した場合、どちらのパターンで一時クレデンシャルが生成されるのかが気になりました。確認してみました。
取得した一時認証情報を環境変数にセットしたのちにaws sts get-caller-identity
で確認すると、ArnはIAMユーザーと同じものになっています。
~ $ aws sts get-caller-identity
{
"UserId": "AIDAxxxxxxxxxxxxx",
"Account": "012345678910",
"Arn": "arn:aws:iam::012345678910:user/Batchi"
}
念のためaws sts get-session-token
を試みると、エラーになりました。
~ $ aws sts get-session-token
An error occurred (AccessDenied) when calling the GetSessionToken operation: Cannot call GetSessionToken with session credentials
ということで、GetSessionToken
によって生成された一時クレデンシャルであることがわかりました。
GetFederationToken
によって生成されたものである場合、Arnにはarn:aws:sts::000000000000:federated-user/test
のようにfederated-user
が含まれるためです。
このあたりの詳細は以下をご参照ください。
aws configure export-credentialsで楽にクレデンシャルを出力する
aws configure export-credentials
というコマンドがあります。クレデンシャルをさまざまなフォーマットで出力できるものです。AWS CLI v1では存在せず、AWS CLI v2でのみ利用可能です。
用途を考えると、以下のオプションをつけることが多くなると思います。
--format
:出力するフォーマットを選択--profile
:出力するプロファイルを選択
今回は「AWS CloudShellを操作しているプリンシパルの一時クレデンシャルを取得する」なので、--profile
は省略します。複数プロファイルが設定されている端末で使う際には、別の端末、別のターミナルでの作業用に出しわけする、という使い方も便利そうです。
話は戻って、--format
です。
特に指定なしだと、--format process
を指定した場合と同様の結果になります。
~ $ aws configure export-credentials
{
"Version": 1,
"AccessKeyId": "ASIA....",
"SecretAccessKey": "UCJ....",
"SessionToken": "IQoJb....",
"Expiration": "2025-07-07T04:44:05+00:00"
}
これはAWS CLIコンフィグのcredential_process
での使用に対応したフォーマットです。以下のように使えます。
[profile myprofile]
output=json
region=ap-northeast-1
role_arn=arn:aws:iam::01234567890:role/sato.masaki
mfa_serial=arn:aws:iam::12345678901:mfa/sato.masaki
[profile myprofile-tf]
credential_process = aws configure export-credentials --profile myprofile
そして今回の用途では--format env
の利用を想定しています。
$ aws configure export-credentials --format env
export AWS_ACCESS_KEY_ID=ASIA...
export AWS_SECRET_ACCESS_KEY=UCJY...
export AWS_SESSION_TOKEN=IQoJb....
export AWS_CREDENTIAL_EXPIRATION=2025-07-07T04:44:05+00:00
👆出力された結果をコピーしてローカル端末にペーストして実行すれば、一時クレデンシャルのセットが簡単に行えます。
おまけとして、そのほかのフォーマットの結果も記しておきます。
折りたたみ
--format env-no-export
の場合。
$ aws configure export-credentials --format env-no-export
AWS_ACCESS_KEY_ID=ASIA...
AWS_SECRET_ACCESS_KEY=Aga6X...
AWS_SESSION_TOKEN=IQoJ...
AWS_CREDENTIAL_EXPIRATION=2025-07-07T04:51:05+00:00
--format powershell
の場合。
$ aws configure export-credentials --format powershell
$Env:AWS_ACCESS_KEY_ID="ASIA..."
$Env:AWS_SECRET_ACCESS_KEY="Aga..."
$Env:AWS_SESSION_TOKEN="IQoJb..."
$Env:AWS_CREDENTIAL_EXPIRATION="2025-07-07T04:51:05+00:00"
--format windows-cmd
の場合。
$ aws configure export-credentials --format windows-cmd
set AWS_ACCESS_KEY_ID=ASIA...
set AWS_SECRET_ACCESS_KEY=Aga6...
set AWS_SESSION_TOKEN=IQoJb...
set AWS_CREDENTIAL_EXPIRATION=2025-07-07T04:51:05+00:00
AWS CloudShell上で取得できる一時クレデンシャルの有効期間はどの程度か?
ここまで「AWS CloudShell上で取得した一時クレデンシャルをローカルの操作端末にセットして用いる」方法を見てきました。
果たしてその一時クレデンシャルはどの程度有効なのかが気になります。長すぎるとリスクが増えますし、短すぎると作業に差し支えが出ます。
取得できる情報にはExpiration
が含まれているので、これを基に有効期間を算出してみます。
以下のコマンドを実行してしばらく流してみます。
while true; do
e=$(curl -s -H "Authorization: $AWS_CONTAINER_AUTHORIZATION_TOKEN" "$AWS_CONTAINER_CREDENTIALS_FULL_URI" | jq -r .Expiration)
echo "Expiration: $e, Remaining: $(( $(date -ud "$e" +%s) - $(date -u +%s) )) sec"
sleep 5
done
(aws configure export-credentials
で実行する場合はこのような形。)
while true; do
e=$(aws configure export-credentials --format process | jq -r .Expiration)
echo "Expiration: $e, Remaining: $(( $(date -ud "$e" +%s) - $(date -u +%s) )) sec"
sleep 5
done
このような形で有効期限と残り秒数が表示され続けます。何サイクルか実行してみると、多少更新のタイミングにばらつきはあるようでした。
...
Expiration: 2025-07-07T05:05:05Z, Remaining: 368 sec
Expiration: 2025-07-07T05:05:05Z, Remaining: 363 sec
Expiration: 2025-07-07T05:05:05Z, Remaining: 358 sec
Expiration: 2025-07-07T05:12:04Z, Remaining: 772 sec
Expiration: 2025-07-07T05:12:04Z, Remaining: 767 sec
...
...
Expiration: 2025-07-07T05:12:04Z, Remaining: 486 sec
Expiration: 2025-07-07T05:12:04Z, Remaining: 481 sec
Expiration: 2025-07-07T05:12:04Z, Remaining: 476 sec
Expiration: 2025-07-07T05:19:05Z, Remaining: 892 sec
Expiration: 2025-07-07T05:19:05Z, Remaining: 887 sec
...
...
Expiration: 2025-07-07T05:19:05+00:00, Remaining: 310 sec
Expiration: 2025-07-07T05:19:05+00:00, Remaining: 304 sec
Expiration: 2025-07-07T05:19:05+00:00, Remaining: 298 sec
Expiration: 2025-07-07T05:26:05+00:00, Remaining: 712 sec
Expiration: 2025-07-07T05:26:05+00:00, Remaining: 707 sec
...
観測した範囲では取得してから有効期限を迎えるまでの期間が4分〜15分の間におさまるようでした。
まとめ
- AWS CloudShell上ではAWSマネジメントコンソールを操作するプリンシパルから生成された一時クレデンシャルがセットされている
- IAMユーザーの場合:GetSessionTokenによって生成されたセッション
- IAMロールの場合:AssumeRoleによって生成されたセッション
- AWS CloudShell上で以下操作をすることで一時クレデンシャルを取得できる
curl -s -H "Authorization: $AWS_CONTAINER_AUTHORIZATION_TOKEN" "$AWS_CONTAINER_CREDENTIALS_FULL_URI"
aws configure export-credentials
- 取得した一時クレデンシャルをローカル端末にセットすればAWSマネジメントコンソールを操作するプリンシパルと同等の権限で操作できる
- AWS CloudShell上で取得した一時認証情報の有効期限は4分~15分程度
終わりに
AWS CloudShell上で使用できる一時クレデンシャルをローカルの操作端末にセットして使ってみる、という話でした。
単発の作業の際など、以下を両立させたい場合に試してみてください。
- 当該作業のためにローカル端末でAWS CLIの新規プロファイルを作成したくない
- ローカル端末とAWS CloudShell間でデータのやり取りをしたくない
なお、一時認証情報の有効期限はそこまで長くないので、単発でサッと終わる作業にだけ使うなど使い所は見極めが必要そうです。セキュリティも考慮の上、お役立てください。
以上、チバユキ (@batchicchi)がお送りしました。
プリンシパルに、必要な権限
cloudshell:PutCredentials
が付与されている場合に限ります。 ↩︎