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  }