15 Mar, 2017

CodeBuild, Brakeman, and CodePipeline

by Ken Johnson

I’m tired of running a Jenkins server; there, I said it. It costs us money, I have to keep it patched, and patching equates to lost energy. Lost energy and lost time which means lost forward momentum working on the things we should be focused on. This is where CodeBuild came into play. We were already using CodePipeline but wanted to use CodeBuild because CodeBuild integrates with CodePipeline. CodeBuild is a replacement for Jenkins, it is a managed service by AWS, and it costs very little.

If you are unfamiliar with the AWS CodePipeline tool, let me give you a basic rundown. New code is pushed to your code repository. CodePipeline detects this change and pushes the new code through various stages, ultimately ending up at your production server.

Those stages are user-defined; and in my case, I added a CodeBuild stage. It isn’t very complicated. Embed a buildspec.yml file into your application, the yaml file has optional installation, pre-build, build, and post-build as well as environment variable key/value pairs. This link offers additional details.

buildspec.yml File

My main concern here was running Brakeman scans. If you’re not familiar with Brakeman, it is a Ruby on Rails security static analysis tool written by Justin Collins. There is an open source version as well as a Pro version. The open source version of Brakeman integrates well into our deployment pipeline while, alternatively, our consultants use the Brakeman Pro version/product to help delve deep into Rails security assessments.

We only wanted our build to fail, therefore denying that code the ability to run on production servers, when high confidence findings (not likely to be false positives) were detected. Additionally, we did not want to print the output to the logs. This is why I used the -z and -w options. The -w 3 option equates to only the highest confidence findings, -z is used to silence output.

With our buildspec.yml file in place, we needed to plug CodeBuild into our CodePipeline. We already had CodePipeline set up. Our setup is simplistic: CodePipeline detects changes in the master branch of our code hosted on GitHub and then pushes that code into Elastic Beanstalk (EB). The setup for pulling code from GitHub and pushing into EB is so simple you do not need instructions to do it. However, the addition of a testing phase using CodeBuild is a little less easy, so let’s discuss that.

Between pulling new code from GitHub and pushing into EB, we wanted to add a testing phase. To do this, I clicked on the ‘+’ stage button.


The next few steps were, in order:

  1. Give the stage a name—I chose “Tests” (super creative, I know).

  2. Choose the Action category “Test”.

  3. Name the Action.

  4. Then choose a test provider, which would be CodeBuild.

Add a Stage to CodePipeline

We’ll continue with the addition of “Project” options. Projects belong to the Action, in this case, our Project is a CodeBuild Project. Again, here are our steps, in order:

  1. Create a new Build project (since we didn’t have any pre-existing CodeBuild projects).

  2. Name the Project.

  3. Use an image managed by AWS (although, you can use docker images).

  4. Choose Ubuntu.

  5. Choose the Ruby language.

  6. Then choose version 2.3.1.

  7. Although you have the option of entering commands manually through the web interface, a buildspec.yml file is a cleaner way to handle this because of versioning through your SCM and the ability to insert multiple commands per stage of the build (e.g. install, post and pre-build, etc.) - so we chose this option.

Create a CodeBuild Project

Finally, we needed to configure a few remaining options. By default, a service role should be created with an auto-generated name, but you can change this if you wish. Lastly, we gave our artifacts (both input and output) names.

Configure the Remaining CodeBuild Steps

At this point, we were ready to hit “Add Action” and save our pipeline. I got an error regarding CodePipeline not having CodeBuild permissions. If you do, this is a simple fix: go into your IAM role for CodePipeline and add the following lines to the attached policy (attached to the CodePipeline role).

CodePipeline Role Policy Addition

Once you’re finished, and assuming you don’t have any high confidence warnings, you should see the following:

Successful Completion

Let’s recap. We wanted to introduce security scans into CodePipeline so that builds failed in the event we had a security issue. We no longer wanted to utilize a Jenkins server for this task, so we used CodeBuild instead. Now we have a low-cost, managed service to run our security scans by using CodeBuild and Brakeman.