Terraformでセキュリティグループに複数のルールを追加する方法
こんにちは!
株式会社ビヨンド大阪オフィスのラーメン王、ヒデです。
今回が10回目の投稿です。
前回はGCLBのグローバル外部 HTTP(S) ロードバランサでURLリダイレクト設定をする方法ついて書きました!
GCLBのグローバル外部 HTTP(S) ロードバランサでURLリダイレクト設定をする場合は、
最新型と従来型ではURLリダイレクトの設定が違って少し難しいですが
知っていると便利ですので興味ある方は、以下をぜひ見てくださいね!
概要
普段、セキュリティグループを作成する時は、インバウンドルールを手動で複数作成してますが、
Terraformでも複数のインバウンドルールを設定されているセキュリティグループを作成して、
インスタンスなどにアタッチさせたいですよね。
この複数ルールを作成するやり方に関しては二通り紹介します。
下記画像のようにするのが最終目標です!
では頑張っていきましょう!
設定方法
まず、一つ目の設定方法は、aws_security_groupにingress(インバウンドルール)を二つ設定する方法です。
こちらは非常にシンプルでとても使いやすいです。
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"] } }
二つ目の設定方法は、aws_security_group_ruleを設定する方法です。
aws_security_groupにはingressを記述せずに、aws_security_group_ruleに記述する方法になります。
この方法では、一つのaws_security_group_ruleリソースの中に一つのルールしか記述することができないので、
複数記述する場合は、下記のようにリソース名を違う名前にした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のインバウンドルールが作成されています。
しかし、二回目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
二回目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で複数のルールを設定する方が管理が楽で競合も起きないと思います。
セキュリティグループを作成する際はぜひ、参考にしてくださいね!