...

Source file src/k8s.io/kubernetes/pkg/securitycontext/util.go

Documentation: k8s.io/kubernetes/pkg/securitycontext

     1  /*
     2  Copyright 2014 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 securitycontext
    18  
    19  import (
    20  	v1 "k8s.io/api/core/v1"
    21  )
    22  
    23  // HasWindowsHostProcessRequest returns true if container should run as HostProcess container,
    24  // taking into account nils
    25  func HasWindowsHostProcessRequest(pod *v1.Pod, container *v1.Container) bool {
    26  	effectiveSc := DetermineEffectiveSecurityContext(pod, container)
    27  
    28  	if effectiveSc.WindowsOptions == nil {
    29  		return false
    30  	}
    31  	if effectiveSc.WindowsOptions.HostProcess == nil {
    32  		return false
    33  	}
    34  	return *effectiveSc.WindowsOptions.HostProcess
    35  }
    36  
    37  // DetermineEffectiveSecurityContext returns a synthesized SecurityContext for reading effective configurations
    38  // from the provided pod's and container's security context. Container's fields take precedence in cases where both
    39  // are set
    40  func DetermineEffectiveSecurityContext(pod *v1.Pod, container *v1.Container) *v1.SecurityContext {
    41  	effectiveSc := securityContextFromPodSecurityContext(pod)
    42  	containerSc := container.SecurityContext
    43  
    44  	if effectiveSc == nil && containerSc == nil {
    45  		return &v1.SecurityContext{}
    46  	}
    47  	if effectiveSc != nil && containerSc == nil {
    48  		return effectiveSc
    49  	}
    50  	if effectiveSc == nil && containerSc != nil {
    51  		return containerSc
    52  	}
    53  
    54  	if containerSc.SELinuxOptions != nil {
    55  		effectiveSc.SELinuxOptions = new(v1.SELinuxOptions)
    56  		*effectiveSc.SELinuxOptions = *containerSc.SELinuxOptions
    57  	}
    58  
    59  	if containerSc.WindowsOptions != nil {
    60  		// only override fields that are set at the container level, not the whole thing
    61  		if effectiveSc.WindowsOptions == nil {
    62  			effectiveSc.WindowsOptions = &v1.WindowsSecurityContextOptions{}
    63  		}
    64  		if containerSc.WindowsOptions.GMSACredentialSpecName != nil || containerSc.WindowsOptions.GMSACredentialSpec != nil {
    65  			// both GMSA fields go hand in hand
    66  			effectiveSc.WindowsOptions.GMSACredentialSpecName = containerSc.WindowsOptions.GMSACredentialSpecName
    67  			effectiveSc.WindowsOptions.GMSACredentialSpec = containerSc.WindowsOptions.GMSACredentialSpec
    68  		}
    69  		if containerSc.WindowsOptions.RunAsUserName != nil {
    70  			effectiveSc.WindowsOptions.RunAsUserName = containerSc.WindowsOptions.RunAsUserName
    71  		}
    72  		if containerSc.WindowsOptions.HostProcess != nil {
    73  			effectiveSc.WindowsOptions.HostProcess = containerSc.WindowsOptions.HostProcess
    74  		}
    75  	}
    76  
    77  	if containerSc.Capabilities != nil {
    78  		effectiveSc.Capabilities = new(v1.Capabilities)
    79  		*effectiveSc.Capabilities = *containerSc.Capabilities
    80  	}
    81  
    82  	if containerSc.Privileged != nil {
    83  		effectiveSc.Privileged = new(bool)
    84  		*effectiveSc.Privileged = *containerSc.Privileged
    85  	}
    86  
    87  	if containerSc.RunAsUser != nil {
    88  		effectiveSc.RunAsUser = new(int64)
    89  		*effectiveSc.RunAsUser = *containerSc.RunAsUser
    90  	}
    91  
    92  	if containerSc.RunAsGroup != nil {
    93  		effectiveSc.RunAsGroup = new(int64)
    94  		*effectiveSc.RunAsGroup = *containerSc.RunAsGroup
    95  	}
    96  
    97  	if containerSc.RunAsNonRoot != nil {
    98  		effectiveSc.RunAsNonRoot = new(bool)
    99  		*effectiveSc.RunAsNonRoot = *containerSc.RunAsNonRoot
   100  	}
   101  
   102  	if containerSc.ReadOnlyRootFilesystem != nil {
   103  		effectiveSc.ReadOnlyRootFilesystem = new(bool)
   104  		*effectiveSc.ReadOnlyRootFilesystem = *containerSc.ReadOnlyRootFilesystem
   105  	}
   106  
   107  	if containerSc.AllowPrivilegeEscalation != nil {
   108  		effectiveSc.AllowPrivilegeEscalation = new(bool)
   109  		*effectiveSc.AllowPrivilegeEscalation = *containerSc.AllowPrivilegeEscalation
   110  	}
   111  
   112  	if containerSc.ProcMount != nil {
   113  		effectiveSc.ProcMount = new(v1.ProcMountType)
   114  		*effectiveSc.ProcMount = *containerSc.ProcMount
   115  	}
   116  
   117  	return effectiveSc
   118  }
   119  
   120  // DetermineEffectiveRunAsUser returns a pointer of UID from the provided pod's
   121  // and container's security context and a bool value to indicate if it is absent.
   122  // Container's runAsUser take precedence in cases where both are set.
   123  func DetermineEffectiveRunAsUser(pod *v1.Pod, container *v1.Container) (*int64, bool) {
   124  	var runAsUser *int64
   125  	if pod.Spec.SecurityContext != nil && pod.Spec.SecurityContext.RunAsUser != nil {
   126  		runAsUser = new(int64)
   127  		*runAsUser = *pod.Spec.SecurityContext.RunAsUser
   128  	}
   129  	if container.SecurityContext != nil && container.SecurityContext.RunAsUser != nil {
   130  		runAsUser = new(int64)
   131  		*runAsUser = *container.SecurityContext.RunAsUser
   132  	}
   133  	if runAsUser == nil {
   134  		return nil, false
   135  	}
   136  	return runAsUser, true
   137  }
   138  
   139  func securityContextFromPodSecurityContext(pod *v1.Pod) *v1.SecurityContext {
   140  	if pod.Spec.SecurityContext == nil {
   141  		return nil
   142  	}
   143  
   144  	synthesized := &v1.SecurityContext{}
   145  
   146  	if pod.Spec.SecurityContext.SELinuxOptions != nil {
   147  		synthesized.SELinuxOptions = &v1.SELinuxOptions{}
   148  		*synthesized.SELinuxOptions = *pod.Spec.SecurityContext.SELinuxOptions
   149  	}
   150  
   151  	if pod.Spec.SecurityContext.WindowsOptions != nil {
   152  		synthesized.WindowsOptions = &v1.WindowsSecurityContextOptions{}
   153  		*synthesized.WindowsOptions = *pod.Spec.SecurityContext.WindowsOptions
   154  	}
   155  
   156  	if pod.Spec.SecurityContext.RunAsUser != nil {
   157  		synthesized.RunAsUser = new(int64)
   158  		*synthesized.RunAsUser = *pod.Spec.SecurityContext.RunAsUser
   159  	}
   160  
   161  	if pod.Spec.SecurityContext.RunAsGroup != nil {
   162  		synthesized.RunAsGroup = new(int64)
   163  		*synthesized.RunAsGroup = *pod.Spec.SecurityContext.RunAsGroup
   164  	}
   165  
   166  	if pod.Spec.SecurityContext.RunAsNonRoot != nil {
   167  		synthesized.RunAsNonRoot = new(bool)
   168  		*synthesized.RunAsNonRoot = *pod.Spec.SecurityContext.RunAsNonRoot
   169  	}
   170  
   171  	return synthesized
   172  }
   173  
   174  // AddNoNewPrivileges returns if we should add the no_new_privs option.
   175  func AddNoNewPrivileges(sc *v1.SecurityContext) bool {
   176  	if sc == nil {
   177  		return false
   178  	}
   179  
   180  	// handle the case where the user did not set the default and did not explicitly set allowPrivilegeEscalation
   181  	if sc.AllowPrivilegeEscalation == nil {
   182  		return false
   183  	}
   184  
   185  	// handle the case where defaultAllowPrivilegeEscalation is false or the user explicitly set allowPrivilegeEscalation to true/false
   186  	return !*sc.AllowPrivilegeEscalation
   187  }
   188  
   189  var (
   190  	// These *must* be kept in sync with moby/moby.
   191  	// https://github.com/moby/moby/blob/master/oci/defaults.go#L105-L123
   192  	// @jessfraz will watch changes to those files upstream.
   193  	defaultMaskedPaths = []string{
   194  		"/proc/asound",
   195  		"/proc/acpi",
   196  		"/proc/kcore",
   197  		"/proc/keys",
   198  		"/proc/latency_stats",
   199  		"/proc/timer_list",
   200  		"/proc/timer_stats",
   201  		"/proc/sched_debug",
   202  		"/proc/scsi",
   203  		"/sys/firmware",
   204  	}
   205  	defaultReadonlyPaths = []string{
   206  		"/proc/bus",
   207  		"/proc/fs",
   208  		"/proc/irq",
   209  		"/proc/sys",
   210  		"/proc/sysrq-trigger",
   211  	}
   212  )
   213  
   214  // ConvertToRuntimeMaskedPaths converts the ProcMountType to the specified or default
   215  // masked paths.
   216  func ConvertToRuntimeMaskedPaths(opt *v1.ProcMountType) []string {
   217  	if opt != nil && *opt == v1.UnmaskedProcMount {
   218  		// Unmasked proc mount should have no paths set as masked.
   219  		return []string{}
   220  	}
   221  
   222  	// Otherwise, add the default masked paths to the runtime security context.
   223  	return defaultMaskedPaths
   224  }
   225  
   226  // ConvertToRuntimeReadonlyPaths converts the ProcMountType to the specified or default
   227  // readonly paths.
   228  func ConvertToRuntimeReadonlyPaths(opt *v1.ProcMountType) []string {
   229  	if opt != nil && *opt == v1.UnmaskedProcMount {
   230  		// Unmasked proc mount should have no paths set as readonly.
   231  		return []string{}
   232  	}
   233  
   234  	// Otherwise, add the default readonly paths to the runtime security context.
   235  	return defaultReadonlyPaths
   236  }
   237  

View as plain text