This Terraform module deploys a bastion service on ECS Fargate for use with AWS Systems Manager Session Manager to securely port-forward into a VPC from the Internet.
Although designed for seamless use with our terraform-aws-ssm-tunnel module to enable provisioning of VPC resources (RDS, ES, etc) directly from your Terraform code, it can be used standalone with the AWS CLI as well.
- Deploys an ECS Cluster, Service, and Task Definition with required least-privilege IAM permissions for the bastion to run, inside your VPC
- Creates a default security group allowing all outbound traffic (can be disabled if you want to provide your own)
- Supports all TCP port forwarding use cases through AWS SSM Session Manager
- Auto-healing if the bastion task fails or if there are underlying infrastructure issues
- Customizable CPU and memory allocation for the Fargate task
- Optionally assign a public IP to the bastion task if you don't have a NAT gateway or ECR, SSM & SSM Messages VPC endpoints
- Optionally run multiple concurrent instances of the bastion task for high availability
SSM Session Manager advantages over traditional SSH bastions
- Simpler setup — No need to manage keys and user access manually, authn is handled natively in IAM next to your existing access controls
- Better security — no need to open inbound ports from the Internet or whitelist IP addresses as communication is relayed through the AWS SSM service
Advantages using SSM Session Manager on Fargate versus an EC2 instance
- Set it and forget it — there are no stateful components, so no EC2 lifecycle to manage, no auto-scaling group to configure, no OS to patch, no instance to monitor, no storage to back up, etc.
- Better security — smaller attack surface: no SSH daemon, no OS to exploit, more layers of the stack are managed by AWS
- Built-in High Availability — the ECS service is self-healing as any issue will cause the taks to be redeployed and several instances can optionally across multiple Availability Zones
- Cost-effective — the cost is roughly the same as in EC2, with all the added benefits above.
In the default configuration, in eu-west-1
and as of this writing, the costs are:
Resource | Cost | Estimated monthly cost |
---|---|---|
Fargate Task (0.25 vCPU, 0.5 GB) | $0.009875 per hour | $7.21 |
Estimated total: $7.21 per month
- ARM support
- Fargate Spot support
- IPv6 support (dualstack and IPv6-only)
Name | Version |
---|---|
terraform | >= 1.0 |
aws | >= 5.0 |
Name | Version |
---|---|
aws | >= 5.0 |
No modules.
Name | Type |
---|---|
aws_ecs_cluster.this | resource |
aws_ecs_service.this | resource |
aws_ecs_task_definition.this | resource |
aws_iam_role.task | resource |
aws_iam_role_policy.task_ecs_exec | resource |
aws_iam_role_policy_attachment.task_ecs | resource |
aws_security_group.this | resource |
aws_iam_policy_document.task_ecs_exec | data source |
Name | Description | Type | Default | Required |
---|---|---|---|---|
assign_public_ip | Whether to assign a public IP to the bastion task. If false, you will need a NAT gateway or at least ECR, SSM & SSM Messages VPC endpoints | bool |
false |
no |
create_default_security_group | Whether to create a default security group allowing all outbound traffic for the bastion task. If false, you will need to provide your own in security_groups |
bool |
true |
no |
desired_count | Number of instances of the bastion task to run | number |
1 |
no |
name | The name of this stack. This will be used in the names of all resources created by this module | string |
n/a | yes |
security_groups | The IDs of the security groups to attach to the bastion task | list(string) |
[] |
no |
subnets | The IDs of the subnets where the bastion should run | list(string) |
n/a | yes |
task_cpu | Number of CPU units to allocate for the bastion task | number |
256 |
no |
task_memory | Amount of memory (in MiB) to allocate for the bastion task | number |
512 |
no |
vpc_id | The ID of the VPC where the bastion should run | string |
n/a | yes |
Name | Description |
---|---|
default_security_group_id | The ID of the default security group created for the bastion task |
ecs_cluster_name | The name of the ECS cluster where the bastion task is running |
ecs_service_name | The name of the ECS service running the bastion task |