Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions pkg/authorization/api/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ func init() {
&PolicyList{},
&PolicyBindingList{},
&RoleBindingList{},
&RoleList{},
)
}

Expand All @@ -31,3 +32,4 @@ func (*SubjectAccessReviewResponse) IsAnAPIObject() {}
func (*PolicyList) IsAnAPIObject() {}
func (*PolicyBindingList) IsAnAPIObject() {}
func (*RoleBindingList) IsAnAPIObject() {}
func (*RoleList) IsAnAPIObject() {}
9 changes: 8 additions & 1 deletion pkg/authorization/api/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,9 +209,16 @@ type PolicyBindingList struct {
Items []PolicyBinding
}

// RoleBindingList is a collection of PolicyBindings
// RoleBindingList is a collection of RoleBindings
type RoleBindingList struct {
kapi.TypeMeta
kapi.ListMeta
Items []RoleBinding
}

// RoleList is a collection of Roles
type RoleList struct {
kapi.TypeMeta
kapi.ListMeta
Items []Role
}
2 changes: 2 additions & 0 deletions pkg/authorization/api/v1beta1/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ func init() {
&PolicyList{},
&PolicyBindingList{},
&RoleBindingList{},
&RoleList{},
)
}

Expand All @@ -31,3 +32,4 @@ func (*SubjectAccessReviewResponse) IsAnAPIObject() {}
func (*PolicyList) IsAnAPIObject() {}
func (*PolicyBindingList) IsAnAPIObject() {}
func (*RoleBindingList) IsAnAPIObject() {}
func (*RoleList) IsAnAPIObject() {}
15 changes: 11 additions & 4 deletions pkg/authorization/api/v1beta1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,9 +169,16 @@ type PolicyBindingList struct {
Items []PolicyBinding `json:"items"`
}

// RoleBindingList is a collection of PolicyBindings
// RoleBindingList is a collection of RoleBindings
type RoleBindingList struct {
kapi.TypeMeta
kapi.ListMeta
Items []RoleBinding
kapi.TypeMeta `json:",inline"`
kapi.ListMeta `json:"metadata,omitempty"`
Items []RoleBinding `json:"items"`
}

// RoleList is a collection of Roles
type RoleList struct {
kapi.TypeMeta `json:",inline"`
kapi.ListMeta `json:"metadata,omitempty"`
Items []Role `json:"items"`
}
22 changes: 22 additions & 0 deletions pkg/authorization/registry/role/registry.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package role

import (
kapi "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
klabels "github.com/GoogleCloudPlatform/kubernetes/pkg/labels"

authorizationapi "github.com/openshift/origin/pkg/authorization/api"
)

// Registry is an interface for things that know how to store Roles.
type Registry interface {
// ListRoles obtains list of policyRoles that match a selector.
ListRoles(ctx kapi.Context, labels, fields klabels.Selector) (*authorizationapi.RoleList, error)
// GetRole retrieves a specific policyRole.
GetRole(ctx kapi.Context, id string) (*authorizationapi.Role, error)
// CreateRole creates a new policyRole.
CreateRole(ctx kapi.Context, policyRole *authorizationapi.Role) error
// UpdateRole updates a policyRole.
UpdateRole(ctx kapi.Context, policyRole *authorizationapi.Role) error
// DeleteRole deletes a policyRole.
DeleteRole(ctx kapi.Context, id string) error
}
113 changes: 25 additions & 88 deletions pkg/authorization/registry/role/rest.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,24 @@ package role

import (
"fmt"
"strings"

kapi "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
kerrors "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"

authorizationapi "github.com/openshift/origin/pkg/authorization/api"
"github.com/openshift/origin/pkg/authorization/api/validation"
policyregistry "github.com/openshift/origin/pkg/authorization/registry/policy"
)

// TODO add get and list
// TODO prevent privilege escalation

// REST implements the RESTStorage interface in terms of an Registry.
type REST struct {
registry policyregistry.Registry
registry Registry
}

