feat(prefect-azure): managed-identity auth for Azure Database for PostgreSQL#22420
feat(prefect-azure): managed-identity auth for Azure Database for PostgreSQL#22420christopherahern wants to merge 6 commits into
Conversation
Add a Prefect plugin implementing set_database_connection_params that lets the Prefect server authenticate to Azure Database for PostgreSQL with a Microsoft Entra ID (managed identity) token instead of a password. Mirrors the prefect-aws RDS IAM plugin. - prefect_azure/plugins.py: async DefaultAzureCredential token as asyncpg password callable (auto-refresh) + SSL; gated by settings - prefect_azure/settings.py: AzureSettings().postgres.managed_identity (enabled, client_id) - register prefect.plugins entry point - tests + README usage section Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Mirror the prefect-aws RDS IAM docs (PrefectHQ#19580): add a managed-identity auth section to the prefect-azure integration page and a sibling subsection under self-hosted Database setup. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7750e2185c
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| in that image/environment): | ||
|
|
||
| ```bash | ||
| export PREFECT_INTEGRATIONS_AZURE_POSTGRES_MANAGED_IDENTITY_ENABLED=true |
There was a problem hiding this comment.
Document enabling the plugin system
Following this README snippet on a fresh server process sets only the Azure integration flag, but Prefect only invokes prefect.plugins database hooks when the plugin system itself is enabled. In that scenario the entry point is never loaded, so the password-less URL still reaches asyncpg without the token callback and authentication fails; add PREFECT_PLUGINS_ENABLED=true (or the supported legacy experiments alias) to this example.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Good catch — fixed in d84bc90. The example now enables the plugin system first, using the GA flag PREFECT_PLUGINS_ENABLED=true (prefect-azure targets prefect>=3.7) and referencing the pre-3.7 PREFECT_EXPERIMENTS_PLUGINS_ENABLED alias in a comment. Standardized the same way across the README, the integration docs, and the self-hosted guide (1560efe).
The managed-identity example set only the integration flag; the plugin hook won't load unless the plugin system itself is enabled, so the password-less URL would fail auth. Add PREFECT_PLUGINS_ENABLED=true (with the pre-3.7 experiments alias noted). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Use PREFECT_PLUGINS_ENABLED in the integration and self-hosted examples (prefect-azure targets prefect>=3.7), noting PREFECT_EXPERIMENTS_PLUGINS_ENABLED as the pre-3.7 alias in a comment. Consistent with the README example. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds a
set_database_connection_paramsplugin toprefect-azureso the Prefect server can authenticate to Azure Database for PostgreSQL using a Microsoft Entra ID (managed identity) token instead of a static password. This mirrors the mergedprefect-awsRDS IAM plugin (#19580).closes #22419
What's included
prefect_azure/plugins.py— the hook returns an asyncDefaultAzureCredentialtoken as the asyncpgpasswordcallable, plus an SSL context; gated by settings.prefect_azure/settings.py—AzureSettings().postgres.managed_identitywithenabledand optionalclient_id(PREFECT_INTEGRATIONS_AZURE_POSTGRES_MANAGED_IDENTITY_*).prefect.pluginsentry point (azure = "prefect_azure.plugins").How token expiration is handled
The
passwordsupplied to asyncpg is a callable, so it is invoked on every new connection.azure-identitycaches the token and refreshes it near expiry, and Azure Postgres validates the token only at login — so existing pooled connections are unaffected and new connections always receive a valid token. No manual refresh loop is required.Verification
Verified end to end against Azure Container Apps and an Entra-only Azure Database for PostgreSQL flexible server (
password_auth_enabled = false): the server connected, ran migrations, and served the API with no password anywhere in the system. Tokens were also confirmed to authenticate through Azure's built-in PgBouncer (General Purpose tier, port 6432).Checklist
mint.json. (N/A — no docs removed)🤖 Generated with Claude Code