AWS Bites Podcast

126. Bastion Containers

This episode discusses solutions for securely accessing private VPC resources for debugging and troubleshooting. We cover traditional approaches like bastion hosts and VPNs and newer solutions using containers and AWS services like Fargate, ECS, and SSM. We explain how to set up a Fargate task with a container image with the necessary tools, enable ECS integration with SSM, and use SSM to start remote shells and port forwarding tunnels into the container. This provides on-demand access without exposing resources on the public internet. We share a Python script to simplify the process. We suggest ideas for improvements like auto-scaling the container down when idle. Overall, this lightweight containerized approach can provide easy access for debugging compared to managing EC2 instances.

AWS Bites is brought to you by fourTheorem an AWS consulting partner with tons of experience with AWS. If you need someone to help you with your ambitious AWS projects, check out fourtheorem.com!

In this episode, we mentioned the following resources:

Let's talk!

Do you agree with our opinions? Do you have interesting AWS questions you'd like us to chat about? Leave a comment on YouTube or connect with us on:

00:01:49

The most common one and the one that has been existing for the longest probably is setting up a jump box or bastion host which is basically an EC2 instance that has a public IP. Maybe you are protecting that instance with some security group that limits the IP ranges that can access it and then of course you have SSH keys but it's still an instance with a public IP so it's publicly reachable on the internet and that instance also has access to the private VPC so effectively what you do you establish a connection to this machine using the public internet and then use that machine as a tunnel to reach out into the private VPC and connect to the specific resource that you want to access. Other approaches are using a VPN and another thing that we've been discussing in a previous episode is still relying on the concept of a jump box but it makes it a little bit more automated and on demand and it's a CLI tool called Basti that effectively makes it easy to create that instance, create the connection for you, create the tunnel for you only when you need it so it's going to create it and destroy it depending on when you need that session and also when you want to use it to access an RDS database it does a bunch of stuff to make that access to RDS even easier for you. So you can see that as an improvement on the classic idea of the jump box or bastion host. So all of these approaches are something we discussed in detail in episode 78. So go and check out that one if you missed it we will have the link in the show notes but these are approaches that work but hopefully today we're going to be able to present a better solution but maybe let's start by discussing what are the challenges with this particular type of approaches.

00:08:56

Now SSM documents are useful for lots of different types of automation on remote servers but there's a specific one called start port forwarding session to remote host that AWS provides as an SSM document that anyone can use. So if you run this document with SSM it's actually going to set up the tunnel for you and all of a sudden you've got the magic happening that allows you to securely tunnel through to your local machine. The command syntax itself it's a bit of a mouthful but, because anyone might be interested, it goes a bit like this so you're doing `start-session` and then you pass in a target which is composed of your ECS cluster, task ID and container. But you also pass in a document name which is your "StartPortForwardingSessionToRemoteHost" document and then you give that document some parameters as a stringified JSON and those parameters have your remote host, the remote port number and the local port number. And that's going to set up one or more port mappings for you between the remote environment, the remote network and your local network. And then you can simply use your database client to connect to Postgres remotely and securely over this local port. And you can set up loads of different port mappings at the same time so you might have one tunnel for your database, one for a private API gateway endpoint, one for your ElastiCache. Once you've done the solution once it's quite easy to repeat and set up as part of your troubleshooting environment. Now there's probably a few steps there, is there any way we can kind of codify this all together, make it easier for people?

Luciano
00:10:27

Yeah probably there is room here for a new open source tool, something similar to what Basti does that tries to remove all the complexity of running multiple commands, passing the right parameters. We can probably apply that same idea to this new approach using containers. But for now we haven't done all of that, we have a simpler version of this which is effectively a Python script that we will make available in a gist, the link will be in the show notes and this should simplify this process making it easier for you to just run the right commands with just minimal configuration. It's not a lot of code so you can probably read it in 10 minutes and really understand what's going on. You should find more or less everything we explained today, just follow the order, see the different commands and how the parameters are wired together. But yeah generally what we will do is when we set a CDK project we will have the script to be part of our deployment and available when we used to use this particular pattern. And you can automate the entire process by providing this script in a development environment and for troubleshooting. For example what you do is you start a container in Fargate, you create the tunnel, you generate IAM credentials for your database users assuming you want to access the database, then you launch something like psql if your database is a Postgres. If you have another database server you need to use the correct client to access that server and the specific command that is required for your client to connect to that particular machine. So this is all we can do with this particular script but is there any room for improvement?

Eoin
00:11:56

Yeah one thing I thought that would be nice to add this would be just some automation to shut down the container automatically when the tunnel hasn't been used for a period of time. We've discussed different ways of doing this. One way might be if you capture CloudTrail events for SSM start session to your Fargate service by using CloudWatch logs for your CloudTrail. And then you could do a CloudWatch logs metrics filter which is going to count up the number of start sessions over time. You could use those metrics then to auto scale the container down when no session has been started for a certain period. Now you don't necessarily know that it's not being used just because it was started a long time ago so maybe it's also possible to use SSM session logs because you can configure SSM to also log all of the commands for compliance that are executed over a remote session. So it might be useful to do that as well to gain more detailed activity information and determine whether sessions are actually idle. We'd love to get ideas from people but generally I think this approach is a simpler option. It allows you to get those connections up for private resources because it's containerized. It might just be easier to manage, keep up to date and switch on and off on demand. I'd love to know are people using something like this from all our listeners and if you have any suggestions for improvements or other tools we can use let us know in the comments. But until next time thanks a lot for listening and we'll catch you in the next episode.

Help us to make this transcription better! If you find an error, please submit a PR with your corrections.