discovery/azure: fix system managed identity when client_id is empty

When using ManagedIdentity authentication with system-assigned identity,
the client_id field is intentionally left empty. However, the current code
unconditionally sets options.ID = azidentity.ClientID(cfg.ClientID), which
passes an empty string instead of nil. The Azure SDK treats an empty
ClientID as a request for a user-assigned identity with an empty client ID,
rather than falling back to system-assigned identity.

Fix by only setting options.ID when cfg.ClientID is non-empty, matching the
pattern already used in storage/remote/azuread/azuread.go.

Fixes #16634

Signed-off-by: Ogulcan Aydogan <ogulcanaydogan@hotmail.com>
This commit is contained in:
Ogulcan Aydogan 2026-03-19 10:49:17 +00:00
parent a9d90952ba
commit 7bbff490a3
2 changed files with 26 additions and 1 deletions

View File

@ -298,7 +298,10 @@ func newCredential(cfg SDConfig, policyClientOptions policy.ClientOptions) (azco
}
credential = azcore.TokenCredential(workloadIdentityCredential)
case authMethodManagedIdentity:
options := &azidentity.ManagedIdentityCredentialOptions{ClientOptions: policyClientOptions, ID: azidentity.ClientID(cfg.ClientID)}
options := &azidentity.ManagedIdentityCredentialOptions{ClientOptions: policyClientOptions}
if cfg.ClientID != "" {
options.ID = azidentity.ClientID(cfg.ClientID)
}
managedIdentityCredential, err := azidentity.NewManagedIdentityCredential(options)
if err != nil {
return nil, err

View File

@ -24,6 +24,7 @@ import (
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/arm"
azfake "github.com/Azure/azure-sdk-for-go/sdk/azcore/fake"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5"
fake "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5/fake"
@ -490,6 +491,27 @@ func TestNewAzureResourceFromID(t *testing.T) {
}
}
func TestNewCredentialManagedIdentity(t *testing.T) {
// Test that system-assigned managed identity (empty ClientID) creates
// a valid credential. Previously, an empty ClientID was passed as
// azidentity.ClientID("") which is not nil and caused Azure SDK to
// look up a non-existent user-assigned identity instead of falling
// back to system-assigned identity.
cfg := SDConfig{
AuthenticationMethod: authMethodManagedIdentity,
ClientID: "",
}
cred, err := newCredential(cfg, policy.ClientOptions{})
require.NoError(t, err)
require.NotNil(t, cred)
// Test that user-assigned managed identity (non-empty ClientID) also works.
cfg.ClientID = "00000000-0000-0000-0000-000000000000"
cred, err = newCredential(cfg, policy.ClientOptions{})
require.NoError(t, err)
require.NotNil(t, cred)
}
func TestAzureRefresh(t *testing.T) {
tests := []struct {
scenario string