A bastion host is a server whose purpose is to provide access to a private network from an external network, such as the Internet. With the public cloud era, this is one of the favorite ways to access your private resources.
Let’s say you want to SSH your EC2 instance in your private subnet you can use the bastion which is in a public subnet to forward your traffic to your EC2 without to open public access to the EC2.
How to manage your SSH key
Managing your SSH keys in the bastion is the worst, it’s fine for a one-person project, as soon as you are a team with people leaving and some arriving you end up adding/removing keys all the time.
For this typical use case AWS has created a service called AWS Systems Manager Session Manager
and as they said :
Session Manager provides secure and auditable instance management without the need to open inbound ports, maintain bastion hosts, or manage SSH keys.
You will ask me why creating a bastion if we have Session Manager
?
A classic answer is to query a database located in a private subnet.
How to build our bastion with CDK
AWS Cloud Development Kit (CDK) lets you create your infra using real languages. In this example, I will use python but CDK is also available for java, javascript, and typescript.
The good thing when you want to create a bastion with CDK is that there is a construct for that:https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-ec2.BastionHostLinux.html
This creates a linux bastion host you can use to connect to other instances or services in your VPC.
The recommended way to connect to the bastion host is by using AWS Systems Manager Session Manager.
The operating system is Amazon Linux 2 with the latest SSM agent installed.
The file below will create a bastion with a security group associated.
https://gist.github.com/thomaspoignant/b498e45f2f4c939e53e429ae9cdced39#file-bastion-py
So as you can see, first, we are creating a security group with no inbound port open (it means that the machine cannot be SSH from anywhere). After we are creating the bastion with a few parameters like the instance type, and where to start it (here in a public subnet) and we are setting the security group to the instance.
Deploy the CDK stack
Now that our bastion configuration is ready, we just need to deploy the stack with:
cdk deploy
Because we are deploying some changes to a security group, CDK will prompt you to validate the changes.
Wait till your stack is done. What it does is running a cloudformation in your AWS account and the command line gives you some information about what was built.
And if you are going to the console you will be able to see that your new instance has started.
Connect to the bastion
To connect to the bastion you need to have your aws cli
setup and your credentials stored.
The first thing to do is to get the InstanceId
of your bastion. For that you can run:
export AWS_REGION=eu-west-3
export BASTION_INSTANCE_ID=$(aws ec2 describe-instances \
--region=$AWS_REGION \
--filter "Name=tag:Name,Values=my-bastion" \
--query "Reservations[].Instances[?State.Name == 'running'].InstanceId[]" \
--output text)
Now you have an environment variable called BASTION_INSTANCE_ID
with the InstanceId of your bastion.
Now we can use AWS Session manager to access to the bastion:
aws ssm start-session --target $BASTION_INSTANCE_ID --region=$AWS_REGION
By running this command every user of your account with the right IAM access will be able to connect to the instance. No SSH key to manage anymore, all the access is given via the IAM policies.
Conclusion
With less than 40 lines of code, you can create a bastion with Session Manager using AWS CDK.
All the complexity is hidden by the high-level construct of CDK, it means that you can be focused on what you want and not how to do it.
I really ❤ CDK
Top comments (0)