Skip to content

Commit 9c24697

Browse files
committed
fix: prefer AZURE_FEDERATED_TOKEN_FILE over hardcoded OIDC token path
oidcAuth() defaulted the OIDC token file path to a hardcoded constant matching the azure-workload-identity webhook's old mount location. The webhook moved that path in v1.6.0 (a documented breaking change) and now sets AZURE_FEDERATED_TOKEN_FILE to the current location instead. Read AZURE_FEDERATED_TOKEN_FILE when no explicit oidcTokenFilePath is set, falling back to the historical hardcoded default only if the env var is also unset, so the provider isn't tied to one specific webhook mount path. Fixes #1280
1 parent 1a5c217 commit 9c24697

2 files changed

Lines changed: 73 additions & 2 deletions

File tree

internal/clients/azure.go

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"context"
99
"encoding/json"
1010
"net/http"
11+
"os"
1112
"strings"
1213
"sync/atomic"
1314

@@ -61,8 +62,15 @@ const (
6162
keyStorageUseAzureAD = "storage_use_azuread"
6263
keyPostgreSQLFlexibleServer = "postgresql_flexible_server"
6364
keyPSQLRestartServerOnConfigurationChange = "restart_server_on_configuration_value_change"
64-
// Default OidcTokenFilePath
65+
// Default OidcTokenFilePath, used only if AZURE_FEDERATED_TOKEN_FILE is
66+
// not set and no explicit oidcTokenFilePath is configured. The azure
67+
// workload identity webhook owns this path and has changed it before
68+
// (see https://github.com/Azure/azure-workload-identity/releases/tag/v1.6.0),
69+
// so AZURE_FEDERATED_TOKEN_FILE is the source of truth whenever available.
6570
defaultOidcTokenFilePath = "/var/run/secrets/azure/tokens/azure-identity-token"
71+
// envAzureFederatedTokenFile is set by the azure workload identity
72+
// webhook to the current projected token path.
73+
envAzureFederatedTokenFile = "AZURE_FEDERATED_TOKEN_FILE"
6674
)
6775

6876
var (
@@ -260,8 +268,14 @@ func oidcAuth(pcSpec *namespacedv1beta1.ProviderConfigSpec, ps *terraform.Setup)
260268
if pcSpec.ClientID == nil || len(*pcSpec.ClientID) == 0 {
261269
return errors.New(errClientIDNotSet)
262270
}
263-
// OIDC Token File Path defaults to a projected-volume path mounted in the pod running in the AKS cluster, when workload identity is enabled on the pod.
271+
// OIDC Token File Path: an explicit oidcTokenFilePath always wins. Otherwise
272+
// prefer AZURE_FEDERATED_TOKEN_FILE, which the azure workload identity webhook
273+
// sets to wherever it actually projected the token, falling back to the
274+
// historical hardcoded default only if that env var isn't set.
264275
ps.Configuration[keyOidcTokenFilePath] = defaultOidcTokenFilePath
276+
if tokenFile := os.Getenv(envAzureFederatedTokenFile); tokenFile != "" {
277+
ps.Configuration[keyOidcTokenFilePath] = tokenFile
278+
}
265279
if pcSpec.OidcTokenFilePath != nil {
266280
ps.Configuration[keyOidcTokenFilePath] = *pcSpec.OidcTokenFilePath
267281
}

internal/clients/azure_test.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ package clients
77
import (
88
"testing"
99

10+
"github.com/crossplane/upjet/v2/pkg/terraform"
1011
"github.com/google/go-cmp/cmp"
12+
13+
namespacedv1beta1 "github.com/upbound/provider-azure/v2/apis/namespaced/v1beta1"
1114
)
1215

1316
func Test_armServiceFromPath(t *testing.T) {
@@ -45,3 +48,57 @@ func Test_armServiceFromPath(t *testing.T) {
4548
})
4649
}
4750
}
51+
52+
func Test_oidcAuth_tokenFilePath(t *testing.T) {
53+
subID, tenantID, clientID := "sub", "tenant", "client"
54+
explicitPath := "/explicit/path/azure-identity-token"
55+
envPath := "/var/run/secrets/azure/wi/token/azure-identity-token"
56+
57+
cases := map[string]struct {
58+
oidcTokenFilePath *string
59+
envValue string
60+
envSet bool
61+
want string
62+
}{
63+
"explicit_path_wins_over_env": {
64+
oidcTokenFilePath: &explicitPath,
65+
envValue: envPath,
66+
envSet: true,
67+
want: explicitPath,
68+
},
69+
"env_used_when_no_explicit_path": {
70+
envValue: envPath,
71+
envSet: true,
72+
want: envPath,
73+
},
74+
"falls_back_to_default_when_env_unset": {
75+
want: defaultOidcTokenFilePath,
76+
},
77+
"falls_back_to_default_when_env_empty": {
78+
envValue: "",
79+
envSet: true,
80+
want: defaultOidcTokenFilePath,
81+
},
82+
}
83+
for name, tc := range cases {
84+
t.Run(name, func(t *testing.T) {
85+
if tc.envSet {
86+
t.Setenv(envAzureFederatedTokenFile, tc.envValue)
87+
}
88+
pcSpec := &namespacedv1beta1.ProviderConfigSpec{
89+
SubscriptionID: &subID,
90+
TenantID: &tenantID,
91+
ClientID: &clientID,
92+
OidcTokenFilePath: tc.oidcTokenFilePath,
93+
}
94+
ps := &terraform.Setup{Configuration: terraform.ProviderConfiguration{}}
95+
if err := oidcAuth(pcSpec, ps); err != nil {
96+
t.Fatalf("oidcAuth() returned unexpected error: %v", err)
97+
}
98+
got, _ := ps.Configuration[keyOidcTokenFilePath].(string)
99+
if diff := cmp.Diff(tc.want, got); diff != "" {
100+
t.Errorf("oidc_token_file_path mismatch (-want +got):\n%s", diff)
101+
}
102+
})
103+
}
104+
}

0 commit comments

Comments
 (0)