CloudFormation 文字列の配列をパラメータで渡してテンプレートを実行したいとき、CommaDelimitedListを使ってみる
CloudFormationのパラメータで文字列を配列で渡したいときどう指定するのか調べる機会がありました。テンプレートのサンプルと共にまとめておきます。
まとめ
- パラメータのデータタイプCommaDelimitedListが文字列の配列形式タイプ
,
区切りで文字列を並べていく- 例)"Sapporo, Kitami, Abashiri"
- 配列に入れたい文字列が多くなるとパラメータが見づらくなる
- 本当にパラメータから文字列を配列で渡したいのか一考の余地あり
例題
配列で文字列をパラメータで渡す例として、AWS WAFにホワイトリスト形式のIPアドレス制限をかけるとします。その際に復数のIPアドレスをホワイトリストに追加したいため、復数のIPアドレスのリストをパラメータとして受け取って実行したい。
サンプルのテンプレートではWAF本体は作成せず、許可または拒否したいIPアドレスのリストを定義するIP setsのみ作成します。
WAF本体も作成したい場合は以下のブログポストを参考にしてください。
ベタ書きの例
アクセスを許可したいIPアドレスが復数ある場合、テンプレートは以下の記述になります。Addresses配下のIPアドレス部分をパラメータとして受け取りたい場合どうするのか?を見ていきましょう。
Resources: IPWhiteList: Type: "AWS::WAFv2::IPSet" Properties: Name: Custom-ipaddress-whitelist Scope: REGIONAL IPAddressVersion: IPV4 Addresses: - 1.1.1.1/32 - 2.2.2.2/32 - 3.3.3.3/32
Addressesで指定するCIDR表記のIPアドレスは数値ではなく文字列の配列扱いとなっています。
パラメータのデータタイプ
よく使われるStringやNumberなどのデータ型のひとつにCommaDelimitedListがあります。これは,
区切りで文字列の配列を渡せます。Default:
で初期値で文字列の配列を設定しています。
AWSTemplateFormatVersion: 2010-09-09 Description: WAF IPSet Parameters: AllowAddresses: Description: IP list to allow access. Type: CommaDelimitedList Default: "1.1.1.1/32, 2.2.2.2/32, 3.3.3.3/32" Resources: IPWhiteList: Type: "AWS::WAFv2::IPSet" Properties: Name: Custom-ipaddress-whitelist Scope: REGIONAL IPAddressVersion: IPV4 Addresses: !Ref AllowAddresses
マネジメントコンソールからスタック作成
先ほどのテンプレートからスタックを作成してみます。パラメータで復数値を渡せるのですが、指定する値が多くなると非常に分かりづらくなります。
実行結果
AWS CLIからスタック作成
AWS CLIからスタックを作成します。パラメータ指定用のJSONファイルを用意して引数でファイルを渡します。
AWS CLIからなら上手いこと見やすくできないかと考えたみたのですが結局こうなりました。これまた分かりづらいですね。
[ { "ParameterKey": "AllowAddresses", "ParameterValue": "4.4.4.4/32, 5.5.5.5/32, 6.6.6.6/32, 7.7.7.7/32" } ]
AWS CLIからスタックを作成します。引数でJSONファイルを渡しています。
aws cloudformation create-stack \ --stack-name sample-ipsetlist \ --template-body file://./ipset.yml \ --parameters file://./parameters.json
実行結果
補足: Refでパラメータの値を取り出すとき
今回の場合、CommaDelimitedListのパラメータの値を!Ref関数で取り出すときは下記の様に指定します。
Addresses: !Ref AllowAddresses
IPアドレス直接指定してたときは下記の書式です。-
付きで指定していました。
Addresses: - 1.1.1.1/32
上記を真似て下の様に-
付きの書式でテンプレートを作成してみました。このテンプレートからスタックを作成するとエラーでリソースの作成に失敗します。
Addresses: - !Ref AllowAddresses
本来は文字列(String)で指定するところにJSON形式の配列が入ってくるため、下記のエラーになります。
Resource handler returned message: "Model validation failed (#/Addresses/0: expected type: String, found: JSONArray)"
些細な違いでエラーになるため指定方法には注意が必要です。このエラーについて書き残したかったがためにまとめました。
おわりに
外部からパラメータとして配列で文字列を渡したいときにはCommaDelimitedListが使えます。今回は文字列の対象がIPアドレスだったこともあり、非常に見づらい結果となりました。本当に外部からパラメータとして文字列の配列をもらい受ける必要があるのかを再考した方がよいかなといった感想です。
Resources: IPWhiteList: Type: "AWS::WAFv2::IPSet" Properties: Name: Custom-ipaddress-whitelist Scope: REGIONAL IPAddressVersion: IPV4 Addresses: - 1.1.1.1/32 # ymlならコメントも書けるし、後で見ても分かりやすい - 2.2.2.2/32 # A社のIPアドレス - 3.3.3.3/32 # B社のIPアドレス