boto3でAWS WAFのIPリストが取得できない件
はじめに
ちょっとしたトラブルシューティングの記事になります。
使ったもの
使ったもの | バージョン |
---|---|
macOS | Sonoma 14.2 |
Python | 3.9系 |
boto3 | 1.34.110 |
何があったのか?
CloudFrontに設定してあるWAFv2から、指定したIPリストを取得するという非常にシンプルな処理を実装しようとしていました。で、boto3 WAFv2のドキュメントを読んでみて、「ああ、このget_ip_set()
って関数使えばいいんだ〜」と思い早速実装してみました。
def get_ip_set_list() -> List:
client = boto3.client('wafv2')
IP_SET_NAME = 'IP_SET_NAME'
Scope = 'CLOUDFRONT'
Id = 'IP_SET_ID'
response = client.get_ip_set(
Name=IP_SET_NAME,
Scope=Scope,
Id=Id
)
return response['IPSet']['Addresses']
def main():
ip_set = get_ip_set_list()
print(ip_set)
if __name__ == '__main__':
main()
が、実行すると何故かエラーが発生。
botocore.errorfactory.WAFInvalidParameterException: An error occurred (WAFInvalidParameterException) when calling the GetIPSet operation: Error reason: The scope is not valid., field: SCOPE_VALUE, parameter: CLOUDFRONT
SCOPEのCLOUDFRONTがどうやら無効とのことです。
ドキュメントには下記のように、スコープには「CLOUDFRONT」と「REGIONAL」が指定できるように見受けられますし、それ以外のパラメータはどこにも書いてありません...🧐
response = client.get_ip_set(
Name='string',
Scope='CLOUDFRONT'|'REGIONAL',
Id='string'
)
解決方法
get_ip_set()
関数の引数の欄をもう少し注意深く見てみると、下記記述がありました。
To work with CloudFront, you must also specify the Region US East (N. Virginia) as follows:
CLI - Specify the Region when you use the CloudFront scope: --scope=CLOUDFRONT --region=us-east-1.
API and SDKs - For all calls, use the Region endpoint us-east-1.
(日本語訳)
CloudFrontを使用するには、以下のようにRegion US East (N. Virginia)も指定する必要があります:
CLI - CloudFrontスコープを使用する際にRegionを指定します: --scope=CLOUDFRONT --region=us-east-1.
APIとSDK - すべてのコールで、Regionエンドポイントus-east-1を使用します。
SCOPEでCLOUDFRONTを指定するには、regionにus-east-1を指定しろと懇切丁寧に書いてあるじゃないですか!そもそもWAFv2のドキュメントのトップページにも書いてあります。
For Amazon CloudFront applications, you must use the API endpoint listed for US East (N. Virginia): us-east-1.
(日本語訳)
Amazon CloudFrontアプリケーションでは、US East (N. Virginia)のAPIエンドポイントus-east-1を使用する必要があります。
オイオイオイ、ここまでくると私の目が節穴すぎて恥ずかしい。
で、結局以下のコードで実装したところ、なんとか実行することができました。
adef get_ip_set_list() -> List:
### us-east-1追加 ###
client = boto3.client('wafv2', region_name='us-east-1')
####################
IP_SET_NAME = 'IP_SET_NAME'
Scope = 'CLOUDFRONT'
Id = 'IP_SET_ID'
response = client.get_ip_set(
Name=IP_SET_NAME,
Scope=Scope,
Id=Id
)
return response['IPSet']['Addresses']
def main():
ip_set = get_ip_set_list()
print(ip_set)
if __name__ == '__main__':
main()
['1.1.1.1/32', '2.2.2.2/32' .....<長いので割愛>
おわりに
ドキュメントは丁寧に読みましょうね...。
参考資料
Discussion