Terraform – Security Groups & EC2 instances

Introduction

In this blog post, we will see how we can create AWS security groups, EC2 instances and see how they can both be configured together. It is simple and can be done quickly via Terraform.

This post is in some sense continuation of the previous post on Security Groups. It introduces how you can configure your EC2 and also introduces an additional security feature – SSH keys. This blog entry is divided into the following sections

In addition, to this, we would be using IntelliJ IDE with Terraform plugin for development. All the code for these blogs is now available on GitHub in the following repo. Before jumping into this blog, please make sure you have gone thru the Terraform – Getting Started and Terraform and Security Groups.

Create AWS security group

So let’s get started. Let’s first create a security group for our blog post. It is similar as the one from my previous post. The file is called security_group.tf.

resource "aws_security_group" "cw_sg_ssh" {
  name = "cw-blog-3-sg-using-terraform"

  #Incoming traffic
  ingress {
    from_port = 22
    to_port = 22
    protocol = "tcp"
    cidr_blocks = ["11.xx.xx.xx/32"] #replace it with your ip address
  }

  #Outgoing traffic
  egress {
    from_port = 0
    protocol = "-1"
    to_port = 0
    cidr_blocks = ["0.0.0.0/0"]
  }
}

The above security group configuration only allows ssh traffic to enter the security group from a specific IP address. Make sure you update the IP addresses in CIDR block to your own IP address.

Create SSH Keys

Before go ahead and create our EC2 instance we want to make sure that it is a bit more secure. So, we introduce public-private SSH keys. Only those users who have the key will be able to login to the server. Creating a public-private key is easy and can be done using the following command.

ssh-keygen -f myblog-key

I have called the key myblog-key but you can call the key whatever you want.

Screenshot of SSH Key generation

Add SSH Key as terraform resource

If you have worked with SSH keys earlier. You would know that the public key is placed in the server and private key is kept with the user. When the user tries to SSH. The server sends the public to the terminal which is then matched with the private key. If the key is authenticated it allows you to login.

That is exactly we are also going to do. Upload the generated public key to the EC2 server when it is provisioned. To achieve that we create a terraform resource. For the sake for having some modularity let’s keep it in a separate file and let’s call it keys.tf(you can call it anything you want)

resource "aws_key_pair" "my_blog_key" {
  key_name = "my_tf_key"
  public_key = file("./ssh-keys/myblog-key.pub")
}

Code Analysis

  • Line 1 – Defines three things.
    • resource – Tells terraform that we want to provision an AWS resource.
    • resource_type – Tells terraform that what type of resource we want to provision. In this case, it is aws_key_pair
    • name – Gives a name to the resource. In our case it is my_blog_key
    • This is a recurring pattern of <resosurce> <resource type><name>
  • Line 2 – Defines the key name
  • Line 3 – Provides the path where to find the key.

Pretty simple!

Create AWS EC2 instance with a security group

Finally, it is time to create bring everything together and provision our EC2 instance. Let’s add another file and call it instance.tf

resource "aws_instance" "blog3-ec2" {
  ami = "ami-0fc841be1f929d7d1"
  instance_type = "t2.micro"
  key_name = aws_key_pair.my_blog_key.key_name
  security_groups = ["cw-blog-3-sg-using-terraform"]
}

Code Analysis

  • Line 1 – Defines three things.
    • resource – Tells terraform that we want to provision an AWS resource.
    • resource_type – Tells terraform that what type of resource we want to provision. In this case, it is aws_instance
    • name – Gives a name to the resource. In our case it is blog3-ec2
    • This is a recurring pattern of <resosurce> <resource type><name>
  • Line 2 – Defines the AMI(Amazon Machine Image) which you want terraform to use. There are many pre-built AMIs available or you can build your own AMI. You can see the list of AMI using this link
  • Line 3 – Define resources for your EC2 instance. In our case, we are going with t2.micro. A complete list of instances is available on this link
  • Line 4 – Refers to the SSH key to use for authentication to login into the EC2 instance.
  • Line 5 – Refers to the security group in which this EC2 instance is going to be created.

Few things before we move forward.

  1. We are still using our default VPC(Virtual Private Cloud). Don’t worry if you don’t understand this for now. It will be covered in lots of detail in the coming blogs.
  2. Here is how our project structure – how it looks like in IntelliJ. But you can use any editor you want.
IntelliJ with Terraform plugin

3. When there are multiple files Terraform takes care of dependency management. So there is no need to sequence the files in any way.

Demo

Time to see it all happen together and login to our EC2 instance.

Step 1 – Open a terminal session and navigate to the directory which has your terraform code and execute the following command. Terraform init initialises and downloads the plugin and does a few more things. More on that later. But for now, let’s move ahead. There will be a blog entry for this.

terraform init

Step 2 – Open a terminal session and navigate to the directory which has your terraform code and execute the following command. Enter yes when prompted!

terraform apply

If you login to your AWS account and goto EC2 instances you would be able to see your EC2 instance running.

Let’s now try and login. Take the host name from the AWS console and fire the following command

ssh -i /path/to/myssh/pvt/key ec2-user@ec2-3-10-205-246.eu-west-2.compute.amazonaws.com

I should see something like this.

You can now destroy this all using a simple command.

terraform destroy

All done! This brings us to the end of this blog. With this you have now been able to create a new security group.

  • Restrict the traffic to only SSH from a given IP address
  • Restrict who can login to EC2 instance by adding SSH RSA keys

The code we have written till now is quite rigid in nature and you may notice it is quite inflexible. But it is time to make it more flexible and interesting. The next few blogs are going to introduce to some Terraform basics which will help you write some pretty neat and powerful code.

This brings us to the end of this blog post. I hope you found this to be helpful. If you like this entry please do share it and stay tuned!!

Leave a Comment