@@ -300,7 +300,7 @@ func TestWorkloadIdentityCredential_Options(t *testing.T) {
300
300
// createTestCA generates a self-signed CA certificate for testing
301
301
func createTestCA (t * testing.T ) ([]byte , string ) {
302
302
t .Helper ()
303
-
303
+
304
304
// Generate private key
305
305
priv , err := rsa .GenerateKey (rand .Reader , 2048 )
306
306
require .NoError (t , err )
@@ -316,11 +316,11 @@ func createTestCA(t *testing.T) ([]byte, string) {
316
316
StreetAddress : []string {"" },
317
317
PostalCode : []string {"" },
318
318
},
319
- NotBefore : time .Now (),
320
- NotAfter : time .Now ().Add (365 * 24 * time .Hour ),
321
- KeyUsage : x509 .KeyUsageKeyEncipherment | x509 .KeyUsageDigitalSignature | x509 .KeyUsageCertSign ,
322
- ExtKeyUsage : []x509.ExtKeyUsage {x509 .ExtKeyUsageServerAuth },
323
- IsCA : true ,
319
+ NotBefore : time .Now (),
320
+ NotAfter : time .Now ().Add (365 * 24 * time .Hour ),
321
+ KeyUsage : x509 .KeyUsageKeyEncipherment | x509 .KeyUsageDigitalSignature | x509 .KeyUsageCertSign ,
322
+ ExtKeyUsage : []x509.ExtKeyUsage {x509 .ExtKeyUsageServerAuth },
323
+ IsCA : true ,
324
324
BasicConstraintsValid : true ,
325
325
}
326
326
@@ -333,7 +333,7 @@ func createTestCA(t *testing.T) ([]byte, string) {
333
333
334
334
// Write to temporary file
335
335
caFile := filepath .Join (t .TempDir (), "ca.crt" )
336
- err = os .WriteFile (caFile , certPEM , 0644 )
336
+ err = os .WriteFile (caFile , certPEM , 0600 )
337
337
require .NoError (t , err )
338
338
339
339
return certPEM , caFile
@@ -448,7 +448,7 @@ func TestWorkloadIdentityCredential_IdentityBinding_Detection(t *testing.T) {
448
448
449
449
// Set up required workload identity variables
450
450
tempTokenFile := filepath .Join (t .TempDir (), "token" )
451
- err := os .WriteFile (tempTokenFile , []byte ("test-token" ), 0644 )
451
+ err := os .WriteFile (tempTokenFile , []byte ("test-token" ), 0600 )
452
452
require .NoError (t , err )
453
453
454
454
t .Setenv (azureClientID , fakeClientID )
@@ -501,7 +501,7 @@ func TestWorkloadIdentityCredential_IdentityBinding_InvalidCAFile(t *testing.T)
501
501
func TestWorkloadIdentityCredential_IdentityBinding_InvalidCAContent (t * testing.T ) {
502
502
// Create invalid CA file
503
503
caFile := filepath .Join (t .TempDir (), "invalid-ca.crt" )
504
- err := os .WriteFile (caFile , []byte ("not a valid certificate" ), 0644 )
504
+ err := os .WriteFile (caFile , []byte ("not a valid certificate" ), 0600 )
505
505
require .NoError (t , err )
506
506
507
507
t .Setenv (azureKubernetesTokenEndpoint , "https://kubernetes.default.svc" )
@@ -527,7 +527,8 @@ func TestWorkloadIdentityCredential_IdentityBinding_TransportRedirection(t *test
527
527
require .NoError (t , err )
528
528
529
529
// Test token request (should be redirected)
530
- req , _ := http .NewRequest ("POST" , "https://login.microsoftonline.com/tenant-id/oauth2/v2.0/token" , nil )
530
+ req , err := http .NewRequest ("POST" , "https://login.microsoftonline.com/tenant-id/oauth2/v2.0/token" , nil )
531
+ require .NoError (t , err )
531
532
_ , _ = transport .Do (req )
532
533
533
534
// Since token requests go through the custom transport's internal logic and don't hit the fallback transport,
@@ -537,7 +538,8 @@ func TestWorkloadIdentityCredential_IdentityBinding_TransportRedirection(t *test
537
538
require .Len (t , requests , 0 , "Token requests should not go through fallback transport" )
538
539
539
540
// Test non-token request (should go through fallback transport)
540
- req2 , _ := http .NewRequest ("GET" , "https://login.microsoftonline.com/common/discovery/instance" , nil )
541
+ req2 , err := http .NewRequest ("GET" , "https://login.microsoftonline.com/common/discovery/instance" , nil )
542
+ require .NoError (t , err )
541
543
_ , _ = transport .Do (req2 )
542
544
543
545
// Verify fallback transport was used for non-token request
@@ -597,7 +599,7 @@ func TestWorkloadIdentityCredential_IdentityBinding_CAReloading(t *testing.T) {
597
599
598
600
// Create initial CA
599
601
initialCA , _ := createTestCA (t )
600
- err := os .WriteFile (caFile , initialCA , 0644 )
602
+ err := os .WriteFile (caFile , initialCA , 0600 )
601
603
require .NoError (t , err )
602
604
603
605
// Create transport recorder
@@ -619,7 +621,7 @@ func TestWorkloadIdentityCredential_IdentityBinding_CAReloading(t *testing.T) {
619
621
620
622
// Create new CA and update file
621
623
newCA , _ := createTestCA (t )
622
- err = os .WriteFile (caFile , newCA , 0644 )
624
+ err = os .WriteFile (caFile , newCA , 0600 )
623
625
require .NoError (t , err )
624
626
625
627
// Get transport again to trigger reload
@@ -639,7 +641,7 @@ func TestWorkloadIdentityCredential_IdentityBinding_EmptyCAFile(t *testing.T) {
639
641
caFile := filepath .Join (tempDir , "empty-ca.crt" )
640
642
641
643
// Create empty CA file
642
- err := os .WriteFile (caFile , []byte ("" ), 0644 )
644
+ err := os .WriteFile (caFile , []byte ("" ), 0600 )
643
645
require .NoError (t , err )
644
646
645
647
// Create transport recorder
@@ -658,7 +660,7 @@ func TestWorkloadIdentityCredential_IdentityBinding_CAFileRotation(t *testing.T)
658
660
659
661
// Create initial CA
660
662
initialCA , _ := createTestCA (t )
661
- err := os .WriteFile (caFile , initialCA , 0644 )
663
+ err := os .WriteFile (caFile , initialCA , 0600 )
662
664
require .NoError (t , err )
663
665
664
666
// Create transport recorder
@@ -669,7 +671,7 @@ func TestWorkloadIdentityCredential_IdentityBinding_CAFileRotation(t *testing.T)
669
671
require .NoError (t , err )
670
672
671
673
// Simulate file rotation - write empty file first (common during rotation)
672
- err = os .WriteFile (caFile , []byte ("" ), 0644 )
674
+ err = os .WriteFile (caFile , []byte ("" ), 0600 )
673
675
require .NoError (t , err )
674
676
675
677
// Force reload with empty file
@@ -681,7 +683,7 @@ func TestWorkloadIdentityCredential_IdentityBinding_CAFileRotation(t *testing.T)
681
683
682
684
// Write new CA content
683
685
newCA , _ := createTestCA (t )
684
- err = os .WriteFile (caFile , newCA , 0644 )
686
+ err = os .WriteFile (caFile , newCA , 0600 )
685
687
require .NoError (t , err )
686
688
687
689
// Force another reload
@@ -721,6 +723,59 @@ func TestWorkloadIdentityCredential_IdentityBinding_ConcurrentAccess(t *testing.
721
723
wg .Wait () // Should complete without hanging
722
724
}
723
725
726
+ func TestWorkloadIdentityCredential_IdentityBinding_ConcurrentAccessWithCARotation (t * testing.T ) {
727
+ tempDir := t .TempDir ()
728
+ caFile := filepath .Join (tempDir , "ca.crt" )
729
+
730
+ // Create initial CA
731
+ initialCA , _ := createTestCA (t )
732
+ err := os .WriteFile (caFile , initialCA , 0600 )
733
+ require .NoError (t , err )
734
+
735
+ // Create transport recorder
736
+ recorder := & identityBindingTransportRecorder {}
737
+
738
+ // Create identity binding transport
739
+ transport , err := newIdentityBindingTransport (caFile , "test.cluster.local" , "https://kubernetes.default.svc" , recorder )
740
+ require .NoError (t , err )
741
+
742
+ // Test concurrent access while rotating CA
743
+ var wg sync.WaitGroup
744
+
745
+ // Start concurrent readers
746
+ for i := 0 ; i < 5 ; i ++ {
747
+ wg .Add (1 )
748
+ go func () {
749
+ defer wg .Done ()
750
+ for j := 0 ; j < 10 ; j ++ {
751
+ _ , _ = transport .getTokenTransporter () // Should not panic or deadlock
752
+ time .Sleep (time .Millisecond * 10 ) // Small delay to create overlap
753
+ }
754
+ }()
755
+ }
756
+
757
+ // Start CA rotation goroutine
758
+ wg .Add (1 )
759
+ go func () {
760
+ defer wg .Done ()
761
+ for k := 0 ; k < 3 ; k ++ {
762
+ time .Sleep (time .Millisecond * 50 )
763
+ // Generate new CA and update file
764
+ newCA , _ := createTestCA (t )
765
+ err := os .WriteFile (caFile , newCA , 0600 )
766
+ if err != nil {
767
+ return // File might be locked during concurrent access
768
+ }
769
+ // Force reload by updating nextRead time
770
+ transport .mtx .Lock ()
771
+ transport .nextRead = time .Now ().Add (- time .Hour )
772
+ transport .mtx .Unlock ()
773
+ }
774
+ }()
775
+
776
+ wg .Wait () // Should complete without hanging or deadlock
777
+ }
778
+
724
779
func TestWorkloadIdentityCredential_IdentityBinding_TLSConfiguration (t * testing.T ) {
725
780
_ , caFile := createTestCA (t )
726
781
@@ -744,7 +799,7 @@ func TestWorkloadIdentityCredential_IdentityBinding_TLSConfiguration(t *testing.
744
799
func TestWorkloadIdentityCredential_IdentityBinding_BackwardCompatibility (t * testing.T ) {
745
800
// Test that standard workload identity still works when no identity binding variables are set
746
801
tempTokenFile := filepath .Join (t .TempDir (), "token" )
747
- err := os .WriteFile (tempTokenFile , []byte (tokenValue ), 0644 )
802
+ err := os .WriteFile (tempTokenFile , []byte (tokenValue ), 0600 )
748
803
require .NoError (t , err )
749
804
750
805
// Set up standard workload identity environment (no binding variables)
0 commit comments