Terraform でセキュリティグループに複数ルールを追加する方法
目次
こんにちは!
株式会社ビヨンド大阪オフィスのラーメン王、ヒデです。
今回が10回目の投稿です。
前回は、Google Cloud Load Balancing(GCLB)のグローバル外部 HTTP(S) ロードバランサで、URL リダイレクト設定をする方法ついて書きました!
最新型と従来型では、URLリダイレクトの設定が違って少し難しいですが、知っていると便利ですので興味ある方は、以下をぜひ見てくださいね!
● Part1:GCPのグローバル外部 HTTP(S) ロードバランサ(従来型)で、URLリダイレクト設定をする方法
● Part2:GCPのグローバル外部 HTTP(S) ロードバランサで、URLリダイレクト設定をする方法
Terraform でセキュリティグループに複数ルールを追加する
普段、セキュリティグループを作成する時は、インバウンドルールを手動で複数作成してますが、Terraform でも複数のインバウンドルールを設定されているセキュリティグループを作成して、インスタンスなどにアタッチさせたいですよね。
この複数ルールを作成する、2パターンのやり方を紹介します。
下記画像のようにするのが最終目標です!
では頑張っていきましょう!
設定方法
まず、一つ目の設定方法は、aws_security_group に ingress(インバウンドルール)を2つ設定する方法です。
こちらは非常にシンプルでとても使いやすいです。
resource "aws_security_group" "test-sg" { name = "test-sg" description = "test-sg" egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } ingress { from_port = 80 to_port = 80 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } ingress { from_port = 443 to_port = 443 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } }
2つ目の設定方法は、aws_security_group_rule を設定する方法です。
aws_security_group にはi ngress を記述せずに、aws_security_group_rule に記述する方法になります。この方法では、一つの aws_security_group_ruleリ ソースの中に、1つのルールしか記述することができないので、複数記述する場合は、下記のようにリソース名を違う名前にした aws_security_group_rule リソースを作成して、その中にルールを追加する方法となります。
しかし、うまく使えば便利かもしれませんが、この aws_security_group_rule を使ってルール設定をする場合は、必ず次を見てから設定をしてください!
resource "aws_security_group" test-sg" { name = "test-sg" description = "test-sg" egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] ipv6_cidr_blocks = ["::/0"] } } resource "aws_security_group_rule" "test-sg-inbound-http" { type = "ingress" from_port = 80 to_port = 80 protocol = "tcp" cidr_blocks = [ "0.0.0.0/0" ] security_group_id = aws_security_group.test-sg.id } resource "aws_security_group_rule" "test-sg-inbound-https" { type = "ingress" from_port = 443 to_port = 443 protocol = "tcp" cidr_blocks = [ "0.0.0.0/0" ] security_group_id = aws_security_group.test-sg.id }
aws_security_group と aws_security_group_rule の両方でルールを設定してはいけない
「aws_security_groupでingress を設定したけど
ingress をもう一つ追加したいから aws_security_group_rule で追加しよ!」
こんな感じで思って aws_security_group でingress ルールを設定しているのに、aws_security_group_rule で追加したら
ルールが競合してapply時に作成されたり、消えたりしてバグります.....
「バグるとかそんなわけないでしょう!何言ってんの?」
こんな感じで思った方はいるはず、初めて知った時は僕も完全にそうでしたw
そんな方のために実際に検証したログを残しておきますね!
以下 main.tf で apply します。
resource "aws_security_group" "test-sg" { name = "test-sg" description = "test-sg" egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } ingress { from_port = 80 to_port = 80 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } } resource "aws_security_group_rule" "test-sg-inbound-https" { type = "ingress" from_port = 443 to_port = 443 protocol = "tcp" cidr_blocks = [ "0.0.0.0/0" ] security_group_id = aws_security_group.test-sg.id }
1回目の apply で、AWS側ではこうなります。
問題なく 80・443ポートのインバウンドルールが作成されています。
しかし2回目に apply すると、main.tf に何も変更を加えていないのにも関わらず、change となりaws_security_group_rule に設定されているものは、削除されるようになってしまいます。
aws_security_group.test-sg: Refreshing state... [id=sg-063e7c33de8e1dc09] aws_security_group_rule.test-sg-inbound-https: Refreshing state... [id=sgrule-4193634971] aws_instance.test: Refreshing state... [id=i-07125d27a59e1b8f5] Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: ~ update in-place Terraform will perform the following actions: # aws_security_group.test-sg will be updated in-place ~ resource "aws_security_group" "test-sg" { id = "sg-063e7c33de8e1dc09" ~ ingress = [ - { - cidr_blocks = [ - "0.0.0.0/0", ] - description = "" - from_port = 443 - ipv6_cidr_blocks = [] - prefix_list_ids = [] - protocol = "tcp" - security_groups = [] - self = false - to_port = 443 }, - { - cidr_blocks = [ - "0.0.0.0/0", ] - description = "" - from_port = 80 - ipv6_cidr_blocks = [] - prefix_list_ids = [] - protocol = "tcp" - security_groups = [] - self = false - to_port = 80 }, + { + cidr_blocks = [ + "0.0.0.0/0", ] + description = null + from_port = 80 + ipv6_cidr_blocks = [] + prefix_list_ids = [] + protocol = "tcp" + security_groups = [] + self = false + to_port = 80 }, ] name = "test-sg" tags = {} # (7 unchanged attributes hidden) } Plan: 0 to add, 1 to change, 0 to destroy. Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes
2回目のapply後のAWS画面は以下になります。aws_security_group_rule で設定された部分は消えてますね。。。
公式の aws_security_group リソースの説明にはこのように書かれています。
要するに aws_security_group_rule に設定しても、aws_security_group に設定した内容に上書きされるということですね。知らないまま運用すると、結構怖いことになりますよね...
Terraform は現在、スタンドアロンのセキュリティ グループ ルール リソース (単一のイングレスまたはエグレス ルール) と、インラインで定義されたイングレスおよびエグレス ルールを含むセキュリティ グループ リソースの両方を提供します。
現時点では、インライン ルールを持つセキュリティ グループをセキュリティ グループ ルール リソースと組み合わせて使用することはできません。これを行うと、ルール設定の競合が発生し、ルールが上書きされます。
● 参考:https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group
まとめ
今回は Terraform でセキュリティグループに複数ルールを追加する方法について紹介しましたが、いかがでしたでしょうか?
aws_security_group と aws_security_group_rule で複数のルールを定義できますが、同時にルールを設定すると、とんでもないミスを招く恐れがあるので注意が必要です!
どちらを使うかはお任せしますが、特別な理由がない限りは、aws_security_group で複数のルールを設定する方が、管理が楽で競合も起きないと思います。
セキュリティグループを作成する際はぜひ、参考にしてくださいね!