@@ -6,8 +6,10 @@ import (
6
6
7
7
kerrors "k8s.io/apimachinery/pkg/api/errors"
8
8
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
9
+ "k8s.io/apimachinery/pkg/runtime"
9
10
"k8s.io/apimachinery/pkg/util/sets"
10
11
kapi "k8s.io/kubernetes/pkg/api"
12
+ "k8s.io/kubernetes/pkg/client/retry"
11
13
12
14
authorizationapi "github.com/openshift/origin/pkg/authorization/apis/authorization"
13
15
"github.com/openshift/origin/pkg/cmd/server/bootstrappolicy"
@@ -34,10 +36,17 @@ var _ = g.Describe("[templates] templateinstance impersonation tests", func() {
34
36
35
37
dummytemplateinstance * templateapi.TemplateInstance
36
38
39
+ dummycondition = templateapi.TemplateInstanceCondition {
40
+ Type : templateapi .TemplateInstanceConditionType ("dummy" ),
41
+ Status : kapi .ConditionTrue ,
42
+ }
43
+
37
44
tests []struct {
38
45
user * userapi.User
39
- expectCreateUpdateSuccess bool
46
+ expectCreateSuccess bool
40
47
expectDeleteSuccess bool
48
+ hasUpdatePermission bool
49
+ hasUpdateStatusPermission bool
41
50
}
42
51
)
43
52
@@ -60,6 +69,7 @@ var _ = g.Describe("[templates] templateinstance impersonation tests", func() {
60
69
Name : "template" ,
61
70
Namespace : "dummy" ,
62
71
},
72
+ Objects : []runtime.Object {},
63
73
},
64
74
// all the tests work with a templateinstance which is set up to
65
75
// impersonate edituser1
@@ -71,38 +81,52 @@ var _ = g.Describe("[templates] templateinstance impersonation tests", func() {
71
81
72
82
tests = []struct {
73
83
user * userapi.User
74
- expectCreateUpdateSuccess bool
84
+ expectCreateSuccess bool
75
85
expectDeleteSuccess bool
86
+ hasUpdatePermission bool
87
+ hasUpdateStatusPermission bool
76
88
}{
77
89
{
78
- user : nil , // system-admin
79
- expectCreateUpdateSuccess : true , // can impersonate anyone
90
+ user : nil , // system-admin
91
+ expectCreateSuccess : true , // can impersonate anyone
80
92
expectDeleteSuccess : true ,
93
+ hasUpdatePermission : true ,
94
+ hasUpdateStatusPermission : true ,
81
95
},
82
96
{
83
- user : adminuser ,
84
- expectCreateUpdateSuccess : false , // cannot impersonate edituser1
97
+ user : adminuser ,
98
+ expectCreateSuccess : false , // cannot impersonate edituser1
85
99
expectDeleteSuccess : true ,
100
+ hasUpdatePermission : true ,
101
+ hasUpdateStatusPermission : false ,
86
102
},
87
103
{
88
- user : impersonateuser ,
89
- expectCreateUpdateSuccess : true , // can impersonate edituser1
104
+ user : impersonateuser ,
105
+ expectCreateSuccess : true , // can impersonate edituser1
90
106
expectDeleteSuccess : true ,
107
+ hasUpdatePermission : true ,
108
+ hasUpdateStatusPermission : false ,
91
109
},
92
110
{
93
- user : edituser1 ,
94
- expectCreateUpdateSuccess : true , // is edituser1
111
+ user : edituser1 ,
112
+ expectCreateSuccess : true , // is edituser1
95
113
expectDeleteSuccess : true ,
114
+ hasUpdatePermission : true ,
115
+ hasUpdateStatusPermission : false ,
96
116
},
97
117
{
98
- user : edituser2 ,
99
- expectCreateUpdateSuccess : false , // cannot impersonate edituser1
118
+ user : edituser2 ,
119
+ expectCreateSuccess : false , // cannot impersonate edituser1
100
120
expectDeleteSuccess : true ,
121
+ hasUpdatePermission : true ,
122
+ hasUpdateStatusPermission : false ,
101
123
},
102
124
{
103
- user : viewuser ,
104
- expectCreateUpdateSuccess : false , // cannot create things and cannot impersonate edituser1
125
+ user : viewuser ,
126
+ expectCreateSuccess : false , // cannot create things and cannot impersonate edituser1
105
127
expectDeleteSuccess : false ,
128
+ hasUpdatePermission : false ,
129
+ hasUpdateStatusPermission : false ,
106
130
},
107
131
}
108
132
@@ -168,7 +192,7 @@ var _ = g.Describe("[templates] templateinstance impersonation tests", func() {
168
192
o .Expect (err ).NotTo (o .HaveOccurred ())
169
193
templateinstance , err := cli .TemplateClient ().Template ().TemplateInstances (cli .Namespace ()).Create (templateinstancecopy .(* templateapi.TemplateInstance ))
170
194
171
- if ! test .expectCreateUpdateSuccess {
195
+ if ! test .expectCreateSuccess {
172
196
o .Expect (err ).To (o .HaveOccurred ())
173
197
o .Expect (kerrors .IsInvalid (err ) || kerrors .IsForbidden (err )).To (o .BeTrue ())
174
198
} else {
@@ -181,39 +205,87 @@ var _ = g.Describe("[templates] templateinstance impersonation tests", func() {
181
205
})
182
206
183
207
g .It ("should pass impersonation update tests" , func () {
184
- // check who can update TemplateInstances (anyone with project write access
185
- // AND is/can impersonate spec.requester.username)
208
+ // check who can update TemplateInstances. Via Update(), spec updates
209
+ // should be rejected (with the exception of spec.metadata fields used
210
+ // by the garbage collector, not tested here). Status updates should be
211
+ // silently ignored. Via UpdateStatus(), spec updates should be
212
+ // silently ignored. Status should only be updatable by a user with
213
+ // update access to that endpoint. In practice this is intended only to
214
+ // be the templateinstance controller and system:admin.
186
215
for _ , test := range tests {
216
+ var templateinstancecopy * templateapi.TemplateInstance
187
217
setUser (cli , test .user )
188
218
189
- templateinstancecopy , err := kapi .Scheme .DeepCopy (dummytemplateinstance )
190
- o .Expect (err ).NotTo (o .HaveOccurred ())
191
- templateinstance , err := cli .AdminTemplateClient ().Template ().TemplateInstances (cli .Namespace ()).Create (templateinstancecopy .(* templateapi.TemplateInstance ))
219
+ templateinstance , err := cli .AdminTemplateClient ().Template ().TemplateInstances (cli .Namespace ()).Create (dummytemplateinstance )
192
220
o .Expect (err ).NotTo (o .HaveOccurred ())
193
221
194
- var newtemplateinstance * templateapi.TemplateInstance
195
- for try := 0 ; try < 3 ; try ++ {
196
- newtemplateinstance , err = cli .TemplateClient ().Template ().TemplateInstances (cli .Namespace ()).Update (templateinstance )
197
- if kerrors .IsConflict (err ) {
198
- templateinstance , err = cli .TemplateClient ().Template ().TemplateInstances (cli .Namespace ()).Get (templateinstance .Name , metav1.GetOptions {})
199
- o .Expect (err ).NotTo (o .HaveOccurred ())
200
- } else {
201
- break
202
- }
222
+ // ensure spec (particularly including spec.requester.username) is
223
+ // immutable via Update()
224
+ err = retry .RetryOnConflict (retry .DefaultRetry , func () error {
225
+ templateinstancecopy , err = cli .TemplateClient ().Template ().TemplateInstances (cli .Namespace ()).Get (templateinstance .Name , metav1.GetOptions {})
226
+ o .Expect (err ).NotTo (o .HaveOccurred ())
227
+
228
+ templateinstancecopy .Spec .Requester .Username = edituser2 .Name
229
+
230
+ _ , err = cli .TemplateClient ().Template ().TemplateInstances (cli .Namespace ()).Update (templateinstancecopy )
231
+ return err
232
+ })
233
+ o .Expect (err ).To (o .HaveOccurred ())
234
+ o .Expect (kerrors .IsInvalid (err ) || kerrors .IsForbidden (err )).To (o .BeTrue ())
235
+
236
+ // ensure status changes are ignored via Update()
237
+ err = retry .RetryOnConflict (retry .DefaultRetry , func () error {
238
+ templateinstancecopy , err = cli .TemplateClient ().Template ().TemplateInstances (cli .Namespace ()).Get (templateinstance .Name , metav1.GetOptions {})
239
+ o .Expect (err ).NotTo (o .HaveOccurred ())
240
+
241
+ templateinstancecopy .Status .Conditions = append (templateinstancecopy .Status .Conditions , dummycondition )
242
+
243
+ templateinstancecopy , err = cli .TemplateClient ().Template ().TemplateInstances (cli .Namespace ()).Update (templateinstancecopy )
244
+ return err
245
+ })
246
+ if ! test .hasUpdatePermission {
247
+ o .Expect (err ).To (o .HaveOccurred ())
248
+ o .Expect (kerrors .IsInvalid (err ) || kerrors .IsForbidden (err )).To (o .BeTrue ())
249
+ } else {
250
+ o .Expect (err ).NotTo (o .HaveOccurred ())
251
+ o .Expect (templateinstancecopy .Status .Conditions ).NotTo (o .ContainElement (dummycondition ))
203
252
}
204
- if ! test .expectCreateUpdateSuccess {
253
+
254
+ // ensure spec changes are ignored via UpdateStatus()
255
+ err = retry .RetryOnConflict (retry .DefaultRetry , func () error {
256
+ templateinstancecopy , err = cli .TemplateClient ().Template ().TemplateInstances (cli .Namespace ()).Get (templateinstance .Name , metav1.GetOptions {})
257
+ o .Expect (err ).NotTo (o .HaveOccurred ())
258
+
259
+ templateinstancecopy .Spec .Requester .Username = edituser2 .Name
260
+
261
+ templateinstancecopy , err = cli .TemplateClient ().Template ().TemplateInstances (cli .Namespace ()).UpdateStatus (templateinstancecopy )
262
+ return err
263
+ })
264
+ if ! test .hasUpdateStatusPermission {
205
265
o .Expect (err ).To (o .HaveOccurred ())
206
266
o .Expect (kerrors .IsInvalid (err ) || kerrors .IsForbidden (err )).To (o .BeTrue ())
207
267
} else {
208
268
o .Expect (err ).NotTo (o .HaveOccurred ())
209
- templateinstance = newtemplateinstance
269
+ o . Expect ( templateinstancecopy . Spec ). To ( o . Equal ( dummytemplateinstance . Spec ))
210
270
}
211
271
212
- // ensure spec (particularly including spec.requester.username) is
213
- // immutable
214
- templateinstance .Spec .Requester .Username = edituser2 .Name
215
- _ , err = cli .TemplateClient ().Template ().TemplateInstances (cli .Namespace ()).Update (templateinstance )
216
- o .Expect (err ).To (o .HaveOccurred ())
272
+ // ensure status changes are allowed via UpdateStatus()
273
+ err = retry .RetryOnConflict (retry .DefaultRetry , func () error {
274
+ templateinstancecopy , err = cli .TemplateClient ().Template ().TemplateInstances (cli .Namespace ()).Get (templateinstance .Name , metav1.GetOptions {})
275
+ o .Expect (err ).NotTo (o .HaveOccurred ())
276
+
277
+ templateinstancecopy .Status .Conditions = []templateapi.TemplateInstanceCondition {dummycondition }
278
+
279
+ templateinstancecopy , err = cli .TemplateClient ().Template ().TemplateInstances (cli .Namespace ()).UpdateStatus (templateinstancecopy )
280
+ return err
281
+ })
282
+ if ! test .hasUpdateStatusPermission {
283
+ o .Expect (err ).To (o .HaveOccurred ())
284
+ o .Expect (kerrors .IsInvalid (err ) || kerrors .IsForbidden (err )).To (o .BeTrue ())
285
+ } else {
286
+ o .Expect (err ).NotTo (o .HaveOccurred ())
287
+ o .Expect (templateinstancecopy .Status .Conditions ).To (o .ContainElement (dummycondition ))
288
+ }
217
289
218
290
err = cli .AdminTemplateClient ().Template ().TemplateInstances (cli .Namespace ()).Delete (templateinstance .Name , nil )
219
291
o .Expect (err ).NotTo (o .HaveOccurred ())
0 commit comments