Boto3でAssumeRoleする際にSTSのリージョナルエンドポイントを使用する

こんにちは。サービスグループの武田です。Boto3でAssumeRoleする際にリージョナルエンドポイントを使用する方法を紹介します。
2022.05.23

こんにちは。サービスグループの武田です。

すべてのリージョンでAWS Configを有効化しようとしたところ、ある特定リージョンのみ次のエラーが出て処理が完了できませんでした。

An error occurred (UnrecognizedClientException) when calling the DescribeConfigurationRecorders operation: The security token included in the request is invalid

あるリージョンというのは香港リージョン(ap-east-1)です。香港リージョンのみ処理が失敗すると聞いてピンとくる人もいるでしょうか。たとえば検索すると次のエントリがヒットします。

このエントリにもあるように、オプトインリージョンで正しく処理するためにはSTSエンドポイントに気をつける必要があります。上記のエントリではAWS CLIの場合を解説していましたが、ここではBoto3のケースを紹介します。

Boto3で正しくリージョナルエンドポイントを指定してAssumeRoleする

Boto3では次のように、STSクライアントを取得する際にリージョンを指定することで、リージョナルエンドポイントを使用します。指定リージョンがus-east-1である必要性はないのですが、無効化できない唯一のリージョンのため、速度の問題がないのであればus-east-1がお勧めです。

sts = boto3.client(
    "sts",
    region_name="us-east-1",
    endpoint_url="https://sts.us-east-1.amazonaws.com",
)

res = sts.assume_role(
    RoleArn="arn:aws:iam::123456789012:role/cm-example",
    RoleSessionName="example-session",
)

session = Session(
    aws_access_key_id=res["Credentials"]["AccessKeyId"],
    aws_secret_access_key=res["Credentials"]["SecretAccessKey"],
    aws_session_token=res["Credentials"]["SessionToken"],
    region_name="ap-northeast-1",
)

このエントリで言いたいことはこれだけなのですが、もう少し注意点を紹介します。クライアントを取得する際にregion_nameのみ指定してもうまくいきません。STSではregion_nameの指定だけではリージョナルエンドポイントを使用してくれないようです。

boto3.client("sts", region_name="us-east-1")

またendpoint_urlのみ指定もやはりうまくいきません。

boto3.client("sts", endpoint_url="https://sts.us-east-1.amazonaws.com")

これだと次のようなエラーが発生してしまいました。

An error occurred (SignatureDoesNotMatch) when calling the AssumeRole operation: Credential should be scoped to a valid region.

というわけで、若干面倒ではありますがregion_nameendpoint_urlどちらも指定してあげることで、正しくリージョナルエンドポイントを使用できます。

まとめ

リージョンをオプトインする機会があまりないため、あまり見たことのないエラーに遭遇しました。また解決にあたっても多少試行錯誤が必要でした。どなたかの問題解決の助けになれば幸いです。