Part 5— HumanGov Application — Terraform-3: Resources Attributes & Dependencies

Cansu Tekin
6 min readSep 28, 2023

--

HumanGov is a software-as-a-service (SaaS) cloud company that will create a Human Resources Management SaaS application for the Department of Education across all 50 states in the US and host the application files and databases in the cloud. Whenever a new employee is hired, a new registry will be created for this employee inside this application.

In this following project series, we are going to transition the architecture from a traditional virtual machine architecture to a modern container-based architecture using Docker containers and Kubernetes running on AWS. In addition, we will also be responsible for automating the complete software delivery process using Pipelines CI/CD using AWS services such as AWS CodeCommit, AWS CodePipeline, AWS CodeBuild, and AWS CodeDeploy. Finally, we will learn how to monitor and observe the cloud environment in real-time using tools such as Prometheus, Grafana, and automate one-off cloud tasks using Python and the AWS SDK.

In this section, we are going to introduce working with Resources Attributes & Dependencies in Terraform and practice Terraform with cloud provider AWS before using it in the implementation of the HumanGov application. This is the 5th part of a project series. Check Part 1, Part 2, Part 3 and Part 4 to follow up.

Resources Attributes in Terraform

In Terraform, resources define and provision infrastructure components in a cloud environment, such as a virtual machine, network interface, database, etc. Resources have attributes that allow you to configure their properties. These attributes vary depending on the type of resource.

Define a resource in Terraform:

resource "provider_resource-type" "resource_name" {
attribute_name = value
# Additional attributes...
}
  • provider_resource-type: Specifies the provider and resource type
  • resource_name: A name you give to the resource instance
  • attribute_name: The attribute of the resource for configuration
  • value: The value you want to assign to the attribute.

Example:

resource "aws_vpc" "example_vpc" {
cidr_block = "10.0.0.0/16"
}

resource "aws_subnet" "example_subnet" {
vpc_id = aws_vpc.example_vpc.id
cidr_block = "10.0.1.0/24"
availability_zone = "us-east-1a"
}

resource "aws_instance" "example_instance" {
ami = "ami-12345678"
instance_type = "t2.micro"
subnet_id = aws_subnet.example_subnet.id
}

Argument References: Attribute values can be hard-coded or referenced to other resources using argument references. It establishes relationships between different parts of the infrastructure using the attributes of one resource as inputs for another. In the example above, the aws_instance and aws_subnetresources reference the id attribute of the aws_subnet and aws_vpc respectively using their argument references.

Hands-on: Terraform Resources Attributes

We will create two resources on AWS; an EC2 instance and a security group which is a firewall for the EC2 instance. Security group ensures the security and controlled access of EC2 instances. It controls inbound and outbound traffic. This helps protect your instances from unauthorized access. Specified IP ranges, allowing or denying traffic on specific ports or port ranges (HTTP or HTTPS, SSH access, database communication, etc.) can restrict access to only authorized users. It’s a best practice to define security group rules that follow the principle of least privilege, where you only allow the minimum required traffic and deny all other traffic by default.

We are going to create an EC2 instance first and then associate a security group to this instance.

Create and provision an EC2 instance and a security group

Open AWS Cloud9 and create a resources.tf file.

Go to the Terraform documentation to use the latest instructions.

Look for aws_instance and aws_security group. We are going to use instructions in these sections.

Step 1: Define the ami Attribute

We need an Amazon Machine Image(AMI) for the EC2 instance inside Terraform resources.tf file. An AMI is a pre-configured virtual machine image used to create EC2 instances and contains the necessary information to launch an instance, including the operating system, applications, and configurations. The ami attribute specifies the AMI.

Go to AWS Console and search for EC2. Go to Launch Instance. Normally, if we create an EC2 instance and select an operating system, for example, Linux, AWS assigns an AMI ID to this instance. This AMI is operating system and region-specific. We are going to use this ID inside our terraform file to configure the EC2 instance using the ami attribute.

Step 2: Create EC2 Instance Resource with ami and instance_type attributes

resource "aws_instance" "example" {
ami = "ami-051f7e7f6c2f40dc1" # This is an Amazon Linux 2 AMI ID in the us-east-1 region
instance_type = "t2.micro"
}

In Terraform, the instance_type attribute determines the virtual machine's hardware configuration, including the number of virtual CPUs, amount of memory, storage capabilities, and network performance.

Step 3: Create security_group Resource

We are going to open port 22 which allows inbound SSH traffic.

resource "aws_security_group" "example" {
name = "example"
description = "Example security group"

ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}

Using the cidr_blocks attribute to specify the IP range that is allowed to connect via SSH. Using "0.0.0.0/0" allows SSH access from any IP address, which might not be the most secure option. You can replace it with a more specific IP range.

This is the Terraform resources.tf file on AWS Cloud9 so far:

Step 4: Link security_group and EC2 Instance Resources

The security groups you attach to an EC2 instance will dictate the rules for inbound and outbound traffic to and from that instance. In Terraform, you need to create security groups before the EC2 instance to be able to attach them.

We can specify the vpc_security_group_ids attribute to associate the EC2 instance with the security. Using dependency such as this lets Terraform create the security group first and assign its value to the attribute. Therefore, it can associate the security group with the EC2 instance.

 resource "aws_instance" "example" {
ami = "ami-051f7e7f6c2f40dc1" # This is an Amazon Linux 2 AMI ID in the us-east-1 region
instance_type = "t2.micro"
vpc_security_group_ids = [aws_security_group.example.id]
}

Step 5: Run Terraform

Now we can run terraform to create resources with defined resource attributes. First, make sure you are inside the right folder where resources.tf file is located. Then run apply to see what is planned, and apply planned changes.

cd humangov-terraform/
terraform plan
terraform apply

You can see that Terraform created the security group first and the EC2 instance later due to dependency.

Go to AWS -> Services -> EC2 -> Instances

You should be able to see the running instance that we created with Terraform.

When you go inside and check the Security, you will see the security group that we attached.

Step 6: Destroy Resources

terraform destroy

Make sure to destroy resources that you will not need and use, otherwise, you will be charged.

CONGRULATIOTIONS!!

--

--

Cansu Tekin

AWS Community Builder | Full Stack Java Developer | DevOps | AWS | Microsoft Azure | Google Cloud | Docker | Kubernetes | Ansible | Terraform