func (m *VirtualStorage) createRole(ctx kapi.Context, obj runtime.Object, allowEscalation bool) (*authorizationapi.Role, error) { if err := rest.BeforeCreate(m.CreateStrategy, ctx, obj); err != nil { return nil, err } role := obj.(*authorizationapi.Role) if !allowEscalation { if err := rulevalidation.ConfirmNoEscalation(ctx, authorizationapi.Resource("role"), role.Name, m.RuleResolver, authorizationinterfaces.NewLocalRoleAdapter(role)); err != nil { return nil, err } } policy, err := m.EnsurePolicy(ctx) if err != nil { return nil, err } if _, exists := policy.Roles[role.Name]; exists { return nil, kapierrors.NewAlreadyExists(authorizationapi.Resource("role"), role.Name) } role.ResourceVersion = policy.ResourceVersion policy.Roles[role.Name] = role policy.LastModified = unversioned.Now() if err := m.PolicyStorage.UpdatePolicy(ctx, policy); err != nil { return nil, err } return role, nil }
func (m *VirtualStorage) confirmNoEscalation(ctx kapi.Context, roleBinding *authorizationapi.RoleBinding) error { modifyingRole, err := m.RuleResolver.GetRole(authorizationinterfaces.NewLocalRoleBindingAdapter(roleBinding)) if err != nil { return err } return rulevalidation.ConfirmNoEscalation(ctx, authorizationapi.Resource("rolebinding"), roleBinding.Name, m.RuleResolver, modifyingRole) }
func (m *VirtualStorage) updateRole(ctx kapi.Context, name string, objInfo rest.UpdatedObjectInfo, allowEscalation bool) (*authorizationapi.Role, bool, error) { old, err := m.Get(ctx, name) if err != nil { return nil, false, err } obj, err := objInfo.UpdatedObject(ctx, old) if err != nil { return nil, false, err } role, ok := obj.(*authorizationapi.Role) if !ok { return nil, false, kapierrors.NewBadRequest(fmt.Sprintf("obj is not a role: %#v", obj)) } if err := rest.BeforeUpdate(m.UpdateStrategy, ctx, obj, old); err != nil { return nil, false, err } if !allowEscalation { if err := rulevalidation.ConfirmNoEscalation(ctx, authorizationapi.Resource("role"), role.Name, m.RuleResolver, authorizationinterfaces.NewLocalRoleAdapter(role)); err != nil { return nil, false, err } } policy, err := m.PolicyStorage.GetPolicy(ctx, authorizationapi.PolicyName) if err != nil && kapierrors.IsNotFound(err) { return nil, false, kapierrors.NewNotFound(authorizationapi.Resource("role"), role.Name) } if err != nil { return nil, false, err } oldRole, exists := policy.Roles[role.Name] if !exists { return nil, false, kapierrors.NewNotFound(authorizationapi.Resource("role"), role.Name) } // non-mutating change if kapi.Semantic.DeepEqual(oldRole, role) { return role, false, nil } role.ResourceVersion = policy.ResourceVersion policy.Roles[role.Name] = role policy.LastModified = unversioned.Now() if err := m.PolicyStorage.UpdatePolicy(ctx, policy); err != nil { return nil, false, err } return role, false, nil }
func (m *VirtualStorage) createRole(ctx kapi.Context, obj runtime.Object, allowEscalation bool) (*authorizationapi.Role, error) { // Copy object before passing to BeforeCreate, since it mutates objCopy, err := kapi.Scheme.DeepCopy(obj) if err != nil { return nil, err } obj = objCopy.(runtime.Object) if err := rest.BeforeCreate(m.CreateStrategy, ctx, obj); err != nil { return nil, err } role := obj.(*authorizationapi.Role) if !allowEscalation { if err := rulevalidation.ConfirmNoEscalation(ctx, m.Resource, role.Name, m.RuleResolver, m.CachedRuleResolver, authorizationinterfaces.NewLocalRoleAdapter(role)); err != nil { return nil, err } } if err := kclient.RetryOnConflict(kclient.DefaultRetry, func() error { policy, err := m.EnsurePolicy(ctx) if err != nil { return err } if _, exists := policy.Roles[role.Name]; exists { return kapierrors.NewAlreadyExists(m.Resource, role.Name) } role.ResourceVersion = policy.ResourceVersion policy.Roles[role.Name] = role policy.LastModified = unversioned.Now() return m.PolicyStorage.UpdatePolicy(ctx, policy) }); err != nil { return nil, err } return role, nil }
func (m *VirtualStorage) updateRole(ctx kapi.Context, name string, objInfo rest.UpdatedObjectInfo, allowEscalation bool) (*authorizationapi.Role, bool, error) { var updatedRole *authorizationapi.Role var roleConflicted = false // Retry if the policy update hits a conflict if err := kclient.RetryOnConflict(kclient.DefaultRetry, func() error { policy, err := m.PolicyStorage.GetPolicy(ctx, authorizationapi.PolicyName) if kapierrors.IsNotFound(err) { return kapierrors.NewNotFound(m.Resource, name) } if err != nil { return err } oldRole, exists := policy.Roles[name] if !exists { return kapierrors.NewNotFound(m.Resource, name) } obj, err := objInfo.UpdatedObject(ctx, oldRole) if err != nil { return err } role, ok := obj.(*authorizationapi.Role) if !ok { return kapierrors.NewBadRequest(fmt.Sprintf("obj is not a role: %#v", obj)) } if len(role.ResourceVersion) == 0 && m.UpdateStrategy.AllowUnconditionalUpdate() { role.ResourceVersion = oldRole.ResourceVersion } if err := rest.BeforeUpdate(m.UpdateStrategy, ctx, obj, oldRole); err != nil { return err } if !allowEscalation { if err := rulevalidation.ConfirmNoEscalation(ctx, m.Resource, role.Name, m.RuleResolver, m.CachedRuleResolver, authorizationinterfaces.NewLocalRoleAdapter(role)); err != nil { return err } } // conflict detection if role.ResourceVersion != oldRole.ResourceVersion { // mark as a conflict err, but return an untyped error to escape the retry roleConflicted = true return errors.New(registry.OptimisticLockErrorMsg) } // non-mutating change if kapi.Semantic.DeepEqual(oldRole, role) { updatedRole = role return nil } role.ResourceVersion = policy.ResourceVersion policy.Roles[role.Name] = role policy.LastModified = unversioned.Now() if err := m.PolicyStorage.UpdatePolicy(ctx, policy); err != nil { return err } updatedRole = role return nil }); err != nil { if roleConflicted { // construct the typed conflict error return nil, false, kapierrors.NewConflict(authorizationapi.Resource("name"), name, err) } return nil, false, err } return updatedRole, false, nil }