strategy.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  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 apparmor
  14. import (
  15. "fmt"
  16. "strings"
  17. "k8s.io/apimachinery/pkg/util/validation/field"
  18. api "k8s.io/kubernetes/pkg/apis/core"
  19. "k8s.io/kubernetes/pkg/security/apparmor"
  20. "k8s.io/kubernetes/pkg/util/maps"
  21. )
  22. // Strategy defines the interface for all AppArmor constraint strategies.
  23. type Strategy interface {
  24. // Generate updates the annotations based on constraint rules. The updates are applied to a copy
  25. // of the annotations, and returned.
  26. Generate(annotations map[string]string, container *api.Container) (map[string]string, error)
  27. // Validate ensures that the specified values fall within the range of the strategy.
  28. Validate(pod *api.Pod, container *api.Container) field.ErrorList
  29. }
  30. type strategy struct {
  31. defaultProfile string
  32. allowedProfiles map[string]bool
  33. // For printing error messages (preserves order).
  34. allowedProfilesString string
  35. }
  36. var _ Strategy = &strategy{}
  37. // NewStrategy creates a new strategy that enforces AppArmor profile constraints.
  38. func NewStrategy(pspAnnotations map[string]string) Strategy {
  39. var allowedProfiles map[string]bool
  40. if allowed, ok := pspAnnotations[apparmor.AllowedProfilesAnnotationKey]; ok {
  41. profiles := strings.Split(allowed, ",")
  42. allowedProfiles = make(map[string]bool, len(profiles))
  43. for _, p := range profiles {
  44. allowedProfiles[p] = true
  45. }
  46. }
  47. return &strategy{
  48. defaultProfile: pspAnnotations[apparmor.DefaultProfileAnnotationKey],
  49. allowedProfiles: allowedProfiles,
  50. allowedProfilesString: pspAnnotations[apparmor.AllowedProfilesAnnotationKey],
  51. }
  52. }
  53. func (s *strategy) Generate(annotations map[string]string, container *api.Container) (map[string]string, error) {
  54. copy := maps.CopySS(annotations)
  55. if annotations[apparmor.ContainerAnnotationKeyPrefix+container.Name] != "" {
  56. // Profile already set, nothing to do.
  57. return copy, nil
  58. }
  59. if s.defaultProfile == "" {
  60. // No default set.
  61. return copy, nil
  62. }
  63. if copy == nil {
  64. copy = map[string]string{}
  65. }
  66. // Add the default profile.
  67. copy[apparmor.ContainerAnnotationKeyPrefix+container.Name] = s.defaultProfile
  68. return copy, nil
  69. }
  70. func (s *strategy) Validate(pod *api.Pod, container *api.Container) field.ErrorList {
  71. if s.allowedProfiles == nil {
  72. // Unrestricted: allow all.
  73. return nil
  74. }
  75. allErrs := field.ErrorList{}
  76. fieldPath := field.NewPath("pod", "metadata", "annotations").Key(apparmor.ContainerAnnotationKeyPrefix + container.Name)
  77. profile := apparmor.GetProfileNameFromPodAnnotations(pod.Annotations, container.Name)
  78. if profile == "" {
  79. if len(s.allowedProfiles) > 0 {
  80. allErrs = append(allErrs, field.Forbidden(fieldPath, "AppArmor profile must be set"))
  81. return allErrs
  82. }
  83. return nil
  84. }
  85. if !s.allowedProfiles[profile] {
  86. msg := fmt.Sprintf("%s is not an allowed profile. Allowed values: %q", profile, s.allowedProfilesString)
  87. allErrs = append(allErrs, field.Forbidden(fieldPath, msg))
  88. }
  89. return allErrs
  90. }