##はじめに
terraformを使ったセキュリティグループの管理はちょこっと癖がありますよね。
(terraformというよりAWSAPIの癖って気もしますが。。)
指定方法が特殊なICMPのルールについて自分自身の備忘も兼ねて纏めておこうと思います。
##terraform公式ドキュメントの記載内容
基本的な書式
resource "aws_security_group_rule" "allow_all" {
type = "ingress"
from_port = 0
to_port = 65535
protocol = "tcp" # Opening to 0.0.0.0/0 can lead to security vulnerabilities.
cidr_blocks = # add a CIDR block here
prefix_list_ids = [
"pl-12c4e678"
]
security_group_id = "sg-123456"
}
icmpルールの場合、ポイントになるのは以下の部分です。
protocol (必須)プロトコル。 icmp、icmpv6、tcp、udp、またはすべてがプロトコル番号を使用しない場合
from_port (必須)開始ポート(またはプロトコルが「icmp」または「icmpv6」の場合はICMPタイプ番号)
to_port (必須)エンドポート(またはプロトコルが「icmp」の場合はICMPコード)
要約するとICMPルールの時は以下を指定しろって事のようですね。
- protocolに「icmpまたはicmpv6」
- from_portに「icmpタイプ番号」
- to_portに「icmpコード」
##ICMPタイプ番号
from_portに「ICMPタイプ番号」というのは少し違和感がありますが、
ICMPにはポート番号という概念が無いので、TYPEを代わりに指定するイメージですか。
ICMPには以下のTYPEがあります。
※v6の場合は番号が異なるので注意
Type | 内容 | 意味 |
---|---|---|
0 | Echo Reply | エコー応答 |
3 | Destination Unreachable | 宛先到達不能 |
4 | Source Quench | 始点抑制 |
5 | Redirect | 最適経路への変更指示 |
8 | Echo Request | エコー要求 |
9 | Router Advertisement | ルータ通知 |
10 | Router Solicitation | ルータ要求 |
11 | Time Exceeded | TTL超過によるパケット破棄の報告 |
12 | Parameter Problem | パケットパラメータにおけるエラー |
13 | Timestamp | タイムスタンプ |
14 | Timestamp Reply | タイムスタンプ応答 |
15 | Information Request | インフォメーション要求 |
16 | Information Reply | インフォメーション応答 |
17 | Address Mask Request | アドレスマスク要求 |
18 | Address Mask Reply | アドレスマスク応答 |
よく使うのはPING=エコー要求の「8」でしょうか。
##ICMPコード
to_portに「icmpコード」
個人的に少し悩みどころだったのですが、ICMPコードはICMPタイプによってあるものとないものがあります。
調べた感じ、ICMPコードがあるのは「ICMP Type3」「ICMP Type5」「ICMP Type9」「ICMP Type11」「ICMP Type12」みたいですね。
※それぞれのcodeは後で時間があれば纏めるかも。ちなみに後述しますが全てのCODEを対象にする場合は「-1」です。
ICMPコードがあるものはその番号を指定すれば良いでしょうが、ここでの問題は**ICMPコードがないものは何を指定すりゃええねん!**って部分ですよね。(自分はすごく悩みました)
よく利用されるであろうエコー要求もICMPコードがない部類ですね。コンソールだと「該当なし」になりますが、CLIでそれをどう表現するんだ。。
で、一生懸命探したところ、terraformではicmpコードなし=「0」を指定せよってことみたいです。
※AWSCLIのリファレンスでは「0」or「-1」がicmpコードなしとして有効な値らしいですが、terraformから実行する場合「-1」は無効な値と判定されるっぽい(実際には試してませんが)ただ、AWSAPI側では「0」を指定しても「-1」に値が変換されて設定されている可能性があるとのこと。う、うん?って感じ。そこは足並みを揃えて欲しいですね。
まあ纏めると以下になるかと。
- ICMPコードがあるものは、指定したいコードまたは「-1」 ※「-1」は「すべて」の意
- ICMPコードがないものは、「0」を指定
##すべてのICMP
ここまでの内容だけでは、まだ足りないものがあります。
そう、「すべてのICMP」を許可するルールはどう作るねんって話ですね。
まあ、これに関してはAWSCLIのリファレンスを信じて問題なさそうです。
https://docs.aws.amazon.com/cli/latest/reference/ec2/authorize-security-group-ingress.html
AWSCLIのリファレンスから重要な部分を抜粋すると以下です。
ICMP/ICMPv6 の場合は、ICMP/ICMPv6 タイプおよびコードも指定する必要があります。-1 を使用すると、すべての種類またはすべてのコードを意味できます。
要約すると以下ですかね。
- 全てのicmpタイプ = 「-1」を指定する
- 全てのicmpコード = 「-1」を指定する
なので、「すべてのICMP」を表すのは以下になります。
protocol = "icmp"
from_port = -1
to_port = -1
##まとめ
terraformからPINGを許可するセキュリティルールはどう指定するん?
resource "aws_security_group_rule" "allow_ping" {
type = "ingress"
from_port = 8
to_port = 0
protocol = "icmp"
cidr_blocks = "0.0.0.0/0"
security_group_id = "sg-123456"
}
terraformからすべてのICMPを許可するセキュリティルールはどう指定するん?
resource "aws_security_group_rule" "allow_icmp_all" {
type = "ingress"
from_port = -1
to_port = -1
protocol = "icmp"
cidr_blocks = "0.0.0.0/0"
security_group_id = "sg-123456"
}
##簡単な調べ方
今回は正確な裏付け情報を得るためにリファレンスとかを漁りましたが、簡単に調べる方法もあります。
コンソールから手でルールを作成して、それがどんな値で設定されているか調べるという方法ですね。(こっちのが確実かも)
CLIで確認するならaws ec2 describe-security-groups
ですかね。
※ただ、ICMPコードの時みたいに「cliでは有効だけどterraformでは無効な値」とかあるかもしれないのが困りものですが。
terraformならterraform import
ですね。
terraform import aws_security_group.<セキュリティグループ>
上記方法は実際には試してないのですが、terraform import
なら正確な設定値が返ってきそうな気がしますね。(時間がある時にエコー要求のルールでどんな値が返ってくるか検証してみようかなー。。)