How to add a new check in KubeLinter? #31
Aug 17, 2021
The following document demonstrates the steps followed while adding a new validation check in the upstream kube-linter project.
KubeLinter is a static analysis tool that checks Kubernetes YAML files and Helm charts to ensure the applications represented in them adhere to best practices.
This document uses the static check
latest-tag, as an example to lay down the steps written below.
latest-tagvalidation check indicates when a deployment-like kubernetes object (i.e. deployments, statefulsets, etc) is running a container with an invalid container image (by default, flags for a floating image tag like “latest”)
Steps to add a new check
[STEP 1] Setup the project on your local machine
Clone the project repository & change directory to the project root
git clone firstname.lastname@example.org:stackrox/kube-linter.git cd kube-linter/
[STEP 2] Setup a new directory for the new validation check
From the root of the project, change directory to the
Create a new directory with the name corresponding to the new check (for example, in this case,
mkdir latesttag cd latesttag/
[STEP 3] Implement the logic for the new check under the new directory
Create the following files & folders in the path
mkdir -p internal/params touch internal/prarms/params.go touch template.go template_test.go
The above files can be understood as (& referred from):
internal/params/params.gofile will contain the paramaters required for the test check.
The actual implementation logic for the new test check will be written in the
And finally, the unit tests to validate the new check logic will be written in
[STEP 4] Make the new check visible to kube-linter
From the root of the project, modify the
pkg/templates/all/all.gofile to include the path to our new test, i.e.
And modify the file to look like following:
package all import ( // Import all check templates. ... _ "golang.stackrox.io/kube-linter/pkg/templates/latesttag" ... )
[STEP 5] Include the new check as a kube-linter builtin check
From the root of the project, go to the
pkg/builtin-checks/yamlsfolder & make a new yaml file corresponding to the name of the new check, (for example,
And edit the file to look like following:
name: "latest-tag" description: "Indicates when a deployment-like object is running a container with an invalid container image" remediation: "Use a container image with a proper image tag satisfying the \"AllowList\" & \"BlockList\" regex patterns." scope: objectKinds: - DeploymentLike template: "latest-tag" params: BlockList: [".*:(latest)$"] AllowList: 
latest-tag.yamlfile does the following:
- provide self-explanatory string values for
define the scope of the check, using the following block
scope: objectKinds: - DeploymentLike
- references the new test check template (defined at
pkg/templates/latesttag/template.go), for example,
provides default paramaeter values required by the check validation logic (defined at
params: BlockList: [".*:(latest)$"] AllowList: 
- provide self-explanatory string values for
(Optional) [STEP 6] Include the new check as a kube-linter default built-in check
So far, the new check is just a builtin check, and is not a default check yet (i.e. kube-linter won’t run this check by default unless specified)
- In order to add the new check as a kube-linter default check:
internal/defaultchecks/defaultcheck.gofile & add the new check name, to look like the following:
package defaultchecks import ( "golang.stackrox.io/kube-linter/internal/set" ) var ( // List is the list of built-in checks that are enabled by default. List = set.NewFrozenStringSet( ... "latest-tag", ... ) )
Once everything above is done, the next step is to test the the newly added check!
Steps to verify the new check
[STEP 1] Build the kube-linter binary from the local project source code.
The local kube-linter binary will contain the new check
Run the following command:
And the output would look something like:
❯ make generated-srcs go generate ./... Compiling Go source in ./cmd/kube-linter to bin/darwin/kube-linter Compiling Go source in ./cmd/kube-linter to bin/linux/kube-linter Compiling Go source in ./cmd/kube-linter to bin/windows/kube-linter.exe kube-linter templates list --format markdown > docs/generated/templates.md kube-linter checks list --format markdown > docs/generated/checks.md
The above command generate local kube-linter binary (for linux, windows & macOS), along with all other auto-generated check templates & markdown documentation required by the kube-linter command line binary tooling to interact with.
[STEP 2] Create an example static yaml manifest
As the new check
latest-tag(we’re adding as part of this documentation), is defined for a scope of
DeploymentLikeobject, I’m creating an example deployment manifest yaml to do the testing.
At the root of the project, create an
examplesdirectory & put a
deployment.yamlfile under it (as our test deployment yaml manifest):
mkdir examples cd examples/ vim deployment.yaml
deployment.yamlfile to look like the following:
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: example.com/test:v1.0.0 ports: - containerPort: 80 - name: frontend image: quay.io/django:latest ports: - containerPort: 8000 - name: key-value-store image: docker.io/redis:v1.4.1 ports: - containerPort: 6379
[STEP 3] Test the new check with the above example static yaml manifest
Execute the following command to run all the kube-linter checks on the test
/bin/linux/kube-linter lint examples/deployment.yaml
In case, you want to run just the newly added
latest-tagcheck, execute the following command:
/bin/linux/kube-linter lint --do-not-include-builtin-checks --include latest-tag examples/deployment.yaml
And the output would look something like this:
❯ ./bin/linux/kube-linter lint /examples/deployment.yaml KubeLinter 0.2.2-6-gc65dd74013-dirty examples/deployment.yaml: (object: <no namespace>/nginx-deployment apps/v1, Kind=Deployment) The container "nginx" is using an invalid container image, "example.com/test:v1.0.0". Please use images that satisfies the `AllowList` criteria : ["^(docker.io)"] (check: latest-tag, remediation: Use a container image with a proper image tag satisfying the "AllowList" & "BlockList" regex patterns.) examples/deployment.yaml: (object: <no namespace>/nginx-deployment apps/v1, Kind=Deployment) The container "frontend" is using an invalid container image, "quay.io/django:latest". Please use images that are not blocked by the `BlockList` criteria : [".*:(latest)$"] (check: latest-tag, remediation: Use a container image with a proper image tag satisfying the "AllowList" & "BlockList" regex patterns.) ...
[STEP 4] Verify the unit tests & the E2E (end-to-end) tests
Run the following command from the root of the project
make test make e2e-test
[STEP 5] Lint the project
Run the following command from the root of the project to lint the project source code
And finally, when you’re happy with how the new check performs, please raise a PR for the upstream
kube-linter project & wait for a review! 🙂