Skip to main content

Command Palette

Search for a command to run...

🔐 Proactive Azure App Security: How to Automate Secret Expiry Alerts with PowerShell

Updated
4 min read
🔐 Proactive Azure App Security: How to Automate Secret Expiry Alerts with PowerShell
M

My name is Marco Notarrigo and I am a System Engineer with a passion for Technology, Math and Computer Science. Since I was a kid, I began programming on 8-bit computers such as the Apple II and the Commodore 64. As my passion for technology and computer science has grown over the years, it has turned into a job for me.

Over the last years, I have gained experience in DevOps, Security and Cloud Computing, making me well-versed in the principles and practices of these critical fields.

Therefore, I want to share this passion with all of you who follow me and hope to inspire you to pursue your interests.

If you're managing Azure App Registrations across multiple environments or teams, you've probably dealt with expiring client secrets at the worst possible time; usually right before something breaks. 😅

Let’s fix that.

In this post, I’ll walk you through a PowerShell solution I built to automatically audit Azure App secrets and notify you before they expire; with a clean HTML report and optional email alerts.


🚨 Why You Need This

App secrets don’t last forever (nor should they). They typically expire in 6–12 months, but there’s no built-in alerting system from Azure unless you build one yourself.

Miss a secret rotation? Suddenly, your production app can’t authenticate, and you’re scrambling to debug authentication failures during a deploy.

This script automates:

✅ Checking all Azure App Registrations
✅ Identifying secrets expiring in the next N days
✅ Generating a sortable HTML report (When running script with UseLocalParameters)
✅ Sending it via email


🛠️ How It Works

The script uses the Microsoft Graph API to authenticate using a service principal (client ID/secret) and fetch all application registrations. It then;

  1. Filters secrets that expire within a configurable number of days (default: 30)

  2. Generates a styled HTML report (saves it locally)

  3. Sends an email report using Microsoft Graph's sendMail endpoint

Bonus: If you include a line like NotifyEmail = team@yourdomain.com in the app’s Notes field, it’ll extract that automatically and show it in the report.


🚀 Getting Started

🧾 Prerequisites

1. App Registration in Entra ID

  • Create an app in Entra ID > App Registrations

  • Assign API Permissions:

    • Application.Read.All

    • Directory.Read.All

    • Mail.Send

2. Licensed Sender Mailbox

Ensure your app is authorized to send mail on behalf of a licensed user, such as noreply@yourdomain.com.

3. Installed modules;

* Microsoft.Graph.Applications

* Microsoft.Graph.Users

* Microsoft.Graph.Authentication

4. Optional: Azure Automation Setup

Store sensitive variables as Automation Variables:

  • ClientID

  • ClientSecret

  • TenantID

  • WarningDays

  • SenderEmail

  • ToEmail


💻 Local Usage

Here’s how to run it locally with manual parameters:

powershellCopyEdit.\Notify-AppSecretExpire.ps1 `
    -ClientId "<your-client-id>" `
    -ClientSecret "<your-client-secret>" `
    -TenantId "<your-tenant-id>" `
    -SenderEmail "noreply@yourdomain.com" `
    -ToEmail "admin@yourdomain.com" `
    -OutputPath "C:\Reports\AppSecretsExpirationReport.html" `
    -UseLocalParameters

☁️ Azure Automation Usage

If you're running this in an Azure Automation Account, you don’t need to pass parameters. Instead, define Automation Variables like:

  • ClientId

  • ClientSecret

  • TenantId

  • SenderEmail

  • ToEmail

The script auto-detects that it's running in Automation and pulls these values in.


📄 What the Report Looks Like

The script outputs a responsive, clean HTML report with:

  • App name and ID

  • Secret name (linked to the Azure portal)

  • Expiration date and days remaining

  • Optional NotifyEmail extracted from notes

  • Clickable column headers for sorting

Here’s a preview of the UI;

(This is an example of the generated HTML report)


🔗 GitHub Repository

All the code is available here:
👉 GitHub – secret-expiry-alert


🔔 New Feature: Notify Application Owners via NotifyEmail

In the latest version of the script (last edited June 20, 2025), there’s now support for automatically notifying the responsible team for each Azure AD App Registration using a custom tag in the app’s branding properties.

✅ How It Works

  • You can specify a NotifyEmail tag in the Notes field under Branding & properties of an App Registration:

      NotifyEmail=team-azureops@yourdomain.com
    
  • When the script runs, it searches for this tag in Internal Notes and extracts the email address.

  • If credentials (client secrets or certificates) are expiring within the configured warning window (e.g. 30 days), the script:

    • Sends a HTML report to the global ToEmail.

    • Sends a separate, targeted email to each unique NotifyEmail recipient with only the credentials related to their apps.

✏️ Example Usage in Branding properties:

  • Go to Azure Portal → Entra ID → App Registrations → [Your App] → Branding & Properties

  • In the Internal Notes add:

      NotifyEmail=team-azureops@yourdomain.com
    

📄 Script Changes Summary

FeatureDescription
NotifyEmail parsingReads from Internal Notes for NotifyEmail=<email>
Per‑team alertsSends a separate email to each unique NotifyEmail address with only relevant expiring credentials
Fallback behaviorIf no NotifyEmail is defined, a credential expiry still appears in the global report, but no separate email is sent

💡 Benefits of Using NotifyEmail

  • Eliminates alert noise by notifying only those who need to act.

  • Ensures accountability by routing alerts to the correct team.

  • Simplifies onboarding of new apps—just define your tag once and the automation handles the rest.


🤝 Contributions Welcome

Have ideas? Found a bug? Want to add secret expiration to KeyVault secrets too?
Open an issue or send a PR; I’d love to collaborate.


🙌 Final Thoughts

Security is proactive; not reactive.
Automating app secret monitoring is one small investment that saves a lot of future pain.

Let me know if you try this in your environment or have feedback!