security_context.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  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 kuberuntime
  14. import (
  15. "fmt"
  16. "k8s.io/api/core/v1"
  17. runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
  18. "k8s.io/kubernetes/pkg/security/apparmor"
  19. "k8s.io/kubernetes/pkg/securitycontext"
  20. )
  21. // determineEffectiveSecurityContext gets container's security context from v1.Pod and v1.Container.
  22. func (m *kubeGenericRuntimeManager) determineEffectiveSecurityContext(pod *v1.Pod, container *v1.Container, uid *int64, username string) *runtimeapi.LinuxContainerSecurityContext {
  23. effectiveSc := securitycontext.DetermineEffectiveSecurityContext(pod, container)
  24. synthesized := convertToRuntimeSecurityContext(effectiveSc)
  25. if synthesized == nil {
  26. synthesized = &runtimeapi.LinuxContainerSecurityContext{
  27. MaskedPaths: securitycontext.ConvertToRuntimeMaskedPaths(effectiveSc.ProcMount),
  28. ReadonlyPaths: securitycontext.ConvertToRuntimeReadonlyPaths(effectiveSc.ProcMount),
  29. }
  30. }
  31. // set SeccompProfilePath.
  32. synthesized.SeccompProfilePath = m.getSeccompProfileFromAnnotations(pod.Annotations, container.Name)
  33. // set ApparmorProfile.
  34. synthesized.ApparmorProfile = apparmor.GetProfileNameFromPodAnnotations(pod.Annotations, container.Name)
  35. // set RunAsUser.
  36. if synthesized.RunAsUser == nil {
  37. if uid != nil {
  38. synthesized.RunAsUser = &runtimeapi.Int64Value{Value: *uid}
  39. }
  40. synthesized.RunAsUsername = username
  41. }
  42. // set namespace options and supplemental groups.
  43. synthesized.NamespaceOptions = namespacesForPod(pod)
  44. podSc := pod.Spec.SecurityContext
  45. if podSc != nil {
  46. if podSc.FSGroup != nil {
  47. synthesized.SupplementalGroups = append(synthesized.SupplementalGroups, int64(*podSc.FSGroup))
  48. }
  49. if podSc.SupplementalGroups != nil {
  50. for _, sg := range podSc.SupplementalGroups {
  51. synthesized.SupplementalGroups = append(synthesized.SupplementalGroups, int64(sg))
  52. }
  53. }
  54. }
  55. if groups := m.runtimeHelper.GetExtraSupplementalGroupsForPod(pod); len(groups) > 0 {
  56. synthesized.SupplementalGroups = append(synthesized.SupplementalGroups, groups...)
  57. }
  58. synthesized.NoNewPrivs = securitycontext.AddNoNewPrivileges(effectiveSc)
  59. synthesized.MaskedPaths = securitycontext.ConvertToRuntimeMaskedPaths(effectiveSc.ProcMount)
  60. synthesized.ReadonlyPaths = securitycontext.ConvertToRuntimeReadonlyPaths(effectiveSc.ProcMount)
  61. return synthesized
  62. }
  63. // verifyRunAsNonRoot verifies RunAsNonRoot.
  64. func verifyRunAsNonRoot(pod *v1.Pod, container *v1.Container, uid *int64, username string) error {
  65. effectiveSc := securitycontext.DetermineEffectiveSecurityContext(pod, container)
  66. // If the option is not set, or if running as root is allowed, return nil.
  67. if effectiveSc == nil || effectiveSc.RunAsNonRoot == nil || !*effectiveSc.RunAsNonRoot {
  68. return nil
  69. }
  70. if effectiveSc.RunAsUser != nil {
  71. if *effectiveSc.RunAsUser == 0 {
  72. return fmt.Errorf("container's runAsUser breaks non-root policy")
  73. }
  74. return nil
  75. }
  76. switch {
  77. case uid != nil && *uid == 0:
  78. return fmt.Errorf("container has runAsNonRoot and image will run as root")
  79. case uid == nil && len(username) > 0:
  80. return fmt.Errorf("container has runAsNonRoot and image has non-numeric user (%s), cannot verify user is non-root", username)
  81. default:
  82. return nil
  83. }
  84. }
  85. // convertToRuntimeSecurityContext converts v1.SecurityContext to runtimeapi.SecurityContext.
  86. func convertToRuntimeSecurityContext(securityContext *v1.SecurityContext) *runtimeapi.LinuxContainerSecurityContext {
  87. if securityContext == nil {
  88. return nil
  89. }
  90. sc := &runtimeapi.LinuxContainerSecurityContext{
  91. Capabilities: convertToRuntimeCapabilities(securityContext.Capabilities),
  92. SelinuxOptions: convertToRuntimeSELinuxOption(securityContext.SELinuxOptions),
  93. }
  94. if securityContext.RunAsUser != nil {
  95. sc.RunAsUser = &runtimeapi.Int64Value{Value: int64(*securityContext.RunAsUser)}
  96. }
  97. if securityContext.RunAsGroup != nil {
  98. sc.RunAsGroup = &runtimeapi.Int64Value{Value: int64(*securityContext.RunAsGroup)}
  99. }
  100. if securityContext.Privileged != nil {
  101. sc.Privileged = *securityContext.Privileged
  102. }
  103. if securityContext.ReadOnlyRootFilesystem != nil {
  104. sc.ReadonlyRootfs = *securityContext.ReadOnlyRootFilesystem
  105. }
  106. return sc
  107. }
  108. // convertToRuntimeSELinuxOption converts v1.SELinuxOptions to runtimeapi.SELinuxOption.
  109. func convertToRuntimeSELinuxOption(opts *v1.SELinuxOptions) *runtimeapi.SELinuxOption {
  110. if opts == nil {
  111. return nil
  112. }
  113. return &runtimeapi.SELinuxOption{
  114. User: opts.User,
  115. Role: opts.Role,
  116. Type: opts.Type,
  117. Level: opts.Level,
  118. }
  119. }
  120. // convertToRuntimeCapabilities converts v1.Capabilities to runtimeapi.Capability.
  121. func convertToRuntimeCapabilities(opts *v1.Capabilities) *runtimeapi.Capability {
  122. if opts == nil {
  123. return nil
  124. }
  125. capabilities := &runtimeapi.Capability{
  126. AddCapabilities: make([]string, len(opts.Add)),
  127. DropCapabilities: make([]string, len(opts.Drop)),
  128. }
  129. for index, value := range opts.Add {
  130. capabilities.AddCapabilities[index] = string(value)
  131. }
  132. for index, value := range opts.Drop {
  133. capabilities.DropCapabilities[index] = string(value)
  134. }
  135. return capabilities
  136. }