Practicing Kubescape In Your CI Pipeline
Roman Belshevitz
Posted on July 13, 2022
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'
⚙️ 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.
Having cluster's context stored on GitHub, we may play around it in our flow.
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
🐞 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.
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.*
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.
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.*
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
Posted on July 13, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.