k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/pkg/security/apparmor/validate.go (about)

     1  /*
     2  Copyright 2016 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package apparmor
    18  
    19  import (
    20  	"errors"
    21  	"fmt"
    22  	"strings"
    23  
    24  	"github.com/opencontainers/runc/libcontainer/apparmor"
    25  	v1 "k8s.io/api/core/v1"
    26  	utilfeature "k8s.io/apiserver/pkg/util/feature"
    27  	podutil "k8s.io/kubernetes/pkg/api/v1/pod"
    28  	"k8s.io/kubernetes/pkg/features"
    29  )
    30  
    31  // Whether AppArmor should be disabled by default.
    32  // Set to true if the wrong build tags are set (see validate_disabled.go).
    33  var isDisabledBuild bool
    34  
    35  // Validator is a interface for validating that a pod with an AppArmor profile can be run by a Node.
    36  type Validator interface {
    37  	Validate(pod *v1.Pod) error
    38  	ValidateHost() error
    39  }
    40  
    41  // NewValidator is in order to find AppArmor FS
    42  func NewValidator() Validator {
    43  	if err := validateHost(); err != nil {
    44  		return &validator{validateHostErr: err}
    45  	}
    46  	return &validator{}
    47  }
    48  
    49  type validator struct {
    50  	validateHostErr error
    51  }
    52  
    53  func (v *validator) Validate(pod *v1.Pod) error {
    54  	if !isRequired(pod) {
    55  		return nil
    56  	}
    57  
    58  	if v.ValidateHost() != nil {
    59  		return v.validateHostErr
    60  	}
    61  
    62  	var retErr error
    63  	podutil.VisitContainers(&pod.Spec, podutil.AllContainers, func(container *v1.Container, containerType podutil.ContainerType) bool {
    64  		profile := GetProfile(pod, container)
    65  		if profile == nil {
    66  			return true
    67  		}
    68  
    69  		// TODO(#64841): This would ideally be part of validation.ValidateAppArmorProfileFormat, but
    70  		// that is called for API validation, and this is tightening validation.
    71  		if profile.Type == v1.AppArmorProfileTypeLocalhost {
    72  			if profile.LocalhostProfile == nil || strings.TrimSpace(*profile.LocalhostProfile) == "" {
    73  				retErr = fmt.Errorf("invalid empty AppArmor profile name: %q", profile)
    74  				return false
    75  			}
    76  		}
    77  		return true
    78  	})
    79  
    80  	return retErr
    81  }
    82  
    83  // ValidateHost verifies that the host and runtime is capable of enforcing AppArmor profiles.
    84  // Note, this is intentionally only check the host at kubelet startup and never re-evaluates the host
    85  // as the expectation is that the kubelet restart will be needed to enable or disable AppArmor support.
    86  func (v *validator) ValidateHost() error {
    87  	return v.validateHostErr
    88  }
    89  
    90  // validateHost verifies that the host and runtime is capable of enforcing AppArmor profiles.
    91  func validateHost() error {
    92  	// Check feature-gates
    93  	if !utilfeature.DefaultFeatureGate.Enabled(features.AppArmor) {
    94  		return errors.New("AppArmor disabled by feature-gate")
    95  	}
    96  
    97  	// Check build support.
    98  	if isDisabledBuild {
    99  		return errors.New("binary not compiled for linux")
   100  	}
   101  
   102  	// Check kernel support.
   103  	if !apparmor.IsEnabled() {
   104  		return errors.New("AppArmor is not enabled on the host")
   105  	}
   106  
   107  	return nil
   108  }