🤖
Cloud Armor の細切れルールによる課金を節約する
こんにちは、クラウドエースの吉崎です。
Cloud Armor の料金体系をご存知でしょうか。
公式ドキュメントを見ると、以下の項目に対して課金されます。
項目 | 課金 |
---|---|
WAF requests | $0.75 per million requests |
WAF security policies | $5 per policy per month |
WAF rules | $1 per rule per month |
最も課金額が大きいのは WAF security policies
ですが、本稿で節約の対象とするのは WAF rules
です。
出来るだけ作成されるルールの数を減らし、さらには管理の手間の削減に貢献するのが本稿の内容です。
※そうです。良い意味でケチです。
節約していない例
まずは会社ごとに許可する IP アドレスを愚直にルールに書いていった例をご覧ください。
before.tf
resource "google_compute_security_policy" "default" {
name = "default"
rule {
description = "company1"
action = "allow"
priority = 100
match {
versioned_expr = "SRC_IPS_V1"
config {
src_ip_ranges = [
"1.1.1.1/32", "2.2.2.2/32", "3.3.3.3/32"
]
}
}
}
rule {
description = "company2"
action = "allow"
priority = 101
match {
versioned_expr = "SRC_IPS_V1"
config {
src_ip_ranges = [
"4.4.4.4/32", "5.5.5.5/32", "6.6.6.6/32",
"7.7.7.7/32", "8.8.8.8/32", "9.9.9.9/32",
]
}
}
}
rule {
description = "company3"
action = "allow"
priority = 102
match {
versioned_expr = "SRC_IPS_V1"
config {
src_ip_ranges = [
"11.11.11.11/32", "12.12.12.12/32", "13.13.13.13/32",
"14.14.14.14/32", "15.15.15.15/32", "16.16.16.16/32",
"17.17.17.17/32",
]
}
}
}
rule {
description = "company4"
action = "allow"
priority = 103
match {
versioned_expr = "SRC_IPS_V1"
config {
src_ip_ranges = [
"18.18.18.18/32", "19.19.19.19/32", "20.20.20.20/32",
"21.21.21.21/32", "22.22.22.22/32", "23.23.23.23/32",
"24.24.24.24/32", "25.25.25.25/32", "26.26.26.26/32",
"27.27.27.27/32",
]
}
}
}
rule {
description = "company4_2"
action = "allow"
priority = 104
match {
versioned_expr = "SRC_IPS_V1"
config {
src_ip_ranges = [
"28.28.28.28/32", "29.29.29.29/32", "30.30.30.30/32",
"31.31.31.31/32", "32.32.32.32/32", "33.33.33.33/32",
"34.34.34.34/32",
]
}
}
}
}
description
を見ればどの会社にどの IP アドレスが許可されているかぱっと見で分かるシンプルな構成ですが、以下のことが気になります。
- company1 と company2 のルールを統合すれば課金を抑えられそう(でも違う会社だしなぁ)
- 許可する IP アドレスが増えたとき
_2
とかつけていくのなんか嫌 - 許可する会社が増えたときどんどんルールが増えてコードが縦に伸びていきそう
節約している例
続いて、作成されるルールの数を減らし、管理の手間を削減した例をご覧ください。
after.tf
locals {
company1 = [
"1.1.1.1/32", "2.2.2.2/32", "3.3.3.3/32",
]
company2 = [
"4.4.4.4/32", "5.5.5.5/32", "6.6.6.6/32",
"7.7.7.7/32", "8.8.8.8/32", "9.9.9.9/32",
]
company3 = [
"11.11.11.11/32", "12.12.12.12/32", "13.13.13.13/32",
"14.14.14.14/32", "15.15.15.15/32", "16.16.16.16/32",
"17.17.17.17/32",
]
company4 = [
"18.18.18.18/32", "19.19.19.19/32", "20.20.20.20/32",
"21.21.21.21/32", "22.22.22.22/32", "23.23.23.23/32",
"24.24.24.24/32", "25.25.25.25/32", "26.26.26.26/32",
"27.27.27.27/32", "28.28.28.28/32", "29.29.29.29/32",
"30.30.30.30/32", "31.31.31.31/32", "32.32.32.32/32",
"33.33.33.33/32", "34.34.34.34/32",
]
}
resource "google_compute_security_policy" "default" {
name = "default"
dynamic "rule" {
for_each = chunklist(concat(
local.company1,
local.company2,
local.company3,
local.company4,
), 10)
content {
description = format("rule%s", rule.key)
action = "allow"
priority = rule.key + 1
match {
versioned_expr = "SRC_IPS_V1"
config {
src_ip_ranges = rule.value
}
}
}
}
}
ポイントは、
を使っている点です。
なんとなく想像がつくかもしれませんが、concat
で引数のリストを結合し、chunklist
で 10 個ずつに分割しています。
これにより、以下の良いことがあります。
- 各ルールに 10 個ずつ IP アドレスが設定されており、無駄がない状態になる(=節約)
- company5 を追加するとき、ルールを足すのではなく locals に足すだけで良い(=可読性向上)
- 許可する IP アドレスが一社につき 10 個を超えた場合、自動で 10 個ずつに分割される(=利便性向上)
terraform plan
をした結果は以下をご覧ください。
terraform plan
$ terraform plan
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# google_compute_security_policy.after will be created
+ resource "google_compute_security_policy" "after" {
+ fingerprint = (known after apply)
+ id = (known after apply)
+ name = "after"
+ project = (known after apply)
+ self_link = (known after apply)
+ type = (known after apply)
+ advanced_options_config {
+ json_parsing = (known after apply)
+ log_level = (known after apply)
}
+ rule {
+ action = "allow"
+ preview = (known after apply)
+ priority = 1
+ match {
+ versioned_expr = "SRC_IPS_V1"
+ config {
+ src_ip_ranges = [
+ "1.1.1.1/32",
+ "11.11.11.11/32",
+ "2.2.2.2/32",
+ "3.3.3.3/32",
+ "4.4.4.4/32",
+ "5.5.5.5/32",
+ "6.6.6.6/32",
+ "7.7.7.7/32",
+ "8.8.8.8/32",
+ "9.9.9.9/32",
]
}
}
}
+ rule {
+ action = "allow"
+ preview = (known after apply)
+ priority = 2
+ match {
+ versioned_expr = "SRC_IPS_V1"
+ config {
+ src_ip_ranges = [
+ "12.12.12.12/32",
+ "13.13.13.13/32",
+ "14.14.14.14/32",
+ "15.15.15.15/32",
+ "16.16.16.16/32",
+ "17.17.17.17/32",
+ "18.18.18.18/32",
+ "19.19.19.19/32",
+ "20.20.20.20/32",
+ "21.21.21.21/32",
]
}
}
}
+ rule {
+ action = "allow"
+ preview = (known after apply)
+ priority = 3
+ match {
+ versioned_expr = "SRC_IPS_V1"
+ config {
+ src_ip_ranges = [
+ "22.22.22.22/32",
+ "23.23.23.23/32",
+ "24.24.24.24/32",
+ "25.25.25.25/32",
+ "26.26.26.26/32",
+ "27.27.27.27/32",
+ "28.28.28.28/32",
+ "29.29.29.29/32",
+ "30.30.30.30/32",
+ "31.31.31.31/32",
]
}
}
}
+ rule {
+ action = "allow"
+ preview = (known after apply)
+ priority = 4
+ match {
+ versioned_expr = "SRC_IPS_V1"
+ config {
+ src_ip_ranges = [
+ "32.32.32.32/32",
+ "33.33.33.33/32",
+ "34.34.34.34/32",
]
}
}
}
+ rule {
+ action = "allow"
+ description = "default rule"
+ preview = (known after apply)
+ priority = 2147483647
+ match {
+ versioned_expr = "SRC_IPS_V1"
+ config {
+ src_ip_ranges = [
+ "*",
]
}
}
}
}
Plan: 1 to add, 0 to change, 0 to destroy.
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
デメリット
この構成に変えたとき、コンソールから見たときにどの IP アドレスがどの会社のものか分からなくなるというデメリットがあります。
画像は文字が小さいですが、節約のためルールが会社ごとではなくなったため、説明を見てもどの会社の IP アドレスかは分かりません。
before(company1~4)
after(rule1~4)
まとめ
コンソールからルールと説明の関係を確認する必要がある場合を除いては、節約と管理の手間の削減から本稿の構成を取ると良いでしょう。
Discussion