【大阪 / 横浜 / 徳島】インフラ / サーバーサイドエンジニア募集中!

【大阪 / 横浜 / 徳島】インフラ / サーバーサイドエンジニア募集中!

【導入実績 500社以上】AWS 構築・運用保守・監視サービス

【導入実績 500社以上】AWS 構築・運用保守・監視サービス

【CentOS 後継】AlmaLinux OS サーバー構築・移行サービス

【CentOS 後継】AlmaLinux OS サーバー構築・移行サービス

【WordPress 専用】クラウドサーバー『ウェブスピード』

【WordPress 専用】クラウドサーバー『ウェブスピード』

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つ設定する方法です。
こちらは非常にシンプルでとても使いやすいです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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 を使ってルール設定をする場合は、必ず次を見てから設定をしてください!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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 します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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 に設定されているものは、削除されるようになってしまいます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
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 で複数のルールを設定する方が、管理が楽で競合も起きないと思います。

セキュリティグループを作成する際はぜひ、参考にしてくださいね!

この記事がお役に立てば【 いいね 】のご協力をお願いいたします!
5
読み込み中...
5 票, 平均: 1.00 / 15
7,268
X facebook はてなブックマーク pocket
【2026.6.30 Amazon Linux 2 サポート終了】Amazon Linux サーバー移行ソリューション

【2026.6.30 Amazon Linux 2 サポート終了】Amazon Linux サーバー移行ソリューション

この記事をかいた人

About the author

ヒデ@インフラエンジニア

超面白かった面接がきっかけで。
大阪のシステムソリューション部に中途入社した人
サーバー・クラウドの構築や運用を業務としています!
一応、LPIC1・AWS SAA・OCI Architect Associateを資格は持っています

実はラーメンが大好きで
大阪では100店舗以上潜入調査済み(。-∀-) ニヒ
ビヨンドのラーメン王を目指し奮闘中!!

Twitterもやっているのでフォローしてね(´∇`)
右角のTwitterマークをクリック!!