Deploy bastion hosts into private subnets with AWS CDK
Deploying bastion hosts in private subnets is a way to provide temporary and limited access to non-production private resources in a virtual private cloud (VPC). Bastion hosts typically sit in public subnets. But in a non-production environment, if you want to allow a group of developers to access an private resource, you might not want to use a bastion host accessible from the internet.
In this post, we explain how to provision scalable and extendable secure bastion hosts in private subnets using AWS Cloud Development Kit (AWS CDK). First, I’ll show you how to configure AWS CDK and clone the GitHub repository I’ve prepared. Second, we demonstrate using AWS CDK to define the target environment and deploy the bastion host stack into a new or existing VPC.
Finally, we create an AWS Identity and Access Management (IAM) policy. We demonstrate how users with that policy can access the bastion host using three operations. We use the AWS Systems Manager Session Manager plugin for the AWS Command Line Interface (AWS CLI), SSH (Secure Shell), and the AWS Management Console. Our process follows AWS Security best practices of granting least privilege and using roles to delegate permissions.
|About this blog post
|Time to read
|Time to complete
|Cost to complete
|Costs depend on the VPC resources provisioned. For more information, refer to Amazon VPC pricing.
|AWS Systems Manager
Amazon Elastic Compute Cloud (Amazon EC2)
AWS Secrets Manager
Figure 1 shows the high-level architecture of our process. Only IAM users can access the bastion host in the private subnet of the VPC. They can use the Session Manager plugin for AWS CLI, SSH, or the AWS Systems Manager console.
Figure 1. Accessing a bastion host in the private subnet
The GitHub repository we provide contains two stacks.
AwsBastion-NetworkCdkStack deploys a new VPC, but you can also use an existing VPC. If you use an existing VPC, you won’t deploy the first stack.
AwsBastion-Ec2CdkStack deploys into the private subnet the bastion host, EC2 key pair, security group, and IAM role and policy.
As we show in the walkthrough, we use the
allowedSecurityGroups parameter in
cdk.json to define the resources to which the bastion host connects. In the example shown in Figure 1, the bastion host connects to an Amazon RDS database instance in an isolated subnet.
Before getting started, make sure that you have the following.
- An AWS account. If you don’t have an AWS account, sign up at https://aws.amazon.com.
- AWS CDK and version 2 of the AWS CLI.
- Session Manager plugin for the AWS CLI.
- Node.js and the Npm command line interface.
Step 1: Configure deployment environment
- Create an IAM user in your AWS account. Make sure that you configure programmatic access with
AWS access key IDand
AWS secret access keyand add IAM identity permissions to the
- Run the following command to create a profile named
$ aws configure --profile bastion-cdk
- The AWS CLI prompts you for four configuration settings. The following example shows sample values. Replace
AWS Access Key IDand
AWS Secret Access Keywith the credentials for the user you create in step 1.
AWS Access Key ID [None]: <AKIAIOSFODNN7EXAMPLE>
AWS Secret Access Key [None]: <wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY>
Default region name [us-east-1]: <us-east-1>
Default output format [json]: <json>