Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
checks:
doNotAutoAddDefaults: false
addAllBuiltIn: true
exclude:
- "unset-cpu-requirements"
- "unset-memory-requirements"
include:
- "host-ipc"
- "host-network"
- "host-pid"
- "non-isolated-pod"
- "pdb-max-unavailable"
- "pdb-min-available"
- "privilege-escalation-container"
- "privileged-container"
- "run-as-non-root"
- "unsafe-sysctls"

1 change: 0 additions & 1 deletion pkg/validations/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ func GetAllNamesFromRegistry(reg checkregistry.CheckRegistry) ([]string, error)
AddAllBuiltIn: true,
},
}
disableIncompatibleChecks(&cfg)

checks, err := configresolver.GetEnabledChecksAndValidate(&cfg, reg)
if err != nil {
Expand Down
23 changes: 0 additions & 23 deletions pkg/validations/validation_engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,8 +204,6 @@ func (ve *validationEngine) processResult(result run.Result, namespaceUID string
}

func (ve *validationEngine) InitRegistry() error {
disableIncompatibleChecks(&ve.config)

registry, err := GetKubeLinterRegistry()
if err != nil {
return err
Expand Down Expand Up @@ -331,24 +329,3 @@ func (ve *validationEngine) removeCheckFromConfig(check string) {
}
}
}

// disableIncompatibleChecks will forcibly update a kube-linter config
// to disable checks that are incompatible with DVO.
// the same check name may end up in the exclude list multiple times as a result of this; this is OK.
func disableIncompatibleChecks(c *config.Config) {
c.Checks.Exclude = append(c.Checks.Exclude, getIncompatibleChecks()...)
}

// getIncompatibleChecks returns an array of kube-linter check names that are incompatible with DVO
// these checks involve kube-linter comparing properties from multiple kubernetes objects at once.
// (e.g. "non-existent-service-account" checks that all serviceaccounts referenced by deployment objects
// exist as serviceaccount objects).
// DVO currently only performs a check against a single kubernetes object at a time,
// so these checks that compare multiple objects together will always fail.
func getIncompatibleChecks() []string {
return []string{
"dangling-service",
"non-existent-service-account",
//"non-isolated-pod",
}
}
80 changes: 26 additions & 54 deletions pkg/validations/validation_engine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,19 @@ import (
"github.com/prometheus/client_golang/prometheus"
promUtils "github.com/prometheus/client_golang/prometheus/testutil"
"github.com/stretchr/testify/assert"
"golang.stackrox.io/kube-linter/pkg/builtinchecks"
"golang.stackrox.io/kube-linter/pkg/checkregistry"
"golang.stackrox.io/kube-linter/pkg/config"
"golang.stackrox.io/kube-linter/pkg/configresolver"
appsv1 "k8s.io/api/apps/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
)

const (
customCheckName = "test-minimum-replicas"
customCheckDescription = "some description"
customCheckRemediation = "some remediation"
customCheckTemplate = "minimum-replicas"
testNamespaceUID = "1234-6789-1011-testUID"
)

func TestGetValidChecks(t *testing.T) {
testCases := []struct {
name string
Expand Down Expand Up @@ -100,13 +105,6 @@ func TestRemoveCheckFromConfig(t *testing.T) {
}
}

const (
customCheckName = "test-minimum-replicas"
customCheckDescription = "some description"
customCheckRemediation = "some remediation"
customCheckTemplate = "minimum-replicas"
)

func newValidationEngine(configPath string, metrics map[string]*prometheus.GaugeVec) (*validationEngine, error) {
config, err := loadConfig(configPath)
if err != nil {
Expand Down Expand Up @@ -144,16 +142,6 @@ func newCustomCheck() config.Check {
}
}

func newEngineConfigWithAllChecks() config.Config {
return config.Config{
CustomChecks: []config.Check{},
Checks: config.ChecksConfig{
AddAllBuiltIn: true,
DoNotAutoAddDefaults: false,
},
}
}

func createTestDeployment(args testutils.TemplateArgs) (*appsv1.Deployment, error) {
d, err := testutils.CreateDeploymentFromTemplate(
&args)
Expand Down Expand Up @@ -199,7 +187,6 @@ func TestUpdateConfig(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
ve, err := newValidationEngine("", make(map[string]*prometheus.GaugeVec))
assert.NoError(t, err, "failed to create a new validation engine")
disableIncompatibleChecks(&tt.initialConfig)
assert.Equal(t, tt.initialConfig, ve.config)
ve.SetConfig(tt.updatedConfig)
assert.Equal(t, tt.updatedConfig, ve.config)
Expand Down Expand Up @@ -246,7 +233,7 @@ func TestRunValidationsForObjects(t *testing.T) {
testutils.TemplateArgs{Replicas: int(tt.initialReplicaCount)})
assert.NoError(t, err, "Error creating deployment from template")
request := NewRequestFromObject(deployment)
request.NamespaceUID = "1234-6789-1011-testUID"
request.NamespaceUID = testNamespaceUID

// run validations with "broken" (replica=1) deployment object
_, err = ve.RunValidationsForObjects([]client.Object{deployment}, request.NamespaceUID)
Expand Down Expand Up @@ -308,7 +295,7 @@ func TestRunValidationsForObjectsAndResetMetrics(t *testing.T) {
testutils.TemplateArgs{Replicas: 1, ResourceLimits: false, ResourceRequests: false})
assert.NoError(t, err, "Error creating deployment from template")
request := NewRequestFromObject(deployment)
request.NamespaceUID = "1234-6789-1011-testUID"
request.NamespaceUID = testNamespaceUID

// run validations with "broken" (replica=1) deployment object
_, err = ve.RunValidationsForObjects([]client.Object{deployment}, request.NamespaceUID)
Expand Down Expand Up @@ -354,40 +341,25 @@ func getMetricValue(v *validationEngine, checkName string, labels prometheus.Lab
return int(promUtils.ToFloat64(metric)), nil
}

func TestIncompatibleChecksAreDisabled(t *testing.T) {
// Initialize engine
ve, err := newValidationEngine("test-resources/default-config.yaml", make(map[string]*prometheus.GaugeVec))
func TestExcludedChecksAreNotActive(t *testing.T) {
ve, err := newValidationEngine("test-resources/config-with-some-excluded-checks.yaml",
make(map[string]*prometheus.GaugeVec))
assert.NoError(t, err, "Error initializing engine")

badChecks := getIncompatibleChecks()
allKubeLinterChecks, err := getAllBuiltInKubeLinterChecks()
assert.NoError(t, err, "Got unexpected error while getting all checks built-into kube-linter")
expectedNumChecks := (len(allKubeLinterChecks) - len(badChecks))

enabledChecks := ve.enabledChecks
assert.Equal(t, expectedNumChecks, len(enabledChecks),
"Expected exactly %v checks to be enabled, but got '%v' checks from list '%v'",
expectedNumChecks, len(enabledChecks), enabledChecks)

for _, badCheck := range badChecks {
assert.NotContains(t, enabledChecks, badCheck)
}
}
deployment, err := createTestDeployment(
testutils.TemplateArgs{Replicas: 1, ResourceLimits: false, ResourceRequests: false})
assert.NoError(t, err, "Error creating deployment from template")
request := NewRequestFromObject(deployment)
request.NamespaceUID = testNamespaceUID

// getAllBuiltInKubeLinterChecks returns every check built-into kube-linter (including checks that DVO disables)
func getAllBuiltInKubeLinterChecks() ([]string, error) {
ve := validationEngine{
config: newEngineConfigWithAllChecks(),
}
registry := checkregistry.New()
if err := builtinchecks.LoadInto(registry); err != nil {
return nil, fmt.Errorf("failed to load built-in validations: %s", err.Error())
}
_, err = ve.RunValidationsForObjects([]client.Object{deployment}, request.NamespaceUID)
assert.NoError(t, err)

enabledChecks, err := configresolver.GetEnabledChecksAndValidate(&ve.config, registry)
if err != nil {
return nil, fmt.Errorf("error finding enabled validations: %s", err.Error())
}
// following two checks are excluded in the corresponding config file
labels := request.ToPromLabels()
_, err = getMetricValue(ve, "unset-cpu-requirements", labels)
assert.Error(t, err, "gauge vector unset-cpu-requirements not found")

return enabledChecks, nil
_, err = getMetricValue(ve, "unset-memory-requirements", labels)
assert.Error(t, err, "gauge vector unset-memory-requirements not found")
}