I have recently started learning Terraform to manage my AWS resources, And it is a great tool for maintaining your infrastructure! I use a Bastion host to SSH into my main servers and bring up the bastion host on demand only when I need it giving me some cost savings. Here are the required Terraform files to get this working.
Set up the bastion.tf
file like so:
1 | # get a reference to aws_ami.id using a data resource by finding the right AMI |
Set up the terraform.tfvars
file like so:
1
2
3
4
5
6
7
8
9
10
11# Set this to `true` and do a `terraform apply` to spin up a bastion host
# and when you are done, set it to `false` and do another `terraform apply`
bastion_enabled = false
# My SSH keyname (without the .pem extension)
ssh_key_name = "hyperngn_aws_ohio"
# The IP of my computer. Do a `curl -sq icanhazip.com` to get it
# Look for the **ProTip** down below to automate this!
myip = ["247.39.103.23/32"]
Set up the vars.tf
file like so:
1
2
3
4
5
6
7
8
9
10
11
12
13variable "ssh_key_name" {
description = "Name of AWS key pair"
}
variable "myip" {
type = list(string)
description = "My IP to allow SSH access into the bastion server"
}
variable "bastion_enabled" {
description = "Spins up a bastion host if enabled"
type = bool
}
Relevant sections from my vpc.tf
, you could just hardcode these values in the
bastion.tf
or use data
if you’ve set these up manually and resources
if
you use terraform to control them
1 | resource "aws_subnet" "subnet" { |
Finally you need to set up your ~/.ssh/config to use the bastion as the jump host like so:
1 | # Bastion config |
Once you are done, you can just login by running the following command and it should run seamlessly:
1 | ssh ecs1 |
Pro-Tip Put the following in your terraform folder’s .envrc, so that you
don’t have to manually copy paste your IP every time you bring your bastion host
up (You also need to have direnv for this to work).
1
2$ cat .envrc
export TF_VAR_myip="[\"$(curl -sq icanhazip.com)/32\"]"
Gotchas
- If you run into any issues use the
ssh -vv ecs1
command to get copious logs and read through all of them to figure out what might be wrong. - Make sure you are using the correct
User
, Ubuntu AMIs create a user calledubuntu
whereas Amazon ECS optimized AMIs create anec2-user
user, If you get the user wrongssh
will fail. - Use private IPs for the target servers that you are jumping into and the public IP or public DNS for your bastion host.
- Make sure your Bastion host is in the same VPC with a default security group which allows inter security group communication and a security group which opens up the SSH port for your IP. If they are not on the same VPC make sure they have the right security groups to allow communication from the bastion host to the target host, specifically on port 22. You can use VPC flow logs to figure problems in your network.
From a security point of view this is a pretty great set up, your normal servers don’t allow any SSH access (and in my case aren’t even public and are fronted by ALBs). And your bastion host is not up all the time, and even when it is up, it only allows traffic from your single IP. It also saves cost by tearing down the bastion instance when you don’t need it.