Skip to content

Commit 2028723

Browse files
janiszclaude
andcommitted
Add kubeconform template for Kubernetes schema validation
This commit introduces a new kubeconform template that validates Kubernetes resources against their schemas using the kubeconform library. Features: - Validates Kubernetes resources against official schemas - Supports custom schema locations and Kubernetes versions - Configurable strict mode for catching extra properties - Can ignore missing schemas for CRDs - Skip/reject specific resource kinds - Schema caching support Changes: - Added kubeconform template with comprehensive parameter support - Fixed godoc comments following Go conventions - Added unit tests for template functionality - Added e2e tests with sample valid and invalid resources - Integrated template into kube-linter's template registry - Updated documentation with template parameters 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 28b9ac8 commit 2028723

File tree

13 files changed

+11945
-0
lines changed

13 files changed

+11945
-0
lines changed

docs/generated/templates.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,64 @@ KubeLinter supports the following templates:
445445
**Supported Objects**: JobLike
446446

447447

448+
## kubeconform
449+
450+
**Key**: `kubeconform`
451+
452+
**Description**: Flag objects that does not match schema using https://github.com/yannh/kubeconform
453+
454+
**Supported Objects**: Any
455+
456+
457+
**Parameters**:
458+
459+
```yaml
460+
- arrayElemType: string
461+
description: 'SchemaLocations contains locations of schemas to use. See: https://github.com/yannh/kubeconform/tree/master?tab=readme-ov-file#overriding-schemas-location'
462+
name: schemaLocations
463+
negationAllowed: true
464+
regexAllowed: false
465+
required: false
466+
type: array
467+
- description: Cache specifies the folder to cache schemas downloaded via HTTP.
468+
name: cache
469+
negationAllowed: true
470+
regexAllowed: false
471+
required: false
472+
type: string
473+
- arrayElemType: string
474+
description: SkipKinds lists resource kinds to ignore during validation.
475+
name: skipKinds
476+
negationAllowed: true
477+
regexAllowed: false
478+
required: false
479+
type: array
480+
- arrayElemType: string
481+
description: RejectKinds lists resource kinds to reject during validation.
482+
name: rejectKinds
483+
negationAllowed: true
484+
regexAllowed: false
485+
required: false
486+
type: array
487+
- description: KubernetesVersion specifies the Kubernetes version - must match one
488+
in https://github.com/instrumenta/kubernetes-json-schema
489+
name: kubernetesVersion
490+
negationAllowed: true
491+
regexAllowed: false
492+
required: false
493+
type: string
494+
- description: Strict enables strict validation that will error if resources contain
495+
undocumented fields.
496+
name: strict
497+
required: false
498+
type: boolean
499+
- description: IgnoreMissingSchemas will skip validation for resources if no schema
500+
can be found.
501+
name: ignoreMissingSchemas
502+
required: false
503+
type: boolean
504+
```
505+
448506
## Latest Tag
449507

450508
**Key**: `latest-tag`

e2etests/bats-tests.sh

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,24 @@ get_value_from() {
4545
[[ "${count}" == "6" ]]
4646
}
4747

