Security Groups

Our servers are useless without some security groups! As it stands, our servers are only accessible by resources within the same security group.

That's a neat ability for security groups, but we need 2 different ones for our use case:

  1. A security group that allows public network traffic
  2. A security group that allows private network traffic only

File security.tf

We'll add a new file into modules/vpc/security.tf, into which we'll create 2 security groups and the rules to add to each.

Note that I once again opt to define the security group and its rules using 2 separate resource types.

You don't have to, but in Terraform, there are benefits to defining them separately.

1###
2# Public Security Group
3##
4 
5resource "aws_security_group" "public" {
6 name = "cloudcasts-${var.infra_env}-public-sg"
7 description = "Public internet access"
8 vpc_id = aws_vpc.vpc.id
9 
10 tags = {
11 Name = "cloudcasts-${var.infra_env}-public-sg"
12 Role = "public"
13 Project = "cloudcasts.io"
14 Environment = var.infra_env
15 ManagedBy = "terraform"
16 }
17}
18 
19resource "aws_security_group_rule" "public_out" {
20 type = "egress"
21 from_port = 0
22 to_port = 0
23 protocol = "-1"
24 cidr_blocks = ["0.0.0.0/0"]
25 
26 security_group_id = aws_security_group.public.id
27}
28 
29resource "aws_security_group_rule" "public_in_ssh" {
30 type = "ingress"
31 from_port = 22
32 to_port = 22
33 protocol = "tcp"
34 cidr_blocks = ["0.0.0.0/0"]
35 security_group_id = aws_security_group.public.id
36}
37 
38resource "aws_security_group_rule" "public_in_http" {
39 type = "ingress"
40 from_port = 80
41 to_port = 80
42 protocol = "tcp"
43 cidr_blocks = ["0.0.0.0/0"]
44 security_group_id = aws_security_group.public.id
45}
46 
47resource "aws_security_group_rule" "public_in_https" {
48 type = "ingress"
49 from_port = 443
50 to_port = 443
51 protocol = "tcp"
52 cidr_blocks = ["0.0.0.0/0"]
53 security_group_id = aws_security_group.public.id
54}
55 
56###
57# Private Security Group
58##
59 
60resource "aws_security_group" "private" {
61 name = "cloudcasts-${var.infra_env}-private-sg"
62 description = "Private internet access"
63 vpc_id = aws_vpc.vpc.id
64 
65 tags = {
66 Name = "cloudcasts-${var.infra_env}-private-sg"
67 Role = "private"
68 Project = "cloudcasts.io"
69 Environment = var.infra_env
70 ManagedBy = "terraform"
71 }
72}
73 
74resource "aws_security_group_rule" "private_out" {
75 type = "egress"
76 from_port = 0
77 to_port = 0
78 protocol = "-1"
79 cidr_blocks = ["0.0.0.0/0"]
80 
81 security_group_id = aws_security_group.private.id
82}
83 
84resource "aws_security_group_rule" "private_in" {
85 type = "ingress"
86 from_port = 0
87 to_port = 65535
88 protocol = "-1"
89 cidr_blocks = [aws_vpc.vpc.cidr_block]
90 
91 security_group_id = aws_security_group.private.id
92}

File: outputs.tf

We'll also want to add to our modules/vpc/outputs.tf file so we can get the security group ID's for these new SG's.

1output "security_group_public" {
2 value = aws_security_group.public.id
3}
4 
5output "security_group_private" {
6 value = aws_security_group.private.id
7}

File cloudcasts.tf

Finally, we can use our new security groups by assigning them to our EC2 servers:

1 module "ec2_app" {
2 source = "./modules/ec2"
3  
4 infra_env = var.infra_env
5 infra_role = "web"
6 instance_size = "t3.small"
7 instance_ami = data.aws_ami.app.id
8 # instance_root_device_size = 12
9 subnets = keys(module.vpc.vpc_public_subnets)
10- security_groups = ["sg-095b0ec176f8fbc14"]
11+ security_groups = [module.vpc.security_group_public]
12 tags = {
13 Name = "cloudcasts-${var.infra_env}-web"
14 }
15 create_eip = true
16 }
17  
18 module "ec2_worker" {
19 source = "./modules/ec2"
20  
21 infra_env = var.infra_env
22 infra_role = "worker"
23 instance_size = "t3.large"
24 instance_ami = data.aws_ami.app.id
25 instance_root_device_size = 20
26 subnets = keys(module.vpc.vpc_private_subnets)
27- security_groups = ["sg-095b0ec176f8fbc14"]
28+ security_groups = [module.vpc.security_group_public]
29 tags = {
30 Name = "cloudcasts-${var.infra_env}-worker"
31 }
32 create_eip = false
33 }

And as always, we can preview our changes and apply them:

1terraform plan -var-file variables.tfvars
2terraform apply -var-file variables.tfvars

Don't miss out

Sign up to learn when new content is released! Courses are in production now.