Propagate context to Authorize() calls

This commit is contained in:
Jordan Liggitt
2019-09-24 10:06:32 -04:00
parent 4ffa91a388
commit 92eb072989
36 changed files with 97 additions and 77 deletions

View File

@@ -126,7 +126,7 @@ func (p *Plugin) Admit(ctx context.Context, a admission.Attributes, o admission.
pod := a.GetObject().(*api.Pod)
// compute the context. Mutation is allowed. ValidatedPSPAnnotation is not taken into account.
allowedPod, pspName, validationErrs, err := p.computeSecurityContext(a, pod, true, "")
allowedPod, pspName, validationErrs, err := p.computeSecurityContext(ctx, a, pod, true, "")
if err != nil {
return admission.NewForbidden(a, err)
}
@@ -161,7 +161,7 @@ func (p *Plugin) Validate(ctx context.Context, a admission.Attributes, o admissi
pod := a.GetObject().(*api.Pod)
// compute the context. Mutation is not allowed. ValidatedPSPAnnotation is used as a hint to gain same speed-up.
allowedPod, pspName, validationErrs, err := p.computeSecurityContext(a, pod, false, pod.ObjectMeta.Annotations[psputil.ValidatedPSPAnnotation])
allowedPod, pspName, validationErrs, err := p.computeSecurityContext(ctx, a, pod, false, pod.ObjectMeta.Annotations[psputil.ValidatedPSPAnnotation])
if err != nil {
return admission.NewForbidden(a, err)
}
@@ -207,7 +207,7 @@ func shouldIgnore(a admission.Attributes) (bool, error) {
// if there is a matching policy with the same security context as given, it will be reused. If there is no
// matching policy the returned pod will be nil and the pspName empty. validatedPSPHint is the validated psp name
// saved in kubernetes.io/psp annotation. This psp is usually the one we are looking for.
func (p *Plugin) computeSecurityContext(a admission.Attributes, pod *api.Pod, specMutationAllowed bool, validatedPSPHint string) (*api.Pod, string, field.ErrorList, error) {
func (p *Plugin) computeSecurityContext(ctx context.Context, a admission.Attributes, pod *api.Pod, specMutationAllowed bool, validatedPSPHint string) (*api.Pod, string, field.ErrorList, error) {
// get all constraints that are usable by the user
klog.V(4).Infof("getting pod security policies for pod %s (generate: %s)", pod.Name, pod.GenerateName)
var saInfo user.Info
@@ -271,7 +271,7 @@ func (p *Plugin) computeSecurityContext(a admission.Attributes, pod *api.Pod, sp
continue
}
if !isAuthorizedForPolicy(a.GetUserInfo(), saInfo, a.GetNamespace(), provider.GetPSPName(), p.authz) {
if !isAuthorizedForPolicy(ctx, a.GetUserInfo(), saInfo, a.GetNamespace(), provider.GetPSPName(), p.authz) {
continue
}
@@ -295,7 +295,7 @@ func (p *Plugin) computeSecurityContext(a admission.Attributes, pod *api.Pod, sp
// Pod is rejected. Filter the validation errors to only include errors from authorized PSPs.
aggregate := field.ErrorList{}
for psp, errs := range validationErrs {
if isAuthorizedForPolicy(a.GetUserInfo(), saInfo, a.GetNamespace(), psp, p.authz) {
if isAuthorizedForPolicy(ctx, a.GetUserInfo(), saInfo, a.GetNamespace(), psp, p.authz) {
aggregate = append(aggregate, errs...)
}
}
@@ -338,27 +338,27 @@ func (p *Plugin) createProvidersFromPolicies(psps []*policyv1beta1.PodSecurityPo
return providers, errs
}
func isAuthorizedForPolicy(user, sa user.Info, namespace, policyName string, authz authorizer.Authorizer) bool {
func isAuthorizedForPolicy(ctx context.Context, user, sa user.Info, namespace, policyName string, authz authorizer.Authorizer) bool {
// Check the service account first, as that is the more common use case.
return authorizedForPolicy(sa, namespace, policyName, authz) ||
authorizedForPolicy(user, namespace, policyName, authz)
return authorizedForPolicy(ctx, sa, namespace, policyName, authz) ||
authorizedForPolicy(ctx, user, namespace, policyName, authz)
}
// 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 {
func authorizedForPolicy(ctx context.Context, 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)
return authorizedForPolicyInAPIGroup(ctx, info, namespace, policyName, policy.GroupName, authz) ||
authorizedForPolicyInAPIGroup(ctx, 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 {
func authorizedForPolicyInAPIGroup(ctx context.Context, info user.Info, namespace, policyName, apiGroupName string, authz authorizer.Authorizer) bool {
if info == nil {
return false
}
attr := buildAttributes(info, namespace, policyName, apiGroupName)
decision, reason, err := authz.Authorize(attr)
decision, reason, err := authz.Authorize(ctx, attr)
if err != nil {
klog.V(5).Infof("cannot authorize for policy: %v,%v", reason, err)
}

View File

@@ -84,7 +84,7 @@ type TestAuthorizer struct {
allowedAPIGroupName string
}
func (t *TestAuthorizer) Authorize(a authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) {
func (t *TestAuthorizer) Authorize(ctx context.Context, a authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) {
if t.usernameToNamespaceToAllowedPSPs == nil {
return authorizer.DecisionAllow, "", nil
}
@@ -2249,7 +2249,7 @@ func TestPolicyAuthorizationErrors(t *testing.T) {
plugin := NewTestAdmission(tc.inPolicies, authz)
attrs := kadmission.NewAttributesRecord(pod, nil, kapi.Kind("Pod").WithVersion("version"), ns, "", kapi.Resource("pods").WithVersion("version"), "", kadmission.Create, &metav1.CreateOptions{}, false, &user.DefaultInfo{Name: userName})
allowedPod, _, validationErrs, err := plugin.computeSecurityContext(attrs, pod, true, "")
allowedPod, _, validationErrs, err := plugin.computeSecurityContext(context.Background(), attrs, pod, true, "")
assert.Nil(t, allowedPod)
assert.NoError(t, err)
assert.Len(t, validationErrs, tc.expectValidationErrs)
@@ -2342,7 +2342,7 @@ func TestPreferValidatedPSP(t *testing.T) {
plugin := NewTestAdmission(tc.inPolicies, authz)
attrs := kadmission.NewAttributesRecord(pod, nil, kapi.Kind("Pod").WithVersion("version"), "ns", "", kapi.Resource("pods").WithVersion("version"), "", kadmission.Update, &metav1.UpdateOptions{}, false, &user.DefaultInfo{Name: "test"})
_, pspName, validationErrs, err := plugin.computeSecurityContext(attrs, pod, false, tc.validatedPSPHint)
_, pspName, validationErrs, err := plugin.computeSecurityContext(context.Background(), attrs, pod, false, tc.validatedPSPHint)
assert.NoError(t, err)
assert.Len(t, validationErrs, tc.expectValidationErrs)
assert.Equal(t, tc.expectedPSP, pspName)