Skip to content

hazelops/terraform-aws-ec2-bastion

Repository files navigation

AWS Terraform Module EC2 Bastion over SSM

This module creates ec2 bastion host in private subnet (without Public IP-address) of a VPC and connects it to a System Manager and copies your ssh public key to .ssh/authorized_keys on the bastion ec2. Bastion host can be controlled by Session Manager documents.

Prerequisites

EC2:

  • System Manager Agent must be installed and running (version 2.3.672.0 or more recent)
  • The EC2 instance must have an IAM role with permission to invoke Systems Manager API (e.g. AmazonSSMManagedInstanceCore)

Local PC:

  • AWS Command Line Interface (CLI) (1.16.220 or more recent)
  • System Manager CLI extension (version 1.1.26.0 or more recent)

https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html

Example:

module "bastion" {
    source    = "hazelops/ec2-bastion/aws"
    version   = "~> 3.0"
    
    aws_profile       = var.aws_profile
    env               = var.env
    vpc_id            = local.vpc_id
    private_subnets   = local.private_subnets
    ec2_key_pair_name = local.ec2_key_pair_name

    ssh_forward_rules = [
      "LocalForward 11433 ${module.rds.sql_endpoint}:${module.rds.sql_port}",
      "LocalForward 44443 ${module.yourapp.alb_dns_name}:443"
    ]
}

Usage:

  1. Create config file in ~/.ssh folder with this:
# SSH over Session Manager
host i-* mi-*
    ProxyCommand sh -c "aws --profile ${var.aws_profile} ssm send-command --instance-ids %h --document-name AWS-RunShellScript --comment 'Add an SSH public key to authorized_keys' --parameters commands='echo ${var.ssh_public_key} >> /home/ubuntu/.ssh/authorized_keys' &&  aws --profile <aws_profile> ssm start-session --target %h --document-name AWS-StartSSHSession --parameters 'portNumber=%p'"

where ${var.aws_profile} - actual aws cli profile; and ${var.ssh_public_key} - your ssh public key (~/.ssh/id_rsa.pub)

  1. Options to run:
  • start tunnel:
ssh -M -S bastion.sock -fNT ubuntu@<instance-id> -L <local_port>:<address of remote host>:<remote_port>
  • check tunnel status:
    ssh -S bastion.sock -O check ubuntu@<instance-id>
    
  • stop tunnel:
    ssh -S bastion.sock -O exit ubuntu@<instance-id>
    

Where:

<instance-id> - bastion ec2 instance-id (see in module output)

<local_port> - port which you want to be used at local machine

<address of remote host> - an address we want to make tunnel to.

<remote_port > - port on remote instance to connect to.

Example of tunnel creation :

  • For example, you need to create a tunnel from localhost to bastion host with ports: 10022:
ssh -M -S bastion.sock -fNT ubuntu@<instance-id> -L 10022:localhost:22

v.1.0 AWS EC2 Bastion Terraform Module

Module creates ec2 bastion host with Public IP-address in VPC.

Example:

module "bastion" {
    source    = "hazelops/ec2-bastion/aws"
    version   = "~> 1.0"
    
    env               = var.env
    vpc_id            = local.vpc_id
    zone_id           = local.zone_id
    public_subnets    = local.public_subnets
    ec2_key_pair_name = local.ec2_key_pair_name

    ssh_forward_rules = [
      "LocalForward 11433 ${module.rds.sql_endpoint}:${module.rds.sql_port}",
      "LocalForward 44443 ${module.yourapp.alb_dns_name}:443"
    ]
}

Requirements

Name Version
terraform >= 0.12
local ~> 1.2

Providers

Name Version
aws n/a

Modules

No modules.

Resources

Name Type
aws_iam_instance_profile.this resource
aws_iam_role.this resource
aws_iam_role_policy_attachment.this resource
aws_instance.this resource
aws_security_group.this resource
aws_ami.this data source
aws_iam_policy_document.this data source

Inputs

Name Description Type Default Required
allowed_cidr_blocks List of network subnets that are allowed. According to PCI-DSS, CIS AWS and SOC2 providing a default wide-open CIDR is not secure. list(string) n/a yes
aws_profile n/a any n/a yes
ec2_key_pair_name n/a any n/a yes
env n/a any n/a yes
ext_security_groups External security groups to add to bastion host list(any) [] no
instance_type n/a string "t3.nano" no
name n/a string "bastion" no
public_subnets n/a any n/a yes
private_subnets n/a any n/a yes
ssh_forward_rules Rules that will enable port forwarding. SSH Config syntax list(string) [] no
ssm_role n/a string "arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM" no
vpc_id n/a any n/a yes

Outputs

Name Description
cmd n/a
instance_id n/a
security_group n/a
ssh_config n/a