CI with Snyk using GitHub Actions
Tags: react, node, devops, github
Published: 2021-12-24 20:53:15

> GitHub Actions can be used as a CI tool for building, testing and deploying our code.  With the aid of [Synk](https://snyk.io), it can also automate the process of checking vulnerabilities.

## Table of Contents
* [Introduction](#introduction)
* [Create Action Secrets in GitHub](#create-action-secrets-in-github)
* [Create a GitHub Action](#create-a-github-action)
* [Compose GitHub Action workflow file](#compose-github-action-workflow-file)
* [Run the GitHub Action](#run-the-github-action)
* [Conclusion](#conclusion)
* [References](#references)

## Introduction

Snyk is a developer security platform for securing code, dependencies, containers, and infrastructure as code.

It can be used in IDE such as IntelliJ, Visual Studio Code and so on as a tool to scan vulnerabilities in the code and librabries.

It can also be used to secure containers by finding and fixing issues in containers and continuously monitor container images.

It can also be integrated with CI/CD tool to find and fix issues in application continuously.

In this article, we will integrate Synk with GitHub Action, a CI tool from GitHub, in order to secure our application continuously.

## Create Action Secrets in GitHub

It is required to submit Access Tokens to Snyk and Npm Registry for authentication when performing security check and publishing respectively.

Action Secrets are environment variables that are encrypted.  It is useful to store sensitive information such as access tokens.  Action Secrets can be used in Action Workflow file.

![GitHub Action](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uf9bk237wxz5w91atct9.png)

### Generate Access Token for publishing packages to npm Registry.

1. Login [npm](https://www.npmjs.com).

2. Click "Access Tokens" on the popup menu shown when the profile image is clicked.

    ![npm Access Token](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eogvri2tgr9awx18d902.png)

3. Click the "Generate New Token" button on the "Access Tokens" page.

    ![npm Access Token](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n5cn0yc0a0ym6ysp37bv.png)

4. In the "New Access Token" page shown, select "Automation" from the "Select type" list, and click "Generate Token".

    ![npm Access Token](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vf0mkta8ulthw3nxtp1g.png)

5. A new Token should then be generated.  Copy the token for later use.

    ![npm Access Token](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/krv33b90xjcbrhf15n3r.png)

### Generate Auth Token for authentication to Snyk.

1. Login [Snyk](https://snyk.io).

2. Click Account Settings > API Token section.

3. In the KEY field, click "click to show", then select and copy your token.

    ![Snyk Auth token](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hkt9bgn5elx9rq4ob7h9.png)


### Create Action Secrets

Create Actions Secrets NPM_TOKEN and SNYK_TOKEN for access to npm repository and Snyk respectively.

1. Login [GitHub](https://github.com).

2. Click the target repository.

3. Select the "Settings" tab.

4. On the "Settings" page, select "Secrets" on the left navigation menu.  "Action secrets" page should be shown.

5. Click the "New repository secret" button.  A "New secret" page should be shown.

6. Input "Name" and "Value" of the tokens, and then click the "Add secret" button.

    | Name       | Value |
    | ---------- | ----- |
    | NPM_TOKEN  | &#123; Access Token for NPM &#125; |
    | SNYK_TOKEN | &#123; Auth Token for Sync &#125; |

    ![GitHub Action](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oq2mf3zuzxxoseis8qis.png)

## Create a GitHub Action

1. Open the target GitHub repository in browser.


2. Click on the *Actions* tab.


3. Click the link on "set up a workflow yourself".

    ![GitHub Action](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ksdfoepgv0re6wlk9t65.png)


4. An editor should be shown for editing the workflow file *main.yml*.

    ![Edit GitHub Action](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fva85bg9u6vlr1nfj2rs.png)


## Compose GitHub Action workflow file.

A basic GitHub Action workflow file consists of 3 secions:
* ***name***: Action Name
* ***on***: How the action will be triggered.
* ***jobs***: Jobs to be performed when the Action is triggered.

1. Update ***name*** section.

    ```yml
    name: CI Publish, with security check using Snyk
    ```

2. Keep ***on*** section unchanged.  By default, the action is triggered when a push or a pull request occurs.

    ```yml
    # Controls when the workflow will run
    on:
      # Triggers the workflow on push or pull request events but only for the main branch
      push:
        branches: [ main ]
      pull_request:
        branches: [ main ]
    ```

3. Update ***jobs*** section.

    There are 3 jobs that are set up in this Action:

    i. ***security***: Use Snyk to check for any vulnerability.

    ii. ***build***: This job is used to build the code.  In this example, we build a Node.js application with various Node versions defined in an array.  This allows us to test the application running on different Node versions in a very easy approach.

    iii. ***publish***: Publish the package to npm repository, allowing other developers to download and install the package, simple using the `npm insall` command.

    To set up a job that depends on other job(s) to be run successfully, `needs` can be used.  For example, `needs: [security, build]` means that the job ***publish*** requires the jobs ***security*** and ***build*** to be executed successfully before it can be run.  If either of the jobs fails, the ***publish*** job will not be executed.

    ![Edit GitHub Action - Job Dependency](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ef5zr5wvydz5zdkhe6d1.png)

    Here below list the entire workflow file:
    ```yml
    # A workflow run is made up of one or more jobs that can run sequentially or in parallel
    jobs:
      security:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@master
          - name: Run Snyk to check for vulnerabilities
            uses: snyk/actions/node@master
            env:
              SNYK_TOKEN&#58; &#36;&#123;&#123; secrets.SNYK_TOKEN &#125;&#125;
            with:
              command: monitor

      build:
        runs-on: ubuntu-latest
        strategy:
          matrix:
          node-version: [10.x, 12.x, 14.x, 15.x]
        
        steps:
          # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
          - uses: actions/checkout@v2
          - name: Use Node.js &#36;&#123;&#123; matrix.node-version &#125;&#125;
            uses: actions/setup-node@v2
            with:
              node-version&#58; &#36;&#123;&#123; matrix.node-version &#125;&#125;
          - name: Install dependencies
            run: npm ci
          - run: npm run build --if-present
          - run: npm test

      publish:
        needs: [security, build]
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v2
          - name: Use Node.js
            uses: actions/setup-node@v2
            with:
              node-version: '15.x'
              registry-url: 'https://registry.npmjs.org'
          - name: Install dependencies
            run: npm ci
          - name: Publish
            run: npm publish
            env:
              NODE_AUTH_TOKEN&#58; &#36;&#123;&#123; secrets.NPM_TOKEN &#125;&#125;
    ```

4. Commit the workflow file.
    * Click "Start Commit" button on the left.
    * Input description.  It is better to input the Action Name, since it will be shown in the Action History. 
    * Click "Commit changes" button.
    * Once the "Commit changes" button is clicked, the Action will be triggered to execute.

    ![Commit GitHub Action workflow file](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6925086lrf4adusyzi3j.png)



## Run the GitHub Action

  Our GitHub Action action can be triggered when the workflow file is updated, push or pull request occurs.

1. Once the Action is triggered, the defined jobs will be run.

    ![GitHub Action In Progress](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9so1pc62nean6umjo27w.png)


2. Once the Action is completed successfully, a green tick will be shown.

    ![GitHub Action Completed](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7lqku11pcuy0h1s9sh6q.png)


3. Upon completion, check the security job details by clicking the ***security*** link on the summary panel on the left.

    ![GitHub Action Completed - security job](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dyvae3nsgvayzx63dll2.png)

    ```yml
    security:
      runs-on: ubuntu-latest
      steps:
        - uses: actions/checkout@master
        - name: Run Snyk to check for vulnerabilities
          uses: snyk/actions/node@master
          env:
            SNYK_TOKEN&#58; &#36;&#123;&#123; secrets.SNYK_TOKEN &#125;&#125;
          with:
           command: monitor
    ```

    With ***monitor command***, the scan is performed and report is generated, but the process will not be interrupted.  In other words, even if vulnerabilities are found, the job is finished successfully without error and next job will not be interfered and will then start.

    To view the report, open the link stated as "Explore this snapshot at" in the result of "Run Snyk to check for vulnerabilities" section of the security job in a browser.

    ![GitHub Action - Snyk Report Link ](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m1klhaz6g1xc1x11h6jt.png)

    ![GitHub Action - Snyk Report](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qlhzp8kvev8838r9ap11.png)

    It is recommended to use the ***monitor command*** at the beginning to find the vulnerabilities during development stage.  After the vulnerabilities are fixed or ignored, in production stage, we can then set to "synk test" command.  This command will fail the builds when vulnerabilities are found.  In this case, we can decide whether to stop or continue the build for production deployment. 


4. Check the build jobs details by clicking the ***build*** link on the summary panel on the left.

    ![GitHub Action Completed - build job](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j1c1ersb24da75l4kxn8.png)


5. Check the publish job details by clicking the ***security*** link on the summary panel on the left.

    ![GitHub Action Completed - publish job](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hamgh548vm01oljw2ei7.png)


6. Check whether the package is published at [npm repository](https://www.npmjs.com/).

    ![GitHub Action Completed - publish job](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xlcrohsqbm13amd3ygj2.png)


## Conclusion

Security vulnerabilities are subject to attack and should be closely monitored.  By applying security scan during CI/CD Integration, our applications can be continuously monitored against security threats.

## References
1. [Source code in GitHub](https://github.com/adafycheng/reactjs-tabbedpane-component)
2. [Published component in npm repository](https://www.npmjs.com/package/reactjs-tabbedpane-component)
3. [Publishing and installing a package with GitHub Actions](https://docs.github.com/en/packages/managing-github-packages-using-github-actions-workflows/publishing-and-installing-a-package-with-github-actions)
4. [Snyk CI/CD Integration: good practices](https://docs.snyk.io/getting-started/snyk-cicd-integration-good-practices)