Here at UserZoom, we like to go from good to great! That’s why we took the best parts of Infrastructure as Code and created a new concept for security operations...
Companies are constantly evolving. In a world where Agile is gaining momentum and delivering fast is a must, sometimes security is compromised along the way. Keeping track of all the improvements, having a sturdy change management procedure, and keeping up with the speed seems almost impossible.
Thanks to Infrastructure as Code it is possible to design all the infrastructure settings, changes, migrations, and much more through code.
The benefits are clear: a single source of truth of the required configurations, reducing the cost of deploying the same infrastructure in different scenarios, bring down human errors, as well as the added robustness of managing everything with code; having code reviews, approvals, blames, and all the amazing git features you want!
Here at UserZoom, we like to go from good to great! That’s why we took the best parts of Infrastructure as Code and created a new concept for security operations, I will let you guess… yeah it’s Security as Code! The main concept still remains the same, to be able to deploy security measures, rules, access controls, and alerting systems through code... but there's more.
An excellent use case may be a scenario where multiple AWS accounts need to be managed and secure in a similar way. Having to deal with manual changes, tracking which account has what rules enabled, and not being able to get the whole picture of the security state of your accounts used to be a nightmare. Thanks to Security as Code we just need to ensure the code reflects our compliance and security policies and then that’s it! (Almost... there’s a lot of magic to be done before that.)
We use Terraform to manage the security infrastructure. It has a huge community of developers and is constantly evolving, which also makes it challenging. There are certain AWS services that we need to have configured in the same way across all the AWS accounts, for example, AWS Config, AWS Guardduty, Cloudtrail, VPC flow logs, etc. Basically monitoring and alerting resources. The bread and butter of the security teams.
Example schematics of AWS Security Services
There are many different ways to work with Terraform and organize a project. We decided to go with an environment-branching-git-flow approach. So basically we have a branch for each environment we have. That way, we know for sure what changes are deployed where reducing human errors and configuration deviations from the code. And for the development, we went with the classic git-flow process.
So, as an example... If we wanted to deploy a new AWS config rule on all the accounts we would first checkout master, work on a feature branch and open a PR to a DEV environment. Once tested and deployed, we would open a new PR to a STAGING environment, and eventually a PR against MASTER with those changes. For hotfixes, we would merge to MASTER and then propagate the changes into the different environments via PR.
Source: https://github.com/SvanBoxel/release-based-workflow/issues/1
Another common scenario where we use Terraform is to manage our source code settings in GitHub.
Imagine you have a GitHub organization with 100 repositories. Imagine that your CTO requests that you implement some changes in order to be compliant with the new legislation. In the good old days, you would have to go one by one and manually change all the settings. You could speed things up using the GitHub API, but then how could you enforce that nobody changed those settings? How could you reflect in your change management process that configuration request? What if you need to add external collaborators to only specific repositories, you would need to do that manually, right?
All these problems are solved using terraform to define the GitHub infrastructure! It also helps small security teams to ensure the security policies are enforced. Nobody will bypass your security controls without encountering a smart security engineer ready to smash some policies.
It also empowers the developers to be able to request access using the language that is flowing through their veins, code. Instead of sending an email, Slack, calling a busy security engineer to request access, and slowing the process, they just need to create a PR with the accesses they need. The corresponding code reviewers approve or deny the request, add discussions, interact with the requester all in the same place where it is going to be implemented.
Can we make this process even a little better? Why not add some checks into the changes we are making in our code? We would not want to introduce bugs or malicious code into what’s supposed to be security as code. Thus we rely on GitHub actions to make those checks and then automatically apply the required changes. Here is an example of the workflow for the Pull Requests:
name: Terraform Plan Security
on:
pull_request:
branches:
- main
paths:
- ‘security/**’
workflow_dispatch:
defaults:
run:
working-directory: security
jobs:
terraform-actions:
name: Workflow
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@master
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
role-duration-seconds: 1200
- name: Setup Terraform
uses: hashicorp/setup-terraform@v1
- name: Terraform Fmt
id: fmt
run: terraform fmt -check -diff
continue-on-error: true
- name: Terraform Init
id: init
run: terraform init
continue-on-error: true
- name: Terraform Validate
id: validate
run: terraform validate -no-color
continue-on-error: true
- name: Terraform Plan
id: plan
run: |
terraform plan -no-color;
continue-on-error: true
- name: ‘End results’
shell: bash
run: |
echo fmt
test ${{ steps.fmt.outputs.exitcode }} -eq 0
echo init
test ${{ steps.init.outputs.exitcode }} -eq 0
echo validate
test ${{ steps.validate.outputs.exitcode }} -eq 0
We would basically do the same for the terraform apply but thanks to this action we can ensure that the code has been validated, we will see the plan and its changes and we then can review and approve code based on those checks.
Thanks to Security as Code we have reduced the amount of time and resources dedicated to making sure we are compliant with our security policies whilst implementing a more resilient procedure.
Of course, there are always going to be ways to bypass these restrictions, but having a good change procedure will make those deviations visible, which is half of the battle in any defense team!