How to add multiple rules to a security group in Terraform

 

*Tsukemen Shigeta (Rokkomichi, Kobe)

Hello!
I'm Hide, the Ramen King from Beyond Inc.'s Osaka office.
This is my 10th post.

Last time, I wrote about how to set up URL redirection with the Google Cloud Load Balancing (GCLB) global external HTTP(S) load balancer!

The URL redirection settings are different between the latest and traditional models, which can be a little difficult, but it's useful to know, so if you're interested, please take a look below!

● Part 1: How to set up URL redirection with GCP's global external HTTP(S) load balancer (traditional type)
● Part 2: How to set up URL redirection with GCP's global external HTTP(S) load balancer

Adding multiple rules to a security group in Terraform

Normally, when creating a security group, multiple inbound rules are created manually, but you may want to create a security group with multiple inbound rules in Terraform as well and attach it to an instance, etc

We will introduce two ways to create these multiple rules

The final goal is to make it look like the image below!
Let's do our best!

How to set it up

The first setting method is to set two ingress (inbound rules) in aws_security_group.
This is very simple and easy to use.

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"] } }

The second setting method is to set aws_security_group_rule

This method involves not writing ingress in aws_security_group, but writing it in aws_security_group_rule. With this method, you can only write one rule in one aws_security_group_rule resource, so if you want to write multiple rules, you need to create an aws_security_group_rule resource with a different resource name as shown below and add the rules to it

However, while it may be useful if used properly, if you use this aws_security_group_rule to set rules, be sure to read the following before setting them up!

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 }

Do not set rules in both aws_security_group and aws_security_group_rule


"I set up ingress with aws_security_group, but

I want to add another ingress, so I'll add it with aws_security_group_rule!

I set ingress rules with aws_security_group like this, but when I add them with aws_security_group_rule,
the rules conflict and are created and deleted when I apply them, causing bugs...

"There's no way it'll bug out! What are you talking about?"

I'm sure there are people out there who have thought the same thing, and that's exactly what I thought when I first learned about it lol.
For those of you who feel the same way, I'll leave a log of my actual testing!

Apply the following in main.tf

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 }

After the first apply , the following will appear on the AWS side.
The inbound rules for ports 80 and 443 have been created without any issues.

However, when you apply it the second time, even though you haven't made any changes to main.tf, it will be marked as changed and anything set in aws_security_group_rule will be deleted

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

The AWS screen after the second apply will look like this. The part set in aws_security_group_rule has disappeared

The official aws_security_group resource description states:

In other words, even if you set it in aws_security_group_rule, it will be overwritten by the setting in aws_security_group. If you operate without knowing this, it can be quite scary...

Terraform currently provides both a standalone security group rule resource (a single ingress or egress rule) and a security group resource with ingress and egress rules defined inline

Currently, you cannot use security groups with inline rules in combination with security group rule resources, as this will result in conflicting rule settings and overwriting the rules

● Reference: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group

summary

This time, we introduced how to add multiple rules to a security group using Terraform. What did you think?

You can define multiple rules with aws_security_group and aws_security_group_rule, but be careful not to set rules at the same time as this can lead to serious mistakes!

It's up to you which one to use, but unless there is a special reason, I think setting multiple rules with aws_security_group is easier to manage and less likely to cause conflicts

Please use this as a reference when creating a security group!

If you found this article useful, please click [Like]!
5
Loading...
5 votes, average: 1.00 / 15
8,233
X Facebook Hatena Bookmark pocket

The person who wrote this article

About the author

Hide@Infrastructure Engineer

It all started with a really interesting interview.
I joined the System Solutions Department in Osaka mid-career and
am currently involved in the construction and operation of servers and clouds!
I hold LPIC1, AWS SAA, and OCI Architect Associate certifications.

In fact, I love ramen and
have investigated over 100 ramen shops in Osaka (。-∀-) I am striving to become the ramen king of Nibi Beyond

I'm also on Twitter, so please follow me (´∇`)
Click on the Twitter mark in the right corner!!