CloudShellからassumed-roleの認証情報で7日間有効なS3署名付きURLは作れません
はじめに
かつまたです。
CloudShell から S3署名付き URLを--expires-in に最大値の 7 日を指定したのに、実際の有効期限はそれより短かった場面に遭遇しました。
この事象に要因や回避策を調査してみたのでご紹介します。
事象
CloudShell 上で、対象オブジェクトに対して 7 日有効を期待して署名 URL を発行しました。
aws s3 presign s3://my-bucket/report.csv --expires-in 604800
発行された URL は問題なく開けるのですが、配布からしばらく経過(完全に7日未満)すると、アクセス時に次のような ExpiredToken エラーが返るようになりました。
<Error>
<Code>ExpiredToken</Code>
<Message>The provided token has expired.</Message>
</Error>
--expires-in には 604800 秒を指定しているにもかかわらず、実際には数時間程度で失効していました。S3 バケットのライフサイクルやバケットポリシーには、有効期限を縛るような設定は入れていません。
原因
Presigned URL の有効期限は、--expires-in で指定した値と、署名に使った認証情報そのものの有効期限のうち、早く到来する方で打ち切られルようでした。
CloudShell は IAM ロールを引き受けた一時認証情報で動作しています。
aws sts get-caller-identity --query Arn --output text
arn:aws:sts::123456789012:assumed-role/xxxxxxxx/xxxxxxxx
この一時認証情報で署名すると、URL のクエリ文字列に X-Amz-Security-Token が含まれます。S3 はアクセス時にこのトークンの有効性を確認するため、セッションが失効した時点で URL も無効になります。AssumeRole のセッションはデフォルトで 1 時間(最大でもロールの MaxSessionDuration まで)のため、7 日を指定しても 1 時間で切れていた、というわけです。
対応内容
期待する有効期限を確保するには、署名に使う認証情報の有効期限を、欲しい URL 有効期限以上にする必要があります。2つの方法を試してみました。
1. AssumeRole のセッション有効期限を延ばす
一時認証情報のまま、ロールのセッション時間を延ばす方法です。対象ロールの MaxSessionDuration を必要な長さまで引き上げます。上限は 12 時間(43200 秒)です。
aws iam update-role --role-name <ロール名> --max-session-duration 43200
そのうえで aws sts assume-role の --duration-seconds に同じ長さを指定して認証情報を取得し、その認証情報で署名します。
2. IAM ユーザーの長期アクセスキーで署名する(7 日まで)
一時認証情報ではなく IAM ユーザーのアクセスキーで署名します。SigV4 では、IAM ユーザーの認証情報で署名した URL は最大 7 日まで有効です。
なお、アクセスキーはセキュリティ推奨されないため、最小権限及び、利用時の一時作成などを推奨します。
以下のように Cloudshell 上でアクセスキーを指定し、URLを作成していきます。
AWS_ACCESS_KEY_ID=AKIAxxxxxxxxxxxxxxxx \
AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx \
AWS_SESSION_TOKEN= \
aws s3 presign s3://my-bucket/report.csv --expires-in 604800
動作確認
発行した URL の有効性は GET で確認します。aws s3 presign はデフォルトで GET メソッドを含めて署名するため、curl -I(HEAD)では署名不一致で 403 になります。検証は GET で行ってください。
curl -s -o /dev/null -w "HTTP %{http_code}\n" "$URL"
HTTP 200 が返れば有効です。
おわりに
ご覧いただきありがとうございました。
CloudShell や踏み台の assumed-role でそのまま aws s3 presign を実行すると、--expires-in をいくら大きくしてもセッション失効で URL が切れてしまいます。これは S3 側の設定ではなく、署名に使った認証情報の有効期限に縛られる SigV4 の仕様です。
12 時間程度で足りるなら AssumeRole のセッション延長で、7 日有効が必要なら IAM ユーザーの長期キーで署名、と使い分けるのがおすすめです。同じ事象で URL が早く切れて困っている方の参考になれば幸いです。
クラスメソッドオペレーションズ株式会社について
クラスメソッドグループのオペレーション企業です。
運用・保守開発・サポート・情シス・バックオフィスの専門チームが、IT・AIをフル活用した「しくみ」を通じて、お客様の業務代行から課題解決や高付加価値サービスまでを提供するエキスパート集団です。
当社は様々な職種でメンバーを募集しています。
「オペレーション・エクセレンス」と「らしく働く、らしく生きる」を共に実現するカルチャー・しくみ・働き方にご興味がある方は、クラスメソッドオペレーションズ株式会社 コーポレートサイト をぜひご覧ください。
※2026年1月 アノテーション㈱から社名変更しました







