mirror of https://github.com/k3s-io/k3s
PodSecurityPolicy.allowedCapabilities: add support for using * to allow to request any capabilities.
Also modify "privileged" PSP to use it and allow privileged users to use any capabilities.pull/6/head
parent
bef5cf386e
commit
9015a82692
|
@ -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"}
|
||||
|
@ -2586,6 +2590,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,
|
||||
|
|
|
@ -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])
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue