DEV Community

Cover image for Practicing Kubescape In Your CI Pipeline
Roman Balashevich for Otomato

Posted on

Practicing Kubescape In Your CI Pipeline

We brought something special to you.

This is an inset supplementing a previously published article about kubescape.

As mentioned earlier, there's an option of CI integration 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.

Well, it looks like we've made it! 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 page.

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

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'
Enter fullscreen mode Exit fullscreen mode

⚙️ 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 (Settings → Secrets → Action secrets) containing your cluster's configuration.

Image description

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

Image description

It may be useful if more than one context defined in your KUBECONFIG.

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
Enter fullscreen mode Exit fullscreen mode

🐞 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.

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 is set to be used.

Image description

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.

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

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

Thanks to Konrad Pabjan, he was the first to be puzzled by the task of preserving artifacts, 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, but keep in mind that the username and password for authentication on the mail server must be present as secrets in your repository.

- 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.*
Enter fullscreen mode Exit fullscreen mode

This step can also be observed in our example.

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

🎨 Pic source: Manufacturing Digital

Discussion (0)