func ConfirmNoEscalation(ctx kapi.Context, ruleResolver AuthorizationRuleResolver, role authorizationinterfaces.Role) error { ruleResolutionErrors := []error{} ownerLocalRules, err := ruleResolver.GetEffectivePolicyRules(ctx) if err != nil { // do not fail in this case. Rules are purely additive, so we can continue with a coverage check based on the rules we have user, _ := kapi.UserFrom(ctx) glog.V(1).Infof("non-fatal error getting local rules for %v: %v", user, err) ruleResolutionErrors = append(ruleResolutionErrors, err) } masterContext := kapi.WithNamespace(ctx, "") ownerGlobalRules, err := ruleResolver.GetEffectivePolicyRules(masterContext) if err != nil { // do not fail in this case. Rules are purely additive, so we can continue with a coverage check based on the rules we have user, _ := kapi.UserFrom(ctx) glog.V(1).Infof("non-fatal error getting global rules for %v: %v", user, err) ruleResolutionErrors = append(ruleResolutionErrors, err) } ownerRules := make([]authorizationapi.PolicyRule, 0, len(ownerGlobalRules)+len(ownerLocalRules)) ownerRules = append(ownerRules, ownerLocalRules...) ownerRules = append(ownerRules, ownerGlobalRules...) ownerRightsCover, missingRights := Covers(ownerRules, role.Rules()) if !ownerRightsCover { user, _ := kapi.UserFrom(ctx) return kapierrors.NewUnauthorized(fmt.Sprintf("attempt to grant extra privileges: %v user=%v ownerrules=%v ruleResolutionErrors=%v", missingRights, user, ownerRules, ruleResolutionErrors)) } return nil }
// ConfirmNoEscalation determines if the roles for a given user in a given namespace encompass the provided role. func ConfirmNoEscalation(ctx api.Context, ruleResolver AuthorizationRuleResolver, rules []rbac.PolicyRule) error { ruleResolutionErrors := []error{} ownerLocalRules, err := ruleResolver.GetEffectivePolicyRules(ctx) if err != nil { // As per AuthorizationRuleResolver contract, this may return a non fatal error with an incomplete list of policies. Log the error and continue. user, _ := api.UserFrom(ctx) glog.V(1).Infof("non-fatal error getting local rules for %v: %v", user, err) ruleResolutionErrors = append(ruleResolutionErrors, err) } masterContext := api.WithNamespace(ctx, "") ownerGlobalRules, err := ruleResolver.GetEffectivePolicyRules(masterContext) if err != nil { // Same case as above. Log error, don't fail. user, _ := api.UserFrom(ctx) glog.V(1).Infof("non-fatal error getting global rules for %v: %v", user, err) ruleResolutionErrors = append(ruleResolutionErrors, err) } ownerRules := make([]rbac.PolicyRule, 0, len(ownerGlobalRules)+len(ownerLocalRules)) ownerRules = append(ownerRules, ownerLocalRules...) ownerRules = append(ownerRules, ownerGlobalRules...) ownerRightsCover, missingRights := Covers(ownerRules, rules) if !ownerRightsCover { user, _ := api.UserFrom(ctx) return errors.NewUnauthorized(fmt.Sprintf("attempt to grant extra privileges: %v user=%v ownerrules=%v ruleResolutionErrors=%v", missingRights, user, ownerRules, ruleResolutionErrors)) } return nil }
func WithActingAs(handler http.Handler, requestContextMapper api.RequestContextMapper, a authorizer.Authorizer) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { requestedSubject := req.Header.Get("Impersonate-User") if len(requestedSubject) == 0 { handler.ServeHTTP(w, req) return } ctx, exists := requestContextMapper.Get(req) if !exists { forbidden(w, req) return } requestor, exists := api.UserFrom(ctx) if !exists { forbidden(w, req) return } actingAsAttributes := &authorizer.AttributesRecord{ User: requestor, Verb: "impersonate", APIGroup: api.GroupName, Resource: "users", // ResourceName: requestedSubject, ResourceRequest: true, } err := a.Authorize(actingAsAttributes) if err != nil { forbidden(w, req) return } switch { case strings.HasPrefix(requestedSubject, serviceaccount.ServiceAccountUsernamePrefix): namespace, name, err := serviceaccount.SplitUsername(requestedSubject) if err != nil { forbidden(w, req) return } requestContextMapper.Update(req, api.WithUser(ctx, serviceaccount.UserInfo(namespace, name, ""))) default: newUser := &user.DefaultInfo{ Name: requestedSubject, } requestContextMapper.Update(req, api.WithUser(ctx, newUser)) } newCtx, _ := requestContextMapper.Get(req) oldUser, _ := api.UserFrom(ctx) newUser, _ := api.UserFrom(newCtx) httplog.LogOf(req, w).Addf("%v is acting as %v", oldUser, newUser) handler.ServeHTTP(w, req) }) }
func (r *requestAttributeGetter) GetAttribs(req *http.Request) authorizer.Attributes { attribs := authorizer.AttributesRecord{} ctx, ok := r.requestContextMapper.Get(req) if ok { user, ok := api.UserFrom(ctx) if ok { attribs.User = user } } requestInfo, _ := r.requestInfoResolver.GetRequestInfo(req) // Start with common attributes that apply to resource and non-resource requests attribs.ResourceRequest = requestInfo.IsResourceRequest attribs.Path = requestInfo.Path attribs.Verb = requestInfo.Verb // If the request was for a resource in an API group, include that info attribs.APIGroup = requestInfo.APIGroup // If a path follows the conventions of the REST object store, then // we can extract the resource. Otherwise, not. attribs.Resource = requestInfo.Resource // If the request specifies a namespace, then the namespace is filled in. // Assumes there is no empty string namespace. Unspecified results // in empty (does not understand defaulting rules.) attribs.Namespace = requestInfo.Namespace return &attribs }
func GetAuthorizerAttributes(ctx api.Context) (authorizer.Attributes, error) { attribs := authorizer.AttributesRecord{} user, ok := api.UserFrom(ctx) if ok { attribs.User = user } requestInfo, found := request.RequestInfoFrom(ctx) if !found { return nil, errors.New("no RequestInfo found in the context") } // Start with common attributes that apply to resource and non-resource requests attribs.ResourceRequest = requestInfo.IsResourceRequest attribs.Path = requestInfo.Path attribs.Verb = requestInfo.Verb attribs.APIGroup = requestInfo.APIGroup attribs.APIVersion = requestInfo.APIVersion attribs.Resource = requestInfo.Resource attribs.Subresource = requestInfo.Subresource attribs.Namespace = requestInfo.Namespace attribs.Name = requestInfo.Name return &attribs, nil }
func (r *REST) Create(ctx api.Context, obj runtime.Object) (runtime.Object, error) { selfSAR, ok := obj.(*authorizationapi.SelfSubjectAccessReview) if !ok { return nil, apierrors.NewBadRequest(fmt.Sprintf("not a SelfSubjectAccessReview: %#v", obj)) } if errs := authorizationvalidation.ValidateSelfSubjectAccessReview(selfSAR); len(errs) > 0 { return nil, apierrors.NewInvalid(authorizationapi.Kind(selfSAR.Kind), "", errs) } userToCheck, exists := api.UserFrom(ctx) if !exists { return nil, apierrors.NewBadRequest("no user present on request") } var authorizationAttributes authorizer.AttributesRecord if selfSAR.Spec.ResourceAttributes != nil { authorizationAttributes = authorizationutil.ResourceAttributesFrom(userToCheck, *selfSAR.Spec.ResourceAttributes) } else { authorizationAttributes = authorizationutil.NonResourceAttributesFrom(userToCheck, *selfSAR.Spec.NonResourceAttributes) } allowed, reason, evaluationErr := r.authorizer.Authorize(authorizationAttributes) selfSAR.Status = authorizationapi.SubjectAccessReviewStatus{ Allowed: allowed, Reason: reason, } if evaluationErr != nil { selfSAR.Status.EvaluationError = evaluationErr.Error() } return selfSAR, nil }
func (impersonateAuthorizer) Authorize(ctx kapi.Context, a authorizer.AuthorizationAttributes) (allowed bool, reason string, err error) { user, exists := kapi.UserFrom(ctx) if !exists { return false, "missing user", nil } 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()) == 1 && user.GetGroups()[0] == "wheel" && a.GetVerb() == "impersonate" && a.GetResource() == "systemusers" { return true, "", nil } if len(user.GetGroups()) == 1 && user.GetGroups()[0] == "sa-impersonater" && a.GetVerb() == "impersonate" && a.GetResource() == "serviceaccounts" { return true, "", nil } if len(user.GetGroups()) == 1 && user.GetGroups()[0] == "regular-impersonater" && a.GetVerb() == "impersonate" && a.GetResource() == "users" { return true, "", nil } return false, "deny by default", nil }
func TestAuthenticateRequest(t *testing.T) { success := make(chan struct{}) contextMapper := api.NewRequestContextMapper() auth, err := NewRequestAuthenticator( contextMapper, authenticator.RequestFunc(func(req *http.Request) (user.Info, bool, error) { return &user.DefaultInfo{Name: "user"}, true, nil }), http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) { t.Errorf("unexpected call to failed") }), http.HandlerFunc(func(_ http.ResponseWriter, req *http.Request) { ctx, ok := contextMapper.Get(req) if ctx == nil || !ok { t.Errorf("no context stored on contextMapper: %#v", contextMapper) } user, ok := api.UserFrom(ctx) if user == nil || !ok { t.Errorf("no user stored in context: %#v", ctx) } close(success) }), ) auth.ServeHTTP(httptest.NewRecorder(), &http.Request{}) <-success empty, err := api.IsEmpty(contextMapper) if err != nil { t.Fatalf("unexpected error: %v", err) } if !empty { t.Fatalf("contextMapper should have no stored requests: %v", contextMapper) } }
func (s *Storage) Create(ctx api.Context, obj runtime.Object) (runtime.Object, error) { if u, ok := api.UserFrom(ctx); ok { if s.superUser != "" && u.GetName() == s.superUser { return s.StandardStorage.Create(ctx, obj) } // system:masters is special because the API server uses it for privileged loopback connections // therefore we know that a member of system:masters can always do anything for _, group := range u.GetGroups() { if group == user.SystemPrivilegedGroup { return s.StandardStorage.Create(ctx, obj) } } } clusterRoleBinding := obj.(*rbac.ClusterRoleBinding) rules, err := s.ruleResolver.GetRoleReferenceRules(ctx, clusterRoleBinding.RoleRef, clusterRoleBinding.Namespace) if err != nil { return nil, err } if err := validation.ConfirmNoEscalation(ctx, s.ruleResolver, rules); err != nil { return nil, errors.NewForbidden(groupResource, clusterRoleBinding.Name, err) } return s.StandardStorage.Create(ctx, obj) }
func (m *VirtualStorage) confirmNoEscalation(ctx kapi.Context, roleBinding *authorizationapi.RoleBinding) error { modifyingRole, err := m.getReferencedRole(roleBinding.RoleRef) if err != nil { return err } ruleResolver := rulevalidation.NewDefaultRuleResolver( m.PolicyRegistry, m.BindingRegistry, m.ClusterPolicyRegistry, m.ClusterPolicyBindingRegistry, ) ownerLocalRules, err := ruleResolver.GetEffectivePolicyRules(ctx) if err != nil { return kapierrors.NewInternalError(err) } masterContext := kapi.WithNamespace(ctx, "") ownerGlobalRules, err := ruleResolver.GetEffectivePolicyRules(masterContext) if err != nil { return kapierrors.NewInternalError(err) } ownerRules := make([]authorizationapi.PolicyRule, 0, len(ownerGlobalRules)+len(ownerLocalRules)) ownerRules = append(ownerRules, ownerLocalRules...) ownerRules = append(ownerRules, ownerGlobalRules...) ownerRightsCover, missingRights := rulevalidation.Covers(ownerRules, modifyingRole.Rules) if !ownerRightsCover { user, _ := kapi.UserFrom(ctx) return kapierrors.NewUnauthorized(fmt.Sprintf("attempt to grant extra privileges: %v user=%v ownerrules=%v", missingRights, user, ownerRules)) } return nil }
// getResourceHandler is an HTTP handler function for get requests. It delegates to the // passed-in getterFunc to perform the actual get. func getResourceHandler(scope RequestScope, getter getterFunc) restful.RouteFunction { return func(req *restful.Request, res *restful.Response) { w := res.ResponseWriter namespace, name, err := scope.Namer.Name(req) if err != nil { errorJSON(err, scope.Codec, w) return } ctx := scope.ContextFunc(req) ctx = api.WithNamespace(ctx, namespace) result, err := getter(ctx, name, req) if err != nil { errorJSON(err, scope.Codec, w) return } if err := setSelfLink(result, req, scope.Namer); err != nil { errorJSON(err, scope.Codec, w) return } // userinfo, ok := api.UserFrom(ctx) if ok && !authorizer.IsWhiteListedUser(userinfo.GetName()) { tenant := api.TenantValue(ctx) if objTenant, err := scope.Namer.ObjectTenant(result); err == nil { if objTenant != tenant && tenant != "" && objTenant != "" { forbidden(w, req.Request) return } } } write(http.StatusOK, scope.APIVersion, scope.Codec, result, w, req.Request) } }
func GetEffectivePolicyRules(ctx kapi.Context, ruleResolver rulevalidation.AuthorizationRuleResolver, clusterPolicyGetter client.ClusterPolicyLister) ([]authorizationapi.PolicyRule, []error) { namespace := kapi.NamespaceValue(ctx) if len(namespace) == 0 { return nil, []error{kapierrors.NewBadRequest(fmt.Sprintf("namespace is required on this type: %v", namespace))} } user, exists := kapi.UserFrom(ctx) if !exists { return nil, []error{kapierrors.NewBadRequest(fmt.Sprintf("user missing from context"))} } var errors []error var rules []authorizationapi.PolicyRule namespaceRules, err := ruleResolver.RulesFor(user, namespace) if err != nil { errors = append(errors, err) } for _, rule := range namespaceRules { rules = append(rules, rulevalidation.BreakdownRule(rule)...) } if scopes := user.GetExtra()[authorizationapi.ScopesKey]; len(scopes) > 0 { rules, err = filterRulesByScopes(rules, scopes, namespace, clusterPolicyGetter) if err != nil { return nil, []error{kapierrors.NewInternalError(err)} } } if compactedRules, err := rulevalidation.CompactRules(rules); err == nil { rules = compactedRules } sort.Sort(authorizationapi.SortableRuleSlice(rules)) return rules, errors }
func (r *requestAttributeGetter) GetAttribs(req *http.Request) authorizer.Attributes { attribs := authorizer.AttributesRecord{} ctx, ok := r.requestContextMapper.Get(req) if ok { user, ok := api.UserFrom(ctx) if ok { attribs.User = user } } apiRequestInfo, _ := r.apiRequestInfoResolver.GetAPIRequestInfo(req) attribs.Verb = apiRequestInfo.Verb // Check whether meaningful api information can be resolved for the current path if isAPIResourceRequest(r.apiRequestInfoResolver.APIPrefixes, req) { attribs.APIGroup = apiRequestInfo.APIGroup // If a path follows the conventions of the REST object store, then // we can extract the resource. Otherwise, not. attribs.Resource = apiRequestInfo.Resource // If the request specifies a namespace, then the namespace is filled in. // Assumes there is no empty string namespace. Unspecified results // in empty (does not understand defaulting rules.) attribs.Namespace = apiRequestInfo.Namespace } else { // If a request does not fall into an api namespace/resource pattern, it's a special path. attribs.NonResourcePath = req.URL.Path } return &attribs }
func cacheKey(ctx kapi.Context, a authorizer.Action) (string, error) { if a.GetRequestAttributes() != nil { // TODO: see if we can serialize this? return "", errors.New("cannot cache request attributes") } keyData := map[string]interface{}{ "verb": a.GetVerb(), "apiVersion": a.GetAPIVersion(), "apiGroup": a.GetAPIGroup(), "resource": a.GetResource(), "resourceName": a.GetResourceName(), "nonResourceURL": a.IsNonResourceURL(), "url": a.GetURL(), } if namespace, ok := kapi.NamespaceFrom(ctx); ok { keyData["namespace"] = namespace } if user, ok := kapi.UserFrom(ctx); ok { keyData["user"] = user.GetName() keyData["groups"] = user.GetGroups() keyData["scopes"] = user.GetExtra()[authorizationapi.ScopesKey] } key, err := json.Marshal(keyData) return string(key), err }
// GetEffectivePolicyRules returns the list of rules that apply to a given user in a given namespace and error. If an error is returned, the slice of // PolicyRules may not be complete, but it contains all retrievable rules. This is done because policy rules are purely additive and policy determinations // can be made on the basis of those rules that are found. func (a *DefaultRuleResolver) GetEffectivePolicyRules(ctx kapi.Context) ([]authorizationapi.PolicyRule, error) { roleBindings, err := a.GetRoleBindings(ctx) if err != nil { return nil, err } user, exists := kapi.UserFrom(ctx) if !exists { return nil, errors.New("user missing from context") } errs := []error{} rules := make([]authorizationapi.PolicyRule, 0, len(roleBindings)) for _, roleBinding := range roleBindings { if !appliesToUser(roleBinding.Users(), roleBinding.Groups(), user) { continue } role, err := a.GetRole(roleBinding) if err != nil { errs = append(errs, err) continue } for _, curr := range role.Rules() { rules = append(rules, curr) } } return rules, kerrors.NewAggregate(errs) }
func (r *requestAttributeGetter) GetAttribs(req *http.Request) authorizer.Attributes { attribs := authorizer.AttributesRecord{} ctx, ok := r.requestContextMapper.Get(req) if ok { user, ok := api.UserFrom(ctx) if ok { attribs.User = user } } requestInfo, _ := r.requestInfoResolver.GetRequestInfo(req) // Start with common attributes that apply to resource and non-resource requests attribs.ResourceRequest = requestInfo.IsResourceRequest attribs.Path = requestInfo.Path attribs.Verb = requestInfo.Verb attribs.APIGroup = requestInfo.APIGroup attribs.APIVersion = requestInfo.APIVersion attribs.Resource = requestInfo.Resource attribs.Subresource = requestInfo.Subresource attribs.Namespace = requestInfo.Namespace attribs.Name = requestInfo.Name return &attribs }
func (r *requestAttributeGetter) GetAttribs(req *http.Request) authorizer.Attributes { attribs := authorizer.AttributesRecord{} ctx, ok := r.requestContextMapper.Get(req) if ok { user, ok := api.UserFrom(ctx) if ok { attribs.User = user } } attribs.ReadOnly = IsReadOnlyReq(*req) apiRequestInfo, _ := r.apiRequestInfoResolver.GetAPIRequestInfo(req) // If a path follows the conventions of the REST object store, then // we can extract the resource. Otherwise, not. attribs.Resource = apiRequestInfo.Resource // If the request specifies a namespace, then the namespace is filled in. // Assumes there is no empty string namespace. Unspecified results // in empty (does not understand defaulting rules.) attribs.Namespace = apiRequestInfo.Namespace return &attribs }
func (r *requestAttributeGetter) GetAttribs(req *http.Request) (authorizer.Attributes, error) { attribs := authorizer.AttributesRecord{} ctx, ok := r.requestContextMapper.Get(req) if !ok { return nil, errors.New("no context found for request") } user, ok := api.UserFrom(ctx) if ok { attribs.User = user } requestInfo, found := request.RequestInfoFrom(ctx) if !found { return nil, errors.New("no RequestInfo found in the context") } // Start with common attributes that apply to resource and non-resource requests attribs.ResourceRequest = requestInfo.IsResourceRequest attribs.Path = requestInfo.Path attribs.Verb = requestInfo.Verb attribs.APIGroup = requestInfo.APIGroup attribs.APIVersion = requestInfo.APIVersion attribs.Resource = requestInfo.Resource attribs.Subresource = requestInfo.Subresource attribs.Namespace = requestInfo.Namespace attribs.Name = requestInfo.Name return &attribs, nil }
// Create instantiates a deployment config func (r *REST) Create(ctx kapi.Context, obj runtime.Object) (runtime.Object, error) { req, ok := obj.(*deployapi.DeploymentRequest) if !ok { return nil, errors.NewInternalError(fmt.Errorf("wrong object passed for requesting a new rollout: %#v", obj)) } configObj, err := r.store.Get(ctx, req.Name) if err != nil { return nil, err } config := configObj.(*deployapi.DeploymentConfig) old := config if errs := validation.ValidateRequestForDeploymentConfig(req, config); len(errs) > 0 { return nil, errors.NewInvalid(deployapi.Kind("DeploymentRequest"), req.Name, errs) } // We need to process the deployment config before we can determine if it is possible to trigger // a deployment. if req.Latest { if err := processTriggers(config, r.isn, req.Force); err != nil { return nil, err } } canTrigger, causes, err := canTrigger(config, r.rn, r.decoder, req.Force) if err != nil { return nil, err } // If we cannot trigger then there is nothing to do here. if !canTrigger { return &unversioned.Status{ Message: fmt.Sprintf("deployment config %q cannot be instantiated", config.Name), Code: int32(204), }, nil } glog.V(4).Infof("New deployment for %q caused by %#v", config.Name, causes) config.Status.Details = new(deployapi.DeploymentDetails) config.Status.Details.Causes = causes switch causes[0].Type { case deployapi.DeploymentTriggerOnConfigChange: config.Status.Details.Message = "config change" case deployapi.DeploymentTriggerOnImageChange: config.Status.Details.Message = "image change" case deployapi.DeploymentTriggerManual: config.Status.Details.Message = "manual change" } config.Status.LatestVersion++ userInfo, _ := kapi.UserFrom(ctx) attrs := admission.NewAttributesRecord(config, old, deployapi.Kind("DeploymentConfig").WithVersion(""), config.Namespace, config.Name, deployapi.Resource("DeploymentConfig").WithVersion(""), "", admission.Update, userInfo) if err := r.admit.Admit(attrs); err != nil { return nil, err } updated, _, err := r.store.Update(ctx, config.Name, rest.DefaultUpdatedObjectInfo(config, kapi.Scheme)) return updated, err }
func ConfirmNoEscalation(ctx kapi.Context, resource unversioned.GroupResource, name string, ruleResolver AuthorizationRuleResolver, role authorizationinterfaces.Role) error { ruleResolutionErrors := []error{} ownerLocalRules, err := ruleResolver.GetEffectivePolicyRules(ctx) if err != nil { // do not fail in this case. Rules are purely additive, so we can continue with a coverage check based on the rules we have user, _ := kapi.UserFrom(ctx) glog.V(1).Infof("non-fatal error getting local rules for %v: %v", user, err) ruleResolutionErrors = append(ruleResolutionErrors, err) } masterContext := kapi.WithNamespace(ctx, "") ownerGlobalRules, err := ruleResolver.GetEffectivePolicyRules(masterContext) if err != nil { // do not fail in this case. Rules are purely additive, so we can continue with a coverage check based on the rules we have user, _ := kapi.UserFrom(ctx) glog.V(1).Infof("non-fatal error getting global rules for %v: %v", user, err) ruleResolutionErrors = append(ruleResolutionErrors, err) } ownerRules := make([]authorizationapi.PolicyRule, 0, len(ownerGlobalRules)+len(ownerLocalRules)) ownerRules = append(ownerRules, ownerLocalRules...) ownerRules = append(ownerRules, ownerGlobalRules...) ownerRightsCover, missingRights := Covers(ownerRules, role.Rules()) if !ownerRightsCover { if compactedMissingRights, err := CompactRules(missingRights); err == nil { missingRights = compactedMissingRights } missingRightsStrings := make([]string, 0, len(missingRights)) for _, missingRight := range missingRights { missingRightsStrings = append(missingRightsStrings, missingRight.CompactString()) } sort.Strings(missingRightsStrings) user, _ := kapi.UserFrom(ctx) var internalErr error if len(ruleResolutionErrors) > 0 { internalErr = fmt.Errorf("user %q cannot grant extra privileges:\n%v\nrule resolution errors: %v)", user.GetName(), strings.Join(missingRightsStrings, "\n"), ruleResolutionErrors) } else { internalErr = fmt.Errorf("user %q cannot grant extra privileges:\n%v", user.GetName(), strings.Join(missingRightsStrings, "\n")) } return kapierrors.NewForbidden(resource, name, internalErr) } return nil }
// Validate validates a new namespace. func (namespaceStrategy) Validate(ctx api.Context, obj runtime.Object) fielderrors.ValidationErrorList { var admin bool = true userinfo, ok := api.UserFrom(ctx) if ok && !authorizer.IsWhiteListedUser(userinfo.GetName()) { admin = false } namespace := obj.(*api.Namespace) return validation.ValidateNamespace(namespace, admin) }
// ValidateUpdate is the default update validation for an end user. func (namespaceStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) fielderrors.ValidationErrorList { var admin bool = true userinfo, ok := api.UserFrom(ctx) if ok && !authorizer.IsWhiteListedUser(userinfo.GetName()) { admin = false } errorList := validation.ValidateNamespace(obj.(*api.Namespace), admin) return append(errorList, validation.ValidateNamespaceUpdate(obj.(*api.Namespace), old.(*api.Namespace))...) }
// List retrieves a list of Projects that match label. func (s *REST) List(ctx kapi.Context, label labels.Selector, field fields.Selector) (runtime.Object, error) { user, ok := kapi.UserFrom(ctx) if !ok { return nil, kerrors.NewForbidden("Project", "", fmt.Errorf("unable to list projects without a user on the context")) } namespaceList, err := s.lister.List(user) if err != nil { return nil, err } return convertNamespaceList(namespaceList), nil }
// Validate validates a new image stream. func (s Strategy) Validate(ctx kapi.Context, obj runtime.Object) field.ErrorList { stream := obj.(*api.ImageStream) user, ok := kapi.UserFrom(ctx) if !ok { return field.ErrorList{field.Forbidden(field.NewPath("imageStream"), stream.Name)} } errs := s.tagVerifier.Verify(nil, stream, user) errs = append(errs, s.tagsChanged(nil, stream)...) errs = append(errs, validation.ValidateImageStream(stream)...) return errs }
// Validate validates a new image stream. func (s Strategy) Validate(ctx kapi.Context, obj runtime.Object) fielderrors.ValidationErrorList { stream := obj.(*api.ImageStream) user, ok := kapi.UserFrom(ctx) if !ok { return fielderrors.ValidationErrorList{kerrors.NewForbidden("imageStream", stream.Name, fmt.Errorf("unable to update an ImageStream without a user on the context"))} } errs := s.tagVerifier.Verify(nil, stream, user) errs = append(errs, s.tagsChanged(nil, stream)...) errs = append(errs, validation.ValidateImageStream(stream)...) return errs }
func appliesTo(ctx api.Context, subjects []rbac.Subject) (bool, error) { user, ok := api.UserFrom(ctx) if !ok { return false, fmt.Errorf("no user data associated with context") } for _, subject := range subjects { if ok, err := appliesToUser(user, subject); err != nil || ok { return ok, err } } return false, nil }
// Create registers a given new ResourceAccessReview instance to r.registry. func (r *REST) Create(ctx kapi.Context, obj runtime.Object) (runtime.Object, error) { subjectAccessReview, ok := obj.(*authorizationapi.SubjectAccessReview) if !ok { return nil, kapierrors.NewBadRequest(fmt.Sprintf("not a subjectAccessReview: %#v", obj)) } if err := kutilerrors.NewAggregate(authorizationvalidation.ValidateSubjectAccessReview(subjectAccessReview)); err != nil { return nil, err } // if a namespace is present on the request, then the namespace on the on the SAR is overwritten. // This is to support backwards compatibility. To have gotten here in this state, it means that // the authorizer decided that a user could run an SAR against this namespace if namespace := kapi.NamespaceValue(ctx); len(namespace) > 0 { subjectAccessReview.Action.Namespace = namespace } else if err := r.isAllowed(ctx, subjectAccessReview); err != nil { // this check is mutually exclusive to the condition above. localSAR and localRAR both clear the namespace before delegating their calls // We only need to check if the SAR is allowed **again** if the authorizer didn't already approve the request for a legacy call. return nil, err } var userToCheck user.Info if (len(subjectAccessReview.User) == 0) && (len(subjectAccessReview.Groups) == 0) { // if no user or group was specified, use the info from the context ctxUser, exists := kapi.UserFrom(ctx) if !exists { return nil, kapierrors.NewBadRequest("user missing from context") } userToCheck = ctxUser } else { userToCheck = &user.DefaultInfo{ Name: subjectAccessReview.User, Groups: subjectAccessReview.Groups.List(), } } requestContext := kapi.WithNamespace(kapi.WithUser(ctx, userToCheck), subjectAccessReview.Action.Namespace) attributes := authorizer.ToDefaultAuthorizationAttributes(subjectAccessReview.Action) allowed, reason, err := r.authorizer.Authorize(requestContext, attributes) if err != nil { return nil, err } response := &authorizationapi.SubjectAccessReviewResponse{ Namespace: subjectAccessReview.Action.Namespace, Allowed: allowed, Reason: reason, } return response, nil }
// Create registers a given new pspssr instance to r.registry. func (r *REST) Create(ctx kapi.Context, obj runtime.Object) (runtime.Object, error) { pspssr, ok := obj.(*securityapi.PodSecurityPolicySelfSubjectReview) if !ok { return nil, kapierrors.NewBadRequest(fmt.Sprintf("not a PodSecurityPolicySelfSubjectReview: %#v", obj)) } if errs := securityvalidation.ValidatePodSecurityPolicySelfSubjectReview(pspssr); len(errs) > 0 { return nil, kapierrors.NewInvalid(kapi.Kind("PodSecurityPolicySelfSubjectReview"), "", errs) } userInfo, ok := kapi.UserFrom(ctx) if !ok { return nil, kapierrors.NewBadRequest(fmt.Sprintf("no user data associated with context")) } ns, ok := kapi.NamespaceFrom(ctx) if !ok { return nil, kapierrors.NewBadRequest("namespace parameter required.") } matchedConstraints, err := r.sccMatcher.FindApplicableSCCs(userInfo) if err != nil { return nil, kapierrors.NewBadRequest(fmt.Sprintf("unable to find SecurityContextConstraints: %v", err)) } saName := pspssr.Spec.Template.Spec.ServiceAccountName if len(saName) > 0 { saUserInfo := serviceaccount.UserInfo(ns, saName, "") saConstraints, err := r.sccMatcher.FindApplicableSCCs(saUserInfo) if err != nil { return nil, kapierrors.NewBadRequest(fmt.Sprintf("unable to find SecurityContextConstraints: %v", err)) } matchedConstraints = append(matchedConstraints, saConstraints...) } oscc.DeduplicateSecurityContextConstraints(matchedConstraints) sort.Sort(oscc.ByPriority(matchedConstraints)) var namespace *kapi.Namespace for _, constraint := range matchedConstraints { var ( provider kscc.SecurityContextConstraintsProvider err error ) if provider, namespace, err = oscc.CreateProviderFromConstraint(ns, namespace, constraint, r.client); err != nil { glog.Errorf("Unable to create provider for constraint: %v", err) continue } filled, err := podsecuritypolicysubjectreview.FillPodSecurityPolicySubjectReviewStatus(&pspssr.Status, provider, pspssr.Spec.Template.Spec, constraint) if err != nil { glog.Errorf("unable to fill PodSecurityPolicySelfSubjectReview from constraint %v", err) continue } if filled { return pspssr, nil } } return pspssr, nil }
func (a *fakeTestAuthorizer) Authorize(ctx kapi.Context, passedAttributes authorizer.AuthorizationAttributes) (bool, string, error) { a.t.Logf("Authorize: ctx: %#v", ctx) ui, ok := kapi.UserFrom(ctx) if !ok { return false, "", fmt.Errorf("No valid UserInfo for Context") } // User with pods/bindings. permission: if ui.GetName() == "system:serviceaccount:openshift-infra:daemonset-controller" { return true, "", nil } // User without pods/bindings. permission: return false, "", nil }
func (s *Storage) Create(ctx api.Context, obj runtime.Object) (runtime.Object, error) { if user, ok := api.UserFrom(ctx); ok { if s.superUser != "" && user.GetName() == s.superUser { return s.StandardStorage.Create(ctx, obj) } } clusterRole := obj.(*rbac.ClusterRole) rules := clusterRole.Rules if err := validation.ConfirmNoEscalation(ctx, s.ruleResolver, rules); err != nil { return nil, errors.NewForbidden(groupResource, clusterRole.Name, err) } return s.StandardStorage.Create(ctx, obj) }