// subjectMatches returns true if specified user and group properties in the policy match the attributes func subjectMatches(p api.Policy, a authorizer.Attributes) bool { matched := false // If the policy specified a user, ensure it matches if len(p.Spec.User) > 0 { if p.Spec.User == "*" { matched = true } else { matched = p.Spec.User == a.GetUserName() if !matched { return false } } } // If the policy specified a group, ensure it matches if len(p.Spec.Group) > 0 { if p.Spec.Group == "*" { matched = true } else { matched = false for _, group := range a.GetGroups() { if p.Spec.Group == group { matched = true } } if !matched { return false } } } return matched }
// OriginAuthorizerAttributes adapts Kubernetes authorization attributes to Origin authorization attributes // Note that some info (like resourceName, apiVersion, apiGroup) is not available from the Kubernetes attributes func OriginAuthorizerAttributes(kattrs kauthorizer.Attributes) (kapi.Context, oauthorizer.AuthorizationAttributes) { // Build a context to hold the namespace and user info ctx := kapi.NewContext() ctx = kapi.WithNamespace(ctx, kattrs.GetNamespace()) ctx = kapi.WithUser(ctx, &user.DefaultInfo{ Name: kattrs.GetUserName(), Groups: kattrs.GetGroups(), }) // If the passed attributes already satisfy our interface, use it directly if oattrs, ok := kattrs.(oauthorizer.AuthorizationAttributes); ok { return ctx, oattrs } // Otherwise build what we can oattrs := &oauthorizer.DefaultAuthorizationAttributes{ Verb: kattrs.GetVerb(), Resource: kattrs.GetResource(), // TODO: add to kube authorizer attributes // APIVersion string // APIGroup string // ResourceName string // RequestAttributes interface{} // NonResourceURL bool // URL string } return ctx, oattrs }
func (sarAuthorizer) Authorize(a authorizer.Attributes) (bool, string, error) { if a.GetUser().GetName() == "dave" { return false, "no", errors.New("I'm sorry, Dave") } return true, "you're not dave", nil }
func (r *RBACAuthorizer) Authorize(requestAttributes authorizer.Attributes) (bool, string, error) { rules, ruleResolutionError := r.authorizationRuleResolver.RulesFor(requestAttributes.GetUser(), requestAttributes.GetNamespace()) if RulesAllow(requestAttributes, rules...) { return true, "", nil } return false, "", ruleResolutionError }
func (r *privilegedGroupAuthorizer) Authorize(attr authorizer.Attributes) (bool, string, error) { for attr_group := range attr.GetUser().GetGroups() { for priv_group := range r.groups { if priv_group == attr_group { return true, "", nil } } } return false, "Not in privileged list.", nil }
func (r *RBACAuthorizer) Authorize(requestAttributes authorizer.Attributes) (bool, string, error) { rules, ruleResolutionError := r.authorizationRuleResolver.RulesFor(requestAttributes.GetUser(), requestAttributes.GetNamespace()) if RulesAllow(requestAttributes, rules...) { return true, "", nil } glog.V(2).Infof("RBAC DENY: user %q groups %v cannot %q on \"%v.%v/%v\"", requestAttributes.GetUser().GetName(), requestAttributes.GetUser().GetGroups(), requestAttributes.GetVerb(), requestAttributes.GetResource(), requestAttributes.GetAPIGroup(), requestAttributes.GetSubresource()) return false, "", ruleResolutionError }
func (r *privilegedGroupAuthorizer) Authorize(attr authorizer.Attributes) (bool, string, error) { if attr.GetUser() == nil { return false, "Error", errors.New("no user on request.") } for _, attr_group := range attr.GetUser().GetGroups() { for _, priv_group := range r.groups { if priv_group == attr_group { return true, "", nil } } } return false, "", nil }
func verbMatches(p api.Policy, a authorizer.Attributes) bool { // TODO: match on verb // All policies allow read only requests if a.IsReadOnly() { return true } // Allow if policy is not readonly if !p.Spec.Readonly { return true } return false }
// alice can't act as anyone and bob can't do anything but act-as someone func (impersonateAuthorizer) Authorize(a authorizer.Attributes) error { if a.GetUserName() == "alice" && a.GetVerb() != "impersonate" { return nil } if a.GetUserName() == "bob" && a.GetVerb() == "impersonate" { return nil } return errors.New("I can't allow that. Go ask alice.") }
func (p policy) matches(a authorizer.Attributes) bool { if p.subjectMatches(a) { if p.Readonly == false || (p.Readonly == a.IsReadOnly()) { switch { case p.NonResourcePath != "": if p.NonResourcePath == a.GetNonResourcePath() { return true } // When the path is a non-resource path it cannot match. case len(a.GetNonResourcePath()) == 0 && (p.Resource == "" || (p.Resource == a.GetResource())): if p.Namespace == "" || (p.Namespace == a.GetNamespace()) { return true } } } } return false }
func (p policy) subjectMatches(a authorizer.Attributes) bool { if p.User != "" { // Require user match if p.User != a.GetUserName() { return false } } if p.Group != "" { // Require group match for _, group := range a.GetGroups() { if p.Group == group { return true } } return false } return true }
func resourceMatches(p api.Policy, a authorizer.Attributes) bool { // A resource policy cannot match a non-resource request if a.IsResourceRequest() { if p.Spec.Namespace == "*" || p.Spec.Namespace == a.GetNamespace() { if p.Spec.Resource == "*" || p.Spec.Resource == a.GetResource() { if p.Spec.APIGroup == "*" || p.Spec.APIGroup == a.GetAPIGroup() { return true } } } } return false }
// subjectMatches returns true if specified user and group properties in the policy match the attributes func subjectMatches(p api.Policy, a authorizer.Attributes) bool { matched := false username := "" groups := []string{} if user := a.GetUser(); user != nil { username = user.GetName() groups = user.GetGroups() } // If the policy specified a user, ensure it matches if len(p.Spec.User) > 0 { if p.Spec.User == "*" { matched = true } else { matched = p.Spec.User == username if !matched { return false } } } // If the policy specified a group, ensure it matches if len(p.Spec.Group) > 0 { if p.Spec.Group == "*" { matched = true } else { matched = false for _, group := range groups { if p.Spec.Group == group { matched = true } } if !matched { return false } } } return matched }
func (p policy) matches(a authorizer.Attributes) bool { if p.subjectMatches(a) { if p.Readonly == false || (p.Readonly == a.IsReadOnly()) { if p.Resource == "" || (p.Resource == a.GetResource()) { if p.Namespace == "" || (p.Namespace == a.GetNamespace()) { return true } } } } return false }
func (fakeAuthorizer) Authorize(a authorizer.Attributes) (bool, string, error) { username := a.GetUser().GetName() if username == "non-deleter" { if a.GetVerb() == "delete" { return false, "", nil } return true, "", nil } if username == "non-pod-deleter" { if a.GetVerb() == "delete" && a.GetResource() == "pods" { return false, "", nil } return true, "", nil } return true, "", nil }
func nonResourceMatches(p api.Policy, a authorizer.Attributes) bool { // A non-resource policy cannot match a resource request if !a.IsResourceRequest() { // Allow wildcard match if p.Spec.NonResourcePath == "*" { return true } // Allow exact match if p.Spec.NonResourcePath == a.GetPath() { return true } // Allow a trailing * subpath match if strings.HasSuffix(p.Spec.NonResourcePath, "*") && strings.HasPrefix(a.GetPath(), strings.TrimRight(p.Spec.NonResourcePath, "*")) { return true } } return false }
// Authorize makes a REST request to the remote service describing the attempted action as a JSON // serialized api.authorization.v1beta1.SubjectAccessReview object. An example request body is // provided bellow. // // { // "apiVersion": "authorization.k8s.io/v1beta1", // "kind": "SubjectAccessReview", // "spec": { // "resourceAttributes": { // "namespace": "kittensandponies", // "verb": "GET", // "group": "group3", // "resource": "pods" // }, // "user": "******", // "group": [ // "group1", // "group2" // ] // } // } // // The remote service is expected to fill the SubjectAccessReviewStatus field to either allow or // disallow access. A permissive response would return: // // { // "apiVersion": "authorization.k8s.io/v1beta1", // "kind": "SubjectAccessReview", // "status": { // "allowed": true // } // } // // To disallow access, the remote service would return: // // { // "apiVersion": "authorization.k8s.io/v1beta1", // "kind": "SubjectAccessReview", // "status": { // "allowed": false, // "reason": "user does not have read access to the namespace" // } // } // func (w *WebhookAuthorizer) Authorize(attr authorizer.Attributes) (err error) { r := &v1beta1.SubjectAccessReview{ Spec: v1beta1.SubjectAccessReviewSpec{ User: attr.GetUserName(), Groups: attr.GetGroups(), }, } if attr.IsResourceRequest() { r.Spec.ResourceAttributes = &v1beta1.ResourceAttributes{ Namespace: attr.GetNamespace(), Verb: attr.GetVerb(), Group: attr.GetAPIGroup(), Version: attr.GetAPIVersion(), Resource: attr.GetResource(), Subresource: attr.GetSubresource(), Name: attr.GetName(), } } else { r.Spec.NonResourceAttributes = &v1beta1.NonResourceAttributes{ Path: attr.GetPath(), Verb: attr.GetVerb(), } } key, err := json.Marshal(r.Spec) if err != nil { return err } if entry, ok := w.responseCache.Get(string(key)); ok { r.Status = entry.(v1beta1.SubjectAccessReviewStatus) } else { result := w.WithExponentialBackoff(func() restclient.Result { return w.RestClient.Post().Body(r).Do() }) if err := result.Error(); err != nil { // An error here indicates bad configuration or an outage. Log for debugging. glog.Errorf("Failed to make webhook authorizer request: %v", err) return err } var statusCode int if result.StatusCode(&statusCode); statusCode < 200 || statusCode >= 300 { return fmt.Errorf("Error contacting webhook: %d", statusCode) } if err := result.Into(r); err != nil { return err } if r.Status.Allowed { w.responseCache.Add(string(key), r.Status, w.authorizedTTL) } else { w.responseCache.Add(string(key), r.Status, w.unauthorizedTTL) } } if r.Status.Allowed { return nil } if r.Status.Reason != "" { return errors.New(r.Status.Reason) } return errors.New("unauthorized") }
func RuleAllows(requestAttributes authorizer.Attributes, rule rbac.PolicyRule) bool { if requestAttributes.IsResourceRequest() { resource := requestAttributes.GetResource() if len(requestAttributes.GetSubresource()) > 0 { resource = requestAttributes.GetResource() + "/" + requestAttributes.GetSubresource() } return rbac.VerbMatches(rule, requestAttributes.GetVerb()) && rbac.APIGroupMatches(rule, requestAttributes.GetAPIGroup()) && rbac.ResourceMatches(rule, resource) && rbac.ResourceNameMatches(rule, requestAttributes.GetName()) } return rbac.VerbMatches(rule, requestAttributes.GetVerb()) && rbac.NonResourceURLMatches(rule, requestAttributes.GetPath()) }
func (allowAliceAuthorizer) Authorize(a authorizer.Attributes) error { if a.GetUserName() == "alice" { return nil } return errors.New("I can't allow that. Go ask alice.") }
// alice can't act as anyone and bob can't do anything but act-as someone func (impersonateAuthorizer) Authorize(a authorizer.Attributes) error { // alice can impersonate service accounts and do other actions if a.GetUserName() == "alice" && a.GetVerb() == "impersonate" && a.GetResource() == "serviceaccounts" { return nil } if a.GetUserName() == "alice" && a.GetVerb() != "impersonate" { return nil } // bob can impersonate anyone, but that it if a.GetUserName() == "bob" && a.GetVerb() == "impersonate" { return nil } // service accounts can do everything if strings.HasPrefix(a.GetUserName(), serviceaccount.ServiceAccountUsernamePrefix) { return nil } return errors.New("I can't allow that. Go ask alice.") }
// alice can't act as anyone and bob can't do anything but act-as someone func (impersonateAuthorizer) Authorize(a authorizer.Attributes) (bool, string, error) { // alice can impersonate service accounts and do other actions if a.GetUser() != nil && a.GetUser().GetName() == "alice" && a.GetVerb() == "impersonate" && a.GetResource() == "serviceaccounts" { return true, "", nil } if a.GetUser() != nil && a.GetUser().GetName() == "alice" && a.GetVerb() != "impersonate" { return true, "", nil } // bob can impersonate anyone, but that it if a.GetUser() != nil && a.GetUser().GetName() == "bob" && a.GetVerb() == "impersonate" { return true, "", nil } // service accounts can do everything if a.GetUser() != nil && strings.HasPrefix(a.GetUser().GetName(), serviceaccount.ServiceAccountUsernamePrefix) { return true, "", nil } return false, "I can't allow that. Go ask alice.", nil }
func (impersonateAuthorizer) Authorize(a authorizer.Attributes) (authorized bool, reason string, err error) { user := a.GetUser() switch { case user.GetName() == "system:admin": return true, "", nil case user.GetName() == "tester": return false, "", fmt.Errorf("works on my machine") case user.GetName() == "deny-me": return false, "denied", nil } if len(user.GetGroups()) > 0 && user.GetGroups()[0] == "wheel" && a.GetVerb() == "impersonate" && a.GetResource() == "users" { return true, "", nil } if len(user.GetGroups()) > 0 && user.GetGroups()[0] == "sa-impersonater" && a.GetVerb() == "impersonate" && a.GetResource() == "serviceaccounts" { return true, "", nil } if len(user.GetGroups()) > 0 && user.GetGroups()[0] == "regular-impersonater" && a.GetVerb() == "impersonate" && a.GetResource() == "users" { return true, "", nil } if len(user.GetGroups()) > 1 && user.GetGroups()[1] == "group-impersonater" && a.GetVerb() == "impersonate" && a.GetResource() == "groups" { return true, "", nil } if len(user.GetGroups()) > 1 && user.GetGroups()[1] == "extra-setter-scopes" && a.GetVerb() == "impersonate" && a.GetResource() == "userextras" && a.GetSubresource() == "scopes" { return true, "", nil } if len(user.GetGroups()) > 1 && user.GetGroups()[1] == "extra-setter-particular-scopes" && a.GetVerb() == "impersonate" && a.GetResource() == "userextras" && a.GetSubresource() == "scopes" && a.GetName() == "scope-a" { return true, "", nil } if len(user.GetGroups()) > 1 && user.GetGroups()[1] == "extra-setter-project" && a.GetVerb() == "impersonate" && a.GetResource() == "userextras" && a.GetSubresource() == "project" { return true, "", nil } return false, "deny by default", nil }
// Authorize makes a REST request to the remote service describing the attempted action as a JSON // serialized api.authorization.v1beta1.SubjectAccessReview object. An example request body is // provided bellow. // // { // "apiVersion": "authorization.k8s.io/v1beta1", // "kind": "SubjectAccessReview", // "spec": { // "resourceAttributes": { // "namespace": "kittensandponies", // "verb": "GET", // "group": "group3", // "resource": "pods" // }, // "user": "******", // "group": [ // "group1", // "group2" // ] // } // } // // The remote service is expected to fill the SubjectAccessReviewStatus field to either allow or // disallow access. A permissive response would return: // // { // "apiVersion": "authorization.k8s.io/v1beta1", // "kind": "SubjectAccessReview", // "status": { // "allowed": true // } // } // // To disallow access, the remote service would return: // // { // "apiVersion": "authorization.k8s.io/v1beta1", // "kind": "SubjectAccessReview", // "status": { // "allowed": false, // "reason": "user does not have read access to the namespace" // } // } // func (w *WebhookAuthorizer) Authorize(attr authorizer.Attributes) (err error) { r := &v1beta1.SubjectAccessReview{ Spec: v1beta1.SubjectAccessReviewSpec{ User: attr.GetUserName(), Groups: attr.GetGroups(), }, } if attr.IsResourceRequest() { r.Spec.ResourceAttributes = &v1beta1.ResourceAttributes{ Namespace: attr.GetNamespace(), Verb: attr.GetVerb(), Group: attr.GetAPIGroup(), Version: attr.GetAPIVersion(), Resource: attr.GetResource(), Subresource: attr.GetSubresource(), Name: attr.GetName(), } } else { r.Spec.NonResourceAttributes = &v1beta1.NonResourceAttributes{ Path: attr.GetPath(), Verb: attr.GetVerb(), } } result := w.RestClient.Post().Body(r).Do() if err := result.Error(); err != nil { return err } if err := result.Into(r); err != nil { return err } if r.Status.Allowed { return nil } if r.Status.Reason != "" { return errors.New(r.Status.Reason) } return errors.New("unauthorized") }
// Authorize makes a REST request to the remote service describing the attempted action as a JSON // serialized api.authorization.v1beta1.SubjectAccessReview object. An example request body is // provided bellow. // // { // "apiVersion": "authorization.k8s.io/v1beta1", // "kind": "SubjectAccessReview", // "spec": { // "resourceAttributes": { // "namespace": "kittensandponies", // "verb": "GET", // "group": "group3", // "resource": "pods" // }, // "user": "******", // "group": [ // "group1", // "group2" // ] // } // } // // The remote service is expected to fill the SubjectAccessReviewStatus field to either allow or // disallow access. A permissive response would return: // // { // "apiVersion": "authorization.k8s.io/v1beta1", // "kind": "SubjectAccessReview", // "status": { // "allowed": true // } // } // // To disallow access, the remote service would return: // // { // "apiVersion": "authorization.k8s.io/v1beta1", // "kind": "SubjectAccessReview", // "status": { // "allowed": false, // "reason": "user does not have read access to the namespace" // } // } // func (w *WebhookAuthorizer) Authorize(attr authorizer.Attributes) (authorized bool, reason string, err error) { r := &authorization.SubjectAccessReview{} if user := attr.GetUser(); user != nil { r.Spec = authorization.SubjectAccessReviewSpec{ User: user.GetName(), Groups: user.GetGroups(), Extra: convertToSARExtra(user.GetExtra()), } } if attr.IsResourceRequest() { r.Spec.ResourceAttributes = &authorization.ResourceAttributes{ Namespace: attr.GetNamespace(), Verb: attr.GetVerb(), Group: attr.GetAPIGroup(), Version: attr.GetAPIVersion(), Resource: attr.GetResource(), Subresource: attr.GetSubresource(), Name: attr.GetName(), } } else { r.Spec.NonResourceAttributes = &authorization.NonResourceAttributes{ Path: attr.GetPath(), Verb: attr.GetVerb(), } } key, err := json.Marshal(r.Spec) if err != nil { return false, "", err } if entry, ok := w.responseCache.Get(string(key)); ok { r.Status = entry.(authorization.SubjectAccessReviewStatus) } else { var ( result *authorization.SubjectAccessReview err error ) webhook.WithExponentialBackoff(w.initialBackoff, func() error { result, err = w.subjectAccessReview.Create(r) return err }) if err != nil { // An error here indicates bad configuration or an outage. Log for debugging. glog.Errorf("Failed to make webhook authorizer request: %v", err) return false, "", err } r.Status = result.Status if r.Status.Allowed { w.responseCache.Add(string(key), r.Status, w.authorizedTTL) } else { w.responseCache.Add(string(key), r.Status, w.unauthorizedTTL) } } return r.Status.Allowed, r.Status.Reason, nil }
// AllowedSubjects returns the subjects that can perform an action and any errors encountered while computing the list. // It is possible to have both subjects and errors returned if some rolebindings couldn't be resolved, but others could be. func (r *SubjectAccessEvaluator) AllowedSubjects(requestAttributes authorizer.Attributes) ([]rbac.Subject, error) { subjects := []rbac.Subject{{Kind: rbac.GroupKind, Name: user.SystemPrivilegedGroup}} if len(r.superUser) > 0 { subjects = append(subjects, rbac.Subject{Kind: rbac.UserKind, APIVersion: "v1alpha1", Name: r.superUser}) } errorlist := []error{} if clusterRoleBindings, err := r.clusterRoleBindingLister.ListClusterRoleBindings(); err != nil { errorlist = append(errorlist, err) } else { for _, clusterRoleBinding := range clusterRoleBindings { rules, err := r.roleToRuleMapper.GetRoleReferenceRules(clusterRoleBinding.RoleRef, "") if err != nil { // if we have an error, just keep track of it and keep processing. Since rules are additive, // missing a reference is bad, but we can continue with other rolebindings and still have a list // that does not contain any invalid values errorlist = append(errorlist, err) } if RulesAllow(requestAttributes, rules...) { subjects = append(subjects, clusterRoleBinding.Subjects...) } } } if namespace := requestAttributes.GetNamespace(); len(namespace) > 0 { if roleBindings, err := r.roleBindingLister.ListRoleBindings(namespace); err != nil { errorlist = append(errorlist, err) } else { for _, roleBinding := range roleBindings { rules, err := r.roleToRuleMapper.GetRoleReferenceRules(roleBinding.RoleRef, namespace) if err != nil { // if we have an error, just keep track of it and keep processing. Since rules are additive, // missing a reference is bad, but we can continue with other rolebindings and still have a list // that does not contain any invalid values errorlist = append(errorlist, err) } if RulesAllow(requestAttributes, rules...) { subjects = append(subjects, roleBinding.Subjects...) } } } } dedupedSubjects := []rbac.Subject{} for _, subject := range subjects { found := false for _, curr := range dedupedSubjects { if curr == subject { found = true break } } if !found { dedupedSubjects = append(dedupedSubjects, subject) } } return subjects, utilerrors.NewAggregate(errorlist) }
func (ka *allowTestAuthorizer) Authorize(a authorizer.Attributes) (string, error) { var ( tenantName string ns *api.Namespace err error ) if authorizer.IsWhiteListedUser(a.GetUserName()) { return "", nil } else { if !a.IsReadOnly() && a.GetResource() == "tenants" { return "", errors.New("only admin can write tenant") } } if a.GetNamespace() != "" { ns, err = ka.kubeClient.Namespaces().Get(a.GetNamespace()) if err != nil { glog.Error(err) return "", err } tenantName = ns.Tenant } else { if a.GetTenant() != "" { te, err := ka.kubeClient.Tenants().Get(a.GetTenant()) if err != nil { glog.Error(err) return "", err } tenantName = te.Name } } if tenantName == "" || tenantName == TenantTest { return TenantTest, nil } return "", errors.New("Keystone authorization failed") }
func (r *RBACAuthorizer) Authorize(attr authorizer.Attributes) error { if r.superUser != "" && attr.GetUserName() == r.superUser { return nil } userInfo := &user.DefaultInfo{ Name: attr.GetUserName(), Groups: attr.GetGroups(), } ctx := api.WithNamespace(api.WithUser(api.NewContext(), userInfo), attr.GetNamespace()) // Frame the authorization request as a privilege escalation check. var requestedRule rbac.PolicyRule if attr.IsResourceRequest() { requestedRule = rbac.PolicyRule{ Verbs: []string{attr.GetVerb()}, APIGroups: []string{attr.GetAPIGroup()}, // TODO(ericchiang): add api version here too? Resources: []string{attr.GetResource()}, ResourceNames: []string{attr.GetName()}, } } else { requestedRule = rbac.PolicyRule{ NonResourceURLs: []string{attr.GetPath()}, } } return validation.ConfirmNoEscalation(ctx, r.authorizationRuleResolver, []rbac.PolicyRule{requestedRule}) }
// Authorize makes a REST request to the remote service describing the attempted action as a JSON // serialized api.authorization.v1beta1.SubjectAccessReview object. An example request body is // provided bellow. // // { // "apiVersion": "authorization.k8s.io/v1beta1", // "kind": "SubjectAccessReview", // "spec": { // "resourceAttributes": { // "namespace": "kittensandponies", // "verb": "GET", // "group": "group3", // "resource": "pods" // }, // "user": "******", // "group": [ // "group1", // "group2" // ] // } // } // // The remote service is expected to fill the SubjectAccessReviewStatus field to either allow or // disallow access. A permissive response would return: // // { // "apiVersion": "authorization.k8s.io/v1beta1", // "kind": "SubjectAccessReview", // "status": { // "allowed": true // } // } // // To disallow access, the remote service would return: // // { // "apiVersion": "authorization.k8s.io/v1beta1", // "kind": "SubjectAccessReview", // "status": { // "allowed": false, // "reason": "user does not have read access to the namespace" // } // } // func (w *WebhookAuthorizer) Authorize(attr authorizer.Attributes) (err error) { r := &v1beta1.SubjectAccessReview{ Spec: v1beta1.SubjectAccessReviewSpec{ User: attr.GetUserName(), Groups: attr.GetGroups(), }, } if attr.IsResourceRequest() { r.Spec.ResourceAttributes = &v1beta1.ResourceAttributes{ Namespace: attr.GetNamespace(), Verb: attr.GetVerb(), Group: attr.GetAPIGroup(), Version: attr.GetAPIVersion(), Resource: attr.GetResource(), Subresource: attr.GetSubresource(), Name: attr.GetName(), } } else { r.Spec.NonResourceAttributes = &v1beta1.NonResourceAttributes{ Path: attr.GetPath(), Verb: attr.GetVerb(), } } key, err := json.Marshal(r.Spec) if err != nil { return err } if entry, ok := w.responseCache.Get(string(key)); ok { r.Status = entry.(v1beta1.SubjectAccessReviewStatus) } else { result := w.RestClient.Post().Body(r).Do() if err := result.Error(); err != nil { return err } if err := result.Into(r); err != nil { return err } go func() { if r.Status.Allowed { w.responseCache.Add(string(key), r.Status, w.authorizedTTL) } else { w.responseCache.Add(string(key), r.Status, w.unauthorizedTTL) } }() } if r.Status.Allowed { return nil } if r.Status.Reason != "" { return errors.New(r.Status.Reason) } return errors.New("unauthorized") }
func (authz *mockAuthorizer) Authorize(a authorizer.Attributes) (authorized bool, reason string, err error) { authz.lastURI = a.GetPath() return true, "", nil }
func (allowAliceAuthorizer) Authorize(a authorizer.Attributes) (bool, string, error) { if a.GetUser() != nil && a.GetUser().GetName() == "alice" { return true, "", nil } return false, "I can't allow that. Go ask alice.", nil }