48+
@test "template-kubeconform" {
49+
tmp="tests/checks/kubeconform.yml"
50+
cmd="${KUBE_LINTER_BIN} lint --config e2etests/testdata/kubeconform-config.yaml --do-not-auto-add-defaults --format json ${tmp}"
51+
run ${cmd}
52+
53+
print_info "${status}" "${output}" "${cmd}" "${tmp}"
54+
[ "$status" -eq 1 ]
55+
56+
message1=$(get_value_from "${lines[0]}" '.Reports[0].Object.K8sObject.GroupVersionKind.Kind + ": " + .Reports[0].Diagnostic.Message')
57+
message2=$(get_value_from "${lines[0]}" '.Reports[1].Object.K8sObject.GroupVersionKind.Kind + ": " + .Reports[1].Diagnostic.Message')
58+
count=$(get_value_from "${lines[0]}" '.Reports | length')
59+
60+
# Should find 2 validation errors: DaemonSet with replicas field and Pod with invalid field
61+
[[ "${count}" == "2" ]]
62+
[[ "${message1}" =~ "DaemonSet: resource is not valid:" ]]
63+
[[ "${message2}" =~ "Pod: resource is not valid:" ]]
64+
}
65+
4866
@test "template-check-installed-bash-version" {
4967
run "bash --version"
5068
[[ "${BASH_VERSION:0:1}" -ge '4' ]] || false
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
checks:
2+
addAllBuiltIn: false
3+
customChecks:
4+
- name: "kubeconform-validation"
5+
description: "Validate Kubernetes resources against their schemas using kubeconform"
6+
remediation: "Fix the resource to conform to the Kubernetes API schema"
7+
scope:
8+
objectKinds:
9+
- Any
10+
template: "kubeconform"
11+
params:
12+
strict: true
13+
ignoreMissingSchemas: true

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ require (
1818
github.com/spf13/pflag v1.0.10
1919
github.com/spf13/viper v1.21.0
2020
github.com/stretchr/testify v1.11.1
21+
github.com/yannh/kubeconform v0.7.0
2122
helm.sh/helm/v3 v3.19.0
2223
k8s.io/api v0.34.1
2324
k8s.io/apimachinery v0.34.1
@@ -63,7 +64,9 @@ require (
6364
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect
6465
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
6566
github.com/hashicorp/errwrap v1.1.0 // indirect
67+
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
6668
github.com/hashicorp/go-multierror v1.1.1 // indirect
69+
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
6770
github.com/huandu/xstrings v1.5.0 // indirect
6871
github.com/inconshreveable/mousetrap v1.1.0 // indirect
6972
github.com/josharian/intern v1.0.0 // indirect

go.sum

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,14 @@ github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1/go.mod h1:Zanoh4+gvIgluNqcfMVT
146146
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
147147
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
148148
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
149+
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
150+
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
151+
github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
152+
github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
149153
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
150154
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
155+
github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU=
156+
github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
151157
github.com/hashicorp/golang-lru/arc/v2 v2.0.5 h1:l2zaLDubNhW4XO3LnliVj0GXO3+/CGNJAg1dcN2Fpfw=
152158
github.com/hashicorp/golang-lru/arc/v2 v2.0.5/go.mod h1:ny6zBSQZi2JxIeYcv7kt2sH2PXJtirBN7RDhRpxPkxU=
153159
github.com/hashicorp/golang-lru/v2 v2.0.5 h1:wW7h1TG88eUIJ2i69gaE3uNVtEPIagzhGvHgwfx2Vm4=
@@ -300,6 +306,8 @@ github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
300306
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
301307
github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ=
302308
github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0=
309+
github.com/yannh/kubeconform v0.7.0 h1:ZFfniR8VChrWQxaxTUGnNrxw8RIDkjVBrjdhXSamwjw=
310+
github.com/yannh/kubeconform v0.7.0/go.mod h1:oHO1wjM16sTRW6s41HJUox+tD69qOTE5ZVQ9HeqX+xM=
303311
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
304312
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
305313
github.com/zclconf/go-cty v1.10.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk=

pkg/templates/all/all.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
_ "golang.stackrox.io/kube-linter/pkg/templates/hpareplicas"
2828
_ "golang.stackrox.io/kube-linter/pkg/templates/imagepullpolicy"
2929
_ "golang.stackrox.io/kube-linter/pkg/templates/jobttlsecondsafterfinished"
30+
_ "golang.stackrox.io/kube-linter/pkg/templates/kubeconform"
3031
_ "golang.stackrox.io/kube-linter/pkg/templates/latesttag"
3132
_ "golang.stackrox.io/kube-linter/pkg/templates/livenessport"
3233
_ "golang.stackrox.io/kube-linter/pkg/templates/livenessprobe"

pkg/templates/kubeconform/internal/params/gen-params.go

Lines changed: 170 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package params
2+
3+
// Params defines the configuration parameters for this template.
4+
type Params struct {
5+
// SchemaLocations contains locations of schemas to use. See: https://github.com/yannh/kubeconform/tree/master?tab=readme-ov-file#overriding-schemas-location
6+
// +noregex
7+
SchemaLocations []string
8+
// Cache specifies the folder to cache schemas downloaded via HTTP.
9+
// +noregex
10+
Cache string
11+
// SkipKinds lists resource kinds to ignore during validation.
12+
// +noregex
13+
SkipKinds []string
14+
// RejectKinds lists resource kinds to reject during validation.
15+
// +noregex
16+
RejectKinds []string
17+
// KubernetesVersion specifies the Kubernetes version - must match one in https://github.com/instrumenta/kubernetes-json-schema
18+
// +noregex
19+
KubernetesVersion string
20+
// Strict enables strict validation that will error if resources contain undocumented fields.
21+
Strict bool
22+
// IgnoreMissingSchemas will skip validation for resources if no schema can be found.
23+
IgnoreMissingSchemas bool
24+
}

0 commit comments

Comments
 (0)