みなさん、こんにちは。AWS CLI が好きなテクニカルサポート課の市野です。
マネージドプレフィックスリストを用いたセキュリティグループの管理をご検討のお客様で、ルール数の計算が合わない場面があり、エントリ数の設定などハマりやすいポイントがありましたので、以下、検証時の内容を備忘録として記載します。
また、せっかくですので、大量のデータが CSV ファイルとして存在しているなどの想定で、AWS CLI を利用した手順として作成していますので、大量のルールの管理に苦慮されている場合のご参考となれば幸いです。
想定
- セキュリティグループのルール数については上限緩和しておらず、デフォルトのまま(60)で利用している。
- プレフィックスリストの CIDR とその説明は CSV ファイルで管理されていると想定。(prefixlist-01.csv、prefixlist-02.csv)
- 該当の CSV ファイルから読み取って AWS CLI で一括登録する処理として組み立てる。
- プレフィックスリストは2つ作り、同一のセキュリティグループのインバウンドルールに以下のようにアタッチする。
- 80/TCP → プレフィックスリスト1
- 8080/TCP → プレフィックスリスト2
検証内容
セキュリティグループのルールにマネージドプレフィックスリストを含めた時のルール数のカウント方法の確認
まとめ
少し手順も長く、ブログのエントリ自体が長くなってしまったので、結論を先に。
AWS 公式ドキュメントにも記載があることを確認しましたが、セキュリティグループのルール内からマネージドプレフィックスリストを参照する場合、該当のマネージドプレフィックスリストとして作成する際に設定した最大エントリ数がカウントされます。
実際にエントリとして登録されている CIDR の記述の行数ではない点に注意が必要です。
検証手順
環境
以下の通り、Amazon CloudShell を利用して実行します。
[cloudshell-user@ip-10-0-162-194 ~]$ cat /etc/os-release NAME="Amazon Linux" VERSION="2" ID="amzn" ID_LIKE="centos rhel fedora" VERSION_ID="2" PRETTY_NAME="Amazon Linux 2" ANSI_COLOR="0;33" CPE_NAME="cpe:2.3:o:amazon:amazon_linux:2" HOME_URL="https://amazonlinux.com/" [cloudshell-user@ip-10-0-162-194 ~]$ bash --version GNU bash, version 4.2.46(2)-release (x86_64-koji-linux-gnu) Copyright (C) 2011 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software; you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.
一つ目のプレフィックスリストのための処理
プレフィックスリスト管理表の作成
cat << EOF > prefixlist-01.csv cidr,description 10.0.0.0/27,subnet-1a EOF
プレフィックスリスト管理表から --entries オプション用文字列の生成
ENTRIES="" SEPARATOR="" while read line do ENTRIES+="${SEPARATOR}Cidr=$(cut -d ',' -f 1 <<<$line)," ENTRIES+="Description=$(cut -d ',' -f 2 <<<${line})" if [ "${SEPARATOR}" = "" ]; then SEPARATOR=" " fi done < <(tail -n +2 prefixlist-01.csv) echo ${ENTRIES}
プレフィックスリストの作成
リスト( CSV ファイル)には 1 エントリのみの記載になっているが、将来用に --max-entries を 32 とし、確保しておく想定をしている。
aws ec2 create-managed-prefix-list \ --prefix-list-name prefixlist-01 \ --max-entries 32 \ --address-family IPv4 \ --entries $(echo "${ENTRIES}")
【注意】
--prefix-list-name オプションの入力値は既存のプリフィックスリスト名との重複を考慮していない点に注意が必要です。
重複が起こった場合、後述のプリフィクスリスト ID の取得後の処理でエラーが出るので注意が必要です。
二つ目のプレフィックスリストのための処理
プレフィックスリスト管理表の作成
cat << EOF > prefixlist-02.csv cidr,description 10.1.0.0/27,subnet-1a 10.1.0.64/26,subnet-1b 10.1.1.0/27,subnet-2b 10.1.1.64/26,subnet-2b 10.1.2.0/27,subnet-3a 10.1.2.64/26,subnet-3b 10.1.3.0/27,subnet-4a 10.1.3.64/26,subnet-4b 10.1.4.0/27,subnet-5a 10.1.4.64/26,subnet-5a 10.1.5.0/27,subnet-6a 10.1.5.64/26,subnet-6c 10.1.6.0/27,subnet-7a 10.1.6.64/26,subnet-7a 10.1.7.0/27,subnet-8a 10.1.7.64/26,subnet-8b 10.1.8.0/27,subnet-9a 10.1.8.64/26,subnet-9b 10.1.9.0/27,subnet-10a 10.1.9.64/26,subnet-10b 10.1.10.0/27,subnet-11a 10.1.10.64/26,subnet-11b 10.1.11.0/27,subnet-12b 10.1.11.64/26,subnet-12b 10.1.12.0/27,subnet-13a 10.1.12.64/26,subnet-13b 10.1.13.0/27,subnet-14a 10.1.13.64/26,subnet-14b 10.1.14.0/27,subnet-15a 10.1.14.64/26,subnet-15a 10.1.15.0/27,subnet-16a 10.1.15.64/26,subnet-16c 10.1.16.0/27,subnet-17a 10.1.16.64/26,subnet-17a 10.1.17.0/27,subnet-18a 10.1.17.64/26,subnet-18b 10.1.18.0/27,subnet-19a 10.1.18.64/26,subnet-19b 10.1.19.0/27,subnet-20a 10.1.19.64/26,subnet-20b EOF
プレフィックスリスト管理表から --entries オプション用文字列の生成
ENTRIES="" SEPARATOR="" while read line do ENTRIES+="${SEPARATOR}Cidr=$(cut -d ',' -f 1 <<<$line)," ENTRIES+="Description=$(cut -d ',' -f 2 <<<${line})" if [ "${SEPARATOR}" = "" ]; then SEPARATOR=" " fi done < <(tail -n +2 prefixlist-02.csv) \ echo ${ENTRIES}
プレフィックスリストの作成
ここでは、--max-entries はリストに存在している行数(40)としている。(件数が確定している想定)
aws ec2 create-managed-prefix-list \ --prefix-list-name prefixlist-02 \ --max-entries 40 \ --address-family IPv4 \ --entries $(echo "${ENTRIES}")
【注意】
--prefix-list-name オプションの入力値は既存のプリフィックスリスト名との重複を考慮していない点に注意が必要です。
重複が起こった場合、後述のプリフィクスリスト ID の取得後の処理でエラーが出るので注意が必要です。
セキュリティグループの作成とルールへのプリフィックスリストの適用
セキュリティグループの作成
VPC_ID=vpc-xxxxxxxxxxxxxxxxx aws ec2 create-security-group \ --vpc-id ${VPC_ID} \ --group-name for-prefix \ --description sg-for-prefix
【注意】
上記コマンドでは、--group-name オプションの値として設定した文字列と、同一のセキュリティグループ名を持つ既存のセキュリティグループの考慮をしていないため注意が必要です。
セキュリティグループへのプリフィックスリストの適用
セキュリティグループ ID の取得
SECURITY_GROUP_ID=$(aws ec2 describe-security-groups \ --filters "Name=group-name,Values=for-prefix" \ --query "SecurityGroups[].GroupId" \ --output text) \ && echo ${SECURITY_GROUP_ID}
プリフィックスリスト ID の取得(一つ目)
PREFIX_LIST_ID_01=$(aws ec2 describe-managed-prefix-lists \ --filters "Name=prefix-list-name,Values=prefixlist-01" \ --query 'PrefixLists[].PrefixListId' \ --output text) \ && echo ${PREFIX_LIST_ID_01}
プリフィックスリスト ID の取得(二つ目)
PREFIX_LIST_ID_02=$(aws ec2 describe-managed-prefix-lists \ --filters "Name=prefix-list-name,Values=prefixlist-02" \ --query 'PrefixLists[].PrefixListId' \ --output text)
セキュリティグループへのルールの追加(一つ目)
aws ec2 authorize-security-group-ingress \ --group-id ${SECURITY_GROUP_ID} \ --ip-permissions "ToPort=80,FromPort=80,IpProtocol=tcp,PrefixListIds=[{Description=${PREFIX_LIST_ID_01},PrefixListId=${PREFIX_LIST_ID_01}}]"
セキュリティグループへのルールの追加(二つ目)そしてエラーが発生
aws ec2 authorize-security-group-ingress \ --group-id ${SECURITY_GROUP_ID} \ --ip-permissions "ToPort=8080,FromPort=8080,IpProtocol=tcp,PrefixListIds=[{Description=${PREFIX_LIST_ID_02},PrefixListId=${PREFIX_LIST_ID_02}}]"
戻り値
An error occurred (RulesPerSecurityGroupLimitExceeded) when calling the AuthorizeSecurityGroupIngress operation: The maximum number of rules per security group has been reached.
エラー内容の確認と精査
発生したエラーメッセージには「The maximum number of rules per security group has been reached.」とあるので、セキュリティグループのルールの上限値に達したものと推察されます。
新規に作成したセキュリティグループのため、プレフィックスリスト1に記載のエントリ 1 + プレフィックスリスト2に記載のエントリ 40 = 41
となっている計算をしていましたので、該当のエラーが出る想定をしていませんでした。
あらためて、マネージドプレフィックスリストについて公式ドキュメントを確認したところ、ちゃんと以下のように記載がありました。
マネージドプレフィックスリストを使用して CIDR ブロックをグループ化する - プレフィックスリストの概念とルール
リソース内でプレフィックスリストを参照する場合、プレフィックスリストのエントリの最大数は、リソースのエントリの数のクォータに対してカウントされます。例えば、エントリ数が 20 個のプレフィックスリストを作成し、セキュリティグループルール内でそのプレフィックスリストを参照する場合、セキュリティグループの 20 個のルールとしてカウントされます。
上記の記載の通り、セキュリティグループ内でプレフィックスリストを参照する場合、作成時の最大エントリ数としてカウントされるため、今回の例では、プレフィックスリスト1に設定した最大エントリ数 32 + プレフィックスリスト2に設定した最大エントリ数 40 = 72
としてカウントされ、「セキュリティグループ当たりのインバウンドルールまたはアウトバウンドルールの数」のデフォルト 60 を超えたため発生したエラーだと分かりました。
修正と再設定による確認
プレフィックスリスト1の修正
aws ec2 modify-managed-prefix-list \ --prefix-list-id ${PREFIX_LIST_ID_01} \ --max-entries 20
戻り値
{ "PrefixList": { "PrefixListId": "pl-00000000000000000", "AddressFamily": "IPv4", "State": "modify-in-progress", "StateMessage": "Attempting to modify maximum entries from (32) to (20).", "PrefixListArn": "arn:aws:ec2:ap-northeast-1:000000000000:prefix-list/pl-00000000000000000", "PrefixListName": "prefixlist-01", "MaxEntries": 32, "Version": 1, "OwnerId": "000000000000" } }
実際には、State が modify-complete となるまで、待機する必要があります。
セキュリティグループへのルールの追加(二つ目)の再試行
aws ec2 authorize-security-group-ingress \ --group-id ${SECURITY_GROUP_ID} \ --ip-permissions "ToPort=8080,FromPort=8080,IpProtocol=tcp,PrefixListIds=[{Description=${PREFIX_LIST_ID_02},PrefixListId=${PREFIX_LIST_ID_02}}]"
エラーなくセキュリティグループへのルール追加が完了することを確認。
最後に
- 試しに、すでにセキュリティグループにアタッチされたマネージドプレフィックスリストに対して、セキュリティグループの上限値を超えるだけの最大エントリ数を設定するように、
modify-managed-prefix-list
を実行すると、AWS CLI 上の API コールではエラー発生はないものの、結果的に State が modify-failed となり、失敗します。( modify-managed-prefix-list サブコマンド実行時には気づくことができないので注意が必要です。) - ブログのエントリ中では、マネージドプレフィックスリストを雑に作っていますが、もう少しまとめられる CIDR はまとめるなどの整理は必要です。
- 結局、セキュリティグループを含め、全体的なネットワーク設計は必要
では、また。
市野 和明 (記事一覧)
マネージドサービス部・テクニカルサポート課
お客様から寄せられたご質問や技術検証を通じて得られた気づきを投稿していきます。
情シスだった前職までの経験で、UI がコロコロ変わる AWS においては GUI で手順を残しているとはなく画面構成が変わってしまって後々まごつくことが多かったので、極力変わりにくい AWS CLI での記事が多めです。