k8s.io/kubernetes@v1.29.3/pkg/securitycontext/util.go (about) 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 }