13
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

aws loginのクレデンシャルが15分で切れる問題を解決した話

Posted at

はじめに

boto3を使ったPythonアプリケーションで、aws loginコマンドで認証したのに、15分くらいで「クレデンシャルが期限切れです」というエラーが出て困っていました。

調べてみると、awscrtライブラリのバージョンが古いことが原因で、クレデンシャルの自動更新が失敗していたことが判明しました。

この記事では、問題の原因と解決方法を共有します。同じ問題で困っている方の参考になれば幸いです!

aws loginとは?

aws loginは、AWS CLI 2.15.0以降で追加された比較的新しいコマンドです。

従来の認証方法との違い

従来の方法(aws sso login):

aws sso login --profile my-profile
  • AWS IAM Identity Center(旧AWS SSO)を使用
  • 組織のSSOポータルにアクセスして認証

新しい方法(aws login):

aws login
  • AWS Management Consoleの認証情報を直接使用
  • ブラウザでAWSコンソールにログインするのと同じ感覚
  • より直感的で簡単

aws loginの特徴

  • 🔐 リフレッシュトークン対応: 一度ログインすれば、自動的にクレデンシャルが更新される(はず)
  • 🚀 シンプル: プロファイル設定が不要
  • 🔄 boto3と連携: Pythonアプリケーションから透過的に使える

発生した問題

症状

boto3を使ったPythonアプリケーションで、以下のような問題が発生していました:

import boto3

session = boto3.Session()
sts = session.client('sts')

# 最初は成功
identity = sts.get_caller_identity()
print(f"Account: {identity['Account']}")  # OK

# 15分後...
identity = sts.get_caller_identity()  # ❌ エラー!

エラーメッセージ:

ExpiredTokenException: The security token included in the request is expired

期待していた動作

boto3は、クレデンシャルの有効期限が近づくと、自動的にリフレッシュトークンを使って新しいクレデンシャルを取得してくれるはずでした。

しかし、実際にはリフレッシュが失敗していて、15分でクレデンシャルが期限切れになっていました。

原因の調査

1. クレデンシャルの確認

まず、boto3がどのクレデンシャルを使っているか確認しました:

import boto3

session = boto3.Session()
credentials = session.get_credentials()

print(f"プロバイダー: {credentials.method}")
# 出力: login

print(f"リフレッシュ可能: {isinstance(credentials, RefreshableCredentials)}")
# 出力: True

boto3は正しくloginプロバイダーを認識していて、リフレッシュ可能なクレデンシャルとして扱っていました。

2. キャッシュファイルの確認

aws loginのクレデンシャルは、以下の場所にキャッシュされています:

~/.aws/login/cache/<hash>.json

中身を見ると、リフレッシュトークンも正しく保存されていました:

{
  "accessToken": {
    "accessKeyId": "ASIA************",
    "secretAccessKey": "**********************",
    "sessionToken": "**********************",
    "expiresAt": "2026-01-05T07:12:30Z"
  },
  "refreshToken": "**********************",
  "dpopKey": "-----BEGIN EC PRIVATE KEY-----\n..."
}

3. リフレッシュの動作確認

有効期限を強制的に短くして、リフレッシュが実行されるか確認しました:

import boto3
import json
from datetime import datetime, timedelta, timezone

# キャッシュファイルを読み込み
cache_file = "~/.aws/login/cache/<hash>.json"
with open(cache_file, 'r') as f:
    token_data = json.load(f)

# 有効期限を1分後に設定
new_expiry = datetime.now(timezone.utc) + timedelta(minutes=1)
token_data['accessToken']['expiresAt'] = new_expiry.strftime('%Y-%m-%dT%H:%M:%SZ')

# キャッシュファイルを更新
with open(cache_file, 'w') as f:
    json.dump(token_data, f)

# boto3で新しいセッションを作成
session = boto3.Session()
sts = session.client('sts')

# STS呼び出し(リフレッシュがトリガーされるはず)
identity = sts.get_caller_identity()

すると、以下のエラーが発生しました:

AttributeError: type object 'EC' has no attribute 'decode_der_signature_to_padded_pair'

これが原因でした!

4. 根本原因の特定

boto3のソースコードを確認すると、aws loginのリフレッシュ処理では、DPoP(Demonstrating Proof-of-Possession)ヘッダーを生成する必要があることがわかりました。

このヘッダー生成に、awscrtライブラリのECクラスが使われているのですが、古いバージョン(0.28.4)では必要なメソッドが存在しないことが判明しました。

# botocore/credentials.py の該当部分(簡略化)
from awscrt.auth import EC

