Buildkite is a platform for running fast, secure, and scalable continuous integration pipelines on your own infrastructure. In the example below I will run my Buildkite pipeline on my Macbook to perform two Snyk Tests, one for Open-Source dependancies and the other a SAST test of the code itself.
Snyk is an open source security platform designed to help software-driven businesses enhance developer security.
You will need an account on Snyk and Buildkite to follow the steps below.
Steps
1. First in Snyk let's create a Service Account which will be the Snyk token I will use to authenticate with. You can use the Snyk API Token but the service account is all you need to run "Snyk Tests" so makes sense to use that.
2. Next let's store that Service Account token somewhere where I can safely inject that into my pipeline at the appropriate step. In this example I am using "Google Secret Manager" but there are other choices of course.
Note: We will be using the secret NAME shortly "PAS_BUILDKITE_SA_SNYK_TOKEN"
3. You will need a Buildkite agent on your local Infrastructure in my case I using my Macbook so that's done as follows
https://buildkite.com/docs/agent/v3/macos
pasapicella@192-168-1-113:~/demos/integrations/buildkite$ ./start-agent.sh
_ _ _ _ _ _ _ _
| | (_) | | | | (_) | | |
| |__ _ _ _| | __| | | ___| |_ ___ __ _ __ _ ___ _ __ | |_
| '_ \| | | | | |/ _` | |/ / | __/ _ \ / _` |/ _` |/ _ \ '_ \| __|
| |_) | |_| | | | (_| | <| | || __/ | (_| | (_| | __/ | | | |_
|_.__/ \__,_|_|_|\__,_|_|\_\_|\__\___| \__,_|\__, |\___|_| |_|\__|
__/ |
https://buildkite.com/agent |___/
2021-09-15 11:09:33 NOTICE Starting buildkite-agent v3.32.3 with PID: 50130
2021-09-15 11:09:33 NOTICE The agent source code can be found here: https://github.com/buildkite/agent
2021-09-15 11:09:33 NOTICE For questions and support, email us at: hello@buildkite.com
2021-09-15 11:09:33 INFO Configuration loaded path=/usr/local/etc/buildkite-agent/buildkite-agent.cfg
2021-09-15 11:09:33 INFO Registering agent with Buildkite...
2021-09-15 11:09:35 INFO Successfully registered agent "y.y.y.y.tpgi.com.au-1" with tags []
2021-09-15 11:09:35 INFO Starting 1 Agent(s)
2021-09-15 11:09:35 INFO You can press Ctrl-C to stop the agents
4. You're now ready to create a pipeline. A pipeline is a template of the steps you want to run. There are many types of steps, some run scripts, some define conditional logic, and others wait for user input. When you run a pipeline, a build is created. Each of the steps in the pipeline end up as jobs in the build, which then get distributed to available agents.
In the example below our pipeline is created from a GitHub repo and then select the default branch. At that point incoming webhooks are sent to Buildkite by source control providers (GitHub, GitLab, Bitbucket, etc.) to trigger builds, in this scenario we using GitHub
5. Let's go ahead and actually just edit the build steps using YAML. My final YAML is as follows and I explain below why it looks this way but in short I just want to run two snyk tests rather then actually deploy anything for this demo.
steps:
- commands:
- "snyk config set api=$$SNYK_SA_TOKEN_VAR"
- "snyk test --severity-threshold=$$SEVERITY_THRESHOLD"
- "snyk code test --org=$$SNYK_ORG"
plugins:
- avaly/gcp-secret-manager#v1.0.0:
credentials_file: /Users/pasapicella/snyk/clouds/gcp/buildkite-secrets-gcp.json
env:
SNYK_SA_TOKEN_VAR: PAS_BUILDKITE_SA_SNYK_TOKEN
env:
SEVERITY_THRESHOLD: "critical"
SNYK_ORG: "pas.apicella-41p"
label: "Employee API Snyk Test"
Few things to note here:
- I am using a GCP secret manager plugin to retrieve my Snyk SA token with a name as follows "PAS_BUILDKITE_SA_SNYK_TOKEN"
- I am using a Google Service Account JSON so I can authenticate with GCP and retrieve my secret "SNYK_SA_TOKEN_VAR", you will need to use a Service Account with privileges to at least READ from Google Secret Manager
- I am using some local non sensitive ENV variables which get used at the appropriate time
- I have three commands of which the first command sets my Snyk API token for the Snyk CLI
- I have not installed the Snyk CLI because it already exists on my Macbook
- I am only looking for my Snyk tests to fail if it finds any CRITICAL issues only
- I should be running a "mvn package" here but I can still execute a "snyk test" without it for demo purposes as we have a pom..xml
- I could also build a container in the pipeline from the source code and then run a "snyk container test" as well, in fact I could even run "snyk iac test" against any IaC files in the repo as well
- If a test fails we can easily run "snyk monitor" to load the results into the Snyk App but for this demo we don't do that
6. Now we can manually run a build or wait for triggering event on our repo, here is some screen shots of what it looks like including some failures where we find vulnerabilities in a separate node.js repo
It makes more sense to create a Buildkite plugin for Snyk rather than execute commands using a script and here is an example of one below. Having said that the commands you run to execute a "snyk test" are simple enough to include in the pipeline YML without the need for a plugin here especially if you have infrastructure already setup with the ability to run the "snyk cli". A plugin would be the right approach here though as per the example below.
https://github.com/seek-oss/snyk-buildkite-plugin
Hopefully you have seen how easy it is to continuously avoid known vulnerabilities in your dependencies and code, by integrating Snyk into your continuous integration pipeline with Buildkite.
More Information
Snyk