util.go 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738
  1. /*
  2. Copyright 2015 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package pod
  14. import (
  15. "strings"
  16. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  17. utilfeature "k8s.io/apiserver/pkg/util/feature"
  18. api "k8s.io/kubernetes/pkg/apis/core"
  19. "k8s.io/kubernetes/pkg/features"
  20. "k8s.io/kubernetes/pkg/security/apparmor"
  21. )
  22. // Visitor is called with each object name, and returns true if visiting should continue
  23. type Visitor func(name string) (shouldContinue bool)
  24. // VisitPodSecretNames invokes the visitor function with the name of every secret
  25. // referenced by the pod spec. If visitor returns false, visiting is short-circuited.
  26. // Transitive references (e.g. pod -> pvc -> pv -> secret) are not visited.
  27. // Returns true if visiting completed, false if visiting was short-circuited.
  28. func VisitPodSecretNames(pod *api.Pod, visitor Visitor) bool {
  29. for _, reference := range pod.Spec.ImagePullSecrets {
  30. if !visitor(reference.Name) {
  31. return false
  32. }
  33. }
  34. for i := range pod.Spec.InitContainers {
  35. if !visitContainerSecretNames(&pod.Spec.InitContainers[i], visitor) {
  36. return false
  37. }
  38. }
  39. for i := range pod.Spec.Containers {
  40. if !visitContainerSecretNames(&pod.Spec.Containers[i], visitor) {
  41. return false
  42. }
  43. }
  44. var source *api.VolumeSource
  45. for i := range pod.Spec.Volumes {
  46. source = &pod.Spec.Volumes[i].VolumeSource
  47. switch {
  48. case source.AzureFile != nil:
  49. if len(source.AzureFile.SecretName) > 0 && !visitor(source.AzureFile.SecretName) {
  50. return false
  51. }
  52. case source.CephFS != nil:
  53. if source.CephFS.SecretRef != nil && !visitor(source.CephFS.SecretRef.Name) {
  54. return false
  55. }
  56. case source.Cinder != nil:
  57. if source.Cinder.SecretRef != nil && !visitor(source.Cinder.SecretRef.Name) {
  58. return false
  59. }
  60. case source.FlexVolume != nil:
  61. if source.FlexVolume.SecretRef != nil && !visitor(source.FlexVolume.SecretRef.Name) {
  62. return false
  63. }
  64. case source.Projected != nil:
  65. for j := range source.Projected.Sources {
  66. if source.Projected.Sources[j].Secret != nil {
  67. if !visitor(source.Projected.Sources[j].Secret.Name) {
  68. return false
  69. }
  70. }
  71. }
  72. case source.RBD != nil:
  73. if source.RBD.SecretRef != nil && !visitor(source.RBD.SecretRef.Name) {
  74. return false
  75. }
  76. case source.Secret != nil:
  77. if !visitor(source.Secret.SecretName) {
  78. return false
  79. }
  80. case source.ScaleIO != nil:
  81. if source.ScaleIO.SecretRef != nil && !visitor(source.ScaleIO.SecretRef.Name) {
  82. return false
  83. }
  84. case source.ISCSI != nil:
  85. if source.ISCSI.SecretRef != nil && !visitor(source.ISCSI.SecretRef.Name) {
  86. return false
  87. }
  88. case source.StorageOS != nil:
  89. if source.StorageOS.SecretRef != nil && !visitor(source.StorageOS.SecretRef.Name) {
  90. return false
  91. }
  92. case source.CSI != nil:
  93. if source.CSI.NodePublishSecretRef != nil && !visitor(source.CSI.NodePublishSecretRef.Name) {
  94. return false
  95. }
  96. }
  97. }
  98. return true
  99. }
  100. func visitContainerSecretNames(container *api.Container, visitor Visitor) bool {
  101. for _, env := range container.EnvFrom {
  102. if env.SecretRef != nil {
  103. if !visitor(env.SecretRef.Name) {
  104. return false
  105. }
  106. }
  107. }
  108. for _, envVar := range container.Env {
  109. if envVar.ValueFrom != nil && envVar.ValueFrom.SecretKeyRef != nil {
  110. if !visitor(envVar.ValueFrom.SecretKeyRef.Name) {
  111. return false
  112. }
  113. }
  114. }
  115. return true
  116. }
  117. // VisitPodConfigmapNames invokes the visitor function with the name of every configmap
  118. // referenced by the pod spec. If visitor returns false, visiting is short-circuited.
  119. // Transitive references (e.g. pod -> pvc -> pv -> secret) are not visited.
  120. // Returns true if visiting completed, false if visiting was short-circuited.
  121. func VisitPodConfigmapNames(pod *api.Pod, visitor Visitor) bool {
  122. for i := range pod.Spec.InitContainers {
  123. if !visitContainerConfigmapNames(&pod.Spec.InitContainers[i], visitor) {
  124. return false
  125. }
  126. }
  127. for i := range pod.Spec.Containers {
  128. if !visitContainerConfigmapNames(&pod.Spec.Containers[i], visitor) {
  129. return false
  130. }
  131. }
  132. var source *api.VolumeSource
  133. for i := range pod.Spec.Volumes {
  134. source = &pod.Spec.Volumes[i].VolumeSource
  135. switch {
  136. case source.Projected != nil:
  137. for j := range source.Projected.Sources {
  138. if source.Projected.Sources[j].ConfigMap != nil {
  139. if !visitor(source.Projected.Sources[j].ConfigMap.Name) {
  140. return false
  141. }
  142. }
  143. }
  144. case source.ConfigMap != nil:
  145. if !visitor(source.ConfigMap.Name) {
  146. return false
  147. }
  148. }
  149. }
  150. return true
  151. }
  152. func visitContainerConfigmapNames(container *api.Container, visitor Visitor) bool {
  153. for _, env := range container.EnvFrom {
  154. if env.ConfigMapRef != nil {
  155. if !visitor(env.ConfigMapRef.Name) {
  156. return false
  157. }
  158. }
  159. }
  160. for _, envVar := range container.Env {
  161. if envVar.ValueFrom != nil && envVar.ValueFrom.ConfigMapKeyRef != nil {
  162. if !visitor(envVar.ValueFrom.ConfigMapKeyRef.Name) {
  163. return false
  164. }
  165. }
  166. }
  167. return true
  168. }
  169. // IsPodReady returns true if a pod is ready; false otherwise.
  170. func IsPodReady(pod *api.Pod) bool {
  171. return IsPodReadyConditionTrue(pod.Status)
  172. }
  173. // IsPodReadyConditionTrue returns true if a pod is ready; false otherwise.
  174. func IsPodReadyConditionTrue(status api.PodStatus) bool {
  175. condition := GetPodReadyCondition(status)
  176. return condition != nil && condition.Status == api.ConditionTrue
  177. }
  178. // GetPodReadyCondition extracts the pod ready condition from the given status and returns that.
  179. // Returns nil if the condition is not present.
  180. func GetPodReadyCondition(status api.PodStatus) *api.PodCondition {
  181. _, condition := GetPodCondition(&status, api.PodReady)
  182. return condition
  183. }
  184. // GetPodCondition extracts the provided condition from the given status and returns that.
  185. // Returns nil and -1 if the condition is not present, and the index of the located condition.
  186. func GetPodCondition(status *api.PodStatus, conditionType api.PodConditionType) (int, *api.PodCondition) {
  187. if status == nil {
  188. return -1, nil
  189. }
  190. for i := range status.Conditions {
  191. if status.Conditions[i].Type == conditionType {
  192. return i, &status.Conditions[i]
  193. }
  194. }
  195. return -1, nil
  196. }
  197. // UpdatePodCondition updates existing pod condition or creates a new one. Sets LastTransitionTime to now if the
  198. // status has changed.
  199. // Returns true if pod condition has changed or has been added.
  200. func UpdatePodCondition(status *api.PodStatus, condition *api.PodCondition) bool {
  201. condition.LastTransitionTime = metav1.Now()
  202. // Try to find this pod condition.
  203. conditionIndex, oldCondition := GetPodCondition(status, condition.Type)
  204. if oldCondition == nil {
  205. // We are adding new pod condition.
  206. status.Conditions = append(status.Conditions, *condition)
  207. return true
  208. }
  209. // We are updating an existing condition, so we need to check if it has changed.
  210. if condition.Status == oldCondition.Status {
  211. condition.LastTransitionTime = oldCondition.LastTransitionTime
  212. }
  213. isEqual := condition.Status == oldCondition.Status &&
  214. condition.Reason == oldCondition.Reason &&
  215. condition.Message == oldCondition.Message &&
  216. condition.LastProbeTime.Equal(&oldCondition.LastProbeTime) &&
  217. condition.LastTransitionTime.Equal(&oldCondition.LastTransitionTime)
  218. status.Conditions[conditionIndex] = *condition
  219. // Return true if one of the fields have changed.
  220. return !isEqual
  221. }
  222. // DropDisabledTemplateFields removes disabled fields from the pod template metadata and spec.
  223. // This should be called from PrepareForCreate/PrepareForUpdate for all resources containing a PodTemplateSpec
  224. func DropDisabledTemplateFields(podTemplate, oldPodTemplate *api.PodTemplateSpec) {
  225. var (
  226. podSpec *api.PodSpec
  227. podAnnotations map[string]string
  228. oldPodSpec *api.PodSpec
  229. oldPodAnnotations map[string]string
  230. )
  231. if podTemplate != nil {
  232. podSpec = &podTemplate.Spec
  233. podAnnotations = podTemplate.Annotations
  234. }
  235. if oldPodTemplate != nil {
  236. oldPodSpec = &oldPodTemplate.Spec
  237. oldPodAnnotations = oldPodTemplate.Annotations
  238. }
  239. dropDisabledFields(podSpec, podAnnotations, oldPodSpec, oldPodAnnotations)
  240. }
  241. // DropDisabledPodFields removes disabled fields from the pod metadata and spec.
  242. // This should be called from PrepareForCreate/PrepareForUpdate for all resources containing a Pod
  243. func DropDisabledPodFields(pod, oldPod *api.Pod) {
  244. var (
  245. podSpec *api.PodSpec
  246. podAnnotations map[string]string
  247. oldPodSpec *api.PodSpec
  248. oldPodAnnotations map[string]string
  249. )
  250. if pod != nil {
  251. podSpec = &pod.Spec
  252. podAnnotations = pod.Annotations
  253. }
  254. if oldPod != nil {
  255. oldPodSpec = &oldPod.Spec
  256. oldPodAnnotations = oldPod.Annotations
  257. }
  258. dropDisabledFields(podSpec, podAnnotations, oldPodSpec, oldPodAnnotations)
  259. }
  260. // dropDisabledFields removes disabled fields from the pod metadata and spec.
  261. func dropDisabledFields(
  262. podSpec *api.PodSpec, podAnnotations map[string]string,
  263. oldPodSpec *api.PodSpec, oldPodAnnotations map[string]string,
  264. ) {
  265. // the new spec must always be non-nil
  266. if podSpec == nil {
  267. podSpec = &api.PodSpec{}
  268. }
  269. if !utilfeature.DefaultFeatureGate.Enabled(features.TokenRequestProjection) &&
  270. !tokenRequestProjectionInUse(oldPodSpec) {
  271. for i := range podSpec.Volumes {
  272. if podSpec.Volumes[i].Projected != nil {
  273. for j := range podSpec.Volumes[i].Projected.Sources {
  274. podSpec.Volumes[i].Projected.Sources[j].ServiceAccountToken = nil
  275. }
  276. }
  277. }
  278. }
  279. if !utilfeature.DefaultFeatureGate.Enabled(features.AppArmor) && !appArmorInUse(oldPodAnnotations) {
  280. for k := range podAnnotations {
  281. if strings.HasPrefix(k, apparmor.ContainerAnnotationKeyPrefix) {
  282. delete(podAnnotations, k)
  283. }
  284. }
  285. }
  286. if !utilfeature.DefaultFeatureGate.Enabled(features.PodShareProcessNamespace) && !shareProcessNamespaceInUse(oldPodSpec) {
  287. if podSpec.SecurityContext != nil {
  288. podSpec.SecurityContext.ShareProcessNamespace = nil
  289. }
  290. }
  291. if !utilfeature.DefaultFeatureGate.Enabled(features.PodPriority) && !podPriorityInUse(oldPodSpec) {
  292. // Set to nil pod's priority fields if the feature is disabled and the old pod
  293. // does not specify any values for these fields.
  294. podSpec.Priority = nil
  295. podSpec.PriorityClassName = ""
  296. }
  297. if !utilfeature.DefaultFeatureGate.Enabled(features.Sysctls) && !sysctlsInUse(oldPodSpec) {
  298. if podSpec.SecurityContext != nil {
  299. podSpec.SecurityContext.Sysctls = nil
  300. }
  301. }
  302. if !utilfeature.DefaultFeatureGate.Enabled(features.LocalStorageCapacityIsolation) && !emptyDirSizeLimitInUse(oldPodSpec) {
  303. for i := range podSpec.Volumes {
  304. if podSpec.Volumes[i].EmptyDir != nil {
  305. podSpec.Volumes[i].EmptyDir.SizeLimit = nil
  306. }
  307. }
  308. }
  309. if !utilfeature.DefaultFeatureGate.Enabled(features.VolumeSubpath) && !subpathInUse(oldPodSpec) {
  310. // drop subpath from the pod if the feature is disabled and the old spec did not specify subpaths
  311. for i := range podSpec.Containers {
  312. for j := range podSpec.Containers[i].VolumeMounts {
  313. podSpec.Containers[i].VolumeMounts[j].SubPath = ""
  314. }
  315. }
  316. for i := range podSpec.InitContainers {
  317. for j := range podSpec.InitContainers[i].VolumeMounts {
  318. podSpec.InitContainers[i].VolumeMounts[j].SubPath = ""
  319. }
  320. }
  321. }
  322. if (!utilfeature.DefaultFeatureGate.Enabled(features.VolumeSubpath) || !utilfeature.DefaultFeatureGate.Enabled(features.VolumeSubpathEnvExpansion)) && !subpathExprInUse(oldPodSpec) {
  323. // drop subpath env expansion from the pod if either of the subpath features is disabled and the old spec did not specify subpath env expansion
  324. for i := range podSpec.Containers {
  325. for j := range podSpec.Containers[i].VolumeMounts {
  326. podSpec.Containers[i].VolumeMounts[j].SubPathExpr = ""
  327. }
  328. }
  329. for i := range podSpec.InitContainers {
  330. for j := range podSpec.InitContainers[i].VolumeMounts {
  331. podSpec.InitContainers[i].VolumeMounts[j].SubPathExpr = ""
  332. }
  333. }
  334. }
  335. dropDisabledVolumeDevicesFields(podSpec, oldPodSpec)
  336. dropDisabledRunAsGroupField(podSpec, oldPodSpec)
  337. dropDisabledGMSAFields(podSpec, oldPodSpec)
  338. if !utilfeature.DefaultFeatureGate.Enabled(features.RuntimeClass) && !runtimeClassInUse(oldPodSpec) {
  339. // Set RuntimeClassName to nil only if feature is disabled and it is not used
  340. podSpec.RuntimeClassName = nil
  341. }
  342. dropDisabledProcMountField(podSpec, oldPodSpec)
  343. dropDisabledCSIVolumeSourceAlphaFields(podSpec, oldPodSpec)
  344. if !utilfeature.DefaultFeatureGate.Enabled(features.NonPreemptingPriority) &&
  345. !podPriorityInUse(oldPodSpec) {
  346. // Set to nil pod's PreemptionPolicy fields if the feature is disabled and the old pod
  347. // does not specify any values for these fields.
  348. podSpec.PreemptionPolicy = nil
  349. }
  350. }
  351. // dropDisabledRunAsGroupField removes disabled fields from PodSpec related
  352. // to RunAsGroup
  353. func dropDisabledRunAsGroupField(podSpec, oldPodSpec *api.PodSpec) {
  354. if !utilfeature.DefaultFeatureGate.Enabled(features.RunAsGroup) && !runAsGroupInUse(oldPodSpec) {
  355. if podSpec.SecurityContext != nil {
  356. podSpec.SecurityContext.RunAsGroup = nil
  357. }
  358. for i := range podSpec.Containers {
  359. if podSpec.Containers[i].SecurityContext != nil {
  360. podSpec.Containers[i].SecurityContext.RunAsGroup = nil
  361. }
  362. }
  363. for i := range podSpec.InitContainers {
  364. if podSpec.InitContainers[i].SecurityContext != nil {
  365. podSpec.InitContainers[i].SecurityContext.RunAsGroup = nil
  366. }
  367. }
  368. }
  369. }
  370. // dropDisabledGMSAFields removes disabled fields related to Windows GMSA
  371. // from the given PodSpec.
  372. func dropDisabledGMSAFields(podSpec, oldPodSpec *api.PodSpec) {
  373. if utilfeature.DefaultFeatureGate.Enabled(features.WindowsGMSA) ||
  374. gMSAFieldsInUse(oldPodSpec) {
  375. return
  376. }
  377. if podSpec.SecurityContext != nil {
  378. dropDisabledGMSAFieldsFromWindowsSecurityOptions(podSpec.SecurityContext.WindowsOptions)
  379. }
  380. dropDisabledGMSAFieldsFromContainers(podSpec.Containers)
  381. dropDisabledGMSAFieldsFromContainers(podSpec.InitContainers)
  382. }
  383. // dropDisabledGMSAFieldsFromWindowsSecurityOptions removes disabled fields
  384. // related to Windows GMSA from the given WindowsSecurityContextOptions.
  385. func dropDisabledGMSAFieldsFromWindowsSecurityOptions(windowsOptions *api.WindowsSecurityContextOptions) {
  386. if windowsOptions != nil {
  387. windowsOptions.GMSACredentialSpecName = nil
  388. windowsOptions.GMSACredentialSpec = nil
  389. }
  390. }
  391. // dropDisabledGMSAFieldsFromContainers removes disabled fields
  392. func dropDisabledGMSAFieldsFromContainers(containers []api.Container) {
  393. for i := range containers {
  394. if containers[i].SecurityContext != nil {
  395. dropDisabledGMSAFieldsFromWindowsSecurityOptions(containers[i].SecurityContext.WindowsOptions)
  396. }
  397. }
  398. }
  399. // dropDisabledProcMountField removes disabled fields from PodSpec related
  400. // to ProcMount only if it is not already used by the old spec
  401. func dropDisabledProcMountField(podSpec, oldPodSpec *api.PodSpec) {
  402. if !utilfeature.DefaultFeatureGate.Enabled(features.ProcMountType) && !procMountInUse(oldPodSpec) {
  403. defaultProcMount := api.DefaultProcMount
  404. for i := range podSpec.Containers {
  405. if podSpec.Containers[i].SecurityContext != nil {
  406. if podSpec.Containers[i].SecurityContext.ProcMount != nil {
  407. // The ProcMount field was improperly forced to non-nil in 1.12.
  408. // If the feature is disabled, and the existing object is not using any non-default values, and the ProcMount field is present in the incoming object, force to the default value.
  409. // Note: we cannot force the field to nil when the feature is disabled because it causes a diff against previously persisted data.
  410. podSpec.Containers[i].SecurityContext.ProcMount = &defaultProcMount
  411. }
  412. }
  413. }
  414. for i := range podSpec.InitContainers {
  415. if podSpec.InitContainers[i].SecurityContext != nil {
  416. if podSpec.InitContainers[i].SecurityContext.ProcMount != nil {
  417. // The ProcMount field was improperly forced to non-nil in 1.12.
  418. // If the feature is disabled, and the existing object is not using any non-default values, and the ProcMount field is present in the incoming object, force to the default value.
  419. // Note: we cannot force the field to nil when the feature is disabled because it causes a diff against previously persisted data.
  420. podSpec.InitContainers[i].SecurityContext.ProcMount = &defaultProcMount
  421. }
  422. }
  423. }
  424. }
  425. }
  426. // dropDisabledVolumeDevicesFields removes disabled fields from []VolumeDevice if it has not been already populated.
  427. // This should be called from PrepareForCreate/PrepareForUpdate for all resources containing a VolumeDevice
  428. func dropDisabledVolumeDevicesFields(podSpec, oldPodSpec *api.PodSpec) {
  429. if !utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) && !volumeDevicesInUse(oldPodSpec) {
  430. for i := range podSpec.Containers {
  431. podSpec.Containers[i].VolumeDevices = nil
  432. }
  433. for i := range podSpec.InitContainers {
  434. podSpec.InitContainers[i].VolumeDevices = nil
  435. }
  436. }
  437. }
  438. // dropDisabledCSIVolumeSourceAlphaFields removes disabled alpha fields from []CSIVolumeSource.
  439. // This should be called from PrepareForCreate/PrepareForUpdate for all pod specs resources containing a CSIVolumeSource
  440. func dropDisabledCSIVolumeSourceAlphaFields(podSpec, oldPodSpec *api.PodSpec) {
  441. if !utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) && !csiInUse(oldPodSpec) {
  442. for i := range podSpec.Volumes {
  443. podSpec.Volumes[i].CSI = nil
  444. }
  445. }
  446. }
  447. // subpathInUse returns true if the pod spec is non-nil and has a volume mount that makes use of the subPath feature
  448. func subpathInUse(podSpec *api.PodSpec) bool {
  449. if podSpec == nil {
  450. return false
  451. }
  452. for i := range podSpec.Containers {
  453. for j := range podSpec.Containers[i].VolumeMounts {
  454. if len(podSpec.Containers[i].VolumeMounts[j].SubPath) > 0 {
  455. return true
  456. }
  457. }
  458. }
  459. for i := range podSpec.InitContainers {
  460. for j := range podSpec.InitContainers[i].VolumeMounts {
  461. if len(podSpec.InitContainers[i].VolumeMounts[j].SubPath) > 0 {
  462. return true
  463. }
  464. }
  465. }
  466. return false
  467. }
  468. // runtimeClassInUse returns true if the pod spec is non-nil and has a RuntimeClassName set
  469. func runtimeClassInUse(podSpec *api.PodSpec) bool {
  470. if podSpec == nil {
  471. return false
  472. }
  473. if podSpec.RuntimeClassName != nil {
  474. return true
  475. }
  476. return false
  477. }
  478. // procMountInUse returns true if the pod spec is non-nil and has a SecurityContext's ProcMount field set to a non-default value
  479. func procMountInUse(podSpec *api.PodSpec) bool {
  480. if podSpec == nil {
  481. return false
  482. }
  483. for i := range podSpec.Containers {
  484. if podSpec.Containers[i].SecurityContext != nil {
  485. if podSpec.Containers[i].SecurityContext.ProcMount != nil {
  486. if *podSpec.Containers[i].SecurityContext.ProcMount != api.DefaultProcMount {
  487. return true
  488. }
  489. }
  490. }
  491. }
  492. for i := range podSpec.InitContainers {
  493. if podSpec.InitContainers[i].SecurityContext != nil {
  494. if podSpec.InitContainers[i].SecurityContext.ProcMount != nil {
  495. if *podSpec.InitContainers[i].SecurityContext.ProcMount != api.DefaultProcMount {
  496. return true
  497. }
  498. }
  499. }
  500. }
  501. return false
  502. }
  503. // appArmorInUse returns true if the pod has apparmor related information
  504. func appArmorInUse(podAnnotations map[string]string) bool {
  505. for k := range podAnnotations {
  506. if strings.HasPrefix(k, apparmor.ContainerAnnotationKeyPrefix) {
  507. return true
  508. }
  509. }
  510. return false
  511. }
  512. func shareProcessNamespaceInUse(podSpec *api.PodSpec) bool {
  513. if podSpec == nil {
  514. return false
  515. }
  516. if podSpec.SecurityContext != nil && podSpec.SecurityContext.ShareProcessNamespace != nil {
  517. return true
  518. }
  519. return false
  520. }
  521. func tokenRequestProjectionInUse(podSpec *api.PodSpec) bool {
  522. if podSpec == nil {
  523. return false
  524. }
  525. for _, v := range podSpec.Volumes {
  526. if v.Projected == nil {
  527. continue
  528. }
  529. for _, s := range v.Projected.Sources {
  530. if s.ServiceAccountToken != nil {
  531. return true
  532. }
  533. }
  534. }
  535. return false
  536. }
  537. // podPriorityInUse returns true if the pod spec is non-nil and has Priority or PriorityClassName set.
  538. func podPriorityInUse(podSpec *api.PodSpec) bool {
  539. if podSpec == nil {
  540. return false
  541. }
  542. if podSpec.Priority != nil || podSpec.PriorityClassName != "" {
  543. return true
  544. }
  545. return false
  546. }
  547. func sysctlsInUse(podSpec *api.PodSpec) bool {
  548. if podSpec == nil {
  549. return false
  550. }
  551. if podSpec.SecurityContext != nil && podSpec.SecurityContext.Sysctls != nil {
  552. return true
  553. }
  554. return false
  555. }
  556. // emptyDirSizeLimitInUse returns true if any pod's EptyDir volumes use SizeLimit.
  557. func emptyDirSizeLimitInUse(podSpec *api.PodSpec) bool {
  558. if podSpec == nil {
  559. return false
  560. }
  561. for i := range podSpec.Volumes {
  562. if podSpec.Volumes[i].EmptyDir != nil {
  563. if podSpec.Volumes[i].EmptyDir.SizeLimit != nil {
  564. return true
  565. }
  566. }
  567. }
  568. return false
  569. }
  570. // volumeDevicesInUse returns true if the pod spec is non-nil and has VolumeDevices set.
  571. func volumeDevicesInUse(podSpec *api.PodSpec) bool {
  572. if podSpec == nil {
  573. return false
  574. }
  575. for i := range podSpec.Containers {
  576. if podSpec.Containers[i].VolumeDevices != nil {
  577. return true
  578. }
  579. }
  580. for i := range podSpec.InitContainers {
  581. if podSpec.InitContainers[i].VolumeDevices != nil {
  582. return true
  583. }
  584. }
  585. return false
  586. }
  587. // runAsGroupInUse returns true if the pod spec is non-nil and has a SecurityContext's RunAsGroup field set
  588. func runAsGroupInUse(podSpec *api.PodSpec) bool {
  589. if podSpec == nil {
  590. return false
  591. }
  592. if podSpec.SecurityContext != nil && podSpec.SecurityContext.RunAsGroup != nil {
  593. return true
  594. }
  595. for i := range podSpec.Containers {
  596. if podSpec.Containers[i].SecurityContext != nil && podSpec.Containers[i].SecurityContext.RunAsGroup != nil {
  597. return true
  598. }
  599. }
  600. for i := range podSpec.InitContainers {
  601. if podSpec.InitContainers[i].SecurityContext != nil && podSpec.InitContainers[i].SecurityContext.RunAsGroup != nil {
  602. return true
  603. }
  604. }
  605. return false
  606. }
  607. // gMSAFieldsInUse returns true if the pod spec is non-nil and has one of any
  608. // SecurityContext's GMSACredentialSpecName or GMSACredentialSpec fields set.
  609. func gMSAFieldsInUse(podSpec *api.PodSpec) bool {
  610. if podSpec == nil {
  611. return false
  612. }
  613. if podSpec.SecurityContext != nil && gMSAFieldsInUseInWindowsSecurityOptions(podSpec.SecurityContext.WindowsOptions) {
  614. return true
  615. }
  616. return gMSAFieldsInUseInAnyContainer(podSpec.Containers) ||
  617. gMSAFieldsInUseInAnyContainer(podSpec.InitContainers)
  618. }
  619. // gMSAFieldsInUseInWindowsSecurityOptions returns true if the given WindowsSecurityContextOptions is
  620. // non-nil and one of its GMSACredentialSpecName or GMSACredentialSpec fields is set.
  621. func gMSAFieldsInUseInWindowsSecurityOptions(windowsOptions *api.WindowsSecurityContextOptions) bool {
  622. if windowsOptions == nil {
  623. return false
  624. }
  625. return windowsOptions.GMSACredentialSpecName != nil ||
  626. windowsOptions.GMSACredentialSpec != nil
  627. }
  628. // gMSAFieldsInUseInAnyContainer returns true if any of the given Containers has its
  629. // SecurityContext's GMSACredentialSpecName or GMSACredentialSpec fields set.
  630. func gMSAFieldsInUseInAnyContainer(containers []api.Container) bool {
  631. for _, container := range containers {
  632. if container.SecurityContext != nil && gMSAFieldsInUseInWindowsSecurityOptions(container.SecurityContext.WindowsOptions) {
  633. return true
  634. }
  635. }
  636. return false
  637. }
  638. // subpathExprInUse returns true if the pod spec is non-nil and has a volume mount that makes use of the subPathExpr feature
  639. func subpathExprInUse(podSpec *api.PodSpec) bool {
  640. if podSpec == nil {
  641. return false
  642. }
  643. for i := range podSpec.Containers {
  644. for j := range podSpec.Containers[i].VolumeMounts {
  645. if len(podSpec.Containers[i].VolumeMounts[j].SubPathExpr) > 0 {
  646. return true
  647. }
  648. }
  649. }
  650. for i := range podSpec.InitContainers {
  651. for j := range podSpec.InitContainers[i].VolumeMounts {
  652. if len(podSpec.InitContainers[i].VolumeMounts[j].SubPathExpr) > 0 {
  653. return true
  654. }
  655. }
  656. }
  657. return false
  658. }
  659. // csiInUse returns true if any pod's spec include inline CSI volumes.
  660. func csiInUse(podSpec *api.PodSpec) bool {
  661. if podSpec == nil {
  662. return false
  663. }
  664. for i := range podSpec.Volumes {
  665. if podSpec.Volumes[i].CSI != nil {
  666. return true
  667. }
  668. }
  669. return false
  670. }