How to add multiple rules to a security group in Terraform
*Tsukemen Shigeta (Kobe Rokkomichi)
Hello!
My name is Hide, the ramen king of Beyond Osaka Office.
This is my 10th post.
Last time, I wrote about how to configure URL redirection using Google Cloud Load Balancing (GCLB)'s global external HTTP(S) load balancer!
The URL redirect settings are different for the latest model and the conventional model, so it's a little difficult, but it's useful to know, so if you're interested, please take a look at the following!
● Part 1: How to configure URL redirect settings with GCP's global external HTTP(S) load balancer (traditional type)
● Part 2: How to configure URL redirect settings with GCP's global external HTTP(S) load balancer
Add multiple rules to a security group in Terraform
Normally, when creating a security group, you manually create multiple inbound rules, but in Terraform as well, you would like to create a security group with multiple inbound rules and attach it to an instance.
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!
Setting method
First, the first setting method is to set two ingress (inbound rules) in aws_security_group.
This is very simple and very 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 configuration method is to configure aws_security_group_rule.
Instead of writing ingress in aws_security_group, you can write 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, create an aws_security_group_rule resource with a different resource name as shown below, and then This is how to add rules to.
However, it may be convenient if used properly, but if you use this aws_security_group_rule to set rules, be sure to read the following before setting it!
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 ingress in aws_security_group, but
I want to add another ingress, so add it with aws_security_group_rule! ”
I thought like this and set an ingress rule in aws_security_group, but if I add it in aws_security_group_rule,
the rule will conflict and be created or deleted during apply, resulting in a bug...
"There's no way it's a bug! What are you talking about?"
I'm sure there are people who thought something like this, and when I first learned about it, I was completely the same way lol
For those people, I'll leave a log of what I actually verified!
Apply in main.tf below.
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 }
The first apply will look like this on the AWS side.
Inbound rules for ports 80 and 443 have been created without any problems.
However, when you apply it the second time, it becomes a change and the settings in aws_security_group_rule are deleted, even though no changes have been made to main.tf.
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 is as follows. The part set in aws_security_group_rule has disappeared. . .
The official aws_security_group resource description says:
In short, even if you set it in aws_security_group_rule, it will be overwritten by the content set in aws_security_group. It can be quite scary if you operate it without knowing...
Terraform currently provides both standalone security group rule resources (single ingress or egress rules) and security group resources that contain inline-defined ingress and egress rules.
Security groups with inline rules cannot currently be used in conjunction with security group rules resources. Doing this will cause a rule configuration conflict and override the rules.
● Reference: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group
summary
This time I introduced how to add multiple rules to a security group using Terraform. What did you think?
You can define multiple rules using aws_security_group and aws_security_group_rule, but be careful not to set rules at the same time as you may end up making a terrible mistake!
I'll leave it up to you which one to use, but unless there's a special reason, I think it's easier to manage and avoid conflicts by setting multiple rules in aws_security_group.
Please refer to this when creating a security group!