mirror of https://github.com/k3s-io/k3s
Modify PodSecurityPolicy admission plugin to additionally allow authorizing via "use" verb in policy API group.
parent
a4222bd8c3
commit
3d4fa8a189
|
@ -5,7 +5,7 @@ metadata:
|
|||
name: restricted-psp-user
|
||||
rules:
|
||||
- apiGroups:
|
||||
- extensions
|
||||
- policy
|
||||
resources:
|
||||
- podsecuritypolicies
|
||||
resourceNames:
|
||||
|
@ -20,7 +20,7 @@ metadata:
|
|||
name: privileged-psp-user
|
||||
rules:
|
||||
- apiGroups:
|
||||
- extensions
|
||||
- policy
|
||||
resources:
|
||||
- podsecuritypolicies
|
||||
resourceNames:
|
||||
|
|
|
@ -33,6 +33,7 @@ import (
|
|||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"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"
|
||||
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
|
||||
|
@ -354,11 +355,19 @@ func isAuthorizedForPolicy(user, sa user.Info, namespace, policyName string, aut
|
|||
}
|
||||
|
||||
// authorizedForPolicy returns true if info is authorized to perform the "use" verb on the policy resource.
|
||||
// TODO: check against only the policy group when PSP will be completely moved out of the extensions
|
||||
func authorizedForPolicy(info user.Info, namespace string, policyName string, authz authorizer.Authorizer) bool {
|
||||
// Check against extensions API group for backward compatibility
|
||||
return authorizedForPolicyInAPIGroup(info, namespace, policyName, policy.GroupName, authz) ||
|
||||
authorizedForPolicyInAPIGroup(info, namespace, policyName, extensions.GroupName, authz)
|
||||
}
|
||||
|
||||
// authorizedForPolicyInAPIGroup returns true if info is authorized to perform the "use" verb on the policy resource in the specified API group.
|
||||
func authorizedForPolicyInAPIGroup(info user.Info, namespace, policyName, apiGroupName string, authz authorizer.Authorizer) bool {
|
||||
if info == nil {
|
||||
return false
|
||||
}
|
||||
attr := buildAttributes(info, namespace, policyName)
|
||||
attr := buildAttributes(info, namespace, policyName, apiGroupName)
|
||||
decision, reason, err := authz.Authorize(attr)
|
||||
if err != nil {
|
||||
glog.V(5).Infof("cannot authorize for policy: %v,%v", reason, err)
|
||||
|
@ -367,14 +376,14 @@ func authorizedForPolicy(info user.Info, namespace string, policyName string, au
|
|||
}
|
||||
|
||||
// buildAttributes builds an attributes record for a SAR based on the user info and policy.
|
||||
func buildAttributes(info user.Info, namespace string, policyName string) authorizer.Attributes {
|
||||
func buildAttributes(info user.Info, namespace, policyName, apiGroupName string) authorizer.Attributes {
|
||||
// check against the namespace that the pod is being created in to allow per-namespace PSP grants.
|
||||
attr := authorizer.AttributesRecord{
|
||||
User: info,
|
||||
Verb: "use",
|
||||
Namespace: namespace,
|
||||
Name: policyName,
|
||||
APIGroup: extensions.GroupName,
|
||||
APIGroup: apiGroupName,
|
||||
Resource: "podsecuritypolicies",
|
||||
ResourceRequest: true,
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ import (
|
|||
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"
|
||||
"k8s.io/kubernetes/pkg/security/apparmor"
|
||||
|
@ -71,6 +72,11 @@ type TestAuthorizer struct {
|
|||
// usernameToNamespaceToAllowedPSPs contains the map of allowed PSPs.
|
||||
// if nil, all PSPs are allowed.
|
||||
usernameToNamespaceToAllowedPSPs map[string]map[string]map[string]bool
|
||||
// allowedAPIGroupName specifies an API Group name that contains PSP resources.
|
||||
// In order to be authorized, AttributesRecord must have this group name.
|
||||
// When empty, API Group name isn't taken into account.
|
||||
// TODO: remove this when PSP will be completely moved out of the extensions and we'll lookup only in "policy" group.
|
||||
allowedAPIGroupName string
|
||||
}
|
||||
|
||||
func (t *TestAuthorizer) Authorize(a authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) {
|
||||
|
@ -79,7 +85,8 @@ func (t *TestAuthorizer) Authorize(a authorizer.Attributes) (authorized authoriz
|
|||
}
|
||||
allowedInNamespace := t.usernameToNamespaceToAllowedPSPs[a.GetUser().GetName()][a.GetNamespace()][a.GetName()]
|
||||
allowedClusterWide := t.usernameToNamespaceToAllowedPSPs[a.GetUser().GetName()][""][a.GetName()]
|
||||
if allowedInNamespace || allowedClusterWide {
|
||||
allowedAPIGroup := len(t.allowedAPIGroupName) == 0 || a.GetAPIGroup() == t.allowedAPIGroupName
|
||||
if allowedAPIGroup && (allowedInNamespace || allowedClusterWide) {
|
||||
return authorizer.DecisionAllow, "", nil
|
||||
}
|
||||
return authorizer.DecisionNoOpinion, "", nil
|
||||
|
@ -1996,8 +2003,9 @@ func TestPolicyAuthorization(t *testing.T) {
|
|||
expectedPolicy string
|
||||
inPolicies []*extensions.PodSecurityPolicy
|
||||
allowed map[string]map[string]map[string]bool
|
||||
allowedGroup string
|
||||
}{
|
||||
"policy allowed by user": {
|
||||
"policy allowed by user (extensions API Group)": {
|
||||
user: &user.DefaultInfo{Name: "user"},
|
||||
sa: "sa",
|
||||
ns: "test",
|
||||
|
@ -2009,7 +2017,7 @@ func TestPolicyAuthorization(t *testing.T) {
|
|||
inPolicies: []*extensions.PodSecurityPolicy{policyWithName("policy")},
|
||||
expectedPolicy: "policy",
|
||||
},
|
||||
"policy allowed by sa": {
|
||||
"policy allowed by sa (extensions API Group)": {
|
||||
user: &user.DefaultInfo{Name: "user"},
|
||||
sa: "sa",
|
||||
ns: "test",
|
||||
|
@ -2021,6 +2029,32 @@ func TestPolicyAuthorization(t *testing.T) {
|
|||
inPolicies: []*extensions.PodSecurityPolicy{policyWithName("policy")},
|
||||
expectedPolicy: "policy",
|
||||
},
|
||||
"policy allowed by user (policy API Group)": {
|
||||
user: &user.DefaultInfo{Name: "user"},
|
||||
sa: "sa",
|
||||
ns: "test",
|
||||
allowed: map[string]map[string]map[string]bool{
|
||||
"user": {
|
||||
"test": {"policy": true},
|
||||
},
|
||||
},
|
||||
inPolicies: []*extensions.PodSecurityPolicy{policyWithName("policy")},
|
||||
expectedPolicy: "policy",
|
||||
allowedGroup: policy.GroupName,
|
||||
},
|
||||
"policy allowed by sa (policy API Group)": {
|
||||
user: &user.DefaultInfo{Name: "user"},
|
||||
sa: "sa",
|
||||
ns: "test",
|
||||
allowed: map[string]map[string]map[string]bool{
|
||||
serviceaccount.MakeUsername("test", "sa"): {
|
||||
"test": {"policy": true},
|
||||
},
|
||||
},
|
||||
inPolicies: []*extensions.PodSecurityPolicy{policyWithName("policy")},
|
||||
expectedPolicy: "policy",
|
||||
allowedGroup: policy.GroupName,
|
||||
},
|
||||
"no policies allowed": {
|
||||
user: &user.DefaultInfo{Name: "user"},
|
||||
sa: "sa",
|
||||
|
@ -2122,7 +2156,7 @@ func TestPolicyAuthorization(t *testing.T) {
|
|||
var (
|
||||
oldPod *kapi.Pod
|
||||
shouldPass = v.expectedPolicy != ""
|
||||
authz = &TestAuthorizer{usernameToNamespaceToAllowedPSPs: v.allowed}
|
||||
authz = &TestAuthorizer{usernameToNamespaceToAllowedPSPs: v.allowed, allowedAPIGroupName: v.allowedGroup}
|
||||
canMutate = true
|
||||
)
|
||||
pod := goodPod()
|
||||
|
|
Loading…
Reference in New Issue