diff --git a/pkg/apis/extensions/fuzzer/fuzzer.go b/pkg/apis/extensions/fuzzer/fuzzer.go index 006d04f9f9c..fb40167542e 100644 --- a/pkg/apis/extensions/fuzzer/fuzzer.go +++ b/pkg/apis/extensions/fuzzer/fuzzer.go @@ -54,34 +54,6 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} { j.RollingUpdate = &rollingUpdate } }, - func(psp *extensions.PodSecurityPolicySpec, c fuzz.Continue) { - c.FuzzNoCustom(psp) // fuzz self without calling this function again - - runAsUserRules := []extensions.RunAsUserStrategy{ - extensions.RunAsUserStrategyMustRunAsNonRoot, - extensions.RunAsUserStrategyMustRunAs, - extensions.RunAsUserStrategyRunAsAny, - } - psp.RunAsUser.Rule = runAsUserRules[c.Rand.Intn(len(runAsUserRules))] - - seLinuxRules := []extensions.SELinuxStrategy{ - extensions.SELinuxStrategyMustRunAs, - extensions.SELinuxStrategyRunAsAny, - } - psp.SELinux.Rule = seLinuxRules[c.Rand.Intn(len(seLinuxRules))] - - supplementalGroupsRules := []extensions.SupplementalGroupsStrategyType{ - extensions.SupplementalGroupsStrategyRunAsAny, - extensions.SupplementalGroupsStrategyMustRunAs, - } - psp.SupplementalGroups.Rule = supplementalGroupsRules[c.Rand.Intn(len(supplementalGroupsRules))] - - fsGroupRules := []extensions.FSGroupStrategyType{ - extensions.FSGroupStrategyMustRunAs, - extensions.FSGroupStrategyRunAsAny, - } - psp.FSGroup.Rule = fsGroupRules[c.Rand.Intn(len(fsGroupRules))] - }, func(j *extensions.DaemonSetSpec, c fuzz.Continue) { c.FuzzNoCustom(j) // fuzz self without calling this function again rhl := int32(c.Rand.Int31()) diff --git a/pkg/apis/extensions/register.go b/pkg/apis/extensions/register.go index 48137fc6962..84c2071ae66 100644 --- a/pkg/apis/extensions/register.go +++ b/pkg/apis/extensions/register.go @@ -21,6 +21,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/kubernetes/pkg/apis/autoscaling" "k8s.io/kubernetes/pkg/apis/networking" + "k8s.io/kubernetes/pkg/apis/policy" ) // GroupName is the group name use in this package @@ -58,8 +59,8 @@ func addKnownTypes(scheme *runtime.Scheme) error { &IngressList{}, &ReplicaSet{}, &ReplicaSetList{}, - &PodSecurityPolicy{}, - &PodSecurityPolicyList{}, + &policy.PodSecurityPolicy{}, + &policy.PodSecurityPolicyList{}, &autoscaling.Scale{}, &networking.NetworkPolicy{}, &networking.NetworkPolicyList{}, diff --git a/pkg/apis/extensions/types.go b/pkg/apis/extensions/types.go index 21f0361aa4c..a2330c45dd4 100644 --- a/pkg/apis/extensions/types.go +++ b/pkg/apis/extensions/types.go @@ -35,13 +35,6 @@ import ( api "k8s.io/kubernetes/pkg/apis/core" ) -const ( - // SysctlsPodSecurityPolicyAnnotationKey represents the key of a whitelist of - // allowed safe and unsafe sysctls in a pod spec. It's a comma-separated list of plain sysctl - // names or sysctl patterns (which end in *). The string "*" matches all sysctls. - SysctlsPodSecurityPolicyAnnotationKey string = "security.alpha.kubernetes.io/sysctls" -) - // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // Dummy definition @@ -780,271 +773,3 @@ type ReplicaSetCondition struct { // +optional Message string } - -// +genclient -// +genclient:nonNamespaced -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object - -// PodSecurityPolicy governs the ability to make requests that affect the SecurityContext -// that will be applied to a pod and container. -type PodSecurityPolicy struct { - metav1.TypeMeta - // +optional - metav1.ObjectMeta - - // Spec defines the policy enforced. - // +optional - Spec PodSecurityPolicySpec -} - -// PodSecurityPolicySpec defines the policy enforced. -type PodSecurityPolicySpec struct { - // Privileged determines if a pod can request to be run as privileged. - // +optional - Privileged bool - // DefaultAddCapabilities is the default set of capabilities that will be added to the container - // unless the pod spec specifically drops the capability. You may not list a capability in both - // DefaultAddCapabilities and RequiredDropCapabilities. Capabilities added here are implicitly - // allowed, and need not be included in the AllowedCapabilities list. - // +optional - DefaultAddCapabilities []api.Capability - // RequiredDropCapabilities are the capabilities that will be dropped from the container. These - // are required to be dropped and cannot be added. - // +optional - RequiredDropCapabilities []api.Capability - // AllowedCapabilities is a list of capabilities that can be requested to add to the container. - // Capabilities in this field may be added at the pod author's discretion. - // You must not list a capability in both AllowedCapabilities and RequiredDropCapabilities. - // To allow all capabilities you may use '*'. - // +optional - AllowedCapabilities []api.Capability - // Volumes is a white list of allowed volume plugins. Empty indicates that - // no volumes may be used. To allow all volumes you may use '*'. - // +optional - Volumes []FSType - // HostNetwork determines if the policy allows the use of HostNetwork in the pod spec. - // +optional - HostNetwork bool - // HostPorts determines which host port ranges are allowed to be exposed. - // +optional - HostPorts []HostPortRange - // HostPID determines if the policy allows the use of HostPID in the pod spec. - // +optional - HostPID bool - // HostIPC determines if the policy allows the use of HostIPC in the pod spec. - // +optional - HostIPC bool - // SELinux is the strategy that will dictate the allowable labels that may be set. - SELinux SELinuxStrategyOptions - // RunAsUser is the strategy that will dictate the allowable RunAsUser values that may be set. - RunAsUser RunAsUserStrategyOptions - // SupplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext. - SupplementalGroups SupplementalGroupsStrategyOptions - // FSGroup is the strategy that will dictate what fs group is used by the SecurityContext. - FSGroup FSGroupStrategyOptions - // ReadOnlyRootFilesystem when set to true will force containers to run with a read only root file - // system. If the container specifically requests to run with a non-read only root file system - // the PSP should deny the pod. - // If set to false the container may run with a read only root file system if it wishes but it - // will not be forced to. - // +optional - ReadOnlyRootFilesystem bool - // DefaultAllowPrivilegeEscalation controls the default setting for whether a - // process can gain more privileges than its parent process. - // +optional - DefaultAllowPrivilegeEscalation *bool - // AllowPrivilegeEscalation determines if a pod can request to allow - // privilege escalation. If unspecified, defaults to true. - // +optional - AllowPrivilegeEscalation bool - // AllowedHostPaths is a white list of allowed host paths. Empty indicates that all host paths may be used. - // +optional - AllowedHostPaths []AllowedHostPath - // AllowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all - // Flexvolumes may be used. This parameter is effective only when the usage of the Flexvolumes - // is allowed in the "Volumes" field. - // +optional - AllowedFlexVolumes []AllowedFlexVolume -} - -// AllowedHostPath defines the host volume conditions that will be enabled by a policy -// for pods to use. It requires the path prefix to be defined. -type AllowedHostPath struct { - // PathPrefix is the path prefix that the host volume must match. - // PathPrefix does not support `*`. - // Trailing slashes are trimmed when validating the path prefix with a host path. - // - // Examples: - // `/foo` would allow `/foo`, `/foo/` and `/foo/bar` - // `/foo` would not allow `/food` or `/etc/foo` - PathPrefix string -} - -// HostPortRange defines a range of host ports that will be enabled by a policy -// for pods to use. It requires both the start and end to be defined. -type HostPortRange struct { - // Min is the start of the range, inclusive. - Min int32 - // Max is the end of the range, inclusive. - Max int32 -} - -// AllowAllCapabilities can be used as a value for the PodSecurityPolicy.AllowAllCapabilities -// field and means that any capabilities are allowed to be requested. -var AllowAllCapabilities api.Capability = "*" - -// FSType gives strong typing to different file systems that are used by volumes. -type FSType string - -var ( - AzureFile FSType = "azureFile" - Flocker FSType = "flocker" - FlexVolume FSType = "flexVolume" - HostPath FSType = "hostPath" - EmptyDir FSType = "emptyDir" - GCEPersistentDisk FSType = "gcePersistentDisk" - AWSElasticBlockStore FSType = "awsElasticBlockStore" - GitRepo FSType = "gitRepo" - Secret FSType = "secret" - NFS FSType = "nfs" - ISCSI FSType = "iscsi" - Glusterfs FSType = "glusterfs" - PersistentVolumeClaim FSType = "persistentVolumeClaim" - RBD FSType = "rbd" - Cinder FSType = "cinder" - CephFS FSType = "cephFS" - DownwardAPI FSType = "downwardAPI" - FC FSType = "fc" - ConfigMap FSType = "configMap" - VsphereVolume FSType = "vsphereVolume" - Quobyte FSType = "quobyte" - AzureDisk FSType = "azureDisk" - PhotonPersistentDisk FSType = "photonPersistentDisk" - StorageOS FSType = "storageos" - Projected FSType = "projected" - PortworxVolume FSType = "portworxVolume" - ScaleIO FSType = "scaleIO" - CSI FSType = "csi" - All FSType = "*" -) - -// AllowedFlexVolume represents a single Flexvolume that is allowed to be used. -type AllowedFlexVolume struct { - // Driver is the name of the Flexvolume driver. - Driver string -} - -// SELinuxStrategyOptions defines the strategy type and any options used to create the strategy. -type SELinuxStrategyOptions struct { - // Rule is the strategy that will dictate the allowable labels that may be set. - Rule SELinuxStrategy - // SELinuxOptions required to run as; required for MustRunAs - // More info: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#selinux - // +optional - SELinuxOptions *api.SELinuxOptions -} - -// SELinuxStrategy denotes strategy types for generating SELinux options for a -// Security. -type SELinuxStrategy string - -const ( - // SELinuxStrategyMustRunAs means that container must have SELinux labels of X applied. - SELinuxStrategyMustRunAs SELinuxStrategy = "MustRunAs" - // SELinuxStrategyRunAsAny means that container may make requests for any SELinux context labels. - SELinuxStrategyRunAsAny SELinuxStrategy = "RunAsAny" -) - -// RunAsUserStrategyOptions defines the strategy type and any options used to create the strategy. -type RunAsUserStrategyOptions struct { - // Rule is the strategy that will dictate the allowable RunAsUser values that may be set. - Rule RunAsUserStrategy - // Ranges are the allowed ranges of uids that may be used. If you would like to force a single uid - // then supply a single range with the same start and end. Required for MustRunAs. - // +optional - Ranges []UserIDRange -} - -// UserIDRange provides a min/max of an allowed range of UserIDs. -type UserIDRange struct { - // Min is the start of the range, inclusive. - Min int64 - // Max is the end of the range, inclusive. - Max int64 -} - -// GroupIDRange provides a min/max of an allowed range of GroupIDs. -type GroupIDRange struct { - // Min is the start of the range, inclusive. - Min int64 - // Max is the end of the range, inclusive. - Max int64 -} - -// RunAsUserStrategy denotes strategy types for generating RunAsUser values for a -// SecurityContext. -type RunAsUserStrategy string - -const ( - // RunAsUserStrategyMustRunAs means that container must run as a particular uid. - RunAsUserStrategyMustRunAs RunAsUserStrategy = "MustRunAs" - // RunAsUserStrategyMustRunAsNonRoot means that container must run as a non-root uid - RunAsUserStrategyMustRunAsNonRoot RunAsUserStrategy = "MustRunAsNonRoot" - // RunAsUserStrategyRunAsAny means that container may make requests for any uid. - RunAsUserStrategyRunAsAny RunAsUserStrategy = "RunAsAny" -) - -// FSGroupStrategyOptions defines the strategy type and options used to create the strategy. -type FSGroupStrategyOptions struct { - // Rule is the strategy that will dictate what FSGroup is used in the SecurityContext. - // +optional - Rule FSGroupStrategyType - // Ranges are the allowed ranges of fs groups. If you would like to force a single - // fs group then supply a single range with the same start and end. Required for MustRunAs. - // +optional - Ranges []GroupIDRange -} - -// FSGroupStrategyType denotes strategy types for generating FSGroup values for a -// SecurityContext -type FSGroupStrategyType string - -const ( - // FSGroupStrategyMustRunAs means that container must have FSGroup of X applied. - FSGroupStrategyMustRunAs FSGroupStrategyType = "MustRunAs" - // FSGroupStrategyRunAsAny means that container may make requests for any FSGroup labels. - FSGroupStrategyRunAsAny FSGroupStrategyType = "RunAsAny" -) - -// SupplementalGroupsStrategyOptions defines the strategy type and options used to create the strategy. -type SupplementalGroupsStrategyOptions struct { - // Rule is the strategy that will dictate what supplemental groups is used in the SecurityContext. - // +optional - Rule SupplementalGroupsStrategyType - // Ranges are the allowed ranges of supplemental groups. If you would like to force a single - // supplemental group then supply a single range with the same start and end. Required for MustRunAs. - // +optional - Ranges []GroupIDRange -} - -// SupplementalGroupsStrategyType denotes strategy types for determining valid supplemental -// groups for a SecurityContext. -type SupplementalGroupsStrategyType string - -const ( - // SupplementalGroupsStrategyMustRunAs means that container must run as a particular gid. - SupplementalGroupsStrategyMustRunAs SupplementalGroupsStrategyType = "MustRunAs" - // SupplementalGroupsStrategyRunAsAny means that container may make requests for any gid. - SupplementalGroupsStrategyRunAsAny SupplementalGroupsStrategyType = "RunAsAny" -) - -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object - -// PodSecurityPolicyList is a list of PodSecurityPolicy objects. -type PodSecurityPolicyList struct { - metav1.TypeMeta - // +optional - metav1.ListMeta - - Items []PodSecurityPolicy -} diff --git a/pkg/apis/extensions/v1beta1/conversion.go b/pkg/apis/extensions/v1beta1/conversion.go index d236a415e13..ce7b78ae20b 100644 --- a/pkg/apis/extensions/v1beta1/conversion.go +++ b/pkg/apis/extensions/v1beta1/conversion.go @@ -61,7 +61,6 @@ func addConversionFuncs(scheme *runtime.Scheme) error { Convert_networking_NetworkPolicyPort_To_v1beta1_NetworkPolicyPort, Convert_v1beta1_NetworkPolicySpec_To_networking_NetworkPolicySpec, Convert_networking_NetworkPolicySpec_To_v1beta1_NetworkPolicySpec, - Convert_extensions_PodSecurityPolicySpec_To_v1beta1_PodSecurityPolicySpec, Convert_v1beta1_IPBlock_To_networking_IPBlock, Convert_networking_IPBlock_To_v1beta1_IPBlock, Convert_networking_NetworkPolicyEgressRule_To_v1beta1_NetworkPolicyEgressRule, @@ -503,7 +502,3 @@ func Convert_networking_NetworkPolicyList_To_v1beta1_NetworkPolicyList(in *netwo } return nil } - -func Convert_extensions_PodSecurityPolicySpec_To_v1beta1_PodSecurityPolicySpec(in *extensions.PodSecurityPolicySpec, out *extensionsv1beta1.PodSecurityPolicySpec, s conversion.Scope) error { - return autoConvert_extensions_PodSecurityPolicySpec_To_v1beta1_PodSecurityPolicySpec(in, out, s) -} diff --git a/pkg/apis/extensions/v1beta1/doc.go b/pkg/apis/extensions/v1beta1/doc.go index da219b9d221..96f579d1eba 100644 --- a/pkg/apis/extensions/v1beta1/doc.go +++ b/pkg/apis/extensions/v1beta1/doc.go @@ -14,6 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ +// +k8s:conversion-gen=k8s.io/kubernetes/pkg/apis/policy // +k8s:conversion-gen=k8s.io/kubernetes/pkg/apis/extensions // +k8s:conversion-gen=k8s.io/kubernetes/pkg/apis/autoscaling // +k8s:conversion-gen-external-types=k8s.io/api/extensions/v1beta1 diff --git a/pkg/apis/extensions/validation/validation.go b/pkg/apis/extensions/validation/validation.go index a1f9aee6dc4..3f0d37470a6 100644 --- a/pkg/apis/extensions/validation/validation.go +++ b/pkg/apis/extensions/validation/validation.go @@ -17,10 +17,7 @@ limitations under the License. package validation import ( - "fmt" "net" - - "path/filepath" "regexp" "strconv" "strings" @@ -30,15 +27,11 @@ import ( unversionedvalidation "k8s.io/apimachinery/pkg/apis/meta/v1/validation" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/util/intstr" - "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/validation" "k8s.io/apimachinery/pkg/util/validation/field" api "k8s.io/kubernetes/pkg/apis/core" apivalidation "k8s.io/kubernetes/pkg/apis/core/validation" "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/security/apparmor" - "k8s.io/kubernetes/pkg/security/podsecuritypolicy/seccomp" - psputil "k8s.io/kubernetes/pkg/security/podsecuritypolicy/util" ) // ValidateDaemonSet tests if required fields in the DaemonSet are set. @@ -613,299 +606,3 @@ func ValidatePodTemplateSpecForReplicaSet(template *api.PodTemplateSpec, selecto } return allErrs } - -// ValidatePodSecurityPolicyName can be used to check whether the given -// pod security policy name is valid. -// Prefix indicates this name will be used as part of generation, in which case -// trailing dashes are allowed. -var ValidatePodSecurityPolicyName = apivalidation.NameIsDNSSubdomain - -func ValidatePodSecurityPolicy(psp *extensions.PodSecurityPolicy) field.ErrorList { - allErrs := field.ErrorList{} - allErrs = append(allErrs, apivalidation.ValidateObjectMeta(&psp.ObjectMeta, false, ValidatePodSecurityPolicyName, field.NewPath("metadata"))...) - allErrs = append(allErrs, ValidatePodSecurityPolicySpecificAnnotations(psp.Annotations, field.NewPath("metadata").Child("annotations"))...) - allErrs = append(allErrs, ValidatePodSecurityPolicySpec(&psp.Spec, field.NewPath("spec"))...) - return allErrs -} - -func ValidatePodSecurityPolicySpec(spec *extensions.PodSecurityPolicySpec, fldPath *field.Path) field.ErrorList { - allErrs := field.ErrorList{} - - allErrs = append(allErrs, validatePSPRunAsUser(fldPath.Child("runAsUser"), &spec.RunAsUser)...) - allErrs = append(allErrs, validatePSPSELinux(fldPath.Child("seLinux"), &spec.SELinux)...) - allErrs = append(allErrs, validatePSPSupplementalGroup(fldPath.Child("supplementalGroups"), &spec.SupplementalGroups)...) - allErrs = append(allErrs, validatePSPFSGroup(fldPath.Child("fsGroup"), &spec.FSGroup)...) - allErrs = append(allErrs, validatePodSecurityPolicyVolumes(fldPath, spec.Volumes)...) - if len(spec.RequiredDropCapabilities) > 0 && hasCap(extensions.AllowAllCapabilities, spec.AllowedCapabilities) { - allErrs = append(allErrs, field.Invalid(field.NewPath("requiredDropCapabilities"), spec.RequiredDropCapabilities, - "must be empty when all capabilities are allowed by a wildcard")) - } - allErrs = append(allErrs, validatePSPCapsAgainstDrops(spec.RequiredDropCapabilities, spec.DefaultAddCapabilities, field.NewPath("defaultAddCapabilities"))...) - allErrs = append(allErrs, validatePSPCapsAgainstDrops(spec.RequiredDropCapabilities, spec.AllowedCapabilities, field.NewPath("allowedCapabilities"))...) - allErrs = append(allErrs, validatePSPDefaultAllowPrivilegeEscalation(fldPath.Child("defaultAllowPrivilegeEscalation"), spec.DefaultAllowPrivilegeEscalation, spec.AllowPrivilegeEscalation)...) - allErrs = append(allErrs, validatePSPAllowedHostPaths(fldPath.Child("allowedHostPaths"), spec.AllowedHostPaths)...) - allErrs = append(allErrs, validatePSPAllowedFlexVolumes(fldPath.Child("allowedFlexVolumes"), spec.AllowedFlexVolumes)...) - - return allErrs -} - -func ValidatePodSecurityPolicySpecificAnnotations(annotations map[string]string, fldPath *field.Path) field.ErrorList { - allErrs := field.ErrorList{} - - if p := annotations[apparmor.DefaultProfileAnnotationKey]; p != "" { - if err := apparmor.ValidateProfileFormat(p); err != nil { - allErrs = append(allErrs, field.Invalid(fldPath.Key(apparmor.DefaultProfileAnnotationKey), p, err.Error())) - } - } - if allowed := annotations[apparmor.AllowedProfilesAnnotationKey]; allowed != "" { - for _, p := range strings.Split(allowed, ",") { - if err := apparmor.ValidateProfileFormat(p); err != nil { - allErrs = append(allErrs, field.Invalid(fldPath.Key(apparmor.AllowedProfilesAnnotationKey), allowed, err.Error())) - } - } - } - - sysctlAnnotation := annotations[extensions.SysctlsPodSecurityPolicyAnnotationKey] - sysctlFldPath := fldPath.Key(extensions.SysctlsPodSecurityPolicyAnnotationKey) - sysctls, err := extensions.SysctlsFromPodSecurityPolicyAnnotation(sysctlAnnotation) - if err != nil { - allErrs = append(allErrs, field.Invalid(sysctlFldPath, sysctlAnnotation, err.Error())) - } else { - allErrs = append(allErrs, validatePodSecurityPolicySysctls(sysctlFldPath, sysctls)...) - } - - if p := annotations[seccomp.DefaultProfileAnnotationKey]; p != "" { - allErrs = append(allErrs, apivalidation.ValidateSeccompProfile(p, fldPath.Key(seccomp.DefaultProfileAnnotationKey))...) - } - if allowed := annotations[seccomp.AllowedProfilesAnnotationKey]; allowed != "" { - for _, p := range strings.Split(allowed, ",") { - if p == seccomp.AllowAny { - continue - } - allErrs = append(allErrs, apivalidation.ValidateSeccompProfile(p, fldPath.Key(seccomp.AllowedProfilesAnnotationKey))...) - } - } - return allErrs -} - -// validatePSPAllowedHostPaths makes sure all allowed host paths follow: -// 1. path prefix is required -// 2. path prefix does not have any element which is ".." -func validatePSPAllowedHostPaths(fldPath *field.Path, allowedHostPaths []extensions.AllowedHostPath) field.ErrorList { - allErrs := field.ErrorList{} - - for i, target := range allowedHostPaths { - if target.PathPrefix == "" { - allErrs = append(allErrs, field.Required(fldPath.Index(i), "is required")) - break - } - parts := strings.Split(filepath.ToSlash(target.PathPrefix), "/") - for _, item := range parts { - if item == ".." { - allErrs = append(allErrs, field.Invalid(fldPath.Index(i), target.PathPrefix, "must not contain '..'")) - break // even for `../../..`, one error is sufficient to make the point - } - } - } - - return allErrs -} - -// validatePSPAllowedFlexVolumes -func validatePSPAllowedFlexVolumes(fldPath *field.Path, flexVolumes []extensions.AllowedFlexVolume) field.ErrorList { - allErrs := field.ErrorList{} - if len(flexVolumes) > 0 { - for idx, fv := range flexVolumes { - if len(fv.Driver) == 0 { - allErrs = append(allErrs, field.Required(fldPath.Child("allowedFlexVolumes").Index(idx).Child("driver"), - "must specify a driver")) - } - } - } - return allErrs -} - -// validatePSPSELinux validates the SELinux fields of PodSecurityPolicy. -func validatePSPSELinux(fldPath *field.Path, seLinux *extensions.SELinuxStrategyOptions) field.ErrorList { - allErrs := field.ErrorList{} - - // ensure the selinux strategy has a valid rule - supportedSELinuxRules := sets.NewString(string(extensions.SELinuxStrategyMustRunAs), - string(extensions.SELinuxStrategyRunAsAny)) - if !supportedSELinuxRules.Has(string(seLinux.Rule)) { - allErrs = append(allErrs, field.NotSupported(fldPath.Child("rule"), seLinux.Rule, supportedSELinuxRules.List())) - } - - return allErrs -} - -// validatePSPRunAsUser validates the RunAsUser fields of PodSecurityPolicy. -func validatePSPRunAsUser(fldPath *field.Path, runAsUser *extensions.RunAsUserStrategyOptions) field.ErrorList { - allErrs := field.ErrorList{} - - // ensure the user strategy has a valid rule - supportedRunAsUserRules := sets.NewString(string(extensions.RunAsUserStrategyMustRunAs), - string(extensions.RunAsUserStrategyMustRunAsNonRoot), - string(extensions.RunAsUserStrategyRunAsAny)) - if !supportedRunAsUserRules.Has(string(runAsUser.Rule)) { - allErrs = append(allErrs, field.NotSupported(fldPath.Child("rule"), runAsUser.Rule, supportedRunAsUserRules.List())) - } - - // validate range settings - for idx, rng := range runAsUser.Ranges { - allErrs = append(allErrs, validateUserIDRange(fldPath.Child("ranges").Index(idx), rng)...) - } - - return allErrs -} - -// validatePSPFSGroup validates the FSGroupStrategyOptions fields of the PodSecurityPolicy. -func validatePSPFSGroup(fldPath *field.Path, groupOptions *extensions.FSGroupStrategyOptions) field.ErrorList { - allErrs := field.ErrorList{} - - supportedRules := sets.NewString( - string(extensions.FSGroupStrategyMustRunAs), - string(extensions.FSGroupStrategyRunAsAny), - ) - if !supportedRules.Has(string(groupOptions.Rule)) { - allErrs = append(allErrs, field.NotSupported(fldPath.Child("rule"), groupOptions.Rule, supportedRules.List())) - } - - for idx, rng := range groupOptions.Ranges { - allErrs = append(allErrs, validateGroupIDRange(fldPath.Child("ranges").Index(idx), rng)...) - } - return allErrs -} - -// validatePSPSupplementalGroup validates the SupplementalGroupsStrategyOptions fields of the PodSecurityPolicy. -func validatePSPSupplementalGroup(fldPath *field.Path, groupOptions *extensions.SupplementalGroupsStrategyOptions) field.ErrorList { - allErrs := field.ErrorList{} - - supportedRules := sets.NewString( - string(extensions.SupplementalGroupsStrategyRunAsAny), - string(extensions.SupplementalGroupsStrategyMustRunAs), - ) - if !supportedRules.Has(string(groupOptions.Rule)) { - allErrs = append(allErrs, field.NotSupported(fldPath.Child("rule"), groupOptions.Rule, supportedRules.List())) - } - - for idx, rng := range groupOptions.Ranges { - allErrs = append(allErrs, validateGroupIDRange(fldPath.Child("ranges").Index(idx), rng)...) - } - return allErrs -} - -// validatePodSecurityPolicyVolumes validates the volume fields of PodSecurityPolicy. -func validatePodSecurityPolicyVolumes(fldPath *field.Path, volumes []extensions.FSType) field.ErrorList { - allErrs := field.ErrorList{} - allowed := psputil.GetAllFSTypesAsSet() - // add in the * value since that is a pseudo type that is not included by default - allowed.Insert(string(extensions.All)) - for _, v := range volumes { - if !allowed.Has(string(v)) { - allErrs = append(allErrs, field.NotSupported(fldPath.Child("volumes"), v, allowed.List())) - } - } - return allErrs -} - -// validatePSPDefaultAllowPrivilegeEscalation validates the DefaultAllowPrivilegeEscalation field against the AllowPrivilegeEscalation field of a PodSecurityPolicy. -func validatePSPDefaultAllowPrivilegeEscalation(fldPath *field.Path, defaultAllowPrivilegeEscalation *bool, allowPrivilegeEscalation bool) field.ErrorList { - allErrs := field.ErrorList{} - if defaultAllowPrivilegeEscalation != nil && *defaultAllowPrivilegeEscalation && !allowPrivilegeEscalation { - allErrs = append(allErrs, field.Invalid(fldPath, defaultAllowPrivilegeEscalation, "Cannot set DefaultAllowPrivilegeEscalation to true without also setting AllowPrivilegeEscalation to true")) - } - - return allErrs -} - -const sysctlPatternSegmentFmt string = "([a-z0-9][-_a-z0-9]*)?[a-z0-9*]" -const SysctlPatternFmt string = "(" + apivalidation.SysctlSegmentFmt + "\\.)*" + sysctlPatternSegmentFmt - -var sysctlPatternRegexp = regexp.MustCompile("^" + SysctlPatternFmt + "$") - -func IsValidSysctlPattern(name string) bool { - if len(name) > apivalidation.SysctlMaxLength { - return false - } - return sysctlPatternRegexp.MatchString(name) -} - -// validatePodSecurityPolicySysctls validates the sysctls fields of PodSecurityPolicy. -func validatePodSecurityPolicySysctls(fldPath *field.Path, sysctls []string) field.ErrorList { - allErrs := field.ErrorList{} - for i, s := range sysctls { - if !IsValidSysctlPattern(string(s)) { - allErrs = append( - allErrs, - field.Invalid(fldPath.Index(i), sysctls[i], fmt.Sprintf("must have at most %d characters and match regex %s", - apivalidation.SysctlMaxLength, - SysctlPatternFmt, - )), - ) - } - } - - return allErrs -} - -func validateUserIDRange(fldPath *field.Path, rng extensions.UserIDRange) field.ErrorList { - return validateIDRanges(fldPath, int64(rng.Min), int64(rng.Max)) -} - -func validateGroupIDRange(fldPath *field.Path, rng extensions.GroupIDRange) field.ErrorList { - return validateIDRanges(fldPath, int64(rng.Min), int64(rng.Max)) -} - -// validateIDRanges ensures the range is valid. -func validateIDRanges(fldPath *field.Path, min, max int64) field.ErrorList { - allErrs := field.ErrorList{} - - // if 0 <= Min <= Max then we do not need to validate max. It is always greater than or - // equal to 0 and Min. - if min < 0 { - allErrs = append(allErrs, field.Invalid(fldPath.Child("min"), min, "min cannot be negative")) - } - if max < 0 { - allErrs = append(allErrs, field.Invalid(fldPath.Child("max"), max, "max cannot be negative")) - } - if min > max { - allErrs = append(allErrs, field.Invalid(fldPath.Child("min"), min, "min cannot be greater than max")) - } - - return allErrs -} - -// validatePSPCapsAgainstDrops ensures an allowed cap is not listed in the required drops. -func validatePSPCapsAgainstDrops(requiredDrops []api.Capability, capsToCheck []api.Capability, fldPath *field.Path) field.ErrorList { - allErrs := field.ErrorList{} - if requiredDrops == nil { - return allErrs - } - for _, cap := range capsToCheck { - if hasCap(cap, requiredDrops) { - allErrs = append(allErrs, field.Invalid(fldPath, cap, - fmt.Sprintf("capability is listed in %s and requiredDropCapabilities", fldPath.String()))) - } - } - return allErrs -} - -// hasCap checks for needle in haystack. -func hasCap(needle api.Capability, haystack []api.Capability) bool { - for _, c := range haystack { - if needle == c { - return true - } - } - return false -} - -// ValidatePodSecurityPolicyUpdate validates a PSP for updates. -func ValidatePodSecurityPolicyUpdate(old *extensions.PodSecurityPolicy, new *extensions.PodSecurityPolicy) field.ErrorList { - allErrs := field.ErrorList{} - allErrs = append(allErrs, apivalidation.ValidateObjectMetaUpdate(&new.ObjectMeta, &old.ObjectMeta, field.NewPath("metadata"))...) - allErrs = append(allErrs, ValidatePodSecurityPolicySpecificAnnotations(new.Annotations, field.NewPath("metadata").Child("annotations"))...) - allErrs = append(allErrs, ValidatePodSecurityPolicySpec(&new.Spec, field.NewPath("spec"))...) - return allErrs -} diff --git a/pkg/apis/extensions/validation/validation_test.go b/pkg/apis/extensions/validation/validation_test.go index 0e325d35a6e..cd56129a9e3 100644 --- a/pkg/apis/extensions/validation/validation_test.go +++ b/pkg/apis/extensions/validation/validation_test.go @@ -28,9 +28,6 @@ import ( "k8s.io/apimachinery/pkg/util/validation/field" api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/security/apparmor" - "k8s.io/kubernetes/pkg/security/podsecuritypolicy/seccomp" - psputil "k8s.io/kubernetes/pkg/security/podsecuritypolicy/util" ) func TestValidateDaemonSetStatusUpdate(t *testing.T) { @@ -2317,527 +2314,3 @@ func TestValidateReplicaSet(t *testing.T) { } } } - -func TestValidatePodSecurityPolicy(t *testing.T) { - validPSP := func() *extensions.PodSecurityPolicy { - return &extensions.PodSecurityPolicy{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - Annotations: map[string]string{}, - }, - Spec: extensions.PodSecurityPolicySpec{ - SELinux: extensions.SELinuxStrategyOptions{ - Rule: extensions.SELinuxStrategyRunAsAny, - }, - RunAsUser: extensions.RunAsUserStrategyOptions{ - Rule: extensions.RunAsUserStrategyRunAsAny, - }, - FSGroup: extensions.FSGroupStrategyOptions{ - Rule: extensions.FSGroupStrategyRunAsAny, - }, - SupplementalGroups: extensions.SupplementalGroupsStrategyOptions{ - Rule: extensions.SupplementalGroupsStrategyRunAsAny, - }, - AllowedHostPaths: []extensions.AllowedHostPath{ - {PathPrefix: "/foo/bar"}, - {PathPrefix: "/baz/"}, - }, - }, - } - } - - noUserOptions := validPSP() - noUserOptions.Spec.RunAsUser.Rule = "" - - noSELinuxOptions := validPSP() - noSELinuxOptions.Spec.SELinux.Rule = "" - - invalidUserStratType := validPSP() - invalidUserStratType.Spec.RunAsUser.Rule = "invalid" - - invalidSELinuxStratType := validPSP() - invalidSELinuxStratType.Spec.SELinux.Rule = "invalid" - - invalidUIDPSP := validPSP() - invalidUIDPSP.Spec.RunAsUser.Rule = extensions.RunAsUserStrategyMustRunAs - invalidUIDPSP.Spec.RunAsUser.Ranges = []extensions.UserIDRange{{Min: -1, Max: 1}} - - missingObjectMetaName := validPSP() - missingObjectMetaName.ObjectMeta.Name = "" - - noFSGroupOptions := validPSP() - noFSGroupOptions.Spec.FSGroup.Rule = "" - - invalidFSGroupStratType := validPSP() - invalidFSGroupStratType.Spec.FSGroup.Rule = "invalid" - - noSupplementalGroupsOptions := validPSP() - noSupplementalGroupsOptions.Spec.SupplementalGroups.Rule = "" - - invalidSupGroupStratType := validPSP() - invalidSupGroupStratType.Spec.SupplementalGroups.Rule = "invalid" - - invalidRangeMinGreaterThanMax := validPSP() - invalidRangeMinGreaterThanMax.Spec.FSGroup.Ranges = []extensions.GroupIDRange{ - {Min: 2, Max: 1}, - } - - invalidRangeNegativeMin := validPSP() - invalidRangeNegativeMin.Spec.FSGroup.Ranges = []extensions.GroupIDRange{ - {Min: -1, Max: 10}, - } - - invalidRangeNegativeMax := validPSP() - invalidRangeNegativeMax.Spec.FSGroup.Ranges = []extensions.GroupIDRange{ - {Min: 1, Max: -10}, - } - - wildcardAllowedCapAndRequiredDrop := validPSP() - wildcardAllowedCapAndRequiredDrop.Spec.RequiredDropCapabilities = []api.Capability{"foo"} - wildcardAllowedCapAndRequiredDrop.Spec.AllowedCapabilities = []api.Capability{extensions.AllowAllCapabilities} - - requiredCapAddAndDrop := validPSP() - requiredCapAddAndDrop.Spec.DefaultAddCapabilities = []api.Capability{"foo"} - requiredCapAddAndDrop.Spec.RequiredDropCapabilities = []api.Capability{"foo"} - - allowedCapListedInRequiredDrop := validPSP() - allowedCapListedInRequiredDrop.Spec.RequiredDropCapabilities = []api.Capability{"foo"} - allowedCapListedInRequiredDrop.Spec.AllowedCapabilities = []api.Capability{"foo"} - - invalidAppArmorDefault := validPSP() - invalidAppArmorDefault.Annotations = map[string]string{ - apparmor.DefaultProfileAnnotationKey: "not-good", - } - invalidAppArmorAllowed := validPSP() - invalidAppArmorAllowed.Annotations = map[string]string{ - apparmor.AllowedProfilesAnnotationKey: apparmor.ProfileRuntimeDefault + ",not-good", - } - - invalidSysctlPattern := validPSP() - invalidSysctlPattern.Annotations[extensions.SysctlsPodSecurityPolicyAnnotationKey] = "a.*.b" - - invalidSeccompDefault := validPSP() - invalidSeccompDefault.Annotations = map[string]string{ - seccomp.DefaultProfileAnnotationKey: "not-good", - } - invalidSeccompAllowAnyDefault := validPSP() - invalidSeccompAllowAnyDefault.Annotations = map[string]string{ - seccomp.DefaultProfileAnnotationKey: "*", - } - invalidSeccompAllowed := validPSP() - invalidSeccompAllowed.Annotations = map[string]string{ - seccomp.AllowedProfilesAnnotationKey: "docker/default,not-good", - } - - invalidAllowedHostPathMissingPath := validPSP() - invalidAllowedHostPathMissingPath.Spec.AllowedHostPaths = []extensions.AllowedHostPath{ - {PathPrefix: ""}, - } - - invalidAllowedHostPathBacksteps := validPSP() - invalidAllowedHostPathBacksteps.Spec.AllowedHostPaths = []extensions.AllowedHostPath{ - {PathPrefix: "/dont/allow/backsteps/.."}, - } - - invalidDefaultAllowPrivilegeEscalation := validPSP() - pe := true - invalidDefaultAllowPrivilegeEscalation.Spec.DefaultAllowPrivilegeEscalation = &pe - - emptyFlexDriver := validPSP() - emptyFlexDriver.Spec.Volumes = []extensions.FSType{extensions.FlexVolume} - emptyFlexDriver.Spec.AllowedFlexVolumes = []extensions.AllowedFlexVolume{{}} - - nonEmptyFlexVolumes := validPSP() - nonEmptyFlexVolumes.Spec.AllowedFlexVolumes = []extensions.AllowedFlexVolume{{Driver: "example/driver"}} - - type testCase struct { - psp *extensions.PodSecurityPolicy - errorType field.ErrorType - errorDetail string - } - errorCases := map[string]testCase{ - "no user options": { - psp: noUserOptions, - errorType: field.ErrorTypeNotSupported, - errorDetail: `supported values: "MustRunAs", "MustRunAsNonRoot", "RunAsAny"`, - }, - "no selinux options": { - psp: noSELinuxOptions, - errorType: field.ErrorTypeNotSupported, - errorDetail: `supported values: "MustRunAs", "RunAsAny"`, - }, - "no fsgroup options": { - psp: noFSGroupOptions, - errorType: field.ErrorTypeNotSupported, - errorDetail: `supported values: "MustRunAs", "RunAsAny"`, - }, - "no sup group options": { - psp: noSupplementalGroupsOptions, - errorType: field.ErrorTypeNotSupported, - errorDetail: `supported values: "MustRunAs", "RunAsAny"`, - }, - "invalid user strategy type": { - psp: invalidUserStratType, - errorType: field.ErrorTypeNotSupported, - errorDetail: `supported values: "MustRunAs", "MustRunAsNonRoot", "RunAsAny"`, - }, - "invalid selinux strategy type": { - psp: invalidSELinuxStratType, - errorType: field.ErrorTypeNotSupported, - errorDetail: `supported values: "MustRunAs", "RunAsAny"`, - }, - "invalid sup group strategy type": { - psp: invalidSupGroupStratType, - errorType: field.ErrorTypeNotSupported, - errorDetail: `supported values: "MustRunAs", "RunAsAny"`, - }, - "invalid fs group strategy type": { - psp: invalidFSGroupStratType, - errorType: field.ErrorTypeNotSupported, - errorDetail: `supported values: "MustRunAs", "RunAsAny"`, - }, - "invalid uid": { - psp: invalidUIDPSP, - errorType: field.ErrorTypeInvalid, - errorDetail: "min cannot be negative", - }, - "missing object meta name": { - psp: missingObjectMetaName, - errorType: field.ErrorTypeRequired, - errorDetail: "name or generateName is required", - }, - "invalid range min greater than max": { - psp: invalidRangeMinGreaterThanMax, - errorType: field.ErrorTypeInvalid, - errorDetail: "min cannot be greater than max", - }, - "invalid range negative min": { - psp: invalidRangeNegativeMin, - errorType: field.ErrorTypeInvalid, - errorDetail: "min cannot be negative", - }, - "invalid range negative max": { - psp: invalidRangeNegativeMax, - errorType: field.ErrorTypeInvalid, - errorDetail: "max cannot be negative", - }, - "non-empty required drops and all caps are allowed by a wildcard": { - psp: wildcardAllowedCapAndRequiredDrop, - errorType: field.ErrorTypeInvalid, - errorDetail: "must be empty when all capabilities are allowed by a wildcard", - }, - "invalid required caps": { - psp: requiredCapAddAndDrop, - errorType: field.ErrorTypeInvalid, - errorDetail: "capability is listed in defaultAddCapabilities and requiredDropCapabilities", - }, - "allowed cap listed in required drops": { - psp: allowedCapListedInRequiredDrop, - errorType: field.ErrorTypeInvalid, - errorDetail: "capability is listed in allowedCapabilities and requiredDropCapabilities", - }, - "invalid AppArmor default profile": { - psp: invalidAppArmorDefault, - errorType: field.ErrorTypeInvalid, - errorDetail: "invalid AppArmor profile name: \"not-good\"", - }, - "invalid AppArmor allowed profile": { - psp: invalidAppArmorAllowed, - errorType: field.ErrorTypeInvalid, - errorDetail: "invalid AppArmor profile name: \"not-good\"", - }, - "invalid sysctl pattern": { - psp: invalidSysctlPattern, - errorType: field.ErrorTypeInvalid, - errorDetail: fmt.Sprintf("must have at most 253 characters and match regex %s", SysctlPatternFmt), - }, - "invalid seccomp default profile": { - psp: invalidSeccompDefault, - errorType: field.ErrorTypeInvalid, - errorDetail: "must be a valid seccomp profile", - }, - "invalid seccomp allow any default profile": { - psp: invalidSeccompAllowAnyDefault, - errorType: field.ErrorTypeInvalid, - errorDetail: "must be a valid seccomp profile", - }, - "invalid seccomp allowed profile": { - psp: invalidSeccompAllowed, - errorType: field.ErrorTypeInvalid, - errorDetail: "must be a valid seccomp profile", - }, - "invalid defaultAllowPrivilegeEscalation": { - psp: invalidDefaultAllowPrivilegeEscalation, - errorType: field.ErrorTypeInvalid, - errorDetail: "Cannot set DefaultAllowPrivilegeEscalation to true without also setting AllowPrivilegeEscalation to true", - }, - "invalid allowed host path empty path": { - psp: invalidAllowedHostPathMissingPath, - errorType: field.ErrorTypeRequired, - errorDetail: "is required", - }, - "invalid allowed host path with backsteps": { - psp: invalidAllowedHostPathBacksteps, - errorType: field.ErrorTypeInvalid, - errorDetail: "must not contain '..'", - }, - "empty flex volume driver": { - psp: emptyFlexDriver, - errorType: field.ErrorTypeRequired, - errorDetail: "must specify a driver", - }, - } - - for k, v := range errorCases { - errs := ValidatePodSecurityPolicy(v.psp) - if len(errs) == 0 { - t.Errorf("%s expected errors but got none", k) - continue - } - if errs[0].Type != v.errorType { - t.Errorf("[%s] received an unexpected error type. Expected: '%s' got: '%s'", k, v.errorType, errs[0].Type) - } - if errs[0].Detail != v.errorDetail { - t.Errorf("[%s] received an unexpected error detail. Expected '%s' got: '%s'", k, v.errorDetail, errs[0].Detail) - } - } - - // Update error is different for 'missing object meta name'. - errorCases["missing object meta name"] = testCase{ - psp: errorCases["missing object meta name"].psp, - errorType: field.ErrorTypeInvalid, - errorDetail: "field is immutable", - } - - // Should not be able to update to an invalid policy. - for k, v := range errorCases { - v.psp.ResourceVersion = "444" // Required for updates. - errs := ValidatePodSecurityPolicyUpdate(validPSP(), v.psp) - if len(errs) == 0 { - t.Errorf("[%s] expected update errors but got none", k) - continue - } - if errs[0].Type != v.errorType { - t.Errorf("[%s] received an unexpected error type. Expected: '%s' got: '%s'", k, v.errorType, errs[0].Type) - } - if errs[0].Detail != v.errorDetail { - t.Errorf("[%s] received an unexpected error detail. Expected '%s' got: '%s'", k, v.errorDetail, errs[0].Detail) - } - } - - mustRunAs := validPSP() - mustRunAs.Spec.FSGroup.Rule = extensions.FSGroupStrategyMustRunAs - mustRunAs.Spec.SupplementalGroups.Rule = extensions.SupplementalGroupsStrategyMustRunAs - mustRunAs.Spec.RunAsUser.Rule = extensions.RunAsUserStrategyMustRunAs - mustRunAs.Spec.RunAsUser.Ranges = []extensions.UserIDRange{ - {Min: 1, Max: 1}, - } - mustRunAs.Spec.SELinux.Rule = extensions.SELinuxStrategyMustRunAs - - runAsNonRoot := validPSP() - runAsNonRoot.Spec.RunAsUser.Rule = extensions.RunAsUserStrategyMustRunAsNonRoot - - caseInsensitiveAddDrop := validPSP() - caseInsensitiveAddDrop.Spec.DefaultAddCapabilities = []api.Capability{"foo"} - caseInsensitiveAddDrop.Spec.RequiredDropCapabilities = []api.Capability{"FOO"} - - caseInsensitiveAllowedDrop := validPSP() - caseInsensitiveAllowedDrop.Spec.RequiredDropCapabilities = []api.Capability{"FOO"} - caseInsensitiveAllowedDrop.Spec.AllowedCapabilities = []api.Capability{"foo"} - - validAppArmor := validPSP() - validAppArmor.Annotations = map[string]string{ - apparmor.DefaultProfileAnnotationKey: apparmor.ProfileRuntimeDefault, - apparmor.AllowedProfilesAnnotationKey: apparmor.ProfileRuntimeDefault + "," + apparmor.ProfileNamePrefix + "foo", - } - - withSysctl := validPSP() - withSysctl.Annotations[extensions.SysctlsPodSecurityPolicyAnnotationKey] = "net.*" - - validSeccomp := validPSP() - validSeccomp.Annotations = map[string]string{ - seccomp.DefaultProfileAnnotationKey: "docker/default", - seccomp.AllowedProfilesAnnotationKey: "docker/default,unconfined,localhost/foo,*", - } - - validDefaultAllowPrivilegeEscalation := validPSP() - pe = true - validDefaultAllowPrivilegeEscalation.Spec.DefaultAllowPrivilegeEscalation = &pe - validDefaultAllowPrivilegeEscalation.Spec.AllowPrivilegeEscalation = true - - flexvolumeWhenFlexVolumesAllowed := validPSP() - flexvolumeWhenFlexVolumesAllowed.Spec.Volumes = []extensions.FSType{extensions.FlexVolume} - flexvolumeWhenFlexVolumesAllowed.Spec.AllowedFlexVolumes = []extensions.AllowedFlexVolume{ - {Driver: "example/driver1"}, - } - - flexvolumeWhenAllVolumesAllowed := validPSP() - flexvolumeWhenAllVolumesAllowed.Spec.Volumes = []extensions.FSType{extensions.All} - flexvolumeWhenAllVolumesAllowed.Spec.AllowedFlexVolumes = []extensions.AllowedFlexVolume{ - {Driver: "example/driver2"}, - } - successCases := map[string]struct { - psp *extensions.PodSecurityPolicy - }{ - "must run as": { - psp: mustRunAs, - }, - "run as any": { - psp: validPSP(), - }, - "run as non-root (user only)": { - psp: runAsNonRoot, - }, - "comparison for add -> drop is case sensitive": { - psp: caseInsensitiveAddDrop, - }, - "comparison for allowed -> drop is case sensitive": { - psp: caseInsensitiveAllowedDrop, - }, - "valid AppArmor annotations": { - psp: validAppArmor, - }, - "with network sysctls": { - psp: withSysctl, - }, - "valid seccomp annotations": { - psp: validSeccomp, - }, - "valid defaultAllowPrivilegeEscalation as true": { - psp: validDefaultAllowPrivilegeEscalation, - }, - "allow white-listed flexVolume when flex volumes are allowed": { - psp: flexvolumeWhenFlexVolumesAllowed, - }, - "allow white-listed flexVolume when all volumes are allowed": { - psp: flexvolumeWhenAllVolumesAllowed, - }, - } - - for k, v := range successCases { - if errs := ValidatePodSecurityPolicy(v.psp); len(errs) != 0 { - t.Errorf("Expected success for %s, got %v", k, errs) - } - - // Should be able to update to a valid PSP. - v.psp.ResourceVersion = "444" // Required for updates. - if errs := ValidatePodSecurityPolicyUpdate(validPSP(), v.psp); len(errs) != 0 { - t.Errorf("Expected success for %s update, got %v", k, errs) - } - } -} - -func TestValidatePSPVolumes(t *testing.T) { - validPSP := func() *extensions.PodSecurityPolicy { - return &extensions.PodSecurityPolicy{ - ObjectMeta: metav1.ObjectMeta{Name: "foo"}, - Spec: extensions.PodSecurityPolicySpec{ - SELinux: extensions.SELinuxStrategyOptions{ - Rule: extensions.SELinuxStrategyRunAsAny, - }, - RunAsUser: extensions.RunAsUserStrategyOptions{ - Rule: extensions.RunAsUserStrategyRunAsAny, - }, - FSGroup: extensions.FSGroupStrategyOptions{ - Rule: extensions.FSGroupStrategyRunAsAny, - }, - SupplementalGroups: extensions.SupplementalGroupsStrategyOptions{ - Rule: extensions.SupplementalGroupsStrategyRunAsAny, - }, - }, - } - } - - volumes := psputil.GetAllFSTypesAsSet() - // add in the * value since that is a pseudo type that is not included by default - volumes.Insert(string(extensions.All)) - - for _, strVolume := range volumes.List() { - psp := validPSP() - psp.Spec.Volumes = []extensions.FSType{extensions.FSType(strVolume)} - errs := ValidatePodSecurityPolicy(psp) - if len(errs) != 0 { - t.Errorf("%s validation expected no errors but received %v", strVolume, errs) - } - } -} - -func TestIsValidSysctlPattern(t *testing.T) { - valid := []string{ - "a.b.c.d", - "a", - "a_b", - "a-b", - "abc", - "abc.def", - "*", - "a.*", - "*", - "abc*", - "a.abc*", - "a.b.*", - } - invalid := []string{ - "", - "รค", - "a_", - "_", - "_a", - "_a._b", - "__", - "-", - ".", - "a.", - ".a", - "a.b.", - "a*.b", - "a*b", - "*a", - "Abc", - func(n int) string { - x := make([]byte, n) - for i := range x { - x[i] = byte('a') - } - return string(x) - }(256), - } - for _, s := range valid { - if !IsValidSysctlPattern(s) { - t.Errorf("%q expected to be a valid sysctl pattern", s) - } - } - for _, s := range invalid { - if IsValidSysctlPattern(s) { - t.Errorf("%q expected to be an invalid sysctl pattern", s) - } - } -} - -func Test_validatePSPRunAsUser(t *testing.T) { - var testCases = []struct { - name string - runAsUserStrategy extensions.RunAsUserStrategyOptions - fail bool - }{ - {"Invalid RunAsUserStrategy", extensions.RunAsUserStrategyOptions{Rule: extensions.RunAsUserStrategy("someInvalidStrategy")}, true}, - {"RunAsUserStrategyMustRunAs", extensions.RunAsUserStrategyOptions{Rule: extensions.RunAsUserStrategyMustRunAs}, false}, - {"RunAsUserStrategyMustRunAsNonRoot", extensions.RunAsUserStrategyOptions{Rule: extensions.RunAsUserStrategyMustRunAsNonRoot}, false}, - {"RunAsUserStrategyMustRunAsNonRoot With Valid Range", extensions.RunAsUserStrategyOptions{Rule: extensions.RunAsUserStrategyMustRunAs, Ranges: []extensions.UserIDRange{{Min: 2, Max: 3}, {Min: 4, Max: 5}}}, false}, - {"RunAsUserStrategyMustRunAsNonRoot With Invalid Range", extensions.RunAsUserStrategyOptions{Rule: extensions.RunAsUserStrategyMustRunAs, Ranges: []extensions.UserIDRange{{Min: 2, Max: 3}, {Min: 5, Max: 4}}}, true}, - } - - for _, testCase := range testCases { - t.Run(testCase.name, func(t *testing.T) { - errList := validatePSPRunAsUser(field.NewPath("status"), &testCase.runAsUserStrategy) - actualErrors := len(errList) - expectedErrors := 1 - if !testCase.fail { - expectedErrors = 0 - } - if actualErrors != expectedErrors { - t.Errorf("In testCase %v, expected %v errors, got %v errors", testCase.name, expectedErrors, actualErrors) - } - }) - } -} diff --git a/pkg/apis/policy/fuzzer/fuzzer.go b/pkg/apis/policy/fuzzer/fuzzer.go index e6b5a6b9798..184004fed14 100644 --- a/pkg/apis/policy/fuzzer/fuzzer.go +++ b/pkg/apis/policy/fuzzer/fuzzer.go @@ -30,5 +30,33 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} { c.FuzzNoCustom(s) // fuzz self without calling this function again s.PodDisruptionsAllowed = int32(c.Rand.Intn(2)) }, + func(psp *policy.PodSecurityPolicySpec, c fuzz.Continue) { + c.FuzzNoCustom(psp) // fuzz self without calling this function again + + runAsUserRules := []policy.RunAsUserStrategy{ + policy.RunAsUserStrategyMustRunAsNonRoot, + policy.RunAsUserStrategyMustRunAs, + policy.RunAsUserStrategyRunAsAny, + } + psp.RunAsUser.Rule = runAsUserRules[c.Rand.Intn(len(runAsUserRules))] + + seLinuxRules := []policy.SELinuxStrategy{ + policy.SELinuxStrategyMustRunAs, + policy.SELinuxStrategyRunAsAny, + } + psp.SELinux.Rule = seLinuxRules[c.Rand.Intn(len(seLinuxRules))] + + supplementalGroupsRules := []policy.SupplementalGroupsStrategyType{ + policy.SupplementalGroupsStrategyRunAsAny, + policy.SupplementalGroupsStrategyMustRunAs, + } + psp.SupplementalGroups.Rule = supplementalGroupsRules[c.Rand.Intn(len(supplementalGroupsRules))] + + fsGroupRules := []policy.FSGroupStrategyType{ + policy.FSGroupStrategyMustRunAs, + policy.FSGroupStrategyRunAsAny, + } + psp.FSGroup.Rule = fsGroupRules[c.Rand.Intn(len(fsGroupRules))] + }, } } diff --git a/pkg/apis/extensions/helpers.go b/pkg/apis/policy/helpers.go similarity index 92% rename from pkg/apis/extensions/helpers.go rename to pkg/apis/policy/helpers.go index 27d3e23add1..9c1ebd15235 100644 --- a/pkg/apis/extensions/helpers.go +++ b/pkg/apis/policy/helpers.go @@ -14,14 +14,14 @@ See the License for the specific language governing permissions and limitations under the License. */ -package extensions +package policy import ( "strings" ) // SysctlsFromPodSecurityPolicyAnnotation parses an annotation value of the key -// SysctlsSecurityPolocyAnnotationKey into a slice of sysctls. An empty slice +// SysctlsSecurityPolicyAnnotationKey into a slice of sysctls. An empty slice // is returned if annotation is the empty string. func SysctlsFromPodSecurityPolicyAnnotation(annotation string) ([]string, error) { if len(annotation) == 0 { diff --git a/pkg/apis/extensions/helpers_test.go b/pkg/apis/policy/helpers_test.go similarity index 99% rename from pkg/apis/extensions/helpers_test.go rename to pkg/apis/policy/helpers_test.go index 29ae139ec96..b07c8e30f58 100644 --- a/pkg/apis/extensions/helpers_test.go +++ b/pkg/apis/policy/helpers_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package extensions +package policy import ( "reflect" diff --git a/pkg/apis/policy/register.go b/pkg/apis/policy/register.go index 6a91919e096..c82e200a1da 100644 --- a/pkg/apis/policy/register.go +++ b/pkg/apis/policy/register.go @@ -19,7 +19,6 @@ package policy import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/kubernetes/pkg/apis/extensions" ) // GroupName is the group name use in this package @@ -49,8 +48,8 @@ func addKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes(SchemeGroupVersion, &PodDisruptionBudget{}, &PodDisruptionBudgetList{}, - &extensions.PodSecurityPolicy{}, - &extensions.PodSecurityPolicyList{}, + &PodSecurityPolicy{}, + &PodSecurityPolicyList{}, &Eviction{}, ) return nil diff --git a/pkg/apis/policy/types.go b/pkg/apis/policy/types.go index ddbf72296be..2d90dec8a74 100644 --- a/pkg/apis/policy/types.go +++ b/pkg/apis/policy/types.go @@ -19,6 +19,14 @@ package policy import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" + api "k8s.io/kubernetes/pkg/apis/core" +) + +const ( + // SysctlsPodSecurityPolicyAnnotationKey represents the key of a whitelist of + // allowed safe and unsafe sysctls in a pod spec. It's a comma-separated list of plain sysctl + // names or sysctl patterns (which end in *). The string "*" matches all sysctls. + SysctlsPodSecurityPolicyAnnotationKey string = "security.alpha.kubernetes.io/sysctls" ) // PodDisruptionBudgetSpec is a description of a PodDisruptionBudget. @@ -122,3 +130,271 @@ type Eviction struct { // +optional DeleteOptions *metav1.DeleteOptions } + +// +genclient +// +genclient:nonNamespaced +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// PodSecurityPolicy governs the ability to make requests that affect the SecurityContext +// that will be applied to a pod and container. +type PodSecurityPolicy struct { + metav1.TypeMeta + // +optional + metav1.ObjectMeta + + // Spec defines the policy enforced. + // +optional + Spec PodSecurityPolicySpec +} + +// PodSecurityPolicySpec defines the policy enforced. +type PodSecurityPolicySpec struct { + // Privileged determines if a pod can request to be run as privileged. + // +optional + Privileged bool + // DefaultAddCapabilities is the default set of capabilities that will be added to the container + // unless the pod spec specifically drops the capability. You may not list a capability in both + // DefaultAddCapabilities and RequiredDropCapabilities. Capabilities added here are implicitly + // allowed, and need not be included in the AllowedCapabilities list. + // +optional + DefaultAddCapabilities []api.Capability + // RequiredDropCapabilities are the capabilities that will be dropped from the container. These + // are required to be dropped and cannot be added. + // +optional + RequiredDropCapabilities []api.Capability + // AllowedCapabilities is a list of capabilities that can be requested to add to the container. + // Capabilities in this field may be added at the pod author's discretion. + // You must not list a capability in both AllowedCapabilities and RequiredDropCapabilities. + // To allow all capabilities you may use '*'. + // +optional + AllowedCapabilities []api.Capability + // Volumes is a white list of allowed volume plugins. Empty indicates that + // no volumes may be used. To allow all volumes you may use '*'. + // +optional + Volumes []FSType + // HostNetwork determines if the policy allows the use of HostNetwork in the pod spec. + // +optional + HostNetwork bool + // HostPorts determines which host port ranges are allowed to be exposed. + // +optional + HostPorts []HostPortRange + // HostPID determines if the policy allows the use of HostPID in the pod spec. + // +optional + HostPID bool + // HostIPC determines if the policy allows the use of HostIPC in the pod spec. + // +optional + HostIPC bool + // SELinux is the strategy that will dictate the allowable labels that may be set. + SELinux SELinuxStrategyOptions + // RunAsUser is the strategy that will dictate the allowable RunAsUser values that may be set. + RunAsUser RunAsUserStrategyOptions + // SupplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext. + SupplementalGroups SupplementalGroupsStrategyOptions + // FSGroup is the strategy that will dictate what fs group is used by the SecurityContext. + FSGroup FSGroupStrategyOptions + // ReadOnlyRootFilesystem when set to true will force containers to run with a read only root file + // system. If the container specifically requests to run with a non-read only root file system + // the PSP should deny the pod. + // If set to false the container may run with a read only root file system if it wishes but it + // will not be forced to. + // +optional + ReadOnlyRootFilesystem bool + // DefaultAllowPrivilegeEscalation controls the default setting for whether a + // process can gain more privileges than its parent process. + // +optional + DefaultAllowPrivilegeEscalation *bool + // AllowPrivilegeEscalation determines if a pod can request to allow + // privilege escalation. If unspecified, defaults to true. + // +optional + AllowPrivilegeEscalation bool + // AllowedHostPaths is a white list of allowed host paths. Empty indicates that all host paths may be used. + // +optional + AllowedHostPaths []AllowedHostPath + // AllowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all + // Flexvolumes may be used. This parameter is effective only when the usage of the Flexvolumes + // is allowed in the "Volumes" field. + // +optional + AllowedFlexVolumes []AllowedFlexVolume +} + +// AllowedHostPath defines the host volume conditions that will be enabled by a policy +// for pods to use. It requires the path prefix to be defined. +type AllowedHostPath struct { + // PathPrefix is the path prefix that the host volume must match. + // PathPrefix does not support `*`. + // Trailing slashes are trimmed when validating the path prefix with a host path. + // + // Examples: + // `/foo` would allow `/foo`, `/foo/` and `/foo/bar` + // `/foo` would not allow `/food` or `/etc/foo` + PathPrefix string +} + +// HostPortRange defines a range of host ports that will be enabled by a policy +// for pods to use. It requires both the start and end to be defined. +type HostPortRange struct { + // Min is the start of the range, inclusive. + Min int32 + // Max is the end of the range, inclusive. + Max int32 +} + +// AllowAllCapabilities can be used as a value for the PodSecurityPolicy.AllowAllCapabilities +// field and means that any capabilities are allowed to be requested. +var AllowAllCapabilities api.Capability = "*" + +// FSType gives strong typing to different file systems that are used by volumes. +type FSType string + +var ( + AzureFile FSType = "azureFile" + Flocker FSType = "flocker" + FlexVolume FSType = "flexVolume" + HostPath FSType = "hostPath" + EmptyDir FSType = "emptyDir" + GCEPersistentDisk FSType = "gcePersistentDisk" + AWSElasticBlockStore FSType = "awsElasticBlockStore" + GitRepo FSType = "gitRepo" + Secret FSType = "secret" + NFS FSType = "nfs" + ISCSI FSType = "iscsi" + Glusterfs FSType = "glusterfs" + PersistentVolumeClaim FSType = "persistentVolumeClaim" + RBD FSType = "rbd" + Cinder FSType = "cinder" + CephFS FSType = "cephFS" + DownwardAPI FSType = "downwardAPI" + FC FSType = "fc" + ConfigMap FSType = "configMap" + VsphereVolume FSType = "vsphereVolume" + Quobyte FSType = "quobyte" + AzureDisk FSType = "azureDisk" + PhotonPersistentDisk FSType = "photonPersistentDisk" + StorageOS FSType = "storageos" + Projected FSType = "projected" + PortworxVolume FSType = "portworxVolume" + ScaleIO FSType = "scaleIO" + CSI FSType = "csi" + All FSType = "*" +) + +// AllowedFlexVolume represents a single Flexvolume that is allowed to be used. +type AllowedFlexVolume struct { + // Driver is the name of the Flexvolume driver. + Driver string +} + +// SELinuxStrategyOptions defines the strategy type and any options used to create the strategy. +type SELinuxStrategyOptions struct { + // Rule is the strategy that will dictate the allowable labels that may be set. + Rule SELinuxStrategy + // SELinuxOptions required to run as; required for MustRunAs + // More info: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#selinux + // +optional + SELinuxOptions *api.SELinuxOptions +} + +// SELinuxStrategy denotes strategy types for generating SELinux options for a +// Security. +type SELinuxStrategy string + +const ( + // SELinuxStrategyMustRunAs means that container must have SELinux labels of X applied. + SELinuxStrategyMustRunAs SELinuxStrategy = "MustRunAs" + // SELinuxStrategyRunAsAny means that container may make requests for any SELinux context labels. + SELinuxStrategyRunAsAny SELinuxStrategy = "RunAsAny" +) + +// RunAsUserStrategyOptions defines the strategy type and any options used to create the strategy. +type RunAsUserStrategyOptions struct { + // Rule is the strategy that will dictate the allowable RunAsUser values that may be set. + Rule RunAsUserStrategy + // Ranges are the allowed ranges of uids that may be used. If you would like to force a single uid + // then supply a single range with the same start and end. Required for MustRunAs. + // +optional + Ranges []UserIDRange +} + +// UserIDRange provides a min/max of an allowed range of UserIDs. +type UserIDRange struct { + // Min is the start of the range, inclusive. + Min int64 + // Max is the end of the range, inclusive. + Max int64 +} + +// GroupIDRange provides a min/max of an allowed range of GroupIDs. +type GroupIDRange struct { + // Min is the start of the range, inclusive. + Min int64 + // Max is the end of the range, inclusive. + Max int64 +} + +// RunAsUserStrategy denotes strategy types for generating RunAsUser values for a +// SecurityContext. +type RunAsUserStrategy string + +const ( + // RunAsUserStrategyMustRunAs means that container must run as a particular uid. + RunAsUserStrategyMustRunAs RunAsUserStrategy = "MustRunAs" + // RunAsUserStrategyMustRunAsNonRoot means that container must run as a non-root uid + RunAsUserStrategyMustRunAsNonRoot RunAsUserStrategy = "MustRunAsNonRoot" + // RunAsUserStrategyRunAsAny means that container may make requests for any uid. + RunAsUserStrategyRunAsAny RunAsUserStrategy = "RunAsAny" +) + +// FSGroupStrategyOptions defines the strategy type and options used to create the strategy. +type FSGroupStrategyOptions struct { + // Rule is the strategy that will dictate what FSGroup is used in the SecurityContext. + // +optional + Rule FSGroupStrategyType + // Ranges are the allowed ranges of fs groups. If you would like to force a single + // fs group then supply a single range with the same start and end. Required for MustRunAs. + // +optional + Ranges []GroupIDRange +} + +// FSGroupStrategyType denotes strategy types for generating FSGroup values for a +// SecurityContext +type FSGroupStrategyType string + +const ( + // FSGroupStrategyMustRunAs means that container must have FSGroup of X applied. + FSGroupStrategyMustRunAs FSGroupStrategyType = "MustRunAs" + // FSGroupStrategyRunAsAny means that container may make requests for any FSGroup labels. + FSGroupStrategyRunAsAny FSGroupStrategyType = "RunAsAny" +) + +// SupplementalGroupsStrategyOptions defines the strategy type and options used to create the strategy. +type SupplementalGroupsStrategyOptions struct { + // Rule is the strategy that will dictate what supplemental groups is used in the SecurityContext. + // +optional + Rule SupplementalGroupsStrategyType + // Ranges are the allowed ranges of supplemental groups. If you would like to force a single + // supplemental group then supply a single range with the same start and end. Required for MustRunAs. + // +optional + Ranges []GroupIDRange +} + +// SupplementalGroupsStrategyType denotes strategy types for determining valid supplemental +// groups for a SecurityContext. +type SupplementalGroupsStrategyType string + +const ( + // SupplementalGroupsStrategyMustRunAs means that container must run as a particular gid. + SupplementalGroupsStrategyMustRunAs SupplementalGroupsStrategyType = "MustRunAs" + // SupplementalGroupsStrategyRunAsAny means that container may make requests for any gid. + SupplementalGroupsStrategyRunAsAny SupplementalGroupsStrategyType = "RunAsAny" +) + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// PodSecurityPolicyList is a list of PodSecurityPolicy objects. +type PodSecurityPolicyList struct { + metav1.TypeMeta + // +optional + metav1.ListMeta + + Items []PodSecurityPolicy +} diff --git a/pkg/apis/policy/v1beta1/doc.go b/pkg/apis/policy/v1beta1/doc.go index 925a0b74235..9629da3fcd4 100644 --- a/pkg/apis/policy/v1beta1/doc.go +++ b/pkg/apis/policy/v1beta1/doc.go @@ -15,7 +15,6 @@ limitations under the License. */ // +k8s:conversion-gen=k8s.io/kubernetes/pkg/apis/policy -// +k8s:conversion-gen=k8s.io/kubernetes/pkg/apis/extensions // +k8s:conversion-gen-external-types=k8s.io/api/policy/v1beta1 // +k8s:defaulter-gen=TypeMeta // +k8s:defaulter-gen-input=../../../../vendor/k8s.io/api/policy/v1beta1 diff --git a/pkg/apis/policy/validation/validation.go b/pkg/apis/policy/validation/validation.go index cae1609de6e..2c1e1de2a87 100644 --- a/pkg/apis/policy/validation/validation.go +++ b/pkg/apis/policy/validation/validation.go @@ -17,13 +17,22 @@ limitations under the License. package validation import ( + "fmt" + "path/filepath" "reflect" + "regexp" + "strings" unversionedvalidation "k8s.io/apimachinery/pkg/apis/meta/v1/validation" + "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/validation/field" + core "k8s.io/kubernetes/pkg/apis/core" apivalidation "k8s.io/kubernetes/pkg/apis/core/validation" extensionsvalidation "k8s.io/kubernetes/pkg/apis/extensions/validation" "k8s.io/kubernetes/pkg/apis/policy" + "k8s.io/kubernetes/pkg/security/apparmor" + "k8s.io/kubernetes/pkg/security/podsecuritypolicy/seccomp" + psputil "k8s.io/kubernetes/pkg/security/podsecuritypolicy/util" ) func ValidatePodDisruptionBudget(pdb *policy.PodDisruptionBudget) field.ErrorList { @@ -77,3 +86,302 @@ func ValidatePodDisruptionBudgetStatus(status policy.PodDisruptionBudgetStatus, allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.ExpectedPods), fldPath.Child("expectedPods"))...) return allErrs } + +// ValidatePodSecurityPolicyName can be used to check whether the given +// pod security policy name is valid. +// Prefix indicates this name will be used as part of generation, in which case +// trailing dashes are allowed. +var ValidatePodSecurityPolicyName = apivalidation.NameIsDNSSubdomain + +func ValidatePodSecurityPolicy(psp *policy.PodSecurityPolicy) field.ErrorList { + allErrs := field.ErrorList{} + allErrs = append(allErrs, apivalidation.ValidateObjectMeta(&psp.ObjectMeta, false, ValidatePodSecurityPolicyName, field.NewPath("metadata"))...) + allErrs = append(allErrs, ValidatePodSecurityPolicySpecificAnnotations(psp.Annotations, field.NewPath("metadata").Child("annotations"))...) + allErrs = append(allErrs, ValidatePodSecurityPolicySpec(&psp.Spec, field.NewPath("spec"))...) + return allErrs +} + +func ValidatePodSecurityPolicySpec(spec *policy.PodSecurityPolicySpec, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + + allErrs = append(allErrs, validatePSPRunAsUser(fldPath.Child("runAsUser"), &spec.RunAsUser)...) + allErrs = append(allErrs, validatePSPSELinux(fldPath.Child("seLinux"), &spec.SELinux)...) + allErrs = append(allErrs, validatePSPSupplementalGroup(fldPath.Child("supplementalGroups"), &spec.SupplementalGroups)...) + allErrs = append(allErrs, validatePSPFSGroup(fldPath.Child("fsGroup"), &spec.FSGroup)...) + allErrs = append(allErrs, validatePodSecurityPolicyVolumes(fldPath, spec.Volumes)...) + if len(spec.RequiredDropCapabilities) > 0 && hasCap(policy.AllowAllCapabilities, spec.AllowedCapabilities) { + allErrs = append(allErrs, field.Invalid(field.NewPath("requiredDropCapabilities"), spec.RequiredDropCapabilities, + "must be empty when all capabilities are allowed by a wildcard")) + } + allErrs = append(allErrs, validatePSPCapsAgainstDrops(spec.RequiredDropCapabilities, spec.DefaultAddCapabilities, field.NewPath("defaultAddCapabilities"))...) + allErrs = append(allErrs, validatePSPCapsAgainstDrops(spec.RequiredDropCapabilities, spec.AllowedCapabilities, field.NewPath("allowedCapabilities"))...) + allErrs = append(allErrs, validatePSPDefaultAllowPrivilegeEscalation(fldPath.Child("defaultAllowPrivilegeEscalation"), spec.DefaultAllowPrivilegeEscalation, spec.AllowPrivilegeEscalation)...) + allErrs = append(allErrs, validatePSPAllowedHostPaths(fldPath.Child("allowedHostPaths"), spec.AllowedHostPaths)...) + allErrs = append(allErrs, validatePSPAllowedFlexVolumes(fldPath.Child("allowedFlexVolumes"), spec.AllowedFlexVolumes)...) + + return allErrs +} + +func ValidatePodSecurityPolicySpecificAnnotations(annotations map[string]string, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + + if p := annotations[apparmor.DefaultProfileAnnotationKey]; p != "" { + if err := apparmor.ValidateProfileFormat(p); err != nil { + allErrs = append(allErrs, field.Invalid(fldPath.Key(apparmor.DefaultProfileAnnotationKey), p, err.Error())) + } + } + if allowed := annotations[apparmor.AllowedProfilesAnnotationKey]; allowed != "" { + for _, p := range strings.Split(allowed, ",") { + if err := apparmor.ValidateProfileFormat(p); err != nil { + allErrs = append(allErrs, field.Invalid(fldPath.Key(apparmor.AllowedProfilesAnnotationKey), allowed, err.Error())) + } + } + } + + sysctlAnnotation := annotations[policy.SysctlsPodSecurityPolicyAnnotationKey] + sysctlFldPath := fldPath.Key(policy.SysctlsPodSecurityPolicyAnnotationKey) + sysctls, err := policy.SysctlsFromPodSecurityPolicyAnnotation(sysctlAnnotation) + if err != nil { + allErrs = append(allErrs, field.Invalid(sysctlFldPath, sysctlAnnotation, err.Error())) + } else { + allErrs = append(allErrs, validatePodSecurityPolicySysctls(sysctlFldPath, sysctls)...) + } + + if p := annotations[seccomp.DefaultProfileAnnotationKey]; p != "" { + allErrs = append(allErrs, apivalidation.ValidateSeccompProfile(p, fldPath.Key(seccomp.DefaultProfileAnnotationKey))...) + } + if allowed := annotations[seccomp.AllowedProfilesAnnotationKey]; allowed != "" { + for _, p := range strings.Split(allowed, ",") { + if p == seccomp.AllowAny { + continue + } + allErrs = append(allErrs, apivalidation.ValidateSeccompProfile(p, fldPath.Key(seccomp.AllowedProfilesAnnotationKey))...) + } + } + return allErrs +} + +// validatePSPAllowedHostPaths makes sure all allowed host paths follow: +// 1. path prefix is required +// 2. path prefix does not have any element which is ".." +func validatePSPAllowedHostPaths(fldPath *field.Path, allowedHostPaths []policy.AllowedHostPath) field.ErrorList { + allErrs := field.ErrorList{} + + for i, target := range allowedHostPaths { + if target.PathPrefix == "" { + allErrs = append(allErrs, field.Required(fldPath.Index(i), "is required")) + break + } + parts := strings.Split(filepath.ToSlash(target.PathPrefix), "/") + for _, item := range parts { + if item == ".." { + allErrs = append(allErrs, field.Invalid(fldPath.Index(i), target.PathPrefix, "must not contain '..'")) + break // even for `../../..`, one error is sufficient to make the point + } + } + } + + return allErrs +} + +func validatePSPAllowedFlexVolumes(fldPath *field.Path, flexVolumes []policy.AllowedFlexVolume) field.ErrorList { + allErrs := field.ErrorList{} + if len(flexVolumes) > 0 { + for idx, fv := range flexVolumes { + if len(fv.Driver) == 0 { + allErrs = append(allErrs, field.Required(fldPath.Child("allowedFlexVolumes").Index(idx).Child("driver"), + "must specify a driver")) + } + } + } + return allErrs +} + +// validatePSPSELinux validates the SELinux fields of PodSecurityPolicy. +func validatePSPSELinux(fldPath *field.Path, seLinux *policy.SELinuxStrategyOptions) field.ErrorList { + allErrs := field.ErrorList{} + + // ensure the selinux strategy has a valid rule + supportedSELinuxRules := sets.NewString( + string(policy.SELinuxStrategyMustRunAs), + string(policy.SELinuxStrategyRunAsAny), + ) + if !supportedSELinuxRules.Has(string(seLinux.Rule)) { + allErrs = append(allErrs, field.NotSupported(fldPath.Child("rule"), seLinux.Rule, supportedSELinuxRules.List())) + } + + return allErrs +} + +// validatePSPRunAsUser validates the RunAsUser fields of PodSecurityPolicy. +func validatePSPRunAsUser(fldPath *field.Path, runAsUser *policy.RunAsUserStrategyOptions) field.ErrorList { + allErrs := field.ErrorList{} + + // ensure the user strategy has a valid rule + supportedRunAsUserRules := sets.NewString( + string(policy.RunAsUserStrategyMustRunAs), + string(policy.RunAsUserStrategyMustRunAsNonRoot), + string(policy.RunAsUserStrategyRunAsAny), + ) + if !supportedRunAsUserRules.Has(string(runAsUser.Rule)) { + allErrs = append(allErrs, field.NotSupported(fldPath.Child("rule"), runAsUser.Rule, supportedRunAsUserRules.List())) + } + + // validate range settings + for idx, rng := range runAsUser.Ranges { + allErrs = append(allErrs, validateUserIDRange(fldPath.Child("ranges").Index(idx), rng)...) + } + + return allErrs +} + +// validatePSPFSGroup validates the FSGroupStrategyOptions fields of the PodSecurityPolicy. +func validatePSPFSGroup(fldPath *field.Path, groupOptions *policy.FSGroupStrategyOptions) field.ErrorList { + allErrs := field.ErrorList{} + + supportedRules := sets.NewString( + string(policy.FSGroupStrategyMustRunAs), + string(policy.FSGroupStrategyRunAsAny), + ) + if !supportedRules.Has(string(groupOptions.Rule)) { + allErrs = append(allErrs, field.NotSupported(fldPath.Child("rule"), groupOptions.Rule, supportedRules.List())) + } + + for idx, rng := range groupOptions.Ranges { + allErrs = append(allErrs, validateGroupIDRange(fldPath.Child("ranges").Index(idx), rng)...) + } + return allErrs +} + +// validatePSPSupplementalGroup validates the SupplementalGroupsStrategyOptions fields of the PodSecurityPolicy. +func validatePSPSupplementalGroup(fldPath *field.Path, groupOptions *policy.SupplementalGroupsStrategyOptions) field.ErrorList { + allErrs := field.ErrorList{} + + supportedRules := sets.NewString( + string(policy.SupplementalGroupsStrategyRunAsAny), + string(policy.SupplementalGroupsStrategyMustRunAs), + ) + if !supportedRules.Has(string(groupOptions.Rule)) { + allErrs = append(allErrs, field.NotSupported(fldPath.Child("rule"), groupOptions.Rule, supportedRules.List())) + } + + for idx, rng := range groupOptions.Ranges { + allErrs = append(allErrs, validateGroupIDRange(fldPath.Child("ranges").Index(idx), rng)...) + } + return allErrs +} + +// validatePodSecurityPolicyVolumes validates the volume fields of PodSecurityPolicy. +func validatePodSecurityPolicyVolumes(fldPath *field.Path, volumes []policy.FSType) field.ErrorList { + allErrs := field.ErrorList{} + allowed := psputil.GetAllFSTypesAsSet() + // add in the * value since that is a pseudo type that is not included by default + allowed.Insert(string(policy.All)) + for _, v := range volumes { + if !allowed.Has(string(v)) { + allErrs = append(allErrs, field.NotSupported(fldPath.Child("volumes"), v, allowed.List())) + } + } + return allErrs +} + +// validatePSPDefaultAllowPrivilegeEscalation validates the DefaultAllowPrivilegeEscalation field against the AllowPrivilegeEscalation field of a PodSecurityPolicy. +func validatePSPDefaultAllowPrivilegeEscalation(fldPath *field.Path, defaultAllowPrivilegeEscalation *bool, allowPrivilegeEscalation bool) field.ErrorList { + allErrs := field.ErrorList{} + if defaultAllowPrivilegeEscalation != nil && *defaultAllowPrivilegeEscalation && !allowPrivilegeEscalation { + allErrs = append(allErrs, field.Invalid(fldPath, defaultAllowPrivilegeEscalation, "Cannot set DefaultAllowPrivilegeEscalation to true without also setting AllowPrivilegeEscalation to true")) + } + + return allErrs +} + +const sysctlPatternSegmentFmt string = "([a-z0-9][-_a-z0-9]*)?[a-z0-9*]" +const SysctlPatternFmt string = "(" + apivalidation.SysctlSegmentFmt + "\\.)*" + sysctlPatternSegmentFmt + +var sysctlPatternRegexp = regexp.MustCompile("^" + SysctlPatternFmt + "$") + +func IsValidSysctlPattern(name string) bool { + if len(name) > apivalidation.SysctlMaxLength { + return false + } + return sysctlPatternRegexp.MatchString(name) +} + +// validatePodSecurityPolicySysctls validates the sysctls fields of PodSecurityPolicy. +func validatePodSecurityPolicySysctls(fldPath *field.Path, sysctls []string) field.ErrorList { + allErrs := field.ErrorList{} + for i, s := range sysctls { + if !IsValidSysctlPattern(string(s)) { + allErrs = append( + allErrs, + field.Invalid(fldPath.Index(i), sysctls[i], fmt.Sprintf("must have at most %d characters and match regex %s", + apivalidation.SysctlMaxLength, + SysctlPatternFmt, + )), + ) + } + } + + return allErrs +} + +func validateUserIDRange(fldPath *field.Path, rng policy.UserIDRange) field.ErrorList { + return validateIDRanges(fldPath, int64(rng.Min), int64(rng.Max)) +} + +func validateGroupIDRange(fldPath *field.Path, rng policy.GroupIDRange) field.ErrorList { + return validateIDRanges(fldPath, int64(rng.Min), int64(rng.Max)) +} + +// validateIDRanges ensures the range is valid. +func validateIDRanges(fldPath *field.Path, min, max int64) field.ErrorList { + allErrs := field.ErrorList{} + + // if 0 <= Min <= Max then we do not need to validate max. It is always greater than or + // equal to 0 and Min. + if min < 0 { + allErrs = append(allErrs, field.Invalid(fldPath.Child("min"), min, "min cannot be negative")) + } + if max < 0 { + allErrs = append(allErrs, field.Invalid(fldPath.Child("max"), max, "max cannot be negative")) + } + if min > max { + allErrs = append(allErrs, field.Invalid(fldPath.Child("min"), min, "min cannot be greater than max")) + } + + return allErrs +} + +// validatePSPCapsAgainstDrops ensures an allowed cap is not listed in the required drops. +func validatePSPCapsAgainstDrops(requiredDrops []core.Capability, capsToCheck []core.Capability, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + if requiredDrops == nil { + return allErrs + } + for _, cap := range capsToCheck { + if hasCap(cap, requiredDrops) { + allErrs = append(allErrs, field.Invalid(fldPath, cap, + fmt.Sprintf("capability is listed in %s and requiredDropCapabilities", fldPath.String()))) + } + } + return allErrs +} + +// ValidatePodSecurityPolicyUpdate validates a PSP for updates. +func ValidatePodSecurityPolicyUpdate(old *policy.PodSecurityPolicy, new *policy.PodSecurityPolicy) field.ErrorList { + allErrs := field.ErrorList{} + allErrs = append(allErrs, apivalidation.ValidateObjectMetaUpdate(&new.ObjectMeta, &old.ObjectMeta, field.NewPath("metadata"))...) + allErrs = append(allErrs, ValidatePodSecurityPolicySpecificAnnotations(new.Annotations, field.NewPath("metadata").Child("annotations"))...) + allErrs = append(allErrs, ValidatePodSecurityPolicySpec(&new.Spec, field.NewPath("spec"))...) + return allErrs +} + +// hasCap checks for needle in haystack. +func hasCap(needle core.Capability, haystack []core.Capability) bool { + for _, c := range haystack { + if needle == c { + return true + } + } + return false +} diff --git a/pkg/apis/policy/validation/validation_test.go b/pkg/apis/policy/validation/validation_test.go index c2ba5b61fbe..2d0e943f91f 100644 --- a/pkg/apis/policy/validation/validation_test.go +++ b/pkg/apis/policy/validation/validation_test.go @@ -17,11 +17,17 @@ limitations under the License. package validation import ( + "fmt" "testing" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/validation/field" + api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/apis/policy" + "k8s.io/kubernetes/pkg/security/apparmor" + "k8s.io/kubernetes/pkg/security/podsecuritypolicy/seccomp" + psputil "k8s.io/kubernetes/pkg/security/podsecuritypolicy/util" ) func TestValidatePodDisruptionBudgetSpec(t *testing.T) { @@ -221,3 +227,527 @@ func TestValidatePodDisruptionBudgetUpdate(t *testing.T) { } } } + +func TestValidatePodSecurityPolicy(t *testing.T) { + validPSP := func() *policy.PodSecurityPolicy { + return &policy.PodSecurityPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + Annotations: map[string]string{}, + }, + Spec: policy.PodSecurityPolicySpec{ + SELinux: policy.SELinuxStrategyOptions{ + Rule: policy.SELinuxStrategyRunAsAny, + }, + RunAsUser: policy.RunAsUserStrategyOptions{ + Rule: policy.RunAsUserStrategyRunAsAny, + }, + FSGroup: policy.FSGroupStrategyOptions{ + Rule: policy.FSGroupStrategyRunAsAny, + }, + SupplementalGroups: policy.SupplementalGroupsStrategyOptions{ + Rule: policy.SupplementalGroupsStrategyRunAsAny, + }, + AllowedHostPaths: []policy.AllowedHostPath{ + {PathPrefix: "/foo/bar"}, + {PathPrefix: "/baz/"}, + }, + }, + } + } + + noUserOptions := validPSP() + noUserOptions.Spec.RunAsUser.Rule = "" + + noSELinuxOptions := validPSP() + noSELinuxOptions.Spec.SELinux.Rule = "" + + invalidUserStratType := validPSP() + invalidUserStratType.Spec.RunAsUser.Rule = "invalid" + + invalidSELinuxStratType := validPSP() + invalidSELinuxStratType.Spec.SELinux.Rule = "invalid" + + invalidUIDPSP := validPSP() + invalidUIDPSP.Spec.RunAsUser.Rule = policy.RunAsUserStrategyMustRunAs + invalidUIDPSP.Spec.RunAsUser.Ranges = []policy.UserIDRange{{Min: -1, Max: 1}} + + missingObjectMetaName := validPSP() + missingObjectMetaName.ObjectMeta.Name = "" + + noFSGroupOptions := validPSP() + noFSGroupOptions.Spec.FSGroup.Rule = "" + + invalidFSGroupStratType := validPSP() + invalidFSGroupStratType.Spec.FSGroup.Rule = "invalid" + + noSupplementalGroupsOptions := validPSP() + noSupplementalGroupsOptions.Spec.SupplementalGroups.Rule = "" + + invalidSupGroupStratType := validPSP() + invalidSupGroupStratType.Spec.SupplementalGroups.Rule = "invalid" + + invalidRangeMinGreaterThanMax := validPSP() + invalidRangeMinGreaterThanMax.Spec.FSGroup.Ranges = []policy.GroupIDRange{ + {Min: 2, Max: 1}, + } + + invalidRangeNegativeMin := validPSP() + invalidRangeNegativeMin.Spec.FSGroup.Ranges = []policy.GroupIDRange{ + {Min: -1, Max: 10}, + } + + invalidRangeNegativeMax := validPSP() + invalidRangeNegativeMax.Spec.FSGroup.Ranges = []policy.GroupIDRange{ + {Min: 1, Max: -10}, + } + + wildcardAllowedCapAndRequiredDrop := validPSP() + wildcardAllowedCapAndRequiredDrop.Spec.RequiredDropCapabilities = []api.Capability{"foo"} + wildcardAllowedCapAndRequiredDrop.Spec.AllowedCapabilities = []api.Capability{policy.AllowAllCapabilities} + + requiredCapAddAndDrop := validPSP() + requiredCapAddAndDrop.Spec.DefaultAddCapabilities = []api.Capability{"foo"} + requiredCapAddAndDrop.Spec.RequiredDropCapabilities = []api.Capability{"foo"} + + allowedCapListedInRequiredDrop := validPSP() + allowedCapListedInRequiredDrop.Spec.RequiredDropCapabilities = []api.Capability{"foo"} + allowedCapListedInRequiredDrop.Spec.AllowedCapabilities = []api.Capability{"foo"} + + invalidAppArmorDefault := validPSP() + invalidAppArmorDefault.Annotations = map[string]string{ + apparmor.DefaultProfileAnnotationKey: "not-good", + } + invalidAppArmorAllowed := validPSP() + invalidAppArmorAllowed.Annotations = map[string]string{ + apparmor.AllowedProfilesAnnotationKey: apparmor.ProfileRuntimeDefault + ",not-good", + } + + invalidSysctlPattern := validPSP() + invalidSysctlPattern.Annotations[policy.SysctlsPodSecurityPolicyAnnotationKey] = "a.*.b" + + invalidSeccompDefault := validPSP() + invalidSeccompDefault.Annotations = map[string]string{ + seccomp.DefaultProfileAnnotationKey: "not-good", + } + invalidSeccompAllowAnyDefault := validPSP() + invalidSeccompAllowAnyDefault.Annotations = map[string]string{ + seccomp.DefaultProfileAnnotationKey: "*", + } + invalidSeccompAllowed := validPSP() + invalidSeccompAllowed.Annotations = map[string]string{ + seccomp.AllowedProfilesAnnotationKey: "docker/default,not-good", + } + + invalidAllowedHostPathMissingPath := validPSP() + invalidAllowedHostPathMissingPath.Spec.AllowedHostPaths = []policy.AllowedHostPath{ + {PathPrefix: ""}, + } + + invalidAllowedHostPathBacksteps := validPSP() + invalidAllowedHostPathBacksteps.Spec.AllowedHostPaths = []policy.AllowedHostPath{ + {PathPrefix: "/dont/allow/backsteps/.."}, + } + + invalidDefaultAllowPrivilegeEscalation := validPSP() + pe := true + invalidDefaultAllowPrivilegeEscalation.Spec.DefaultAllowPrivilegeEscalation = &pe + + emptyFlexDriver := validPSP() + emptyFlexDriver.Spec.Volumes = []policy.FSType{policy.FlexVolume} + emptyFlexDriver.Spec.AllowedFlexVolumes = []policy.AllowedFlexVolume{{}} + + nonEmptyFlexVolumes := validPSP() + nonEmptyFlexVolumes.Spec.AllowedFlexVolumes = []policy.AllowedFlexVolume{{Driver: "example/driver"}} + + type testCase struct { + psp *policy.PodSecurityPolicy + errorType field.ErrorType + errorDetail string + } + errorCases := map[string]testCase{ + "no user options": { + psp: noUserOptions, + errorType: field.ErrorTypeNotSupported, + errorDetail: `supported values: "MustRunAs", "MustRunAsNonRoot", "RunAsAny"`, + }, + "no selinux options": { + psp: noSELinuxOptions, + errorType: field.ErrorTypeNotSupported, + errorDetail: `supported values: "MustRunAs", "RunAsAny"`, + }, + "no fsgroup options": { + psp: noFSGroupOptions, + errorType: field.ErrorTypeNotSupported, + errorDetail: `supported values: "MustRunAs", "RunAsAny"`, + }, + "no sup group options": { + psp: noSupplementalGroupsOptions, + errorType: field.ErrorTypeNotSupported, + errorDetail: `supported values: "MustRunAs", "RunAsAny"`, + }, + "invalid user strategy type": { + psp: invalidUserStratType, + errorType: field.ErrorTypeNotSupported, + errorDetail: `supported values: "MustRunAs", "MustRunAsNonRoot", "RunAsAny"`, + }, + "invalid selinux strategy type": { + psp: invalidSELinuxStratType, + errorType: field.ErrorTypeNotSupported, + errorDetail: `supported values: "MustRunAs", "RunAsAny"`, + }, + "invalid sup group strategy type": { + psp: invalidSupGroupStratType, + errorType: field.ErrorTypeNotSupported, + errorDetail: `supported values: "MustRunAs", "RunAsAny"`, + }, + "invalid fs group strategy type": { + psp: invalidFSGroupStratType, + errorType: field.ErrorTypeNotSupported, + errorDetail: `supported values: "MustRunAs", "RunAsAny"`, + }, + "invalid uid": { + psp: invalidUIDPSP, + errorType: field.ErrorTypeInvalid, + errorDetail: "min cannot be negative", + }, + "missing object meta name": { + psp: missingObjectMetaName, + errorType: field.ErrorTypeRequired, + errorDetail: "name or generateName is required", + }, + "invalid range min greater than max": { + psp: invalidRangeMinGreaterThanMax, + errorType: field.ErrorTypeInvalid, + errorDetail: "min cannot be greater than max", + }, + "invalid range negative min": { + psp: invalidRangeNegativeMin, + errorType: field.ErrorTypeInvalid, + errorDetail: "min cannot be negative", + }, + "invalid range negative max": { + psp: invalidRangeNegativeMax, + errorType: field.ErrorTypeInvalid, + errorDetail: "max cannot be negative", + }, + "non-empty required drops and all caps are allowed by a wildcard": { + psp: wildcardAllowedCapAndRequiredDrop, + errorType: field.ErrorTypeInvalid, + errorDetail: "must be empty when all capabilities are allowed by a wildcard", + }, + "invalid required caps": { + psp: requiredCapAddAndDrop, + errorType: field.ErrorTypeInvalid, + errorDetail: "capability is listed in defaultAddCapabilities and requiredDropCapabilities", + }, + "allowed cap listed in required drops": { + psp: allowedCapListedInRequiredDrop, + errorType: field.ErrorTypeInvalid, + errorDetail: "capability is listed in allowedCapabilities and requiredDropCapabilities", + }, + "invalid AppArmor default profile": { + psp: invalidAppArmorDefault, + errorType: field.ErrorTypeInvalid, + errorDetail: "invalid AppArmor profile name: \"not-good\"", + }, + "invalid AppArmor allowed profile": { + psp: invalidAppArmorAllowed, + errorType: field.ErrorTypeInvalid, + errorDetail: "invalid AppArmor profile name: \"not-good\"", + }, + "invalid sysctl pattern": { + psp: invalidSysctlPattern, + errorType: field.ErrorTypeInvalid, + errorDetail: fmt.Sprintf("must have at most 253 characters and match regex %s", SysctlPatternFmt), + }, + "invalid seccomp default profile": { + psp: invalidSeccompDefault, + errorType: field.ErrorTypeInvalid, + errorDetail: "must be a valid seccomp profile", + }, + "invalid seccomp allow any default profile": { + psp: invalidSeccompAllowAnyDefault, + errorType: field.ErrorTypeInvalid, + errorDetail: "must be a valid seccomp profile", + }, + "invalid seccomp allowed profile": { + psp: invalidSeccompAllowed, + errorType: field.ErrorTypeInvalid, + errorDetail: "must be a valid seccomp profile", + }, + "invalid defaultAllowPrivilegeEscalation": { + psp: invalidDefaultAllowPrivilegeEscalation, + errorType: field.ErrorTypeInvalid, + errorDetail: "Cannot set DefaultAllowPrivilegeEscalation to true without also setting AllowPrivilegeEscalation to true", + }, + "invalid allowed host path empty path": { + psp: invalidAllowedHostPathMissingPath, + errorType: field.ErrorTypeRequired, + errorDetail: "is required", + }, + "invalid allowed host path with backsteps": { + psp: invalidAllowedHostPathBacksteps, + errorType: field.ErrorTypeInvalid, + errorDetail: "must not contain '..'", + }, + "empty flex volume driver": { + psp: emptyFlexDriver, + errorType: field.ErrorTypeRequired, + errorDetail: "must specify a driver", + }, + } + + for k, v := range errorCases { + errs := ValidatePodSecurityPolicy(v.psp) + if len(errs) == 0 { + t.Errorf("%s expected errors but got none", k) + continue + } + if errs[0].Type != v.errorType { + t.Errorf("[%s] received an unexpected error type. Expected: '%s' got: '%s'", k, v.errorType, errs[0].Type) + } + if errs[0].Detail != v.errorDetail { + t.Errorf("[%s] received an unexpected error detail. Expected '%s' got: '%s'", k, v.errorDetail, errs[0].Detail) + } + } + + // Update error is different for 'missing object meta name'. + errorCases["missing object meta name"] = testCase{ + psp: errorCases["missing object meta name"].psp, + errorType: field.ErrorTypeInvalid, + errorDetail: "field is immutable", + } + + // Should not be able to update to an invalid policy. + for k, v := range errorCases { + v.psp.ResourceVersion = "444" // Required for updates. + errs := ValidatePodSecurityPolicyUpdate(validPSP(), v.psp) + if len(errs) == 0 { + t.Errorf("[%s] expected update errors but got none", k) + continue + } + if errs[0].Type != v.errorType { + t.Errorf("[%s] received an unexpected error type. Expected: '%s' got: '%s'", k, v.errorType, errs[0].Type) + } + if errs[0].Detail != v.errorDetail { + t.Errorf("[%s] received an unexpected error detail. Expected '%s' got: '%s'", k, v.errorDetail, errs[0].Detail) + } + } + + mustRunAs := validPSP() + mustRunAs.Spec.FSGroup.Rule = policy.FSGroupStrategyMustRunAs + mustRunAs.Spec.SupplementalGroups.Rule = policy.SupplementalGroupsStrategyMustRunAs + mustRunAs.Spec.RunAsUser.Rule = policy.RunAsUserStrategyMustRunAs + mustRunAs.Spec.RunAsUser.Ranges = []policy.UserIDRange{ + {Min: 1, Max: 1}, + } + mustRunAs.Spec.SELinux.Rule = policy.SELinuxStrategyMustRunAs + + runAsNonRoot := validPSP() + runAsNonRoot.Spec.RunAsUser.Rule = policy.RunAsUserStrategyMustRunAsNonRoot + + caseInsensitiveAddDrop := validPSP() + caseInsensitiveAddDrop.Spec.DefaultAddCapabilities = []api.Capability{"foo"} + caseInsensitiveAddDrop.Spec.RequiredDropCapabilities = []api.Capability{"FOO"} + + caseInsensitiveAllowedDrop := validPSP() + caseInsensitiveAllowedDrop.Spec.RequiredDropCapabilities = []api.Capability{"FOO"} + caseInsensitiveAllowedDrop.Spec.AllowedCapabilities = []api.Capability{"foo"} + + validAppArmor := validPSP() + validAppArmor.Annotations = map[string]string{ + apparmor.DefaultProfileAnnotationKey: apparmor.ProfileRuntimeDefault, + apparmor.AllowedProfilesAnnotationKey: apparmor.ProfileRuntimeDefault + "," + apparmor.ProfileNamePrefix + "foo", + } + + withSysctl := validPSP() + withSysctl.Annotations[policy.SysctlsPodSecurityPolicyAnnotationKey] = "net.*" + + validSeccomp := validPSP() + validSeccomp.Annotations = map[string]string{ + seccomp.DefaultProfileAnnotationKey: "docker/default", + seccomp.AllowedProfilesAnnotationKey: "docker/default,unconfined,localhost/foo,*", + } + + validDefaultAllowPrivilegeEscalation := validPSP() + pe = true + validDefaultAllowPrivilegeEscalation.Spec.DefaultAllowPrivilegeEscalation = &pe + validDefaultAllowPrivilegeEscalation.Spec.AllowPrivilegeEscalation = true + + flexvolumeWhenFlexVolumesAllowed := validPSP() + flexvolumeWhenFlexVolumesAllowed.Spec.Volumes = []policy.FSType{policy.FlexVolume} + flexvolumeWhenFlexVolumesAllowed.Spec.AllowedFlexVolumes = []policy.AllowedFlexVolume{ + {Driver: "example/driver1"}, + } + + flexvolumeWhenAllVolumesAllowed := validPSP() + flexvolumeWhenAllVolumesAllowed.Spec.Volumes = []policy.FSType{policy.All} + flexvolumeWhenAllVolumesAllowed.Spec.AllowedFlexVolumes = []policy.AllowedFlexVolume{ + {Driver: "example/driver2"}, + } + successCases := map[string]struct { + psp *policy.PodSecurityPolicy + }{ + "must run as": { + psp: mustRunAs, + }, + "run as any": { + psp: validPSP(), + }, + "run as non-root (user only)": { + psp: runAsNonRoot, + }, + "comparison for add -> drop is case sensitive": { + psp: caseInsensitiveAddDrop, + }, + "comparison for allowed -> drop is case sensitive": { + psp: caseInsensitiveAllowedDrop, + }, + "valid AppArmor annotations": { + psp: validAppArmor, + }, + "with network sysctls": { + psp: withSysctl, + }, + "valid seccomp annotations": { + psp: validSeccomp, + }, + "valid defaultAllowPrivilegeEscalation as true": { + psp: validDefaultAllowPrivilegeEscalation, + }, + "allow white-listed flexVolume when flex volumes are allowed": { + psp: flexvolumeWhenFlexVolumesAllowed, + }, + "allow white-listed flexVolume when all volumes are allowed": { + psp: flexvolumeWhenAllVolumesAllowed, + }, + } + + for k, v := range successCases { + if errs := ValidatePodSecurityPolicy(v.psp); len(errs) != 0 { + t.Errorf("Expected success for %s, got %v", k, errs) + } + + // Should be able to update to a valid PSP. + v.psp.ResourceVersion = "444" // Required for updates. + if errs := ValidatePodSecurityPolicyUpdate(validPSP(), v.psp); len(errs) != 0 { + t.Errorf("Expected success for %s update, got %v", k, errs) + } + } +} + +func TestValidatePSPVolumes(t *testing.T) { + validPSP := func() *policy.PodSecurityPolicy { + return &policy.PodSecurityPolicy{ + ObjectMeta: metav1.ObjectMeta{Name: "foo"}, + Spec: policy.PodSecurityPolicySpec{ + SELinux: policy.SELinuxStrategyOptions{ + Rule: policy.SELinuxStrategyRunAsAny, + }, + RunAsUser: policy.RunAsUserStrategyOptions{ + Rule: policy.RunAsUserStrategyRunAsAny, + }, + FSGroup: policy.FSGroupStrategyOptions{ + Rule: policy.FSGroupStrategyRunAsAny, + }, + SupplementalGroups: policy.SupplementalGroupsStrategyOptions{ + Rule: policy.SupplementalGroupsStrategyRunAsAny, + }, + }, + } + } + + volumes := psputil.GetAllFSTypesAsSet() + // add in the * value since that is a pseudo type that is not included by default + volumes.Insert(string(policy.All)) + + for _, strVolume := range volumes.List() { + psp := validPSP() + psp.Spec.Volumes = []policy.FSType{policy.FSType(strVolume)} + errs := ValidatePodSecurityPolicy(psp) + if len(errs) != 0 { + t.Errorf("%s validation expected no errors but received %v", strVolume, errs) + } + } +} + +func TestIsValidSysctlPattern(t *testing.T) { + valid := []string{ + "a.b.c.d", + "a", + "a_b", + "a-b", + "abc", + "abc.def", + "*", + "a.*", + "*", + "abc*", + "a.abc*", + "a.b.*", + } + invalid := []string{ + "", + "รค", + "a_", + "_", + "_a", + "_a._b", + "__", + "-", + ".", + "a.", + ".a", + "a.b.", + "a*.b", + "a*b", + "*a", + "Abc", + func(n int) string { + x := make([]byte, n) + for i := range x { + x[i] = byte('a') + } + return string(x) + }(256), + } + for _, s := range valid { + if !IsValidSysctlPattern(s) { + t.Errorf("%q expected to be a valid sysctl pattern", s) + } + } + for _, s := range invalid { + if IsValidSysctlPattern(s) { + t.Errorf("%q expected to be an invalid sysctl pattern", s) + } + } +} + +func Test_validatePSPRunAsUser(t *testing.T) { + var testCases = []struct { + name string + runAsUserStrategy policy.RunAsUserStrategyOptions + fail bool + }{ + {"Invalid RunAsUserStrategy", policy.RunAsUserStrategyOptions{Rule: policy.RunAsUserStrategy("someInvalidStrategy")}, true}, + {"RunAsUserStrategyMustRunAs", policy.RunAsUserStrategyOptions{Rule: policy.RunAsUserStrategyMustRunAs}, false}, + {"RunAsUserStrategyMustRunAsNonRoot", policy.RunAsUserStrategyOptions{Rule: policy.RunAsUserStrategyMustRunAsNonRoot}, false}, + {"RunAsUserStrategyMustRunAsNonRoot With Valid Range", policy.RunAsUserStrategyOptions{Rule: policy.RunAsUserStrategyMustRunAs, Ranges: []policy.UserIDRange{{Min: 2, Max: 3}, {Min: 4, Max: 5}}}, false}, + {"RunAsUserStrategyMustRunAsNonRoot With Invalid Range", policy.RunAsUserStrategyOptions{Rule: policy.RunAsUserStrategyMustRunAs, Ranges: []policy.UserIDRange{{Min: 2, Max: 3}, {Min: 5, Max: 4}}}, true}, + } + + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + errList := validatePSPRunAsUser(field.NewPath("status"), &testCase.runAsUserStrategy) + actualErrors := len(errList) + expectedErrors := 1 + if !testCase.fail { + expectedErrors = 0 + } + if actualErrors != expectedErrors { + t.Errorf("In testCase %v, expected %v errors, got %v errors", testCase.name, expectedErrors, actualErrors) + } + }) + } +} diff --git a/pkg/kubelet/sysctl/whitelist.go b/pkg/kubelet/sysctl/whitelist.go index e236f795231..8269e94bb37 100644 --- a/pkg/kubelet/sysctl/whitelist.go +++ b/pkg/kubelet/sysctl/whitelist.go @@ -22,7 +22,7 @@ import ( v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" "k8s.io/kubernetes/pkg/apis/core/validation" - extvalidation "k8s.io/kubernetes/pkg/apis/extensions/validation" + policyvalidation "k8s.io/kubernetes/pkg/apis/policy/validation" "k8s.io/kubernetes/pkg/kubelet/lifecycle" ) @@ -64,11 +64,11 @@ func NewWhitelist(patterns []string, annotationKey string) (*patternWhitelist, e } for _, s := range patterns { - if !extvalidation.IsValidSysctlPattern(s) { + if !policyvalidation.IsValidSysctlPattern(s) { return nil, fmt.Errorf("sysctl %q must have at most %d characters and match regex %s", s, validation.SysctlMaxLength, - extvalidation.SysctlPatternFmt, + policyvalidation.SysctlPatternFmt, ) } if strings.HasSuffix(s, "*") { diff --git a/pkg/printers/internalversion/describe.go b/pkg/printers/internalversion/describe.go index 14ba72c465e..8be77ab1ec5 100644 --- a/pkg/printers/internalversion/describe.go +++ b/pkg/printers/internalversion/describe.go @@ -3475,7 +3475,7 @@ type PodSecurityPolicyDescriber struct { } func (d *PodSecurityPolicyDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) { - psp, err := d.Extensions().PodSecurityPolicies().Get(name, metav1.GetOptions{}) + psp, err := d.Policy().PodSecurityPolicies().Get(name, metav1.GetOptions{}) if err != nil { return "", err } @@ -3483,7 +3483,7 @@ func (d *PodSecurityPolicyDescriber) Describe(namespace, name string, describerS return describePodSecurityPolicy(psp) } -func describePodSecurityPolicy(psp *extensions.PodSecurityPolicy) (string, error) { +func describePodSecurityPolicy(psp *policy.PodSecurityPolicy) (string, error) { return tabbedString(func(out io.Writer) error { w := NewPrefixWriter(out) w.Write(LEVEL_0, "Name:\t%s\n", psp.Name) @@ -3543,7 +3543,7 @@ func stringOrDefaultValue(s, defaultValue string) string { return defaultValue } -func fsTypeToString(volumes []extensions.FSType) string { +func fsTypeToString(volumes []policy.FSType) string { strVolumes := []string{} for _, v := range volumes { strVolumes = append(strVolumes, string(v)) @@ -3551,7 +3551,7 @@ func fsTypeToString(volumes []extensions.FSType) string { return stringOrNone(strings.Join(strVolumes, ",")) } -func flexVolumesToString(flexVolumes []extensions.AllowedFlexVolume) string { +func flexVolumesToString(flexVolumes []policy.AllowedFlexVolume) string { volumes := []string{} for _, flexVolume := range flexVolumes { volumes = append(volumes, "driver="+flexVolume.Driver) @@ -3559,7 +3559,7 @@ func flexVolumesToString(flexVolumes []extensions.AllowedFlexVolume) string { return stringOrDefaultValue(strings.Join(volumes, ","), "") } -func hostPortRangeToString(ranges []extensions.HostPortRange) string { +func hostPortRangeToString(ranges []policy.HostPortRange) string { formattedString := "" if ranges != nil { strRanges := []string{} @@ -3571,7 +3571,7 @@ func hostPortRangeToString(ranges []extensions.HostPortRange) string { return stringOrNone(formattedString) } -func userIDRangeToString(ranges []extensions.UserIDRange) string { +func userIDRangeToString(ranges []policy.UserIDRange) string { formattedString := "" if ranges != nil { strRanges := []string{} @@ -3583,7 +3583,7 @@ func userIDRangeToString(ranges []extensions.UserIDRange) string { return stringOrNone(formattedString) } -func groupIDRangeToString(ranges []extensions.GroupIDRange) string { +func groupIDRangeToString(ranges []policy.GroupIDRange) string { formattedString := "" if ranges != nil { strRanges := []string{} diff --git a/pkg/printers/internalversion/describe_test.go b/pkg/printers/internalversion/describe_test.go index a49b812d9fc..70b906aaf1c 100644 --- a/pkg/printers/internalversion/describe_test.go +++ b/pkg/printers/internalversion/describe_test.go @@ -2187,22 +2187,22 @@ func TestDescribePodSecurityPolicy(t *testing.T) { "Supplemental Groups Strategy: RunAsAny", } - fake := fake.NewSimpleClientset(&extensions.PodSecurityPolicy{ + fake := fake.NewSimpleClientset(&policy.PodSecurityPolicy{ ObjectMeta: metav1.ObjectMeta{ Name: "mypsp", }, - Spec: extensions.PodSecurityPolicySpec{ - SELinux: extensions.SELinuxStrategyOptions{ - Rule: extensions.SELinuxStrategyRunAsAny, + Spec: policy.PodSecurityPolicySpec{ + SELinux: policy.SELinuxStrategyOptions{ + Rule: policy.SELinuxStrategyRunAsAny, }, - RunAsUser: extensions.RunAsUserStrategyOptions{ - Rule: extensions.RunAsUserStrategyRunAsAny, + RunAsUser: policy.RunAsUserStrategyOptions{ + Rule: policy.RunAsUserStrategyRunAsAny, }, - FSGroup: extensions.FSGroupStrategyOptions{ - Rule: extensions.FSGroupStrategyRunAsAny, + FSGroup: policy.FSGroupStrategyOptions{ + Rule: policy.FSGroupStrategyRunAsAny, }, - SupplementalGroups: extensions.SupplementalGroupsStrategyOptions{ - Rule: extensions.SupplementalGroupsStrategyRunAsAny, + SupplementalGroups: policy.SupplementalGroupsStrategyOptions{ + Rule: policy.SupplementalGroupsStrategyRunAsAny, }, }, }) diff --git a/pkg/printers/internalversion/printers.go b/pkg/printers/internalversion/printers.go index 08475be5c09..c2834a8cd69 100644 --- a/pkg/printers/internalversion/printers.go +++ b/pkg/printers/internalversion/printers.go @@ -1619,7 +1619,7 @@ func printConfigMapList(list *api.ConfigMapList, options printers.PrintOptions) return rows, nil } -func printPodSecurityPolicy(obj *extensions.PodSecurityPolicy, options printers.PrintOptions) ([]metav1beta1.TableRow, error) { +func printPodSecurityPolicy(obj *policy.PodSecurityPolicy, options printers.PrintOptions) ([]metav1beta1.TableRow, error) { row := metav1beta1.TableRow{ Object: runtime.RawExtension{Object: obj}, } @@ -1640,7 +1640,7 @@ func printPodSecurityPolicy(obj *extensions.PodSecurityPolicy, options printers. return []metav1beta1.TableRow{row}, nil } -func printPodSecurityPolicyList(list *extensions.PodSecurityPolicyList, options printers.PrintOptions) ([]metav1beta1.TableRow, error) { +func printPodSecurityPolicyList(list *policy.PodSecurityPolicyList, options printers.PrintOptions) ([]metav1beta1.TableRow, error) { rows := make([]metav1beta1.TableRow, 0, len(list.Items)) for i := range list.Items { r, err := printPodSecurityPolicy(&list.Items[i], options) diff --git a/pkg/registry/extensions/podsecuritypolicy/storage/storage.go b/pkg/registry/extensions/podsecuritypolicy/storage/storage.go index ceaecefa3cc..20b3f651b2b 100644 --- a/pkg/registry/extensions/podsecuritypolicy/storage/storage.go +++ b/pkg/registry/extensions/podsecuritypolicy/storage/storage.go @@ -17,10 +17,11 @@ limitations under the License. package storage import ( + extensions "k8s.io/api/extensions/v1beta1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apiserver/pkg/registry/generic" genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" - "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/policy" "k8s.io/kubernetes/pkg/printers" printersinternal "k8s.io/kubernetes/pkg/printers/internalversion" printerstorage "k8s.io/kubernetes/pkg/printers/storage" @@ -35,8 +36,8 @@ type REST struct { // NewREST returns a RESTStorage object that will work against PodSecurityPolicy objects. func NewREST(optsGetter generic.RESTOptionsGetter) *REST { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &extensions.PodSecurityPolicy{} }, - NewListFunc: func() runtime.Object { return &extensions.PodSecurityPolicyList{} }, + NewFunc: func() runtime.Object { return &policy.PodSecurityPolicy{} }, + NewListFunc: func() runtime.Object { return &policy.PodSecurityPolicyList{} }, DefaultQualifiedResource: extensions.Resource("podsecuritypolicies"), CreateStrategy: podsecuritypolicy.Strategy, diff --git a/pkg/registry/extensions/podsecuritypolicy/storage/storage_test.go b/pkg/registry/extensions/podsecuritypolicy/storage/storage_test.go index d380c1ac032..8cca24c743e 100644 --- a/pkg/registry/extensions/podsecuritypolicy/storage/storage_test.go +++ b/pkg/registry/extensions/podsecuritypolicy/storage/storage_test.go @@ -20,9 +20,9 @@ import ( "testing" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/kubernetes/pkg/apis/extensions" - // Ensure that extensions/v1beta1 package is initialized. - _ "k8s.io/api/extensions/v1beta1" + "k8s.io/kubernetes/pkg/apis/policy" + // Ensure that policy/v1beta1 package is initialized. + _ "k8s.io/api/policy/v1beta1" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" @@ -33,7 +33,7 @@ import ( ) func newStorage(t *testing.T) (*REST, *etcdtesting.EtcdTestServer) { - etcdStorage, server := registrytest.NewEtcdStorage(t, "extensions") + etcdStorage, server := registrytest.NewEtcdStorage(t, "policy") restOptions := generic.RESTOptions{ StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, @@ -43,23 +43,23 @@ func newStorage(t *testing.T) (*REST, *etcdtesting.EtcdTestServer) { return NewREST(restOptions), server } -func validNewPodSecurityPolicy() *extensions.PodSecurityPolicy { - return &extensions.PodSecurityPolicy{ +func validNewPodSecurityPolicy() *policy.PodSecurityPolicy { + return &policy.PodSecurityPolicy{ ObjectMeta: metav1.ObjectMeta{ Name: "foo", }, - Spec: extensions.PodSecurityPolicySpec{ - SELinux: extensions.SELinuxStrategyOptions{ - Rule: extensions.SELinuxStrategyRunAsAny, + Spec: policy.PodSecurityPolicySpec{ + SELinux: policy.SELinuxStrategyOptions{ + Rule: policy.SELinuxStrategyRunAsAny, }, - RunAsUser: extensions.RunAsUserStrategyOptions{ - Rule: extensions.RunAsUserStrategyRunAsAny, + RunAsUser: policy.RunAsUserStrategyOptions{ + Rule: policy.RunAsUserStrategyRunAsAny, }, - FSGroup: extensions.FSGroupStrategyOptions{ - Rule: extensions.FSGroupStrategyRunAsAny, + FSGroup: policy.FSGroupStrategyOptions{ + Rule: policy.FSGroupStrategyRunAsAny, }, - SupplementalGroups: extensions.SupplementalGroupsStrategyOptions{ - Rule: extensions.SupplementalGroupsStrategyRunAsAny, + SupplementalGroups: policy.SupplementalGroupsStrategyOptions{ + Rule: policy.SupplementalGroupsStrategyRunAsAny, }, }, } @@ -76,7 +76,7 @@ func TestCreate(t *testing.T) { // valid psp, // invalid - &extensions.PodSecurityPolicy{ + &policy.PodSecurityPolicy{ ObjectMeta: metav1.ObjectMeta{Name: "name with spaces"}, }, ) @@ -92,7 +92,7 @@ func TestUpdate(t *testing.T) { validNewPodSecurityPolicy(), // updateFunc func(obj runtime.Object) runtime.Object { - object := obj.(*extensions.PodSecurityPolicy) + object := obj.(*policy.PodSecurityPolicy) object.Labels = map[string]string{"a": "b"} return object }, diff --git a/pkg/registry/extensions/podsecuritypolicy/strategy.go b/pkg/registry/extensions/podsecuritypolicy/strategy.go index 118b6914684..06d48e3a797 100644 --- a/pkg/registry/extensions/podsecuritypolicy/strategy.go +++ b/pkg/registry/extensions/podsecuritypolicy/strategy.go @@ -23,8 +23,8 @@ import ( "k8s.io/apiserver/pkg/registry/rest" "k8s.io/apiserver/pkg/storage/names" "k8s.io/kubernetes/pkg/api/legacyscheme" - "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/apis/extensions/validation" + "k8s.io/kubernetes/pkg/apis/policy" + "k8s.io/kubernetes/pkg/apis/policy/validation" ) // strategy implements behavior for PodSecurityPolicy objects @@ -63,9 +63,9 @@ func (strategy) Canonicalize(obj runtime.Object) { } func (strategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { - return validation.ValidatePodSecurityPolicy(obj.(*extensions.PodSecurityPolicy)) + return validation.ValidatePodSecurityPolicy(obj.(*policy.PodSecurityPolicy)) } func (strategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { - return validation.ValidatePodSecurityPolicyUpdate(old.(*extensions.PodSecurityPolicy), obj.(*extensions.PodSecurityPolicy)) + return validation.ValidatePodSecurityPolicyUpdate(old.(*policy.PodSecurityPolicy), obj.(*policy.PodSecurityPolicy)) } diff --git a/pkg/security/podsecuritypolicy/capabilities/capabilities.go b/pkg/security/podsecuritypolicy/capabilities/capabilities.go index bb713c7be1e..0e1f41c6175 100644 --- a/pkg/security/podsecuritypolicy/capabilities/capabilities.go +++ b/pkg/security/podsecuritypolicy/capabilities/capabilities.go @@ -22,7 +22,7 @@ import ( "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/validation/field" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/policy" ) // defaultCapabilities implements the Strategy interface @@ -100,7 +100,7 @@ func (s *defaultCapabilities) Validate(pod *api.Pod, container *api.Container, c } allowedAdd := makeCapSet(s.allowedCaps) - allowAllCaps := allowedAdd.Has(string(extensions.AllowAllCapabilities)) + allowAllCaps := allowedAdd.Has(string(policy.AllowAllCapabilities)) if allowAllCaps { // skip validation against allowed/defaultAdd/requiredDrop because all capabilities are allowed by a wildcard return allErrs diff --git a/pkg/security/podsecuritypolicy/capabilities/capabilities_test.go b/pkg/security/podsecuritypolicy/capabilities/capabilities_test.go index 56cf5db5a4e..6f752a03150 100644 --- a/pkg/security/podsecuritypolicy/capabilities/capabilities_test.go +++ b/pkg/security/podsecuritypolicy/capabilities/capabilities_test.go @@ -21,7 +21,7 @@ import ( "testing" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/policy" ) func TestGenerateAdds(t *testing.T) { @@ -278,7 +278,7 @@ func TestValidateAdds(t *testing.T) { }, }, "no required, all allowed, container requests valid": { - allowedCaps: []api.Capability{extensions.AllowAllCapabilities}, + allowedCaps: []api.Capability{policy.AllowAllCapabilities}, containerCaps: &api.Capabilities{ Add: []api.Capability{"foo"}, }, diff --git a/pkg/security/podsecuritypolicy/factory.go b/pkg/security/podsecuritypolicy/factory.go index 69cf3945d6a..a198058e6eb 100644 --- a/pkg/security/podsecuritypolicy/factory.go +++ b/pkg/security/podsecuritypolicy/factory.go @@ -21,7 +21,7 @@ import ( "k8s.io/apimachinery/pkg/util/errors" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/policy" "k8s.io/kubernetes/pkg/security/podsecuritypolicy/apparmor" "k8s.io/kubernetes/pkg/security/podsecuritypolicy/capabilities" "k8s.io/kubernetes/pkg/security/podsecuritypolicy/group" @@ -39,7 +39,7 @@ func NewSimpleStrategyFactory() StrategyFactory { return &simpleStrategyFactory{} } -func (f *simpleStrategyFactory) CreateStrategies(psp *extensions.PodSecurityPolicy, namespace string) (*ProviderStrategies, error) { +func (f *simpleStrategyFactory) CreateStrategies(psp *policy.PodSecurityPolicy, namespace string) (*ProviderStrategies, error) { errs := []error{} userStrat, err := createUserStrategy(&psp.Spec.RunAsUser) @@ -78,9 +78,9 @@ func (f *simpleStrategyFactory) CreateStrategies(psp *extensions.PodSecurityPoli } var unsafeSysctls []string - if ann, found := psp.Annotations[extensions.SysctlsPodSecurityPolicyAnnotationKey]; found { + if ann, found := psp.Annotations[policy.SysctlsPodSecurityPolicyAnnotationKey]; found { var err error - unsafeSysctls, err = extensions.SysctlsFromPodSecurityPolicyAnnotation(ann) + unsafeSysctls, err = policy.SysctlsFromPodSecurityPolicyAnnotation(ann) if err != nil { errs = append(errs, err) } @@ -106,13 +106,13 @@ func (f *simpleStrategyFactory) CreateStrategies(psp *extensions.PodSecurityPoli } // createUserStrategy creates a new user strategy. -func createUserStrategy(opts *extensions.RunAsUserStrategyOptions) (user.RunAsUserStrategy, error) { +func createUserStrategy(opts *policy.RunAsUserStrategyOptions) (user.RunAsUserStrategy, error) { switch opts.Rule { - case extensions.RunAsUserStrategyMustRunAs: + case policy.RunAsUserStrategyMustRunAs: return user.NewMustRunAs(opts) - case extensions.RunAsUserStrategyMustRunAsNonRoot: + case policy.RunAsUserStrategyMustRunAsNonRoot: return user.NewRunAsNonRoot(opts) - case extensions.RunAsUserStrategyRunAsAny: + case policy.RunAsUserStrategyRunAsAny: return user.NewRunAsAny(opts) default: return nil, fmt.Errorf("Unrecognized RunAsUser strategy type %s", opts.Rule) @@ -120,11 +120,11 @@ func createUserStrategy(opts *extensions.RunAsUserStrategyOptions) (user.RunAsUs } // createSELinuxStrategy creates a new selinux strategy. -func createSELinuxStrategy(opts *extensions.SELinuxStrategyOptions) (selinux.SELinuxStrategy, error) { +func createSELinuxStrategy(opts *policy.SELinuxStrategyOptions) (selinux.SELinuxStrategy, error) { switch opts.Rule { - case extensions.SELinuxStrategyMustRunAs: + case policy.SELinuxStrategyMustRunAs: return selinux.NewMustRunAs(opts) - case extensions.SELinuxStrategyRunAsAny: + case policy.SELinuxStrategyRunAsAny: return selinux.NewRunAsAny(opts) default: return nil, fmt.Errorf("Unrecognized SELinuxContext strategy type %s", opts.Rule) @@ -132,21 +132,21 @@ func createSELinuxStrategy(opts *extensions.SELinuxStrategyOptions) (selinux.SEL } // createAppArmorStrategy creates a new AppArmor strategy. -func createAppArmorStrategy(psp *extensions.PodSecurityPolicy) (apparmor.Strategy, error) { +func createAppArmorStrategy(psp *policy.PodSecurityPolicy) (apparmor.Strategy, error) { return apparmor.NewStrategy(psp.Annotations), nil } // createSeccompStrategy creates a new seccomp strategy. -func createSeccompStrategy(psp *extensions.PodSecurityPolicy) (seccomp.Strategy, error) { +func createSeccompStrategy(psp *policy.PodSecurityPolicy) (seccomp.Strategy, error) { return seccomp.NewStrategy(psp.Annotations), nil } // createFSGroupStrategy creates a new fsgroup strategy -func createFSGroupStrategy(opts *extensions.FSGroupStrategyOptions) (group.GroupStrategy, error) { +func createFSGroupStrategy(opts *policy.FSGroupStrategyOptions) (group.GroupStrategy, error) { switch opts.Rule { - case extensions.FSGroupStrategyRunAsAny: + case policy.FSGroupStrategyRunAsAny: return group.NewRunAsAny() - case extensions.FSGroupStrategyMustRunAs: + case policy.FSGroupStrategyMustRunAs: return group.NewMustRunAs(opts.Ranges, fsGroupField) default: return nil, fmt.Errorf("Unrecognized FSGroup strategy type %s", opts.Rule) @@ -154,11 +154,11 @@ func createFSGroupStrategy(opts *extensions.FSGroupStrategyOptions) (group.Group } // createSupplementalGroupStrategy creates a new supplemental group strategy -func createSupplementalGroupStrategy(opts *extensions.SupplementalGroupsStrategyOptions) (group.GroupStrategy, error) { +func createSupplementalGroupStrategy(opts *policy.SupplementalGroupsStrategyOptions) (group.GroupStrategy, error) { switch opts.Rule { - case extensions.SupplementalGroupsStrategyRunAsAny: + case policy.SupplementalGroupsStrategyRunAsAny: return group.NewRunAsAny() - case extensions.SupplementalGroupsStrategyMustRunAs: + case policy.SupplementalGroupsStrategyMustRunAs: return group.NewMustRunAs(opts.Ranges, supplementalGroupsField) default: return nil, fmt.Errorf("Unrecognized SupplementalGroups strategy type %s", opts.Rule) diff --git a/pkg/security/podsecuritypolicy/group/mustrunas.go b/pkg/security/podsecuritypolicy/group/mustrunas.go index 0ec73053dd3..5516351ccb8 100644 --- a/pkg/security/podsecuritypolicy/group/mustrunas.go +++ b/pkg/security/podsecuritypolicy/group/mustrunas.go @@ -21,20 +21,20 @@ import ( "k8s.io/apimachinery/pkg/util/validation/field" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/policy" psputil "k8s.io/kubernetes/pkg/security/podsecuritypolicy/util" ) // mustRunAs implements the GroupStrategy interface type mustRunAs struct { - ranges []extensions.GroupIDRange + ranges []policy.GroupIDRange field string } var _ GroupStrategy = &mustRunAs{} // NewMustRunAs provides a new MustRunAs strategy based on ranges. -func NewMustRunAs(ranges []extensions.GroupIDRange, field string) (GroupStrategy, error) { +func NewMustRunAs(ranges []policy.GroupIDRange, field string) (GroupStrategy, error) { if len(ranges) == 0 { return nil, fmt.Errorf("ranges must be supplied for MustRunAs") } diff --git a/pkg/security/podsecuritypolicy/group/mustrunas_test.go b/pkg/security/podsecuritypolicy/group/mustrunas_test.go index 1e7dfe779eb..970c4fd4633 100644 --- a/pkg/security/podsecuritypolicy/group/mustrunas_test.go +++ b/pkg/security/podsecuritypolicy/group/mustrunas_test.go @@ -20,19 +20,19 @@ import ( "strings" "testing" - "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/policy" ) func TestMustRunAsOptions(t *testing.T) { tests := map[string]struct { - ranges []extensions.GroupIDRange + ranges []policy.GroupIDRange pass bool }{ "empty": { - ranges: []extensions.GroupIDRange{}, + ranges: []policy.GroupIDRange{}, }, "ranges": { - ranges: []extensions.GroupIDRange{ + ranges: []policy.GroupIDRange{ {Min: 1, Max: 1}, }, pass: true, @@ -52,23 +52,23 @@ func TestMustRunAsOptions(t *testing.T) { func TestGenerate(t *testing.T) { tests := map[string]struct { - ranges []extensions.GroupIDRange + ranges []policy.GroupIDRange expected []int64 }{ "multi value": { - ranges: []extensions.GroupIDRange{ + ranges: []policy.GroupIDRange{ {Min: 1, Max: 2}, }, expected: []int64{1}, }, "single value": { - ranges: []extensions.GroupIDRange{ + ranges: []policy.GroupIDRange{ {Min: 1, Max: 1}, }, expected: []int64{1}, }, "multi range": { - ranges: []extensions.GroupIDRange{ + ranges: []policy.GroupIDRange{ {Min: 1, Max: 1}, {Min: 2, Max: 500}, }, @@ -110,25 +110,25 @@ func TestGenerate(t *testing.T) { func TestValidate(t *testing.T) { tests := map[string]struct { - ranges []extensions.GroupIDRange + ranges []policy.GroupIDRange groups []int64 expectedError string }{ "nil security context": { - ranges: []extensions.GroupIDRange{ + ranges: []policy.GroupIDRange{ {Min: 1, Max: 3}, }, expectedError: "unable to validate empty groups against required ranges", }, "empty groups": { - ranges: []extensions.GroupIDRange{ + ranges: []policy.GroupIDRange{ {Min: 1, Max: 3}, }, expectedError: "unable to validate empty groups against required ranges", }, "not in range": { groups: []int64{5}, - ranges: []extensions.GroupIDRange{ + ranges: []policy.GroupIDRange{ {Min: 1, Max: 3}, {Min: 4, Max: 4}, }, @@ -136,25 +136,25 @@ func TestValidate(t *testing.T) { }, "in range 1": { groups: []int64{2}, - ranges: []extensions.GroupIDRange{ + ranges: []policy.GroupIDRange{ {Min: 1, Max: 3}, }, }, "in range boundary min": { groups: []int64{1}, - ranges: []extensions.GroupIDRange{ + ranges: []policy.GroupIDRange{ {Min: 1, Max: 3}, }, }, "in range boundary max": { groups: []int64{3}, - ranges: []extensions.GroupIDRange{ + ranges: []policy.GroupIDRange{ {Min: 1, Max: 3}, }, }, "singular range": { groups: []int64{4}, - ranges: []extensions.GroupIDRange{ + ranges: []policy.GroupIDRange{ {Min: 4, Max: 4}, }, }, diff --git a/pkg/security/podsecuritypolicy/provider.go b/pkg/security/podsecuritypolicy/provider.go index 9554e018dbe..2fe3d96699a 100644 --- a/pkg/security/podsecuritypolicy/provider.go +++ b/pkg/security/podsecuritypolicy/provider.go @@ -22,7 +22,7 @@ import ( "k8s.io/apimachinery/pkg/util/validation/field" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/policy" psputil "k8s.io/kubernetes/pkg/security/podsecuritypolicy/util" "k8s.io/kubernetes/pkg/securitycontext" ) @@ -36,7 +36,7 @@ const ( // simpleProvider is the default implementation of Provider. type simpleProvider struct { - psp *extensions.PodSecurityPolicy + psp *policy.PodSecurityPolicy strategies *ProviderStrategies } @@ -44,7 +44,7 @@ type simpleProvider struct { var _ Provider = &simpleProvider{} // NewSimpleProvider creates a new Provider instance. -func NewSimpleProvider(psp *extensions.PodSecurityPolicy, namespace string, strategyFactory StrategyFactory) (Provider, error) { +func NewSimpleProvider(psp *policy.PodSecurityPolicy, namespace string, strategyFactory StrategyFactory) (Provider, error) { if psp == nil { return nil, fmt.Errorf("NewSimpleProvider requires a PodSecurityPolicy") } @@ -144,7 +144,7 @@ func (s *simpleProvider) DefaultContainerSecurityContext(pod *api.Pod, container // if we're using the non-root strategy set the marker that this container should not be // run as root which will signal to the kubelet to do a final check either on the runAsUser // or, if runAsUser is not set, the image UID will be checked. - if sc.RunAsNonRoot() == nil && sc.RunAsUser() == nil && s.psp.Spec.RunAsUser.Rule == extensions.RunAsUserStrategyMustRunAsNonRoot { + if sc.RunAsNonRoot() == nil && sc.RunAsUser() == nil && s.psp.Spec.RunAsUser.Rule == policy.RunAsUserStrategyMustRunAsNonRoot { nonRoot := true sc.SetRunAsNonRoot(&nonRoot) } @@ -226,7 +226,7 @@ func (s *simpleProvider) ValidatePod(pod *api.Pod, fldPath *field.Path) field.Er continue } - if fsType == extensions.HostPath { + if fsType == policy.HostPath { if !psputil.AllowsHostVolumePath(s.psp, v.HostPath.Path) { allErrs = append(allErrs, field.Invalid( field.NewPath("spec", "volumes").Index(i).Child("hostPath", "pathPrefix"), v.HostPath.Path, @@ -234,7 +234,7 @@ func (s *simpleProvider) ValidatePod(pod *api.Pod, fldPath *field.Path) field.Er } } - if fsType == extensions.FlexVolume && len(s.psp.Spec.AllowedFlexVolumes) > 0 { + if fsType == policy.FlexVolume && len(s.psp.Spec.AllowedFlexVolumes) > 0 { found := false driver := v.FlexVolume.Driver for _, allowedFlexVolume := range s.psp.Spec.AllowedFlexVolumes { @@ -333,7 +333,7 @@ func (s *simpleProvider) GetPSPName() string { return s.psp.Name } -func hostPortRangesToString(ranges []extensions.HostPortRange) string { +func hostPortRangesToString(ranges []policy.HostPortRange) string { formattedString := "" if ranges != nil { strRanges := []string{} diff --git a/pkg/security/podsecuritypolicy/provider_test.go b/pkg/security/podsecuritypolicy/provider_test.go index 983393eb127..4d8747c7494 100644 --- a/pkg/security/podsecuritypolicy/provider_test.go +++ b/pkg/security/podsecuritypolicy/provider_test.go @@ -30,7 +30,7 @@ import ( "k8s.io/apimachinery/pkg/util/validation/field" api "k8s.io/kubernetes/pkg/apis/core" k8s_api_v1 "k8s.io/kubernetes/pkg/apis/core/v1" - "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/policy" "k8s.io/kubernetes/pkg/security/apparmor" "k8s.io/kubernetes/pkg/security/podsecuritypolicy/seccomp" psputil "k8s.io/kubernetes/pkg/security/podsecuritypolicy/util" @@ -49,27 +49,27 @@ func TestDefaultPodSecurityContextNonmutating(t *testing.T) { } // Create a PSP with strategies that will populate a blank psc - createPSP := func() *extensions.PodSecurityPolicy { - return &extensions.PodSecurityPolicy{ + createPSP := func() *policy.PodSecurityPolicy { + return &policy.PodSecurityPolicy{ ObjectMeta: metav1.ObjectMeta{ Name: "psp-sa", Annotations: map[string]string{ seccomp.AllowedProfilesAnnotationKey: "*", }, }, - Spec: extensions.PodSecurityPolicySpec{ + Spec: policy.PodSecurityPolicySpec{ AllowPrivilegeEscalation: true, - RunAsUser: extensions.RunAsUserStrategyOptions{ - Rule: extensions.RunAsUserStrategyRunAsAny, + RunAsUser: policy.RunAsUserStrategyOptions{ + Rule: policy.RunAsUserStrategyRunAsAny, }, - SELinux: extensions.SELinuxStrategyOptions{ - Rule: extensions.SELinuxStrategyRunAsAny, + SELinux: policy.SELinuxStrategyOptions{ + Rule: policy.SELinuxStrategyRunAsAny, }, - FSGroup: extensions.FSGroupStrategyOptions{ - Rule: extensions.FSGroupStrategyRunAsAny, + FSGroup: policy.FSGroupStrategyOptions{ + Rule: policy.FSGroupStrategyRunAsAny, }, - SupplementalGroups: extensions.SupplementalGroupsStrategyOptions{ - Rule: extensions.SupplementalGroupsStrategyRunAsAny, + SupplementalGroups: policy.SupplementalGroupsStrategyOptions{ + Rule: policy.SupplementalGroupsStrategyRunAsAny, }, }, } @@ -120,8 +120,8 @@ func TestDefaultContainerSecurityContextNonmutating(t *testing.T) { } // Create a PSP with strategies that will populate a blank security context - createPSP := func() *extensions.PodSecurityPolicy { - return &extensions.PodSecurityPolicy{ + createPSP := func() *policy.PodSecurityPolicy { + return &policy.PodSecurityPolicy{ ObjectMeta: metav1.ObjectMeta{ Name: "psp-sa", Annotations: map[string]string{ @@ -129,19 +129,19 @@ func TestDefaultContainerSecurityContextNonmutating(t *testing.T) { seccomp.DefaultProfileAnnotationKey: "foo", }, }, - Spec: extensions.PodSecurityPolicySpec{ + Spec: policy.PodSecurityPolicySpec{ AllowPrivilegeEscalation: true, - RunAsUser: extensions.RunAsUserStrategyOptions{ - Rule: extensions.RunAsUserStrategyRunAsAny, + RunAsUser: policy.RunAsUserStrategyOptions{ + Rule: policy.RunAsUserStrategyRunAsAny, }, - SELinux: extensions.SELinuxStrategyOptions{ - Rule: extensions.SELinuxStrategyRunAsAny, + SELinux: policy.SELinuxStrategyOptions{ + Rule: policy.SELinuxStrategyRunAsAny, }, - FSGroup: extensions.FSGroupStrategyOptions{ - Rule: extensions.FSGroupStrategyRunAsAny, + FSGroup: policy.FSGroupStrategyOptions{ + Rule: policy.FSGroupStrategyRunAsAny, }, - SupplementalGroups: extensions.SupplementalGroupsStrategyOptions{ - Rule: extensions.SupplementalGroupsStrategyRunAsAny, + SupplementalGroups: policy.SupplementalGroupsStrategyOptions{ + Rule: policy.SupplementalGroupsStrategyRunAsAny, }, }, } @@ -184,9 +184,9 @@ func TestValidatePodSecurityContextFailures(t *testing.T) { failSupplementalGroupPod := defaultPod() failSupplementalGroupPod.Spec.SecurityContext.SupplementalGroups = []int64{999} failSupplementalGroupPSP := defaultPSP() - failSupplementalGroupPSP.Spec.SupplementalGroups = extensions.SupplementalGroupsStrategyOptions{ - Rule: extensions.SupplementalGroupsStrategyMustRunAs, - Ranges: []extensions.GroupIDRange{ + failSupplementalGroupPSP.Spec.SupplementalGroups = policy.SupplementalGroupsStrategyOptions{ + Rule: policy.SupplementalGroupsStrategyMustRunAs, + Ranges: []policy.GroupIDRange{ {Min: 1, Max: 1}, }, } @@ -195,16 +195,16 @@ func TestValidatePodSecurityContextFailures(t *testing.T) { fsGroup := int64(999) failFSGroupPod.Spec.SecurityContext.FSGroup = &fsGroup failFSGroupPSP := defaultPSP() - failFSGroupPSP.Spec.FSGroup = extensions.FSGroupStrategyOptions{ - Rule: extensions.FSGroupStrategyMustRunAs, - Ranges: []extensions.GroupIDRange{ + failFSGroupPSP.Spec.FSGroup = policy.FSGroupStrategyOptions{ + Rule: policy.FSGroupStrategyMustRunAs, + Ranges: []policy.GroupIDRange{ {Min: 1, Max: 1}, }, } failNilSELinuxPod := defaultPod() failSELinuxPSP := defaultPSP() - failSELinuxPSP.Spec.SELinux.Rule = extensions.SELinuxStrategyMustRunAs + failSELinuxPSP.Spec.SELinux.Rule = policy.SELinuxStrategyMustRunAs failSELinuxPSP.Spec.SELinux.SELinuxOptions = &api.SELinuxOptions{ Level: "foo", } @@ -236,16 +236,16 @@ func TestValidatePodSecurityContextFailures(t *testing.T) { }, } failHostPathDirPSP := defaultPSP() - failHostPathDirPSP.Spec.Volumes = []extensions.FSType{extensions.HostPath} - failHostPathDirPSP.Spec.AllowedHostPaths = []extensions.AllowedHostPath{ + failHostPathDirPSP.Spec.Volumes = []policy.FSType{policy.HostPath} + failHostPathDirPSP.Spec.AllowedHostPaths = []policy.AllowedHostPath{ {PathPrefix: "/foo/bar"}, } failOtherSysctlsAllowedPSP := defaultPSP() - failOtherSysctlsAllowedPSP.Annotations[extensions.SysctlsPodSecurityPolicyAnnotationKey] = "bar,abc" + failOtherSysctlsAllowedPSP.Annotations[policy.SysctlsPodSecurityPolicyAnnotationKey] = "bar,abc" failNoSysctlAllowedPSP := defaultPSP() - failNoSysctlAllowedPSP.Annotations[extensions.SysctlsPodSecurityPolicyAnnotationKey] = "" + failNoSysctlAllowedPSP.Annotations[policy.SysctlsPodSecurityPolicyAnnotationKey] = "" failSafeSysctlFooPod := defaultPod() failSafeSysctlFooPod.Annotations[api.SysctlsPodAnnotationKey] = "foo=1" @@ -270,7 +270,7 @@ func TestValidatePodSecurityContextFailures(t *testing.T) { errorCases := map[string]struct { pod *api.Pod - psp *extensions.PodSecurityPolicy + psp *policy.PodSecurityPolicy expectedError string }{ "failHostNetwork": { @@ -380,24 +380,24 @@ func TestValidatePodSecurityContextFailures(t *testing.T) { } } -func allowFlexVolumesPSP(allowAllFlexVolumes, allowAllVolumes bool) *extensions.PodSecurityPolicy { +func allowFlexVolumesPSP(allowAllFlexVolumes, allowAllVolumes bool) *policy.PodSecurityPolicy { psp := defaultPSP() - allowedVolumes := []extensions.AllowedFlexVolume{ + allowedVolumes := []policy.AllowedFlexVolume{ {Driver: "example/foo"}, {Driver: "example/bar"}, } if allowAllFlexVolumes { - allowedVolumes = []extensions.AllowedFlexVolume{} + allowedVolumes = []policy.AllowedFlexVolume{} } - allowedVolumeType := extensions.FlexVolume + allowedVolumeType := policy.FlexVolume if allowAllVolumes { - allowedVolumeType = extensions.All + allowedVolumeType = policy.All } psp.Spec.AllowedFlexVolumes = allowedVolumes - psp.Spec.Volumes = []extensions.FSType{allowedVolumeType} + psp.Spec.Volumes = []policy.FSType{allowedVolumeType} return psp } @@ -407,17 +407,17 @@ func TestValidateContainerSecurityContextFailures(t *testing.T) { failUserPSP := defaultPSP() uid := int64(999) badUID := int64(1) - failUserPSP.Spec.RunAsUser = extensions.RunAsUserStrategyOptions{ - Rule: extensions.RunAsUserStrategyMustRunAs, - Ranges: []extensions.UserIDRange{{Min: uid, Max: uid}}, + failUserPSP.Spec.RunAsUser = policy.RunAsUserStrategyOptions{ + Rule: policy.RunAsUserStrategyMustRunAs, + Ranges: []policy.UserIDRange{{Min: uid, Max: uid}}, } failUserPod := defaultPod() failUserPod.Spec.Containers[0].SecurityContext.RunAsUser = &badUID // fail selinux strategy failSELinuxPSP := defaultPSP() - failSELinuxPSP.Spec.SELinux = extensions.SELinuxStrategyOptions{ - Rule: extensions.SELinuxStrategyMustRunAs, + failSELinuxPSP.Spec.SELinux = policy.SELinuxStrategyOptions{ + Rule: policy.SELinuxStrategyMustRunAs, SELinuxOptions: &api.SELinuxOptions{ Level: "foo", }, @@ -469,7 +469,7 @@ func TestValidateContainerSecurityContextFailures(t *testing.T) { errorCases := map[string]struct { pod *api.Pod - psp *extensions.PodSecurityPolicy + psp *policy.PodSecurityPolicy expectedError string }{ "failUserPSP": { @@ -562,9 +562,9 @@ func TestValidatePodSecurityContextSuccess(t *testing.T) { hostIPCPod.Spec.SecurityContext.HostIPC = true supGroupPSP := defaultPSP() - supGroupPSP.Spec.SupplementalGroups = extensions.SupplementalGroupsStrategyOptions{ - Rule: extensions.SupplementalGroupsStrategyMustRunAs, - Ranges: []extensions.GroupIDRange{ + supGroupPSP.Spec.SupplementalGroups = policy.SupplementalGroupsStrategyOptions{ + Rule: policy.SupplementalGroupsStrategyMustRunAs, + Ranges: []policy.GroupIDRange{ {Min: 1, Max: 5}, }, } @@ -572,9 +572,9 @@ func TestValidatePodSecurityContextSuccess(t *testing.T) { supGroupPod.Spec.SecurityContext.SupplementalGroups = []int64{3} fsGroupPSP := defaultPSP() - fsGroupPSP.Spec.FSGroup = extensions.FSGroupStrategyOptions{ - Rule: extensions.FSGroupStrategyMustRunAs, - Ranges: []extensions.GroupIDRange{ + fsGroupPSP.Spec.FSGroup = policy.FSGroupStrategyOptions{ + Rule: policy.FSGroupStrategyMustRunAs, + Ranges: []policy.GroupIDRange{ {Min: 1, Max: 5}, }, } @@ -590,7 +590,7 @@ func TestValidatePodSecurityContextSuccess(t *testing.T) { Level: "level", } seLinuxPSP := defaultPSP() - seLinuxPSP.Spec.SELinux.Rule = extensions.SELinuxStrategyMustRunAs + seLinuxPSP.Spec.SELinux.Rule = policy.SELinuxStrategyMustRunAs seLinuxPSP.Spec.SELinux.SELinuxOptions = &api.SELinuxOptions{ User: "user", Role: "role", @@ -611,19 +611,19 @@ func TestValidatePodSecurityContextSuccess(t *testing.T) { } hostPathDirPSP := defaultPSP() - hostPathDirPSP.Spec.Volumes = []extensions.FSType{extensions.HostPath} - hostPathDirPSP.Spec.AllowedHostPaths = []extensions.AllowedHostPath{ + hostPathDirPSP.Spec.Volumes = []policy.FSType{policy.HostPath} + hostPathDirPSP.Spec.AllowedHostPaths = []policy.AllowedHostPath{ {PathPrefix: "/foo/bar"}, } hostPathDirAsterisksPSP := defaultPSP() - hostPathDirAsterisksPSP.Spec.Volumes = []extensions.FSType{extensions.All} - hostPathDirAsterisksPSP.Spec.AllowedHostPaths = []extensions.AllowedHostPath{ + hostPathDirAsterisksPSP.Spec.Volumes = []policy.FSType{policy.All} + hostPathDirAsterisksPSP.Spec.AllowedHostPaths = []policy.AllowedHostPath{ {PathPrefix: "/foo/bar"}, } sysctlAllowFooPSP := defaultPSP() - sysctlAllowFooPSP.Annotations[extensions.SysctlsPodSecurityPolicyAnnotationKey] = "foo" + sysctlAllowFooPSP.Annotations[policy.SysctlsPodSecurityPolicyAnnotationKey] = "foo" safeSysctlFooPod := defaultPod() safeSysctlFooPod.Annotations[api.SysctlsPodAnnotationKey] = "foo=1" @@ -655,7 +655,7 @@ func TestValidatePodSecurityContextSuccess(t *testing.T) { successCases := map[string]struct { pod *api.Pod - psp *extensions.PodSecurityPolicy + psp *policy.PodSecurityPolicy }{ "pass hostNetwork validating PSP": { pod: hostNetworkPod, @@ -744,17 +744,17 @@ func TestValidateContainerSecurityContextSuccess(t *testing.T) { // success user strategy userPSP := defaultPSP() uid := int64(999) - userPSP.Spec.RunAsUser = extensions.RunAsUserStrategyOptions{ - Rule: extensions.RunAsUserStrategyMustRunAs, - Ranges: []extensions.UserIDRange{{Min: uid, Max: uid}}, + userPSP.Spec.RunAsUser = policy.RunAsUserStrategyOptions{ + Rule: policy.RunAsUserStrategyMustRunAs, + Ranges: []policy.UserIDRange{{Min: uid, Max: uid}}, } userPod := defaultPod() userPod.Spec.Containers[0].SecurityContext.RunAsUser = &uid // success selinux strategy seLinuxPSP := defaultPSP() - seLinuxPSP.Spec.SELinux = extensions.SELinuxStrategyOptions{ - Rule: extensions.SELinuxStrategyMustRunAs, + seLinuxPSP.Spec.SELinux = policy.SELinuxStrategyOptions{ + Rule: policy.SELinuxStrategyMustRunAs, SELinuxOptions: &api.SELinuxOptions{ Level: "foo", }, @@ -795,7 +795,7 @@ func TestValidateContainerSecurityContextSuccess(t *testing.T) { } hostDirPSP := defaultPSP() - hostDirPSP.Spec.Volumes = []extensions.FSType{extensions.HostPath} + hostDirPSP.Spec.Volumes = []policy.FSType{policy.HostPath} hostDirPod := defaultPod() hostDirPod.Spec.Volumes = []api.Volume{ { @@ -807,7 +807,7 @@ func TestValidateContainerSecurityContextSuccess(t *testing.T) { } hostPortPSP := defaultPSP() - hostPortPSP.Spec.HostPorts = []extensions.HostPortRange{{Min: 1, Max: 1}} + hostPortPSP.Spec.HostPorts = []policy.HostPortRange{{Min: 1, Max: 1}} hostPortPod := defaultPod() hostPortPod.Spec.Containers[0].Ports = []api.ContainerPort{{HostPort: 1}} @@ -836,7 +836,7 @@ func TestValidateContainerSecurityContextSuccess(t *testing.T) { successCases := map[string]struct { pod *api.Pod - psp *extensions.PodSecurityPolicy + psp *policy.PodSecurityPolicy }{ "pass user must run as PSP": { pod: userPod, @@ -922,7 +922,7 @@ func TestGenerateContainerSecurityContextReadOnlyRootFS(t *testing.T) { tests := map[string]struct { pod *api.Pod - psp *extensions.PodSecurityPolicy + psp *policy.PodSecurityPolicy expected *bool }{ "false psp, nil sc": { @@ -985,24 +985,24 @@ func TestGenerateContainerSecurityContextReadOnlyRootFS(t *testing.T) { } } -func defaultPSP() *extensions.PodSecurityPolicy { - return &extensions.PodSecurityPolicy{ +func defaultPSP() *policy.PodSecurityPolicy { + return &policy.PodSecurityPolicy{ ObjectMeta: metav1.ObjectMeta{ Name: "psp-sa", Annotations: map[string]string{}, }, - Spec: extensions.PodSecurityPolicySpec{ - RunAsUser: extensions.RunAsUserStrategyOptions{ - Rule: extensions.RunAsUserStrategyRunAsAny, + Spec: policy.PodSecurityPolicySpec{ + RunAsUser: policy.RunAsUserStrategyOptions{ + Rule: policy.RunAsUserStrategyRunAsAny, }, - SELinux: extensions.SELinuxStrategyOptions{ - Rule: extensions.SELinuxStrategyRunAsAny, + SELinux: policy.SELinuxStrategyOptions{ + Rule: policy.SELinuxStrategyRunAsAny, }, - FSGroup: extensions.FSGroupStrategyOptions{ - Rule: extensions.FSGroupStrategyRunAsAny, + FSGroup: policy.FSGroupStrategyOptions{ + Rule: policy.FSGroupStrategyRunAsAny, }, - SupplementalGroups: extensions.SupplementalGroupsStrategyOptions{ - Rule: extensions.SupplementalGroupsStrategyRunAsAny, + SupplementalGroups: policy.SupplementalGroupsStrategyOptions{ + Rule: policy.SupplementalGroupsStrategyRunAsAny, }, AllowPrivilegeEscalation: true, }, @@ -1104,14 +1104,14 @@ func TestValidateAllowedVolumes(t *testing.T) { } // now add the fstype directly to the psp and it should validate - psp.Spec.Volumes = []extensions.FSType{fsType} + psp.Spec.Volumes = []policy.FSType{fsType} errs = provider.ValidatePod(pod, field.NewPath("")) if len(errs) != 0 { t.Errorf("directly allowing volume expected no errors for %s but got %v", fieldVal.Name, errs) } // now change the psp to allow any volumes and the pod should still validate - psp.Spec.Volumes = []extensions.FSType{extensions.All} + psp.Spec.Volumes = []policy.FSType{policy.All} errs = provider.ValidatePod(pod, field.NewPath("")) if len(errs) != 0 { t.Errorf("wildcard volume expected no errors for %s but got %v", fieldVal.Name, errs) diff --git a/pkg/security/podsecuritypolicy/selinux/mustrunas.go b/pkg/security/podsecuritypolicy/selinux/mustrunas.go index 67f23b99508..e958555ffa6 100644 --- a/pkg/security/podsecuritypolicy/selinux/mustrunas.go +++ b/pkg/security/podsecuritypolicy/selinux/mustrunas.go @@ -23,17 +23,17 @@ import ( "k8s.io/apimachinery/pkg/util/validation/field" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/policy" "k8s.io/kubernetes/pkg/security/podsecuritypolicy/util" ) type mustRunAs struct { - opts *extensions.SELinuxStrategyOptions + opts *policy.SELinuxStrategyOptions } var _ SELinuxStrategy = &mustRunAs{} -func NewMustRunAs(options *extensions.SELinuxStrategyOptions) (SELinuxStrategy, error) { +func NewMustRunAs(options *policy.SELinuxStrategyOptions) (SELinuxStrategy, error) { if options == nil { return nil, fmt.Errorf("MustRunAs requires SELinuxContextStrategyOptions") } diff --git a/pkg/security/podsecuritypolicy/selinux/mustrunas_test.go b/pkg/security/podsecuritypolicy/selinux/mustrunas_test.go index 09d602de420..41fbce7b329 100644 --- a/pkg/security/podsecuritypolicy/selinux/mustrunas_test.go +++ b/pkg/security/podsecuritypolicy/selinux/mustrunas_test.go @@ -18,7 +18,7 @@ package selinux import ( api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/policy" "reflect" "strings" "testing" @@ -26,7 +26,7 @@ import ( func TestMustRunAsOptions(t *testing.T) { tests := map[string]struct { - opts *extensions.SELinuxStrategyOptions + opts *policy.SELinuxStrategyOptions pass bool }{ "nil opts": { @@ -34,11 +34,11 @@ func TestMustRunAsOptions(t *testing.T) { pass: false, }, "invalid opts": { - opts: &extensions.SELinuxStrategyOptions{}, + opts: &policy.SELinuxStrategyOptions{}, pass: false, }, "valid opts": { - opts: &extensions.SELinuxStrategyOptions{SELinuxOptions: &api.SELinuxOptions{}}, + opts: &policy.SELinuxStrategyOptions{SELinuxOptions: &api.SELinuxOptions{}}, pass: true, }, } @@ -54,7 +54,7 @@ func TestMustRunAsOptions(t *testing.T) { } func TestMustRunAsGenerate(t *testing.T) { - opts := &extensions.SELinuxStrategyOptions{ + opts := &policy.SELinuxStrategyOptions{ SELinuxOptions: &api.SELinuxOptions{ User: "user", Role: "role", @@ -145,7 +145,7 @@ func TestMustRunAsValidate(t *testing.T) { } for name, tc := range tests { - opts := &extensions.SELinuxStrategyOptions{ + opts := &policy.SELinuxStrategyOptions{ SELinuxOptions: tc.pspSeLinux, } mustRunAs, err := NewMustRunAs(opts) diff --git a/pkg/security/podsecuritypolicy/selinux/runasany.go b/pkg/security/podsecuritypolicy/selinux/runasany.go index 008ad0a41d5..63e590c7c97 100644 --- a/pkg/security/podsecuritypolicy/selinux/runasany.go +++ b/pkg/security/podsecuritypolicy/selinux/runasany.go @@ -19,7 +19,7 @@ package selinux import ( "k8s.io/apimachinery/pkg/util/validation/field" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/policy" ) // runAsAny implements the SELinuxStrategy interface. @@ -28,7 +28,7 @@ type runAsAny struct{} var _ SELinuxStrategy = &runAsAny{} // NewRunAsAny provides a strategy that will return the configured se linux context or nil. -func NewRunAsAny(options *extensions.SELinuxStrategyOptions) (SELinuxStrategy, error) { +func NewRunAsAny(options *policy.SELinuxStrategyOptions) (SELinuxStrategy, error) { return &runAsAny{}, nil } diff --git a/pkg/security/podsecuritypolicy/selinux/runasany_test.go b/pkg/security/podsecuritypolicy/selinux/runasany_test.go index 8e1a7f1b07d..71ff385055c 100644 --- a/pkg/security/podsecuritypolicy/selinux/runasany_test.go +++ b/pkg/security/podsecuritypolicy/selinux/runasany_test.go @@ -18,7 +18,7 @@ package selinux import ( api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/policy" "testing" ) @@ -27,14 +27,14 @@ func TestRunAsAnyOptions(t *testing.T) { if err != nil { t.Fatalf("unexpected error initializing NewRunAsAny %v", err) } - _, err = NewRunAsAny(&extensions.SELinuxStrategyOptions{}) + _, err = NewRunAsAny(&policy.SELinuxStrategyOptions{}) if err != nil { t.Errorf("unexpected error initializing NewRunAsAny %v", err) } } func TestRunAsAnyGenerate(t *testing.T) { - s, err := NewRunAsAny(&extensions.SELinuxStrategyOptions{}) + s, err := NewRunAsAny(&policy.SELinuxStrategyOptions{}) if err != nil { t.Fatalf("unexpected error initializing NewRunAsAny %v", err) } @@ -48,7 +48,7 @@ func TestRunAsAnyGenerate(t *testing.T) { } func TestRunAsAnyValidate(t *testing.T) { - s, err := NewRunAsAny(&extensions.SELinuxStrategyOptions{ + s, err := NewRunAsAny(&policy.SELinuxStrategyOptions{ SELinuxOptions: &api.SELinuxOptions{ Level: "foo", }, @@ -61,7 +61,7 @@ func TestRunAsAnyValidate(t *testing.T) { if len(errs) != 0 { t.Errorf("unexpected errors validating with ") } - s, err = NewRunAsAny(&extensions.SELinuxStrategyOptions{}) + s, err = NewRunAsAny(&policy.SELinuxStrategyOptions{}) if err != nil { t.Fatalf("unexpected error initializing NewRunAsAny %v", err) } diff --git a/pkg/security/podsecuritypolicy/types.go b/pkg/security/podsecuritypolicy/types.go index c839c680e3b..ee7fdae1e9c 100644 --- a/pkg/security/podsecuritypolicy/types.go +++ b/pkg/security/podsecuritypolicy/types.go @@ -19,7 +19,7 @@ package podsecuritypolicy import ( "k8s.io/apimachinery/pkg/util/validation/field" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/policy" "k8s.io/kubernetes/pkg/security/podsecuritypolicy/apparmor" "k8s.io/kubernetes/pkg/security/podsecuritypolicy/capabilities" "k8s.io/kubernetes/pkg/security/podsecuritypolicy/group" @@ -54,7 +54,7 @@ type Provider interface { type StrategyFactory interface { // CreateStrategies creates the strategies that a provider will use. The namespace argument // should be the namespace of the object being checked (the pod's namespace). - CreateStrategies(psp *extensions.PodSecurityPolicy, namespace string) (*ProviderStrategies, error) + CreateStrategies(psp *policy.PodSecurityPolicy, namespace string) (*ProviderStrategies, error) } // ProviderStrategies is a holder for all strategies that the provider requires to be populated. diff --git a/pkg/security/podsecuritypolicy/user/mustrunas.go b/pkg/security/podsecuritypolicy/user/mustrunas.go index 7082dd69097..fdcf519ed4e 100644 --- a/pkg/security/podsecuritypolicy/user/mustrunas.go +++ b/pkg/security/podsecuritypolicy/user/mustrunas.go @@ -21,17 +21,17 @@ import ( "k8s.io/apimachinery/pkg/util/validation/field" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/policy" psputil "k8s.io/kubernetes/pkg/security/podsecuritypolicy/util" ) // mustRunAs implements the RunAsUserStrategy interface type mustRunAs struct { - opts *extensions.RunAsUserStrategyOptions + opts *policy.RunAsUserStrategyOptions } // NewMustRunAs provides a strategy that requires the container to run as a specific UID in a range. -func NewMustRunAs(options *extensions.RunAsUserStrategyOptions) (RunAsUserStrategy, error) { +func NewMustRunAs(options *policy.RunAsUserStrategyOptions) (RunAsUserStrategy, error) { if options == nil { return nil, fmt.Errorf("MustRunAs requires run as user options") } diff --git a/pkg/security/podsecuritypolicy/user/mustrunas_test.go b/pkg/security/podsecuritypolicy/user/mustrunas_test.go index 5a0a7703700..3caf48b1317 100644 --- a/pkg/security/podsecuritypolicy/user/mustrunas_test.go +++ b/pkg/security/podsecuritypolicy/user/mustrunas_test.go @@ -18,14 +18,14 @@ package user import ( api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/policy" "strings" "testing" ) func TestNewMustRunAs(t *testing.T) { tests := map[string]struct { - opts *extensions.RunAsUserStrategyOptions + opts *policy.RunAsUserStrategyOptions pass bool }{ "nil opts": { @@ -33,12 +33,12 @@ func TestNewMustRunAs(t *testing.T) { pass: false, }, "invalid opts": { - opts: &extensions.RunAsUserStrategyOptions{}, + opts: &policy.RunAsUserStrategyOptions{}, pass: false, }, "valid opts": { - opts: &extensions.RunAsUserStrategyOptions{ - Ranges: []extensions.UserIDRange{ + opts: &policy.RunAsUserStrategyOptions{ + Ranges: []policy.UserIDRange{ {Min: 1, Max: 1}, }, }, @@ -57,8 +57,8 @@ func TestNewMustRunAs(t *testing.T) { } func TestGenerate(t *testing.T) { - opts := &extensions.RunAsUserStrategyOptions{ - Ranges: []extensions.UserIDRange{ + opts := &policy.RunAsUserStrategyOptions{ + Ranges: []policy.UserIDRange{ {Min: 1, Max: 1}, }, } @@ -76,8 +76,8 @@ func TestGenerate(t *testing.T) { } func TestValidate(t *testing.T) { - opts := &extensions.RunAsUserStrategyOptions{ - Ranges: []extensions.UserIDRange{ + opts := &policy.RunAsUserStrategyOptions{ + Ranges: []policy.UserIDRange{ {Min: 1, Max: 1}, {Min: 10, Max: 20}, }, diff --git a/pkg/security/podsecuritypolicy/user/nonroot.go b/pkg/security/podsecuritypolicy/user/nonroot.go index 68e644a7e32..64c32caa03e 100644 --- a/pkg/security/podsecuritypolicy/user/nonroot.go +++ b/pkg/security/podsecuritypolicy/user/nonroot.go @@ -19,14 +19,14 @@ package user import ( "k8s.io/apimachinery/pkg/util/validation/field" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/policy" ) type nonRoot struct{} var _ RunAsUserStrategy = &nonRoot{} -func NewRunAsNonRoot(options *extensions.RunAsUserStrategyOptions) (RunAsUserStrategy, error) { +func NewRunAsNonRoot(options *policy.RunAsUserStrategyOptions) (RunAsUserStrategy, error) { return &nonRoot{}, nil } diff --git a/pkg/security/podsecuritypolicy/user/nonroot_test.go b/pkg/security/podsecuritypolicy/user/nonroot_test.go index 1597af00832..4a02f3f4176 100644 --- a/pkg/security/podsecuritypolicy/user/nonroot_test.go +++ b/pkg/security/podsecuritypolicy/user/nonroot_test.go @@ -18,7 +18,7 @@ package user import ( api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/policy" "testing" ) @@ -27,14 +27,14 @@ func TestNonRootOptions(t *testing.T) { if err != nil { t.Fatalf("unexpected error initializing NewRunAsNonRoot %v", err) } - _, err = NewRunAsNonRoot(&extensions.RunAsUserStrategyOptions{}) + _, err = NewRunAsNonRoot(&policy.RunAsUserStrategyOptions{}) if err != nil { t.Errorf("unexpected error initializing NewRunAsNonRoot %v", err) } } func TestNonRootGenerate(t *testing.T) { - s, err := NewRunAsNonRoot(&extensions.RunAsUserStrategyOptions{}) + s, err := NewRunAsNonRoot(&policy.RunAsUserStrategyOptions{}) if err != nil { t.Fatalf("unexpected error initializing NewRunAsNonRoot %v", err) } @@ -52,7 +52,7 @@ func TestNonRootValidate(t *testing.T) { badUID := int64(0) untrue := false unfalse := true - s, err := NewRunAsNonRoot(&extensions.RunAsUserStrategyOptions{}) + s, err := NewRunAsNonRoot(&policy.RunAsUserStrategyOptions{}) if err != nil { t.Fatalf("unexpected error initializing NewMustRunAs %v", err) } diff --git a/pkg/security/podsecuritypolicy/user/runasany.go b/pkg/security/podsecuritypolicy/user/runasany.go index e1384f2da71..935338978f2 100644 --- a/pkg/security/podsecuritypolicy/user/runasany.go +++ b/pkg/security/podsecuritypolicy/user/runasany.go @@ -19,7 +19,7 @@ package user import ( "k8s.io/apimachinery/pkg/util/validation/field" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/policy" ) // runAsAny implements the interface RunAsUserStrategy. @@ -28,7 +28,7 @@ type runAsAny struct{} var _ RunAsUserStrategy = &runAsAny{} // NewRunAsAny provides a strategy that will return nil. -func NewRunAsAny(options *extensions.RunAsUserStrategyOptions) (RunAsUserStrategy, error) { +func NewRunAsAny(options *policy.RunAsUserStrategyOptions) (RunAsUserStrategy, error) { return &runAsAny{}, nil } diff --git a/pkg/security/podsecuritypolicy/user/runasany_test.go b/pkg/security/podsecuritypolicy/user/runasany_test.go index 9a3181b4865..43b02b69820 100644 --- a/pkg/security/podsecuritypolicy/user/runasany_test.go +++ b/pkg/security/podsecuritypolicy/user/runasany_test.go @@ -19,7 +19,7 @@ package user import ( "testing" - "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/policy" ) func TestRunAsAnyOptions(t *testing.T) { @@ -27,14 +27,14 @@ func TestRunAsAnyOptions(t *testing.T) { if err != nil { t.Fatalf("unexpected error initializing NewRunAsAny %v", err) } - _, err = NewRunAsAny(&extensions.RunAsUserStrategyOptions{}) + _, err = NewRunAsAny(&policy.RunAsUserStrategyOptions{}) if err != nil { t.Errorf("unexpected error initializing NewRunAsAny %v", err) } } func TestRunAsAnyGenerate(t *testing.T) { - s, err := NewRunAsAny(&extensions.RunAsUserStrategyOptions{}) + s, err := NewRunAsAny(&policy.RunAsUserStrategyOptions{}) if err != nil { t.Fatalf("unexpected error initializing NewRunAsAny %v", err) } @@ -48,7 +48,7 @@ func TestRunAsAnyGenerate(t *testing.T) { } func TestRunAsAnyValidate(t *testing.T) { - s, err := NewRunAsAny(&extensions.RunAsUserStrategyOptions{}) + s, err := NewRunAsAny(&policy.RunAsUserStrategyOptions{}) if err != nil { t.Fatalf("unexpected error initializing NewRunAsAny %v", err) } diff --git a/pkg/security/podsecuritypolicy/util/util.go b/pkg/security/podsecuritypolicy/util/util.go index d581f5012a0..ff9092b686d 100644 --- a/pkg/security/podsecuritypolicy/util/util.go +++ b/pkg/security/podsecuritypolicy/util/util.go @@ -22,7 +22,7 @@ import ( "k8s.io/apimachinery/pkg/util/sets" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/policy" ) const ( @@ -40,102 +40,102 @@ func GetAllFSTypesExcept(exceptions ...string) sets.String { func GetAllFSTypesAsSet() sets.String { fstypes := sets.NewString() fstypes.Insert( - string(extensions.HostPath), - string(extensions.AzureFile), - string(extensions.Flocker), - string(extensions.FlexVolume), - string(extensions.EmptyDir), - string(extensions.GCEPersistentDisk), - string(extensions.AWSElasticBlockStore), - string(extensions.GitRepo), - string(extensions.Secret), - string(extensions.NFS), - string(extensions.ISCSI), - string(extensions.Glusterfs), - string(extensions.PersistentVolumeClaim), - string(extensions.RBD), - string(extensions.Cinder), - string(extensions.CephFS), - string(extensions.DownwardAPI), - string(extensions.FC), - string(extensions.ConfigMap), - string(extensions.VsphereVolume), - string(extensions.Quobyte), - string(extensions.AzureDisk), - string(extensions.PhotonPersistentDisk), - string(extensions.StorageOS), - string(extensions.Projected), - string(extensions.PortworxVolume), - string(extensions.ScaleIO), - string(extensions.CSI), + string(policy.HostPath), + string(policy.AzureFile), + string(policy.Flocker), + string(policy.FlexVolume), + string(policy.EmptyDir), + string(policy.GCEPersistentDisk), + string(policy.AWSElasticBlockStore), + string(policy.GitRepo), + string(policy.Secret), + string(policy.NFS), + string(policy.ISCSI), + string(policy.Glusterfs), + string(policy.PersistentVolumeClaim), + string(policy.RBD), + string(policy.Cinder), + string(policy.CephFS), + string(policy.DownwardAPI), + string(policy.FC), + string(policy.ConfigMap), + string(policy.VsphereVolume), + string(policy.Quobyte), + string(policy.AzureDisk), + string(policy.PhotonPersistentDisk), + string(policy.StorageOS), + string(policy.Projected), + string(policy.PortworxVolume), + string(policy.ScaleIO), + string(policy.CSI), ) return fstypes } // getVolumeFSType gets the FSType for a volume. -func GetVolumeFSType(v api.Volume) (extensions.FSType, error) { +func GetVolumeFSType(v api.Volume) (policy.FSType, error) { switch { case v.HostPath != nil: - return extensions.HostPath, nil + return policy.HostPath, nil case v.EmptyDir != nil: - return extensions.EmptyDir, nil + return policy.EmptyDir, nil case v.GCEPersistentDisk != nil: - return extensions.GCEPersistentDisk, nil + return policy.GCEPersistentDisk, nil case v.AWSElasticBlockStore != nil: - return extensions.AWSElasticBlockStore, nil + return policy.AWSElasticBlockStore, nil case v.GitRepo != nil: - return extensions.GitRepo, nil + return policy.GitRepo, nil case v.Secret != nil: - return extensions.Secret, nil + return policy.Secret, nil case v.NFS != nil: - return extensions.NFS, nil + return policy.NFS, nil case v.ISCSI != nil: - return extensions.ISCSI, nil + return policy.ISCSI, nil case v.Glusterfs != nil: - return extensions.Glusterfs, nil + return policy.Glusterfs, nil case v.PersistentVolumeClaim != nil: - return extensions.PersistentVolumeClaim, nil + return policy.PersistentVolumeClaim, nil case v.RBD != nil: - return extensions.RBD, nil + return policy.RBD, nil case v.FlexVolume != nil: - return extensions.FlexVolume, nil + return policy.FlexVolume, nil case v.Cinder != nil: - return extensions.Cinder, nil + return policy.Cinder, nil case v.CephFS != nil: - return extensions.CephFS, nil + return policy.CephFS, nil case v.Flocker != nil: - return extensions.Flocker, nil + return policy.Flocker, nil case v.DownwardAPI != nil: - return extensions.DownwardAPI, nil + return policy.DownwardAPI, nil case v.FC != nil: - return extensions.FC, nil + return policy.FC, nil case v.AzureFile != nil: - return extensions.AzureFile, nil + return policy.AzureFile, nil case v.ConfigMap != nil: - return extensions.ConfigMap, nil + return policy.ConfigMap, nil case v.VsphereVolume != nil: - return extensions.VsphereVolume, nil + return policy.VsphereVolume, nil case v.Quobyte != nil: - return extensions.Quobyte, nil + return policy.Quobyte, nil case v.AzureDisk != nil: - return extensions.AzureDisk, nil + return policy.AzureDisk, nil case v.PhotonPersistentDisk != nil: - return extensions.PhotonPersistentDisk, nil + return policy.PhotonPersistentDisk, nil case v.StorageOS != nil: - return extensions.StorageOS, nil + return policy.StorageOS, nil case v.Projected != nil: - return extensions.Projected, nil + return policy.Projected, nil case v.PortworxVolume != nil: - return extensions.PortworxVolume, nil + return policy.PortworxVolume, nil case v.ScaleIO != nil: - return extensions.ScaleIO, nil + return policy.ScaleIO, nil } return "", fmt.Errorf("unknown volume type for volume: %#v", v) } // FSTypeToStringSet converts an FSType slice to a string set. -func FSTypeToStringSet(fsTypes []extensions.FSType) sets.String { +func FSTypeToStringSet(fsTypes []policy.FSType) sets.String { set := sets.NewString() for _, v := range fsTypes { set.Insert(string(v)) @@ -144,19 +144,19 @@ func FSTypeToStringSet(fsTypes []extensions.FSType) sets.String { } // PSPAllowsAllVolumes checks for FSTypeAll in the psp's allowed volumes. -func PSPAllowsAllVolumes(psp *extensions.PodSecurityPolicy) bool { - return PSPAllowsFSType(psp, extensions.All) +func PSPAllowsAllVolumes(psp *policy.PodSecurityPolicy) bool { + return PSPAllowsFSType(psp, policy.All) } // PSPAllowsFSType is a utility for checking if a PSP allows a particular FSType. // If all volumes are allowed then this will return true for any FSType passed. -func PSPAllowsFSType(psp *extensions.PodSecurityPolicy, fsType extensions.FSType) bool { +func PSPAllowsFSType(psp *policy.PodSecurityPolicy, fsType policy.FSType) bool { if psp == nil { return false } for _, v := range psp.Spec.Volumes { - if v == fsType || v == extensions.All { + if v == fsType || v == policy.All { return true } } @@ -164,18 +164,18 @@ func PSPAllowsFSType(psp *extensions.PodSecurityPolicy, fsType extensions.FSType } // UserFallsInRange is a utility to determine it the id falls in the valid range. -func UserFallsInRange(id int64, rng extensions.UserIDRange) bool { +func UserFallsInRange(id int64, rng policy.UserIDRange) bool { return id >= rng.Min && id <= rng.Max } // GroupFallsInRange is a utility to determine it the id falls in the valid range. -func GroupFallsInRange(id int64, rng extensions.GroupIDRange) bool { +func GroupFallsInRange(id int64, rng policy.GroupIDRange) bool { return id >= rng.Min && id <= rng.Max } // AllowsHostVolumePath is a utility for checking if a PSP allows the host volume path. // This only checks the path. You should still check to make sure the host volume fs type is allowed. -func AllowsHostVolumePath(psp *extensions.PodSecurityPolicy, hostPath string) bool { +func AllowsHostVolumePath(psp *policy.PodSecurityPolicy, hostPath string) bool { if psp == nil { return false } diff --git a/pkg/security/podsecuritypolicy/util/util_test.go b/pkg/security/podsecuritypolicy/util/util_test.go index 12e0970d751..3f48db6f21b 100644 --- a/pkg/security/podsecuritypolicy/util/util_test.go +++ b/pkg/security/podsecuritypolicy/util/util_test.go @@ -18,7 +18,7 @@ package util import ( api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/policy" "reflect" "testing" ) @@ -52,45 +52,45 @@ func TestVolumeSourceFSTypeDrift(t *testing.T) { func TestPSPAllowsFSType(t *testing.T) { tests := map[string]struct { - psp *extensions.PodSecurityPolicy - fsType extensions.FSType + psp *policy.PodSecurityPolicy + fsType policy.FSType allows bool }{ "nil psp": { psp: nil, - fsType: extensions.HostPath, + fsType: policy.HostPath, allows: false, }, "empty volumes": { - psp: &extensions.PodSecurityPolicy{}, - fsType: extensions.HostPath, + psp: &policy.PodSecurityPolicy{}, + fsType: policy.HostPath, allows: false, }, "non-matching": { - psp: &extensions.PodSecurityPolicy{ - Spec: extensions.PodSecurityPolicySpec{ - Volumes: []extensions.FSType{extensions.AWSElasticBlockStore}, + psp: &policy.PodSecurityPolicy{ + Spec: policy.PodSecurityPolicySpec{ + Volumes: []policy.FSType{policy.AWSElasticBlockStore}, }, }, - fsType: extensions.HostPath, + fsType: policy.HostPath, allows: false, }, "match on FSTypeAll": { - psp: &extensions.PodSecurityPolicy{ - Spec: extensions.PodSecurityPolicySpec{ - Volumes: []extensions.FSType{extensions.All}, + psp: &policy.PodSecurityPolicy{ + Spec: policy.PodSecurityPolicySpec{ + Volumes: []policy.FSType{policy.All}, }, }, - fsType: extensions.HostPath, + fsType: policy.HostPath, allows: true, }, "match on direct match": { - psp: &extensions.PodSecurityPolicy{ - Spec: extensions.PodSecurityPolicySpec{ - Volumes: []extensions.FSType{extensions.HostPath}, + psp: &policy.PodSecurityPolicy{ + Spec: policy.PodSecurityPolicySpec{ + Volumes: []policy.FSType{policy.HostPath}, }, }, - fsType: extensions.HostPath, + fsType: policy.HostPath, allows: true, }, } @@ -105,7 +105,7 @@ func TestPSPAllowsFSType(t *testing.T) { func TestAllowsHostVolumePath(t *testing.T) { tests := map[string]struct { - psp *extensions.PodSecurityPolicy + psp *policy.PodSecurityPolicy path string allows bool }{ @@ -115,14 +115,14 @@ func TestAllowsHostVolumePath(t *testing.T) { allows: false, }, "empty allowed paths": { - psp: &extensions.PodSecurityPolicy{}, + psp: &policy.PodSecurityPolicy{}, path: "/test", allows: true, }, "non-matching": { - psp: &extensions.PodSecurityPolicy{ - Spec: extensions.PodSecurityPolicySpec{ - AllowedHostPaths: []extensions.AllowedHostPath{ + psp: &policy.PodSecurityPolicy{ + Spec: policy.PodSecurityPolicySpec{ + AllowedHostPaths: []policy.AllowedHostPath{ {PathPrefix: "/foo"}, }, }, @@ -131,9 +131,9 @@ func TestAllowsHostVolumePath(t *testing.T) { allows: false, }, "match on direct match": { - psp: &extensions.PodSecurityPolicy{ - Spec: extensions.PodSecurityPolicySpec{ - AllowedHostPaths: []extensions.AllowedHostPath{ + psp: &policy.PodSecurityPolicy{ + Spec: policy.PodSecurityPolicySpec{ + AllowedHostPaths: []policy.AllowedHostPath{ {PathPrefix: "/foo"}, }, }, @@ -142,9 +142,9 @@ func TestAllowsHostVolumePath(t *testing.T) { allows: true, }, "match with trailing slash on host path": { - psp: &extensions.PodSecurityPolicy{ - Spec: extensions.PodSecurityPolicySpec{ - AllowedHostPaths: []extensions.AllowedHostPath{ + psp: &policy.PodSecurityPolicy{ + Spec: policy.PodSecurityPolicySpec{ + AllowedHostPaths: []policy.AllowedHostPath{ {PathPrefix: "/foo"}, }, }, @@ -153,9 +153,9 @@ func TestAllowsHostVolumePath(t *testing.T) { allows: true, }, "match with trailing slash on allowed path": { - psp: &extensions.PodSecurityPolicy{ - Spec: extensions.PodSecurityPolicySpec{ - AllowedHostPaths: []extensions.AllowedHostPath{ + psp: &policy.PodSecurityPolicy{ + Spec: policy.PodSecurityPolicySpec{ + AllowedHostPaths: []policy.AllowedHostPath{ {PathPrefix: "/foo/"}, }, }, @@ -164,9 +164,9 @@ func TestAllowsHostVolumePath(t *testing.T) { allows: true, }, "match child directory": { - psp: &extensions.PodSecurityPolicy{ - Spec: extensions.PodSecurityPolicySpec{ - AllowedHostPaths: []extensions.AllowedHostPath{ + psp: &policy.PodSecurityPolicy{ + Spec: policy.PodSecurityPolicySpec{ + AllowedHostPaths: []policy.AllowedHostPath{ {PathPrefix: "/foo/"}, }, }, @@ -175,9 +175,9 @@ func TestAllowsHostVolumePath(t *testing.T) { allows: true, }, "non-matching parent directory": { - psp: &extensions.PodSecurityPolicy{ - Spec: extensions.PodSecurityPolicySpec{ - AllowedHostPaths: []extensions.AllowedHostPath{ + psp: &policy.PodSecurityPolicy{ + Spec: policy.PodSecurityPolicySpec{ + AllowedHostPaths: []policy.AllowedHostPath{ {PathPrefix: "/foo/bar"}, }, }, diff --git a/plugin/pkg/admission/security/podsecuritypolicy/admission.go b/plugin/pkg/admission/security/podsecuritypolicy/admission.go index 849ab451415..3a31f33f968 100644 --- a/plugin/pkg/admission/security/podsecuritypolicy/admission.go +++ b/plugin/pkg/admission/security/podsecuritypolicy/admission.go @@ -35,7 +35,7 @@ import ( "k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/kubernetes/pkg/apis/policy" informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion" - extensionslisters "k8s.io/kubernetes/pkg/client/listers/extensions/internalversion" + policylisters "k8s.io/kubernetes/pkg/client/listers/policy/internalversion" kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission" rbacregistry "k8s.io/kubernetes/pkg/registry/rbac" psp "k8s.io/kubernetes/pkg/security/podsecuritypolicy" @@ -61,7 +61,7 @@ type PodSecurityPolicyPlugin struct { strategyFactory psp.StrategyFactory failOnNoPolicies bool authz authorizer.Authorizer - lister extensionslisters.PodSecurityPolicyLister + lister policylisters.PodSecurityPolicyLister } // SetAuthorizer sets the authorizer. @@ -95,7 +95,7 @@ func newPlugin(strategyFactory psp.StrategyFactory, failOnNoPolicies bool) *PodS } func (a *PodSecurityPolicyPlugin) SetInternalKubeInformerFactory(f informers.SharedInformerFactory) { - podSecurityPolicyInformer := f.Extensions().InternalVersion().PodSecurityPolicies() + podSecurityPolicyInformer := f.Policy().InternalVersion().PodSecurityPolicies() a.lister = podSecurityPolicyInformer.Lister() a.SetReadyFunc(podSecurityPolicyInformer.Informer().HasSynced) } @@ -329,7 +329,7 @@ func assignSecurityContext(provider psp.Provider, pod *api.Pod, fldPath *field.P } // createProvidersFromPolicies creates providers from the constraints supplied. -func (c *PodSecurityPolicyPlugin) createProvidersFromPolicies(psps []*extensions.PodSecurityPolicy, namespace string) ([]psp.Provider, []error) { +func (c *PodSecurityPolicyPlugin) createProvidersFromPolicies(psps []*policy.PodSecurityPolicy, namespace string) ([]psp.Provider, []error) { var ( // collected providers providers []psp.Provider diff --git a/plugin/pkg/admission/security/podsecuritypolicy/admission_test.go b/plugin/pkg/admission/security/podsecuritypolicy/admission_test.go index 329e9033050..8bb596dc122 100644 --- a/plugin/pkg/admission/security/podsecuritypolicy/admission_test.go +++ b/plugin/pkg/admission/security/podsecuritypolicy/admission_test.go @@ -36,7 +36,6 @@ import ( "k8s.io/kubernetes/pkg/api/legacyscheme" kapi "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/apis/core/helper" - "k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/kubernetes/pkg/apis/policy" informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion" "k8s.io/kubernetes/pkg/controller" @@ -50,13 +49,13 @@ import ( const defaultContainerName = "test-c" // NewTestAdmission provides an admission plugin with test implementations of internal structs. -func NewTestAdmission(psps []*extensions.PodSecurityPolicy, authz authorizer.Authorizer) *PodSecurityPolicyPlugin { +func NewTestAdmission(psps []*policy.PodSecurityPolicy, authz authorizer.Authorizer) *PodSecurityPolicyPlugin { informerFactory := informers.NewSharedInformerFactory(nil, controller.NoResyncPeriodFunc()) - store := informerFactory.Extensions().InternalVersion().PodSecurityPolicies().Informer().GetStore() + store := informerFactory.Policy().InternalVersion().PodSecurityPolicies().Informer().GetStore() for _, psp := range psps { store.Add(psp) } - lister := informerFactory.Extensions().InternalVersion().PodSecurityPolicies().Lister() + lister := informerFactory.Policy().InternalVersion().PodSecurityPolicies().Lister() if authz == nil { authz = &TestAuthorizer{} } @@ -217,7 +216,7 @@ func TestAdmitSeccomp(t *testing.T) { }, }, } - testPSPAdmit(k, []*extensions.PodSecurityPolicy{psp}, pod, v.shouldPassAdmit, v.shouldPassValidate, psp.Name, t) + testPSPAdmit(k, []*policy.PodSecurityPolicy{psp}, pod, v.shouldPassAdmit, v.shouldPassValidate, psp.Name, t) } } @@ -241,7 +240,7 @@ func TestAdmitPrivileged(t *testing.T) { tests := map[string]struct { pod *kapi.Pod - psps []*extensions.PodSecurityPolicy + psps []*policy.PodSecurityPolicy shouldPassAdmit bool shouldPassValidate bool expectedPriv *bool @@ -249,7 +248,7 @@ func TestAdmitPrivileged(t *testing.T) { }{ "pod with priv=nil allowed under non priv PSP": { pod: goodPod(), - psps: []*extensions.PodSecurityPolicy{nonPrivilegedPSP}, + psps: []*policy.PodSecurityPolicy{nonPrivilegedPSP}, shouldPassAdmit: true, shouldPassValidate: true, expectedPriv: nil, @@ -257,7 +256,7 @@ func TestAdmitPrivileged(t *testing.T) { }, "pod with priv=nil allowed under priv PSP": { pod: goodPod(), - psps: []*extensions.PodSecurityPolicy{privilegedPSP}, + psps: []*policy.PodSecurityPolicy{privilegedPSP}, shouldPassAdmit: true, shouldPassValidate: true, expectedPriv: nil, @@ -265,7 +264,7 @@ func TestAdmitPrivileged(t *testing.T) { }, "pod with priv=false allowed under non priv PSP": { pod: createPodWithPriv(false), - psps: []*extensions.PodSecurityPolicy{nonPrivilegedPSP}, + psps: []*policy.PodSecurityPolicy{nonPrivilegedPSP}, shouldPassAdmit: true, shouldPassValidate: true, expectedPriv: &falseValue, @@ -273,7 +272,7 @@ func TestAdmitPrivileged(t *testing.T) { }, "pod with priv=false allowed under priv PSP": { pod: createPodWithPriv(false), - psps: []*extensions.PodSecurityPolicy{privilegedPSP}, + psps: []*policy.PodSecurityPolicy{privilegedPSP}, shouldPassAdmit: true, shouldPassValidate: true, expectedPriv: &falseValue, @@ -281,13 +280,13 @@ func TestAdmitPrivileged(t *testing.T) { }, "pod with priv=true denied by non priv PSP": { pod: createPodWithPriv(true), - psps: []*extensions.PodSecurityPolicy{nonPrivilegedPSP}, + psps: []*policy.PodSecurityPolicy{nonPrivilegedPSP}, shouldPassAdmit: false, shouldPassValidate: false, }, "pod with priv=true allowed by priv PSP": { pod: createPodWithPriv(true), - psps: []*extensions.PodSecurityPolicy{nonPrivilegedPSP, privilegedPSP}, + psps: []*policy.PodSecurityPolicy{nonPrivilegedPSP, privilegedPSP}, shouldPassAdmit: true, shouldPassValidate: true, expectedPriv: &trueValue, @@ -325,11 +324,11 @@ func defaultPod(t *testing.T, pod *kapi.Pod) *kapi.Pod { func TestAdmitPreferNonmutating(t *testing.T) { mutating1 := restrictivePSP() mutating1.Name = "mutating1" - mutating1.Spec.RunAsUser.Ranges = []extensions.UserIDRange{{Min: int64(1), Max: int64(1)}} + mutating1.Spec.RunAsUser.Ranges = []policy.UserIDRange{{Min: int64(1), Max: int64(1)}} mutating2 := restrictivePSP() mutating2.Name = "mutating2" - mutating2.Spec.RunAsUser.Ranges = []extensions.UserIDRange{{Min: int64(2), Max: int64(2)}} + mutating2.Spec.RunAsUser.Ranges = []policy.UserIDRange{{Min: int64(2), Max: int64(2)}} privilegedPSP := permissivePSP() privilegedPSP.Name = "privileged" @@ -364,7 +363,7 @@ func TestAdmitPreferNonmutating(t *testing.T) { operation kadmission.Operation pod *kapi.Pod podBeforeUpdate *kapi.Pod - psps []*extensions.PodSecurityPolicy + psps []*policy.PodSecurityPolicy shouldPassValidate bool expectMutation bool expectedContainerUser *int64 @@ -373,7 +372,7 @@ func TestAdmitPreferNonmutating(t *testing.T) { "pod should not be mutated by allow-all strategies": { operation: kadmission.Create, pod: unprivilegedRunAsAnyPod.DeepCopy(), - psps: []*extensions.PodSecurityPolicy{privilegedPSP}, + psps: []*policy.PodSecurityPolicy{privilegedPSP}, shouldPassValidate: true, expectMutation: false, expectedContainerUser: nil, @@ -382,7 +381,7 @@ func TestAdmitPreferNonmutating(t *testing.T) { "pod should prefer non-mutating PSP on create": { operation: kadmission.Create, pod: unprivilegedRunAsAnyPod.DeepCopy(), - psps: []*extensions.PodSecurityPolicy{mutating2, mutating1, privilegedPSP}, + psps: []*policy.PodSecurityPolicy{mutating2, mutating1, privilegedPSP}, shouldPassValidate: true, expectMutation: false, expectedContainerUser: nil, @@ -391,7 +390,7 @@ func TestAdmitPreferNonmutating(t *testing.T) { "pod should use deterministic mutating PSP on create": { operation: kadmission.Create, pod: unprivilegedRunAsAnyPod.DeepCopy(), - psps: []*extensions.PodSecurityPolicy{mutating2, mutating1}, + psps: []*policy.PodSecurityPolicy{mutating2, mutating1}, shouldPassValidate: true, expectMutation: true, expectedContainerUser: &mutating1.Spec.RunAsUser.Ranges[0].Min, @@ -400,7 +399,7 @@ func TestAdmitPreferNonmutating(t *testing.T) { "pod should use deterministic mutating PSP on create even if ValidatedPSPAnnotation is set": { operation: kadmission.Create, pod: podWithAnnotation, - psps: []*extensions.PodSecurityPolicy{mutating2, mutating1}, + psps: []*policy.PodSecurityPolicy{mutating2, mutating1}, shouldPassValidate: true, expectMutation: true, expectedContainerUser: &mutating1.Spec.RunAsUser.Ranges[0].Min, @@ -410,7 +409,7 @@ func TestAdmitPreferNonmutating(t *testing.T) { operation: kadmission.Update, pod: changedPodWithSC.DeepCopy(), podBeforeUpdate: podWithSC.DeepCopy(), - psps: []*extensions.PodSecurityPolicy{mutating2, mutating1, privilegedPSP}, + psps: []*policy.PodSecurityPolicy{mutating2, mutating1, privilegedPSP}, shouldPassValidate: true, expectMutation: false, expectedContainerUser: nil, @@ -420,7 +419,7 @@ func TestAdmitPreferNonmutating(t *testing.T) { operation: kadmission.Update, pod: changedPod.DeepCopy(), podBeforeUpdate: unprivilegedRunAsAnyPod.DeepCopy(), - psps: []*extensions.PodSecurityPolicy{mutating2, mutating1}, + psps: []*policy.PodSecurityPolicy{mutating2, mutating1}, shouldPassValidate: false, expectMutation: false, expectedContainerUser: nil, @@ -430,7 +429,7 @@ func TestAdmitPreferNonmutating(t *testing.T) { operation: kadmission.Update, pod: unprivilegedRunAsAnyPod.DeepCopy(), podBeforeUpdate: unprivilegedRunAsAnyPod.DeepCopy(), - psps: []*extensions.PodSecurityPolicy{mutating2, mutating1}, + psps: []*policy.PodSecurityPolicy{mutating2, mutating1}, shouldPassValidate: true, expectMutation: false, expectedContainerUser: nil, @@ -440,7 +439,7 @@ func TestAdmitPreferNonmutating(t *testing.T) { operation: kadmission.Update, pod: gcChangedPod.DeepCopy(), podBeforeUpdate: unprivilegedRunAsAnyPod.DeepCopy(), - psps: []*extensions.PodSecurityPolicy{mutating2, mutating1}, + psps: []*policy.PodSecurityPolicy{mutating2, mutating1}, shouldPassValidate: true, expectMutation: false, expectedContainerUser: nil, @@ -516,11 +515,11 @@ func TestAdmitCaps(t *testing.T) { allowAllInAllowed := restrictivePSP() allowAllInAllowed.Name = "allowAllCapsInAllowed" - allowAllInAllowed.Spec.AllowedCapabilities = []kapi.Capability{extensions.AllowAllCapabilities} + allowAllInAllowed.Spec.AllowedCapabilities = []kapi.Capability{policy.AllowAllCapabilities} tc := map[string]struct { pod *kapi.Pod - psps []*extensions.PodSecurityPolicy + psps []*policy.PodSecurityPolicy shouldPassAdmit bool shouldPassValidate bool expectedCapabilities *kapi.Capabilities @@ -530,7 +529,7 @@ func TestAdmitCaps(t *testing.T) { // should be rejected. "should reject cap add when not allowed or required": { pod: createPodWithCaps(&kapi.Capabilities{Add: []kapi.Capability{"foo"}}), - psps: []*extensions.PodSecurityPolicy{restricted}, + psps: []*policy.PodSecurityPolicy{restricted}, shouldPassAdmit: false, shouldPassValidate: false, }, @@ -538,7 +537,7 @@ func TestAdmitCaps(t *testing.T) { // to add the cap. "should accept cap add when in allowed": { pod: createPodWithCaps(&kapi.Capabilities{Add: []kapi.Capability{"foo"}}), - psps: []*extensions.PodSecurityPolicy{restricted, allowsFooInAllowed}, + psps: []*policy.PodSecurityPolicy{restricted, allowsFooInAllowed}, shouldPassAdmit: true, shouldPassValidate: true, expectedPSP: allowsFooInAllowed.Name, @@ -547,7 +546,7 @@ func TestAdmitCaps(t *testing.T) { // to add the cap. "should accept cap add when in required": { pod: createPodWithCaps(&kapi.Capabilities{Add: []kapi.Capability{"foo"}}), - psps: []*extensions.PodSecurityPolicy{restricted, allowsFooInRequired}, + psps: []*policy.PodSecurityPolicy{restricted, allowsFooInRequired}, shouldPassAdmit: true, shouldPassValidate: true, expectedPSP: allowsFooInRequired.Name, @@ -556,7 +555,7 @@ func TestAdmitCaps(t *testing.T) { // in the verification of adds and verification of drops "should reject cap add when requested cap is required to be dropped": { pod: createPodWithCaps(&kapi.Capabilities{Add: []kapi.Capability{"foo"}}), - psps: []*extensions.PodSecurityPolicy{restricted, requiresFooToBeDropped}, + psps: []*policy.PodSecurityPolicy{restricted, requiresFooToBeDropped}, shouldPassAdmit: false, shouldPassValidate: false, }, @@ -564,7 +563,7 @@ func TestAdmitCaps(t *testing.T) { // a manual request to drop the cap. "should accept cap drop when cap is required to be dropped": { pod: createPodWithCaps(&kapi.Capabilities{Drop: []kapi.Capability{"foo"}}), - psps: []*extensions.PodSecurityPolicy{requiresFooToBeDropped}, + psps: []*policy.PodSecurityPolicy{requiresFooToBeDropped}, shouldPassAdmit: true, shouldPassValidate: true, expectedPSP: requiresFooToBeDropped.Name, @@ -572,7 +571,7 @@ func TestAdmitCaps(t *testing.T) { // UC 6: required add is defaulted "required add is defaulted": { pod: goodPod(), - psps: []*extensions.PodSecurityPolicy{allowsFooInRequired}, + psps: []*policy.PodSecurityPolicy{allowsFooInRequired}, shouldPassAdmit: true, shouldPassValidate: true, expectedCapabilities: &kapi.Capabilities{ @@ -583,7 +582,7 @@ func TestAdmitCaps(t *testing.T) { // UC 7: required drop is defaulted "required drop is defaulted": { pod: goodPod(), - psps: []*extensions.PodSecurityPolicy{requiresFooToBeDropped}, + psps: []*policy.PodSecurityPolicy{requiresFooToBeDropped}, shouldPassAdmit: true, shouldPassValidate: true, expectedCapabilities: &kapi.Capabilities{ @@ -594,7 +593,7 @@ func TestAdmitCaps(t *testing.T) { // UC 8: using '*' in allowed caps "should accept cap add when all caps are allowed": { pod: createPodWithCaps(&kapi.Capabilities{Add: []kapi.Capability{"foo"}}), - psps: []*extensions.PodSecurityPolicy{restricted, allowAllInAllowed}, + psps: []*policy.PodSecurityPolicy{restricted, allowAllInAllowed}, shouldPassAdmit: true, shouldPassValidate: true, expectedPSP: allowAllInAllowed.Name, @@ -652,19 +651,19 @@ func TestAdmitVolumes(t *testing.T) { psp := restrictivePSP() // expect a denial for this PSP - testPSPAdmit(fmt.Sprintf("%s denial", string(fsType)), []*extensions.PodSecurityPolicy{psp}, pod, false, false, "", t) + testPSPAdmit(fmt.Sprintf("%s denial", string(fsType)), []*policy.PodSecurityPolicy{psp}, pod, false, false, "", t) // also expect a denial for this PSP if it's an init container useInitContainers(pod) - testPSPAdmit(fmt.Sprintf("%s denial", string(fsType)), []*extensions.PodSecurityPolicy{psp}, pod, false, false, "", t) + testPSPAdmit(fmt.Sprintf("%s denial", string(fsType)), []*policy.PodSecurityPolicy{psp}, pod, false, false, "", t) // now add the fstype directly to the psp and it should validate - psp.Spec.Volumes = []extensions.FSType{fsType} - testPSPAdmit(fmt.Sprintf("%s direct accept", string(fsType)), []*extensions.PodSecurityPolicy{psp}, pod, true, true, psp.Name, t) + psp.Spec.Volumes = []policy.FSType{fsType} + testPSPAdmit(fmt.Sprintf("%s direct accept", string(fsType)), []*policy.PodSecurityPolicy{psp}, pod, true, true, psp.Name, t) // now change the psp to allow any volumes and the pod should still validate - psp.Spec.Volumes = []extensions.FSType{extensions.All} - testPSPAdmit(fmt.Sprintf("%s wildcard accept", string(fsType)), []*extensions.PodSecurityPolicy{psp}, pod, true, true, psp.Name, t) + psp.Spec.Volumes = []policy.FSType{policy.All} + testPSPAdmit(fmt.Sprintf("%s wildcard accept", string(fsType)), []*policy.PodSecurityPolicy{psp}, pod, true, true, psp.Name, t) } } @@ -685,7 +684,7 @@ func TestAdmitHostNetwork(t *testing.T) { tests := map[string]struct { pod *kapi.Pod - psps []*extensions.PodSecurityPolicy + psps []*policy.PodSecurityPolicy shouldPassAdmit bool shouldPassValidate bool expectedHostNetwork bool @@ -693,7 +692,7 @@ func TestAdmitHostNetwork(t *testing.T) { }{ "pod without hostnetwork request allowed under noHostNetwork PSP": { pod: goodPod(), - psps: []*extensions.PodSecurityPolicy{noHostNetwork}, + psps: []*policy.PodSecurityPolicy{noHostNetwork}, shouldPassAdmit: true, shouldPassValidate: true, expectedHostNetwork: false, @@ -701,7 +700,7 @@ func TestAdmitHostNetwork(t *testing.T) { }, "pod without hostnetwork request allowed under hostNetwork PSP": { pod: goodPod(), - psps: []*extensions.PodSecurityPolicy{hostNetwork}, + psps: []*policy.PodSecurityPolicy{hostNetwork}, shouldPassAdmit: true, shouldPassValidate: true, expectedHostNetwork: false, @@ -709,13 +708,13 @@ func TestAdmitHostNetwork(t *testing.T) { }, "pod with hostnetwork request denied by noHostNetwork PSP": { pod: createPodWithHostNetwork(true), - psps: []*extensions.PodSecurityPolicy{noHostNetwork}, + psps: []*policy.PodSecurityPolicy{noHostNetwork}, shouldPassAdmit: false, shouldPassValidate: false, }, "pod with hostnetwork request allowed by hostNetwork PSP": { pod: createPodWithHostNetwork(true), - psps: []*extensions.PodSecurityPolicy{noHostNetwork, hostNetwork}, + psps: []*policy.PodSecurityPolicy{noHostNetwork, hostNetwork}, shouldPassAdmit: true, shouldPassValidate: true, expectedHostNetwork: true, @@ -760,47 +759,47 @@ func TestAdmitHostPorts(t *testing.T) { hostPorts := restrictivePSP() hostPorts.Name = "hostPorts" - hostPorts.Spec.HostPorts = []extensions.HostPortRange{ + hostPorts.Spec.HostPorts = []policy.HostPortRange{ {Min: 1, Max: 10}, } tests := map[string]struct { pod *kapi.Pod - psps []*extensions.PodSecurityPolicy + psps []*policy.PodSecurityPolicy shouldPassAdmit bool shouldPassValidate bool expectedPSP string }{ "host port out of range": { pod: createPodWithHostPorts(11), - psps: []*extensions.PodSecurityPolicy{hostPorts}, + psps: []*policy.PodSecurityPolicy{hostPorts}, shouldPassAdmit: false, shouldPassValidate: false, }, "host port in range": { pod: createPodWithHostPorts(5), - psps: []*extensions.PodSecurityPolicy{hostPorts}, + psps: []*policy.PodSecurityPolicy{hostPorts}, shouldPassAdmit: true, shouldPassValidate: true, expectedPSP: hostPorts.Name, }, "no host ports with range": { pod: goodPod(), - psps: []*extensions.PodSecurityPolicy{hostPorts}, + psps: []*policy.PodSecurityPolicy{hostPorts}, shouldPassAdmit: true, shouldPassValidate: true, expectedPSP: hostPorts.Name, }, "no host ports without range": { pod: goodPod(), - psps: []*extensions.PodSecurityPolicy{noHostPorts}, + psps: []*policy.PodSecurityPolicy{noHostPorts}, shouldPassAdmit: true, shouldPassValidate: true, expectedPSP: noHostPorts.Name, }, "host ports without range": { pod: createPodWithHostPorts(5), - psps: []*extensions.PodSecurityPolicy{noHostPorts}, + psps: []*policy.PodSecurityPolicy{noHostPorts}, shouldPassAdmit: false, shouldPassValidate: false, }, @@ -831,7 +830,7 @@ func TestAdmitHostPID(t *testing.T) { tests := map[string]struct { pod *kapi.Pod - psps []*extensions.PodSecurityPolicy + psps []*policy.PodSecurityPolicy shouldPassAdmit bool shouldPassValidate bool expectedHostPID bool @@ -839,7 +838,7 @@ func TestAdmitHostPID(t *testing.T) { }{ "pod without hostpid request allowed under noHostPID PSP": { pod: goodPod(), - psps: []*extensions.PodSecurityPolicy{noHostPID}, + psps: []*policy.PodSecurityPolicy{noHostPID}, shouldPassAdmit: true, shouldPassValidate: true, expectedHostPID: false, @@ -847,7 +846,7 @@ func TestAdmitHostPID(t *testing.T) { }, "pod without hostpid request allowed under hostPID PSP": { pod: goodPod(), - psps: []*extensions.PodSecurityPolicy{hostPID}, + psps: []*policy.PodSecurityPolicy{hostPID}, shouldPassAdmit: true, shouldPassValidate: true, expectedHostPID: false, @@ -855,12 +854,12 @@ func TestAdmitHostPID(t *testing.T) { }, "pod with hostpid request denied by noHostPID PSP": { pod: createPodWithHostPID(true), - psps: []*extensions.PodSecurityPolicy{noHostPID}, + psps: []*policy.PodSecurityPolicy{noHostPID}, shouldPassAdmit: false, }, "pod with hostpid request allowed by hostPID PSP": { pod: createPodWithHostPID(true), - psps: []*extensions.PodSecurityPolicy{noHostPID, hostPID}, + psps: []*policy.PodSecurityPolicy{noHostPID, hostPID}, shouldPassAdmit: true, shouldPassValidate: true, expectedHostPID: true, @@ -896,7 +895,7 @@ func TestAdmitHostIPC(t *testing.T) { tests := map[string]struct { pod *kapi.Pod - psps []*extensions.PodSecurityPolicy + psps []*policy.PodSecurityPolicy shouldPassAdmit bool shouldPassValidate bool expectedHostIPC bool @@ -904,7 +903,7 @@ func TestAdmitHostIPC(t *testing.T) { }{ "pod without hostIPC request allowed under noHostIPC PSP": { pod: goodPod(), - psps: []*extensions.PodSecurityPolicy{noHostIPC}, + psps: []*policy.PodSecurityPolicy{noHostIPC}, shouldPassAdmit: true, shouldPassValidate: true, expectedHostIPC: false, @@ -912,7 +911,7 @@ func TestAdmitHostIPC(t *testing.T) { }, "pod without hostIPC request allowed under hostIPC PSP": { pod: goodPod(), - psps: []*extensions.PodSecurityPolicy{hostIPC}, + psps: []*policy.PodSecurityPolicy{hostIPC}, shouldPassAdmit: true, shouldPassValidate: true, expectedHostIPC: false, @@ -920,13 +919,13 @@ func TestAdmitHostIPC(t *testing.T) { }, "pod with hostIPC request denied by noHostIPC PSP": { pod: createPodWithHostIPC(true), - psps: []*extensions.PodSecurityPolicy{noHostIPC}, + psps: []*policy.PodSecurityPolicy{noHostIPC}, shouldPassAdmit: false, shouldPassValidate: false, }, "pod with hostIPC request allowed by hostIPC PSP": { pod: createPodWithHostIPC(true), - psps: []*extensions.PodSecurityPolicy{noHostIPC, hostIPC}, + psps: []*policy.PodSecurityPolicy{noHostIPC, hostIPC}, shouldPassAdmit: true, shouldPassValidate: true, expectedHostIPC: true, @@ -955,12 +954,12 @@ func createPodWithSecurityContexts(podSC *kapi.PodSecurityContext, containerSC * func TestAdmitSELinux(t *testing.T) { runAsAny := permissivePSP() runAsAny.Name = "runAsAny" - runAsAny.Spec.SELinux.Rule = extensions.SELinuxStrategyRunAsAny + runAsAny.Spec.SELinux.Rule = policy.SELinuxStrategyRunAsAny runAsAny.Spec.SELinux.SELinuxOptions = nil mustRunAs := permissivePSP() mustRunAs.Name = "mustRunAs" - mustRunAs.Spec.SELinux.Rule = extensions.SELinuxStrategyMustRunAs + mustRunAs.Spec.SELinux.Rule = policy.SELinuxStrategyMustRunAs mustRunAs.Spec.SELinux.SELinuxOptions = &kapi.SELinuxOptions{} mustRunAs.Spec.SELinux.SELinuxOptions.Level = "level" mustRunAs.Spec.SELinux.SELinuxOptions.Role = "role" @@ -969,7 +968,7 @@ func TestAdmitSELinux(t *testing.T) { tests := map[string]struct { pod *kapi.Pod - psps []*extensions.PodSecurityPolicy + psps []*policy.PodSecurityPolicy shouldPassAdmit bool shouldPassValidate bool expectedPodSC *kapi.PodSecurityContext @@ -978,7 +977,7 @@ func TestAdmitSELinux(t *testing.T) { }{ "runAsAny with no request": { pod: createPodWithSecurityContexts(nil, nil), - psps: []*extensions.PodSecurityPolicy{runAsAny}, + psps: []*policy.PodSecurityPolicy{runAsAny}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: nil, @@ -987,7 +986,7 @@ func TestAdmitSELinux(t *testing.T) { }, "runAsAny with empty pod request": { pod: createPodWithSecurityContexts(&kapi.PodSecurityContext{}, nil), - psps: []*extensions.PodSecurityPolicy{runAsAny}, + psps: []*policy.PodSecurityPolicy{runAsAny}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: &kapi.PodSecurityContext{}, @@ -996,7 +995,7 @@ func TestAdmitSELinux(t *testing.T) { }, "runAsAny with empty container request": { pod: createPodWithSecurityContexts(nil, &kapi.SecurityContext{}), - psps: []*extensions.PodSecurityPolicy{runAsAny}, + psps: []*policy.PodSecurityPolicy{runAsAny}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: nil, @@ -1006,7 +1005,7 @@ func TestAdmitSELinux(t *testing.T) { "runAsAny with pod request": { pod: createPodWithSecurityContexts(&kapi.PodSecurityContext{SELinuxOptions: &kapi.SELinuxOptions{User: "foo"}}, nil), - psps: []*extensions.PodSecurityPolicy{runAsAny}, + psps: []*policy.PodSecurityPolicy{runAsAny}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: &kapi.PodSecurityContext{SELinuxOptions: &kapi.SELinuxOptions{User: "foo"}}, @@ -1015,7 +1014,7 @@ func TestAdmitSELinux(t *testing.T) { }, "runAsAny with container request": { pod: createPodWithSecurityContexts(nil, &kapi.SecurityContext{SELinuxOptions: &kapi.SELinuxOptions{User: "foo"}}), - psps: []*extensions.PodSecurityPolicy{runAsAny}, + psps: []*policy.PodSecurityPolicy{runAsAny}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: nil, @@ -1024,7 +1023,7 @@ func TestAdmitSELinux(t *testing.T) { }, "runAsAny with pod and container request": { pod: createPodWithSecurityContexts(&kapi.PodSecurityContext{SELinuxOptions: &kapi.SELinuxOptions{User: "bar"}}, &kapi.SecurityContext{SELinuxOptions: &kapi.SELinuxOptions{User: "foo"}}), - psps: []*extensions.PodSecurityPolicy{runAsAny}, + psps: []*policy.PodSecurityPolicy{runAsAny}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: &kapi.PodSecurityContext{SELinuxOptions: &kapi.SELinuxOptions{User: "bar"}}, @@ -1034,19 +1033,19 @@ func TestAdmitSELinux(t *testing.T) { "mustRunAs with bad pod request": { pod: createPodWithSecurityContexts(&kapi.PodSecurityContext{SELinuxOptions: &kapi.SELinuxOptions{User: "foo"}}, nil), - psps: []*extensions.PodSecurityPolicy{mustRunAs}, + psps: []*policy.PodSecurityPolicy{mustRunAs}, shouldPassAdmit: false, shouldPassValidate: false, }, "mustRunAs with bad container request": { pod: createPodWithSecurityContexts(nil, &kapi.SecurityContext{SELinuxOptions: &kapi.SELinuxOptions{User: "foo"}}), - psps: []*extensions.PodSecurityPolicy{mustRunAs}, + psps: []*policy.PodSecurityPolicy{mustRunAs}, shouldPassAdmit: false, shouldPassValidate: false, }, "mustRunAs with no request": { pod: createPodWithSecurityContexts(nil, nil), - psps: []*extensions.PodSecurityPolicy{mustRunAs}, + psps: []*policy.PodSecurityPolicy{mustRunAs}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: &kapi.PodSecurityContext{SELinuxOptions: mustRunAs.Spec.SELinux.SELinuxOptions}, @@ -1058,7 +1057,7 @@ func TestAdmitSELinux(t *testing.T) { &kapi.PodSecurityContext{SELinuxOptions: &kapi.SELinuxOptions{Level: "level", Role: "role", Type: "type", User: "user"}}, nil, ), - psps: []*extensions.PodSecurityPolicy{mustRunAs}, + psps: []*policy.PodSecurityPolicy{mustRunAs}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: &kapi.PodSecurityContext{SELinuxOptions: mustRunAs.Spec.SELinux.SELinuxOptions}, @@ -1070,7 +1069,7 @@ func TestAdmitSELinux(t *testing.T) { &kapi.PodSecurityContext{SELinuxOptions: &kapi.SELinuxOptions{Level: "level", Role: "role", Type: "type", User: "user"}}, nil, ), - psps: []*extensions.PodSecurityPolicy{mustRunAs}, + psps: []*policy.PodSecurityPolicy{mustRunAs}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: &kapi.PodSecurityContext{SELinuxOptions: mustRunAs.Spec.SELinux.SELinuxOptions}, @@ -1117,7 +1116,7 @@ func TestAdmitAppArmor(t *testing.T) { tests := map[string]struct { pod *kapi.Pod - psp *extensions.PodSecurityPolicy + psp *policy.PodSecurityPolicy shouldPassAdmit bool shouldPassValidate bool expectedProfile string @@ -1172,7 +1171,7 @@ func TestAdmitAppArmor(t *testing.T) { } for k, v := range tests { - testPSPAdmit(k, []*extensions.PodSecurityPolicy{v.psp}, v.pod, v.shouldPassAdmit, v.shouldPassValidate, v.psp.Name, t) + testPSPAdmit(k, []*policy.PodSecurityPolicy{v.psp}, v.pod, v.shouldPassAdmit, v.shouldPassValidate, v.psp.Name, t) if v.shouldPassAdmit { assert.Equal(t, v.expectedProfile, apparmor.GetProfileNameFromPodAnnotations(v.pod.Annotations, defaultContainerName), k) @@ -1190,24 +1189,24 @@ func TestAdmitRunAsUser(t *testing.T) { runAsAny := permissivePSP() runAsAny.Name = "runAsAny" - runAsAny.Spec.RunAsUser.Rule = extensions.RunAsUserStrategyRunAsAny + runAsAny.Spec.RunAsUser.Rule = policy.RunAsUserStrategyRunAsAny mustRunAs := permissivePSP() mustRunAs.Name = "mustRunAs" - mustRunAs.Spec.RunAsUser.Rule = extensions.RunAsUserStrategyMustRunAs - mustRunAs.Spec.RunAsUser.Ranges = []extensions.UserIDRange{ + mustRunAs.Spec.RunAsUser.Rule = policy.RunAsUserStrategyMustRunAs + mustRunAs.Spec.RunAsUser.Ranges = []policy.UserIDRange{ {Min: int64(999), Max: int64(1000)}, } runAsNonRoot := permissivePSP() runAsNonRoot.Name = "runAsNonRoot" - runAsNonRoot.Spec.RunAsUser.Rule = extensions.RunAsUserStrategyMustRunAsNonRoot + runAsNonRoot.Spec.RunAsUser.Rule = policy.RunAsUserStrategyMustRunAsNonRoot trueValue := true tests := map[string]struct { pod *kapi.Pod - psps []*extensions.PodSecurityPolicy + psps []*policy.PodSecurityPolicy shouldPassAdmit bool shouldPassValidate bool expectedPodSC *kapi.PodSecurityContext @@ -1216,7 +1215,7 @@ func TestAdmitRunAsUser(t *testing.T) { }{ "runAsAny no pod request": { pod: createPodWithSecurityContexts(nil, nil), - psps: []*extensions.PodSecurityPolicy{runAsAny}, + psps: []*policy.PodSecurityPolicy{runAsAny}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: nil, @@ -1225,7 +1224,7 @@ func TestAdmitRunAsUser(t *testing.T) { }, "runAsAny pod request": { pod: createPodWithSecurityContexts(podSC(utilpointer.Int64Ptr(1)), nil), - psps: []*extensions.PodSecurityPolicy{runAsAny}, + psps: []*policy.PodSecurityPolicy{runAsAny}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: podSC(utilpointer.Int64Ptr(1)), @@ -1234,7 +1233,7 @@ func TestAdmitRunAsUser(t *testing.T) { }, "runAsAny container request": { pod: createPodWithSecurityContexts(nil, containerSC(utilpointer.Int64Ptr(1))), - psps: []*extensions.PodSecurityPolicy{runAsAny}, + psps: []*policy.PodSecurityPolicy{runAsAny}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: nil, @@ -1244,20 +1243,20 @@ func TestAdmitRunAsUser(t *testing.T) { "mustRunAs pod request out of range": { pod: createPodWithSecurityContexts(podSC(utilpointer.Int64Ptr(1)), nil), - psps: []*extensions.PodSecurityPolicy{mustRunAs}, + psps: []*policy.PodSecurityPolicy{mustRunAs}, shouldPassAdmit: false, shouldPassValidate: false, }, "mustRunAs container request out of range": { pod: createPodWithSecurityContexts(podSC(utilpointer.Int64Ptr(999)), containerSC(utilpointer.Int64Ptr(1))), - psps: []*extensions.PodSecurityPolicy{mustRunAs}, + psps: []*policy.PodSecurityPolicy{mustRunAs}, shouldPassAdmit: false, shouldPassValidate: false, }, "mustRunAs pod request in range": { pod: createPodWithSecurityContexts(podSC(utilpointer.Int64Ptr(999)), nil), - psps: []*extensions.PodSecurityPolicy{mustRunAs}, + psps: []*policy.PodSecurityPolicy{mustRunAs}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: podSC(&mustRunAs.Spec.RunAsUser.Ranges[0].Min), @@ -1266,7 +1265,7 @@ func TestAdmitRunAsUser(t *testing.T) { }, "mustRunAs container request in range": { pod: createPodWithSecurityContexts(nil, containerSC(utilpointer.Int64Ptr(999))), - psps: []*extensions.PodSecurityPolicy{mustRunAs}, + psps: []*policy.PodSecurityPolicy{mustRunAs}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: nil, @@ -1275,7 +1274,7 @@ func TestAdmitRunAsUser(t *testing.T) { }, "mustRunAs pod and container request in range": { pod: createPodWithSecurityContexts(podSC(utilpointer.Int64Ptr(999)), containerSC(utilpointer.Int64Ptr(1000))), - psps: []*extensions.PodSecurityPolicy{mustRunAs}, + psps: []*policy.PodSecurityPolicy{mustRunAs}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: podSC(utilpointer.Int64Ptr(999)), @@ -1284,7 +1283,7 @@ func TestAdmitRunAsUser(t *testing.T) { }, "mustRunAs no request": { pod: createPodWithSecurityContexts(nil, nil), - psps: []*extensions.PodSecurityPolicy{mustRunAs}, + psps: []*policy.PodSecurityPolicy{mustRunAs}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: nil, @@ -1294,7 +1293,7 @@ func TestAdmitRunAsUser(t *testing.T) { "runAsNonRoot no request": { pod: createPodWithSecurityContexts(nil, nil), - psps: []*extensions.PodSecurityPolicy{runAsNonRoot}, + psps: []*policy.PodSecurityPolicy{runAsNonRoot}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: nil, @@ -1303,13 +1302,13 @@ func TestAdmitRunAsUser(t *testing.T) { }, "runAsNonRoot pod request root": { pod: createPodWithSecurityContexts(podSC(utilpointer.Int64Ptr(0)), nil), - psps: []*extensions.PodSecurityPolicy{runAsNonRoot}, + psps: []*policy.PodSecurityPolicy{runAsNonRoot}, shouldPassAdmit: false, shouldPassValidate: false, }, "runAsNonRoot pod request non-root": { pod: createPodWithSecurityContexts(podSC(utilpointer.Int64Ptr(1)), nil), - psps: []*extensions.PodSecurityPolicy{runAsNonRoot}, + psps: []*policy.PodSecurityPolicy{runAsNonRoot}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: podSC(utilpointer.Int64Ptr(1)), @@ -1317,13 +1316,13 @@ func TestAdmitRunAsUser(t *testing.T) { }, "runAsNonRoot container request root": { pod: createPodWithSecurityContexts(podSC(utilpointer.Int64Ptr(1)), containerSC(utilpointer.Int64Ptr(0))), - psps: []*extensions.PodSecurityPolicy{runAsNonRoot}, + psps: []*policy.PodSecurityPolicy{runAsNonRoot}, shouldPassAdmit: false, shouldPassValidate: false, }, "runAsNonRoot container request non-root": { pod: createPodWithSecurityContexts(podSC(utilpointer.Int64Ptr(1)), containerSC(utilpointer.Int64Ptr(2))), - psps: []*extensions.PodSecurityPolicy{runAsNonRoot}, + psps: []*policy.PodSecurityPolicy{runAsNonRoot}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: podSC(utilpointer.Int64Ptr(1)), @@ -1353,16 +1352,16 @@ func TestAdmitSupplementalGroups(t *testing.T) { runAsAny := permissivePSP() runAsAny.Name = "runAsAny" - runAsAny.Spec.SupplementalGroups.Rule = extensions.SupplementalGroupsStrategyRunAsAny + runAsAny.Spec.SupplementalGroups.Rule = policy.SupplementalGroupsStrategyRunAsAny mustRunAs := permissivePSP() mustRunAs.Name = "mustRunAs" - mustRunAs.Spec.SupplementalGroups.Rule = extensions.SupplementalGroupsStrategyMustRunAs - mustRunAs.Spec.SupplementalGroups.Ranges = []extensions.GroupIDRange{{Min: int64(999), Max: int64(1000)}} + mustRunAs.Spec.SupplementalGroups.Rule = policy.SupplementalGroupsStrategyMustRunAs + mustRunAs.Spec.SupplementalGroups.Ranges = []policy.GroupIDRange{{Min: int64(999), Max: int64(1000)}} tests := map[string]struct { pod *kapi.Pod - psps []*extensions.PodSecurityPolicy + psps []*policy.PodSecurityPolicy shouldPassAdmit bool shouldPassValidate bool expectedPodSC *kapi.PodSecurityContext @@ -1370,7 +1369,7 @@ func TestAdmitSupplementalGroups(t *testing.T) { }{ "runAsAny no pod request": { pod: createPodWithSecurityContexts(nil, nil), - psps: []*extensions.PodSecurityPolicy{runAsAny}, + psps: []*policy.PodSecurityPolicy{runAsAny}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: nil, @@ -1378,7 +1377,7 @@ func TestAdmitSupplementalGroups(t *testing.T) { }, "runAsAny empty pod request": { pod: createPodWithSecurityContexts(&kapi.PodSecurityContext{}, nil), - psps: []*extensions.PodSecurityPolicy{runAsAny}, + psps: []*policy.PodSecurityPolicy{runAsAny}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: &kapi.PodSecurityContext{}, @@ -1386,7 +1385,7 @@ func TestAdmitSupplementalGroups(t *testing.T) { }, "runAsAny empty pod request empty supplemental groups": { pod: createPodWithSecurityContexts(&kapi.PodSecurityContext{SupplementalGroups: []int64{}}, nil), - psps: []*extensions.PodSecurityPolicy{runAsAny}, + psps: []*policy.PodSecurityPolicy{runAsAny}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: &kapi.PodSecurityContext{SupplementalGroups: []int64{}}, @@ -1394,7 +1393,7 @@ func TestAdmitSupplementalGroups(t *testing.T) { }, "runAsAny pod request": { pod: createPodWithSecurityContexts(podSC(1), nil), - psps: []*extensions.PodSecurityPolicy{runAsAny}, + psps: []*policy.PodSecurityPolicy{runAsAny}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: &kapi.PodSecurityContext{SupplementalGroups: []int64{1}}, @@ -1402,7 +1401,7 @@ func TestAdmitSupplementalGroups(t *testing.T) { }, "mustRunAs no pod request": { pod: createPodWithSecurityContexts(nil, nil), - psps: []*extensions.PodSecurityPolicy{mustRunAs}, + psps: []*policy.PodSecurityPolicy{mustRunAs}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: podSC(mustRunAs.Spec.SupplementalGroups.Ranges[0].Min), @@ -1410,13 +1409,13 @@ func TestAdmitSupplementalGroups(t *testing.T) { }, "mustRunAs bad pod request": { pod: createPodWithSecurityContexts(podSC(1), nil), - psps: []*extensions.PodSecurityPolicy{mustRunAs}, + psps: []*policy.PodSecurityPolicy{mustRunAs}, shouldPassAdmit: false, shouldPassValidate: false, }, "mustRunAs good pod request": { pod: createPodWithSecurityContexts(podSC(999), nil), - psps: []*extensions.PodSecurityPolicy{mustRunAs}, + psps: []*policy.PodSecurityPolicy{mustRunAs}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: podSC(999), @@ -1447,14 +1446,14 @@ func TestAdmitFSGroup(t *testing.T) { runAsAny := restrictivePSP() runAsAny.Name = "runAsAny" - runAsAny.Spec.FSGroup.Rule = extensions.FSGroupStrategyRunAsAny + runAsAny.Spec.FSGroup.Rule = policy.FSGroupStrategyRunAsAny mustRunAs := restrictivePSP() mustRunAs.Name = "mustRunAs" tests := map[string]struct { pod *kapi.Pod - psps []*extensions.PodSecurityPolicy + psps []*policy.PodSecurityPolicy shouldPassAdmit bool shouldPassValidate bool expectedFSGroup *int64 @@ -1462,7 +1461,7 @@ func TestAdmitFSGroup(t *testing.T) { }{ "runAsAny no pod request": { pod: goodPod(), - psps: []*extensions.PodSecurityPolicy{runAsAny}, + psps: []*policy.PodSecurityPolicy{runAsAny}, shouldPassAdmit: true, shouldPassValidate: true, expectedFSGroup: nil, @@ -1470,7 +1469,7 @@ func TestAdmitFSGroup(t *testing.T) { }, "runAsAny pod request": { pod: createPodWithFSGroup(1), - psps: []*extensions.PodSecurityPolicy{runAsAny}, + psps: []*policy.PodSecurityPolicy{runAsAny}, shouldPassAdmit: true, shouldPassValidate: true, expectedFSGroup: utilpointer.Int64Ptr(1), @@ -1478,7 +1477,7 @@ func TestAdmitFSGroup(t *testing.T) { }, "mustRunAs no pod request": { pod: goodPod(), - psps: []*extensions.PodSecurityPolicy{mustRunAs}, + psps: []*policy.PodSecurityPolicy{mustRunAs}, shouldPassAdmit: true, shouldPassValidate: true, expectedFSGroup: &mustRunAs.Spec.SupplementalGroups.Ranges[0].Min, @@ -1486,13 +1485,13 @@ func TestAdmitFSGroup(t *testing.T) { }, "mustRunAs bad pod request": { pod: createPodWithFSGroup(1), - psps: []*extensions.PodSecurityPolicy{mustRunAs}, + psps: []*policy.PodSecurityPolicy{mustRunAs}, shouldPassAdmit: false, shouldPassValidate: false, }, "mustRunAs good pod request": { pod: createPodWithFSGroup(999), - psps: []*extensions.PodSecurityPolicy{mustRunAs}, + psps: []*policy.PodSecurityPolicy{mustRunAs}, shouldPassAdmit: true, shouldPassValidate: true, expectedFSGroup: utilpointer.Int64Ptr(999), @@ -1540,7 +1539,7 @@ func TestAdmitReadOnlyRootFilesystem(t *testing.T) { tests := map[string]struct { pod *kapi.Pod - psps []*extensions.PodSecurityPolicy + psps []*policy.PodSecurityPolicy shouldPassAdmit bool shouldPassValidate bool expectedRORFS bool @@ -1548,7 +1547,7 @@ func TestAdmitReadOnlyRootFilesystem(t *testing.T) { }{ "no-rorfs allows pod request with rorfs": { pod: createPodWithRORFS(true), - psps: []*extensions.PodSecurityPolicy{noRORFS}, + psps: []*policy.PodSecurityPolicy{noRORFS}, shouldPassAdmit: true, shouldPassValidate: true, expectedRORFS: true, @@ -1556,7 +1555,7 @@ func TestAdmitReadOnlyRootFilesystem(t *testing.T) { }, "no-rorfs allows pod request without rorfs": { pod: createPodWithRORFS(false), - psps: []*extensions.PodSecurityPolicy{noRORFS}, + psps: []*policy.PodSecurityPolicy{noRORFS}, shouldPassAdmit: true, shouldPassValidate: true, expectedRORFS: false, @@ -1564,13 +1563,13 @@ func TestAdmitReadOnlyRootFilesystem(t *testing.T) { }, "rorfs rejects pod request without rorfs": { pod: createPodWithRORFS(false), - psps: []*extensions.PodSecurityPolicy{rorfs}, + psps: []*policy.PodSecurityPolicy{rorfs}, shouldPassAdmit: false, shouldPassValidate: false, }, "rorfs defaults nil pod request": { pod: goodPod(), - psps: []*extensions.PodSecurityPolicy{rorfs}, + psps: []*policy.PodSecurityPolicy{rorfs}, shouldPassAdmit: true, shouldPassValidate: true, expectedRORFS: true, @@ -1578,7 +1577,7 @@ func TestAdmitReadOnlyRootFilesystem(t *testing.T) { }, "rorfs accepts pod request with rorfs": { pod: createPodWithRORFS(true), - psps: []*extensions.PodSecurityPolicy{rorfs}, + psps: []*policy.PodSecurityPolicy{rorfs}, shouldPassAdmit: true, shouldPassValidate: true, expectedRORFS: true, @@ -1619,156 +1618,156 @@ func TestAdmitSysctls(t *testing.T) { emptySysctls := restrictivePSP() emptySysctls.Name = "empty sysctls" - emptySysctls.Annotations[extensions.SysctlsPodSecurityPolicyAnnotationKey] = "" + emptySysctls.Annotations[policy.SysctlsPodSecurityPolicyAnnotationKey] = "" mixedSysctls := restrictivePSP() mixedSysctls.Name = "wildcard sysctls" - mixedSysctls.Annotations[extensions.SysctlsPodSecurityPolicyAnnotationKey] = "a.*,b.*,c,d.e.f" + mixedSysctls.Annotations[policy.SysctlsPodSecurityPolicyAnnotationKey] = "a.*,b.*,c,d.e.f" aSysctl := restrictivePSP() aSysctl.Name = "a sysctl" - aSysctl.Annotations[extensions.SysctlsPodSecurityPolicyAnnotationKey] = "a" + aSysctl.Annotations[policy.SysctlsPodSecurityPolicyAnnotationKey] = "a" bSysctl := restrictivePSP() bSysctl.Name = "b sysctl" - bSysctl.Annotations[extensions.SysctlsPodSecurityPolicyAnnotationKey] = "b" + bSysctl.Annotations[policy.SysctlsPodSecurityPolicyAnnotationKey] = "b" cSysctl := restrictivePSP() cSysctl.Name = "c sysctl" - cSysctl.Annotations[extensions.SysctlsPodSecurityPolicyAnnotationKey] = "c" + cSysctl.Annotations[policy.SysctlsPodSecurityPolicyAnnotationKey] = "c" catchallSysctls := restrictivePSP() catchallSysctls.Name = "catchall sysctl" - catchallSysctls.Annotations[extensions.SysctlsPodSecurityPolicyAnnotationKey] = "*" + catchallSysctls.Annotations[policy.SysctlsPodSecurityPolicyAnnotationKey] = "*" tests := map[string]struct { pod *kapi.Pod - psps []*extensions.PodSecurityPolicy + psps []*policy.PodSecurityPolicy shouldPassAdmit bool shouldPassValidate bool expectedPSP string }{ "pod without unsafe sysctls request allowed under noSysctls PSP": { pod: goodPod(), - psps: []*extensions.PodSecurityPolicy{noSysctls}, + psps: []*policy.PodSecurityPolicy{noSysctls}, shouldPassAdmit: true, shouldPassValidate: true, expectedPSP: noSysctls.Name, }, "pod without any sysctls request allowed under emptySysctls PSP": { pod: goodPod(), - psps: []*extensions.PodSecurityPolicy{emptySysctls}, + psps: []*policy.PodSecurityPolicy{emptySysctls}, shouldPassAdmit: true, shouldPassValidate: true, expectedPSP: emptySysctls.Name, }, "pod with safe sysctls request allowed under noSysctls PSP": { pod: podWithSysctls([]string{"a", "b"}, []string{}), - psps: []*extensions.PodSecurityPolicy{noSysctls}, + psps: []*policy.PodSecurityPolicy{noSysctls}, shouldPassAdmit: true, shouldPassValidate: true, expectedPSP: noSysctls.Name, }, "pod with unsafe sysctls request allowed under noSysctls PSP": { pod: podWithSysctls([]string{}, []string{"a", "b"}), - psps: []*extensions.PodSecurityPolicy{noSysctls}, + psps: []*policy.PodSecurityPolicy{noSysctls}, shouldPassAdmit: true, shouldPassValidate: true, expectedPSP: noSysctls.Name, }, "pod with safe sysctls request disallowed under emptySysctls PSP": { pod: podWithSysctls([]string{"a", "b"}, []string{}), - psps: []*extensions.PodSecurityPolicy{emptySysctls}, + psps: []*policy.PodSecurityPolicy{emptySysctls}, shouldPassAdmit: false, shouldPassValidate: false, }, "pod with unsafe sysctls a, b request disallowed under aSysctls SCC": { pod: podWithSysctls([]string{}, []string{"a", "b"}), - psps: []*extensions.PodSecurityPolicy{aSysctl}, + psps: []*policy.PodSecurityPolicy{aSysctl}, shouldPassAdmit: false, shouldPassValidate: false, }, "pod with unsafe sysctls b request disallowed under aSysctls SCC": { pod: podWithSysctls([]string{}, []string{"b"}), - psps: []*extensions.PodSecurityPolicy{aSysctl}, + psps: []*policy.PodSecurityPolicy{aSysctl}, shouldPassAdmit: false, shouldPassValidate: false, }, "pod with unsafe sysctls a request allowed under aSysctls SCC": { pod: podWithSysctls([]string{}, []string{"a"}), - psps: []*extensions.PodSecurityPolicy{aSysctl}, + psps: []*policy.PodSecurityPolicy{aSysctl}, shouldPassAdmit: true, shouldPassValidate: true, expectedPSP: aSysctl.Name, }, "pod with safe sysctls a, b request disallowed under aSysctls SCC": { pod: podWithSysctls([]string{"a", "b"}, []string{}), - psps: []*extensions.PodSecurityPolicy{aSysctl}, + psps: []*policy.PodSecurityPolicy{aSysctl}, shouldPassAdmit: false, shouldPassValidate: false, }, "pod with safe sysctls b request disallowed under aSysctls SCC": { pod: podWithSysctls([]string{"b"}, []string{}), - psps: []*extensions.PodSecurityPolicy{aSysctl}, + psps: []*policy.PodSecurityPolicy{aSysctl}, shouldPassAdmit: false, shouldPassValidate: false, }, "pod with safe sysctls a request allowed under aSysctls SCC": { pod: podWithSysctls([]string{"a"}, []string{}), - psps: []*extensions.PodSecurityPolicy{aSysctl}, + psps: []*policy.PodSecurityPolicy{aSysctl}, shouldPassAdmit: true, shouldPassValidate: true, expectedPSP: aSysctl.Name, }, "pod with unsafe sysctls request disallowed under emptySysctls PSP": { pod: podWithSysctls([]string{}, []string{"a", "b"}), - psps: []*extensions.PodSecurityPolicy{emptySysctls}, + psps: []*policy.PodSecurityPolicy{emptySysctls}, shouldPassAdmit: false, shouldPassValidate: false, }, "pod with matching sysctls request allowed under mixedSysctls PSP": { pod: podWithSysctls([]string{"a.b", "b.c"}, []string{"c", "d.e.f"}), - psps: []*extensions.PodSecurityPolicy{mixedSysctls}, + psps: []*policy.PodSecurityPolicy{mixedSysctls}, shouldPassAdmit: true, shouldPassValidate: true, expectedPSP: mixedSysctls.Name, }, "pod with not-matching unsafe sysctls request disallowed under mixedSysctls PSP": { pod: podWithSysctls([]string{"a.b", "b.c", "c", "d.e.f"}, []string{"e"}), - psps: []*extensions.PodSecurityPolicy{mixedSysctls}, + psps: []*policy.PodSecurityPolicy{mixedSysctls}, shouldPassAdmit: false, shouldPassValidate: false, }, "pod with not-matching safe sysctls request disallowed under mixedSysctls PSP": { pod: podWithSysctls([]string{"a.b", "b.c", "c", "d.e.f", "e"}, []string{}), - psps: []*extensions.PodSecurityPolicy{mixedSysctls}, + psps: []*policy.PodSecurityPolicy{mixedSysctls}, shouldPassAdmit: false, shouldPassValidate: false, }, "pod with sysctls request allowed under catchallSysctls PSP": { pod: podWithSysctls([]string{"e"}, []string{"f"}), - psps: []*extensions.PodSecurityPolicy{catchallSysctls}, + psps: []*policy.PodSecurityPolicy{catchallSysctls}, shouldPassAdmit: true, shouldPassValidate: true, expectedPSP: catchallSysctls.Name, }, "pod with sysctls request allowed under catchallSysctls PSP, not under mixedSysctls or emptySysctls PSP": { pod: podWithSysctls([]string{"e"}, []string{"f"}), - psps: []*extensions.PodSecurityPolicy{mixedSysctls, catchallSysctls, emptySysctls}, + psps: []*policy.PodSecurityPolicy{mixedSysctls, catchallSysctls, emptySysctls}, shouldPassAdmit: true, shouldPassValidate: true, expectedPSP: catchallSysctls.Name, }, "pod with safe c sysctl request allowed under cSysctl PSP, not under aSysctl or bSysctl PSP": { pod: podWithSysctls([]string{}, []string{"c"}), - psps: []*extensions.PodSecurityPolicy{aSysctl, bSysctl, cSysctl}, + psps: []*policy.PodSecurityPolicy{aSysctl, bSysctl, cSysctl}, shouldPassAdmit: true, shouldPassValidate: true, expectedPSP: cSysctl.Name, }, "pod with unsafe c sysctl request allowed under cSysctl PSP, not under aSysctl or bSysctl PSP": { pod: podWithSysctls([]string{"c"}, []string{}), - psps: []*extensions.PodSecurityPolicy{aSysctl, bSysctl, cSysctl}, + psps: []*policy.PodSecurityPolicy{aSysctl, bSysctl, cSysctl}, shouldPassAdmit: true, shouldPassValidate: true, expectedPSP: cSysctl.Name, @@ -1795,11 +1794,11 @@ func TestAdmitSysctls(t *testing.T) { } } -func testPSPAdmit(testCaseName string, psps []*extensions.PodSecurityPolicy, pod *kapi.Pod, shouldPassAdmit, shouldPassValidate bool, expectedPSP string, t *testing.T) { +func testPSPAdmit(testCaseName string, psps []*policy.PodSecurityPolicy, pod *kapi.Pod, shouldPassAdmit, shouldPassValidate bool, expectedPSP string, t *testing.T) { testPSPAdmitAdvanced(testCaseName, kadmission.Create, psps, nil, &user.DefaultInfo{}, pod, nil, shouldPassAdmit, shouldPassValidate, true, expectedPSP, t) } -func testPSPAdmitAdvanced(testCaseName string, op kadmission.Operation, psps []*extensions.PodSecurityPolicy, authz authorizer.Authorizer, userInfo user.Info, pod, oldPod *kapi.Pod, shouldPassAdmit, shouldPassValidate bool, canMutate bool, expectedPSP string, t *testing.T) { +func testPSPAdmitAdvanced(testCaseName string, op kadmission.Operation, psps []*policy.PodSecurityPolicy, authz authorizer.Authorizer, userInfo user.Info, pod, oldPod *kapi.Pod, shouldPassAdmit, shouldPassValidate bool, canMutate bool, expectedPSP string, t *testing.T) { originalPod := pod.DeepCopy() plugin := NewTestAdmission(psps, authz) @@ -1907,50 +1906,50 @@ func TestAssignSecurityContext(t *testing.T) { func TestCreateProvidersFromConstraints(t *testing.T) { testCases := map[string]struct { // use a generating function so we can test for non-mutation - psp func() *extensions.PodSecurityPolicy + psp func() *policy.PodSecurityPolicy expectedErr string }{ "valid psp": { - psp: func() *extensions.PodSecurityPolicy { - return &extensions.PodSecurityPolicy{ + psp: func() *policy.PodSecurityPolicy { + return &policy.PodSecurityPolicy{ ObjectMeta: metav1.ObjectMeta{ Name: "valid psp", }, - Spec: extensions.PodSecurityPolicySpec{ - SELinux: extensions.SELinuxStrategyOptions{ - Rule: extensions.SELinuxStrategyRunAsAny, + Spec: policy.PodSecurityPolicySpec{ + SELinux: policy.SELinuxStrategyOptions{ + Rule: policy.SELinuxStrategyRunAsAny, }, - RunAsUser: extensions.RunAsUserStrategyOptions{ - Rule: extensions.RunAsUserStrategyRunAsAny, + RunAsUser: policy.RunAsUserStrategyOptions{ + Rule: policy.RunAsUserStrategyRunAsAny, }, - FSGroup: extensions.FSGroupStrategyOptions{ - Rule: extensions.FSGroupStrategyRunAsAny, + FSGroup: policy.FSGroupStrategyOptions{ + Rule: policy.FSGroupStrategyRunAsAny, }, - SupplementalGroups: extensions.SupplementalGroupsStrategyOptions{ - Rule: extensions.SupplementalGroupsStrategyRunAsAny, + SupplementalGroups: policy.SupplementalGroupsStrategyOptions{ + Rule: policy.SupplementalGroupsStrategyRunAsAny, }, }, } }, }, "bad psp strategy options": { - psp: func() *extensions.PodSecurityPolicy { - return &extensions.PodSecurityPolicy{ + psp: func() *policy.PodSecurityPolicy { + return &policy.PodSecurityPolicy{ ObjectMeta: metav1.ObjectMeta{ Name: "bad psp user options", }, - Spec: extensions.PodSecurityPolicySpec{ - SELinux: extensions.SELinuxStrategyOptions{ - Rule: extensions.SELinuxStrategyRunAsAny, + Spec: policy.PodSecurityPolicySpec{ + SELinux: policy.SELinuxStrategyOptions{ + Rule: policy.SELinuxStrategyRunAsAny, }, - RunAsUser: extensions.RunAsUserStrategyOptions{ - Rule: extensions.RunAsUserStrategyMustRunAs, + RunAsUser: policy.RunAsUserStrategyOptions{ + Rule: policy.RunAsUserStrategyMustRunAs, }, - FSGroup: extensions.FSGroupStrategyOptions{ - Rule: extensions.FSGroupStrategyRunAsAny, + FSGroup: policy.FSGroupStrategyOptions{ + Rule: policy.FSGroupStrategyRunAsAny, }, - SupplementalGroups: extensions.SupplementalGroupsStrategyOptions{ - Rule: extensions.SupplementalGroupsStrategyRunAsAny, + SupplementalGroups: policy.SupplementalGroupsStrategyOptions{ + Rule: policy.SupplementalGroupsStrategyRunAsAny, }, }, } @@ -1966,7 +1965,7 @@ func TestCreateProvidersFromConstraints(t *testing.T) { } psp := v.psp() - _, errs := admit.createProvidersFromPolicies([]*extensions.PodSecurityPolicy{psp}, "namespace") + _, errs := admit.createProvidersFromPolicies([]*policy.PodSecurityPolicy{psp}, "namespace") if !reflect.DeepEqual(psp, v.psp()) { diff := diff.ObjectDiff(psp, v.psp()) @@ -1991,7 +1990,7 @@ func TestCreateProvidersFromConstraints(t *testing.T) { } func TestPolicyAuthorization(t *testing.T) { - policyWithName := func(name string) *extensions.PodSecurityPolicy { + policyWithName := func(name string) *policy.PodSecurityPolicy { p := permissivePSP() p.Name = name return p @@ -2002,7 +2001,7 @@ func TestPolicyAuthorization(t *testing.T) { sa string ns string expectedPolicy string - inPolicies []*extensions.PodSecurityPolicy + inPolicies []*policy.PodSecurityPolicy allowed map[string]map[string]map[string]bool allowedGroup string }{ @@ -2015,7 +2014,7 @@ func TestPolicyAuthorization(t *testing.T) { "test": {"policy": true}, }, }, - inPolicies: []*extensions.PodSecurityPolicy{policyWithName("policy")}, + inPolicies: []*policy.PodSecurityPolicy{policyWithName("policy")}, expectedPolicy: "policy", }, "policy allowed by sa (extensions API Group)": { @@ -2027,7 +2026,7 @@ func TestPolicyAuthorization(t *testing.T) { "test": {"policy": true}, }, }, - inPolicies: []*extensions.PodSecurityPolicy{policyWithName("policy")}, + inPolicies: []*policy.PodSecurityPolicy{policyWithName("policy")}, expectedPolicy: "policy", }, "policy allowed by user (policy API Group)": { @@ -2039,7 +2038,7 @@ func TestPolicyAuthorization(t *testing.T) { "test": {"policy": true}, }, }, - inPolicies: []*extensions.PodSecurityPolicy{policyWithName("policy")}, + inPolicies: []*policy.PodSecurityPolicy{policyWithName("policy")}, expectedPolicy: "policy", allowedGroup: policy.GroupName, }, @@ -2052,7 +2051,7 @@ func TestPolicyAuthorization(t *testing.T) { "test": {"policy": true}, }, }, - inPolicies: []*extensions.PodSecurityPolicy{policyWithName("policy")}, + inPolicies: []*policy.PodSecurityPolicy{policyWithName("policy")}, expectedPolicy: "policy", allowedGroup: policy.GroupName, }, @@ -2061,7 +2060,7 @@ func TestPolicyAuthorization(t *testing.T) { sa: "sa", ns: "test", allowed: map[string]map[string]map[string]bool{}, - inPolicies: []*extensions.PodSecurityPolicy{policyWithName("policy")}, + inPolicies: []*policy.PodSecurityPolicy{policyWithName("policy")}, expectedPolicy: "", }, "multiple policies allowed": { @@ -2080,7 +2079,7 @@ func TestPolicyAuthorization(t *testing.T) { "other": {"policy7": true}, }, }, - inPolicies: []*extensions.PodSecurityPolicy{ + inPolicies: []*policy.PodSecurityPolicy{ // Prefix to force checking these policies first. policyWithName("a_policy1"), // not allowed in this namespace policyWithName("a_policy2"), // not allowed in this namespace @@ -2104,7 +2103,7 @@ func TestPolicyAuthorization(t *testing.T) { "test": {"policy2": true}, }, }, - inPolicies: []*extensions.PodSecurityPolicy{ + inPolicies: []*policy.PodSecurityPolicy{ policyWithName("policy1"), policyWithName("policy2"), policyWithName("policy3"), @@ -2124,7 +2123,7 @@ func TestPolicyAuthorization(t *testing.T) { "test": {"policy2": true}, }, }, - inPolicies: []*extensions.PodSecurityPolicy{ + inPolicies: []*policy.PodSecurityPolicy{ policyWithName("policy1"), policyWithName("policy2"), policyWithName("policy3"), @@ -2144,7 +2143,7 @@ func TestPolicyAuthorization(t *testing.T) { "test": {"policy2": true}, }, }, - inPolicies: []*extensions.PodSecurityPolicy{ + inPolicies: []*policy.PodSecurityPolicy{ policyWithName("policy1"), policyWithName("policy2"), policyWithName("policy3"), @@ -2169,7 +2168,7 @@ func TestPolicyAuthorization(t *testing.T) { } func TestPolicyAuthorizationErrors(t *testing.T) { - policyWithName := func(name string) *extensions.PodSecurityPolicy { + policyWithName := func(name string) *policy.PodSecurityPolicy { p := restrictivePSP() p.Name = name return p @@ -2182,13 +2181,13 @@ func TestPolicyAuthorizationErrors(t *testing.T) { ) tests := map[string]struct { - inPolicies []*extensions.PodSecurityPolicy + inPolicies []*policy.PodSecurityPolicy allowed map[string]map[string]map[string]bool expectValidationErrs int }{ "policies not allowed": { allowed: map[string]map[string]map[string]bool{}, - inPolicies: []*extensions.PodSecurityPolicy{ + inPolicies: []*policy.PodSecurityPolicy{ policyWithName("policy1"), policyWithName("policy2"), }, @@ -2200,7 +2199,7 @@ func TestPolicyAuthorizationErrors(t *testing.T) { "test": {"policy1": true}, }, }, - inPolicies: []*extensions.PodSecurityPolicy{ + inPolicies: []*policy.PodSecurityPolicy{ policyWithName("policy1"), policyWithName("policy2"), }, @@ -2212,7 +2211,7 @@ func TestPolicyAuthorizationErrors(t *testing.T) { "test": {"policy2": true}, }, }, - inPolicies: []*extensions.PodSecurityPolicy{ + inPolicies: []*policy.PodSecurityPolicy{ policyWithName("policy1"), policyWithName("policy2"), }, @@ -2227,7 +2226,7 @@ func TestPolicyAuthorizationErrors(t *testing.T) { "test": {"policy2": true}, }, }, - inPolicies: []*extensions.PodSecurityPolicy{ + inPolicies: []*policy.PodSecurityPolicy{ policyWithName("policy1"), policyWithName("policy2"), }, @@ -2254,26 +2253,26 @@ func TestPolicyAuthorizationErrors(t *testing.T) { } func TestPreferValidatedPSP(t *testing.T) { - restrictivePSPWithName := func(name string) *extensions.PodSecurityPolicy { + restrictivePSPWithName := func(name string) *policy.PodSecurityPolicy { p := restrictivePSP() p.Name = name return p } - permissivePSPWithName := func(name string) *extensions.PodSecurityPolicy { + permissivePSPWithName := func(name string) *policy.PodSecurityPolicy { p := permissivePSP() p.Name = name return p } tests := map[string]struct { - inPolicies []*extensions.PodSecurityPolicy + inPolicies []*policy.PodSecurityPolicy expectValidationErrs int validatedPSPHint string expectedPSP string }{ "no policy saved in annotations, PSPs are ordered lexicographically": { - inPolicies: []*extensions.PodSecurityPolicy{ + inPolicies: []*policy.PodSecurityPolicy{ restrictivePSPWithName("001restrictive"), restrictivePSPWithName("002restrictive"), permissivePSPWithName("002permissive"), @@ -2285,7 +2284,7 @@ func TestPreferValidatedPSP(t *testing.T) { expectedPSP: "001permissive", }, "policy saved in annotations is preferred": { - inPolicies: []*extensions.PodSecurityPolicy{ + inPolicies: []*policy.PodSecurityPolicy{ restrictivePSPWithName("001restrictive"), restrictivePSPWithName("002restrictive"), permissivePSPWithName("001permissive"), @@ -2297,7 +2296,7 @@ func TestPreferValidatedPSP(t *testing.T) { expectedPSP: "002permissive", }, "policy saved in annotations is invalid": { - inPolicies: []*extensions.PodSecurityPolicy{ + inPolicies: []*policy.PodSecurityPolicy{ restrictivePSPWithName("001restrictive"), restrictivePSPWithName("002restrictive"), }, @@ -2306,7 +2305,7 @@ func TestPreferValidatedPSP(t *testing.T) { expectedPSP: "", }, "policy saved in annotations is disallowed anymore": { - inPolicies: []*extensions.PodSecurityPolicy{ + inPolicies: []*policy.PodSecurityPolicy{ restrictivePSPWithName("001restrictive"), restrictivePSPWithName("002restrictive"), }, @@ -2315,7 +2314,7 @@ func TestPreferValidatedPSP(t *testing.T) { expectedPSP: "", }, "policy saved in annotations is disallowed anymore, but find another one": { - inPolicies: []*extensions.PodSecurityPolicy{ + inPolicies: []*policy.PodSecurityPolicy{ restrictivePSPWithName("001restrictive"), restrictivePSPWithName("002restrictive"), permissivePSPWithName("002permissive"), @@ -2346,34 +2345,34 @@ func TestPreferValidatedPSP(t *testing.T) { } } -func restrictivePSP() *extensions.PodSecurityPolicy { - return &extensions.PodSecurityPolicy{ +func restrictivePSP() *policy.PodSecurityPolicy { + return &policy.PodSecurityPolicy{ ObjectMeta: metav1.ObjectMeta{ Name: "restrictive", Annotations: map[string]string{}, }, - Spec: extensions.PodSecurityPolicySpec{ - RunAsUser: extensions.RunAsUserStrategyOptions{ - Rule: extensions.RunAsUserStrategyMustRunAs, - Ranges: []extensions.UserIDRange{ + Spec: policy.PodSecurityPolicySpec{ + RunAsUser: policy.RunAsUserStrategyOptions{ + Rule: policy.RunAsUserStrategyMustRunAs, + Ranges: []policy.UserIDRange{ {Min: int64(999), Max: int64(999)}, }, }, - SELinux: extensions.SELinuxStrategyOptions{ - Rule: extensions.SELinuxStrategyMustRunAs, + SELinux: policy.SELinuxStrategyOptions{ + Rule: policy.SELinuxStrategyMustRunAs, SELinuxOptions: &kapi.SELinuxOptions{ Level: "s9:z0,z1", }, }, - FSGroup: extensions.FSGroupStrategyOptions{ - Rule: extensions.FSGroupStrategyMustRunAs, - Ranges: []extensions.GroupIDRange{ + FSGroup: policy.FSGroupStrategyOptions{ + Rule: policy.FSGroupStrategyMustRunAs, + Ranges: []policy.GroupIDRange{ {Min: int64(999), Max: int64(999)}, }, }, - SupplementalGroups: extensions.SupplementalGroupsStrategyOptions{ - Rule: extensions.SupplementalGroupsStrategyMustRunAs, - Ranges: []extensions.GroupIDRange{ + SupplementalGroups: policy.SupplementalGroupsStrategyOptions{ + Rule: policy.SupplementalGroupsStrategyMustRunAs, + Ranges: []policy.GroupIDRange{ {Min: int64(999), Max: int64(999)}, }, }, @@ -2381,31 +2380,31 @@ func restrictivePSP() *extensions.PodSecurityPolicy { } } -func permissivePSP() *extensions.PodSecurityPolicy { - return &extensions.PodSecurityPolicy{ +func permissivePSP() *policy.PodSecurityPolicy { + return &policy.PodSecurityPolicy{ ObjectMeta: metav1.ObjectMeta{ Name: "privileged", Annotations: map[string]string{}, }, - Spec: extensions.PodSecurityPolicySpec{ + Spec: policy.PodSecurityPolicySpec{ AllowPrivilegeEscalation: true, HostIPC: true, HostNetwork: true, HostPID: true, - HostPorts: []extensions.HostPortRange{{Min: 0, Max: 65536}}, - Volumes: []extensions.FSType{extensions.All}, - AllowedCapabilities: []kapi.Capability{extensions.AllowAllCapabilities}, - RunAsUser: extensions.RunAsUserStrategyOptions{ - Rule: extensions.RunAsUserStrategyRunAsAny, + HostPorts: []policy.HostPortRange{{Min: 0, Max: 65536}}, + Volumes: []policy.FSType{policy.All}, + AllowedCapabilities: []kapi.Capability{policy.AllowAllCapabilities}, + RunAsUser: policy.RunAsUserStrategyOptions{ + Rule: policy.RunAsUserStrategyRunAsAny, }, - SELinux: extensions.SELinuxStrategyOptions{ - Rule: extensions.SELinuxStrategyRunAsAny, + SELinux: policy.SELinuxStrategyOptions{ + Rule: policy.SELinuxStrategyRunAsAny, }, - FSGroup: extensions.FSGroupStrategyOptions{ - Rule: extensions.FSGroupStrategyRunAsAny, + FSGroup: policy.FSGroupStrategyOptions{ + Rule: policy.FSGroupStrategyRunAsAny, }, - SupplementalGroups: extensions.SupplementalGroupsStrategyOptions{ - Rule: extensions.SupplementalGroupsStrategyRunAsAny, + SupplementalGroups: policy.SupplementalGroupsStrategyOptions{ + Rule: policy.SupplementalGroupsStrategyRunAsAny, }, }, }