Azure Workload Identity / SDK auth for `azure_sd_configs`
Is your feature request related to a problem? Please describe
vmagent's azure_sd_configs currently only supports two authentication_method values — OAuth (static client_secret) and ManagedIdentity. This is enforced in lib/promscrape/discovery/azure/api.go in getRefreshTokenFunc, which explicitly returns:
unsupported authentication_method: %q only OAuth and ManagedIdentity are supportedThat leaves no passwordless option for vmagent running outside an Azure-managed VM/AKS node — for example on a non-Azure Kubernetes cluster (Gardener, EKS, GKE, on-prem, etc.) that has been federated with an Azure AD application via workload identity federation (OIDC).
In practice this means every team running vmagent on non-Azure infrastructure that wants to discover Azure VMs / VMSS must:
- store an Azure AD client secret in a Kubernetes Secret and rotate it manually, or
- give up on
azure_sd_configsand use static targets / a separate discovery pipeline.
Prometheus already solves this cleanly: since prometheus/prometheus#13809 (Prometheus v2.52) its azure_sd_config accepts authentication_method: SDK and authentication_method: WorkloadIdentity, both of which use the standard Azure SDK credential chain (AZURE_CLIENT_ID, AZURE_TENANT_ID, AZURE_FEDERATED_TOKEN_FILE) injected by the Azure Workload Identity mutating webhook. This makes azure_sd_configs fully credential-less across clouds.
We already use the equivalent pattern for ec2_sd_configs in vmagent today: AWS_ROLE_ARN + AWS_WEB_IDENTITY_TOKEN_FILE are picked up transparently by lib/awsapi/config.go and the pod trusts a Gardener-managed OIDC issuer against AWS IAM. It works out of the box. Azure is the last piece missing to close the loop on passwordless cloud service discovery.
Describe the solution you'd like
Extend azure_sd_configs authentication_method to accept two new values, matching Prometheus:
| method | Behavior |
|---|---|
WorkloadIdentity |
Use azidentity.NewWorkloadIdentityCredential. Reads AZURE_CLIENT_ID, AZURE_TENANT_ID, and AZURE_FEDERATED_TOKEN_FILE from the environment (injected by the AKS/OSS Workload Identity webhook). No additional YAML fields required. |
SDK |
Use azidentity.NewDefaultAzureCredential. Honors the full DefaultAzureCredential chain (env vars, workload identity, managed identity, Azure CLI, …). Optional tenant_id narrows the credential to a specific tenant. |
Concretely, the change is a small addition to the auth switch in lib/promscrape/discovery/azure/api.go (getRefreshTokenFunc), plus the corresponding authentication_method validation in lib/promscrape/discovery/azure/azure.go (SDConfig). No new mandatory YAML fields are needed — everything the workload-identity path needs is already in the pod's environment thanks to the webhook. This is the same approach Prometheus took.
For reference, Prometheus' entire implementation of the two new methods fits in ~20 lines in discovery/azure/azure.go newCredential():
case authMethodWorkloadIdentity:
cred, err := azidentity.NewWorkloadIdentityCredential(&azidentity.WorkloadIdentityCredentialOptions{
ClientOptions: policyClientOptions,
})
// …
case authMethodSDK:
opts := &azidentity.DefaultAzureCredentialOptions{ClientOptions: policyClientOptions}
if cfg.TenantID != "" {
opts.TenantID = cfg.TenantID
}
cred, err := azidentity.NewDefaultAzureCredential(opts)
// …The Azure SDK is already an indirect dependency of vmagent (via lib/backup/azremote etc.), so no new heavyweight dependency is introduced.
Example config after the change:
scrape_configs:
- job_name: azure-vms
azure_sd_configs:
- subscription_id: 00000000-0000-0000-0000-000000000000
authentication_method: WorkloadIdentity
# tenant_id/client_id/client_secret intentionally omitted —
# AZURE_CLIENT_ID / AZURE_TENANT_ID / AZURE_FEDERATED_TOKEN_FILE
# are injected by the Azure Workload Identity webhook.Backwards compatibility: the existing OAuth and ManagedIdentity paths and their YAML fields remain unchanged. WorkloadIdentity and SDK are strictly additive.
Describe alternatives you've considered
- Keep using
OAuthwith a rotatedclient_secret. Works today but leaves a long-lived shared secret in a Kubernetes Secret. Rotation has to be built and monitored externally. This is exactly what workload identity is designed to eliminate. - Run vmagent on an Azure VM / AKS node so
ManagedIdentityworks. Not an option when the vmagent fleet lives outside Azure (e.g. Gardener-managed Kubernetes on GCP/AWS/on-prem federated to Azure AD). - Sidecar that mints a token and rewrites
vmagent's config. Fragile, adds a moving part, and reintroduces failure modes that the SDK credential chain already handles (token refresh, retries, clock skew). - Fork/patch
vmagentlocally. Doable but obviously undesirable for an OSS-first stack — hence this feature request.
Additional information
Prior art / references:
- Prometheus
azure_sd_configdocs (SDK + WorkloadIdentity): https://prometheus.io/docs/prometheus/latest/configuration/configuration/#azure_sd_config - Prometheus implementation (
newCredentialswitch): https://github.com/prometheus/prometheus/blob/main/discovery/azure/azure.go - Azure Workload Identity project (webhook that injects
AZURE_*env vars and the projected token file): https://azure.github.io/azure-workload-identity/ - Azure SDK
azidentitydocs forWorkloadIdentityCredentialandDefaultAzureCredential: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity - The original VictoriaMetrics feature request that introduced
azure_sd_configsin v1.79.0: #1364
Files most likely touched by the change:
lib/promscrape/discovery/azure/azure.go— extendSDConfig'sauthentication_methodvalidation.lib/promscrape/discovery/azure/api.go— extend the switch ingetRefreshTokenFunc(or refactor to return aTokenCredentialand useazidentityuniformly, similar to how Prometheus did it).docs/sd_configs.md— document the two new values.CHANGELOG.md— one line undervmagent.
Concrete use case driving this request:
We run vmagent on Gardener-managed Kubernetes clusters (not on Azure). Each cluster has its own managed OIDC issuer. For AWS we've already wired vmagent up passwordlessly via AWS_ROLE_ARN + AWS_WEB_IDENTITY_TOKEN_FILE (works out of the box with the existing ec2_sd_configs). For Azure the only blocker is that azure_sd_configs doesn't recognize the workload-identity env vars — with this feature we'd be able to remove the last remaining static client secrets.
Happy to help test a PR against our clusters.
*Disclaimer: feature request was created with the help of AI
Source: VictoriaMetrics/VictoriaMetrics