mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	Merge pull request #51337 from php-coder/psp_star_in_allowed_caps
Automatic merge from submit-queue (batch tested with PRs 51337, 47080, 52646, 52635, 52666). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.. PodSecurityPolicy.allowedCapabilities: add support for * to allow to request any capabilities **What this PR does / why we need it**: Prior this change there was no way to allow to pods to request any capabilities. Cluster admin had always specify a full list of capabilities explicitly. Because there are many of them, it gets tedious. This PR makes possible to use `*` to allow all possible capabilities. Non-paranoid (and lazy) cluster admins can use it. Those who are super strict and paranoid of course won't use it because `*` allows capabilities that don't exist today but may be introduced in the future. "privileged" PSP in examples was modified to allow privileged users to use this feature. **Which issue this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close that issue when PR gets merged)*: fixes #50055 **Special notes for your reviewer**: This functional is already present in OpenShift: https://github.com/openshift/origin/pull/12875 and https://github.com/openshift/origin/pull/15135 **Release note**: ```release-note PSP: add support for using `*` as a value in `allowedCapabilities` to allow to request any capabilities ``` CC @simo5 @pweil- @gyliu513 @liqlin2015
This commit is contained in:
		@@ -14,6 +14,8 @@ spec:
 | 
			
		||||
    rule: RunAsAny
 | 
			
		||||
  volumes:
 | 
			
		||||
  - '*'
 | 
			
		||||
  allowedCapabilities:
 | 
			
		||||
  - '*'
 | 
			
		||||
---
 | 
			
		||||
apiVersion: extensions/v1beta1
 | 
			
		||||
kind: PodSecurityPolicy
 | 
			
		||||
 
 | 
			
		||||
@@ -898,6 +898,7 @@ type PodSecurityPolicySpec struct {
 | 
			
		||||
	// 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 all plugins
 | 
			
		||||
@@ -966,6 +967,10 @@ type HostPortRange struct {
 | 
			
		||||
	Max int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -660,6 +660,10 @@ func ValidatePodSecurityPolicySpec(spec *extensions.PodSecurityPolicySpec, fldPa
 | 
			
		||||
	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)...)
 | 
			
		||||
 
 | 
			
		||||
@@ -2472,6 +2472,10 @@ func TestValidatePodSecurityPolicy(t *testing.T) {
 | 
			
		||||
		{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"}
 | 
			
		||||
@@ -2590,6 +2594,11 @@ func TestValidatePodSecurityPolicy(t *testing.T) {
 | 
			
		||||
			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,
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,7 @@ go_library(
 | 
			
		||||
    ],
 | 
			
		||||
    deps = [
 | 
			
		||||
        "//pkg/api:go_default_library",
 | 
			
		||||
        "//pkg/apis/extensions:go_default_library",
 | 
			
		||||
        "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
 | 
			
		||||
        "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
 | 
			
		||||
    ],
 | 
			
		||||
@@ -24,7 +25,10 @@ go_test(
 | 
			
		||||
    name = "go_default_test",
 | 
			
		||||
    srcs = ["mustrunas_test.go"],
 | 
			
		||||
    library = ":go_default_library",
 | 
			
		||||
    deps = ["//pkg/api:go_default_library"],
 | 
			
		||||
    deps = [
 | 
			
		||||
        "//pkg/api:go_default_library",
 | 
			
		||||
        "//pkg/apis/extensions:go_default_library",
 | 
			
		||||
    ],
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
filegroup(
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,7 @@ import (
 | 
			
		||||
	"k8s.io/apimachinery/pkg/util/sets"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/util/validation/field"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/api"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/apis/extensions"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// defaultCapabilities implements the Strategy interface
 | 
			
		||||
@@ -101,9 +102,15 @@ func (s *defaultCapabilities) Validate(pod *api.Pod, container *api.Container) f
 | 
			
		||||
		return allErrs
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	allowedAdd := makeCapSet(s.allowedCaps)
 | 
			
		||||
	allowAllCaps := allowedAdd.Has(string(extensions.AllowAllCapabilities))
 | 
			
		||||
	if allowAllCaps {
 | 
			
		||||
		// skip validation against allowed/defaultAdd/requiredDrop because all capabilities are allowed by a wildcard
 | 
			
		||||
		return allErrs
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// validate that anything being added is in the default or allowed sets
 | 
			
		||||
	defaultAdd := makeCapSet(s.defaultAddCapabilities)
 | 
			
		||||
	allowedAdd := makeCapSet(s.allowedCaps)
 | 
			
		||||
 | 
			
		||||
	for _, cap := range container.SecurityContext.Capabilities.Add {
 | 
			
		||||
		sCap := string(cap)
 | 
			
		||||
 
 | 
			
		||||
@@ -21,6 +21,7 @@ import (
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"k8s.io/kubernetes/pkg/api"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/apis/extensions"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestGenerateAdds(t *testing.T) {
 | 
			
		||||
@@ -250,6 +251,12 @@ func TestValidateAdds(t *testing.T) {
 | 
			
		||||
				Add: []api.Capability{"foo"},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		"no required, all allowed, container requests valid": {
 | 
			
		||||
			allowedCaps: []api.Capability{extensions.AllowAllCapabilities},
 | 
			
		||||
			containerCaps: &api.Capabilities{
 | 
			
		||||
				Add: []api.Capability{"foo"},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		"no required, allowed, container requests invalid": {
 | 
			
		||||
			allowedCaps: []api.Capability{"foo"},
 | 
			
		||||
			containerCaps: &api.Capabilities{
 | 
			
		||||
 
 | 
			
		||||
@@ -272,6 +272,10 @@ func TestAdmitCaps(t *testing.T) {
 | 
			
		||||
	requiresFooToBeDropped.Name = "requireDrop"
 | 
			
		||||
	requiresFooToBeDropped.Spec.RequiredDropCapabilities = []kapi.Capability{"foo"}
 | 
			
		||||
 | 
			
		||||
	allowAllInAllowed := restrictivePSP()
 | 
			
		||||
	allowAllInAllowed.Name = "allowAllCapsInAllowed"
 | 
			
		||||
	allowAllInAllowed.Spec.AllowedCapabilities = []kapi.Capability{extensions.AllowAllCapabilities}
 | 
			
		||||
 | 
			
		||||
	tc := map[string]struct {
 | 
			
		||||
		pod                  *kapi.Pod
 | 
			
		||||
		psps                 []*extensions.PodSecurityPolicy
 | 
			
		||||
@@ -337,6 +341,13 @@ func TestAdmitCaps(t *testing.T) {
 | 
			
		||||
			},
 | 
			
		||||
			expectedPSP: requiresFooToBeDropped.Name,
 | 
			
		||||
		},
 | 
			
		||||
		// 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},
 | 
			
		||||
			shouldPass:  true,
 | 
			
		||||
			expectedPSP: allowAllInAllowed.Name,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for k, v := range tc {
 | 
			
		||||
@@ -1360,7 +1371,7 @@ func testPSPAdmit(testCaseName string, psps []*extensions.PodSecurityPolicy, pod
 | 
			
		||||
 | 
			
		||||
	if shouldPass && err == nil {
 | 
			
		||||
		if pod.Annotations[psputil.ValidatedPSPAnnotation] != expectedPSP {
 | 
			
		||||
			t.Errorf("%s: expected to validate under %s but found %s", testCaseName, expectedPSP, pod.Annotations[psputil.ValidatedPSPAnnotation])
 | 
			
		||||
			t.Errorf("%s: expected to validate under %q PSP but found %q", testCaseName, expectedPSP, pod.Annotations[psputil.ValidatedPSPAnnotation])
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user