boto3が~/.aws/credentialsのaws_session_tokenを見ないで毎回`Enter MFA code:`と聞いてくるのをなんとかする方法


はじめに

AWSのroleを使っていてMFAが設定してあり、boto3を使いつつLocal環境開発時の鬱陶しさ軽減の話です。

※ よく見ると ISSUE: https://github.com/boto/botocore/issues/1126 になっていますね。いずれ修正されるのでしょう。

Version

  • boto3==1.4.4
  • botocore==1.5.7

ちょっと古いです。

内容

Pythonのboto3ライブラリは、AWS操作の鉄板ライブラリです。
認証の時にCredentialを色々な箇所から自動的に取得してくれますが、
~/.aws/configrole_arnmfa_serial があると、~/.aws/credentials にキーを設定してあってもその前にAssumeRoleProviderが発動し、Enter MFA code: というプロンプトを表示してMFAの入力を求められてしまいます。

ソースコード を見ると、

  • EnvProvider
  • AssumeRoleProvider
  • SharedCredentialProvider

の順にCredentialをチェックして、AssumeRoleProvider の時にこのプロンプトを表示します。
別途事前にassume-roleを実行していてファイル~/.aws/credentialsに書いてある場合はこの手順はスキップしたいです。

以下のようにするととりあえずできます。

sample.py
from botocore.session import get_session
from boto3.session import Session

bc_session = get_session()
session = Session(botocore_session=bc_session, profile_name="<your profile name>")
cred_resolver = bc_session.get_component('credential_provider')  # type: CredentialResolver

# set assume-role after shared-credentials-file
assume_role = cred_resolver.get_provider("assume-role")
cred_resolver.remove("assume-role")
cred_resolver.insert_after('shared-credentials-file', assume_role)

#
s3 = session.resource("s3")

# for testing
for bucket in s3.buckets.all():
    print(bucket.name)

ちなみにprofile_name の部分は、環境変数AWS_PROFILE で指定してあれば省略可能です。

さいごに

小技でした。