123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- /*
- Copyright 2016 The Kubernetes Authors.
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
- package selinux
- import (
- "fmt"
- "sort"
- "strings"
- policy "k8s.io/api/policy/v1beta1"
- "k8s.io/apimachinery/pkg/util/validation/field"
- api "k8s.io/kubernetes/pkg/apis/core"
- "k8s.io/kubernetes/pkg/apis/core/v1"
- "k8s.io/kubernetes/pkg/security/podsecuritypolicy/util"
- )
- type mustRunAs struct {
- opts *api.SELinuxOptions
- }
- var _ SELinuxStrategy = &mustRunAs{}
- func NewMustRunAs(options *policy.SELinuxStrategyOptions) (SELinuxStrategy, error) {
- if options == nil {
- return nil, fmt.Errorf("MustRunAs requires SELinuxContextStrategyOptions")
- }
- if options.SELinuxOptions == nil {
- return nil, fmt.Errorf("MustRunAs requires SELinuxOptions")
- }
- internalSELinuxOptions := &api.SELinuxOptions{}
- if err := v1.Convert_v1_SELinuxOptions_To_core_SELinuxOptions(options.SELinuxOptions, internalSELinuxOptions, nil); err != nil {
- return nil, err
- }
- return &mustRunAs{
- opts: internalSELinuxOptions,
- }, nil
- }
- // Generate creates the SELinuxOptions based on constraint rules.
- func (s *mustRunAs) Generate(_ *api.Pod, _ *api.Container) (*api.SELinuxOptions, error) {
- return s.opts, nil
- }
- // Validate ensures that the specified values fall within the range of the strategy.
- func (s *mustRunAs) Validate(fldPath *field.Path, _ *api.Pod, _ *api.Container, seLinux *api.SELinuxOptions) field.ErrorList {
- allErrs := field.ErrorList{}
- if seLinux == nil {
- allErrs = append(allErrs, field.Required(fldPath, ""))
- return allErrs
- }
- if !equalLevels(s.opts.Level, seLinux.Level) {
- detail := fmt.Sprintf("must be %s", s.opts.Level)
- allErrs = append(allErrs, field.Invalid(fldPath.Child("level"), seLinux.Level, detail))
- }
- if seLinux.Role != s.opts.Role {
- detail := fmt.Sprintf("must be %s", s.opts.Role)
- allErrs = append(allErrs, field.Invalid(fldPath.Child("role"), seLinux.Role, detail))
- }
- if seLinux.Type != s.opts.Type {
- detail := fmt.Sprintf("must be %s", s.opts.Type)
- allErrs = append(allErrs, field.Invalid(fldPath.Child("type"), seLinux.Type, detail))
- }
- if seLinux.User != s.opts.User {
- detail := fmt.Sprintf("must be %s", s.opts.User)
- allErrs = append(allErrs, field.Invalid(fldPath.Child("user"), seLinux.User, detail))
- }
- return allErrs
- }
- // equalLevels compares SELinux levels for equality.
- func equalLevels(expected, actual string) bool {
- if expected == actual {
- return true
- }
- // "s0:c6,c0" => [ "s0", "c6,c0" ]
- expectedParts := strings.SplitN(expected, ":", 2)
- actualParts := strings.SplitN(actual, ":", 2)
- // both SELinux levels must be in a format "sX:cY"
- if len(expectedParts) != 2 || len(actualParts) != 2 {
- return false
- }
- if !equalSensitivity(expectedParts[0], actualParts[0]) {
- return false
- }
- if !equalCategories(expectedParts[1], actualParts[1]) {
- return false
- }
- return true
- }
- // equalSensitivity compares sensitivities of the SELinux levels for equality.
- func equalSensitivity(expected, actual string) bool {
- return expected == actual
- }
- // equalCategories compares categories of the SELinux levels for equality.
- func equalCategories(expected, actual string) bool {
- expectedCategories := strings.Split(expected, ",")
- actualCategories := strings.Split(actual, ",")
- sort.Strings(expectedCategories)
- sort.Strings(actualCategories)
- return util.EqualStringSlices(expectedCategories, actualCategories)
- }
|