util.go 6.8 KB

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