Key Vault Secret Expiry Monitor
Scheduled flow calls the Azure Key Vault REST API via HTTP to enumerate all secrets and certificates, checks expiration dates, and flags any expiring within 30 days. Logs expiring items to a Dataverse tracking table and posts a Teams alert to the security channel with secret name, vault name, and days remaining. Sends an Outlook summary to the admin responsible for rotation.
Provided as-is, without warranty of any kind. Review and test each pattern in a non-production environment before deploying it to live automations. See our Terms.
Overview
A scheduled cloud flow that scans an Azure Key Vault on a weekly cadence, identifies any secrets or keys whose validityEndTime falls inside a configurable expiry threshold, writes one Dataverse audit record per expiring item, and notifies the security team via Microsoft Teams and a high-importance Outlook email summary. When nothing is expiring, the flow finishes silently — no inbox/channel noise on healthy weeks.
Use Case
Secrets and keys that quietly expire in production cause page-quality outages. This flow gives the security and platform teams a no-touch weekly heads-up so rotations can be scheduled before anything breaks.
The flow is ideal for teams that:
- Surfaces both secrets and keys (separate connector calls, unified report)
- Tunable lead time via an environment variable (default: 30 days)
- Logs to Dataverse for trend analysis and historical audit
- Sends a single consolidated Teams + email digest per run
Flow Architecture
Run Weekly Expiry Scan
RecurrenceMondays, 8:00 AM Eastern.
Initialize working variables
InitializeVariable (×8)Hydrate 6 environment variables (varKeyVaultName, varExpiryThresholdDays, varTrackingTable, varAdminTeamsGroupId, varAdminTeamsChannelId, varSecurityTeamEmail) and 2 working accumulators (varExpiringCount, varHtmlRows).
Initialize varDetectedOn
InitializeVariableStamp the run timestamp once for consistent audit rows across the run.
List Vault Secrets
Azure Key Vault — ListSecretsEnumerate every secret in the configured Key Vault.
Loop Through Secrets
ForeachFor each secret in body('List_Vault_Secrets')?['value']: evaluate the expiry threshold and triage the item.
If Secret Within Threshold
If conditionCompares each secret's validityEndTime against addDays(utcNow(), varExpiryThresholdDays).
- Compute Days Remaining — Compose: ticks-based days-until-expiry math.
- Append HTML Row — AppendToString builds one row of the consolidated summary table.
- Increment Count — IncrementVariable on varExpiringCount.
- Create Audit Record — Dataverse CreateRecord into the tracking table with name, item type, vault name, expiration date, days remaining, and detected-on timestamp.
Environment Variables
| Schema name | Type | Default | Description |
|---|---|---|---|
| flowlibs_KeyVaultName | String | kv-flowlibs-demo | Friendly vault name embedded in alerts and audit rows. The underlying connection points to the actual Key Vault. |
| flowlibs_SecretExpiryThresholdDays | String | 30 | Number of days ahead of expiration to flag secrets and keys. |
| flowlibs_KeyVaultExpiryTrackingTable | String | flowlibs_keyvaultexpiringitems | Dataverse entity set name used as the audit log destination. |
| flowlibs_AdminTeamsGroupId | String | <configure> | Microsoft Teams Group/Team ID where the channel post should be made. |
| flowlibs_AdminTeamsChannelId | String | <configure> | Microsoft Teams Channel ID inside the Group above where the headline message lands. |
| flowlibs_SecurityTeamEmail | String | security@yourcompany.com | Recipient for the high-importance summary email. |
Connectors & Connections
| Connector | API name | Actions used |
|---|---|---|
| Azure Key Vault | shared_keyvault | ListSecrets ListKeys |
| Microsoft Dataverse | shared_commondataserviceforapps | CreateRecord (called twice — once per loop) |
| Microsoft Teams | shared_teams | PostMessageToConversation |
| Office 365 Outlook | shared_office365 | SendEmailV2 (Importance: High) |
Note — All connections are referenced as solution connection references; the flow is portable between environments as long as a connection is mapped at import time.
Customization Guide
Almost every realistic variant of this flow can be implemented by changing environment variable values. A few cases require small edits inside the flow definition — those are called out explicitly below.
- Change the vault
- Re-authorize the shared_keyvault connection against the target vault, then update flowlibs_KeyVaultName to match for clearer alert text.
- Change the lead time
- Edit the flowlibs_SecretExpiryThresholdDays current value. No JSON changes needed — the variable feeds both the threshold filter and the days-remaining math.
- Change the cadence
- Open the Run Weekly Expiry Scan trigger and adjust frequency / interval / day-of-week / hour. The flow uses Eastern Standard Time by default.
- Change recipients
- Update flowlibs_AdminTeamsGroupId, flowlibs_AdminTeamsChannelId, or flowlibs_SecurityTeamEmail current values. The variables are hydrated once at the top of every run.
- Change the audit destination
- Point flowlibs_KeyVaultExpiryTrackingTable to a different entity set name. Both CreateRecord actions reference the env var via the variable, so retargeting is a single edit.
Key Expressions
The flow is intentionally light on Power Fx / WDL gymnastics — the heaviest expressions are the branch-name concatenation and the approval outcome check. They are listed below in the order they appear in the flow.
EXPR.01Expiry threshold upper bound
Builds the upper bound for the expiry window at runtime. Compared against validityEndTime from each secret/key.
EXPR.02Days-remaining math
Days-remaining math using ticks. 864000000000 ticks-per-day converts the delta to whole days for the audit row and the HTML table.
EXPR.03Threshold check field
Field used for the threshold comparison. The Key Vault connector populates validityEndTime on every SecretMetadata / KeyMetadata payload returned by ListSecrets / ListKeys — no extra GetSecretMetadata round-trip is needed.
Comments
Sign in to join the conversation.
Sign inNo comments yet. Be the first to share your experience with this flow.