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

@ -19,6 +19,7 @@ package abac
import ( import (
"bufio" "bufio"
"context"
"fmt" "fmt"
"os" "os"
"strings" "strings"
@ -224,7 +225,7 @@ func resourceMatches(p abac.Policy, a authorizer.Attributes) bool {
} }
// Authorize implements authorizer.Authorize // Authorize implements authorizer.Authorize
func (pl PolicyList) Authorize(a authorizer.Attributes) (authorizer.Decision, string, error) { func (pl PolicyList) Authorize(ctx context.Context, a authorizer.Attributes) (authorizer.Decision, string, error) {
for _, p := range pl { for _, p := range pl {
if matches(*p, a) { if matches(*p, a) {
return authorizer.DecisionAllow, "", nil return authorizer.DecisionAllow, "", nil

View File

@ -17,6 +17,7 @@ limitations under the License.
package abac package abac
import ( import (
"context"
"io/ioutil" "io/ioutil"
"os" "os"
"reflect" "reflect"
@ -133,7 +134,7 @@ func TestAuthorizeV0(t *testing.T) {
ResourceRequest: len(tc.NS) > 0 || len(tc.Resource) > 0, ResourceRequest: len(tc.NS) > 0 || len(tc.Resource) > 0,
} }
decision, _, _ := a.Authorize(attr) decision, _, _ := a.Authorize(context.Background(), attr)
if tc.ExpectDecision != decision { if tc.ExpectDecision != decision {
t.Logf("tc: %v -> attr %v", tc, attr) t.Logf("tc: %v -> attr %v", tc, attr)
t.Errorf("%d: Expected allowed=%v but actually allowed=%v\n\t%v", t.Errorf("%d: Expected allowed=%v but actually allowed=%v\n\t%v",
@ -451,7 +452,7 @@ func TestAuthorizeV1beta1(t *testing.T) {
Path: tc.Path, Path: tc.Path,
} }
// t.Logf("tc %2v: %v -> attr %v", i, tc, attr) // t.Logf("tc %2v: %v -> attr %v", i, tc, attr)
decision, _, _ := a.Authorize(attr) decision, _, _ := a.Authorize(context.Background(), attr)
if tc.ExpectDecision != decision { if tc.ExpectDecision != decision {
t.Errorf("%d: Expected allowed=%v but actually allowed=%v, for case %+v & %+v", t.Errorf("%d: Expected allowed=%v but actually allowed=%v, for case %+v & %+v",
i, tc.ExpectDecision, decision, tc, attr) i, tc.ExpectDecision, decision, tc, attr)

View File

@ -260,7 +260,7 @@ func (s *Server) InstallAuthFilter() {
attrs := s.auth.GetRequestAttributes(info.User, req.Request) attrs := s.auth.GetRequestAttributes(info.User, req.Request)
// Authorize // Authorize
decision, _, err := s.auth.Authorize(attrs) decision, _, err := s.auth.Authorize(req.Request.Context(), attrs)
if err != nil { if err != nil {
msg := fmt.Sprintf("Authorization error (user=%s, verb=%s, resource=%s, subresource=%s)", attrs.GetUser().GetName(), attrs.GetVerb(), attrs.GetResource(), attrs.GetSubresource()) msg := fmt.Sprintf("Authorization error (user=%s, verb=%s, resource=%s, subresource=%s)", attrs.GetUser().GetName(), attrs.GetVerb(), attrs.GetResource(), attrs.GetSubresource())
klog.Errorf(msg, err) klog.Errorf(msg, err)

View File

@ -284,7 +284,7 @@ func (f *fakeAuth) AuthenticateRequest(req *http.Request) (*authenticator.Respon
func (f *fakeAuth) GetRequestAttributes(u user.Info, req *http.Request) authorizer.Attributes { func (f *fakeAuth) GetRequestAttributes(u user.Info, req *http.Request) authorizer.Attributes {
return f.attributesFunc(u, req) return f.attributesFunc(u, req)
} }
func (f *fakeAuth) Authorize(a authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) { func (f *fakeAuth) Authorize(ctx context.Context, a authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) {
return f.authorizeFunc(a) return f.authorizeFunc(a)
} }

View File

@ -70,7 +70,7 @@ func (r *REST) Create(ctx context.Context, obj runtime.Object, createValidation
} }
authorizationAttributes := authorizationutil.AuthorizationAttributesFrom(localSubjectAccessReview.Spec) authorizationAttributes := authorizationutil.AuthorizationAttributesFrom(localSubjectAccessReview.Spec)
decision, reason, evaluationErr := r.authorizer.Authorize(authorizationAttributes) decision, reason, evaluationErr := r.authorizer.Authorize(ctx, authorizationAttributes)
localSubjectAccessReview.Status = authorizationapi.SubjectAccessReviewStatus{ localSubjectAccessReview.Status = authorizationapi.SubjectAccessReviewStatus{
Allowed: (decision == authorizer.DecisionAllow), Allowed: (decision == authorizer.DecisionAllow),

View File

@ -73,7 +73,7 @@ func (r *REST) Create(ctx context.Context, obj runtime.Object, createValidation
authorizationAttributes = authorizationutil.NonResourceAttributesFrom(userToCheck, *selfSAR.Spec.NonResourceAttributes) authorizationAttributes = authorizationutil.NonResourceAttributesFrom(userToCheck, *selfSAR.Spec.NonResourceAttributes)
} }
decision, reason, evaluationErr := r.authorizer.Authorize(authorizationAttributes) decision, reason, evaluationErr := r.authorizer.Authorize(ctx, authorizationAttributes)
selfSAR.Status = authorizationapi.SubjectAccessReviewStatus{ selfSAR.Status = authorizationapi.SubjectAccessReviewStatus{
Allowed: (decision == authorizer.DecisionAllow), Allowed: (decision == authorizer.DecisionAllow),

View File

@ -62,7 +62,7 @@ func (r *REST) Create(ctx context.Context, obj runtime.Object, createValidation
} }
authorizationAttributes := authorizationutil.AuthorizationAttributesFrom(subjectAccessReview.Spec) authorizationAttributes := authorizationutil.AuthorizationAttributesFrom(subjectAccessReview.Spec)
decision, reason, evaluationErr := r.authorizer.Authorize(authorizationAttributes) decision, reason, evaluationErr := r.authorizer.Authorize(ctx, authorizationAttributes)
subjectAccessReview.Status = authorizationapi.SubjectAccessReviewStatus{ subjectAccessReview.Status = authorizationapi.SubjectAccessReviewStatus{
Allowed: (decision == authorizer.DecisionAllow), Allowed: (decision == authorizer.DecisionAllow),

View File

@ -17,6 +17,7 @@ limitations under the License.
package subjectaccessreview package subjectaccessreview
import ( import (
"context"
"errors" "errors"
"strings" "strings"
"testing" "testing"
@ -39,7 +40,7 @@ type fakeAuthorizer struct {
err error err error
} }
func (f *fakeAuthorizer) Authorize(attrs authorizer.Attributes) (authorizer.Decision, string, error) { func (f *fakeAuthorizer) Authorize(ctx context.Context, attrs authorizer.Attributes) (authorizer.Decision, string, error) {
f.attrs = attrs f.attrs = attrs
return f.decision, f.reason, f.err return f.decision, f.reason, f.err
} }

View File

@ -87,7 +87,7 @@ func RoleEscalationAuthorized(ctx context.Context, a authorizer.Authorizer) bool
ResourceRequest: true, ResourceRequest: true,
} }
decision, _, err := a.Authorize(attrs) decision, _, err := a.Authorize(ctx, attrs)
if err != nil { if err != nil {
utilruntime.HandleError(fmt.Errorf( utilruntime.HandleError(fmt.Errorf(
"error authorizing user %#v to escalate %#v named %q in namespace %q: %v", "error authorizing user %#v to escalate %#v named %q in namespace %q: %v",
@ -135,7 +135,7 @@ func BindingAuthorized(ctx context.Context, roleRef rbac.RoleRef, bindingNamespa
return false return false
} }
decision, _, err := a.Authorize(attrs) decision, _, err := a.Authorize(ctx, attrs)
if err != nil { if err != nil {
utilruntime.HandleError(fmt.Errorf( utilruntime.HandleError(fmt.Errorf(
"error authorizing user %#v to bind %#v in namespace %s: %v", "error authorizing user %#v to bind %#v in namespace %s: %v",

View File

@ -112,7 +112,7 @@ func (a *gcPermissionsEnforcement) Validate(ctx context.Context, attributes admi
ResourceRequest: true, ResourceRequest: true,
Path: "", Path: "",
} }
decision, reason, err := a.authorizer.Authorize(deleteAttributes) decision, reason, err := a.authorizer.Authorize(ctx, deleteAttributes)
if decision != authorizer.DecisionAllow { if decision != authorizer.DecisionAllow {
return admission.NewForbidden(attributes, fmt.Errorf("cannot set an ownerRef on a resource you can't delete: %v, %v", reason, err)) return admission.NewForbidden(attributes, fmt.Errorf("cannot set an ownerRef on a resource you can't delete: %v, %v", reason, err))
} }
@ -131,7 +131,7 @@ func (a *gcPermissionsEnforcement) Validate(ctx context.Context, attributes admi
// resources. User needs to have delete permission on all the // resources. User needs to have delete permission on all the
// matched Resources. // matched Resources.
for _, record := range records { for _, record := range records {
decision, reason, err := a.authorizer.Authorize(record) decision, reason, err := a.authorizer.Authorize(ctx, record)
if decision != authorizer.DecisionAllow { if decision != authorizer.DecisionAllow {
return admission.NewForbidden(attributes, fmt.Errorf("cannot set blockOwnerDeletion if an ownerReference refers to a resource you can't set finalizers on: %v, %v", reason, err)) return admission.NewForbidden(attributes, fmt.Errorf("cannot set blockOwnerDeletion if an ownerReference refers to a resource you can't set finalizers on: %v, %v", reason, err))
} }

View File

@ -40,7 +40,7 @@ import (
type fakeAuthorizer struct{} type fakeAuthorizer struct{}
func (fakeAuthorizer) Authorize(a authorizer.Attributes) (authorizer.Decision, string, error) { func (fakeAuthorizer) Authorize(ctx context.Context, a authorizer.Attributes) (authorizer.Decision, string, error) {
username := a.GetUser().GetName() username := a.GetUser().GetName()
if username == "non-deleter" { if username == "non-deleter" {

View File

@ -126,7 +126,7 @@ func (p *Plugin) Admit(ctx context.Context, a admission.Attributes, o admission.
pod := a.GetObject().(*api.Pod) pod := a.GetObject().(*api.Pod)
// compute the context. Mutation is allowed. ValidatedPSPAnnotation is not taken into account. // 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 { if err != nil {
return admission.NewForbidden(a, err) 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) pod := a.GetObject().(*api.Pod)
// compute the context. Mutation is not allowed. ValidatedPSPAnnotation is used as a hint to gain same speed-up. // 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 { if err != nil {
return admission.NewForbidden(a, err) 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 // 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 // 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. // 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 // 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) klog.V(4).Infof("getting pod security policies for pod %s (generate: %s)", pod.Name, pod.GenerateName)
var saInfo user.Info var saInfo user.Info
@ -271,7 +271,7 @@ func (p *Plugin) computeSecurityContext(a admission.Attributes, pod *api.Pod, sp
continue 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 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. // Pod is rejected. Filter the validation errors to only include errors from authorized PSPs.
aggregate := field.ErrorList{} aggregate := field.ErrorList{}
for psp, errs := range validationErrs { 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...) aggregate = append(aggregate, errs...)
} }
} }
@ -338,27 +338,27 @@ func (p *Plugin) createProvidersFromPolicies(psps []*policyv1beta1.PodSecurityPo
return providers, errs 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. // Check the service account first, as that is the more common use case.
return authorizedForPolicy(sa, namespace, policyName, authz) || return authorizedForPolicy(ctx, sa, namespace, policyName, authz) ||
authorizedForPolicy(user, 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. // 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 // 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 // Check against extensions API group for backward compatibility
return authorizedForPolicyInAPIGroup(info, namespace, policyName, policy.GroupName, authz) || return authorizedForPolicyInAPIGroup(ctx, info, namespace, policyName, policy.GroupName, authz) ||
authorizedForPolicyInAPIGroup(info, namespace, policyName, extensions.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. // 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 { if info == nil {
return false return false
} }
attr := buildAttributes(info, namespace, policyName, apiGroupName) attr := buildAttributes(info, namespace, policyName, apiGroupName)
decision, reason, err := authz.Authorize(attr) decision, reason, err := authz.Authorize(ctx, attr)
if err != nil { if err != nil {
klog.V(5).Infof("cannot authorize for policy: %v,%v", reason, err) klog.V(5).Infof("cannot authorize for policy: %v,%v", reason, err)
} }

View File

@ -84,7 +84,7 @@ type TestAuthorizer struct {
allowedAPIGroupName string 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 { if t.usernameToNamespaceToAllowedPSPs == nil {
return authorizer.DecisionAllow, "", nil return authorizer.DecisionAllow, "", nil
} }
@ -2249,7 +2249,7 @@ func TestPolicyAuthorizationErrors(t *testing.T) {
plugin := NewTestAdmission(tc.inPolicies, authz) 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}) 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.Nil(t, allowedPod)
assert.NoError(t, err) assert.NoError(t, err)
assert.Len(t, validationErrs, tc.expectValidationErrs) assert.Len(t, validationErrs, tc.expectValidationErrs)
@ -2342,7 +2342,7 @@ func TestPreferValidatedPSP(t *testing.T) {
plugin := NewTestAdmission(tc.inPolicies, authz) 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"}) 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.NoError(t, err)
assert.Len(t, validationErrs, tc.expectValidationErrs) assert.Len(t, validationErrs, tc.expectValidationErrs)
assert.Equal(t, tc.expectedPSP, pspName) assert.Equal(t, tc.expectedPSP, pspName)

View File

@ -17,6 +17,7 @@ limitations under the License.
package node package node
import ( import (
"context"
"fmt" "fmt"
"k8s.io/klog" "k8s.io/klog"
@ -78,7 +79,7 @@ var (
csiNodeResource = storageapi.Resource("csinodes") csiNodeResource = storageapi.Resource("csinodes")
) )
func (r *NodeAuthorizer) Authorize(attrs authorizer.Attributes) (authorizer.Decision, string, error) { func (r *NodeAuthorizer) Authorize(ctx context.Context, attrs authorizer.Attributes) (authorizer.Decision, string, error) {
nodeName, isNode := r.identifier.NodeIdentity(attrs.GetUser()) nodeName, isNode := r.identifier.NodeIdentity(attrs.GetUser())
if !isNode { if !isNode {
// reject requests from non-nodes // reject requests from non-nodes

View File

@ -17,6 +17,7 @@ limitations under the License.
package node package node
import ( import (
"context"
"fmt" "fmt"
"runtime" "runtime"
"runtime/pprof" "runtime/pprof"
@ -414,7 +415,7 @@ func TestAuthorizer(t *testing.T) {
} else { } else {
authz.features = tc.features authz.features = tc.features
} }
decision, _, _ := authz.Authorize(tc.attrs) decision, _, _ := authz.Authorize(context.Background(), tc.attrs)
if decision != tc.expect { if decision != tc.expect {
t.Errorf("expected %v, got %v", tc.expect, decision) t.Errorf("expected %v, got %v", tc.expect, decision)
} }
@ -504,13 +505,13 @@ func TestAuthorizerSharedResources(t *testing.T) {
) )
if len(tc.Secret) > 0 { if len(tc.Secret) > 0 {
decision, _, err = authz.Authorize(authorizer.AttributesRecord{User: tc.User, ResourceRequest: true, Verb: "get", Resource: "secrets", Namespace: "ns1", Name: tc.Secret}) decision, _, err = authz.Authorize(context.Background(), authorizer.AttributesRecord{User: tc.User, ResourceRequest: true, Verb: "get", Resource: "secrets", Namespace: "ns1", Name: tc.Secret})
if err != nil { if err != nil {
t.Errorf("%d: unexpected error: %v", i, err) t.Errorf("%d: unexpected error: %v", i, err)
continue continue
} }
} else if len(tc.ConfigMap) > 0 { } else if len(tc.ConfigMap) > 0 {
decision, _, err = authz.Authorize(authorizer.AttributesRecord{User: tc.User, ResourceRequest: true, Verb: "get", Resource: "configmaps", Namespace: "ns1", Name: tc.ConfigMap}) decision, _, err = authz.Authorize(context.Background(), authorizer.AttributesRecord{User: tc.User, ResourceRequest: true, Verb: "get", Resource: "configmaps", Namespace: "ns1", Name: tc.ConfigMap})
if err != nil { if err != nil {
t.Errorf("%d: unexpected error: %v", i, err) t.Errorf("%d: unexpected error: %v", i, err)
continue continue
@ -527,7 +528,7 @@ func TestAuthorizerSharedResources(t *testing.T) {
{ {
node3SharedSecretGet := authorizer.AttributesRecord{User: node3, ResourceRequest: true, Verb: "get", Resource: "secrets", Namespace: "ns1", Name: "shared-all"} node3SharedSecretGet := authorizer.AttributesRecord{User: node3, ResourceRequest: true, Verb: "get", Resource: "secrets", Namespace: "ns1", Name: "shared-all"}
decision, _, err := authz.Authorize(node3SharedSecretGet) decision, _, err := authz.Authorize(context.Background(), node3SharedSecretGet)
if err != nil { if err != nil {
t.Errorf("unexpected error: %v", err) t.Errorf("unexpected error: %v", err)
} }
@ -539,7 +540,7 @@ func TestAuthorizerSharedResources(t *testing.T) {
pod3.Spec.Volumes = nil pod3.Spec.Volumes = nil
g.AddPod(pod3) g.AddPod(pod3)
decision, _, err = authz.Authorize(node3SharedSecretGet) decision, _, err = authz.Authorize(context.Background(), node3SharedSecretGet)
if err != nil { if err != nil {
t.Errorf("unexpected error: %v", err) t.Errorf("unexpected error: %v", err)
} }
@ -833,7 +834,7 @@ func BenchmarkAuthorization(b *testing.B) {
b.SetParallelism(5000) b.SetParallelism(5000)
b.RunParallel(func(pb *testing.PB) { b.RunParallel(func(pb *testing.PB) {
for pb.Next() { for pb.Next() {
decision, _, _ := authz.Authorize(tc.attrs) decision, _, _ := authz.Authorize(context.Background(), tc.attrs)
if decision != tc.expect { if decision != tc.expect {
b.Errorf("expected %v, got %v", tc.expect, decision) b.Errorf("expected %v, got %v", tc.expect, decision)
} }

View File

@ -19,6 +19,7 @@ package rbac
import ( import (
"bytes" "bytes"
"context"
"fmt" "fmt"
"k8s.io/klog" "k8s.io/klog"
@ -71,7 +72,7 @@ func (v *authorizingVisitor) visit(source fmt.Stringer, rule *rbacv1.PolicyRule,
return true return true
} }
func (r *RBACAuthorizer) Authorize(requestAttributes authorizer.Attributes) (authorizer.Decision, string, error) { func (r *RBACAuthorizer) Authorize(ctx context.Context, requestAttributes authorizer.Attributes) (authorizer.Decision, string, error) {
ruleCheckingVisitor := &authorizingVisitor{requestAttributes: requestAttributes} ruleCheckingVisitor := &authorizingVisitor{requestAttributes: requestAttributes}
r.authorizationRuleResolver.VisitRulesFor(requestAttributes.GetUser(), requestAttributes.GetNamespace(), ruleCheckingVisitor.visit) r.authorizationRuleResolver.VisitRulesFor(requestAttributes.GetUser(), requestAttributes.GetNamespace(), ruleCheckingVisitor.visit)

View File

@ -17,6 +17,7 @@ limitations under the License.
package rbac package rbac
import ( import (
"context"
"fmt" "fmt"
"strings" "strings"
"testing" "testing"
@ -248,13 +249,13 @@ func TestAuthorizer(t *testing.T) {
ruleResolver, _ := rbacregistryvalidation.NewTestRuleResolver(tt.roles, tt.roleBindings, tt.clusterRoles, tt.clusterRoleBindings) ruleResolver, _ := rbacregistryvalidation.NewTestRuleResolver(tt.roles, tt.roleBindings, tt.clusterRoles, tt.clusterRoleBindings)
a := RBACAuthorizer{ruleResolver} a := RBACAuthorizer{ruleResolver}
for _, attr := range tt.shouldPass { for _, attr := range tt.shouldPass {
if decision, _, _ := a.Authorize(attr); decision != authorizer.DecisionAllow { if decision, _, _ := a.Authorize(context.Background(), attr); decision != authorizer.DecisionAllow {
t.Errorf("case %d: incorrectly restricted %s", i, attr) t.Errorf("case %d: incorrectly restricted %s", i, attr)
} }
} }
for _, attr := range tt.shouldFail { for _, attr := range tt.shouldFail {
if decision, _, _ := a.Authorize(attr); decision == authorizer.DecisionAllow { if decision, _, _ := a.Authorize(context.Background(), attr); decision == authorizer.DecisionAllow {
t.Errorf("case %d: incorrectly passed %s", i, attr) t.Errorf("case %d: incorrectly passed %s", i, attr)
} }
} }
@ -516,7 +517,7 @@ func BenchmarkAuthorize(b *testing.B) {
for _, request := range requests { for _, request := range requests {
b.Run(request.name, func(b *testing.B) { b.Run(request.name, func(b *testing.B) {
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
authz.Authorize(request.attrs) authz.Authorize(context.Background(), request.attrs)
} }
}) })
} }

View File

@ -115,7 +115,7 @@ var _ initializer.WantsAuthorizer = &WantAuthorizerAdmission{}
// TestAuthorizer is a test stub that fulfills the WantsAuthorizer interface. // TestAuthorizer is a test stub that fulfills the WantsAuthorizer interface.
type TestAuthorizer struct{} type TestAuthorizer struct{}
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) {
return authorizer.DecisionNoOpinion, "", nil return authorizer.DecisionNoOpinion, "", nil
} }

View File

@ -17,6 +17,7 @@ limitations under the License.
package authorizer package authorizer
import ( import (
"context"
"net/http" "net/http"
"k8s.io/apiserver/pkg/authentication/user" "k8s.io/apiserver/pkg/authentication/user"
@ -67,12 +68,12 @@ type Attributes interface {
// zero or more calls to methods of the Attributes interface. It returns nil when an action is // zero or more calls to methods of the Attributes interface. It returns nil when an action is
// authorized, otherwise it returns an error. // authorized, otherwise it returns an error.
type Authorizer interface { type Authorizer interface {
Authorize(a Attributes) (authorized Decision, reason string, err error) Authorize(ctx context.Context, a Attributes) (authorized Decision, reason string, err error)
} }
type AuthorizerFunc func(a Attributes) (Decision, string, error) type AuthorizerFunc func(a Attributes) (Decision, string, error)
func (f AuthorizerFunc) Authorize(a Attributes) (Decision, string, error) { func (f AuthorizerFunc) Authorize(ctx context.Context, a Attributes) (Decision, string, error) {
return f(a) return f(a)
} }

View File

@ -17,6 +17,7 @@ limitations under the License.
package authorizerfactory package authorizerfactory
import ( import (
"context"
"errors" "errors"
"k8s.io/apiserver/pkg/authentication/user" "k8s.io/apiserver/pkg/authentication/user"
@ -28,7 +29,7 @@ import (
// It is useful in tests and when using kubernetes in an open manner. // It is useful in tests and when using kubernetes in an open manner.
type alwaysAllowAuthorizer struct{} type alwaysAllowAuthorizer struct{}
func (alwaysAllowAuthorizer) Authorize(a authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) { func (alwaysAllowAuthorizer) Authorize(ctx context.Context, a authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) {
return authorizer.DecisionAllow, "", nil return authorizer.DecisionAllow, "", nil
} }
@ -56,7 +57,7 @@ func NewAlwaysAllowAuthorizer() *alwaysAllowAuthorizer {
// It is useful in unit tests to force an operation to be forbidden. // It is useful in unit tests to force an operation to be forbidden.
type alwaysDenyAuthorizer struct{} type alwaysDenyAuthorizer struct{}
func (alwaysDenyAuthorizer) Authorize(a authorizer.Attributes) (decision authorizer.Decision, reason string, err error) { func (alwaysDenyAuthorizer) Authorize(ctx context.Context, a authorizer.Attributes) (decision authorizer.Decision, reason string, err error) {
return authorizer.DecisionNoOpinion, "Everything is forbidden.", nil return authorizer.DecisionNoOpinion, "Everything is forbidden.", nil
} }
@ -72,7 +73,7 @@ type privilegedGroupAuthorizer struct {
groups []string groups []string
} }
func (r *privilegedGroupAuthorizer) Authorize(attr authorizer.Attributes) (authorizer.Decision, string, error) { func (r *privilegedGroupAuthorizer) Authorize(ctx context.Context, attr authorizer.Attributes) (authorizer.Decision, string, error) {
if attr.GetUser() == nil { if attr.GetUser() == nil {
return authorizer.DecisionNoOpinion, "Error", errors.New("no user on request.") return authorizer.DecisionNoOpinion, "Error", errors.New("no user on request.")
} }

View File

@ -17,6 +17,7 @@ limitations under the License.
package authorizerfactory package authorizerfactory
import ( import (
"context"
"testing" "testing"
"k8s.io/apiserver/pkg/authentication/user" "k8s.io/apiserver/pkg/authentication/user"
@ -25,14 +26,14 @@ import (
func TestNewAlwaysAllowAuthorizer(t *testing.T) { func TestNewAlwaysAllowAuthorizer(t *testing.T) {
aaa := NewAlwaysAllowAuthorizer() aaa := NewAlwaysAllowAuthorizer()
if decision, _, _ := aaa.Authorize(nil); decision != authorizer.DecisionAllow { if decision, _, _ := aaa.Authorize(context.Background(), nil); decision != authorizer.DecisionAllow {
t.Errorf("AlwaysAllowAuthorizer.Authorize did not authorize successfully.") t.Errorf("AlwaysAllowAuthorizer.Authorize did not authorize successfully.")
} }
} }
func TestNewAlwaysDenyAuthorizer(t *testing.T) { func TestNewAlwaysDenyAuthorizer(t *testing.T) {
ada := NewAlwaysDenyAuthorizer() ada := NewAlwaysDenyAuthorizer()
if decision, _, _ := ada.Authorize(nil); decision == authorizer.DecisionAllow { if decision, _, _ := ada.Authorize(context.Background(), nil); decision == authorizer.DecisionAllow {
t.Errorf("AlwaysDenyAuthorizer.Authorize returned nil instead of error.") t.Errorf("AlwaysDenyAuthorizer.Authorize returned nil instead of error.")
} }
} }
@ -43,10 +44,10 @@ func TestPrivilegedGroupAuthorizer(t *testing.T) {
yes := authorizer.AttributesRecord{User: &user.DefaultInfo{Groups: []string{"no", "allow-01"}}} yes := authorizer.AttributesRecord{User: &user.DefaultInfo{Groups: []string{"no", "allow-01"}}}
no := authorizer.AttributesRecord{User: &user.DefaultInfo{Groups: []string{"no", "deny-01"}}} no := authorizer.AttributesRecord{User: &user.DefaultInfo{Groups: []string{"no", "deny-01"}}}
if authorized, _, _ := auth.Authorize(yes); authorized != authorizer.DecisionAllow { if authorized, _, _ := auth.Authorize(context.Background(), yes); authorized != authorizer.DecisionAllow {
t.Errorf("failed") t.Errorf("failed")
} }
if authorized, _, _ := auth.Authorize(no); authorized == authorizer.DecisionAllow { if authorized, _, _ := auth.Authorize(context.Background(), no); authorized == authorizer.DecisionAllow {
t.Errorf("failed") t.Errorf("failed")
} }
} }

View File

@ -17,6 +17,7 @@ limitations under the License.
package path package path
import ( import (
"context"
"testing" "testing"
"k8s.io/apiserver/pkg/authorization/authorizer" "k8s.io/apiserver/pkg/authorization/authorizer"
@ -65,7 +66,7 @@ func TestNewAuthorizer(t *testing.T) {
info := authorizer.AttributesRecord{ info := authorizer.AttributesRecord{
Path: pth, Path: pth,
} }
if got, _, err := a.Authorize(info); err != nil { if got, _, err := a.Authorize(context.Background(), info); err != nil {
t.Errorf("NewAuthorizer(%v).Authorize(%q) return unexpected error: %v", tt.excludedPaths, pth, err) t.Errorf("NewAuthorizer(%v).Authorize(%q) return unexpected error: %v", tt.excludedPaths, pth, err)
} else if got != cases.want { } else if got != cases.want {
t.Errorf("NewAuthorizer(%v).Authorize(%q) = %v, want %v", tt.excludedPaths, pth, got, cases.want) t.Errorf("NewAuthorizer(%v).Authorize(%q) = %v, want %v", tt.excludedPaths, pth, got, cases.want)

View File

@ -25,6 +25,7 @@ limitations under the License.
package union package union
import ( import (
"context"
"strings" "strings"
utilerrors "k8s.io/apimachinery/pkg/util/errors" utilerrors "k8s.io/apimachinery/pkg/util/errors"
@ -41,14 +42,14 @@ func New(authorizationHandlers ...authorizer.Authorizer) authorizer.Authorizer {
} }
// Authorizes against a chain of authorizer.Authorizer objects and returns nil if successful and returns error if unsuccessful // Authorizes against a chain of authorizer.Authorizer objects and returns nil if successful and returns error if unsuccessful
func (authzHandler unionAuthzHandler) Authorize(a authorizer.Attributes) (authorizer.Decision, string, error) { func (authzHandler unionAuthzHandler) Authorize(ctx context.Context, a authorizer.Attributes) (authorizer.Decision, string, error) {
var ( var (
errlist []error errlist []error
reasonlist []string reasonlist []string
) )
for _, currAuthzHandler := range authzHandler { for _, currAuthzHandler := range authzHandler {
decision, reason, err := currAuthzHandler.Authorize(a) decision, reason, err := currAuthzHandler.Authorize(ctx, a)
if err != nil { if err != nil {
errlist = append(errlist, err) errlist = append(errlist, err)

View File

@ -17,6 +17,7 @@ limitations under the License.
package union package union
import ( import (
"context"
"errors" "errors"
"fmt" "fmt"
"reflect" "reflect"
@ -31,7 +32,7 @@ type mockAuthzHandler struct {
err error err error
} }
func (mock *mockAuthzHandler) Authorize(a authorizer.Attributes) (authorizer.Decision, string, error) { func (mock *mockAuthzHandler) Authorize(ctx context.Context, a authorizer.Attributes) (authorizer.Decision, string, error) {
return mock.decision, "", mock.err return mock.decision, "", mock.err
} }
@ -40,7 +41,7 @@ func TestAuthorizationSecondPasses(t *testing.T) {
handler2 := &mockAuthzHandler{decision: authorizer.DecisionAllow} handler2 := &mockAuthzHandler{decision: authorizer.DecisionAllow}
authzHandler := New(handler1, handler2) authzHandler := New(handler1, handler2)
authorized, _, _ := authzHandler.Authorize(nil) authorized, _, _ := authzHandler.Authorize(context.Background(), nil)
if authorized != authorizer.DecisionAllow { if authorized != authorizer.DecisionAllow {
t.Errorf("Unexpected authorization failure") t.Errorf("Unexpected authorization failure")
} }
@ -51,7 +52,7 @@ func TestAuthorizationFirstPasses(t *testing.T) {
handler2 := &mockAuthzHandler{decision: authorizer.DecisionNoOpinion} handler2 := &mockAuthzHandler{decision: authorizer.DecisionNoOpinion}
authzHandler := New(handler1, handler2) authzHandler := New(handler1, handler2)
authorized, _, _ := authzHandler.Authorize(nil) authorized, _, _ := authzHandler.Authorize(context.Background(), nil)
if authorized != authorizer.DecisionAllow { if authorized != authorizer.DecisionAllow {
t.Errorf("Unexpected authorization failure") t.Errorf("Unexpected authorization failure")
} }
@ -62,7 +63,7 @@ func TestAuthorizationNonePasses(t *testing.T) {
handler2 := &mockAuthzHandler{decision: authorizer.DecisionNoOpinion} handler2 := &mockAuthzHandler{decision: authorizer.DecisionNoOpinion}
authzHandler := New(handler1, handler2) authzHandler := New(handler1, handler2)
authorized, _, _ := authzHandler.Authorize(nil) authorized, _, _ := authzHandler.Authorize(context.Background(), nil)
if authorized == authorizer.DecisionAllow { if authorized == authorizer.DecisionAllow {
t.Errorf("Expected failed authorization") t.Errorf("Expected failed authorization")
} }
@ -73,7 +74,7 @@ func TestAuthorizationError(t *testing.T) {
handler2 := &mockAuthzHandler{err: fmt.Errorf("foo")} handler2 := &mockAuthzHandler{err: fmt.Errorf("foo")}
authzHandler := New(handler1, handler2) authzHandler := New(handler1, handler2)
_, _, err := authzHandler.Authorize(nil) _, _, err := authzHandler.Authorize(context.Background(), nil)
if err == nil { if err == nil {
t.Errorf("Expected error: %v", err) t.Errorf("Expected error: %v", err)
} }
@ -257,7 +258,7 @@ func TestAuthorizationUnequivocalDeny(t *testing.T) {
t.Run(fmt.Sprintf("case %v", i), func(t *testing.T) { t.Run(fmt.Sprintf("case %v", i), func(t *testing.T) {
authzHandler := New(c.authorizers...) authzHandler := New(c.authorizers...)
decision, _, _ := authzHandler.Authorize(nil) decision, _, _ := authzHandler.Authorize(context.Background(), nil)
if decision != c.decision { if decision != c.decision {
t.Errorf("Unexpected authorization failure: %v, expected: %v", decision, c.decision) t.Errorf("Unexpected authorization failure: %v, expected: %v", decision, c.decision)
} }

View File

@ -56,7 +56,7 @@ func WithAuthorization(handler http.Handler, a authorizer.Authorizer, s runtime.
responsewriters.InternalError(w, req, err) responsewriters.InternalError(w, req, err)
return return
} }
authorized, reason, err := a.Authorize(attributes) authorized, reason, err := a.Authorize(ctx, attributes)
// an authorizer like RBAC could encounter evaluation errors and still allow the request, so authorizer decision is checked before error here. // an authorizer like RBAC could encounter evaluation errors and still allow the request, so authorizer decision is checked before error here.
if authorized == authorizer.DecisionAllow { if authorized == authorizer.DecisionAllow {
audit.LogAnnotation(ae, decisionAnnotationKey, decisionAllow) audit.LogAnnotation(ae, decisionAnnotationKey, decisionAllow)

View File

@ -17,6 +17,7 @@ limitations under the License.
package filters package filters
import ( import (
"context"
"errors" "errors"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
@ -129,7 +130,7 @@ type fakeAuthorizer struct {
err error err error
} }
func (f fakeAuthorizer) Authorize(a authorizer.Attributes) (authorizer.Decision, string, error) { func (f fakeAuthorizer) Authorize(ctx context.Context, a authorizer.Attributes) (authorizer.Decision, string, error) {
return f.decision, f.reason, f.err return f.decision, f.reason, f.err
} }

View File

@ -109,7 +109,7 @@ func WithImpersonation(handler http.Handler, a authorizer.Authorizer, s runtime.
return return
} }
decision, reason, err := a.Authorize(actingAsAttributes) decision, reason, err := a.Authorize(ctx, actingAsAttributes)
if err != nil || decision != authorizer.DecisionAllow { if err != nil || decision != authorizer.DecisionAllow {
klog.V(4).Infof("Forbidden: %#v, Reason: %s, Error: %v", req.RequestURI, reason, err) klog.V(4).Infof("Forbidden: %#v, Reason: %s, Error: %v", req.RequestURI, reason, err)
responsewriters.Forbidden(ctx, actingAsAttributes, w, req, reason, s) responsewriters.Forbidden(ctx, actingAsAttributes, w, req, reason, s)

View File

@ -36,7 +36,7 @@ import (
type impersonateAuthorizer struct{} type impersonateAuthorizer struct{}
func (impersonateAuthorizer) Authorize(a authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) { func (impersonateAuthorizer) Authorize(ctx context.Context, a authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) {
user := a.GetUser() user := a.GetUser()
switch { switch {

View File

@ -210,7 +210,7 @@ func withAuthorization(validate rest.ValidateObjectFunc, a authorizer.Authorizer
return errors.NewInternalError(fmt.Errorf("no authorizer provided, unable to authorize a create on update")) return errors.NewInternalError(fmt.Errorf("no authorizer provided, unable to authorize a create on update"))
} }
once.Do(func() { once.Do(func() {
authorizerDecision, authorizerReason, authorizerErr = a.Authorize(attributes) authorizerDecision, authorizerReason, authorizerErr = a.Authorize(ctx, attributes)
}) })
// an authorizer like RBAC could encounter evaluation errors and still allow the request, so authorizer decision is checked before error here. // an authorizer like RBAC could encounter evaluation errors and still allow the request, so authorizer decision is checked before error here.
if authorizerDecision == authorizer.DecisionAllow { if authorizerDecision == authorizer.DecisionAllow {

View File

@ -477,7 +477,7 @@ type mockAuthorizer struct {
lastURI string lastURI string
} }
func (authz *mockAuthorizer) Authorize(a authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) { func (authz *mockAuthorizer) Authorize(ctx context.Context, a authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) {
authz.lastURI = a.GetPath() authz.lastURI = a.GetPath()
return authorizer.DecisionAllow, "", nil return authorizer.DecisionAllow, "", nil
} }

View File

@ -18,6 +18,7 @@ limitations under the License.
package webhook package webhook
import ( import (
"context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"time" "time"
@ -149,7 +150,7 @@ func newWithBackoff(subjectAccessReview authorizationclient.SubjectAccessReviewI
// TODO(mikedanese): We should eventually support failing closed when we // TODO(mikedanese): We should eventually support failing closed when we
// encounter an error. We are failing open now to preserve backwards compatible // encounter an error. We are failing open now to preserve backwards compatible
// behavior. // behavior.
func (w *WebhookAuthorizer) Authorize(attr authorizer.Attributes) (decision authorizer.Decision, reason string, err error) { func (w *WebhookAuthorizer) Authorize(ctx context.Context, attr authorizer.Attributes) (decision authorizer.Decision, reason string, err error) {
r := &authorization.SubjectAccessReview{} r := &authorization.SubjectAccessReview{}
if user := attr.GetUser(); user != nil { if user := attr.GetUser(); user != nil {
r.Spec = authorization.SubjectAccessReviewSpec{ r.Spec = authorization.SubjectAccessReviewSpec{

View File

@ -17,6 +17,7 @@ limitations under the License.
package webhook package webhook
import ( import (
"context"
"crypto/tls" "crypto/tls"
"crypto/x509" "crypto/x509"
"encoding/json" "encoding/json"
@ -397,7 +398,7 @@ func TestTLSConfig(t *testing.T) {
// Allow all and see if we get an error. // Allow all and see if we get an error.
service.Allow() service.Allow()
decision, _, err := wh.Authorize(attr) decision, _, err := wh.Authorize(context.Background(), attr)
if tt.wantAuth { if tt.wantAuth {
if decision != authorizer.DecisionAllow { if decision != authorizer.DecisionAllow {
t.Errorf("expected successful authorization") t.Errorf("expected successful authorization")
@ -419,7 +420,7 @@ func TestTLSConfig(t *testing.T) {
} }
service.Deny() service.Deny()
if decision, _, _ := wh.Authorize(attr); decision == authorizer.DecisionAllow { if decision, _, _ := wh.Authorize(context.Background(), attr); decision == authorizer.DecisionAllow {
t.Errorf("%s: incorrectly authorized with DenyAll policy", tt.test) t.Errorf("%s: incorrectly authorized with DenyAll policy", tt.test)
} }
}() }()
@ -523,7 +524,7 @@ func TestWebhook(t *testing.T) {
} }
for i, tt := range tests { for i, tt := range tests {
decision, _, err := wh.Authorize(tt.attr) decision, _, err := wh.Authorize(context.Background(), tt.attr)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -627,7 +628,7 @@ func TestWebhookCache(t *testing.T) {
serv.called = 0 serv.called = 0
serv.allow = test.allow serv.allow = test.allow
serv.statusCode = test.statusCode serv.statusCode = test.statusCode
authorized, _, err := wh.Authorize(test.attr) authorized, _, err := wh.Authorize(context.Background(), test.attr)
if test.expectedErr && err == nil { if test.expectedErr && err == nil {
t.Fatalf("%d: Expected error", i) t.Fatalf("%d: Expected error", i)
} else if !test.expectedErr && err != nil { } else if !test.expectedErr && err != nil {

View File

@ -17,6 +17,7 @@ limitations under the License.
package auth package auth
import ( import (
"context"
"errors" "errors"
"net/http" "net/http"
"strings" "strings"
@ -38,7 +39,7 @@ import (
// TODO(etune): remove this test once a more comprehensive built-in authorizer is implemented. // TODO(etune): remove this test once a more comprehensive built-in authorizer is implemented.
type sarAuthorizer struct{} type sarAuthorizer struct{}
func (sarAuthorizer) Authorize(a authorizer.Attributes) (authorizer.Decision, string, error) { func (sarAuthorizer) Authorize(ctx context.Context, a authorizer.Attributes) (authorizer.Decision, string, error) {
if a.GetUser().GetName() == "dave" { if a.GetUser().GetName() == "dave" {
return authorizer.DecisionNoOpinion, "no", errors.New("I'm sorry, Dave") return authorizer.DecisionNoOpinion, "no", errors.New("I'm sorry, Dave")
} }

View File

@ -22,6 +22,7 @@ package auth
import ( import (
"bytes" "bytes"
"context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
@ -539,7 +540,7 @@ func TestAuthModeAlwaysDeny(t *testing.T) {
// TODO(etune): remove this test once a more comprehensive built-in authorizer is implemented. // TODO(etune): remove this test once a more comprehensive built-in authorizer is implemented.
type allowAliceAuthorizer struct{} type allowAliceAuthorizer struct{}
func (allowAliceAuthorizer) Authorize(a authorizer.Attributes) (authorizer.Decision, string, error) { func (allowAliceAuthorizer) Authorize(ctx context.Context, a authorizer.Attributes) (authorizer.Decision, string, error) {
if a.GetUser() != nil && a.GetUser().GetName() == "alice" { if a.GetUser() != nil && a.GetUser().GetName() == "alice" {
return authorizer.DecisionAllow, "", nil return authorizer.DecisionAllow, "", nil
} }
@ -705,7 +706,7 @@ func TestUnknownUserIsUnauthorized(t *testing.T) {
type impersonateAuthorizer struct{} type impersonateAuthorizer struct{}
// alice can't act as anyone and bob can't do anything but act-as someone // alice can't act as anyone and bob can't do anything but act-as someone
func (impersonateAuthorizer) Authorize(a authorizer.Attributes) (authorizer.Decision, string, error) { func (impersonateAuthorizer) Authorize(ctx context.Context, a authorizer.Attributes) (authorizer.Decision, string, error) {
// alice can impersonate service accounts and do other actions // alice can impersonate service accounts and do other actions
if a.GetUser() != nil && a.GetUser().GetName() == "alice" && a.GetVerb() == "impersonate" && a.GetResource() == "serviceaccounts" { if a.GetUser() != nil && a.GetUser().GetName() == "alice" && a.GetVerb() == "impersonate" && a.GetResource() == "serviceaccounts" {
return authorizer.DecisionAllow, "", nil return authorizer.DecisionAllow, "", nil
@ -864,7 +865,7 @@ type trackingAuthorizer struct {
requestAttributes []authorizer.Attributes requestAttributes []authorizer.Attributes
} }
func (a *trackingAuthorizer) Authorize(attributes authorizer.Attributes) (authorizer.Decision, string, error) { func (a *trackingAuthorizer) Authorize(ctx context.Context, attributes authorizer.Attributes) (authorizer.Decision, string, error) {
a.requestAttributes = append(a.requestAttributes, attributes) a.requestAttributes = append(a.requestAttributes, attributes)
return authorizer.DecisionAllow, "", nil return authorizer.DecisionAllow, "", nil
} }

View File

@ -17,6 +17,7 @@ limitations under the License.
package framework package framework
import ( import (
"context"
"flag" "flag"
"net" "net"
"net/http" "net/http"
@ -69,7 +70,7 @@ type Config struct {
// alwaysAllow always allows an action // alwaysAllow always allows an action
type alwaysAllow struct{} type alwaysAllow struct{}
func (alwaysAllow) Authorize(requestAttributes authorizer.Attributes) (authorizer.Decision, string, error) { func (alwaysAllow) Authorize(ctx context.Context, requestAttributes authorizer.Attributes) (authorizer.Decision, string, error) {
return authorizer.DecisionAllow, "always allow", nil return authorizer.DecisionAllow, "always allow", nil
} }

View File

@ -18,6 +18,7 @@ package master
import ( import (
"bytes" "bytes"
"context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
@ -59,7 +60,7 @@ const (
type allowAliceAuthorizer struct{} type allowAliceAuthorizer struct{}
func (allowAliceAuthorizer) Authorize(a authorizer.Attributes) (authorizer.Decision, string, error) { func (allowAliceAuthorizer) Authorize(ctx context.Context, a authorizer.Attributes) (authorizer.Decision, string, error) {
if a.GetUser() != nil && a.GetUser().GetName() == "alice" { if a.GetUser() != nil && a.GetUser().GetName() == "alice" {
return authorizer.DecisionAllow, "", nil return authorizer.DecisionAllow, "", nil
} }