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

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

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

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

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

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

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

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

【格安】Webサイト セキュリティ自動診断「クイックスキャナー」

【格安】Webサイト セキュリティ自動診断「クイックスキャナー」

【低コスト】Wasabi オブジェクトストレージ 構築・運用サービス

【低コスト】Wasabi オブジェクトストレージ 構築・運用サービス

【予約システム開発】EDISONE カスタマイズ開発サービス

【予約システム開発】EDISONE カスタマイズ開発サービス

【100URLの登録が0円】Webサイト監視サービス『Appmill』

【100URLの登録が0円】Webサイト監視サービス『Appmill』

【中国現地企業に対応】中国クラウド / サーバー構築・運用保守

【中国現地企業に対応】中国クラウド / サーバー構築・運用保守

【YouTube】ビヨンド公式チャンネル「びよまるチャンネル」

【YouTube】ビヨンド公式チャンネル「びよまるチャンネル」

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 で複数のルールを設定する方が、管理が楽で競合も起きないと思います。

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

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

【2024.6.30 CentOS サポート終了】CentOS サーバー移行ソリューション

【大阪 / 横浜】インフラエンジニア・サーバーサイドエンジニア 積極採用中!

【大阪 / 横浜】インフラエンジニア・サーバーサイドエンジニア 積極採用中!

この記事をかいた人

About the author

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

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

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

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