DynamoDBの操作を効率的にコーディングする方法を調べていたら、突然以下のエラーに襲われました。
botocore.exceptions.ClientError: An error occurred (UnrecognizedClientException) when calling the ListTables operation: The security token included in the request is invalid.
このエラー自体は何度か見たことがあり、credentialに問題があると思ったのですが、~/.aws/credentialsを見ても特におかしなところは無く、IAMでも有効となっていました。何かの有効期限に引っ掛かったのかと思い、新しいアクセスキーを作成して設定しても状況は変わらず。
import os
os.environ['AWS_DEFAULT_PROFILE'] = 'ttkiida'
コードの最初でプロファイルを指定してもダメでした。ここまで来たらどこかで謎のcredentialが指定されているとしか思えないので、エラーの出る直前で環境変数を表示してみたところ…。
'AWS_ACCESS_KEY_ID': 'foobar_key', 'AWS_SECRET_ACCESS_KEY': 'foobar_secret'
何だこの値は?! 変なパッケージを読み込んでいたのか? ネットで調べてみると…。
from moto import mock_dynamodb2
このインポート文を残していたことが原因だと判りました。これはBoto3のモックライブラリであるMotoというもので、色々試しているうちに削除やコメントアウトされず残ってしまっていたのです。
os.environ.setdefault("AWS_ACCESS_KEY_ID", "foobar_key")
os.environ.setdefault("AWS_SECRET_ACCESS_KEY", "foobar_secret")
こんなコードがMotoに含まれており、このせいでcredentialが上書きされてしまってたんですね。ユニットテストの時にcredentialをダミーの値にしておくというのは私もよくやっているので、Motoにこのコードがあるのは納得なのですが、PyCharmで「未使用のimport文」としてグレーアウトされていてので気付けませんでした。ということで、不要なimport文には要注意!