From c5f120ac0d127a29c2cf0d57f245a8d357cc99e8 Mon Sep 17 00:00:00 2001 From: anjmao Date: Tue, 21 Oct 2025 09:25:42 +0300 Subject: [PATCH 1/2] Drop kubelinter --- cmd/controller/app/app.go | 14 - cmd/controller/config/config.go | 2 - .../controllers/kubelinter/controller.go | 188 ------------- .../controllers/kubelinter/controller_test.go | 78 ------ .../additionalcapabilities.go | 16 -- .../customchecks/automount/automount.go | 89 ------ .../customchecks/bindings/bindings.go | 146 ---------- .../containerdsock/containerdsock.go | 16 -- .../networkpolicypernamespace.go | 94 ------- .../customchecks/privescverbs/privescverbs.go | 99 ------- .../securitycontext/securitycontext.go | 122 -------- .../kubelinter/customobjectkinds/namespace.go | 27 -- .../controllers/kubelinter/delta.go | 65 ----- .../controllers/kubelinter/kubelinter.go | 265 ------------------ .../controllers/kubelinter/kubelinter_test.go | 128 --------- .../controllers/kubelinter/types.go | 219 --------------- .../controllers/kubelinter/types_test.go | 22 -- cmd/controller/main.go | 13 +- go.mod | 12 +- go.sum | 14 - 20 files changed, 9 insertions(+), 1620 deletions(-) delete mode 100644 cmd/controller/controllers/kubelinter/controller.go delete mode 100644 cmd/controller/controllers/kubelinter/controller_test.go delete mode 100644 cmd/controller/controllers/kubelinter/customchecks/additionalcapabilities/additionalcapabilities.go delete mode 100644 cmd/controller/controllers/kubelinter/customchecks/automount/automount.go delete mode 100644 cmd/controller/controllers/kubelinter/customchecks/bindings/bindings.go delete mode 100644 cmd/controller/controllers/kubelinter/customchecks/containerdsock/containerdsock.go delete mode 100644 cmd/controller/controllers/kubelinter/customchecks/networkpolicypernamespace/networkpolicypernamespace.go delete mode 100644 cmd/controller/controllers/kubelinter/customchecks/privescverbs/privescverbs.go delete mode 100644 cmd/controller/controllers/kubelinter/customchecks/securitycontext/securitycontext.go delete mode 100644 cmd/controller/controllers/kubelinter/customobjectkinds/namespace.go delete mode 100644 cmd/controller/controllers/kubelinter/delta.go delete mode 100644 cmd/controller/controllers/kubelinter/kubelinter.go delete mode 100644 cmd/controller/controllers/kubelinter/kubelinter_test.go delete mode 100644 cmd/controller/controllers/kubelinter/types.go delete mode 100644 cmd/controller/controllers/kubelinter/types_test.go diff --git a/cmd/controller/app/app.go b/cmd/controller/app/app.go index 760ba48c..37024ca7 100644 --- a/cmd/controller/app/app.go +++ b/cmd/controller/app/app.go @@ -16,7 +16,6 @@ import ( "github.com/labstack/echo/v4/middleware" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" - "github.com/samber/lo" "golang.org/x/sync/errgroup" "golang.org/x/time/rate" "google.golang.org/grpc" @@ -28,7 +27,6 @@ import ( "github.com/castai/kvisor/cmd/controller/controllers" "github.com/castai/kvisor/cmd/controller/controllers/imagescan" "github.com/castai/kvisor/cmd/controller/controllers/kubebench" - "github.com/castai/kvisor/cmd/controller/controllers/kubelinter" "github.com/castai/kvisor/cmd/controller/kube" "github.com/castai/kvisor/pkg/blobscache" "github.com/castai/kvisor/pkg/castai" @@ -132,18 +130,6 @@ func (a *App) Run(ctx context.Context) error { }) } - if cfg.Linter.Enabled { - linter, err := kubelinter.New(lo.Keys(kubelinter.LinterRuleMap)) - if err != nil { - return err - } - linterCtrl := kubelinter.NewController(log, a.cfg.Linter, linter, castaiClient.GRPC) - kubeClient.RegisterKubernetesChangeListener(linterCtrl) - errg.Go(func() error { - return linterCtrl.Run(ctx) - }) - } - if cfg.KubeBench.Enabled { logsReader := kube.NewPodLogReader(clientset) kubeBenchCtrl := kubebench.NewController(log, clientset, a.cfg.KubeBench, castaiClient.GRPC, logsReader, kubeClient, []string{}) diff --git a/cmd/controller/config/config.go b/cmd/controller/config/config.go index c577b325..80d6f854 100644 --- a/cmd/controller/config/config.go +++ b/cmd/controller/config/config.go @@ -6,7 +6,6 @@ import ( "github.com/castai/kvisor/cmd/controller/controllers" "github.com/castai/kvisor/cmd/controller/controllers/imagescan" "github.com/castai/kvisor/cmd/controller/controllers/kubebench" - "github.com/castai/kvisor/cmd/controller/controllers/kubelinter" "github.com/castai/kvisor/pkg/castai" ) @@ -35,7 +34,6 @@ type Config struct { CastaiController controllers.CastaiConfig `json:"castaiController"` CastaiEnv castai.Config `json:"castaiEnv"` ImageScan imagescan.Config `json:"imageScan"` - Linter kubelinter.Config `json:"linter"` KubeBench kubebench.Config `json:"kubeBench"` JobsCleanup controllers.JobsCleanupConfig `json:"jobsCleanup"` AgentConfig AgentConfig `json:"agentConfig"` diff --git a/cmd/controller/controllers/kubelinter/controller.go b/cmd/controller/controllers/kubelinter/controller.go deleted file mode 100644 index 457e50a0..00000000 --- a/cmd/controller/controllers/kubelinter/controller.go +++ /dev/null @@ -1,188 +0,0 @@ -package kubelinter - -import ( - "context" - "errors" - "fmt" - "reflect" - "strings" - "time" - - castaipb "github.com/castai/kvisor/api/v1/runtime" - "github.com/castai/kvisor/cmd/controller/kube" - "github.com/castai/kvisor/pkg/logging" - "google.golang.org/grpc" - appsv1 "k8s.io/api/apps/v1" - batchv1 "k8s.io/api/batch/v1" - networkingv1 "k8s.io/api/networking/v1" - rbacv1 "k8s.io/api/rbac/v1" - - "github.com/samber/lo" - "golang.stackrox.io/kube-linter/pkg/lintcontext" - corev1 "k8s.io/api/core/v1" -) - -type castaiClient interface { - KubeLinterReportIngest(ctx context.Context, in *castaipb.KubeLinterReport, opts ...grpc.CallOption) (*castaipb.KubeLinterReportIngestResponse, error) -} - -type Config struct { - Enabled bool `json:"enabled"` - ScanInterval time.Duration `validate:"required" json:"scanInterval"` - InitDelay time.Duration `json:"initDelay"` -} - -func NewController(log *logging.Logger, cfg Config, linter *Linter, castaiClient castaiClient) *Controller { - return &Controller{ - log: log.WithField("component", "kubelinter"), - cfg: cfg, - linter: linter, - client: castaiClient, - delta: newDeltaState(), - } -} - -type Controller struct { - log *logging.Logger - cfg Config - linter *Linter - client castaiClient - delta *deltaState -} - -func (c *Controller) RequiredTypes() []reflect.Type { - return []reflect.Type{ - reflect.TypeOf(&corev1.Pod{}), - reflect.TypeOf(&corev1.Namespace{}), - reflect.TypeOf(&corev1.Service{}), - reflect.TypeOf(&appsv1.Deployment{}), - reflect.TypeOf(&appsv1.DaemonSet{}), - reflect.TypeOf(&appsv1.StatefulSet{}), - reflect.TypeOf(&rbacv1.ClusterRoleBinding{}), - reflect.TypeOf(&rbacv1.RoleBinding{}), - reflect.TypeOf(&rbacv1.ClusterRole{}), - reflect.TypeOf(&rbacv1.Role{}), - reflect.TypeOf(&networkingv1.NetworkPolicy{}), - reflect.TypeOf(&networkingv1.Ingress{}), - reflect.TypeOf(&batchv1.Job{}), - reflect.TypeOf(&batchv1.CronJob{}), - } -} - -func (c *Controller) Run(ctx context.Context) error { - c.log.Info("running") - defer c.log.Infof("stopping") - - select { - case <-ctx.Done(): - return ctx.Err() - case <-time.After(c.cfg.InitDelay): - } - - for { - select { - case <-ctx.Done(): - return nil - case <-time.After(c.cfg.ScanInterval): - objects := c.delta.flush() - if len(objects) > 0 { - if err := c.lintObjects(ctx, objects); err != nil && !errors.Is(err, context.Canceled) { - c.log.Error(err.Error()) - - // put unprocessed objects back to delta queue - c.delta.insert(objects...) - } - } - } - } -} - -func (c *Controller) OnAdd(obj kube.Object) { - c.modifyDelta(kube.EventAdd, obj) -} - -func (c *Controller) OnUpdate(obj kube.Object) { - c.modifyDelta(kube.EventUpdate, obj) -} - -func (c *Controller) OnDelete(obj kube.Object) { - c.modifyDelta(kube.EventDelete, obj) -} - -func (c *Controller) modifyDelta(event kube.EventType, o kube.Object) { - switch o := o.(type) { - case *corev1.Pod: - // Do not process not static pods. - if !isStandalonePod(o) { - return - } - case *batchv1.Job: - // Skip jobs which belongs to cronjobs etc. - if !isStandaloneJob(o) { - return - } - } - - switch event { - case kube.EventAdd: - c.delta.upsert(o) - case kube.EventUpdate: - c.delta.upsert(o) - case kube.EventDelete: - c.delta.delete(o) - } -} - -func (c *Controller) lintObjects(ctx context.Context, objects []kube.Object) (rerr error) { - checks, err := c.linter.Run(lo.Map(objects, func(o kube.Object, i int) lintcontext.Object { - return lintcontext.Object{K8sObject: o} - })) - if err != nil { - return fmt.Errorf("kubelinter failed: %w", err) - } - - ctx, cancel := context.WithTimeout(ctx, time.Second*5) - defer cancel() - - pbReport := &castaipb.KubeLinterReport{ - Checks: lo.Map(checks, func(item LinterCheck, index int) *castaipb.KubeLinterCheck { - var passed, failed uint64 - if item.Passed != nil { - passed = uint64(*item.Passed) // nolint:gosec - } - if item.Failed != nil { - failed = uint64(*item.Failed) // nolint:gosec - } - return &castaipb.KubeLinterCheck{ - ResourceUid: item.ResourceID, - Passed: passed, - Failed: failed, - } - }), - } - - if _, err := c.client.KubeLinterReportIngest(ctx, pbReport); err != nil { - return fmt.Errorf("can not send kubelinter checks: %w", err) - } - - c.log.Infof("kubelinter finished, checks: %d", len(checks)) - return nil -} - -func isStandalonePod(pod *corev1.Pod) bool { - if pod.Spec.NodeName == "" { - return false - } - - // Pod created without parent. - if len(pod.OwnerReferences) == 0 { - return true - } - - // Static pod. - return strings.HasSuffix(pod.Name, pod.Spec.NodeName) -} - -func isStandaloneJob(job *batchv1.Job) bool { - return len(job.OwnerReferences) == 0 -} diff --git a/cmd/controller/controllers/kubelinter/controller_test.go b/cmd/controller/controllers/kubelinter/controller_test.go deleted file mode 100644 index 7150c33e..00000000 --- a/cmd/controller/controllers/kubelinter/controller_test.go +++ /dev/null @@ -1,78 +0,0 @@ -package kubelinter - -import ( - "context" - rbacv1 "k8s.io/api/rbac/v1" - "testing" - - castaipb "github.com/castai/kvisor/api/v1/runtime" - "github.com/castai/kvisor/cmd/controller/kube" - "github.com/castai/kvisor/pkg/logging" - "github.com/samber/lo" - "github.com/stretchr/testify/require" - "google.golang.org/grpc" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -func TestSubscriber(t *testing.T) { - log := logging.NewTestLog() - - t.Run("sends linter checks", func(t *testing.T) { - r := require.New(t) - castaiClient := &mockCastaiClient{} - - linter, err := New(lo.Keys(LinterRuleMap)) - r.NoError(err) - - ctrl := &Controller{ - client: castaiClient, - linter: linter, - delta: newDeltaState(), - log: log, - } - - objects := []kube.Object{ - &corev1.Pod{ - TypeMeta: metav1.TypeMeta{ - Kind: "Pod", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "test_pod", - }, - }, - &rbacv1.ClusterRoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test_role_binding", - }, - TypeMeta: metav1.TypeMeta{ - Kind: "ClusterRoleBinding", - APIVersion: "rbac.authorization.k8s.io/v1", - }, - Subjects: []rbacv1.Subject{ - { - Kind: "Group", - Name: "system:authenticated", - }, - }, - RoleRef: rbacv1.RoleRef{ - Kind: "Role", - Name: "testrole", - }, - }, - } - ctx := context.Background() - r.NoError(ctrl.lintObjects(ctx, objects)) - r.Len(castaiClient.reports, 1) - }) -} - -type mockCastaiClient struct { - reports []*castaipb.KubeLinterReport -} - -func (m *mockCastaiClient) KubeLinterReportIngest(ctx context.Context, in *castaipb.KubeLinterReport, opts ...grpc.CallOption) (*castaipb.KubeLinterReportIngestResponse, error) { - m.reports = append(m.reports, in) - return &castaipb.KubeLinterReportIngestResponse{}, nil -} diff --git a/cmd/controller/controllers/kubelinter/customchecks/additionalcapabilities/additionalcapabilities.go b/cmd/controller/controllers/kubelinter/customchecks/additionalcapabilities/additionalcapabilities.go deleted file mode 100644 index a2026f38..00000000 --- a/cmd/controller/controllers/kubelinter/customchecks/additionalcapabilities/additionalcapabilities.go +++ /dev/null @@ -1,16 +0,0 @@ -package additionalcapabilities - -import ( - "golang.stackrox.io/kube-linter/pkg/config" -) - -func Check() *config.Check { - return &config.Check{ - Name: "additional-capabilities", - Description: "Checks if pod has additional capabilities.", - Template: "verify-container-capabilities", - Params: map[string]interface{}{ - "forbiddenCapabilities": []string{"all"}, - }, - } -} diff --git a/cmd/controller/controllers/kubelinter/customchecks/automount/automount.go b/cmd/controller/controllers/kubelinter/customchecks/automount/automount.go deleted file mode 100644 index fb477228..00000000 --- a/cmd/controller/controllers/kubelinter/customchecks/automount/automount.go +++ /dev/null @@ -1,89 +0,0 @@ -package automount - -import ( - "fmt" - "strings" - - "golang.stackrox.io/kube-linter/pkg/check" - "golang.stackrox.io/kube-linter/pkg/config" - "golang.stackrox.io/kube-linter/pkg/diagnostic" - "golang.stackrox.io/kube-linter/pkg/extract" - "golang.stackrox.io/kube-linter/pkg/lintcontext" - "golang.stackrox.io/kube-linter/pkg/objectkinds" - "golang.stackrox.io/kube-linter/pkg/templates" - "golang.stackrox.io/kube-linter/pkg/templates/util" -) - -func Check() *config.Check { - return &config.Check{ - Name: "sa-token-automount", - Description: "Service Account Token automount is not disabled", - Template: "sa-token-automount", - Params: map[string]interface{}{}, - } -} - -func init() { - templates.Register(check.Template{ - HumanName: "Service Account Token mounts", - Key: "sa-token-automount", - SupportedObjectKinds: config.ObjectKindsDesc{ - ObjectKinds: []string{objectkinds.DeploymentLike}, - }, - Parameters: ParamDescs, - ParseAndValidateParams: ParseAndValidate, - Instantiate: WrapInstantiateFunc(func(_ Params) (check.Func, error) { - return func(_ lintcontext.LintContext, object lintcontext.Object) []diagnostic.Diagnostic { - podSpec, found := extract.PodSpec(object.K8sObject) - if !found { - return nil - } - if podSpec.AutomountServiceAccountToken != nil && !*podSpec.AutomountServiceAccountToken { - return nil - } - return []diagnostic.Diagnostic{{Message: "Resource does not have service account token automount disabled"}} - }, nil - }), - }) -} - -type Params struct { -} - -var ( - // Use some imports in case they don't get used otherwise. - _ = util.MustParseParameterDesc - _ = fmt.Sprintf - - ParamDescs = []check.ParameterDesc{} -) - -func (p *Params) Validate() error { - var validationErrors []string - if len(validationErrors) > 0 { - return fmt.Errorf("invalid parameters: %s", strings.Join(validationErrors, ", ")) - } - return nil -} - -// ParseAndValidate instantiates a Params object out of the passed map[string]interface{}, -// validates it, and returns it. -// The return type is interface{} to satisfy the type in the Template struct. -func ParseAndValidate(m map[string]interface{}) (interface{}, error) { - var p Params - if err := util.DecodeMapStructure(m, &p); err != nil { - return nil, err - } - if err := p.Validate(); err != nil { - return nil, err - } - return p, nil -} - -// WrapInstantiateFunc is a convenience wrapper that wraps an untyped instantiate function -// into a typed one. -func WrapInstantiateFunc(f func(p Params) (check.Func, error)) func(interface{}) (check.Func, error) { - return func(paramsInt interface{}) (check.Func, error) { - return f(paramsInt.(Params)) - } -} diff --git a/cmd/controller/controllers/kubelinter/customchecks/bindings/bindings.go b/cmd/controller/controllers/kubelinter/customchecks/bindings/bindings.go deleted file mode 100644 index 4eaaa63b..00000000 --- a/cmd/controller/controllers/kubelinter/customchecks/bindings/bindings.go +++ /dev/null @@ -1,146 +0,0 @@ -package bindings - -import ( - "fmt" - "slices" - - "golang.stackrox.io/kube-linter/pkg/check" - "golang.stackrox.io/kube-linter/pkg/config" - "golang.stackrox.io/kube-linter/pkg/diagnostic" - "golang.stackrox.io/kube-linter/pkg/lintcontext" - "golang.stackrox.io/kube-linter/pkg/objectkinds" - "golang.stackrox.io/kube-linter/pkg/templates" - "golang.stackrox.io/kube-linter/pkg/templates/util" - rbacv1 "k8s.io/api/rbac/v1" -) - -const ( - templateName = "bindings" -) - -var ( - ParamDescs = []check.ParameterDesc{} -) - -func Checks() []*config.Check { - var checks []*config.Check - for k, v := range rules { - checks = append(checks, &config.Check{ - Name: k, - Template: templateName, - Description: v.Name, - Params: map[string]interface{}{ - "Values": v.Values, - "ExcludedValues": v.ExcludedValues, - }, - }) - } - - return checks -} - -func init() { - templates.Register(roleBindingsTemplate()) -} - -var ( - rules = map[string]BindingsCheck{ - "system-masters": { - Name: "Avoid use of system:masters group", - Values: []string{"system:masters"}, - }, - "system-anonymous": { - Name: "Avoid binding to system:anonymous", - Values: []string{"system:anonymous"}, - }, - "system-unauthenticated": { - Name: "Avoid non-default bindings to system:unauthenticated", - Values: []string{"system:unauthenticated"}, - ExcludedValues: []string{"system:public-info-viewer"}, - }, - "system-authenticated": { - Name: "Avoid non-default bindings to system:authenticated", - Values: []string{"system:authenticated"}, - ExcludedValues: []string{"system:public-info-viewer", "system:basic-user", "system:discovery"}, - }, - } -) - -type BindingsCheck struct { - Name string - Values []string - ExcludedValues []string -} - -func roleBindingsTemplate() check.Template { - template := check.Template{ - HumanName: "Avoid bindings to certain groups", - Key: templateName, - SupportedObjectKinds: config.ObjectKindsDesc{ - ObjectKinds: []string{ - objectkinds.RoleBinding, - objectkinds.ClusterRoleBinding, - }, - }, - Parameters: ParamDescs, - ParseAndValidateParams: ParseAndValidate, - Instantiate: WrapInstantiateFunc(func(p Params) (check.Func, error) { - return func(_ lintcontext.LintContext, object lintcontext.Object) []diagnostic.Diagnostic { - var subjects []rbacv1.Subject - var roleRef rbacv1.RoleRef - - rb, ok := object.K8sObject.(*rbacv1.RoleBinding) - if !ok { - crb, ok := object.K8sObject.(*rbacv1.ClusterRoleBinding) - if !ok { - return nil - } - - subjects = crb.Subjects - roleRef = crb.RoleRef - } else { - subjects = rb.Subjects - roleRef = rb.RoleRef - } - - for _, subject := range subjects { - if subject.Kind == "Group" && slices.Contains(p.Values, subject.Name) { - if p.ExcludedValues == nil || !slices.Contains(p.ExcludedValues, roleRef.Name) { - return []diagnostic.Diagnostic{{Message: fmt.Sprintf("Binding to %s", subject.Name)}} - } - } - } - - return nil - }, nil - }), - } - - return template -} - -type Params struct { - Values []string - ExcludedValues []string -} - -func (p *Params) Validate() error { - return nil -} - -func ParseAndValidate(m map[string]interface{}) (interface{}, error) { - var p Params - if err := util.DecodeMapStructure(m, &p); err != nil { - return nil, err - } - if err := p.Validate(); err != nil { - return nil, err - } - return p, nil -} - -func WrapInstantiateFunc(f func(p Params) (check.Func, error)) func(interface{}) (check.Func, error) { - return func(paramsInt interface{}) (check.Func, error) { - return f(paramsInt.(Params)) - } -} diff --git a/cmd/controller/controllers/kubelinter/customchecks/containerdsock/containerdsock.go b/cmd/controller/controllers/kubelinter/customchecks/containerdsock/containerdsock.go deleted file mode 100644 index b4820d53..00000000 --- a/cmd/controller/controllers/kubelinter/customchecks/containerdsock/containerdsock.go +++ /dev/null @@ -1,16 +0,0 @@ -package containerdsock - -import ( - "golang.stackrox.io/kube-linter/pkg/config" -) - -func Check() *config.Check { - return &config.Check{ - Name: "containerd-sock", - Description: "Alert on deployments with containerd.sock mounted in containers.", - Template: "host-mounts", - Params: map[string]interface{}{ - "dirs": []string{"containerd.sock$"}, - }, - } -} diff --git a/cmd/controller/controllers/kubelinter/customchecks/networkpolicypernamespace/networkpolicypernamespace.go b/cmd/controller/controllers/kubelinter/customchecks/networkpolicypernamespace/networkpolicypernamespace.go deleted file mode 100644 index 4420e6bd..00000000 --- a/cmd/controller/controllers/kubelinter/customchecks/networkpolicypernamespace/networkpolicypernamespace.go +++ /dev/null @@ -1,94 +0,0 @@ -package networkpolicypernamespace - -import ( - "fmt" - "strings" - - "github.com/castai/kvisor/cmd/controller/controllers/kubelinter/customobjectkinds" - "golang.stackrox.io/kube-linter/pkg/check" - "golang.stackrox.io/kube-linter/pkg/config" - "golang.stackrox.io/kube-linter/pkg/diagnostic" - "golang.stackrox.io/kube-linter/pkg/lintcontext" - "golang.stackrox.io/kube-linter/pkg/templates" - "golang.stackrox.io/kube-linter/pkg/templates/util" - corev1 "k8s.io/api/core/v1" - networkingv1 "k8s.io/api/networking/v1" -) - -func Check() *config.Check { - return &config.Check{ - Name: "network-policy-per-namespace", - Description: "Use network policies to isolate traffic in your cluster network", - Template: "network-policy-per-namespace", - Params: map[string]interface{}{}, - } -} - -func init() { - networkPolicyGVR := networkingv1.SchemeGroupVersion.WithKind("NetworkPolicy") - - templates.Register(check.Template{ - HumanName: "Use network policies to isolate traffic in your cluster network", - Key: "network-policy-per-namespace", - SupportedObjectKinds: config.ObjectKindsDesc{ - ObjectKinds: []string{customobjectkinds.Namespace}, - }, - Parameters: ParamDescs, - ParseAndValidateParams: ParseAndValidate, - Instantiate: WrapInstantiateFunc(func(_ Params) (check.Func, error) { - return func(ctx lintcontext.LintContext, object lintcontext.Object) []diagnostic.Diagnostic { - ns, ok := object.K8sObject.(*corev1.Namespace) - if !ok { - return nil - } - for _, obj := range ctx.Objects() { - if obj.GetK8sObjectName().GroupVersionKind == networkPolicyGVR && obj.K8sObject.GetNamespace() == ns.Name { - return nil - } - } - return []diagnostic.Diagnostic{{Message: "Namespace does not have any network policy"}} - }, nil - }), - }) -} - -type Params struct { -} - -var ( - // Use some imports in case they don't get used otherwise. - _ = util.MustParseParameterDesc - _ = fmt.Sprintf - - ParamDescs = []check.ParameterDesc{} -) - -func (p *Params) Validate() error { - var validationErrors []string - if len(validationErrors) > 0 { - return fmt.Errorf("invalid parameters: %s", strings.Join(validationErrors, ", ")) - } - return nil -} - -// ParseAndValidate instantiates a Params object out of the passed map[string]interface{}, -// validates it, and returns it. -// The return type is interface{} to satisfy the type in the Template struct. -func ParseAndValidate(m map[string]interface{}) (interface{}, error) { - var p Params - if err := util.DecodeMapStructure(m, &p); err != nil { - return nil, err - } - if err := p.Validate(); err != nil { - return nil, err - } - return p, nil -} - -// WrapInstantiateFunc is a convenience wrapper that wraps an untyped instantiate function -// into a typed one. -func WrapInstantiateFunc(f func(p Params) (check.Func, error)) func(interface{}) (check.Func, error) { - return func(paramsInt interface{}) (check.Func, error) { - return f(paramsInt.(Params)) - } -} diff --git a/cmd/controller/controllers/kubelinter/customchecks/privescverbs/privescverbs.go b/cmd/controller/controllers/kubelinter/customchecks/privescverbs/privescverbs.go deleted file mode 100644 index 3fa49adb..00000000 --- a/cmd/controller/controllers/kubelinter/customchecks/privescverbs/privescverbs.go +++ /dev/null @@ -1,99 +0,0 @@ -package privescverbs - -import ( - "fmt" - "slices" - "strings" - - "golang.stackrox.io/kube-linter/pkg/check" - "golang.stackrox.io/kube-linter/pkg/config" - "golang.stackrox.io/kube-linter/pkg/diagnostic" - "golang.stackrox.io/kube-linter/pkg/lintcontext" - "golang.stackrox.io/kube-linter/pkg/objectkinds" - "golang.stackrox.io/kube-linter/pkg/templates" - "golang.stackrox.io/kube-linter/pkg/templates/util" - rbacv1 "k8s.io/api/rbac/v1" -) - -func Check() *config.Check { - return &config.Check{ - Name: "privesc-verbs", - Description: "Use of Bind, Impersonate and Escalate permissions", - Template: "privesc-verbs", - Params: map[string]interface{}{}, - } -} - -var ( - privescVerbs = []string{"bind", "escalate", "impersonate"} -) - -func init() { - templates.Register(check.Template{ - HumanName: "Use of Bind, Impersonate and Escalate permissions", - Key: "privesc-verbs", - SupportedObjectKinds: config.ObjectKindsDesc{ - ObjectKinds: []string{ - objectkinds.Role, - objectkinds.ClusterRole, - }, - }, - Parameters: ParamDescs, - ParseAndValidateParams: ParseAndValidate, - Instantiate: WrapInstantiateFunc(func(_ Params) (check.Func, error) { - return func(_ lintcontext.LintContext, object lintcontext.Object) []diagnostic.Diagnostic { - var policyRules []rbacv1.PolicyRule - rb, ok := object.K8sObject.(*rbacv1.Role) - if !ok { - cr, ok := object.K8sObject.(*rbacv1.ClusterRole) - if !ok { - return nil - } - policyRules = cr.Rules - } else { - policyRules = rb.Rules - } - for _, rule := range policyRules { - for _, verb := range rule.Verbs { - if slices.Contains(privescVerbs, verb) { - return []diagnostic.Diagnostic{{Message: "Usage of 'bind, impersonate, escalate'"}} - } - } - } - - return nil - }, nil - }), - }) -} - -type Params struct { -} - -var ( - // Use some imports in case they don't get used otherwise. - _ = util.MustParseParameterDesc - _ = fmt.Sprintf - - ParamDescs = []check.ParameterDesc{} -) - -func (p *Params) Validate() error { - var validationErrors []string - if len(validationErrors) > 0 { - return fmt.Errorf("invalid parameters: %s", strings.Join(validationErrors, ", ")) - } - return nil -} - -func ParseAndValidate(m map[string]interface{}) (interface{}, error) { - return Params{}, nil -} - -// WrapInstantiateFunc is a convenience wrapper that wraps an untyped instantiate function -// into a typed one. -func WrapInstantiateFunc(f func(p Params) (check.Func, error)) func(interface{}) (check.Func, error) { - return func(paramsInt interface{}) (check.Func, error) { - return f(paramsInt.(Params)) - } -} diff --git a/cmd/controller/controllers/kubelinter/customchecks/securitycontext/securitycontext.go b/cmd/controller/controllers/kubelinter/customchecks/securitycontext/securitycontext.go deleted file mode 100644 index 13ce26a4..00000000 --- a/cmd/controller/controllers/kubelinter/customchecks/securitycontext/securitycontext.go +++ /dev/null @@ -1,122 +0,0 @@ -package securitycontext - -import ( - "fmt" - "strings" - - "golang.stackrox.io/kube-linter/pkg/check" - "golang.stackrox.io/kube-linter/pkg/config" - "golang.stackrox.io/kube-linter/pkg/diagnostic" - "golang.stackrox.io/kube-linter/pkg/extract" - "golang.stackrox.io/kube-linter/pkg/lintcontext" - "golang.stackrox.io/kube-linter/pkg/objectkinds" - "golang.stackrox.io/kube-linter/pkg/templates" - "golang.stackrox.io/kube-linter/pkg/templates/util" - corev1 "k8s.io/api/core/v1" -) - -func Check() *config.Check { - return &config.Check{ - Name: "has-security-context", - Description: "Resource has security context", - Template: "has-security-context", - Params: map[string]interface{}{}, - } -} - -func init() { - templates.Register(check.Template{ - HumanName: "Resource has security context", - Key: "has-security-context", - SupportedObjectKinds: config.ObjectKindsDesc{ - ObjectKinds: []string{objectkinds.DeploymentLike}, - }, - Parameters: ParamDescs, - ParseAndValidateParams: ParseAndValidate, - Instantiate: WrapInstantiateFunc(func(_ Params) (check.Func, error) { - return func(_ lintcontext.LintContext, object lintcontext.Object) []diagnostic.Diagnostic { - podSpec, found := extract.PodSpec(object.K8sObject) - if !found { - return nil - } - // Check if security context is set at the pod level - if isSecurityContextSet(podSpec.SecurityContext) { - return nil - } - // Check if security context is set for all the containers in the pod - for _, container := range podSpec.NonInitContainers() { - if !isContainerSecurityContextSet(container.SecurityContext) { - return []diagnostic.Diagnostic{{ - Message: "Resource does not have security context attached to the pod or any of the containers", - }} - } - } - return nil - }, nil - }), - }) -} - -func isSecurityContextSet(ctx *corev1.PodSecurityContext) bool { - if ctx == nil { - return false - } - return ctx.SELinuxOptions != nil || ctx.WindowsOptions != nil || - ctx.RunAsUser != nil || ctx.RunAsGroup != nil || - ctx.RunAsNonRoot != nil || ctx.SupplementalGroups != nil || - ctx.FSGroup != nil || ctx.Sysctls != nil || - ctx.FSGroupChangePolicy != nil || ctx.SeccompProfile != nil -} - -func isContainerSecurityContextSet(ctx *corev1.SecurityContext) bool { - if ctx == nil { - return false - } - return ctx.Capabilities != nil || ctx.Privileged != nil || - ctx.SELinuxOptions != nil || ctx.WindowsOptions != nil || - ctx.RunAsUser != nil || ctx.RunAsGroup != nil || - ctx.RunAsNonRoot != nil || ctx.ReadOnlyRootFilesystem != nil || - ctx.AllowPrivilegeEscalation != nil || ctx.ProcMount != nil || - ctx.SeccompProfile != nil || ctx.AppArmorProfile != nil -} - -type Params struct { -} - -var ( - // Use some imports in case they don't get used otherwise. - _ = util.MustParseParameterDesc - _ = fmt.Sprintf - - ParamDescs = []check.ParameterDesc{} -) - -func (p *Params) Validate() error { - var validationErrors []string - if len(validationErrors) > 0 { - return fmt.Errorf("invalid parameters: %s", strings.Join(validationErrors, ", ")) - } - return nil -} - -// ParseAndValidate instantiates a Params object out of the passed map[string]interface{}, -// validates it, and returns it. -// The return type is interface{} to satisfy the type in the Template struct. -func ParseAndValidate(m map[string]interface{}) (interface{}, error) { - var p Params - if err := util.DecodeMapStructure(m, &p); err != nil { - return nil, err - } - if err := p.Validate(); err != nil { - return nil, err - } - return p, nil -} - -// WrapInstantiateFunc is a convenience wrapper that wraps an untyped instantiate function -// into a typed one. -func WrapInstantiateFunc(f func(p Params) (check.Func, error)) func(interface{}) (check.Func, error) { - return func(paramsInt interface{}) (check.Func, error) { - return f(paramsInt.(Params)) - } -} diff --git a/cmd/controller/controllers/kubelinter/customobjectkinds/namespace.go b/cmd/controller/controllers/kubelinter/customobjectkinds/namespace.go deleted file mode 100644 index 960ae40c..00000000 --- a/cmd/controller/controllers/kubelinter/customobjectkinds/namespace.go +++ /dev/null @@ -1,27 +0,0 @@ -package customobjectkinds - -import ( - "sync" - - "golang.stackrox.io/kube-linter/pkg/objectkinds" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -const ( - // Namespace represents Kubernetes Namespace objects. Case sensitive. - Namespace = "Namespace" -) - -var ( - namespaceGVK = corev1.SchemeGroupVersion.WithKind("Namespace") - once sync.Once -) - -func RegisterNamespaceKind() { - once.Do(func() { - objectkinds.RegisterObjectKind(Namespace, objectkinds.MatcherFunc(func(gvk schema.GroupVersionKind) bool { - return gvk == namespaceGVK - })) - }) -} diff --git a/cmd/controller/controllers/kubelinter/delta.go b/cmd/controller/controllers/kubelinter/delta.go deleted file mode 100644 index db7ae228..00000000 --- a/cmd/controller/controllers/kubelinter/delta.go +++ /dev/null @@ -1,65 +0,0 @@ -package kubelinter - -import ( - "sync" - - "github.com/castai/kvisor/cmd/controller/kube" - "github.com/samber/lo" - v1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/types" -) - -func newDeltaState() *deltaState { - return &deltaState{ - objectMap: make(map[types.UID]kube.Object), - mu: sync.Mutex{}, - } -} - -type deltaState struct { - objectMap map[types.UID]kube.Object - mu sync.Mutex -} - -func (d *deltaState) insert(objs ...kube.Object) { - d.mu.Lock() - defer d.mu.Unlock() - - for _, o := range objs { - key := o.GetUID() - if _, ok := d.objectMap[key]; !ok { - d.objectMap[key] = o - } - } -} - -func (d *deltaState) upsert(o kube.Object) { - d.mu.Lock() - defer d.mu.Unlock() - - // Skip linting pod updates. - switch o.(type) { - case *v1.Pod: - return - } - - key := o.GetUID() - d.objectMap[key] = o -} - -func (d *deltaState) delete(o kube.Object) { - d.mu.Lock() - defer d.mu.Unlock() - - delete(d.objectMap, o.GetUID()) -} - -func (d *deltaState) flush() []kube.Object { - d.mu.Lock() - defer d.mu.Unlock() - defer func() { - d.objectMap = make(map[types.UID]kube.Object) - }() - - return lo.Values(d.objectMap) -} diff --git a/cmd/controller/controllers/kubelinter/kubelinter.go b/cmd/controller/controllers/kubelinter/kubelinter.go deleted file mode 100644 index 02c67859..00000000 --- a/cmd/controller/controllers/kubelinter/kubelinter.go +++ /dev/null @@ -1,265 +0,0 @@ -package kubelinter - -import ( - "fmt" - - "github.com/castai/kvisor/cmd/controller/controllers/kubelinter/customchecks/additionalcapabilities" - "github.com/castai/kvisor/cmd/controller/controllers/kubelinter/customchecks/automount" - "github.com/castai/kvisor/cmd/controller/controllers/kubelinter/customchecks/bindings" - "github.com/castai/kvisor/cmd/controller/controllers/kubelinter/customchecks/containerdsock" - "github.com/castai/kvisor/cmd/controller/controllers/kubelinter/customchecks/networkpolicypernamespace" - "github.com/castai/kvisor/cmd/controller/controllers/kubelinter/customchecks/privescverbs" - "github.com/castai/kvisor/cmd/controller/controllers/kubelinter/customchecks/securitycontext" - "github.com/castai/kvisor/cmd/controller/controllers/kubelinter/customobjectkinds" - "github.com/samber/lo" - "golang.stackrox.io/kube-linter/pkg/builtinchecks" - "golang.stackrox.io/kube-linter/pkg/checkregistry" - kubelinterconfig "golang.stackrox.io/kube-linter/pkg/config" - "golang.stackrox.io/kube-linter/pkg/configresolver" - "golang.stackrox.io/kube-linter/pkg/diagnostic" - "golang.stackrox.io/kube-linter/pkg/ignore" - "golang.stackrox.io/kube-linter/pkg/instantiatedcheck" - "golang.stackrox.io/kube-linter/pkg/lintcontext" - "golang.stackrox.io/kube-linter/pkg/run" - _ "golang.stackrox.io/kube-linter/pkg/templates/accesstoresources" // Import check templates. - _ "golang.stackrox.io/kube-linter/pkg/templates/antiaffinity" - _ "golang.stackrox.io/kube-linter/pkg/templates/clusteradminrolebinding" - _ "golang.stackrox.io/kube-linter/pkg/templates/containercapabilities" - _ "golang.stackrox.io/kube-linter/pkg/templates/cpurequirements" - _ "golang.stackrox.io/kube-linter/pkg/templates/danglinghpa" - _ "golang.stackrox.io/kube-linter/pkg/templates/danglingingress" - _ "golang.stackrox.io/kube-linter/pkg/templates/danglingnetworkpolicy" - _ "golang.stackrox.io/kube-linter/pkg/templates/danglingnetworkpolicypeer" - _ "golang.stackrox.io/kube-linter/pkg/templates/danglingservice" - _ "golang.stackrox.io/kube-linter/pkg/templates/danglingservicemonitor" - _ "golang.stackrox.io/kube-linter/pkg/templates/deprecatedserviceaccount" - _ "golang.stackrox.io/kube-linter/pkg/templates/disallowedgvk" - _ "golang.stackrox.io/kube-linter/pkg/templates/dnsconfigoptions" - _ "golang.stackrox.io/kube-linter/pkg/templates/duplicatenvvar" - _ "golang.stackrox.io/kube-linter/pkg/templates/envvar" - _ "golang.stackrox.io/kube-linter/pkg/templates/forbiddenannotation" - _ "golang.stackrox.io/kube-linter/pkg/templates/hostipc" - _ "golang.stackrox.io/kube-linter/pkg/templates/hostmounts" - _ "golang.stackrox.io/kube-linter/pkg/templates/hostnetwork" - _ "golang.stackrox.io/kube-linter/pkg/templates/hostpid" - _ "golang.stackrox.io/kube-linter/pkg/templates/hpareplicas" - _ "golang.stackrox.io/kube-linter/pkg/templates/imagepullpolicy" - _ "golang.stackrox.io/kube-linter/pkg/templates/latesttag" - _ "golang.stackrox.io/kube-linter/pkg/templates/livenessport" - _ "golang.stackrox.io/kube-linter/pkg/templates/livenessprobe" - _ "golang.stackrox.io/kube-linter/pkg/templates/memoryrequirements" - _ "golang.stackrox.io/kube-linter/pkg/templates/mismatchingselector" - _ "golang.stackrox.io/kube-linter/pkg/templates/namespace" - _ "golang.stackrox.io/kube-linter/pkg/templates/nodeaffinity" - _ "golang.stackrox.io/kube-linter/pkg/templates/nonexistentserviceaccount" - _ "golang.stackrox.io/kube-linter/pkg/templates/nonisolatedpod" - _ "golang.stackrox.io/kube-linter/pkg/templates/pdbmaxunavailable" - _ "golang.stackrox.io/kube-linter/pkg/templates/pdbminavailable" - _ "golang.stackrox.io/kube-linter/pkg/templates/pdbunhealthypodevictionpolicy" - _ "golang.stackrox.io/kube-linter/pkg/templates/ports" - _ "golang.stackrox.io/kube-linter/pkg/templates/privileged" - _ "golang.stackrox.io/kube-linter/pkg/templates/privilegedports" - _ "golang.stackrox.io/kube-linter/pkg/templates/privilegeescalation" - _ "golang.stackrox.io/kube-linter/pkg/templates/readinessport" - _ "golang.stackrox.io/kube-linter/pkg/templates/readinessprobe" - _ "golang.stackrox.io/kube-linter/pkg/templates/readonlyrootfs" - _ "golang.stackrox.io/kube-linter/pkg/templates/readsecret" - _ "golang.stackrox.io/kube-linter/pkg/templates/replicas" - _ "golang.stackrox.io/kube-linter/pkg/templates/requiredannotation" - _ "golang.stackrox.io/kube-linter/pkg/templates/requiredlabel" - _ "golang.stackrox.io/kube-linter/pkg/templates/restartpolicy" - _ "golang.stackrox.io/kube-linter/pkg/templates/runasnonroot" - _ "golang.stackrox.io/kube-linter/pkg/templates/sccdenypriv" - _ "golang.stackrox.io/kube-linter/pkg/templates/serviceaccount" - _ "golang.stackrox.io/kube-linter/pkg/templates/servicetype" - _ "golang.stackrox.io/kube-linter/pkg/templates/startupport" - _ "golang.stackrox.io/kube-linter/pkg/templates/sysctl" - _ "golang.stackrox.io/kube-linter/pkg/templates/targetport" - _ "golang.stackrox.io/kube-linter/pkg/templates/unsafeprocmount" - _ "golang.stackrox.io/kube-linter/pkg/templates/updateconfig" - _ "golang.stackrox.io/kube-linter/pkg/templates/wildcardinrules" - _ "golang.stackrox.io/kube-linter/pkg/templates/writablehostmount" - "k8s.io/apimachinery/pkg/types" -) - -func New(checks []string) (*Linter, error) { - registry := checkregistry.New() - - if err := builtinchecks.LoadInto(registry); err != nil { - return nil, fmt.Errorf("load info from registry: %w", err) - } - - registerCustomObjectKinds() - - if err := registerCustomChecks(registry); err != nil { - return nil, fmt.Errorf("loading custom CAST check: %w", err) - } - - cfg := kubelinterconfig.Config{ - Checks: kubelinterconfig.ChecksConfig{ - AddAllBuiltIn: true, - }, - } - if err := configresolver.LoadCustomChecksInto(&cfg, registry); err != nil { - return nil, fmt.Errorf("loading custom checks info: %w", err) - } - - rules := make(map[string]struct{}) - instantiatedChecks := make([]*instantiatedcheck.InstantiatedCheck, 0, len(checks)) - for _, checkName := range checks { - rules[checkName] = struct{}{} - instantiatedCheck := registry.Load(checkName) - if instantiatedCheck == nil { - return nil, fmt.Errorf("check %q not found", checkName) - } - if checkName == "namespace" { - hideKubernetesDefaultService(instantiatedCheck) - } - instantiatedChecks = append(instantiatedChecks, instantiatedCheck) - } - - return &Linter{ - rules: rules, - registry: registry, - instantiatedChecks: instantiatedChecks, - }, nil -} - -func registerCustomChecks(registry checkregistry.CheckRegistry) error { - checks := []*kubelinterconfig.Check{ - automount.Check(), - containerdsock.Check(), - securitycontext.Check(), - networkpolicypernamespace.Check(), - additionalcapabilities.Check(), - privescverbs.Check(), - } - checks = append(checks, bindings.Checks()...) - - for _, check := range checks { - if err := registry.Register(check); err != nil { - return err - } - } - return nil -} - -func registerCustomObjectKinds() { - customobjectkinds.RegisterNamespaceKind() -} - -type Linter struct { - rules map[string]struct{} - registry checkregistry.CheckRegistry - instantiatedChecks []*instantiatedcheck.InstantiatedCheck -} - -func (l *Linter) RunWithRules(objects []lintcontext.Object, rules []string) ([]LinterCheck, error) { - return l.run(objects, lo.SliceToMap(rules, func(item string) (string, struct{}) { - return item, struct{}{} - })) -} - -func (l *Linter) Run(objects []lintcontext.Object) ([]LinterCheck, error) { - return l.run(objects, l.rules) -} - -func (l *Linter) run(objects []lintcontext.Object, rules map[string]struct{}) ([]LinterCheck, error) { - lintctx := &lintContext{ - objects: objects, - } - - res := l.runKubeLinter([]lintcontext.LintContext{lintctx}, rules) - - resources := make(map[types.UID]LinterCheck) - for _, check := range res.Reports { - obj := check.Object.K8sObject - - if _, ok := resources[obj.GetUID()]; !ok { - resources[obj.GetUID()] = LinterCheck{ - ResourceID: string(obj.GetUID()), - Failed: new(LinterRuleSet), - Passed: new(LinterRuleSet), - } - } - - if check.Diagnostic.Message != "" { - resources[obj.GetUID()].Failed.Add(LinterRuleMap[check.Check]) - } else { - resources[obj.GetUID()].Passed.Add(LinterRuleMap[check.Check]) - } - - } - - return lo.Values(resources), nil -} - -func (l *Linter) runKubeLinter(lintCtxs []lintcontext.LintContext, rules map[string]struct{}) run.Result { - var result run.Result - - for _, instantiatedCheck := range l.instantiatedChecks { - if _, ok := rules[instantiatedCheck.Spec.Name]; ok { - result.Checks = append(result.Checks, instantiatedCheck.Spec) - } - } - - for _, lintCtx := range lintCtxs { - for _, obj := range lintCtx.Objects() { - for _, check := range l.instantiatedChecks { - if _, ok := rules[check.Spec.Name]; !ok { - continue - } - if !check.Matcher.Matches(obj.K8sObject.GetObjectKind().GroupVersionKind()) { - continue - } - if ignore.ObjectForCheck(obj.K8sObject.GetAnnotations(), check.Spec.Name) { - continue - } - diagnostics := check.Func(lintCtx, obj) - if len(diagnostics) > 0 { - for _, d := range diagnostics { - result.Reports = append(result.Reports, diagnostic.WithContext{ - Diagnostic: d, - Check: check.Spec.Name, - Object: obj, - }) - } - } else { - result.Reports = append(result.Reports, diagnostic.WithContext{ - Diagnostic: diagnostic.Diagnostic{}, - Check: check.Spec.Name, - Object: obj, - }) - } - } - } - } - - return result -} - -type lintContext struct { - objects []lintcontext.Object - invalidObjects []lintcontext.InvalidObject -} - -// Objects returns the (valid) objects loaded from this LintContext. -func (l *lintContext) Objects() []lintcontext.Object { - return l.objects -} - -// InvalidObjects returns any objects that we attempted to load, but which were invalid. -func (l *lintContext) InvalidObjects() []lintcontext.InvalidObject { - return l.invalidObjects -} - -func hideKubernetesDefaultService(check *instantiatedcheck.InstantiatedCheck) { - check.Func = func(lintCtx lintcontext.LintContext, object lintcontext.Object) []diagnostic.Diagnostic { - if object.K8sObject.GetNamespace() == "default" && - object.K8sObject.GetObjectKind().GroupVersionKind().Kind == "Service" && - object.K8sObject.GetName() == "kubernetes" { - return []diagnostic.Diagnostic{} - } - return check.Func(lintCtx, object) - } -} diff --git a/cmd/controller/controllers/kubelinter/kubelinter_test.go b/cmd/controller/controllers/kubelinter/kubelinter_test.go deleted file mode 100644 index fb69d46c..00000000 --- a/cmd/controller/controllers/kubelinter/kubelinter_test.go +++ /dev/null @@ -1,128 +0,0 @@ -package kubelinter - -import ( - "testing" - - "github.com/samber/lo" - "github.com/stretchr/testify/require" - "golang.stackrox.io/kube-linter/pkg/lintcontext" - corev1 "k8s.io/api/core/v1" - rbacv1 "k8s.io/api/rbac/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -func TestLinter(t *testing.T) { - t.Run("checks for containerd sock mount", func(t *testing.T) { - r := require.New(t) - - linter, err := New(lo.Keys(LinterRuleMap)) - r.NoError(err) - - checks, err := linter.Run([]lintcontext.Object{{ - K8sObject: &corev1.Pod{ - TypeMeta: metav1.TypeMeta{ - Kind: "Pod", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "test_pod", - }, - Spec: corev1.PodSpec{ - Containers: []corev1.Container{ - { - Name: "test", - Image: "test-image", - VolumeMounts: []corev1.VolumeMount{ - { - Name: "containerd.sock", - MountPath: "/var/lib/containerd.sock", - }, - }, - }, - }, - Volumes: []corev1.Volume{ - { - Name: "containerd.sock", - VolumeSource: corev1.VolumeSource{ - HostPath: &corev1.HostPathVolumeSource{ - Path: "/var/lib/containerd.sock", - }, - }, - }, - }, - }, - }, - }}) - r.NoError(err) - r.Contains(checks[0].Failed.Rules(), "containerd-sock") - }) - - t.Run("checks for additional capabilities", func(t *testing.T) { - r := require.New(t) - - linter, err := New(lo.Keys(LinterRuleMap)) - r.NoError(err) - - checks, err := linter.Run([]lintcontext.Object{{ - K8sObject: &corev1.Pod{ - TypeMeta: metav1.TypeMeta{ - Kind: "Pod", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "test_pod", - }, - Spec: corev1.PodSpec{ - Containers: []corev1.Container{ - { - Name: "test", - Image: "test-image", - SecurityContext: &corev1.SecurityContext{ - Capabilities: &corev1.Capabilities{ - Add: []corev1.Capability{ - "NET_ADMIN", - }, - }, - }, - }, - }, - }, - }, - }}) - r.NoError(err) - r.Contains(checks[0].Failed.Rules(), "additional-capabilities") - }) - - t.Run("checks for bindings", func(t *testing.T) { - r := require.New(t) - - linter, err := New(lo.Keys(LinterRuleMap)) - r.NoError(err) - - checks, err := linter.Run([]lintcontext.Object{{ - K8sObject: &rbacv1.ClusterRoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test_role_binding", - }, - TypeMeta: metav1.TypeMeta{ - Kind: "ClusterRoleBinding", - APIVersion: "rbac.authorization.k8s.io/v1", - }, - Subjects: []rbacv1.Subject{ - { - Kind: "Group", - Name: "system:authenticated", - }, - }, - RoleRef: rbacv1.RoleRef{ - Kind: "Role", - Name: "testrole", - }, - }, - }}) - - r.NoError(err) - r.Len(checks, 1) - r.Contains(checks[0].Failed.Rules(), "system-authenticated") - }) -} diff --git a/cmd/controller/controllers/kubelinter/types.go b/cmd/controller/controllers/kubelinter/types.go deleted file mode 100644 index 54bf2dfb..00000000 --- a/cmd/controller/controllers/kubelinter/types.go +++ /dev/null @@ -1,219 +0,0 @@ -package kubelinter - -import "fmt" - -type LinterRule int -type LinterRuleSet LinterRule - -const ( - DanglingService LinterRule = 1 << iota - DeprecatedServiceAccountField - DockerSock - DropNetRawCapability - EnvVarSecret - ExposedService - HostIPC - HostNetwork - HostPID - InvalidTargetPorta - LatestTag - MismatchingSelector - NoAntiAffinity - NoLivenessProbe - NoReadOnlyRootFS - NoReadinessProbe - NoRollingUpdateStrategy - PrivilegeEsxalationContainer - PrivilegedContainer - PrivilegedProts - RunAsNonRoot - SensitiveHostMounts - SSHPort - UnsafeProcMount - UnsafeSysctls - UnsetMempryRequirements - UseNamespace - WritableHostMount - ClusterAdminRoleBinding - AccessToSecrets - DefaultServiceAccount - WildcardInRules - AccessToCreatePods - TokenAutomount - ReadSecretFromEnvVar - HasSecurityContext - DanglingNetworkPolicy - DanglingHPA - DanglingIngress - NetworkPolicyPerNamespace - ContainerdSock - AdditionalCapabilities - SystemMasters - SystemAnonymous - SystemAuthenticated - SystemUnauthenticated - PrivescVerbs -) - -var LinterRuleMap = map[string]LinterRule{ - "dangling-service": DanglingService, - "deprecated-service-account-field": DeprecatedServiceAccountField, - "docker-sock": DockerSock, - "drop-net-raw-capability": DropNetRawCapability, - "env-var-secret": EnvVarSecret, - "exposed-services": ExposedService, - "host-ipc": HostIPC, - "host-network": HostNetwork, - "host-pid": HostPID, - "invalid-target-ports": InvalidTargetPorta, - "latest-tag": LatestTag, - "mismatching-selector": MismatchingSelector, - "no-anti-affinity": NoAntiAffinity, - "no-liveness-probe": NoLivenessProbe, - "no-read-only-root-fs": NoReadOnlyRootFS, - "no-readiness-probe": NoReadinessProbe, - "no-rolling-update-strategy": NoRollingUpdateStrategy, - "privilege-escalation-container": PrivilegeEsxalationContainer, - "privileged-container": PrivilegedContainer, - "privileged-ports": PrivilegedProts, - "run-as-non-root": RunAsNonRoot, - "sensitive-host-mounts": SensitiveHostMounts, - "ssh-port": SSHPort, - "unsafe-proc-mount": UnsafeProcMount, - "unsafe-sysctls": UnsafeSysctls, - "unset-memory-requirements": UnsetMempryRequirements, - "use-namespace": UseNamespace, - "writable-host-mount": WritableHostMount, - "cluster-admin-role-binding": ClusterAdminRoleBinding, - "access-to-secrets": AccessToSecrets, - "wildcard-in-rules": WildcardInRules, - "access-to-create-pods": AccessToCreatePods, - "default-service-account": DefaultServiceAccount, - "sa-token-automount": TokenAutomount, - "read-secret-from-env-var": ReadSecretFromEnvVar, - "has-security-context": HasSecurityContext, - "dangling-networkpolicy": DanglingNetworkPolicy, - "dangling-horizontalpodautoscaler": DanglingHPA, - "dangling-ingress": DanglingIngress, - "network-policy-per-namespace": NetworkPolicyPerNamespace, - "containerd-sock": ContainerdSock, - "additional-capabilities": AdditionalCapabilities, - "system-masters": SystemMasters, - "system-anonymous": SystemAnonymous, - "system-authenticated": SystemAuthenticated, - "system-unauthenticated": SystemUnauthenticated, - "privesc-verbs": PrivescVerbs, -} - -var HostIsolationBundle = map[string]LinterRule{ - "drop-net-raw-capability": DropNetRawCapability, - "host-ipc": HostIPC, - "host-network": HostNetwork, - "host-pid": HostPID, - "privilege-escalation-container": PrivilegeEsxalationContainer, - "privileged-container": PrivilegedContainer, - "run-as-non-root": RunAsNonRoot, - "unsafe-sysctls": UnsafeSysctls, - "additional-capabilities": AdditionalCapabilities, - "no-read-only-root-fs": NoReadOnlyRootFS, - "privileged-ports": PrivilegedProts, -} - -var GoodPracticesBundle = map[string]LinterRule{ - "sa-token-automount": TokenAutomount, - "exposed-services": ExposedService, - "deprecated-service-account-field": DeprecatedServiceAccountField, - "latest-tag": LatestTag, - "mismatching-selector": MismatchingSelector, - "no-anti-affinity": NoAntiAffinity, - "no-liveness-probe": NoLivenessProbe, - "no-readiness-probe": NoReadinessProbe, - "no-rolling-update-strategy": NoRollingUpdateStrategy, - "unset-memory-requirements": UnsetMempryRequirements, - "use-namespace": UseNamespace, - "default-service-account": DefaultServiceAccount, - "has-security-context": HasSecurityContext, - "read-secret-from-env-var": ReadSecretFromEnvVar, - "env-var-secret": EnvVarSecret, - "network-policy-per-namespace": NetworkPolicyPerNamespace, -} - -var PortsBundle = map[string]LinterRule{ - "invalid-target-ports": InvalidTargetPorta, - "ssh-port": SSHPort, -} - -var MountPointsBundle = map[string]LinterRule{ - "docker-sock": DockerSock, - "containerd-sock": ContainerdSock, - "writable-host-mount": WritableHostMount, - "unsafe-proc-mount": UnsafeProcMount, - "sensitive-host-mounts": SensitiveHostMounts, -} - -var DanglingResourcesBundle = map[string]LinterRule{ - "dangling-service": DanglingService, - "dangling-networkpolicy": DanglingNetworkPolicy, - "dangling-horizontalpodautoscaler": DanglingHPA, - "dangling-ingress": DanglingIngress, -} - -var RBACBundle = map[string]LinterRule{ - "cluster-admin-role-binding": ClusterAdminRoleBinding, - "access-to-secrets": AccessToSecrets, - "wildcard-in-rules": WildcardInRules, - "access-to-create-pods": AccessToCreatePods, -} - -type LinterCheck struct { - ResourceID string `json:"resourceID"` - Passed *LinterRuleSet `json:"passed"` - Failed *LinterRuleSet `json:"failed"` -} - -func (s *LinterRuleSet) Add(i LinterRule) { - v := LinterRule(*s) - v |= i - - *s = LinterRuleSet(v) -} - -func (s *LinterRuleSet) Has(i LinterRule) bool { - return LinterRule(*s)&i != 0 -} - -func (s *LinterRuleSet) Rules() []string { - result := make([]string, 0) - for name, mask := range LinterRuleMap { - if LinterRule(*s)&mask != 0 { - result = append(result, name) - } - } - - return result -} - -type Resource struct { - ObjectMeta ObjectMeta - ObjectType ObjectType -} - -type ObjectMeta struct { - Namespace string `json:"namespace"` - Name string `json:"name"` -} - -type ObjectType struct { - APIVersion string `json:"APIVersion"` - Kind string `json:"kind"` -} - -func (r Resource) ObjectKey() string { - return fmt.Sprintf( - "%s/%s/%s/%s", - r.ObjectType.APIVersion, - r.ObjectType.Kind, - r.ObjectMeta.Namespace, - r.ObjectMeta.Name, - ) -} diff --git a/cmd/controller/controllers/kubelinter/types_test.go b/cmd/controller/controllers/kubelinter/types_test.go deleted file mode 100644 index 7b5c4954..00000000 --- a/cmd/controller/controllers/kubelinter/types_test.go +++ /dev/null @@ -1,22 +0,0 @@ -package kubelinter - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func TestLinterRuleSet(t *testing.T) { - r := require.New(t) - - set := new(LinterRuleSet) - r.False(set.Has(RunAsNonRoot)) - set.Add(RunAsNonRoot) - r.True(set.Has(RunAsNonRoot)) - set.Add(WritableHostMount) - set.Add(LatestTag) - r.Len(set.Rules(), 3) - r.Contains(set.Rules(), "latest-tag") - r.Contains(set.Rules(), "writable-host-mount") - r.Contains(set.Rules(), "run-as-non-root") -} diff --git a/cmd/controller/main.go b/cmd/controller/main.go index 48a16bdd..99aeff00 100644 --- a/cmd/controller/main.go +++ b/cmd/controller/main.go @@ -13,7 +13,6 @@ import ( "github.com/castai/kvisor/cmd/controller/config" "github.com/castai/kvisor/cmd/controller/controllers/imagescan" "github.com/castai/kvisor/cmd/controller/controllers/kubebench" - "github.com/castai/kvisor/cmd/controller/controllers/kubelinter" "github.com/castai/kvisor/pkg/castai" "github.com/spf13/pflag" "k8s.io/client-go/kubernetes" @@ -74,9 +73,10 @@ var ( // deprecated: use cloudProvider kubeBenchCloudProvider = pflag.String("kube-bench-cloud-provider", "", "Kube bench cloud provider. Deprecated: use `cloud-provider` instead.") - kubeLinterEnabled = pflag.Bool("kube-linter-enabled", false, "Kube linter enabled") - kubeLinterScanInterval = pflag.Duration("kube-linter-scan-interval", 60*time.Second, "Kube linter scan interval") - kubeLinterInitDelay = pflag.Duration("kube-linter-init-delay", 60*time.Second, "Kube linter init delay") + // Kubelinter flags are no longer used. Keeping here for now in case some of these flags are still in helm. + _ = pflag.Bool("kube-linter-enabled", false, "Kube linter enabled") + _ = pflag.Duration("kube-linter-scan-interval", 60*time.Second, "Kube linter scan interval") + _ = pflag.Duration("kube-linter-init-delay", 60*time.Second, "Kube linter init delay") jobsCleanupInterval = pflag.Duration("jobs-cleanup", 10*time.Minute, "Jobs cleanup interval") jobsCleanupJobAge = pflag.Duration("jobs-cleanup-job-age", 10*time.Minute, "Jobs cleanup job age") @@ -167,11 +167,6 @@ func main() { IgnoredNamespaces: *imageScanIgnoredNamespaces, DisabledAnalyzers: *imageScanDisabledAnalyzers, }, - Linter: kubelinter.Config{ - Enabled: *kubeLinterEnabled, - ScanInterval: *kubeLinterScanInterval, - InitDelay: *kubeLinterInitDelay, - }, KubeBench: kubebench.Config{ Enabled: *kubeBenchEnabled, Force: *kubeBenchForceScan, diff --git a/go.mod b/go.mod index 6d6e542a..95998f55 100644 --- a/go.mod +++ b/go.mod @@ -50,7 +50,6 @@ require ( golang.org/x/sync v0.15.0 golang.org/x/sys v0.35.0 golang.org/x/time v0.11.0 - golang.stackrox.io/kube-linter v0.7.3-0.20250507172404-3f4b9037f56f google.golang.org/grpc v1.71.1 google.golang.org/protobuf v1.36.6 gopkg.in/yaml.v3 v3.0.1 @@ -133,7 +132,6 @@ require ( github.com/envoyproxy/protoc-gen-validate v1.2.1 // indirect github.com/evanphx/json-patch/v5 v5.9.11 // indirect github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect - github.com/expr-lang/expr v1.17.2 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/go-faster/city v1.0.1 // indirect github.com/go-faster/errors v0.7.1 // indirect @@ -151,19 +149,21 @@ require ( github.com/go-openapi/spec v0.21.0 // indirect github.com/go-openapi/strfmt v0.23.0 // indirect github.com/go-openapi/validate v0.24.0 // indirect + github.com/go-sql-driver/mysql v1.9.1 // indirect github.com/go-viper/mapstructure/v2 v2.3.0 // indirect + github.com/gofrs/uuid v4.4.0+incompatible // indirect github.com/golang-jwt/jwt/v5 v5.2.2 // indirect github.com/google/go-github/v62 v62.0.0 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/gopacket/gopacket v1.3.1 // indirect github.com/gosuri/uitable v0.0.4 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect + github.com/hashicorp/golang-lru v1.0.2 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/hashicorp/hcl/v2 v2.23.0 // indirect github.com/in-toto/in-toto-golang v0.9.0 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/jmoiron/sqlx v1.4.0 // indirect - github.com/kedacore/keda/v2 v2.17.1 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect github.com/klauspost/cpuid/v2 v2.2.3 // indirect github.com/knqyf263/go-rpm-version v0.0.0-20220614171824-631e686d1075 // indirect @@ -185,6 +185,8 @@ require ( github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect github.com/oklog/ulid v1.3.1 // indirect github.com/oklog/ulid/v2 v2.1.0 // indirect + github.com/onsi/ginkgo/v2 v2.23.4 // indirect + github.com/onsi/gomega v1.37.0 // indirect github.com/open-policy-agent/opa v1.4.0 // indirect github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect github.com/owenrumney/squealer v1.2.11 // indirect @@ -196,7 +198,6 @@ require ( github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect - github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.79.2 // indirect github.com/rubenv/sql-migrate v1.7.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/rust-secure-code/go-rustaudit v0.0.0-20250226111315-e20ec32e963c // indirect @@ -235,14 +236,12 @@ require ( go.uber.org/dig v1.17.1 // indirect go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect golang.org/x/tools v0.33.0 // indirect - gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect k8s.io/apiserver v0.32.2 // indirect k8s.io/component-base v0.32.3 // indirect k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kubectl v0.32.3 // indirect - knative.dev/pkg v0.0.0-20250326102644-9f3e60a9244c // indirect mvdan.cc/sh/v3 v3.11.0 // indirect sigs.k8s.io/controller-runtime v0.19.7 // indirect sigs.k8s.io/gateway-api v1.2.1 // indirect @@ -376,7 +375,6 @@ require ( github.com/opencontainers/image-spec v1.1.1 github.com/opencontainers/runtime-spec v1.2.0 // indirect github.com/opencontainers/selinux v1.11.1 // indirect - github.com/openshift/api v3.9.0+incompatible // indirect github.com/pelletier/go-toml/v2 v2.2.3 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect github.com/pkg/errors v0.9.1 // indirect diff --git a/go.sum b/go.sum index 972ba91b..a2755ade 100644 --- a/go.sum +++ b/go.sum @@ -1029,8 +1029,6 @@ github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjT github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM= github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4= github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSYXu++VVOHnXeitef/D8n/6y4QV8uLHSFXX4NeXMGc= -github.com/expr-lang/expr v1.17.2 h1:o0A99O/Px+/DTjEnQiodAgOIK9PPxL8DtXhBRKC+Iso= -github.com/expr-lang/expr v1.17.2/go.mod h1:8/vRC7+7HBzESEqt5kKpYXxrxkr31SaO8r40VO/1IT4= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= @@ -1416,8 +1414,6 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= -github.com/kedacore/keda/v2 v2.17.1 h1:UomWibe5aO7COMUyF+jVM9fuENf4/wcSpiui65tF+d0= -github.com/kedacore/keda/v2 v2.17.1/go.mod h1:yKJMF8zuLI2xXvZtgfcbW+V8k3VO4a4R/fucy3z5lC8= github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= @@ -1622,8 +1618,6 @@ github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/selinux v1.11.1 h1:nHFvthhM0qY8/m+vfhJylliSshm8G1jJ2jDMcgULaH8= github.com/opencontainers/selinux v1.11.1/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= -github.com/openshift/api v3.9.0+incompatible h1:fJ/KsefYuZAjmrr3+5U9yZIZbTOpVkDDLDLFresAeYs= -github.com/openshift/api v3.9.0+incompatible/go.mod h1:dh9o4Fs58gpFXGSYfnVxGR9PnV53I8TW84pQaJDdGiY= github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A= github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU= github.com/openvex/discovery v0.1.1-0.20240802171711-7c54efc57553 h1:c4u0GIH0w2Q57Pm2Oldrq6EiHFnLCCnRs98A+ggj/YQ= @@ -1676,8 +1670,6 @@ github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/poy/onpar v1.1.2 h1:QaNrNiZx0+Nar5dLgTVp5mXkyoVFIbepjyEoGSnhbAY= github.com/poy/onpar v1.1.2/go.mod h1:6X8FLNoxyr9kkmnlqpK6LSoiOtrO6MICtWwEuWkLjzg= -github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.79.2 h1:DGv150w4UyxnjNHlkCw85R3+lspOxegtdnbpP2vKRrk= -github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.79.2/go.mod h1:AVMP4QEW8xuGWnxaWSpI3kKjP9fDA31nO68zsyREJZA= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= @@ -2436,10 +2428,6 @@ golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNq golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da h1:noIWHXmPHxILtqtCOPIhSt0ABwskkZKjD3bXGnZGpNY= golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= -golang.stackrox.io/kube-linter v0.7.3-0.20250507172404-3f4b9037f56f h1:YqtfKlF8ohFIKSE8vbNhM2w42X9GZiYFaPixvtOZumM= -golang.stackrox.io/kube-linter v0.7.3-0.20250507172404-3f4b9037f56f/go.mod h1:Yq9KHlQ7slOFfF2lkxSOUsNevt0iG8luDoT5x+sJCc4= -gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= -gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= gonum.org/v1/gonum v0.9.3/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0= @@ -2784,8 +2772,6 @@ k8s.io/kubectl v0.32.3 h1:VMi584rbboso+yjfv0d8uBHwwxbC438LKq+dXd5tOAI= k8s.io/kubectl v0.32.3/go.mod h1:6Euv2aso5GKzo/UVMacV6C7miuyevpfI91SvBvV9Zdg= k8s.io/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJJI8IUa1AmH/qa0= k8s.io/utils v0.0.0-20241210054802-24370beab758/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -knative.dev/pkg v0.0.0-20250326102644-9f3e60a9244c h1:6IZwH1QHGfWlmfdy7svgDCPhRqWpisWK/Gcp8wdAwE0= -knative.dev/pkg v0.0.0-20250326102644-9f3e60a9244c/go.mod h1:gx7Pp9NPcKYApNhR8m0KSOeg71pqhwPWhuhUJ6xCa2g= lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= From ec221e29f590094d0ee7b55ff87bdcef083db24c Mon Sep 17 00:00:00 2001 From: anjmao Date: Tue, 21 Oct 2025 09:51:05 +0300 Subject: [PATCH 2/2] Fix e2e --- e2e/e2e.go | 34 ---------------------------------- 1 file changed, 34 deletions(-) diff --git a/e2e/e2e.go b/e2e/e2e.go index 5fe6a10d..c14c7a16 100644 --- a/e2e/e2e.go +++ b/e2e/e2e.go @@ -161,12 +161,6 @@ func run(ctx context.Context) error { return fmt.Errorf("assert kube bench: %w", err) } - fmt.Println("🙏waiting for kube linter") - if err := srv.assertKubeLinter(ctx); err != nil { - return fmt.Errorf("assert kube linter: %w", err) - } - srv.kubeLinterReports = nil - fmt.Println("🙏waiting for image metadata") if err := srv.assertImageMetadata(ctx); err != nil { return fmt.Errorf("assert image metadata: %w", err) @@ -230,9 +224,6 @@ func installChart(ns, imageTag string) ([]byte, error) { --set controller.extraArgs.kube-bench-enabled=true \ --set controller.extraArgs.kube-bench-scan-interval=5s \ --set controller.extraArgs.kube-bench-cloud-provider=gke \ - --set controller.extraArgs.kube-linter-enabled=true \ - --set controller.extraArgs.kube-linter-scan-interval=5s \ - --set controller.extraArgs.kube-linter-init-delay=5s \ --set castai.grpcAddr=%s \ --set castai.apiKey=%s \ --set castai.clusterID=%s \ @@ -264,7 +255,6 @@ type testCASTAIServer struct { logs []*castaipb.LogEvent imageMetadatas []*castaipb.ImageMetadata kubeBenchReports []*castaipb.KubeBenchReport - kubeLinterReports []*castaipb.KubeLinterReport processTreeEvents []*castaipb.ProcessTreeEvent controllerConfig []byte agentConfig []byte @@ -408,7 +398,6 @@ func (t *testCASTAIServer) KubeBenchReportIngest(ctx context.Context, report *ca } func (t *testCASTAIServer) KubeLinterReportIngest(ctx context.Context, report *castaipb.KubeLinterReport) (*castaipb.KubeLinterReportIngestResponse, error) { - t.kubeLinterReports = append(t.kubeLinterReports, report) return &castaipb.KubeLinterReportIngestResponse{}, nil } @@ -1225,29 +1214,6 @@ func (t *testCASTAIServer) assertKubeBenchReport(ctx context.Context) error { } } -func (t *testCASTAIServer) assertKubeLinter(ctx context.Context) error { - timeout := time.After(10 * time.Second) - for { - select { - case <-ctx.Done(): - return ctx.Err() - case <-timeout: - return errors.New("timeout waiting kube linter") - case <-time.After(1 * time.Second): - t.mu.Lock() - items := t.kubeLinterReports - t.mu.Unlock() - if len(items) > 0 { - l1 := items[0] - if len(l1.Checks) == 0 { - return errors.New("missing linter checks") - } - return nil - } - } - } -} - func (t *testCASTAIServer) assertNetflows(ctx context.Context, workload string, family uint16) error { timeout := time.After(30 * time.Second) r := newAssertions()