func (e clusterRoleEvaluator) ResolveGettableNamespaces(scope string, clusterPolicyGetter client.ClusterPolicyLister) ([]string, error) { _, scopeNamespace, _, err := e.parseScope(scope) if err != nil { return nil, err } rules, err := e.resolveRules(scope, clusterPolicyGetter) if err != nil { return nil, err } attributes := authorizer.DefaultAuthorizationAttributes{ APIGroup: kapi.GroupName, Verb: "get", Resource: "namespaces", } errors := []error{} for _, rule := range rules { matches, err := attributes.RuleMatches(rule) if err != nil { errors = append(errors, err) continue } if matches { return []string{scopeNamespace}, nil } } return []string{}, kutilerrors.NewAggregate(errors) }
// build LocalSubjectAccessReview struct to validate role via checkAccess func (o *podNodeConstraints) checkPodsBindAccess(attr admission.Attributes) (bool, error) { ctx := kapi.WithUser(kapi.WithNamespace(kapi.NewContext(), attr.GetNamespace()), attr.GetUserInfo()) authzAttr := authorizer.DefaultAuthorizationAttributes{ Verb: "create", Resource: "pods/binding", APIGroup: kapi.GroupName, } if attr.GetResource().GroupResource() == kapi.Resource("pods") { authzAttr.ResourceName = attr.GetName() } allow, _, err := o.authorizer.Authorize(ctx, authzAttr) return allow, err }
// GetRequestAttributes populates authorizer attributes for the requests to the kubelet API. // Default attributes are {apiVersion=v1,verb=proxy,resource=nodes,resourceName=<node name>} // More specific verb/resource is set for the following request patterns: // /stats/* => verb=<api verb from request>, resource=nodes/stats // /metrics/* => verb=<api verb from request>, resource=nodes/metrics // /logs/* => verb=<api verb from request>, resource=nodes/log func (n NodeAuthorizerAttributesGetter) GetRequestAttributes(u user.Info, r *http.Request) kauthorizer.Attributes { namespace := "" apiVerb := "" switch r.Method { case "POST": apiVerb = "create" case "GET": apiVerb = "get" case "PUT": apiVerb = "update" case "PATCH": apiVerb = "patch" case "DELETE": apiVerb = "delete" } // Default verb/resource is <apiVerb> nodes/proxy, which allows full access to the kubelet API attrs := oauthorizer.DefaultAuthorizationAttributes{ APIVersion: "v1", APIGroup: "", Verb: apiVerb, Resource: "nodes/proxy", ResourceName: n.nodeName, URL: r.URL.Path, } // Override verb/resource for specific paths // Updates to these rules require updating NodeAdminRole and NodeReaderRole in bootstrap policy switch { case isSubpath(r, "/spec"): attrs.Verb = apiVerb attrs.Resource = authorizationapi.NodeSpecResource case isSubpath(r, "/stats"): attrs.Verb = apiVerb attrs.Resource = authorizationapi.NodeStatsResource case isSubpath(r, "/metrics"): attrs.Verb = apiVerb attrs.Resource = authorizationapi.NodeMetricsResource case isSubpath(r, "/logs"): attrs.Verb = apiVerb attrs.Resource = authorizationapi.NodeLogResource } // TODO: handle other things like /healthz/*? not sure if "non-resource" urls on the kubelet make sense to authorize against master non-resource URL policy glog.V(2).Infof("Node request attributes: namespace=%s, user=%#v, attrs=%#v", namespace, u, attrs) return authzadapter.KubernetesAuthorizerAttributes(namespace, u, attrs) }
// isAllowed checks to see if the current user has rights to issue a LocalSubjectAccessReview on the namespace they're attempting to access func (r *REST) isAllowed(ctx kapi.Context, rar *authorizationapi.ResourceAccessReview) error { localRARAttributes := authorizer.DefaultAuthorizationAttributes{ Verb: "create", Resource: "localresourceaccessreviews", } allowed, reason, err := r.authorizer.Authorize(kapi.WithNamespace(ctx, rar.Action.Namespace), localRARAttributes) if err != nil { return kapierrors.NewForbidden(authorizationapi.Resource(localRARAttributes.GetResource()), localRARAttributes.GetResourceName(), err) } if !allowed { forbiddenError := kapierrors.NewForbidden(authorizationapi.Resource(localRARAttributes.GetResource()), localRARAttributes.GetResourceName(), errors.New("") /*discarded*/) forbiddenError.ErrStatus.Message = reason return forbiddenError } return nil }
func TestRoundTrip(t *testing.T) { // Start with origin attributes oattrs := oauthorizer.DefaultAuthorizationAttributes{ Verb: "get", APIVersion: "av", APIGroup: "ag", Resource: "r", ResourceName: "rn", RequestAttributes: "ra", NonResourceURL: true, URL: "/123", } // Convert to kube attributes kattrs := KubernetesAuthorizerAttributes("ns", &user.DefaultInfo{Name: "myuser", Groups: []string{"mygroup"}}, oattrs) if kattrs.GetUser().GetName() != "myuser" { t.Errorf("Expected %v, got %v", "myuser", kattrs.GetUser().GetName()) } if !reflect.DeepEqual(kattrs.GetUser().GetGroups(), []string{"mygroup"}) { t.Errorf("Expected %v, got %v", []string{"mygroup"}, kattrs.GetUser().GetGroups()) } if kattrs.GetVerb() != "get" { t.Errorf("Expected %v, got %v", "get", kattrs.GetVerb()) } if kattrs.IsReadOnly() != true { t.Errorf("Expected %v, got %v", true, kattrs.IsReadOnly()) } if kattrs.GetNamespace() != "ns" { t.Errorf("Expected %v, got %v", "ns", kattrs.GetNamespace()) } if kattrs.GetResource() != "r" { t.Errorf("Expected %v, got %v", "", kattrs.GetResource()) } if kattrs.IsResourceRequest() != false { t.Errorf("Expected %v, got %v", false, kattrs.IsResourceRequest()) } if kattrs.GetPath() != "/123" { t.Errorf("Expected %v, got %v", "/123", kattrs.GetPath()) } // Convert back to context+origin attributes ctx, oattrs2 := OriginAuthorizerAttributes(kattrs) // Ensure namespace/user info is preserved if user, ok := kapi.UserFrom(ctx); !ok { t.Errorf("No user in context") } else if user.GetName() != "myuser" { t.Errorf("Expected %v, got %v", "myuser", user.GetName()) } else if !reflect.DeepEqual(user.GetGroups(), []string{"mygroup"}) { t.Errorf("Expected %v, got %v", []string{"mygroup"}, user.GetGroups()) } // Ensure common attribute info is preserved if oattrs.GetVerb() != oattrs2.GetVerb() { t.Errorf("Expected %v, got %v", oattrs.GetVerb(), oattrs2.GetVerb()) } if oattrs.GetResource() != oattrs2.GetResource() { t.Errorf("Expected %v, got %v", oattrs.GetResource(), oattrs2.GetResource()) } // Ensure origin-specific info is preserved if oattrs.GetAPIVersion() != oattrs2.GetAPIVersion() { t.Errorf("Expected %v, got %v", oattrs.GetAPIVersion(), oattrs2.GetAPIVersion()) } if oattrs.GetAPIGroup() != oattrs2.GetAPIGroup() { t.Errorf("Expected %v, got %v", oattrs.GetAPIGroup(), oattrs2.GetAPIGroup()) } if oattrs.GetResourceName() != oattrs2.GetResourceName() { t.Errorf("Expected %v, got %v", oattrs.GetResourceName(), oattrs2.GetResourceName()) } if oattrs.GetRequestAttributes() != oattrs2.GetRequestAttributes() { t.Errorf("Expected %v, got %v", oattrs.GetRequestAttributes(), oattrs2.GetRequestAttributes()) } if oattrs.IsNonResourceURL() != oattrs2.IsNonResourceURL() { t.Errorf("Expected %v, got %v", oattrs.IsNonResourceURL(), oattrs2.IsNonResourceURL()) } if oattrs.GetURL() != oattrs2.GetURL() { t.Errorf("Expected %v, got %v", oattrs.GetURL(), oattrs2.GetURL()) } }