Introduction

In this post I will provide an introduction to Roadhouse, a python library for managing security group settings across multiple VPCs in AWS. At the conclusion, you will have an understanding of the benefits of using Roadhouse as well as be able to implement it yourself in your infrastructure.

First off - what is the purpose of a VPC? A VPC provides an isolated network within Amazon, allowing you similar control as if you were managing the switches yourself. The security groups within a VPC are isolated. By default a VPC doesn’t even provide access to the outside word.

It’s important to answer the question: How does a VPC help us? Today’s companies are frequently built out from microservices, instead of one giant monolithic service. This allows for separation of resources, both hardware and engineering. Martin Fowler has a great article on explaining the benefits of microservices and it’s benefits as an organization grows. The side effect of microservices in an AWS environment is now the operations team needs to manage potentially dozens of different environments. Some companies handle this change by simply using one VPC for each environment, ie: staging & production. In my opinion, this is doing it wrong. It is better to use VPCs to provide service isolation, one for each instance. In short, we can think of a VPC as a virtual container for an instance of a microservice within a region.

While it’s possible for every single microservice to have its own tech stack, release process, security groups, etc, it’s beneficial to find some common ground. For an operations team, having a common set of databases, web servers, search, as building blocks, is the ideal. This allows a single team to scale to any number of services while maintaining a single set of templated configurations that can be applied to each VPC. Roadhouse focuses on a security groups as a template. Assuming we can have some sort of consistency of security group rules across VPCs, we can use a roadhouse configuration like a rubber stamp, and apply those rules to each VPC.

Real World Example

Lets say our company, Joe’s Widgets, has one website, but its complexity leads to breaking it into microservices. There is a user service, one for payment processing, and one for inventory. Each of the services maintains its own Cassandra cluster and web server farm, and maybe Redis for caching. So each VPC we want to create looks kind of like this:

We know that in each VPC, we’ll want the following security groups and rules:

  • cassandra (port 9042, open to web server)
  • redis (port 6379, open to web server)
  • web server (no open ports for now)

If each service has 2 data centers (east & west cost for high availability), plus 1 for a staging environment, we’re already looking at a minimum of 9 VPCs. Managing this manually is unacceptably time consuming.

Enter Roadhouse

We see a pattern emerge. What if we could reliably replicate the same security group settings across each VPC? Managing this with the AWS api is certainly possible, but there are enough edge cases where it becomes extremely tedious. Additionally, reviewing the code can be difficult when logic starts to get added about removing rules, new port ranges, etc. When it comes to managing servers, we use tools like Puppet and Chef, we don’t script anymore. Why write complex code when you can specify what something should be in a declarative manner?

Roadhouse allows you to write configuration instead of code. For example, in the above scenario, our configuration would look like this:

web:
    options:
        description: web server

cassandra:
    options: 
        description: cassandra
    rules:
        - tcp port 9042 web

redis:
    options:
        description: redis servers
    rules:
        - tcp port 6379 web
        

As you can see, it’s trivial to write rules in a declarative manner. You may specify multiple rules, port ranges, TCP / UPD / ICMP, IPs, and named groups. Maybe we want to add nagios to the mix and allow office access:

nagios:
    options:
        description: monitoring
    rules:
        - tcp port 22,80 173.1.1.0 

The next time you apply the roadhouse configuration to the VPC, the rules will sync. Any new rules you add will be applied. Currently roadhouse does not remove existing rules or do any destructive actions, but plans for pruning are in the works. Additionally, the /32 mask is automatically assumed unless you specify an optional /mask.

Using Python & boto, the logic to apply the configuration to our VPCs looks like this:

from boto import ec2
from boto import vpc
from roadhouse.group import SecurityGroupsConfig

v = vpc.connect_to_region('us-west-1')
e = ec2.connect_to_region('us-west-1')

config = SecurityGroupsConfig.load("roadhouse.yaml")
config.configure(e) # registers the configuration manager to a specific region

for vpc in v.get_all_vpcs(): # loop over each VPC in this region
    config.apply(vpc) # apply our security group settings to this VPC

To reference the example above, we apply our template to each of our 3 VPCs, creating the same security group rules in every VPC:

We now have a situation where we can repeatably and reliably rubber stamp our security group settings across hundreds of VPCs without adding a single line of additional logic. This is incredibly powerful, and allows small operations teams to scale with the growing needs of the business.

Next Steps

Now that you know what Roadhouse is useful for, you should try it out. It’s available on pypi:

pip install roadhouse

Check out the readme for more examples. Please be sure to create an issue if there’s anything confusing, or that seems to be working incorrectly!