How to Protect Your CI/CD Pipelines from... Yourself

Have you found yourself in any of these situations?

  • You deployed a broken or an old branch to production, making some features disappear, while allowing broken ones to go live?
  • You deleted a database because you ran the wrong command on the command line?
  • You gave the wrong person access to the system and had to clean up the mess?

I think most engineers have experienced situations like these at some point in their career. (I have.) One of the traps that we hit so often early in our careers is being a bit overconfident, breezing through our work, and then all of a sudden we run a command, or click a thing, and poof, it's all gone.

Now that I am in a senior role, I have a little less fear about those early mistakes, but I’m still vigilant about securing myself and my team.

Buildkite has some features that help our users secure their systems and protect against someone who shouldn't have particular access within the system.

Here are three to know.

Human Gates (Block Step)

One way to stop someone from performing a “dangerous” action is to block them from executing a build until someone else can authorize the action and confirm that it’s safe. Buildkite’s block step pauses the execution of a build until a team member unblocks it.

When you define a block step in your pipeline settings, you can set them up to ask for text input (e.g., a changelog entry) or radio button select input. Once the steps before the block are complete, the execution of the pipeline will pause until an authorized team member allows it to move forward.

A block step is useful for situations where you don’t want something to deploy until it's had signoff from a particular team in your organization.

Blocked State

blocked_state is a block step attribute that we released in 2020. It was introduced to solve a previous problem with Buildkite, in which when a build was blocked, it would show as “passed” in the Buildkite UI and other integrations. That clearly wasn’t OK for some pipelines. If a step needs key person approval, a developer shouldn’t be able to merge pull requests.

Now, when the build is blocked, you can choose whether the build shows as “failed” or “running” so that you can't merge it.

Permission Structure

It goes without saying, but access control is key to securing yourself. Even for tiny organizations, can you trust every single contributor to not click the wrong thing? Within Buildkite there are two ways to manage access control: by enabling user-level Members permissions or Teams.

Member permissions are really important for ensuring that only authorized people can add or remove pipelines and agents. This is an essential tool in big organizations with change management policies in place, where it's important these actions can't be done by just anyone.

Teams are really handy for scoping pipeline access to different groups. This would usually map to the team/code ownership structure within the organization. For example, Teams is a commonly used feature at organizations where there are tight controls over who can work on infrastructure. At such a place, product engineers and site reliability engineers need different levels of access.

In the case of our team at Buildkite, all engineers are administrators. We operate on a model of high trust, but that may not be scalable or suitable for every organization. Access control is a complicated topic. Stay tuned for a future post where we provide more guidance on how to structure permissions within Buildkite for your team.

What's Next?

Security is an important topic at Buildkite, and we'll be sure to revisit it with some more practical examples for you to follow. In the meantime, be sure to check out our documentation on permissions workflows for more examples.

Don't have a Buildkite account? Start a trial today!