Skip to content

Azure managed-identity credentials on the query path never refresh (#600 class, probable live bug) #605

Description

@xe-nvdk

Summary

Azure managed-identity credentials on the DuckDB query path are resolved once at CREATE SECRET time and never refreshed — the same class as #600 (S3/IRSA ExpiredToken ~1h after start), which is now fixed for every AWS source (#601). Azure has no equivalent refresher: configureAzureAccess and ConfigureAzure emit a PROVIDER CREDENTIAL_CHAIN Azure secret exactly once (internal/database/duckdb.go), and managed-identity OAuth tokens expire (typically 1–24h).

This is a probable live bug, not an enhancement: any deployment using storage.backend=azure (or an Azure cold tier) with managed identity — no account key, no connection string — and a process outliving the token should lose DuckDB query reads exactly like #600, while ingest keeps working (internal/storage/azure.go uses azidentity.NewDefaultAzureCredential, which refreshes). We have not reproduced it live; the mechanism is identical to the S3 case that was reproduced and fixed.

Why it didn't ship with #601

The AWS fix hands DuckDB KEY_ID/SECRET/SESSION_TOKEN — a verified static-credential slot. The Azure secret is CONNECTION_STRING/ACCOUNT_KEY-shaped; there is no verified way to emit a managed-identity OAuth bearer token into a DuckDB Azure secret. That emission mechanism is the open question, not the credential resolution — azidentity is already a direct dependency and ingest already uses the right chain.

Proposal sketch

  1. Verify what DuckDB's azure extension accepts for token-based auth (e.g. a secret with PROVIDER access_token, if supported by the bundled version) — the IRSA: DuckDB query path fails with ExpiredToken ~1h after start (credential_chain never refreshes) #600 lesson: test against the bundled engine before designing.
  2. If a token slot exists: reuse the Extend #600 credential refresher to all expiring credential sources (instance roles, Pod Identity) via a CanExpire gate #601 refresher machinery (it is provider-agnostic — awsCredentialsProvider seam + planners) with an azidentity-backed provider.
  3. If not: interim honesty is already shipping via Surface S3 credential/refresher state in /health — read path can be down for hours behind green probes #603 (credentials: unmanaged_chain, state: unknown in /health), and the workaround is account keys / SAS with external rotation.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions