14
14
15
15
import base64
16
16
import datetime
17
+ import json
17
18
import os
18
19
import shutil
19
20
import tempfile
20
21
from types import SimpleNamespace
21
22
22
23
import yaml
23
- from asynctest import Mock , TestCase , main , patch
24
+ from asynctest import Mock , PropertyMock , TestCase , main , patch
24
25
from six import PY3
25
26
26
27
from .config_exception import ConfigException
@@ -39,6 +40,10 @@ def _base64(string):
39
40
return base64 .encodestring (string .encode ()).decode ()
40
41
41
42
43
+ def _unpadded_base64 (string ):
44
+ return base64 .b64encode (string .encode ()).decode ().rstrip ('' )
45
+
46
+
42
47
def _raise_exception (st ):
43
48
raise Exception (st )
44
49
@@ -67,6 +72,20 @@ def _raise_exception(st):
67
72
TEST_CLIENT_CERT = "client-cert"
68
73
TEST_CLIENT_CERT_BASE64 = _base64 (TEST_CLIENT_CERT )
69
74
75
+ TEST_OIDC_TOKEN = "test-oidc-token"
76
+ TEST_OIDC_INFO = "{\" name\" : \" test\" }"
77
+ TEST_OIDC_BASE = _unpadded_base64 (TEST_OIDC_TOKEN ) + "." + _unpadded_base64 (TEST_OIDC_INFO )
78
+ TEST_OIDC_LOGIN = TEST_OIDC_BASE + "." + TEST_CLIENT_CERT_BASE64
79
+ TEST_OIDC_TOKEN = "Bearer %s" % TEST_OIDC_LOGIN
80
+ TEST_OIDC_EXP = "{\" name\" : \" test\" ,\" exp\" : 536457600}"
81
+ TEST_OIDC_EXP_BASE = _unpadded_base64 (TEST_OIDC_TOKEN ) + "." + _unpadded_base64 (TEST_OIDC_EXP )
82
+ TEST_OIDC_EXPIRED_LOGIN = TEST_OIDC_EXP_BASE + "." + TEST_CLIENT_CERT_BASE64
83
+ TEST_OIDC_CA = _base64 (TEST_CERTIFICATE_AUTH )
84
+
85
+
86
+ async def _return_async_value (val ):
87
+ return val
88
+
70
89
71
90
class BaseTestCase (TestCase ):
72
91
@@ -333,6 +352,27 @@ class TestKubeConfigLoader(BaseTestCase):
333
352
"user" : "expired_gcp"
334
353
}
335
354
},
355
+ {
356
+ "name" : "oidc" ,
357
+ "context" : {
358
+ "cluster" : "default" ,
359
+ "user" : "oidc"
360
+ }
361
+ },
362
+ {
363
+ "name" : "expired_oidc" ,
364
+ "context" : {
365
+ "cluster" : "default" ,
366
+ "user" : "expired_oidc"
367
+ }
368
+ },
369
+ {
370
+ "name" : "expired_oidc_no_idp_cert_data" ,
371
+ "context" : {
372
+ "cluster" : "default" ,
373
+ "user" : "expired_oidc_no_idp_cert_data"
374
+ }
375
+ },
336
376
{
337
377
"name" : "user_pass" ,
338
378
"context" : {
@@ -450,6 +490,48 @@ class TestKubeConfigLoader(BaseTestCase):
450
490
"password" : TEST_PASSWORD , # should be ignored
451
491
}
452
492
},
493
+ {
494
+ "name" : "oidc" ,
495
+ "user" : {
496
+ "auth-provider" : {
497
+ "name" : "oidc" ,
498
+ "config" : {
499
+ "id-token" : TEST_OIDC_LOGIN
500
+ }
501
+ }
502
+ }
503
+ },
504
+ {
505
+ "name" : "expired_oidc" ,
506
+ "user" : {
507
+ "auth-provider" : {
508
+ "name" : "oidc" ,
509
+ "config" : {
510
+ "client-id" : "tectonic-kubectl" ,
511
+ "client-secret" : "FAKE_SECRET" ,
512
+ "id-token" : TEST_OIDC_EXPIRED_LOGIN ,
513
+ "idp-certificate-authority-data" : TEST_OIDC_CA ,
514
+ "idp-issuer-url" : "https://example.localhost/identity" ,
515
+ "refresh-token" : "lucWJjEhlxZW01cXI3YmVlcYnpxNGhzk"
516
+ }
517
+ }
518
+ }
519
+ },
520
+ {
521
+ "name" : "expired_oidc_no_idp_cert_data" ,
522
+ "user" : {
523
+ "auth-provider" : {
524
+ "name" : "oidc" ,
525
+ "config" : {
526
+ "client-id" : "tectonic-kubectl" ,
527
+ "client-secret" : "FAKE_SECRET" ,
528
+ "id-token" : TEST_OIDC_EXPIRED_LOGIN ,
529
+ "idp-issuer-url" : "https://example.localhost/identity" ,
530
+ "refresh-token" : "lucWJjEhlxZW01cXI3YmVlcYnpxNGhzk"
531
+ }
532
+ }
533
+ }
534
+ },
453
535
{
454
536
"name" : "user_pass" ,
455
537
"user" : {
@@ -564,6 +646,65 @@ async def cred():
564
646
self .assertEqual (BEARER_TOKEN_FORMAT % TEST_ANOTHER_DATA_BASE64 ,
565
647
loader .token )
566
648
649
+ async def test_oidc_no_refresh (self ):
650
+ loader = KubeConfigLoader (
651
+ config_dict = self .TEST_KUBE_CONFIG ,
652
+ active_context = 'oidc' ,
653
+ )
654
+ await loader ._load_authentication ()
655
+ self .assertEqual (TEST_OIDC_TOKEN , loader .token )
656
+
657
+ @patch ('kubernetes_asyncio.config.kube_config.OpenIDRequestor.refresh_token' )
658
+ async def test_oidc_with_refresh (self , mock_refresh_token ):
659
+ mock_refresh_token .return_value = {
660
+ 'id_token' : 'abc123' ,
661
+ 'refresh_token' : 'newtoken123'
662
+ }
663
+
664
+ loader = KubeConfigLoader (
665
+ config_dict = self .TEST_KUBE_CONFIG ,
666
+ active_context = 'expired_oidc' ,
667
+ )
668
+ await loader ._load_authentication ()
669
+ self .assertEqual ('Bearer abc123' , loader .token )
670
+
671
+ @patch ('kubernetes_asyncio.config.kube_config.OpenIDRequestor.refresh_token' )
672
+ async def test_oidc_with_refresh_no_idp_cert_data (self , mock_refresh_token ):
673
+ mock_refresh_token .return_value = {
674
+ 'id_token' : 'abc123' ,
675
+ 'refresh_token' : 'newtoken123'
676
+ }
677
+
678
+ loader = KubeConfigLoader (
679
+ config_dict = self .TEST_KUBE_CONFIG ,
680
+ active_context = 'expired_oidc_no_idp_cert_data' ,
681
+ )
682
+ await loader ._load_authentication ()
683
+ self .assertEqual ('Bearer abc123' , loader .token )
684
+
685
+ async def test_invalid_oidc_configs (self ):
686
+ loader = KubeConfigLoader (config_dict = self .TEST_KUBE_CONFIG )
687
+
688
+ with self .assertRaises (ValueError ):
689
+ loader ._user = {'auth-provider' : {}}
690
+ await loader ._load_oid_token ()
691
+
692
+ with self .assertRaises (ValueError ):
693
+ loader ._user = {
694
+ 'auth-provider' : {
695
+ 'config' : {
696
+ 'id-token' : 'notvalid'
697
+ },
698
+ }
699
+ }
700
+ await loader ._load_oid_token ()
701
+
702
+ async def test_invalid_refresh (self ):
703
+ loader = KubeConfigLoader (config_dict = self .TEST_KUBE_CONFIG )
704
+
705
+ with self .assertRaises (ConfigException ):
706
+ await loader ._refresh_oidc ({'config' : {}})
707
+
567
708
async def test_user_pass (self ):
568
709
expected = FakeConfig (host = TEST_HOST , token = TEST_BASIC_TOKEN )
569
710
actual = FakeConfig ()
0 commit comments