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

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

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

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

【圧倒的 低コスト】Oracle Cloud 構築・運用保守・監視サービス

【圧倒的 低コスト】Oracle Cloud 構築・運用保守・監視サービス

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

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

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

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

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

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

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

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

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

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

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

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

【グローバル対応】北米リージョン・クラウド / サーバーMSP

【グローバル対応】北米リージョン・クラウド / サーバーMSP

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

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

Terraformでセキュリティグループに複数のルールを追加する方法

 

*つけ麺 繁田 (神戸六甲道)

 

こんにちは!
株式会社ビヨンド大阪オフィスのラーメン王、ヒデです。
今回が10回目の投稿です。

前回はGCLBのグローバル外部 HTTP(S) ロードバランサでURLリダイレクト設定をする方法ついて書きました!
GCLBのグローバル外部 HTTP(S) ロードバランサでURLリダイレクト設定をする場合は、
最新型と従来型ではURLリダイレクトの設定が違って少し難しいですが
知っていると便利ですので興味ある方は、以下をぜひ見てくださいね!

GCPのグローバル外部 HTTP(S) ロードバランサでURLリダイレクト設定をする方法

GCPのグローバル外部 HTTP(S) ロードバランサ(従来)で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で複数のルールを設定する方が管理が楽で競合も起きないと思います。

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

 

 

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

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

【高セキュリティなレンタルサーバー】ウェブスピード ライトプラン【月額 4,980円】

【高セキュリティなレンタルサーバー】ウェブスピード ライトプラン【月額 4,980円】

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

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

この記事をかいた人

About the author

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

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

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

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