mustmatchpatterns.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  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 sysctl
  14. import (
  15. "fmt"
  16. "strings"
  17. "k8s.io/apimachinery/pkg/util/validation/field"
  18. api "k8s.io/kubernetes/pkg/apis/core"
  19. )
  20. // SafeSysctlWhitelist returns the whitelist of safe sysctls and safe sysctl patterns (ending in *).
  21. //
  22. // A sysctl is called safe iff
  23. // - it is namespaced in the container or the pod
  24. // - it is isolated, i.e. has no influence on any other pod on the same node.
  25. func SafeSysctlWhitelist() []string {
  26. return []string{
  27. "kernel.shm_rmid_forced",
  28. "net.ipv4.ip_local_port_range",
  29. "net.ipv4.tcp_syncookies",
  30. }
  31. }
  32. // mustMatchPatterns implements the SysctlsStrategy interface
  33. type mustMatchPatterns struct {
  34. safeWhitelist []string
  35. allowedUnsafeSysctls []string
  36. forbiddenSysctls []string
  37. }
  38. var (
  39. _ SysctlsStrategy = &mustMatchPatterns{}
  40. defaultSysctlsPatterns = []string{"*"}
  41. )
  42. // NewMustMatchPatterns creates a new mustMatchPatterns strategy that will provide validation.
  43. // Passing nil means the default pattern, passing an empty list means to disallow all sysctls.
  44. func NewMustMatchPatterns(safeWhitelist, allowedUnsafeSysctls, forbiddenSysctls []string) SysctlsStrategy {
  45. return &mustMatchPatterns{
  46. safeWhitelist: safeWhitelist,
  47. allowedUnsafeSysctls: allowedUnsafeSysctls,
  48. forbiddenSysctls: forbiddenSysctls,
  49. }
  50. }
  51. func (s *mustMatchPatterns) isForbidden(sysctlName string) bool {
  52. // Is the sysctl forbidden?
  53. for _, s := range s.forbiddenSysctls {
  54. if strings.HasSuffix(s, "*") {
  55. prefix := strings.TrimSuffix(s, "*")
  56. if strings.HasPrefix(sysctlName, prefix) {
  57. return true
  58. }
  59. } else if sysctlName == s {
  60. return true
  61. }
  62. }
  63. return false
  64. }
  65. func (s *mustMatchPatterns) isSafe(sysctlName string) bool {
  66. for _, ws := range s.safeWhitelist {
  67. if sysctlName == ws {
  68. return true
  69. }
  70. }
  71. return false
  72. }
  73. func (s *mustMatchPatterns) isAllowedUnsafe(sysctlName string) bool {
  74. for _, s := range s.allowedUnsafeSysctls {
  75. if strings.HasSuffix(s, "*") {
  76. prefix := strings.TrimSuffix(s, "*")
  77. if strings.HasPrefix(sysctlName, prefix) {
  78. return true
  79. }
  80. } else if sysctlName == s {
  81. return true
  82. }
  83. }
  84. return false
  85. }
  86. // Validate ensures that the specified values fall within the range of the strategy.
  87. func (s *mustMatchPatterns) Validate(pod *api.Pod) field.ErrorList {
  88. allErrs := field.ErrorList{}
  89. var sysctls []api.Sysctl
  90. if pod.Spec.SecurityContext != nil {
  91. sysctls = pod.Spec.SecurityContext.Sysctls
  92. }
  93. fieldPath := field.NewPath("pod", "spec", "securityContext").Child("sysctls")
  94. for i, sysctl := range sysctls {
  95. switch {
  96. case s.isForbidden(sysctl.Name):
  97. allErrs = append(allErrs, field.ErrorList{field.Forbidden(fieldPath.Index(i), fmt.Sprintf("sysctl %q is not allowed", sysctl.Name))}...)
  98. case s.isSafe(sysctl.Name):
  99. continue
  100. case s.isAllowedUnsafe(sysctl.Name):
  101. continue
  102. default:
  103. allErrs = append(allErrs, field.ErrorList{field.Forbidden(fieldPath.Index(i), fmt.Sprintf("unsafe sysctl %q is not allowed", sysctl.Name))}...)
  104. }
  105. }
  106. return allErrs
  107. }