Skip to content

Commit f7ac5a7

Browse files
Copilotbcho
andcommitted
Address code review feedback: check errors, use 0600 permissions, add concurrent CA rotation test
Co-authored-by: bcho <[email protected]>
1 parent 7153143 commit f7ac5a7

File tree

1 file changed

+73
-18
lines changed

1 file changed

+73
-18
lines changed

sdk/azidentity/workload_identity_test.go

Lines changed: 73 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ func TestWorkloadIdentityCredential_Options(t *testing.T) {
300300
// createTestCA generates a self-signed CA certificate for testing
301301
func createTestCA(t *testing.T) ([]byte, string) {
302302
t.Helper()
303-
303+
304304
// Generate private key
305305
priv, err := rsa.GenerateKey(rand.Reader, 2048)
306306
require.NoError(t, err)
@@ -316,11 +316,11 @@ func createTestCA(t *testing.T) ([]byte, string) {
316316
StreetAddress: []string{""},
317317
PostalCode: []string{""},
318318
},
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,
324324
BasicConstraintsValid: true,
325325
}
326326

@@ -333,7 +333,7 @@ func createTestCA(t *testing.T) ([]byte, string) {
333333

334334
// Write to temporary file
335335
caFile := filepath.Join(t.TempDir(), "ca.crt")
336-
err = os.WriteFile(caFile, certPEM, 0644)
336+
err = os.WriteFile(caFile, certPEM, 0600)
337337
require.NoError(t, err)
338338

339339
return certPEM, caFile
@@ -448,7 +448,7 @@ func TestWorkloadIdentityCredential_IdentityBinding_Detection(t *testing.T) {
448448

449449
// Set up required workload identity variables
450450
tempTokenFile := filepath.Join(t.TempDir(), "token")
451-
err := os.WriteFile(tempTokenFile, []byte("test-token"), 0644)
451+
err := os.WriteFile(tempTokenFile, []byte("test-token"), 0600)
452452
require.NoError(t, err)
453453

454454
t.Setenv(azureClientID, fakeClientID)
@@ -501,7 +501,7 @@ func TestWorkloadIdentityCredential_IdentityBinding_InvalidCAFile(t *testing.T)
501501
func TestWorkloadIdentityCredential_IdentityBinding_InvalidCAContent(t *testing.T) {
502502
// Create invalid CA file
503503
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)
505505
require.NoError(t, err)
506506

507507
t.Setenv(azureKubernetesTokenEndpoint, "https://kubernetes.default.svc")
@@ -527,7 +527,8 @@ func TestWorkloadIdentityCredential_IdentityBinding_TransportRedirection(t *test
527527
require.NoError(t, err)
528528

529529
// 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)
531532
_, _ = transport.Do(req)
532533

533534
// 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
537538
require.Len(t, requests, 0, "Token requests should not go through fallback transport")
538539

539540
// 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)
541543
_, _ = transport.Do(req2)
542544

543545
// Verify fallback transport was used for non-token request
@@ -597,7 +599,7 @@ func TestWorkloadIdentityCredential_IdentityBinding_CAReloading(t *testing.T) {
597599

598600
// Create initial CA
599601
initialCA, _ := createTestCA(t)
600-
err := os.WriteFile(caFile, initialCA, 0644)
602+
err := os.WriteFile(caFile, initialCA, 0600)
601603
require.NoError(t, err)
602604

603605
// Create transport recorder
@@ -619,7 +621,7 @@ func TestWorkloadIdentityCredential_IdentityBinding_CAReloading(t *testing.T) {
619621

620622
// Create new CA and update file
621623
newCA, _ := createTestCA(t)
622-
err = os.WriteFile(caFile, newCA, 0644)
624+
err = os.WriteFile(caFile, newCA, 0600)
623625
require.NoError(t, err)
624626

625627
// Get transport again to trigger reload
@@ -639,7 +641,7 @@ func TestWorkloadIdentityCredential_IdentityBinding_EmptyCAFile(t *testing.T) {
639641
caFile := filepath.Join(tempDir, "empty-ca.crt")
640642

641643
// Create empty CA file
642-
err := os.WriteFile(caFile, []byte(""), 0644)
644+
err := os.WriteFile(caFile, []byte(""), 0600)
643645
require.NoError(t, err)
644646

645647
// Create transport recorder
@@ -658,7 +660,7 @@ func TestWorkloadIdentityCredential_IdentityBinding_CAFileRotation(t *testing.T)
658660

659661
// Create initial CA
660662
initialCA, _ := createTestCA(t)
661-
err := os.WriteFile(caFile, initialCA, 0644)
663+
err := os.WriteFile(caFile, initialCA, 0600)
662664
require.NoError(t, err)
663665

664666
// Create transport recorder
@@ -669,7 +671,7 @@ func TestWorkloadIdentityCredential_IdentityBinding_CAFileRotation(t *testing.T)
669671
require.NoError(t, err)
670672

671673
// Simulate file rotation - write empty file first (common during rotation)
672-
err = os.WriteFile(caFile, []byte(""), 0644)
674+
err = os.WriteFile(caFile, []byte(""), 0600)
673675
require.NoError(t, err)
674676

675677
// Force reload with empty file
@@ -681,7 +683,7 @@ func TestWorkloadIdentityCredential_IdentityBinding_CAFileRotation(t *testing.T)
681683

682684
// Write new CA content
683685
newCA, _ := createTestCA(t)
684-
err = os.WriteFile(caFile, newCA, 0644)
686+
err = os.WriteFile(caFile, newCA, 0600)
685687
require.NoError(t, err)
686688

687689
// Force another reload
@@ -721,6 +723,59 @@ func TestWorkloadIdentityCredential_IdentityBinding_ConcurrentAccess(t *testing.
721723
wg.Wait() // Should complete without hanging
722724
}
723725

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+
724779
func TestWorkloadIdentityCredential_IdentityBinding_TLSConfiguration(t *testing.T) {
725780
_, caFile := createTestCA(t)
726781

@@ -744,7 +799,7 @@ func TestWorkloadIdentityCredential_IdentityBinding_TLSConfiguration(t *testing.
744799
func TestWorkloadIdentityCredential_IdentityBinding_BackwardCompatibility(t *testing.T) {
745800
// Test that standard workload identity still works when no identity binding variables are set
746801
tempTokenFile := filepath.Join(t.TempDir(), "token")
747-
err := os.WriteFile(tempTokenFile, []byte(tokenValue), 0644)
802+
err := os.WriteFile(tempTokenFile, []byte(tokenValue), 0600)
748803
require.NoError(t, err)
749804

750805
// Set up standard workload identity environment (no binding variables)

0 commit comments

Comments
 (0)