
Microsoft to Roll out Automatic Registration for External Authentication Methods
August 6, 2025Deploy LangChain applications to Azure App Service
August 6, 2025In today’s cloud-first environments, maintaining strong security posture requires not just visibility but real-time awareness of changes. This blog walks you through a practical solution to monitor and alert on Microsoft Defender for Cloud recommendations that transition from Healthy to Unhealthy status. By combining the power of Kusto Query Language (KQL) with the automation capabilities of Azure Logic Apps, you’ll learn how to:
- Query historical and current security recommendation states using KQL
- Detect resources that have degraded in compliance over the past 14 days
- Send automatic email alerts when issues are detected
- Customize the email content with HTML tables for easy readability
- Handle edge cases, like sending a “no issues found” email when nothing changes
Whether you’re a security engineer, cloud architect, or DevOps practitioner, this solution helps you close the gap between detection and response and ensure that no security regressions go unnoticed.
Prerequisites
Before implementing the monitoring and alerting solution described in this blog, ensure the following prerequisites are met:
- Microsoft Defender for Cloud is Enabled
- Defender for Cloud must be enabled on the target Azure subscriptions/management group.
- It should be actively monitoring your resources (VMs, SQL, App Services, etc.).
- Make sure the recommendations are getting generated.
- Continuous Export is Enabled for Security Recommendations
- Continuous export should be configured to send security recommendations to a Log Analytics workspace.
- This enables you to query historical recommendation state using KQL.
You can configure continuous export by going to:
Defender for Cloud → Environment settings → Select Subscription → Continuous Export
Then enable export for Security Recommendations to your chosen Log Analytics workspace.
Detailed guidance on setting up continuous export can be found here: Set up continuous export in the Azure portal – Microsoft Defender for Cloud | Microsoft Learn
High-Level Summary of the Automation Flow
This solution provides a fully automated way to track and alert on security posture regressions in Microsoft Defender for Cloud. By integrating KQL queries with Azure Logic Apps, you can stay informed whenever a resource’s security recommendation changes from Healthy to Unhealthy.
Here’s how the flow works:
- Microsoft Defender for Cloud evaluates Azure resources and generates security recommendations based on best practices and potential vulnerabilities.
- These recommendations are continuously exported to a Log Analytics workspace, enabling historical analysis over time.
- A scheduled Logic App runs a KQL query that compares:
- Recommendations from ~14 days ago (baseline),
- With those from the last 7 days (current state).
- If any resources are found to have shifted from Healthy to Unhealthy, the Logic App:
- Formats the data into an HTML table, and
- Sends an email alert with the affected resource details and recommendation metadata.
- If no such changes are found, an optional email can be sent stating that all monitored resources remain compliant — providing peace of mind and audit trail coverage.
This approach enables teams to proactively monitor security drift, reduce manual oversight, and ensure timely remediation of emerging security issues.
Logic Apps Flow
This Logic App is scheduled to trigger daily. It runs a KQL query against a Log Analytics workspace to identify resources that have changed from Healthy to Unhealthy status over the past two weeks. If such changes are detected, the results are formatted into an HTML table and emailed to the security team for review and action.
KQL Query used here:
// Get resources that are currently unhealthy within the last 7 days
let now_unhealthy =
SecurityRecommendation
| where TimeGenerated > ago(7d)
| where RecommendationState == “Unhealthy”
// For each resource and recommendation, get the latest record
| summarize arg_max(TimeGenerated, *) by AssessedResourceId, RecommendationDisplayName;
// Get resources that were healthy approximately 14 days ago (between 12 and 14 days ago)
let past_healthy =
SecurityRecommendation
| where TimeGenerated between (ago(14d) .. ago(12d))
| where RecommendationState == “Healthy”
// For each resource and recommendation, get the latest record in that time window
| summarize arg_max(TimeGenerated, *) by AssessedResourceId, RecommendationDisplayName;
// Join current unhealthy resources with their healthy state 14 days ago
now_unhealthy
| join kind=inner past_healthy on AssessedResourceId, RecommendationDisplayName
| project
AssessedResourceId, // Unique ID of the assessed resource
RecommendationDisplayName, // Name of the security recommendation
RecommendationSeverity, // Severity level of the recommendation
Description, // Description explaining the recommendation
State_14DaysAgo = RecommendationState1,// Resource state about 14 days ago (should be “Healthy”)
State_Recent = RecommendationState, // Current resource state (should be “Unhealthy”)
Timestamp_14DaysAgo = TimeGenerated1, // Timestamp from ~14 days ago
Timestamp_Recent = TimeGenerated // Most recent timestamp
Once this logic app executes successfully, you’ll get an email as per your configuration. This email includes:
- A brief introduction explaining the situation.
- The number of affected recommendations.
- A formatted HTML table with detailed information:
- AssessedResourceId: The full Azure resource ID.
- RecommendationDisplayName: What Defender recommends (e.g., “Enable MFA”).
- Severity: Low, Medium, High.
- Description: What the recommendation means and why it matters.
- State_14DaysAgo: The previous (Healthy) state.
- State_Recent: The current (Unhealthy) state.
- Timestamps: When the states were recorded.
Sample Email for reference:
What the Security Team Can Do with It?
- Review the Impact
- Quickly identify which resources have degraded in security posture.
- Assess if the changes are critical (e.g., exposed VMs, missing patching).
- Prioritize Remediation
- Use the severity level to triage what needs immediate attention.
- Assign tasks to the right teams — infrastructure, app owners, etc.
- Correlate with Other Alerts
- Cross-check with Microsoft Sentinel, vulnerability scanners, or SIEM rules.
- Investigate whether these changes are expected, neglected, or malicious.
- Track and Document
- Use the email as a record of change in security posture.
- Log it in ticketing systems (like Jira or ServiceNow) manually or via integration.
Optional Step: Initiate Remediation Playbooks
- Based on the resource type and issue, teams may:
- Enable security agents,
- Update configurations,
- Apply missing patches,
- Isolate the resource (if necessary).
Automating alerts for resources that go from Healthy to Unhealthy in Defender for Cloud makes life a lot easier for security teams. It helps you catch issues early, act faster, and keep your cloud environment safe without constantly watching dashboards. Give this Logic App a try and see how much smoother your security monitoring and response can be!
Access the JSON deployment file for this Logic App here: Microsoft-Unified-Security-Operations-Platform/Microsoft Defender for Cloud/ResourcesMovingFromHealthytoUnhealthyState/ARMTemplate-HealthytoUnhealthyResources(MDC).json at main · Abhishek-Sharan/Microsoft-Unified-Security-Operations-Platform