github.com/castai/kvisor@v1.7.1-0.20240516114728-b3572a2607b5/cmd/controller/state/kubelinter/customchecks/securitycontext/securitycontext.go (about) 1 package securitycontext 2 3 import ( 4 "fmt" 5 "strings" 6 7 "golang.stackrox.io/kube-linter/pkg/check" 8 "golang.stackrox.io/kube-linter/pkg/config" 9 "golang.stackrox.io/kube-linter/pkg/diagnostic" 10 "golang.stackrox.io/kube-linter/pkg/extract" 11 "golang.stackrox.io/kube-linter/pkg/lintcontext" 12 "golang.stackrox.io/kube-linter/pkg/objectkinds" 13 "golang.stackrox.io/kube-linter/pkg/templates" 14 "golang.stackrox.io/kube-linter/pkg/templates/util" 15 corev1 "k8s.io/api/core/v1" 16 ) 17 18 func Check() *config.Check { 19 return &config.Check{ 20 Name: "has-security-context", 21 Description: "Resource has security context", 22 Template: "has-security-context", 23 Params: map[string]interface{}{}, 24 } 25 } 26 27 func init() { 28 templates.Register(check.Template{ 29 HumanName: "Resource has security context", 30 Key: "has-security-context", 31 SupportedObjectKinds: config.ObjectKindsDesc{ 32 ObjectKinds: []string{objectkinds.DeploymentLike}, 33 }, 34 Parameters: ParamDescs, 35 ParseAndValidateParams: ParseAndValidate, 36 Instantiate: WrapInstantiateFunc(func(_ Params) (check.Func, error) { 37 return func(_ lintcontext.LintContext, object lintcontext.Object) []diagnostic.Diagnostic { 38 podSpec, found := extract.PodSpec(object.K8sObject) 39 if !found { 40 return nil 41 } 42 if isSecurityContextSet(podSpec.SecurityContext) { 43 return nil 44 } 45 return []diagnostic.Diagnostic{{Message: "Resource does not have security context attached"}} 46 }, nil 47 }), 48 }) 49 } 50 51 func isSecurityContextSet(ctx *corev1.PodSecurityContext) bool { 52 if ctx == nil { 53 return false 54 } 55 return ctx.SELinuxOptions != nil || ctx.WindowsOptions != nil || 56 ctx.RunAsUser != nil || ctx.RunAsGroup != nil || 57 ctx.RunAsNonRoot != nil || ctx.SupplementalGroups != nil || 58 ctx.FSGroup != nil || ctx.Sysctls != nil || 59 ctx.FSGroupChangePolicy != nil || ctx.SeccompProfile != nil 60 } 61 62 type Params struct { 63 } 64 65 var ( 66 // Use some imports in case they don't get used otherwise. 67 _ = util.MustParseParameterDesc 68 _ = fmt.Sprintf 69 70 ParamDescs = []check.ParameterDesc{} 71 ) 72 73 func (p *Params) Validate() error { 74 var validationErrors []string 75 if len(validationErrors) > 0 { 76 return fmt.Errorf("invalid parameters: %s", strings.Join(validationErrors, ", ")) 77 } 78 return nil 79 } 80 81 // ParseAndValidate instantiates a Params object out of the passed map[string]interface{}, 82 // validates it, and returns it. 83 // The return type is interface{} to satisfy the type in the Template struct. 84 func ParseAndValidate(m map[string]interface{}) (interface{}, error) { 85 var p Params 86 if err := util.DecodeMapStructure(m, &p); err != nil { 87 return nil, err 88 } 89 if err := p.Validate(); err != nil { 90 return nil, err 91 } 92 return p, nil 93 } 94 95 // WrapInstantiateFunc is a convenience wrapper that wraps an untyped instantiate function 96 // into a typed one. 97 func WrapInstantiateFunc(f func(p Params) (check.Func, error)) func(interface{}) (check.Func, error) { 98 return func(paramsInt interface{}) (check.Func, error) { 99 return f(paramsInt.(Params)) 100 } 101 }