You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Account-level security, health, and governance monitoring for a Rhythmic-managed
Azure subscription. The module emits well-typed control-plane events into a
single shared Action Group and lets the downstream monitoring backend classify
and fan them out; it produces events, it does not own the routing rules.
Called once per subscription (with an aliased provider), it creates:
Control-plane detections: one azurerm_monitor_activity_log_alert per
entry in a curated catalog (role-assignment changes, policy-assignment
changes, Defender plan changes, Recovery Services vault deletion, backup
policy changes, and Azure Policy non-compliance). Each rule fires into the
shared account-alerts Action Group passed in as action_group_id.
Backup job-failure routing: an azurerm_monitor_alert_processing_rule_action_group
that attaches the same Action Group to Azure Backup's built-in job-failure
alerts. Recovery Services vaults raise these alerts natively, but without a
processing rule they reach no Action Group. Enabled by default; toggle with
enable_backup_failure_routing.
Microsoft Defender for Cloud posture (opt-in): zero or more
azurerm_security_center_subscription_pricing plans (empty by default, since
enabling paid plans is a deliberate per-subscription cost decision) and an
optional azurerm_security_center_contact.
The subscription scope is derived from the invoking credential
(data.azurerm_subscription), so the caller never passes a subscription id.
The module requires only the azurerm provider.
One rule per operation. Azure activity-log alert criteria are singular:
a rule filters on a single operation_name. The catalog is therefore modeled
as one operation per map entry. Override the whole activity_log_detections
map to replace the curated set, or add entries for subscription-specific
operations. A nulloperation_name produces a category-wide rule (used for
the Policy non-compliance entry).
Detection transport. Detections route to the shared Action Group only; the
PagerDuty and Slack fan-out stays downstream in the monitoring backend, so
this module produces events rather than routing rules.
Security contact name.security_contact_name defaults to the canonical
single-contact name. Azure validates the accepted value at apply time.
Operation names. The catalog's default operation_name strings are
standard Azure control-plane operations; the provider confirms them against
the subscription at apply time. Adjust the map if a subscription exposes a
different operation surface.
Coverage notes
Vault-lock / immutability changes. Azure Recovery Services immutability
changes ride the broad vaults/write operation, which is too noisy to alert
on directly, so there is no dedicated rule for them. This is a known coverage
gap versus the corresponding backup-lock detection on other clouds.
Directory (Entra ID) audit and sign-in log routing is out of scope here.
It is handled by the Datadog integration module's modules/activity-log
submodule, which routes Entra diagnostics behind its own feature flag. Enable
it there, not in this module.
Service Health / Resource Health alerting is intentionally omitted to
avoid double-routing; it is owned by the health monitor set.
Service-quota monitoring is a candidate follow-up (Azure-native quota
alerts or a scheduled Function). It is not implemented in this version.
Resource ID of the shared account-alerts Action Group every detection fires into (typically the rhythmic-core module's account_action_group_id output).
Control-plane detections rendered as activity-log alert rules wired to the Action Group. Keys are rule name suffixes. Override the whole map to replace the curated catalog. category is required; operation_name narrows to a single control-plane operation (leave null for a category-wide rule); level optionally filters by severity.
{ "backup-policy-changed": { "category": "Administrative", "description": "A Recovery Services backup policy was created or modified.", "operation_name": "Microsoft.RecoveryServices/vaults/backupPolicies/write" }, "defender-plan-changed": { "category": "Administrative", "description": "A Microsoft Defender for Cloud plan tier was changed (guards against silent downgrades).", "operation_name": "Microsoft.Security/pricings/write" }, "policy-assignment-created": { "category": "Administrative", "description": "A policy assignment was created or updated.", "operation_name": "Microsoft.Authorization/policyAssignments/write" }, "policy-assignment-deleted": { "category": "Administrative", "description": "A policy assignment was deleted.", "operation_name": "Microsoft.Authorization/policyAssignments/delete" }, "policy-noncompliance": { "category": "Policy", "description": "Azure Policy reported a compliance state change.", "level": "Warning", "operation_name": null }, "recovery-vault-deleted": { "category": "Administrative", "description": "A Recovery Services vault was deleted.", "operation_name": "Microsoft.RecoveryServices/vaults/delete" }, "role-assignment-created": { "category": "Administrative", "description": "A role assignment was created (privilege grant).", "operation_name": "Microsoft.Authorization/roleAssignments/write" }, "role-assignment-deleted": { "category": "Administrative", "description": "A role assignment was deleted (privilege revocation).", "operation_name": "Microsoft.Authorization/roleAssignments/delete" } }
Microsoft Defender for Cloud plans to enable on the subscription, keyed by resource_type (e.g. VirtualMachines, AppServices, SqlServers, StorageAccounts). Empty by default: enabling paid plans is a deliberate per-client cost decision.
Create a subscription-scope alert processing rule that attaches the Action Group to Azure Backup's built-in job-failure alerts (Recovery Services vaults emit these natively; without a processing rule they route nowhere).
Name of the Defender for Cloud security contact resource. Azure validates the accepted value at apply time; the default matches the canonical single-contact name.