// List returns the set of namespace names the user has access to view func (ac *AuthorizationCache) List(userInfo user.Info) (*kapi.NamespaceList, error) { keys := sets.String{} user := userInfo.GetName() groups := userInfo.GetGroups() obj, exists, _ := ac.userSubjectRecordStore.GetByKey(user) if exists { subjectRecord := obj.(*subjectRecord) keys.Insert(subjectRecord.namespaces.List()...) } for _, group := range groups { obj, exists, _ := ac.groupSubjectRecordStore.GetByKey(group) if exists { subjectRecord := obj.(*subjectRecord) keys.Insert(subjectRecord.namespaces.List()...) } } namespaceList := &kapi.NamespaceList{} for key := range keys { namespace, exists, err := ac.namespaceStore.GetByKey(key) if err != nil { return nil, err } if exists { namespaceList.Items = append(namespaceList.Items, *namespace.(*kapi.Namespace)) } } return namespaceList, nil }
func AddUserToLSAR(user user.Info, lsar *LocalSubjectAccessReview) *LocalSubjectAccessReview { origScopes := user.GetExtra()[ScopesKey] scopes := make([]string, len(origScopes), len(origScopes)) copy(scopes, origScopes) lsar.User = user.GetName() lsar.Groups = sets.NewString(user.GetGroups()...) lsar.Scopes = scopes return lsar }
func (a *Authenticator) AuthenticationSucceeded(user user.Info, state string, w http.ResponseWriter, req *http.Request) (bool, error) { session, err := a.store.Get(req, a.name) if err != nil { return false, err } values := session.Values() values[UserNameKey] = user.GetName() values[UserUIDKey] = user.GetUID() // TODO: should we save groups, scope, and extra in the session as well? return false, a.store.Save(w, req) }
// constraintAppliesTo inspects the constraint's users and groups against the userInfo to determine // if it is usable by the userInfo. func ConstraintAppliesTo(constraint *kapi.SecurityContextConstraints, userInfo user.Info) bool { for _, user := range constraint.Users { if userInfo.GetName() == user { return true } } for _, userGroup := range userInfo.GetGroups() { if constraintSupportsGroup(userGroup, constraint.Groups) { return true } } return false }
func doesApplyToUser(ruleUsers, ruleGroups util.StringSet, user user.Info) bool { if ruleUsers.Has(user.GetName()) { return true } for _, currGroup := range user.GetGroups() { if ruleGroups.Has(currGroup) { return true } } return false }
func appliesToUser(ruleUsers, ruleGroups sets.String, user user.Info) bool { if ruleUsers.Has(user.GetName()) { return true } for _, currGroup := range user.GetGroups() { if ruleGroups.Has(currGroup) { return true } } return false }
// 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 { // Default verb/resource is proxy nodes, which allows full access to the kubelet API attrs := oauthorizer.DefaultAuthorizationAttributes{ APIVersion: "v1", APIGroup: "", Verb: "proxy", Resource: "nodes", ResourceName: n.nodeName, URL: r.URL.Path, } namespace := "" userName := u.GetName() groups := u.GetGroups() apiVerb := "" switch r.Method { case "POST": apiVerb = "create" case "GET": apiVerb = "get" case "PUT": apiVerb = "update" case "PATCH": apiVerb = "patch" case "DELETE": apiVerb = "delete" } // Override verb/resource for specific paths // Updates to these rules require updating NodeAdminRole and NodeReaderRole in bootstrap policy switch { 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=%s, groups=%v, attrs=%#v", namespace, userName, groups, attrs) return authzadapter.KubernetesAuthorizerAttributes(namespace, userName, groups, attrs) }
func appliesToUser(user user.Info, subject rbac.Subject) (bool, error) { switch subject.Kind { case rbac.UserKind: return subject.Name == rbac.UserAll || user.GetName() == subject.Name, nil case rbac.GroupKind: return has(user.GetGroups(), subject.Name), nil case rbac.ServiceAccountKind: if subject.Namespace == "" { return false, fmt.Errorf("subject of kind service account without specified namespace") } return serviceaccount.MakeUsername(subject.Namespace, subject.Name) == user.GetName(), nil default: return false, fmt.Errorf("unknown subject kind: %s", subject.Kind) } }
func appliesToUser(user user.Info, subject rbac.Subject) (bool, error) { switch subject.Kind { case rbac.UserKind: return subject.Name == rbac.UserAll || user.GetName() == subject.Name, nil case rbac.GroupKind: return has(user.GetGroups(), subject.Name), nil case rbac.ServiceAccountKind: if subject.Namespace == "" { return false, fmt.Errorf("subject of kind service account without specified namespace") } // TODO(ericchiang): Is there a better way of matching a service account name? return "system:serviceaccount:"+subject.Name+":"+subject.Namespace == user.GetName(), nil default: return false, fmt.Errorf("unknown subject kind: %s", subject.Kind) } }
func (v *TagVerifier) Verify(old, stream *api.ImageStream, user user.Info) field.ErrorList { var errors field.ErrorList oldTags := map[string]api.TagReference{} if old != nil && old.Spec.Tags != nil { oldTags = old.Spec.Tags } for tag, tagRef := range stream.Spec.Tags { if tagRef.From == nil { continue } if len(tagRef.From.Namespace) == 0 { continue } if stream.Namespace == tagRef.From.Namespace { continue } if oldRef, ok := oldTags[tag]; ok && !tagRefChanged(oldRef, tagRef, stream.Namespace) { continue } streamName, _, err := parseFromReference(stream, tagRef.From) fromPath := field.NewPath("spec", "tags").Key(tag).Child("from") if err != nil { errors = append(errors, field.Invalid(fromPath.Child("name"), tagRef.From.Name, "must be of the form <tag>, <repo>:<tag>, <id>, or <repo>@<id>")) continue } subjectAccessReview := authorizationapi.SubjectAccessReview{ Action: authorizationapi.AuthorizationAttributes{ Verb: "get", Group: api.GroupName, Resource: "imagestreams", ResourceName: streamName, }, User: user.GetName(), Groups: sets.NewString(user.GetGroups()...), } ctx := kapi.WithNamespace(kapi.NewContext(), tagRef.From.Namespace) glog.V(4).Infof("Performing SubjectAccessReview for user=%s, groups=%v to %s/%s", user.GetName(), user.GetGroups(), tagRef.From.Namespace, streamName) resp, err := v.subjectAccessReviewClient.CreateSubjectAccessReview(ctx, &subjectAccessReview) if err != nil || resp == nil || (resp != nil && !resp.Allowed) { errors = append(errors, field.Forbidden(fromPath, fmt.Sprintf("%s/%s", tagRef.From.Namespace, streamName))) continue } } return errors }
func (c *ClientAuthorizationGrantChecker) HasAuthorizedClient(user user.Info, grant *api.Grant) (approved bool, err error) { id := c.registry.ClientAuthorizationName(user.GetName(), grant.Client.GetId()) authorization, err := c.registry.GetClientAuthorization(kapi.NewContext(), id) if errors.IsNotFound(err) { return false, nil } if err != nil { return false, err } if len(authorization.UserUID) != 0 && authorization.UserUID != user.GetUID() { return false, fmt.Errorf("user %s UID %s does not match stored client authorization value for UID %s", user.GetName(), user.GetUID(), authorization.UserUID) } // TODO: improve this to allow the scope implementation to determine overlap if !scope.Covers(authorization.Scopes, scope.Split(grant.Scope)) { return false, nil } return true, nil }
// AppliesToUser returns true if this binding applies to the provided user. func (a ClusterRoleBindingAdapter) AppliesToUser(user user.Info) bool { if authorizationapi.SubjectsContainUser(a.roleBinding.Subjects, a.roleBinding.Namespace, user.GetName()) { return true } if authorizationapi.SubjectsContainAnyGroup(a.roleBinding.Subjects, user.GetGroups()) { return true } return false }
func (l *Grant) handleForm(user user.Info, w http.ResponseWriter, req *http.Request) { q := req.URL.Query() then := q.Get("then") clientID := q.Get("client_id") scopes := q.Get("scopes") redirectURI := q.Get("redirect_uri") client, err := l.clientregistry.GetClient(kapi.NewContext(), clientID) if err != nil || client == nil { l.failed("Could not find client for client_id", w, req) return } if err := scopeauthorizer.ValidateScopeRestrictions(client, scope.Split(scopes)...); err != nil { failure := fmt.Sprintf("%v requested illegal scopes (%v): %v", client.Name, scopes, err) l.failed(failure, w, req) return } uri, err := getBaseURL(req) if err != nil { glog.Errorf("Unable to generate base URL: %v", err) http.Error(w, "Unable to determine URL", http.StatusInternalServerError) return } csrf, err := l.csrf.Generate(w, req) if err != nil { glog.Errorf("Unable to generate CSRF token: %v", err) l.failed("Could not generate CSRF token", w, req) return } form := Form{ Action: uri.String(), Values: FormValues{ Then: then, ThenParam: thenParam, CSRF: csrf, CSRFParam: csrfParam, ClientID: client.Name, ClientIDParam: clientIDParam, UserName: user.GetName(), UserNameParam: userNameParam, Scopes: scopes, ScopesParam: scopesParam, RedirectURI: redirectURI, RedirectURIParam: redirectURIParam, ApproveParam: approveParam, DenyParam: denyParam, }, } l.render.Render(form, w, req) }
func UserToSubject(u user.Info) pkix.Name { return pkix.Name{ CommonName: u.GetName(), SerialNumber: u.GetUID(), Organization: u.GetGroups(), } }
func validateList(t *testing.T, lister Lister, user user.Info, expectedSet sets.String) { namespaceList, err := lister.List(user) if err != nil { t.Errorf("Unexpected error %v", err) } results := sets.String{} for _, namespace := range namespaceList.Items { results.Insert(namespace.Name) } if results.Len() != expectedSet.Len() || !results.HasAll(expectedSet.List()...) { t.Errorf("User %v, Expected: %v, Actual: %v", user.GetName(), expectedSet, results) } }
func appliesToUser(user user.Info, subject rbac.Subject, namespace string) bool { switch subject.Kind { case rbac.UserKind: return subject.Name == rbac.UserAll || user.GetName() == subject.Name case rbac.GroupKind: return has(user.GetGroups(), subject.Name) case rbac.ServiceAccountKind: // default the namespace to namespace we're working in if its available. This allows rolebindings that reference // SAs in th local namespace to avoid having to qualify them. saNamespace := namespace if len(subject.Namespace) > 0 { saNamespace = subject.Namespace } if len(saNamespace) == 0 { return false } return serviceaccount.MakeUsername(saNamespace, subject.Name) == user.GetName() default: return false } }
// List returns the set of namespace names the user has access to view func (ac *AuthorizationCache) List(userInfo user.Info) (*kapi.NamespaceList, error) { keys := sets.String{} user := userInfo.GetName() groups := userInfo.GetGroups() obj, exists, _ := ac.userSubjectRecordStore.GetByKey(user) if exists { subjectRecord := obj.(*subjectRecord) keys.Insert(subjectRecord.namespaces.List()...) } for _, group := range groups { obj, exists, _ := ac.groupSubjectRecordStore.GetByKey(group) if exists { subjectRecord := obj.(*subjectRecord) keys.Insert(subjectRecord.namespaces.List()...) } } allowedNamespaces, err := scope.ScopesToVisibleNamespaces(userInfo.GetExtra()[authorizationapi.ScopesKey], ac.clusterPolicyLister.ClusterPolicies()) if err != nil { return nil, err } namespaceList := &kapi.NamespaceList{} for key := range keys { namespaceObj, exists, err := ac.namespaceStore.GetByKey(key) if err != nil { return nil, err } if exists { namespace := *namespaceObj.(*kapi.Namespace) if allowedNamespaces.Has("*") || allowedNamespaces.Has(namespace.Name) { namespaceList.Items = append(namespaceList.Items, namespace) } } } return namespaceList, nil }
func (l *Grant) handleForm(user user.Info, w http.ResponseWriter, req *http.Request) { q := req.URL.Query() then := q.Get(thenParam) clientID := q.Get(clientIDParam) scopes := scope.Split(q.Get(scopeParam)) redirectURI := q.Get(redirectURIParam) client, err := l.clientregistry.GetClient(kapi.NewContext(), clientID) if err != nil || client == nil { l.failed("Could not find client for client_id", w, req) return } if err := scopeauthorizer.ValidateScopeRestrictions(client, scopes...); err != nil { failure := fmt.Sprintf("%v requested illegal scopes (%v): %v", client.Name, scopes, err) l.failed(failure, w, req) return } uri, err := getBaseURL(req) if err != nil { glog.Errorf("Unable to generate base URL: %v", err) http.Error(w, "Unable to determine URL", http.StatusInternalServerError) return } csrf, err := l.csrf.Generate(w, req) if err != nil { glog.Errorf("Unable to generate CSRF token: %v", err) l.failed("Could not generate CSRF token", w, req) return } grantedScopeNames := []string{} grantedScopes := []Scope{} requestedScopes := []Scope{} clientAuthID := l.authregistry.ClientAuthorizationName(user.GetName(), client.Name) if clientAuth, err := l.authregistry.GetClientAuthorization(kapi.NewContext(), clientAuthID); err == nil { grantedScopeNames = clientAuth.Scopes } for _, s := range scopes { requestedScopes = append(requestedScopes, getScopeData(s, grantedScopeNames)) } for _, s := range grantedScopeNames { grantedScopes = append(grantedScopes, getScopeData(s, grantedScopeNames)) } form := Form{ Action: uri.String(), GrantedScopes: grantedScopes, Names: GrantFormFields{ Then: thenParam, CSRF: csrfParam, ClientID: clientIDParam, UserName: userNameParam, Scopes: scopeParam, RedirectURI: redirectURIParam, Approve: approveParam, Deny: denyParam, }, Values: GrantFormFields{ Then: then, CSRF: csrf, ClientID: client.Name, UserName: user.GetName(), Scopes: requestedScopes, RedirectURI: redirectURI, }, } if saNamespace, saName, err := serviceaccount.SplitUsername(client.Name); err == nil { form.ServiceAccountName = saName form.ServiceAccountNamespace = saNamespace } l.render.Render(form, w, req) }
func (l *Grant) handleGrant(user user.Info, w http.ResponseWriter, req *http.Request) { if ok, err := l.csrf.Check(req, req.FormValue(csrfParam)); !ok || err != nil { glog.Errorf("Unable to check CSRF token: %v", err) l.failed("Invalid CSRF token", w, req) return } req.ParseForm() then := req.FormValue(thenParam) scopes := scope.Join(req.Form[scopeParam]) username := req.FormValue(userNameParam) if username != user.GetName() { glog.Errorf("User (%v) did not match authenticated user (%v)", username, user.GetName()) l.failed("User did not match", w, req) return } if len(req.FormValue(approveParam)) == 0 || len(scopes) == 0 { // Redirect with an error param url, err := url.Parse(then) if len(then) == 0 || err != nil { l.failed("Access denied, but no redirect URL was specified", w, req) return } q := url.Query() q.Set("error", "access_denied") url.RawQuery = q.Encode() http.Redirect(w, req, url.String(), http.StatusFound) return } clientID := req.FormValue(clientIDParam) client, err := l.clientregistry.GetClient(kapi.NewContext(), clientID) if err != nil || client == nil { l.failed("Could not find client for client_id", w, req) return } if err := scopeauthorizer.ValidateScopeRestrictions(client, scope.Split(scopes)...); err != nil { failure := fmt.Sprintf("%v requested illegal scopes (%v): %v", client.Name, scopes, err) l.failed(failure, w, req) return } clientAuthID := l.authregistry.ClientAuthorizationName(user.GetName(), client.Name) ctx := kapi.NewContext() clientAuth, err := l.authregistry.GetClientAuthorization(ctx, clientAuthID) if err == nil && clientAuth != nil { // Add new scopes and update clientAuth.Scopes = scope.Add(clientAuth.Scopes, scope.Split(scopes)) if _, err = l.authregistry.UpdateClientAuthorization(ctx, clientAuth); err != nil { glog.Errorf("Unable to update authorization: %v", err) l.failed("Could not update client authorization", w, req) return } } else { // Make sure client name, user name, grant scope, expiration, and redirect uri match clientAuth = &oapi.OAuthClientAuthorization{ UserName: user.GetName(), UserUID: user.GetUID(), ClientName: client.Name, Scopes: scope.Split(scopes), } clientAuth.Name = clientAuthID if _, err = l.authregistry.CreateClientAuthorization(ctx, clientAuth); err != nil { glog.Errorf("Unable to create authorization: %v", err) l.failed("Could not create client authorization", w, req) return } } // Redirect, overriding the scope param on the redirect with the scopes that were actually granted url, err := url.Parse(then) if len(then) == 0 || err != nil { l.failed("Access granted, but no redirect URL was specified", w, req) return } q := url.Query() q.Set("scope", scopes) url.RawQuery = q.Encode() http.Redirect(w, req, url.String(), http.StatusFound) }
func (a *userAuthorizer) AuthorizeRequest(req *http.Request, user user.Info) (bool, error) { return a.allowedUsers[user.GetName()], nil }
func (l *Grant) handleGrant(user user.Info, w http.ResponseWriter, req *http.Request) { if ok, err := l.csrf.Check(req, req.FormValue("csrf")); !ok || err != nil { glog.Errorf("Unable to check CSRF token: %v", err) l.failed("Invalid CSRF token", w, req) return } then := req.FormValue("then") scopes := req.FormValue("scopes") if len(req.FormValue(approveParam)) == 0 { // Redirect with rejection param url, err := url.Parse(then) if len(then) == 0 || err != nil { l.failed("Access denied, but no redirect URL was specified", w, req) return } q := url.Query() q.Set("error", "access_denied") url.RawQuery = q.Encode() http.Redirect(w, req, url.String(), http.StatusFound) return } clientID := req.FormValue("client_id") client, err := l.clientregistry.GetClient(kapi.NewContext(), clientID) if err != nil || client == nil { l.failed("Could not find client for client_id", w, req) return } clientAuthID := l.authregistry.ClientAuthorizationName(user.GetName(), client.Name) ctx := kapi.NewContext() clientAuth, err := l.authregistry.GetClientAuthorization(ctx, clientAuthID) if err == nil && clientAuth != nil { // Add new scopes and update clientAuth.Scopes = scope.Add(clientAuth.Scopes, scope.Split(scopes)) if _, err = l.authregistry.UpdateClientAuthorization(ctx, clientAuth); err != nil { glog.Errorf("Unable to update authorization: %v", err) l.failed("Could not update client authorization", w, req) return } } else { // Make sure client name, user name, grant scope, expiration, and redirect uri match clientAuth = &oapi.OAuthClientAuthorization{ UserName: user.GetName(), UserUID: user.GetUID(), ClientName: client.Name, Scopes: scope.Split(scopes), } clientAuth.Name = clientAuthID if _, err = l.authregistry.CreateClientAuthorization(ctx, clientAuth); err != nil { glog.Errorf("Unable to create authorization: %v", err) l.failed("Could not create client authorization", w, req) return } } if len(then) == 0 { l.failed("Approval granted, but no redirect URL was specified", w, req) return } http.Redirect(w, req, then, http.StatusFound) }