SnykCon - Making Sense of Container Security with Snyk CLI and GitHub Actions
Tags: devops, security, docker, github
Published: 2020-10-22 19:51:27

I'm so excited I've participated in **SnykCon 2020**! 🔥
Listening to the talks lit a fire in me, and I really want to take container security seriously from now on, knowing how much easier it is today with tools like Snyk 🚀

## But after running a container scan...
... on a couple of very simple projects, well, this is not the result I was expecting: 🤯🤯🤯
![Overwhelming amount of issues](https://dev-to-uploads.s3.amazonaws.com/i/s5wf259u5rrp5n81zomz.png)

This was literally an *"Hello World!"* type of project, what is going to happen if I scan a real project? **How do I start making sense of this?**

Let me do a quick introduction and then I'll show you how I practically approached this problem 😉

# A modern approach to security - DevSecOps
As I learned from this year's conference, **finding vulnerabilities early on in the software development cycle** is paramount in this day and age.

With the adoption of *Continuous Delivery*, hence shorter release cycles, **we can no longer afford to wait for a team of security experts to validate every release**. New code will already be running in production by the time they complete their audit!

Also, developers are the best people that can contextualize the vulnerabilities, and take action to fix them. 👨🏻‍💻

## Shifting the responsibility towards developers
Ok, this is a nice concept, **developers are now responsible for security too**! But hold on a sec, they're developers! How can we expect them to do their job, and also monitor their software for vulnerabilities every day?

This is where I think people at Snyk have done a great job. Their tools are focused on helping developers with:
- identifying vulnerabilities as **early as in the developer's laptop**
- providing **command-line tools** that can be **integrated into CI/CD workflows**
- monitoring generated artifacts to **proactively notify the team when new vulnerabilities are discovered**
- **advise on actions to fix vulnerabilities** directly in the CLI for developers to see

# My experience with Snyk Container scan
Given that **there's no such thing as absolute security**, this is the process I followed to get as close as I could for my demo container.

If you want to have a look at the repository, you can find it [here](https://github.com/mcastellin/snyk-container-demo). It's a simple *"Hello, World!"* Python project, that, when I started, had **a whopping 267 vulnerabilities**!

## Step 0 - creating a Snyk account
The first thing to do is to create a Snyk account. This is required to start using the CLI tools from your development machine. See below, **you just need to authorize the app with one of your existing accounts**
![Create Snyk account](https://dev-to-uploads.s3.amazonaws.com/i/yjzz5fjwwrbcr1kacydt.png)

After creating the account, **Snyk will generate your personal API token**. This is needed to use the CLI tools from command-line and from your CI/CD workflow.

If you already have an account, you'll find the token under *Your Name > General Settings > API Token*
![API token settings](https://dev-to-uploads.s3.amazonaws.com/i/4lguuibhsdfxye6p4wa7.png)

Install the CLI tools with `npm` and **authenticate with your token**:
```bash
# Install Snyk CLI with npm
> npm install -g snyk

# Authenticate with your Snyk account
> snyk auth ${YOUR_API_TOKEN}
```

We're now ready to scan our project! 🚀

## Step 1 - start from the development machine
As I learned in the conference, the best way is to start in your development machine using Snyk CLI.

First I wanted to make sure my python dependencies are clean from vulnerabilities. I'll do that directly from the command-line by running 
```bash
> snyk test
```
![snyk test command](https://dev-to-uploads.s3.amazonaws.com/i/8z2vliyla2spb0977zmc.png)

And it immediately found an issue with my `requirements.txt` file.

What's cool about this, is that Snyk tells me that the vulnerability in `sqlalchemy@1.3.17` has been resolved in a later version of the package, so I will just upgrade it to the suggested version `sqlalchemy@1.3.19`.

### Container image scanning
Next, I want to **run a container scan to make sure my image has as little vulnerabilities as possible**.

To do that, I first need to build the image, and then I can immediately scan it from the command line with `snyk container test`:
```bash
> snyk container test --file=Dockerfile snyk-container-demo
```

By using the `--file=Dockerfile` we can tell Snyk which Dockerfile generated the `snyk-container-demo` image. This way we'll be able to **get more accurate suggestions** from the advisor.

And then I started to cry 😭
![total issues first report](https://dev-to-uploads.s3.amazonaws.com/i/bkmh6vkf0woqtamlhfbx.png)

### Stay calm and keep reading
This is what I told myself when I first read this report. Despite having soo many issues reported (267 to be exact), the report is also **suggesting alternative images** to the one I am currently using for the project:
```bash
Recommendations for base image upgrade:

Alternative image types
Base Image                  Vulnerabilities  Severity
python:3.9.0rc1-slim        73               17 high, 12 medium, 44 low
python:3.9.0b5-slim-buster  73               17 high, 12 medium, 44 low
```

This is pretty nice! I can see that **the `-slim` and `-slim-buster` versions of my base image have fewer vulnerabilities**. So next thing I'll do is changing my `Dockerfile` to use one of those.

### And after applying the suggestion...
... I was glad to see that the number of vulnerabilities found was drastically reduced!
![reduced vulnerabilities second scan](https://dev-to-uploads.s3.amazonaws.com/i/hrcogth3l5j51o70nj0l.png)

In this report, Snyk is also telling me that I'm currently running on **the most secure version of the selected base image**, remember, *there's no such thing as absolute security* 😅

Being happy with the base image I selected, I can commit the changes in the repo and move on with the process.

# Step 2 - CI Integration
I will now **integrate Snyk with my Continuous Integration workflow**. I don't have any in this project yet, so I'm going to use [GitHub Actions](https://github.com/snyk/actions).

With a quick Google search, I found out that **Snyk already published a GitHub action** I can use to scan my repository on every commit and collect the results in the Security tab of the GitHub repo.
[![snyk docker action](https://dev-to-uploads.s3.amazonaws.com/i/3i9z77mehl8h0lzzdp8g.png)](https://github.com/snyk/actions/tree/master/docker "Click to see the repo page")

I will then **copy the template provided**, and create a new file in my repo in the `.github/workflows` directory called `secscan.yml`:
```bash
name: Container Scan
on: push
jobs:
  snyk:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Build the Docker image
      run: docker build -t mcastellin/snyk-container-demo .
    - name: Run Snyk to check Docker image for vulnerabilities
      # Snyk can be used to break the build when it detects vulnerabilities.
      # In this case we want to upload the issues to GitHub Code Scanning
      continue-on-error: true
      uses: snyk/actions/docker@master
      env:
        # In order to use the Snyk Action you will need to have a Snyk API token.
        # More details in https://github.com/snyk/actions#getting-your-snyk-token
        # or you can signup for free at https://snyk.io/login
        SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
      with:
        image: mcastellin/snyk-container-demo
        args: --file=Dockerfile --exclude-base-image-vulns
    - name: Upload result to GitHub Code Scanning
      uses: github/codeql-action/upload-sarif@v1
      with:
        sarif_file: snyk.sarif
```

I have pretty much used the standard values here, except for the `args: --file=Dockerfile --exclude-base-image-vulns`.

By adding the `--exclude-base-image-vulns` parameter we are telling Snyk **not to report vulnerabilities that are introduced by Docker base image layers**. This is to make sure that we are **breaking the build only when we introduce new issues in the Dockerfile**. 

The reason for ignoring base image vulnerabilities is to **avoid having too much noise in the CI scan**. We have already accepted the base image so we're only interested in blocking the issues we add with our customizations.

Before committing our GitHub Action YAML file, we have to configure the `secret.SNYK_TOKEN` in our registry. In the GitHub repository settings, go to *Settings > Secrets > New Secret* and configure the value for the Snyk token:
![add new secret to github](https://dev-to-uploads.s3.amazonaws.com/i/p9j923fnvmwz92ls5cb3.png)

We can now push our changes and see the result of the security scan:
![github action scan results](https://dev-to-uploads.s3.amazonaws.com/i/pgqllp1i474oz0hbowks.png)

# Step 3 - Breaking the build
After all the effort fixing vulnerabilities **I really want to make sure nobody can introduce new ones**! Let's modify our Dockerfile and open a Pull Request that introduces an insecure package: `curl`, who knew!? 🤔

```Dockerfile
...

RUN apt-get update \
    && apt-get install -qqy curl \
    && rm -rf /var/lib/apt/lists

...
```

### Found it!
![build broken](https://dev-to-uploads.s3.amazonaws.com/i/vf4qzc3ws12kr80po7hv.png)

And the **container scan found new vulnerabilities**, giving us the peace of mind, that if anyone installs dodgy packages we'll be able to catch it before merging the code into the main branch! 

# Step 4 - Analyzing the report
![detailed vulnerability report](https://dev-to-uploads.s3.amazonaws.com/i/bwgc9tvqx0k71qa7be1g.png)

For every issue found by Snyk you'll get a very detailed report, telling you:
- **what file** introduced the issue
- a **description** of the vulnerability
- **remediation advice**

![remediation advice](https://dev-to-uploads.s3.amazonaws.com/i/nkv0p03zh7x9g3cjdhrl.png)

# Wrapping up
**It's been a fun couple of days for me to attend to SnykCon 2020** and I hope by sharing my first experience with Snyk and container scanning, I have also **encouraged you to learn how to make the most out of these tools** to keep your applications secure!

Thanks for reading! And don't forget to follow me if you want to see more content like this!

- [YouTube](https://bit.ly/3hTkyWU) 🎬
- [Twitter](https://twitter.com/castellinmanuel)
- [LinkedIn](https://www.linkedin.com/in/castellinmanuel/)