Practicing Kubescape In Your CI Pipeline
Tags: cicd, devops, kubernetes, productivity
Published: 2022-07-13 17:29:37

We brought something special to you.

> This is an inset supplementing a previously published [article](https://dev.to/otomato_io/kubescape-a-kind-insurance-inspector-for-your-kubernetes-investments-3hb6) about `kubescape`. 

As mentioned earlier, there's an option of [CI integration](https://hub.armo.cloud/docs/github-1) for the tool described. GitHub Actions are supported, too.

For example, in your GHA CI you may create a trigger job which is capable to stop the whole flow if your YAMLs are failing the security checks. To achieve that, you can invoke the tool with `-t` flag (for _threshold_) and an appropriate value. Valid values are integers between `0 - 100`. A value of `100` will never fail. 

> A value given after `-t` will serve as a semaphore to consider your cluster as insecure.

What is the author getting at? That's what. 

At Otomato, we've created a Kubescape GitHub action in order to make it easier to integrate Kubernetes security scanning in our customers' pipelines for quickly scanning manifests and clusters. 

Moreover, this is also capable to scan the whole cluster that presents in the `kubeconfig` [contexts](https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/).

Well, it looks like [we've made it](https://github.com/otomato-gh/kubescape-action)! Let's see how to use this predefined action. 

### Parameters
Supported parameters are the following: 

⚙️ `ksversion`: 'v2.0.155' 
⚠️ Required. A version of involved binary. See ARMO [releases](https://github.com/armosec/kubescape/releases) page.

⚙️ `path`: '.' 
Optional. A path where to look for deployments' YAML to scan. Default is repo's home directory.

```yaml
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - name: Prepare file to scan
        run: |
          curl -O https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.2.0/deploy/static/provider/cloud/deploy.yaml
      - name: Scan files 
        uses: otomato-gh/kubescape-action@main
        with:
          ksversion: 'v2.0.155'
          format: 'json'
          path: 'deploy.yaml'
```
⚙️ `threshold`: 20 
Optional. A threshold value `0..100`. This action will fail if, in terms of vulnerability points, your deployment scores more than the value specified.

⚙️ `format`: 'json' 
Optional. An output's format: "pretty-printer", "json", "junit", "prometheus", "pdf" (default is "pretty-printer" (raw console dump)).

⚙️ `context`: ''
Optional. K8s cluster (kube-context given in `KUBECONFIG`) to run scan on (default is empty, so not set, and thus we're going to scan YAML files only).

To involve `KUBECONFIG`, you have to organize its availability for GitHub. The best way to do it is setting a [repository secret](https://docs.github.com/en/actions/security-guides/encrypted-secrets) (Settings → Secrets → Action secrets) containing your cluster's configuration.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p8t411w2mm9qja6wykj2.png)

Having cluster's context stored on GitHub, we may play around it in our flow. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hnxs8d6trvm0ou0gsi1m.png)

It may be useful if _more than one_ context defined in your `KUBECONFIG`.

```yaml
jobs:
  scan-cluster:
   runs-on: ubuntu-latest
   steps:  
    - name: Checkout
      uses: actions/checkout@v3    
    - name: Write kubeconfig to file
      run: echo "${{ secrets.KUBECONFIG_CONTENT }}" > mykubeconfig
    - name: Set context
      id: setcontext
      run: |
        echo $KUBECONFIG
        curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
        chmod +x kubectl
        var=$(kubectl config current-context)
        echo "::set-output name=KUBE_CONTEXT::$var"
      env: 
        KUBECONFIG: mykubeconfig
    - name: Scan cluster
      uses: otomato-gh/kubescape-action@main
      with:
          ksversion: 'v2.0.155'
          format:  'json'
          context: ${{ steps.setcontext.outputs.KUBE_CONTEXT }}
      env: 
        KUBECONFIG: mykubeconfig
```

🐞 Please keep in mind: due to `kubescape` command syntax, you can choose to scan only one thing: either `path` or `context`. It makes no sense to set both parameters at the same time.

You may find an example flow [here](https://github.com/otomato-gh/kubescape-action/blob/main/.github/workflows/test.yaml). 

###Non-blocking execution
Obviously, the subsequent actions must be performed even in the case of a 🔴 red semaphore from the `kubescape`, in this case the `if: always()` [flag](https://stackoverflow.com/questions/58858429/how-to-run-a-github-actions-step-eve n-if-the-previous-step-fails-while-still-f) is set to be used.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ha0vao3jsy11j59gamfu.png)

> Don't abuse it in everyday life, please! Stopping the flow, as a rule, occurs for significant reasons. Do not use `if: always()` too recklessly where the logic does not require it!

Scanning process itself is to be performed inside a docker container. 

```yaml
- name: Retrieve Scan Results via File Upload
        if: always() 
        uses: actions/upload-artifact@v3
        with:
          name: scan-results
          path: results.*  
```

For "json", "junit" and "pdf" [output] this action provides report saving implemented as an uploaded artifact. This means, the report may be downloaded straight from GHA web UI (**Actions** page) for consequent analysis. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gr9gs1f4wvzoxd56o69x.png)

Thanks to Konrad Pabjan, he was the first to be puzzled by the task of [preserving artifacts](https://github.com/actions/upload-artifact), we always mention prominent contributors to open source.

###A little non-obvious trick

You can send a report by e-mail using Dawid Dziurla's [contribution](https://github.com/dawidd6/action-send-mail), but keep in mind that the username and password for authentication on the mail server must be present as secrets in your repository. 
```yaml
- name: Send Scan Results by E-mail
        if: always()
        uses: dawidd6/action-send-mail@v3
        with:
          server_address: smtp.gmail.com
          server_port: 465
          # Optional (recommended): mail server username:
          # username: ${{secrets.MAIL_USERNAME}}
          # Optional (recommended) mail server password:
          # password: ${{secrets.MAIL_PASSWORD}}
          subject: GHA Kubescape Scan Result
          to: roman@otomato.io        
          from: GitHub Actions Runner <runner@github.com>
          secure: true
          # Optional plain body:
          # body: Report from ${{github.repository}} are ready! See attachment.
          # Optional HTML body read from file:
          # html_body: file://README.html
          ignore_cert: true
          # Optional converting Markdown to HTML (set content_type to text/html too):
          # convert_markdown: false
          # Optional attachments:
          # attachments: results.*
```

This step can also be observed in our [example](https://github.com/otomato-gh/kubescape-action/blob/main/.github/workflows/test.yaml).

Convenience matters. We wish you good luck in hardening your Kubernetes' security!


🎨 _Pic source: Manufacturing Digital_