@@ -17,7 +17,9 @@ import (
17
17
corev1 "k8s.io/api/core/v1"
18
18
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
19
19
"sigs.k8s.io/controller-runtime/pkg/client"
20
+ "sigs.k8s.io/controller-runtime/pkg/client/fake"
20
21
22
+ grpcContext "github.com/nginx/nginx-gateway-fabric/v2/internal/controller/nginx/agent/grpc/context"
21
23
"github.com/nginx/nginx-gateway-fabric/v2/internal/framework/controller"
22
24
)
23
25
@@ -67,6 +69,7 @@ func (m *mockClient) List(_ context.Context, obj client.ObjectList, _ ...client.
67
69
Namespace : m .podNamespace ,
68
70
Labels : labels ,
69
71
},
72
+ Status : corev1.PodStatus {Phase : corev1 .PodRunning },
70
73
},
71
74
}
72
75
@@ -204,38 +207,6 @@ func TestInterceptor(t *testing.T) {
204
207
expErrCode : codes .Unauthenticated ,
205
208
expErrMsg : "must be of the format" ,
206
209
},
207
- {
208
- name : "mismatched namespace in username" ,
209
- md : validMetadata ,
210
- peer : validPeerData ,
211
- username : "system:serviceaccount:invalid:gateway-nginx" ,
212
- appName : "gateway-nginx" ,
213
- podNamespace : "default" ,
214
- authenticated : true ,
215
- expErrCode : codes .Unauthenticated ,
216
- expErrMsg : "does not match namespace" ,
217
- },
218
- {
219
- name : "mismatched name in username" ,
220
- md : validMetadata ,
221
- peer : validPeerData ,
222
- username : "system:serviceaccount:default:invalid" ,
223
- appName : "gateway-nginx" ,
224
- podNamespace : "default" ,
225
- authenticated : true ,
226
- expErrCode : codes .Unauthenticated ,
227
- expErrMsg : "does not match service account name" ,
228
- },
229
- {
230
- name : "missing app name label" ,
231
- md : validMetadata ,
232
- peer : validPeerData ,
233
- username : "system:serviceaccount:default:gateway-nginx" ,
234
- podNamespace : "default" ,
235
- authenticated : true ,
236
- expErrCode : codes .Unauthenticated ,
237
- expErrMsg : "could not get app name" ,
238
- },
239
210
}
240
211
241
212
streamHandler := func (_ any , _ grpc.ServerStream ) error {
@@ -261,7 +232,7 @@ func TestInterceptor(t *testing.T) {
261
232
}
262
233
cs := NewContextSetter (mockK8sClient , "ngf-audience" )
263
234
264
- ctx := context . Background ()
235
+ ctx := t . Context ()
265
236
if test .md != nil {
266
237
peerCtx := context .Background ()
267
238
if test .peer != nil {
@@ -290,3 +261,147 @@ func TestInterceptor(t *testing.T) {
290
261
})
291
262
}
292
263
}
264
+
265
+ type patchClient struct {
266
+ client.Client
267
+ }
268
+
269
+ func (p * patchClient ) Create (_ context.Context , obj client.Object , _ ... client.CreateOption ) error {
270
+ tr , ok := obj .(* authv1.TokenReview )
271
+ if ok {
272
+ tr .Status .Authenticated = true
273
+ tr .Status .User .Username = "system:serviceaccount:default:gateway-nginx"
274
+ }
275
+ return nil
276
+ }
277
+
278
+ func TestValidateToken_PodListOptions (t * testing.T ) {
279
+ t .Parallel ()
280
+
281
+ testCases := []struct {
282
+ pod * corev1.Pod
283
+ gi * grpcContext.GrpcInfo
284
+ name string
285
+ shouldErr bool
286
+ }{
287
+ {
288
+ name : "all match" ,
289
+ pod : & corev1.Pod {
290
+ ObjectMeta : metav1.ObjectMeta {
291
+ Name : "nginx-pod" ,
292
+ Namespace : "default" ,
293
+ Labels : map [string ]string {
294
+ controller .AppNameLabel : "gateway-nginx" ,
295
+ },
296
+ },
297
+ Status : corev1.PodStatus {PodIP : "1.2.3.4" , Phase : corev1 .PodRunning },
298
+ },
299
+ gi : & grpcContext.GrpcInfo {Token : "dummy-token" , IPAddress : "1.2.3.4" },
300
+ shouldErr : false ,
301
+ },
302
+ {
303
+ name : "ip matches, namespace does not" ,
304
+ pod : & corev1.Pod {
305
+ ObjectMeta : metav1.ObjectMeta {
306
+ Name : "nginx-pod" ,
307
+ Namespace : "other-namespace" ,
308
+ Labels : map [string ]string {
309
+ controller .AppNameLabel : "gateway-nginx" ,
310
+ },
311
+ },
312
+ Status : corev1.PodStatus {PodIP : "1.2.3.4" , Phase : corev1 .PodRunning },
313
+ },
314
+ gi : & grpcContext.GrpcInfo {Token : "dummy-token" , IPAddress : "1.2.3.4" },
315
+ shouldErr : true ,
316
+ },
317
+ {
318
+ name : "ip matches, label value does not match" ,
319
+ pod : & corev1.Pod {
320
+ ObjectMeta : metav1.ObjectMeta {
321
+ Name : "nginx-pod" ,
322
+ Namespace : "default" ,
323
+ Labels : map [string ]string {
324
+ controller .AppNameLabel : "not-gateway-nginx" ,
325
+ },
326
+ },
327
+ Status : corev1.PodStatus {PodIP : "1.2.3.4" , Phase : corev1 .PodRunning },
328
+ },
329
+ gi : & grpcContext.GrpcInfo {Token : "dummy-token" , IPAddress : "1.2.3.4" },
330
+ shouldErr : true ,
331
+ },
332
+ {
333
+ name : "ip matches, label does not exist" ,
334
+ pod : & corev1.Pod {
335
+ ObjectMeta : metav1.ObjectMeta {
336
+ Name : "nginx-pod" ,
337
+ Namespace : "default" ,
338
+ Labels : map [string ]string {},
339
+ },
340
+ Status : corev1.PodStatus {PodIP : "1.2.3.4" , Phase : corev1 .PodRunning },
341
+ },
342
+ gi : & grpcContext.GrpcInfo {Token : "dummy-token" , IPAddress : "1.2.3.4" },
343
+ shouldErr : true ,
344
+ },
345
+ {
346
+ name : "ip does not match" ,
347
+ pod : & corev1.Pod {
348
+ ObjectMeta : metav1.ObjectMeta {
349
+ Name : "nginx-pod" ,
350
+ Namespace : "default" ,
351
+ Labels : map [string ]string {
352
+ controller .AppNameLabel : "gateway-nginx" ,
353
+ },
354
+ },
355
+ Status : corev1.PodStatus {PodIP : "1.2.3.4" , Phase : corev1 .PodRunning },
356
+ },
357
+ gi : & grpcContext.GrpcInfo {Token : "dummy-token" , IPAddress : "9.9.9.9" },
358
+ shouldErr : true ,
359
+ },
360
+ {
361
+ name : "all match but pod not running" ,
362
+ pod : & corev1.Pod {
363
+ ObjectMeta : metav1.ObjectMeta {
364
+ Name : "nginx-pod" ,
365
+ Namespace : "default" ,
366
+ Labels : map [string ]string {
367
+ controller .AppNameLabel : "gateway-nginx" ,
368
+ },
369
+ },
370
+ Status : corev1.PodStatus {PodIP : "1.2.3.4" , Phase : corev1 .PodPending },
371
+ },
372
+ gi : & grpcContext.GrpcInfo {Token : "dummy-token" , IPAddress : "1.2.3.4" },
373
+ shouldErr : true ,
374
+ },
375
+ }
376
+
377
+ for _ , tc := range testCases {
378
+ t .Run (tc .name , func (t * testing.T ) {
379
+ t .Parallel ()
380
+ g := NewWithT (t )
381
+
382
+ fakeClient := fake .NewClientBuilder ().
383
+ WithObjects (tc .pod ).
384
+ WithIndex (& corev1.Pod {}, "status.podIP" , func (obj client.Object ) []string {
385
+ pod , ok := obj .(* corev1.Pod )
386
+ g .Expect (ok ).To (BeTrue ())
387
+ if pod .Status .PodIP != "" {
388
+ return []string {pod .Status .PodIP }
389
+ }
390
+ return nil
391
+ }).
392
+ Build ()
393
+
394
+ patchedClient := & patchClient {fakeClient }
395
+ csPatched := NewContextSetter (patchedClient , "ngf-audience" )
396
+
397
+ resultCtx , err := csPatched .validateToken (t .Context (), tc .gi )
398
+ if tc .shouldErr {
399
+ g .Expect (err ).To (HaveOccurred ())
400
+ g .Expect (err .Error ()).To (ContainSubstring ("expected a single Running pod" ))
401
+ } else {
402
+ g .Expect (err ).ToNot (HaveOccurred ())
403
+ g .Expect (resultCtx ).ToNot (BeNil ())
404
+ }
405
+ })
406
+ }
407
+ }
0 commit comments