// NewREST creates a new REST for policies.
func NewREST(registry policyregistry.Registry) apiserver.RESTStorage {
func NewREST(registry Registry) apiserver.RESTStorage {
return &REST{registry}
}

Expand All @@ -33,21 +28,32 @@ func (r *REST) New() runtime.Object {
return &authorizationapi.Role{}
}

// Delete asynchronously deletes the Policy specified by its id.
func (r *REST) Delete(ctx kapi.Context, id string) (runtime.Object, error) {
policy, err := r.EnsurePolicy(ctx)
func (*REST) NewList() runtime.Object {
return &authorizationapi.RoleList{}
}

// List obtains a list of roles that match selector.
func (r *REST) List(ctx kapi.Context, selector, fields labels.Selector) (runtime.Object, error) {
roles, err := r.registry.ListRoles(ctx, selector, fields)
if err != nil {
return nil, err
}
return roles, err

if !doesRoleExist(id, policy) {
return nil, fmt.Errorf("role %v does not exist", id)
}
}

delete(policy.Roles, id)
policy.LastModified = util.Now()
// Get obtains the role specified by its name.
func (r *REST) Get(ctx kapi.Context, name string) (runtime.Object, error) {
role, err := r.registry.GetRole(ctx, name)
if err != nil {
return nil, err
}
return role, err
}

return &kapi.Status{Status: kapi.StatusSuccess}, r.registry.UpdatePolicy(ctx, policy)
// Delete asynchronously deletes the role specified by its name.
func (r *REST) Delete(ctx kapi.Context, name string) (runtime.Object, error) {
return &kapi.Status{Status: kapi.StatusSuccess}, r.registry.DeleteRole(ctx, name)
}

// Create registers a given new Role inside the Policy instance to r.registry.
Expand All @@ -65,20 +71,10 @@ func (r *REST) Create(ctx kapi.Context, obj runtime.Object) (runtime.Object, err
return nil, kerrors.NewInvalid("role", role.Name, errs)
}

policy, err := r.EnsurePolicy(ctx)
err := r.registry.CreateRole(ctx, role)
if err != nil {
return nil, err
}
if doesRoleExist(role.Name, policy) {
return nil, fmt.Errorf("role %v already exists", role.Name)
}

policy.Roles[role.Name] = *role
policy.LastModified = util.Now()

if err := r.registry.UpdatePolicy(ctx, policy); err != nil {
return nil, err
}
return role, nil
}

Expand All @@ -96,68 +92,9 @@ func (r *REST) Update(ctx kapi.Context, obj runtime.Object) (runtime.Object, boo
return nil, false, kerrors.NewInvalid("role", role.Name, errs)
}

policy, err := r.EnsurePolicy(ctx)
err := r.registry.UpdateRole(ctx, role)
if err != nil {
return nil, false, err
}
if !doesRoleExist(role.Name, policy) {
return nil, false, fmt.Errorf("role %v does not exist", role.Name)
}

// set defaults
role.CreationTimestamp = util.Now()

policy.Roles[role.Name] = *role
policy.LastModified = util.Now()

if err := r.registry.UpdatePolicy(ctx, policy); err != nil {
return nil, false, err
}
return role, false, nil
}

func doesRoleExist(name string, policy *authorizationapi.Policy) bool {
_, exists := policy.Roles[name]

return exists
}

// EnsurePolicy returns the policy object for the specified namespace. If one does not exist, it is created for you. Permission to
// create, update, or delete roles in a namespace implies the ability to create a Policy object itself.
func (r *REST) EnsurePolicy(ctx kapi.Context) (*authorizationapi.Policy, error) {
policy, err := r.registry.GetPolicy(ctx, authorizationapi.PolicyName)
if err != nil {
if !strings.Contains(err.Error(), "not found") {
return nil, err
}

// if we have no policy, go ahead and make one. creating one here collapses code paths below. We only take this hit once
policy = NewEmptyPolicy(kapi.NamespaceValue(ctx))
if err := r.registry.CreatePolicy(ctx, policy); err != nil {
return nil, err
}

policy, err = r.registry.GetPolicy(ctx, authorizationapi.PolicyName)
if err != nil {
return nil, err
}

}

if policy.Roles == nil {
policy.Roles = make(map[string]authorizationapi.Role)
}

return policy, nil
}

func NewEmptyPolicy(namespace string) *authorizationapi.Policy {
policy := &authorizationapi.Policy{}
policy.Name = authorizationapi.PolicyName
policy.Namespace = namespace
policy.CreationTimestamp = util.Now()
policy.LastModified = util.Now()
policy.Roles = make(map[string]authorizationapi.Role)

return policy
}
Loading