security_context.go 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /*
  2. Copyright 2016 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 dockershim
  14. import (
  15. "fmt"
  16. "strconv"
  17. dockercontainer "github.com/docker/docker/api/types/container"
  18. runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
  19. knetwork "k8s.io/kubernetes/pkg/kubelet/dockershim/network"
  20. )
  21. // applySandboxSecurityContext updates docker sandbox options according to security context.
  22. func applySandboxSecurityContext(lc *runtimeapi.LinuxPodSandboxConfig, config *dockercontainer.Config, hc *dockercontainer.HostConfig, network *knetwork.PluginManager, separator rune) error {
  23. if lc == nil {
  24. return nil
  25. }
  26. var sc *runtimeapi.LinuxContainerSecurityContext
  27. if lc.SecurityContext != nil {
  28. sc = &runtimeapi.LinuxContainerSecurityContext{
  29. SupplementalGroups: lc.SecurityContext.SupplementalGroups,
  30. RunAsUser: lc.SecurityContext.RunAsUser,
  31. RunAsGroup: lc.SecurityContext.RunAsGroup,
  32. ReadonlyRootfs: lc.SecurityContext.ReadonlyRootfs,
  33. SelinuxOptions: lc.SecurityContext.SelinuxOptions,
  34. NamespaceOptions: lc.SecurityContext.NamespaceOptions,
  35. }
  36. }
  37. err := modifyContainerConfig(sc, config)
  38. if err != nil {
  39. return err
  40. }
  41. if err := modifyHostConfig(sc, hc, separator); err != nil {
  42. return err
  43. }
  44. modifySandboxNamespaceOptions(sc.GetNamespaceOptions(), hc, network)
  45. return nil
  46. }
  47. // applyContainerSecurityContext updates docker container options according to security context.
  48. func applyContainerSecurityContext(lc *runtimeapi.LinuxContainerConfig, podSandboxID string, config *dockercontainer.Config, hc *dockercontainer.HostConfig, separator rune) error {
  49. if lc == nil {
  50. return nil
  51. }
  52. err := modifyContainerConfig(lc.SecurityContext, config)
  53. if err != nil {
  54. return err
  55. }
  56. if err := modifyHostConfig(lc.SecurityContext, hc, separator); err != nil {
  57. return err
  58. }
  59. modifyContainerNamespaceOptions(lc.SecurityContext.GetNamespaceOptions(), podSandboxID, hc)
  60. return nil
  61. }
  62. // modifyContainerConfig applies container security context config to dockercontainer.Config.
  63. func modifyContainerConfig(sc *runtimeapi.LinuxContainerSecurityContext, config *dockercontainer.Config) error {
  64. if sc == nil {
  65. return nil
  66. }
  67. if sc.RunAsUser != nil {
  68. config.User = strconv.FormatInt(sc.GetRunAsUser().Value, 10)
  69. }
  70. if sc.RunAsUsername != "" {
  71. config.User = sc.RunAsUsername
  72. }
  73. user := config.User
  74. if sc.RunAsGroup != nil {
  75. if user == "" {
  76. return fmt.Errorf("runAsGroup is specified without a runAsUser")
  77. }
  78. user = fmt.Sprintf("%s:%d", config.User, sc.GetRunAsGroup().Value)
  79. }
  80. config.User = user
  81. return nil
  82. }
  83. // modifyHostConfig applies security context config to dockercontainer.HostConfig.
  84. func modifyHostConfig(sc *runtimeapi.LinuxContainerSecurityContext, hostConfig *dockercontainer.HostConfig, separator rune) error {
  85. if sc == nil {
  86. return nil
  87. }
  88. // Apply supplemental groups.
  89. for _, group := range sc.SupplementalGroups {
  90. hostConfig.GroupAdd = append(hostConfig.GroupAdd, strconv.FormatInt(group, 10))
  91. }
  92. // Apply security context for the container.
  93. hostConfig.Privileged = sc.Privileged
  94. hostConfig.ReadonlyRootfs = sc.ReadonlyRootfs
  95. if sc.Capabilities != nil {
  96. hostConfig.CapAdd = sc.GetCapabilities().AddCapabilities
  97. hostConfig.CapDrop = sc.GetCapabilities().DropCapabilities
  98. }
  99. if sc.SelinuxOptions != nil {
  100. hostConfig.SecurityOpt = addSELinuxOptions(
  101. hostConfig.SecurityOpt,
  102. sc.SelinuxOptions,
  103. separator,
  104. )
  105. }
  106. // Apply apparmor options.
  107. apparmorSecurityOpts, err := getApparmorSecurityOpts(sc, separator)
  108. if err != nil {
  109. return fmt.Errorf("failed to generate apparmor security options: %v", err)
  110. }
  111. hostConfig.SecurityOpt = append(hostConfig.SecurityOpt, apparmorSecurityOpts...)
  112. if sc.NoNewPrivs {
  113. hostConfig.SecurityOpt = append(hostConfig.SecurityOpt, "no-new-privileges")
  114. }
  115. if !hostConfig.Privileged {
  116. hostConfig.MaskedPaths = sc.MaskedPaths
  117. hostConfig.ReadonlyPaths = sc.ReadonlyPaths
  118. }
  119. return nil
  120. }
  121. // modifySandboxNamespaceOptions apply namespace options for sandbox
  122. func modifySandboxNamespaceOptions(nsOpts *runtimeapi.NamespaceOption, hostConfig *dockercontainer.HostConfig, network *knetwork.PluginManager) {
  123. // The sandbox's PID namespace is the one that's shared, so CONTAINER and POD are equivalent for it
  124. if nsOpts.GetPid() == runtimeapi.NamespaceMode_NODE {
  125. hostConfig.PidMode = namespaceModeHost
  126. }
  127. modifyHostOptionsForSandbox(nsOpts, network, hostConfig)
  128. }
  129. // modifyContainerNamespaceOptions apply namespace options for container
  130. func modifyContainerNamespaceOptions(nsOpts *runtimeapi.NamespaceOption, podSandboxID string, hostConfig *dockercontainer.HostConfig) {
  131. switch nsOpts.GetPid() {
  132. case runtimeapi.NamespaceMode_NODE:
  133. hostConfig.PidMode = namespaceModeHost
  134. case runtimeapi.NamespaceMode_POD:
  135. hostConfig.PidMode = dockercontainer.PidMode(fmt.Sprintf("container:%v", podSandboxID))
  136. case runtimeapi.NamespaceMode_TARGET:
  137. hostConfig.PidMode = dockercontainer.PidMode(fmt.Sprintf("container:%v", nsOpts.GetTargetId()))
  138. }
  139. modifyHostOptionsForContainer(nsOpts, podSandboxID, hostConfig)
  140. }
  141. // modifyHostOptionsForSandbox applies NetworkMode/UTSMode to sandbox's dockercontainer.HostConfig.
  142. func modifyHostOptionsForSandbox(nsOpts *runtimeapi.NamespaceOption, network *knetwork.PluginManager, hc *dockercontainer.HostConfig) {
  143. if nsOpts.GetIpc() == runtimeapi.NamespaceMode_NODE {
  144. hc.IpcMode = namespaceModeHost
  145. }
  146. if nsOpts.GetNetwork() == runtimeapi.NamespaceMode_NODE {
  147. hc.NetworkMode = namespaceModeHost
  148. return
  149. }
  150. if network == nil {
  151. hc.NetworkMode = "default"
  152. return
  153. }
  154. switch network.PluginName() {
  155. case "cni":
  156. fallthrough
  157. case "kubenet":
  158. hc.NetworkMode = "none"
  159. default:
  160. hc.NetworkMode = "default"
  161. }
  162. }
  163. // modifyHostOptionsForContainer applies NetworkMode/UTSMode to container's dockercontainer.HostConfig.
  164. func modifyHostOptionsForContainer(nsOpts *runtimeapi.NamespaceOption, podSandboxID string, hc *dockercontainer.HostConfig) {
  165. sandboxNSMode := fmt.Sprintf("container:%v", podSandboxID)
  166. hc.NetworkMode = dockercontainer.NetworkMode(sandboxNSMode)
  167. hc.IpcMode = dockercontainer.IpcMode(sandboxNSMode)
  168. hc.UTSMode = ""
  169. if nsOpts.GetNetwork() == runtimeapi.NamespaceMode_NODE {
  170. hc.UTSMode = namespaceModeHost
  171. }
  172. }