This module launches an EC2 instance that acts as a bastion host for Systems Manager (SSM) Session Manager. This allows users to connect to the instance as an entry point to the VPC without needing to manage SSH keys or open the instance to the internet.
Before you can create a bastion, you will need an EC2 key pair to connect with. See the key_pair_name section for instructions on creating and defining a key pair.
Add this module to your main.tf
(or appropriate) file and configure the inputs
to match your desired configuration. For example:
module "bastion" {
source = "github.com/codeforamerica/tofu-modules-aws-ssm-bastion?ref=1.0.0"
project = "my-project"
environment = "development"
key_pair_name = "my-project-development-bastion"
private_subnet_ids = module.vpc.private_subnets
vpc_id = module.vpc.vpc_id
}
Make sure you re-run tofu init
after adding the module to your configuration.
tofu init
tofu plan
To update the source for this module, pass -upgrade
to tofu init
:
tofu init -upgrade
To connect to the bastion host, you can connect directly using the Systems Manager cli, or through SSH. For either method, you will need to have the latest version of the AWS CLI, and your credentials configured for the appropriate account.
Tip
You can install the required tools on macOS using Homebrew:
brew install awscli session-manager-plugin
You can connect to the instance using the AWS CLI and the Session Manager plugin:
aws ssm start-session \
--target <INSTANCE ID>
There are a number of additional options available for more complex use cases. See the start-session and starting a session documentation for more information.
This is the preferred method of connecting as it does not require distributing the private key, and can be audited and controlled through IAM policies.
You can connect using traditional SSH. This is helpful if you have existing tooling built around SSH.
Before you can begin, you will need to write the private key to a local file. We
recommend giving it an easy to identify name and storing it in $HOME/.ssh
. For
example, $HOME/.ssh/my-project-development-bastion.pem
. Restrict the file's
permissions with chmod 600 <FILE NAME>
.
Additionally, you will need to create an SSH configuration to proxy the request
to the AWS CLI. Add the following to $HOME/.ssh/config
:
# SSH over Session Manager
Host i-* mi-*
ProxyCommand sh -c "aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters 'portNumber=%p'"
User ec2-user
You can now connect using SSH:
ssh -i <KEY FILE> <INSTANCE ID>
For example:
ssh -i $HOME/.ssh/my-project-development-bastion.pem i-0a1b2c3d4e5f6g7h8
To enable port forwarding, you can add the -L
flag to the SSH command. For
example, the following command forwards localhost port 9999 to google.com
port
443:
ssh -i $HOME/.ssh/my-project-development-bastion.pem -L 9999:google.com:443 i-0a1b2c3d4e5f6g7h8
Name | Description | Type | Default | Required |
---|---|---|---|---|
private_subnet_ids | The IDs of the private subnets in which the bastion host should be deployed. | string |
n/a | yes |
project | Name of the project. | string |
n/a | yes |
vpc_id | The ID of the VPC in which the bastion host should be deployed. | string |
n/a | yes |
environment | Environment for the project. | string |
"dev" |
no |
instance_type | The instance type to use for the bastion host. | string |
"t2.micro" |
no |
key_pair_name | Name of the EC2 keypair to associate with the instance. Defaults to ${project}-${environment}-bastion . |
string |
"" |
no |
kms_key_recovery_period | Recovery period for deleted KMS keys in days. Must be between 7 and 30. | number |
30 |
no |
tags | Optional tags to be applied to all resources. | list |
[] |
no |
In order to access the bastion host via SSH, you must have an EC2 key pair. While we could generate a key pair for you, the private key would be stored in the state file in plain text. Instead, you should create a key pair manually.
You can create a new key pair using the AWS CLI:
aws ec2 create-key-pair \
--key-name <KEY NAME> \
--key-type ed25519 \
--key-format pem \
--tag-specifications 'ResourceType=key-pair,Tags=[{Key=project,Value=<PROJECT>},{Key=environment,Value=<ENVIRONMENT>}]' \
--query KeyMaterial \
--output text > <KEY NAME>.pem
Tip
If you choose a key name that matches the default pattern
(${project}-${environment}-bastion
), you can omit the key_pair_name
input.
For example:
aws ec2 create-key-pair \
--key-name my-project-development-bastion \
--key-type ed25519 \
--key-format pem \
--tag-specifications 'ResourceType=key-pair,Tags=[{Key=project,Value=my-project},{Key=environment,Value=development}]' \
--query KeyMaterial \
--output text > my-project-development-bastion.pem
Store the private key in a secure location and share it with the appropriate
users. If you chose a different key name, you must provide it as the value to
key_pair_name
.
Name | Description | Type |
---|---|---|
instance_id | ID of the bastion instance. | string |
Follow the contributing guidelines to contribute to this module.