...

Source file src/k8s.io/kubernetes/pkg/security/apparmor/helpers.go

Documentation: k8s.io/kubernetes/pkg/security/apparmor

     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  	"strings"
    21  
    22  	v1 "k8s.io/api/core/v1"
    23  	utilfeature "k8s.io/apiserver/pkg/util/feature"
    24  	podutil "k8s.io/kubernetes/pkg/api/v1/pod"
    25  	"k8s.io/kubernetes/pkg/features"
    26  )
    27  
    28  // Checks whether app armor is required for the pod to run. AppArmor is considered required if any
    29  // non-unconfined profiles are specified.
    30  func isRequired(pod *v1.Pod) bool {
    31  	if pod.Spec.SecurityContext != nil && pod.Spec.SecurityContext.AppArmorProfile != nil &&
    32  		pod.Spec.SecurityContext.AppArmorProfile.Type != v1.AppArmorProfileTypeUnconfined {
    33  		return true
    34  	}
    35  
    36  	inUse := !podutil.VisitContainers(&pod.Spec, podutil.AllContainers, func(c *v1.Container, _ podutil.ContainerType) bool {
    37  		if c.SecurityContext != nil && c.SecurityContext.AppArmorProfile != nil &&
    38  			c.SecurityContext.AppArmorProfile.Type != v1.AppArmorProfileTypeUnconfined {
    39  			return false // is in use; short-circuit
    40  		}
    41  		return true
    42  	})
    43  	if inUse {
    44  		return true
    45  	}
    46  
    47  	for key, value := range pod.Annotations {
    48  		if strings.HasPrefix(key, v1.DeprecatedAppArmorBetaContainerAnnotationKeyPrefix) {
    49  			return value != v1.DeprecatedAppArmorBetaProfileNameUnconfined
    50  		}
    51  	}
    52  	return false
    53  }
    54  
    55  // GetProfileName returns the name of the profile to use with the container.
    56  func GetProfile(pod *v1.Pod, container *v1.Container) *v1.AppArmorProfile {
    57  	if !utilfeature.DefaultFeatureGate.Enabled(features.AppArmorFields) {
    58  		return getProfileFromPodAnnotations(pod.Annotations, container.Name)
    59  	}
    60  
    61  	if container.SecurityContext != nil && container.SecurityContext.AppArmorProfile != nil {
    62  		return container.SecurityContext.AppArmorProfile
    63  	}
    64  
    65  	// Static pods may not have had annotations synced to fields, so fallback to annotations before
    66  	// the pod profile.
    67  	if profile := getProfileFromPodAnnotations(pod.Annotations, container.Name); profile != nil {
    68  		return profile
    69  	}
    70  
    71  	if pod.Spec.SecurityContext != nil && pod.Spec.SecurityContext.AppArmorProfile != nil {
    72  		return pod.Spec.SecurityContext.AppArmorProfile
    73  	}
    74  
    75  	return nil
    76  }
    77  
    78  // getProfileFromPodAnnotations gets the AppArmor profile to use with container from
    79  // (deprecated) pod annotations.
    80  func getProfileFromPodAnnotations(annotations map[string]string, containerName string) *v1.AppArmorProfile {
    81  	val, ok := annotations[v1.DeprecatedAppArmorBetaContainerAnnotationKeyPrefix+containerName]
    82  	if !ok {
    83  		return nil
    84  	}
    85  
    86  	switch {
    87  	case val == v1.DeprecatedAppArmorBetaProfileRuntimeDefault:
    88  		return &v1.AppArmorProfile{Type: v1.AppArmorProfileTypeRuntimeDefault}
    89  
    90  	case val == v1.DeprecatedAppArmorBetaProfileNameUnconfined:
    91  		return &v1.AppArmorProfile{Type: v1.AppArmorProfileTypeUnconfined}
    92  
    93  	case strings.HasPrefix(val, v1.DeprecatedAppArmorBetaProfileNamePrefix):
    94  		// Note: an invalid empty localhost profile will be rejected by kubelet admission.
    95  		profileName := strings.TrimPrefix(val, v1.DeprecatedAppArmorBetaProfileNamePrefix)
    96  		return &v1.AppArmorProfile{
    97  			Type:             v1.AppArmorProfileTypeLocalhost,
    98  			LocalhostProfile: &profileName,
    99  		}
   100  
   101  	default:
   102  		// Invalid annotation.
   103  		return nil
   104  	}
   105  }
   106  

View as plain text