How to run Snyk test in CircleCI and Argo CD?
How do you secure GitOps pipeline? In this post today, I will be sharing on how you can find vulnerabilities using Snyk in GitOps toolset, mainly CircleCI and Argo CD.
GitOps is an interesting framework to manage and secure the application development pipeline. For instance, the GitOps workflow of an organization which deploys applications onto a K8s platform can be as follows:
- Developers deploy their codes to a Git repository
- Triggers the CI/CD pipeline once the merge request is approved
- Updating the declarative application configuration files
- The CD tool picks it up from Git and detects the configuration drift
- Deploy the application onto the K8s platform automatically to make sure that the desired state is achieved
The above workflow can happen without giving developers direct access to the K8s cluster hence GitOps can definitely fill up the security gaps in distributed environments, and using Git as a single source of truth for declarative infrastructure and applications is just one of them.
There are many tools which can implement GitOps in your application lifecycle and in this post today, the focus will be on using CircleCI as the continuous integration tool, and Argo CD as the declarative continuous delivery tool.
CircleCI Setup with Snyk
CircleCI is a cloud based CI/CD tool which has built support for parallelism and Docker workflow, and CircleCI will be my CI tool.
In my CircleCI, set up the integration with GitHub (I’m using GitHub as my Git repository). My repository can be found here: https://github.com/jiajunngjj/circleci-goof. Once the setup is completed, you should be able to see the following workflow:
Here is the config.yml:
version: 2.1
orbs:
snyk: snyk/snyk@1.1.2
jobs:
build:
docker:
- image: circleci/node:latest
steps:
- checkout
- run: npm install -q
snyk_code_test:
docker:
- image: snyk/snyk-cli:npm
steps:
- checkout
- run:
command: |
snyk auth $SNYK_TOKEN
snyk code test || true
snyk_oss_test:
docker:
- image: circleci/node:4.8.2
steps:
- checkout
- snyk/scan:
token-variable: SNYK_TOKEN
fail-on-issues: false
monitor-on-build: false
docker_build_push:
docker:
- image: cimg/node:18.0.0
steps:
- checkout
- setup_remote_docker
- run: |
TAG=0.1.<< pipeline.number >>
docker build -t $DOCKER_USERNAME/docker-goof:$TAG .
docker login -u $DOCKER_USERNAME --password $DOCKER_PASSWORD
docker push $DOCKER_USERNAME/docker-goof:$TAG
snyk_container_test:
docker:
- image: snyk/snyk-cli:npm
steps:
- checkout
- run:
command: |
TAG=0.1.<< pipeline.number >>
snyk auth $SNYK_TOKEN
snyk container test jiajunngjj/docker-goof:$TAG --file=./Dockerfile || true
trigger_argocd:
docker:
- image: cimg/base:2022.04
steps:
- run : |
TAG=0.1.<< pipeline.number >>
git clone https://github.com/jiajunngjj/argocd-goof.git
cd argocd-goof
sed -i 's/\(docker-goof\)\(.*\)/\1:'$TAG'/' goof/goof-deployment.yaml
git config user.email "ngjiajun13@gmail.com"
git config user.name "jiajunngjj"
git add goof/goof-deployment.yaml
git commit -m "update from circleci to trigger argocd"
git push https://$GITHUB_PERSONAL_TOKEN@github.com/jiajunngjj/argocd-goof.git
workflows:
build_and_test:
jobs:
- build
- snyk_code_test:
requires:
- build
- snyk_oss_test:
requires:
- build
- docker_build_push:
requires:
- snyk_code_test
- snyk_oss_test
- snyk_container_test:
requires:
- docker_build_push
- trigger_argocd:
requires:
- snyk_container_test
Note: I appended || true
to ensure my Snyk test succeeds so it can move to the next stage.
Requirements
- Snyk account
- DockerHub account
- Set up a variable,
SNYK_TOKEN
, using Snyk API token - Set up a variable,
GITHUB_PERSONAL_TOKEN
, to store your GitHub personal access token - Set up a variable,
DOCKER_USERNAME
, to store your DockerHub username - Set up a variable,
DOCKER_PASSWORD
, to store your DockerHub password
CI Workflow
- build - Build/Compile the application
- snyk_code_test - Run Snyk Code test (Static Application Security Testing (SAST))
- snyk_oss_test - Run Snyk Open Source test (Software Composition Analysis (SCA))
- docker_build_push - Run Docker workflow to build container image and push into my DockerHub repository
- snyk_container_test - Run Snyk Container test to scan the built image
- trigger_argocd - Update the git repository with the new image tag which Argo CD tracks
Argo CD Setup with Snyk
Argo CD is a K8s native CD tool which tracks a repository and compares the application state with the current state of the K8s cluster. Then, it applies the required changes to the cluster configuration. I will be using Argo CD as the CD tool to deploy the application directly onto a K8s cluster. Argo CD can be deployed either on K8s or VMs. My GitHub repository which CircleCI updates and Argo CD tracks, can be found here: https://github.com/jiajunngjj/argocd-goof
- Creates an application on your Argo CD:
- Click on the
Sync
button
The above steps should create all the K8s objects (as per my GitHub repository) in your cluster.
To run Snyk IaC scan on the K8s yaml files, you will need to create a K8s job object:
apiVersion: batch/v1
kind: Job
metadata:
name: snyk-iac-scan
annotations:
argocd.argoproj.io/hook: PreSync
spec:
ttlSecondsAfterFinished: 600
template:
spec:
containers:
- name: snyk-cli
image: snyk/snyk-cli:npm
command: ["/bin/sh","-c"]
args:
- git clone https://github.com/jiajunngjj/argocd-goof.git;
snyk auth $SNYK_TOKEN;
snyk iac test argocd-goof/goof/goof-deployment.yaml || true;
env:
- name: SNYK_TOKEN
valueFrom:
secretKeyRef:
name: snyk-token
key: token
restartPolicy: Never
backoffLimit: 0
Note that you will need to create a K8s secret, SNYK_TOKEN
in the namespace (in my case is apples) which you’re going to deploy the applications.
The argocd.argoproj.io/hook: PreSync
will run the snyk-cli
container, which runs the Snyk IaC test on my goof-deployment.yaml
before the actual
deployment of my goof-deployment.yaml
. Any detection of vulnerabilities would result in a failure in deployment.
Sample Output
CircleCI
Pipeline running:
Snyk Code scan:
Argo CD
Before configuration drift detection:
After configuration drift detection, it starts to sync and run the job (Snyk IaC scan):
Snyk IaC scan:
Wrapping up
The entire CI/CD workflow is as follows:
CircleCI
- Build/Compile the application
- Run Snyk Code test (SAST)
- Run Snyk Open Source test (SCA)
- Run Docker workflow to build container image and push into my DockerHub repository
- Run Snyk Container test to scan the built image
- Update the goof-deployment.yaml in my GitHub with the new image tag, which Argo CD tracks
Argo CD
- Detects the configuration drift
- Starts to sync to achieve the new state
- Triggers Snyk IaC scan
- If Snyk IaC detects no vulnerabilities, goof-deployment.yaml will be deployed
The GitOps workflow will fail whenever Snyk detects any vulnerabilities with severity above the threshold you defined. And this will ensure that vulnerable codes will never reach production environment.
Leave a comment