Skip to content

Commit f7cf91d

Browse files
committed
Proxy {Cluster}Role{Binding}s to Native Kube RBAC
Store them as native RBAC Objects via Kubernetes. Provides backwards compatible Openshift API.
1 parent 6a83bd3 commit f7cf91d

File tree

8 files changed

+889
-4
lines changed

8 files changed

+889
-4
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
package clusterrole
2+
3+
import (
4+
"errors"
5+
6+
apierrors "k8s.io/apimachinery/pkg/api/errors"
7+
metainternal "k8s.io/apimachinery/pkg/apis/meta/internalversion"
8+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
9+
"k8s.io/apimachinery/pkg/runtime"
10+
apirequest "k8s.io/apiserver/pkg/endpoints/request"
11+
"k8s.io/apiserver/pkg/registry/rest"
12+
"k8s.io/kubernetes/pkg/api"
13+
"k8s.io/kubernetes/pkg/apis/rbac"
14+
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion"
15+
16+
authorizationapi "github.com/openshift/origin/pkg/authorization/apis/authorization"
17+
"github.com/openshift/origin/pkg/authorization/registry/util"
18+
)
19+
20+
func rbacToClusterRole(in *rbac.ClusterRole) (authorizationapi.ClusterRole, error) {
21+
var out authorizationapi.ClusterRole
22+
err := authorizationapi.Convert_rbac_ClusterRole_To_authorization_ClusterRole(in, &out, nil)
23+
return out, err
24+
}
25+
26+
func rbacFromClusterRole(in *authorizationapi.ClusterRole) (rbac.ClusterRole, error) {
27+
var out rbac.ClusterRole
28+
err := authorizationapi.Convert_authorization_ClusterRole_To_rbac_ClusterRole(in, &out, nil)
29+
return out, err
30+
}
31+
32+
func getImpersonatingClient(ctx apirequest.Context, rbacclient internalversion.RbacInterface) (internalversion.ClusterRoleInterface, error) {
33+
user, ok := apirequest.UserFrom(ctx)
34+
if !ok {
35+
return nil, apierrors.NewInternalError(errors.New("missing user on request"))
36+
}
37+
38+
restclient := util.NewImpersonatingRESTClient(rbacclient.RESTClient(), user)
39+
40+
return internalversion.New(restclient).ClusterRoles(), nil
41+
}
42+
43+
type ClusterRoleStorage struct {
44+
client internalversion.RbacInterface
45+
}
46+
47+
func NewREST(rbacclient internalversion.RbacInterface) *ClusterRoleStorage {
48+
return &ClusterRoleStorage{rbacclient}
49+
}
50+
51+
func (crs *ClusterRoleStorage) New() runtime.Object {
52+
return &authorizationapi.ClusterRole{}
53+
}
54+
func (crs *ClusterRoleStorage) NewList() runtime.Object {
55+
return &authorizationapi.ClusterRoleList{}
56+
}
57+
58+
func (crs *ClusterRoleStorage) List(ctx apirequest.Context, options *metainternal.ListOptions) (runtime.Object, error) {
59+
client, err := getImpersonatingClient(ctx, crs.client)
60+
if err != nil {
61+
return nil, err
62+
}
63+
64+
optv1 := metav1.ListOptions{}
65+
if err := metainternal.Convert_internalversion_ListOptions_To_v1_ListOptions(options, &optv1, nil); err != nil {
66+
return nil, err
67+
}
68+
69+
roles, err := client.List(optv1)
70+
if roles == nil {
71+
return nil, err
72+
}
73+
74+
ret := &authorizationapi.ClusterRoleList{}
75+
for _, curr := range roles.Items {
76+
role, err := rbacToClusterRole(&curr)
77+
if err != nil {
78+
return nil, err
79+
}
80+
ret.Items = append(ret.Items, role)
81+
}
82+
return ret, err
83+
}
84+
85+
func (crs *ClusterRoleStorage) Get(ctx apirequest.Context, name string, options *metav1.GetOptions) (runtime.Object, error) {
86+
client, err := getImpersonatingClient(ctx, crs.client)
87+
if err != nil {
88+
return nil, err
89+
}
90+
91+
ret, err := client.Get(name, *options)
92+
if err != nil {
93+
return nil, err
94+
}
95+
96+
role, err := rbacToClusterRole(ret)
97+
if err != nil {
98+
return nil, err
99+
}
100+
return &role, err
101+
}
102+
103+
func (crs *ClusterRoleStorage) Delete(ctx apirequest.Context, name string, options *metav1.DeleteOptions) (runtime.Object, bool, error) {
104+
client, err := getImpersonatingClient(ctx, crs.client)
105+
if err != nil {
106+
return nil, false, err
107+
}
108+
109+
if err := client.Delete(name, options); err != nil {
110+
return nil, false, err
111+
}
112+
113+
return &metav1.Status{Status: metav1.StatusSuccess}, true, nil
114+
}
115+
116+
func (crs *ClusterRoleStorage) Create(ctx apirequest.Context, obj runtime.Object) (runtime.Object, error) {
117+
client, err := getImpersonatingClient(ctx, crs.client)
118+
if err != nil {
119+
return nil, err
120+
}
121+
122+
clusterObj := obj.(*authorizationapi.ClusterRole)
123+
convertedObj, err := rbacFromClusterRole(clusterObj)
124+
125+
ret, err := client.Create(&convertedObj)
126+
if err != nil {
127+
return nil, err
128+
}
129+
130+
role, err := rbacToClusterRole(ret)
131+
if err != nil {
132+
return nil, err
133+
}
134+
return &role, err
135+
}
136+
137+
func (crs *ClusterRoleStorage) Update(ctx apirequest.Context, name string, objInfo rest.UpdatedObjectInfo) (runtime.Object, bool, error) {
138+
client, err := getImpersonatingClient(ctx, crs.client)
139+
if err != nil {
140+
return nil, false, err
141+
}
142+
143+
old, err := client.Get(name, metav1.GetOptions{})
144+
if err != nil {
145+
if apierrors.IsNotFound(err) {
146+
err = apierrors.NewNotFound(rbac.Resource("clusterrole"), name)
147+
}
148+
return nil, false, err
149+
}
150+
151+
oldRole, err := rbacToClusterRole(old)
152+
if err != nil {
153+
return nil, false, err
154+
}
155+
156+
obj, err := objInfo.UpdatedObject(ctx, &oldRole)
157+
if err != nil {
158+
return nil, false, err
159+
}
160+
161+
updatedRole, err := rbacFromClusterRole(obj.(*authorizationapi.ClusterRole))
162+
if err != nil {
163+
return nil, false, err
164+
}
165+
166+
ret, err := client.Update(&updatedRole)
167+
if err != nil {
168+
return nil, false, err
169+
}
170+
171+
role, err := rbacToClusterRole(ret)
172+
if err != nil {
173+
return nil, false, err
174+
}
175+
return &role, false, err
176+
}
177+
178+
func (crs *ClusterRoleStorage) CreateClusterRoleWithEscalation(ctx apirequest.Context, obj *authorizationapi.ClusterRole) (*authorizationapi.ClusterRole, error) {
179+
ret, err := crs.Create(ctx, obj)
180+
if err != nil {
181+
return nil, err
182+
}
183+
return ret.(*authorizationapi.ClusterRole), err
184+
}
185+
186+
func (crs *ClusterRoleStorage) UpdateClusterRoleWithEscalation(ctx apirequest.Context, obj *authorizationapi.ClusterRole) (*authorizationapi.ClusterRole, bool, error) {
187+
ret, ignored, err := crs.Update(ctx, obj.Name, rest.DefaultUpdatedObjectInfo(obj, api.Scheme))
188+
if err != nil {
189+
return nil, false, err
190+
}
191+
return ret.(*authorizationapi.ClusterRole), ignored, err
192+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
package clusterrolebinding
2+
3+
import (
4+
"errors"
5+
6+
apierrors "k8s.io/apimachinery/pkg/api/errors"
7+
metainternal "k8s.io/apimachinery/pkg/apis/meta/internalversion"
8+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
9+
"k8s.io/apimachinery/pkg/runtime"
10+
apirequest "k8s.io/apiserver/pkg/endpoints/request"
11+
"k8s.io/apiserver/pkg/registry/rest"
12+
"k8s.io/kubernetes/pkg/api"
13+
"k8s.io/kubernetes/pkg/apis/rbac"
14+
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion"
15+
16+
authorizationapi "github.com/openshift/origin/pkg/authorization/apis/authorization"
17+
"github.com/openshift/origin/pkg/authorization/registry/util"
18+
)
19+
20+
func rbacToClusterRoleBinding(in *rbac.ClusterRoleBinding) (authorizationapi.ClusterRoleBinding, error) {
21+
var out authorizationapi.ClusterRoleBinding
22+
err := authorizationapi.Convert_rbac_ClusterRoleBinding_To_authorization_ClusterRoleBinding(in, &out, nil)
23+
return out, err
24+
}
25+
26+
func rbacFromClusterRoleBinding(in *authorizationapi.ClusterRoleBinding) (rbac.ClusterRoleBinding, error) {
27+
var out rbac.ClusterRoleBinding
28+
err := authorizationapi.Convert_authorization_ClusterRoleBinding_To_rbac_ClusterRoleBinding(in, &out, nil)
29+
return out, err
30+
}
31+
32+
func getImpersonatingClient(ctx apirequest.Context, rbacclient internalversion.RbacInterface) (internalversion.ClusterRoleBindingInterface, error) {
33+
user, ok := apirequest.UserFrom(ctx)
34+
if !ok {
35+
return nil, apierrors.NewInternalError(errors.New("missing user on request"))
36+
}
37+
38+
restclient := util.NewImpersonatingRESTClient(rbacclient.RESTClient(), user)
39+
40+
return internalversion.New(restclient).ClusterRoleBindings(), nil
41+
}
42+
43+
type ClusterRoleBindingStorage struct {
44+
client internalversion.RbacInterface
45+
}
46+
47+
func NewREST(rbacclient internalversion.RbacInterface) *ClusterRoleBindingStorage {
48+
return &ClusterRoleBindingStorage{rbacclient}
49+
}
50+
51+
func (crbs *ClusterRoleBindingStorage) New() runtime.Object {
52+
return &authorizationapi.ClusterRoleBinding{}
53+
}
54+
func (crbs *ClusterRoleBindingStorage) NewList() runtime.Object {
55+
return &authorizationapi.ClusterRoleBindingList{}
56+
}
57+
58+
func (crbs *ClusterRoleBindingStorage) List(ctx apirequest.Context, options *metainternal.ListOptions) (runtime.Object, error) {
59+
client, err := getImpersonatingClient(ctx, crbs.client)
60+
if err != nil {
61+
return nil, err
62+
}
63+
64+
optv1 := metav1.ListOptions{}
65+
if err := metainternal.Convert_internalversion_ListOptions_To_v1_ListOptions(options, &optv1, nil); err != nil {
66+
return nil, err
67+
}
68+
roles, err := client.List(optv1)
69+
if roles == nil {
70+
return nil, err
71+
}
72+
ret := &authorizationapi.ClusterRoleBindingList{}
73+
for _, curr := range roles.Items {
74+
role, err := rbacToClusterRoleBinding(&curr)
75+
if err != nil {
76+
return nil, err
77+
}
78+
ret.Items = append(ret.Items, role)
79+
}
80+
return ret, err
81+
}
82+
83+
func (crbs *ClusterRoleBindingStorage) Get(ctx apirequest.Context, name string, options *metav1.GetOptions) (runtime.Object, error) {
84+
client, err := getImpersonatingClient(ctx, crbs.client)
85+
if err != nil {
86+
return nil, err
87+
}
88+
89+
ret, err := client.Get(name, *options)
90+
if err != nil {
91+
return nil, err
92+
}
93+
role, err := rbacToClusterRoleBinding(ret)
94+
if err != nil {
95+
return nil, err
96+
}
97+
return &role, err
98+
}
99+
100+
func (crbs *ClusterRoleBindingStorage) Delete(ctx apirequest.Context, name string, options *metav1.DeleteOptions) (runtime.Object, bool, error) {
101+
client, err := getImpersonatingClient(ctx, crbs.client)
102+
if err != nil {
103+
return nil, false, err
104+
}
105+
106+
if err := client.Delete(name, options); err != nil {
107+
return nil, false, err
108+
}
109+
110+
return &metav1.Status{Status: metav1.StatusSuccess}, true, nil
111+
}
112+
113+
func (crbs *ClusterRoleBindingStorage) Create(ctx apirequest.Context, obj runtime.Object) (runtime.Object, error) {
114+
client, err := getImpersonatingClient(ctx, crbs.client)
115+
if err != nil {
116+
return nil, err
117+
}
118+
119+
clusterObj := obj.(*authorizationapi.ClusterRoleBinding)
120+
convertedObj, err := rbacFromClusterRoleBinding(clusterObj)
121+
122+
ret, err := client.Create(&convertedObj)
123+
if err != nil {
124+
return nil, err
125+
}
126+
127+
role, err := rbacToClusterRoleBinding(ret)
128+
if err != nil {
129+
return nil, err
130+
}
131+
return &role, err
132+
}
133+
134+
func (crbs *ClusterRoleBindingStorage) Update(ctx apirequest.Context, name string, objInfo rest.UpdatedObjectInfo) (runtime.Object, bool, error) {
135+
client, err := getImpersonatingClient(ctx, crbs.client)
136+
if err != nil {
137+
return nil, false, err
138+
}
139+
140+
old, err := client.Get(name, metav1.GetOptions{})
141+
if err != nil {
142+
if apierrors.IsNotFound(err) {
143+
err = apierrors.NewNotFound(rbac.Resource("clusterrolebinding"), name)
144+
}
145+
return nil, false, err
146+
}
147+
148+
oldRoleBinding, err := rbacToClusterRoleBinding(old)
149+
if err != nil {
150+
return nil, false, err
151+
}
152+
153+
obj, err := objInfo.UpdatedObject(ctx, &oldRoleBinding)
154+
if err != nil {
155+
return nil, false, err
156+
}
157+
158+
updatedRoleBinding, err := rbacFromClusterRoleBinding(obj.(*authorizationapi.ClusterRoleBinding))
159+
if err != nil {
160+
return nil, false, err
161+
}
162+
163+
ret, err := client.Update(&updatedRoleBinding)
164+
if err != nil {
165+
return nil, false, err
166+
}
167+
168+
role, err := rbacToClusterRoleBinding(ret)
169+
if err != nil {
170+
return nil, false, err
171+
}
172+
return &role, false, err
173+
}
174+
175+
// FIXME: what's escalation exactly ?
176+
func (crbs *ClusterRoleBindingStorage) CreateClusterRoleBindingWithEscalation(ctx apirequest.Context, obj *authorizationapi.ClusterRoleBinding) (*authorizationapi.ClusterRoleBinding, error) {
177+
ret, err := crbs.Create(ctx, obj)
178+
if err != nil {
179+
return nil, err
180+
}
181+
return ret.(*authorizationapi.ClusterRoleBinding), err
182+
}
183+
184+
func (crbs *ClusterRoleBindingStorage) UpdateClusterRoleBindingWithEscalation(ctx apirequest.Context, obj *authorizationapi.ClusterRoleBinding) (*authorizationapi.ClusterRoleBinding, bool, error) {
185+
ret, ignored, err := crbs.Update(ctx, obj.Name, rest.DefaultUpdatedObjectInfo(obj, api.Scheme))
186+
if err != nil {
187+
return nil, false, err
188+
}
189+
return ret.(*authorizationapi.ClusterRoleBinding), ignored, err
190+
}

0 commit comments

Comments
 (0)