def _build_dpop_header(private_key, uri):
    # ...
    signature_bytes = EC.decode_der_signature_to_padded_pair(
        signature_der, EC.CurveType.SECP384R1
    )  # ← このメソッドが awscrt 0.28.4 には存在しない!

解決方法

ライブラリのアップグレード

解決方法は簡単で、awscrtライブラリをアップグレードするだけでした:

pip install --upgrade awscrt botocore boto3

アップグレード後のバージョン

awscrt: 0.28.4 → 0.30.0
botocore: 1.42.19 → 1.42.21
boto3: 1.42.19 → 1.42.21

requirements.txtへの追加

今後同じ問題が起きないように、requirements.txtに最小バージョンを指定しました:

# AWS credentials refresh support
# awscrt >= 0.30.0 is required for aws login credential auto-refresh
awscrt>=0.30.0
boto3>=1.42.21
botocore>=1.42.21

確認結果

確認スクリプト

アップグレード後、リフレッシュが正常に動作するか確認しました:

# test_credential_refresh.py
import boto3
import json
from datetime import datetime, timedelta, timezone

print("=" * 80)
print("クレデンシャル自動更新テスト")
print("=" * 80)

# キャッシュファイルのパス
cache_file = "~/.aws/login/cache/<hash>.json"

# 有効期限を1分後に設定(リフレッシュを強制)
with open(cache_file, 'r') as f:
    token_data = json.load(f)

original_access_key = token_data['accessToken']['accessKeyId']
print(f"元のアクセスキー: {original_access_key[:15]}...")

new_expiry = datetime.now(timezone.utc) + timedelta(minutes=1)
token_data['accessToken']['expiresAt'] = new_expiry.strftime('%Y-%m-%dT%H:%M:%SZ')

with open(cache_file, 'w') as f:
    json.dump(token_data, f)

# boto3セッションを作成
session = boto3.Session()
sts = session.client('sts')

# STS呼び出し(リフレッシュがトリガーされる)
print("\nSTS呼び出しを実行...")
identity = sts.get_caller_identity()
print(f"✓ 成功: {identity['Account']}")

# リフレッシュ後のキャッシュファイルを確認
with open(cache_file, 'r') as f:
    refreshed_token = json.load(f)

refreshed_access_key = refreshed_token['accessToken']['accessKeyId']
print(f"\nリフレッシュ後のアクセスキー: {refreshed_access_key[:15]}...")

if refreshed_access_key != original_access_key:
    print("\n✓✓✓ 新しいクレデンシャルが取得されました!")
    print("リフレッシュが正常に動作しています!")
else:
    print("\n✗ クレデンシャルは更新されませんでした")

print("=" * 80)

実行結果

================================================================================
クレデンシャル自動更新テスト
================================================================================
元のアクセスキー: ASIATBMRO57RNGQ...

STS呼び出しを実行...
✓ 成功: **********

リフレッシュ後のアクセスキー: ASIATBMRO57RJ4I...

✓✓✓ 新しいクレデンシャルが取得されました!
リフレッシュが正常に動作しています!
================================================================================

完璧です! 新しいアクセスキーが取得され、リフレッシュが正常に動作していることが確認できました。

boto3のリフレッシュタイミング

boto3は、以下のタイミングでクレデンシャルのリフレッシュを試みます:

タイミング 説明 失敗時の動作
Advisory Refresh 有効期限の15分前 既存のクレデンシャルを使い続ける
Mandatory Refresh 有効期限の10分前 エラーを返す
aws login特有 有効期限の5分前 エラーを返す

つまり、有効期限の5分前から自動的にリフレッシュされるため、15分で切れる問題は解消されました。

まとめ

問題の原因

aws loginのクレデンシャルが15分で切れる原因は、awscrtライブラリのバージョンが古かったことでした。

  • awscrt 0.28.4では、DPoPヘッダー生成に必要なメソッドが存在しない
  • そのため、リフレッシュ時にエラーが発生していた
  • boto3は自動更新に失敗し、クレデンシャルが期限切れになっていた

解決方法

pip install --upgrade awscrt botocore boto3

たったこれだけで、クレデンシャルの自動更新が正常に動作するようになりました!

ポイント

  • ✅ awscrt >= 0.30.0 が必須
  • ✅ boto3/botocore も最新版を推奨
  • ✅ クレデンシャルは有効期限の5分前から自動更新される
  • ✅ リフレッシュトークンが有効な限り、再ログイン不要

参考情報

おわりに

aws loginは比較的新しい機能なのでまだ情報が少なく、Kiroに確認してもなぜかaws sso loginを進められたり、credentialsconfigファイルの修正が繰り返されていました・・・

この記事が、同じ問題に遭遇した方の助けになれば嬉しいです!

13
3
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
13
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?