From e3956e5dabe3b5ff96309be25f04e23b329356ce Mon Sep 17 00:00:00 2001 From: Andre Pereira <219305055+cx-andre-pereira@users.noreply.github.com> Date: Tue, 4 Nov 2025 17:54:28 +0000 Subject: [PATCH 01/12] initial implementation --- .../metadata.json | 14 +++ .../query.rego | 89 +++++++++++++++++ .../test/negative1.tf | 45 +++++++++ .../test/positive1.tf | 97 +++++++++++++++++++ .../test/positive2/positive2_1.tf | 18 ++++ .../test/positive2/positive2_2.tf | 20 ++++ .../positive2/positive_expected_result.json | 14 +++ .../test/positive3/positive3_1.tf | 40 ++++++++ .../test/positive3/positive3_2.tf | 19 ++++ .../positive3/positive_expected_result.json | 14 +++ .../test/positive4/positive4_1.tf | 38 ++++++++ .../test/positive4/positive4_2.tf | 19 ++++ .../positive4/positive_expected_result.json | 8 ++ .../test/positive_expected_result.json | 32 ++++++ .../terraform_azure.yaml | 4 + 15 files changed, 471 insertions(+) create mode 100644 assets/queries/terraform/azure/activity_log_alert_for_service_health/metadata.json create mode 100644 assets/queries/terraform/azure/activity_log_alert_for_service_health/query.rego create mode 100644 assets/queries/terraform/azure/activity_log_alert_for_service_health/test/negative1.tf create mode 100644 assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive1.tf create mode 100644 assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive2/positive2_1.tf create mode 100644 assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive2/positive2_2.tf create mode 100644 assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive2/positive_expected_result.json create mode 100644 assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive3/positive3_1.tf create mode 100644 assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive3/positive3_2.tf create mode 100644 assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive3/positive_expected_result.json create mode 100644 assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive4/positive4_1.tf create mode 100644 assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive4/positive4_2.tf create mode 100644 assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive4/positive_expected_result.json create mode 100644 assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive_expected_result.json diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/metadata.json b/assets/queries/terraform/azure/activity_log_alert_for_service_health/metadata.json new file mode 100644 index 00000000000..f394481c476 --- /dev/null +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/metadata.json @@ -0,0 +1,14 @@ +{ + "id": "f677bd92-3922-4e75-8f0c-2c0f8fbc9609", + "queryName": "Beta - Activity Log Alert For Service Health", + "severity": "MEDIUM", + "category": "Observability", + "descriptionText": "There should be a 'azurerm_monitor_activity_log_alert' resource configured to capture service health events", + "descriptionUrl": "https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/monitor_activity_log_alert", + "platform": "Terraform", + "descriptionID": "f677bd92", + "cloudProvider": "azure", + "cwe": "778", + "riskScore": "3.0", + "experimental": "true" +} diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/query.rego b/assets/queries/terraform/azure/activity_log_alert_for_service_health/query.rego new file mode 100644 index 00000000000..ffd557b3716 --- /dev/null +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/query.rego @@ -0,0 +1,89 @@ +package Cx + +import data.generic.common as common_lib +import data.generic.terraform as tf_lib + +filter_fields := ["caller", "level", "levels", "status", "statuses", "sub_status", "sub_statuses"] + +CxPolicy[result] { + resources := {input.document[index].id : log_alerts | + log_alerts := input.document[index].resource.azurerm_monitor_activity_log_alert + } + + value := at_least_one_valid_log_alert(resources) + value.result != "has_valid_log" + + results := get_results(value)[_] + + result := { + "documentId": results.doc_id, + "resourceType": "azurerm_monitor_activity_log_alert", + "resourceName": tf_lib.get_resource_name(results.resource, results.name), + "searchKey": sprintf("azurerm_monitor_activity_log_alert[%s].criteria", [results.name]), + "issueType": "IncorrectValue", + "keyExpectedValue": "A 'azurerm_monitor_activity_log_alert' resource that monitors 'service health' events should be defined", + "keyActualValue": results.keyActualValue, + "searchLine": common_lib.build_search_line(["resource", "azurerm_monitor_activity_log_alert", results.name, "criteria"], []) + } +} + +at_least_one_valid_log_alert(resources) = {"result" : "has_valid_log"} { + resources[doc_index][x].criteria.category == "ServiceHealth" + resources[doc_index][x].criteria.service_health.events[_] == "Incident" + common_lib.valid_key(resources[doc_index][x].action, "action_group_id") + +} else = {"result" : "has_log_without_action", "logs": logs} { + logs := {doc_index: filtered | + resources[doc_index] + filtered := {key: resource | + resource := resources[doc_index][key] + resource.criteria.category == "ServiceHealth" + resource.criteria.service_health.events[_] == "Incident"} + } + logs[_] != {} + +} else = {"result" : "has_log_without_incident_event", "logs": logs} { + logs := {doc_index: filtered | + resources[doc_index] + filtered := {key: resource | + resource := resources[doc_index][key] + resource.criteria.category == "ServiceHealth"} + } + logs[_] != {} + +} else = {"result" : "has_invalid_logs_only", "logs": resources} + +get_results(value) = results { # Case of one or more resources failing due to not setting an "action.action_group_id" field + value.result == "has_log_without_action" + + results := [z | + log := value.logs[doc_id][name] + z := { + "doc_id" : doc_id, + "resource" : log, + "name" : name, + "keyActualValue" : sprintf("The 'azurerm_monitor_activity_log_alert[%s]' resource monitors 'service health' events but is missing an 'action.action_group_id' field", [name]) + }] + +} else = results { # Case of one or more resources failing due to setting filter(s) + value.result == "has_log_without_incident_event" + + results := [z | + log := value.logs[doc_id][name] + z := { + "doc_id" : doc_id, + "resource" : log, + "name" : name, + "keyActualValue" : sprintf("The 'azurerm_monitor_activity_log_alert[%s]' resource monitors 'service health' events but does not include 'Incident' in the criteria.service_health.events array", [name]) + }] + +} else = results { # Case of all resources failing due to invalid category and/or operation_name + results := [z | + log := value.logs[doc_id][name] + z := { + "doc_id" : doc_id, + "resource" : log, + "name" : name, + "keyActualValue" : "None of the 'azurerm_monitor_activity_log_alert' resources monitor 'service health' events" + }] +} diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/negative1.tf b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/negative1.tf new file mode 100644 index 00000000000..d65bdf7abe3 --- /dev/null +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/negative1.tf @@ -0,0 +1,45 @@ +resource "azurerm_monitor_activity_log_alert" "negative1" { + name = "ServiceHealthActivityLogAlert" + resource_group_name = var.resource_group_name + scopes = [data.azurerm_subscription.current.id] + description = "Alert for Azure Service Health events" + enabled = true + + criteria { + category = "ServiceHealth" + + service_health { + events = ["Incident"] + } + } + + action { + action_group_id = azurerm_monitor_action_group.notify_team.id + } +} + +data "azurerm_subscription" "current" {} + +resource "azurerm_monitor_activity_log_alert" "negative2" { + name = "ServiceHealthActivityLogAlert" + resource_group_name = var.resource_group_name + scopes = [data.azurerm_subscription.secondary.id] + description = "Alert for Azure Service Health events" + enabled = true + + criteria { + category = "ServiceHealth" + + service_health { + events = ["Incident"] + } + } + + action { + action_group_id = azurerm_monitor_action_group.notify_team.id + } +} + +data "azurerm_subscription" "secondary" { + subscription_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" +} diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive1.tf b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive1.tf new file mode 100644 index 00000000000..915dc67dff6 --- /dev/null +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive1.tf @@ -0,0 +1,97 @@ +resource "azurerm_monitor_activity_log_alert" "positive1_1" { + name = "ServiceHealthActivityLogAlert" + resource_group_name = var.resource_group_name + scopes = [data.azurerm_subscription.current.id] + description = "Alert for Azure Service Health events" + enabled = true + + criteria { + category = "Security" # Wrong category + + service_health { + events = ["Incident"] + } + } + + action { + action_group_id = azurerm_monitor_action_group.notify_team.id + } +} + +resource "azurerm_monitor_activity_log_alert" "positive1_2" { + name = "ServiceHealthActivityLogAlert" + resource_group_name = var.resource_group_name + scopes = [data.azurerm_subscription.current.id] + description = "Alert for Azure Service Health events" + enabled = true + + criteria { + category = "ServiceHealth" + + service_health { + events = ["Maintenance"] # Missing 'Incident' + } + } + + action { + action_group_id = azurerm_monitor_action_group.notify_team.id + } +} + +resource "azurerm_monitor_activity_log_alert" "positive1_3" { + name = "ServiceHealthActivityLogAlert" + resource_group_name = var.resource_group_name + scopes = [data.azurerm_subscription.current.id] + description = "Alert for Azure Service Health events" + enabled = true + + criteria { + category = "Security" # Wrong category + + service_health { + events = ["Maintenance"] # Missing 'Incident' + } + } + + action { + action_group_id = azurerm_monitor_action_group.notify_team.id + } +} + +resource "azurerm_monitor_activity_log_alert" "positive1_4" { + name = "ServiceHealthActivityLogAlert" + resource_group_name = var.resource_group_name + scopes = [data.azurerm_subscription.current.id] + description = "Alert for Azure Service Health events" + enabled = true + + criteria { + category = "Security" # Wrong category + + service_health { + # Missing 'events' + } + } + + action { + action_group_id = azurerm_monitor_action_group.notify_team.id + } +} + +resource "azurerm_monitor_activity_log_alert" "positive1_5" { + name = "ServiceHealthActivityLogAlert" + resource_group_name = var.resource_group_name + scopes = [data.azurerm_subscription.current.id] + description = "Alert for Azure Service Health events" + enabled = true + + criteria { + category = "Security" # Wrong category + + # Missing 'service_health' + } + + action { + action_group_id = azurerm_monitor_action_group.notify_team.id + } +} diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive2/positive2_1.tf b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive2/positive2_1.tf new file mode 100644 index 00000000000..346c730987d --- /dev/null +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive2/positive2_1.tf @@ -0,0 +1,18 @@ +# Case of correct "service_health.events" and "category" but the "action.action_group_id" field is missing +resource "azurerm_monitor_activity_log_alert" "positive3_1" { + name = "ServiceHealthActivityLogAlert" + resource_group_name = var.resource_group_name + scopes = [data.azurerm_subscription.current.id] + description = "Alert for Azure Service Health events" + enabled = true + + criteria { + category = "ServiceHealth" + + service_health { + events = ["Incident"] + } + } + + # Missing action +} diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive2/positive2_2.tf b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive2/positive2_2.tf new file mode 100644 index 00000000000..1ba594480de --- /dev/null +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive2/positive2_2.tf @@ -0,0 +1,20 @@ +# Case of correct "service_health.events" and "category" but the "action.action_group_id" field is missing +resource "azurerm_monitor_activity_log_alert" "positive3_2" { + name = "ServiceHealthActivityLogAlert" + resource_group_name = var.resource_group_name + scopes = [data.azurerm_subscription.current.id] + description = "Alert for Azure Service Health events" + enabled = true + + criteria { + category = "ServiceHealth" + + service_health { + events = ["Incident"] + } + } + + action { + # Missing action_group_id + } +} diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive2/positive_expected_result.json b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive2/positive_expected_result.json new file mode 100644 index 00000000000..5805b7e93f3 --- /dev/null +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive2/positive_expected_result.json @@ -0,0 +1,14 @@ +[ + { + "queryName": "Beta - Activity Log Alert", + "severity": "MEDIUM", + "line": 9, + "fileName": "positive2_1.tf" + }, + { + "queryName": "Beta - Activity Log Alert", + "severity": "MEDIUM", + "line": 9, + "fileName": "positive2_2.tf" + } +] diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive3/positive3_1.tf b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive3/positive3_1.tf new file mode 100644 index 00000000000..afaa5d5b044 --- /dev/null +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive3/positive3_1.tf @@ -0,0 +1,40 @@ +# Query prioritizes flagging the log alert(s) with correct "category" but missing "Incident" on the events array over ones with wrong "category" +resource "azurerm_monitor_activity_log_alert" "positive3_1" { + name = "ServiceHealthActivityLogAlert" + resource_group_name = var.resource_group_name + scopes = [data.azurerm_subscription.current.id] + description = "Alert for Azure Service Health events" + enabled = true + + criteria { + category = "ServiceHealth" + + service_health { + events = ["Maintenance"] # Missing "Incident" + } + } + + action { + action_group_id = azurerm_monitor_action_group.notify_team.id + } +} + +resource "azurerm_monitor_activity_log_alert" "positive3_2" { + name = "ServiceHealthActivityLogAlert" + resource_group_name = var.resource_group_name + scopes = [data.azurerm_subscription.current.id] + description = "Alert for Azure Service Health events" + enabled = true + + criteria { + category = "ServiceHealth" + + service_health { + events = ["Informational", "ActionRequired"] # Missing "Incident" + } + } + + action { + action_group_id = azurerm_monitor_action_group.notify_team.id + } +} diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive3/positive3_2.tf b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive3/positive3_2.tf new file mode 100644 index 00000000000..274e4154538 --- /dev/null +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive3/positive3_2.tf @@ -0,0 +1,19 @@ +resource "azurerm_monitor_activity_log_alert" "positive3_3" { + name = "ServiceHealthActivityLogAlert" + resource_group_name = var.resource_group_name + scopes = [data.azurerm_subscription.current.id] + description = "Alert for Azure Service Health events" + enabled = true + + criteria { + category = "Security" # Wrong category + + service_health { + events = ["Incident"] + } + } + + action { + action_group_id = azurerm_monitor_action_group.notify_team.id + } +} diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive3/positive_expected_result.json b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive3/positive_expected_result.json new file mode 100644 index 00000000000..2816897cd54 --- /dev/null +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive3/positive_expected_result.json @@ -0,0 +1,14 @@ +[ + { + "queryName": "Beta - Activity Log Alert", + "severity": "MEDIUM", + "line": 9, + "fileName": "positive3_1.tf" + }, + { + "queryName": "Beta - Activity Log Alert", + "severity": "MEDIUM", + "line": 29, + "fileName": "positive3_1.tf" + } +] diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive4/positive4_1.tf b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive4/positive4_1.tf new file mode 100644 index 00000000000..a9c63cba674 --- /dev/null +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive4/positive4_1.tf @@ -0,0 +1,38 @@ +# Query prioritizes flagging the log alert(s) that is "correct" but missing the "action_group_id" field over all others +resource "azurerm_monitor_activity_log_alert" "positive4_1" { + name = "ServiceHealthActivityLogAlert" + resource_group_name = var.resource_group_name + scopes = [data.azurerm_subscription.current.id] + description = "Alert for Azure Service Health events" + enabled = true + + criteria { + category = "ServiceHealth" + + service_health { + events = ["Incident"] + } + } + + # Missing action block +} + +resource "azurerm_monitor_activity_log_alert" "positive4_2" { + name = "ServiceHealthActivityLogAlert" + resource_group_name = var.resource_group_name + scopes = [data.azurerm_subscription.current.id] + description = "Alert for Azure Service Health events" + enabled = true + + criteria { + category = "ServiceHealth" + + service_health { + events = ["Maintenance"] # Missing "Incident" + } + } + + action { + action_group_id = azurerm_monitor_action_group.notify_team.id + } +} diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive4/positive4_2.tf b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive4/positive4_2.tf new file mode 100644 index 00000000000..640004d4703 --- /dev/null +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive4/positive4_2.tf @@ -0,0 +1,19 @@ +resource "azurerm_monitor_activity_log_alert" "positive4_3" { + name = "ServiceHealthActivityLogAlert" + resource_group_name = var.resource_group_name + scopes = [data.azurerm_subscription.current.id] + description = "Alert for Azure Service Health events" + enabled = true + + criteria { + category = "Security" # Wrong category + + service_health { + events = ["Incident"] + } + } + + action { + action_group_id = azurerm_monitor_action_group.notify_team.id + } +} diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive4/positive_expected_result.json b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive4/positive_expected_result.json new file mode 100644 index 00000000000..ecdac5cb2d0 --- /dev/null +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive4/positive_expected_result.json @@ -0,0 +1,8 @@ +[ + { + "queryName": "Beta - Activity Log Alert", + "severity": "MEDIUM", + "line": 9, + "fileName": "positive4_1.tf" + } +] diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive_expected_result.json b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive_expected_result.json new file mode 100644 index 00000000000..a66f65d792a --- /dev/null +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive_expected_result.json @@ -0,0 +1,32 @@ +[ + { + "queryName": "Beta - Activity Log Alert", + "severity": "MEDIUM", + "line": 8, + "fileName": "positive1.tf" + }, + { + "queryName": "Beta - Activity Log Alert", + "severity": "MEDIUM", + "line": 28, + "fileName": "positive1.tf" + }, + { + "queryName": "Beta - Activity Log Alert", + "severity": "MEDIUM", + "line": 48, + "fileName": "positive1.tf" + }, + { + "queryName": "Beta - Activity Log Alert", + "severity": "MEDIUM", + "line": 68, + "fileName": "positive1.tf" + }, + { + "queryName": "Beta - Activity Log Alert", + "severity": "MEDIUM", + "line": 88, + "fileName": "positive1.tf" + } +] diff --git a/assets/similarityID_transition/terraform_azure.yaml b/assets/similarityID_transition/terraform_azure.yaml index 407c810f4d1..962b29184e6 100644 --- a/assets/similarityID_transition/terraform_azure.yaml +++ b/assets/similarityID_transition/terraform_azure.yaml @@ -3,3 +3,7 @@ similarityIDChangeList: queryName: Sensitive Port Is Exposed To Wide Private Network observations: "" change: 5 + - queryId: f677bd92-3922-4e75-8f0c-2c0f8fbc9609 + queryName: Beta - Activity Log Alert For Service Health + observations: "" + change: 2 From d1abf4c043dfc09ca29dcade6a89569b6a872ce9 Mon Sep 17 00:00:00 2001 From: Andre Pereira <219305055+cx-andre-pereira@users.noreply.github.com> Date: Wed, 5 Nov 2025 11:01:33 +0000 Subject: [PATCH 02/12] improvements --- .../query.rego | 2 +- .../test/positive1.tf | 62 +------------------ .../test/positive2/positive2_1.tf | 29 +++++++-- .../test/positive2/positive2_2.tf | 13 ++-- .../positive2/positive_expected_result.json | 10 ++- .../test/positive3/positive3_1.tf | 28 +-------- .../test/positive3/positive3_2.tf | 9 +-- .../positive3/positive_expected_result.json | 4 +- .../test/positive4/positive4_1.tf | 10 +-- .../positive4/positive_expected_result.json | 6 ++ .../test/positive5/positive5_1.tf | 38 ++++++++++++ .../test/positive5/positive5_2.tf | 19 ++++++ .../positive5/positive_expected_result.json | 8 +++ .../test/positive_expected_result.json | 18 ------ 14 files changed, 128 insertions(+), 128 deletions(-) create mode 100644 assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive5/positive5_1.tf create mode 100644 assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive5/positive5_2.tf create mode 100644 assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive5/positive_expected_result.json diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/query.rego b/assets/queries/terraform/azure/activity_log_alert_for_service_health/query.rego index ffd557b3716..769ac9fdd00 100644 --- a/assets/queries/terraform/azure/activity_log_alert_for_service_health/query.rego +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/query.rego @@ -74,7 +74,7 @@ get_results(value) = results { # Case of one or more resources failing due t "doc_id" : doc_id, "resource" : log, "name" : name, - "keyActualValue" : sprintf("The 'azurerm_monitor_activity_log_alert[%s]' resource monitors 'service health' events but does not include 'Incident' in the criteria.service_health.events array", [name]) + "keyActualValue" : sprintf("The 'azurerm_monitor_activity_log_alert[%s]' resource monitors 'service health' events but does not include 'Incident' in the 'criteria.service_health.events' array", [name]) }] } else = results { # Case of all resources failing due to invalid category and/or operation_name diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive1.tf b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive1.tf index 915dc67dff6..856947d6529 100644 --- a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive1.tf +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive1.tf @@ -26,10 +26,10 @@ resource "azurerm_monitor_activity_log_alert" "positive1_2" { enabled = true criteria { - category = "ServiceHealth" + category = "Recommendation" # Wrong category service_health { - events = ["Maintenance"] # Missing 'Incident' + events = ["Incident", "Informational"] } } @@ -37,61 +37,3 @@ resource "azurerm_monitor_activity_log_alert" "positive1_2" { action_group_id = azurerm_monitor_action_group.notify_team.id } } - -resource "azurerm_monitor_activity_log_alert" "positive1_3" { - name = "ServiceHealthActivityLogAlert" - resource_group_name = var.resource_group_name - scopes = [data.azurerm_subscription.current.id] - description = "Alert for Azure Service Health events" - enabled = true - - criteria { - category = "Security" # Wrong category - - service_health { - events = ["Maintenance"] # Missing 'Incident' - } - } - - action { - action_group_id = azurerm_monitor_action_group.notify_team.id - } -} - -resource "azurerm_monitor_activity_log_alert" "positive1_4" { - name = "ServiceHealthActivityLogAlert" - resource_group_name = var.resource_group_name - scopes = [data.azurerm_subscription.current.id] - description = "Alert for Azure Service Health events" - enabled = true - - criteria { - category = "Security" # Wrong category - - service_health { - # Missing 'events' - } - } - - action { - action_group_id = azurerm_monitor_action_group.notify_team.id - } -} - -resource "azurerm_monitor_activity_log_alert" "positive1_5" { - name = "ServiceHealthActivityLogAlert" - resource_group_name = var.resource_group_name - scopes = [data.azurerm_subscription.current.id] - description = "Alert for Azure Service Health events" - enabled = true - - criteria { - category = "Security" # Wrong category - - # Missing 'service_health' - } - - action { - action_group_id = azurerm_monitor_action_group.notify_team.id - } -} diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive2/positive2_1.tf b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive2/positive2_1.tf index 346c730987d..599d3971589 100644 --- a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive2/positive2_1.tf +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive2/positive2_1.tf @@ -1,5 +1,4 @@ -# Case of correct "service_health.events" and "category" but the "action.action_group_id" field is missing -resource "azurerm_monitor_activity_log_alert" "positive3_1" { +resource "azurerm_monitor_activity_log_alert" "positive2_1" { name = "ServiceHealthActivityLogAlert" resource_group_name = var.resource_group_name scopes = [data.azurerm_subscription.current.id] @@ -10,9 +9,31 @@ resource "azurerm_monitor_activity_log_alert" "positive3_1" { category = "ServiceHealth" service_health { - events = ["Incident"] + events = ["Maintenance"] # Missing 'Incident' } } - # Missing action + action { + action_group_id = azurerm_monitor_action_group.notify_team.id + } +} + +resource "azurerm_monitor_activity_log_alert" "positive2_2" { + name = "ServiceHealthActivityLogAlert" + resource_group_name = var.resource_group_name + scopes = [data.azurerm_subscription.current.id] + description = "Alert for Azure Service Health events" + enabled = true + + criteria { + category = "ServiceHealth" # Wrong category + + service_health { + # Missing 'events' + } + } + + action { + action_group_id = azurerm_monitor_action_group.notify_team.id + } } diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive2/positive2_2.tf b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive2/positive2_2.tf index 1ba594480de..cefa62a1289 100644 --- a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive2/positive2_2.tf +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive2/positive2_2.tf @@ -1,5 +1,4 @@ -# Case of correct "service_health.events" and "category" but the "action.action_group_id" field is missing -resource "azurerm_monitor_activity_log_alert" "positive3_2" { +resource "azurerm_monitor_activity_log_alert" "positive2_3" { name = "ServiceHealthActivityLogAlert" resource_group_name = var.resource_group_name scopes = [data.azurerm_subscription.current.id] @@ -7,14 +6,12 @@ resource "azurerm_monitor_activity_log_alert" "positive3_2" { enabled = true criteria { - category = "ServiceHealth" + category = "ServiceHealth" # Wrong category - service_health { - events = ["Incident"] - } + # Missing 'service_health' } action { - # Missing action_group_id - } + action_group_id = azurerm_monitor_action_group.notify_team.id + } } diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive2/positive_expected_result.json b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive2/positive_expected_result.json index 5805b7e93f3..455f26ccd7c 100644 --- a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive2/positive_expected_result.json +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive2/positive_expected_result.json @@ -2,13 +2,19 @@ { "queryName": "Beta - Activity Log Alert", "severity": "MEDIUM", - "line": 9, + "line": 8, "fileName": "positive2_1.tf" }, { "queryName": "Beta - Activity Log Alert", "severity": "MEDIUM", - "line": 9, + "line": 28, + "fileName": "positive2_1.tf" + }, + { + "queryName": "Beta - Activity Log Alert", + "severity": "MEDIUM", + "line": 8, "fileName": "positive2_2.tf" } ] diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive3/positive3_1.tf b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive3/positive3_1.tf index afaa5d5b044..346c730987d 100644 --- a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive3/positive3_1.tf +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive3/positive3_1.tf @@ -1,4 +1,4 @@ -# Query prioritizes flagging the log alert(s) with correct "category" but missing "Incident" on the events array over ones with wrong "category" +# Case of correct "service_health.events" and "category" but the "action.action_group_id" field is missing resource "azurerm_monitor_activity_log_alert" "positive3_1" { name = "ServiceHealthActivityLogAlert" resource_group_name = var.resource_group_name @@ -10,31 +10,9 @@ resource "azurerm_monitor_activity_log_alert" "positive3_1" { category = "ServiceHealth" service_health { - events = ["Maintenance"] # Missing "Incident" + events = ["Incident"] } } - action { - action_group_id = azurerm_monitor_action_group.notify_team.id - } -} - -resource "azurerm_monitor_activity_log_alert" "positive3_2" { - name = "ServiceHealthActivityLogAlert" - resource_group_name = var.resource_group_name - scopes = [data.azurerm_subscription.current.id] - description = "Alert for Azure Service Health events" - enabled = true - - criteria { - category = "ServiceHealth" - - service_health { - events = ["Informational", "ActionRequired"] # Missing "Incident" - } - } - - action { - action_group_id = azurerm_monitor_action_group.notify_team.id - } + # Missing action } diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive3/positive3_2.tf b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive3/positive3_2.tf index 274e4154538..1ba594480de 100644 --- a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive3/positive3_2.tf +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive3/positive3_2.tf @@ -1,4 +1,5 @@ -resource "azurerm_monitor_activity_log_alert" "positive3_3" { +# Case of correct "service_health.events" and "category" but the "action.action_group_id" field is missing +resource "azurerm_monitor_activity_log_alert" "positive3_2" { name = "ServiceHealthActivityLogAlert" resource_group_name = var.resource_group_name scopes = [data.azurerm_subscription.current.id] @@ -6,7 +7,7 @@ resource "azurerm_monitor_activity_log_alert" "positive3_3" { enabled = true criteria { - category = "Security" # Wrong category + category = "ServiceHealth" service_health { events = ["Incident"] @@ -14,6 +15,6 @@ resource "azurerm_monitor_activity_log_alert" "positive3_3" { } action { - action_group_id = azurerm_monitor_action_group.notify_team.id - } + # Missing action_group_id + } } diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive3/positive_expected_result.json b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive3/positive_expected_result.json index 2816897cd54..63b1643c0d9 100644 --- a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive3/positive_expected_result.json +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive3/positive_expected_result.json @@ -8,7 +8,7 @@ { "queryName": "Beta - Activity Log Alert", "severity": "MEDIUM", - "line": 29, - "fileName": "positive3_1.tf" + "line": 9, + "fileName": "positive3_2.tf" } ] diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive4/positive4_1.tf b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive4/positive4_1.tf index a9c63cba674..6e7d1e05248 100644 --- a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive4/positive4_1.tf +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive4/positive4_1.tf @@ -1,4 +1,4 @@ -# Query prioritizes flagging the log alert(s) that is "correct" but missing the "action_group_id" field over all others +# Query prioritizes flagging the log alert(s) with correct "category" but missing "Incident" on the events array over ones with wrong "category" resource "azurerm_monitor_activity_log_alert" "positive4_1" { name = "ServiceHealthActivityLogAlert" resource_group_name = var.resource_group_name @@ -10,11 +10,13 @@ resource "azurerm_monitor_activity_log_alert" "positive4_1" { category = "ServiceHealth" service_health { - events = ["Incident"] + events = ["Maintenance"] # Missing "Incident" } } - # Missing action block + action { + action_group_id = azurerm_monitor_action_group.notify_team.id + } } resource "azurerm_monitor_activity_log_alert" "positive4_2" { @@ -28,7 +30,7 @@ resource "azurerm_monitor_activity_log_alert" "positive4_2" { category = "ServiceHealth" service_health { - events = ["Maintenance"] # Missing "Incident" + events = ["Informational", "ActionRequired"] # Missing "Incident" } } diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive4/positive_expected_result.json b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive4/positive_expected_result.json index ecdac5cb2d0..1c5c074c003 100644 --- a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive4/positive_expected_result.json +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive4/positive_expected_result.json @@ -4,5 +4,11 @@ "severity": "MEDIUM", "line": 9, "fileName": "positive4_1.tf" + }, + { + "queryName": "Beta - Activity Log Alert", + "severity": "MEDIUM", + "line": 29, + "fileName": "positive4_1.tf" } ] diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive5/positive5_1.tf b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive5/positive5_1.tf new file mode 100644 index 00000000000..eb1e01217cd --- /dev/null +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive5/positive5_1.tf @@ -0,0 +1,38 @@ +# Query prioritizes flagging the log alert(s) that is "correct" but missing the "action_group_id" field over all others +resource "azurerm_monitor_activity_log_alert" "positive5_1" { + name = "ServiceHealthActivityLogAlert" + resource_group_name = var.resource_group_name + scopes = [data.azurerm_subscription.current.id] + description = "Alert for Azure Service Health events" + enabled = true + + criteria { + category = "ServiceHealth" + + service_health { + events = ["Incident"] + } + } + + # Missing action block +} + +resource "azurerm_monitor_activity_log_alert" "positive5_2" { + name = "ServiceHealthActivityLogAlert" + resource_group_name = var.resource_group_name + scopes = [data.azurerm_subscription.current.id] + description = "Alert for Azure Service Health events" + enabled = true + + criteria { + category = "ServiceHealth" + + service_health { + events = ["Maintenance"] # Missing "Incident" + } + } + + action { + action_group_id = azurerm_monitor_action_group.notify_team.id + } +} diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive5/positive5_2.tf b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive5/positive5_2.tf new file mode 100644 index 00000000000..6275852af3f --- /dev/null +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive5/positive5_2.tf @@ -0,0 +1,19 @@ +resource "azurerm_monitor_activity_log_alert" "positive5_3" { + name = "ServiceHealthActivityLogAlert" + resource_group_name = var.resource_group_name + scopes = [data.azurerm_subscription.current.id] + description = "Alert for Azure Service Health events" + enabled = true + + criteria { + category = "Security" # Wrong category + + service_health { + events = ["Incident"] + } + } + + action { + action_group_id = azurerm_monitor_action_group.notify_team.id + } +} diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive5/positive_expected_result.json b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive5/positive_expected_result.json new file mode 100644 index 00000000000..827061b72c6 --- /dev/null +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive5/positive_expected_result.json @@ -0,0 +1,8 @@ +[ + { + "queryName": "Beta - Activity Log Alert", + "severity": "MEDIUM", + "line": 9, + "fileName": "positive5_1.tf" + } +] diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive_expected_result.json b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive_expected_result.json index a66f65d792a..0e1aa7d660b 100644 --- a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive_expected_result.json +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive_expected_result.json @@ -10,23 +10,5 @@ "severity": "MEDIUM", "line": 28, "fileName": "positive1.tf" - }, - { - "queryName": "Beta - Activity Log Alert", - "severity": "MEDIUM", - "line": 48, - "fileName": "positive1.tf" - }, - { - "queryName": "Beta - Activity Log Alert", - "severity": "MEDIUM", - "line": 68, - "fileName": "positive1.tf" - }, - { - "queryName": "Beta - Activity Log Alert", - "severity": "MEDIUM", - "line": 88, - "fileName": "positive1.tf" } ] From 2986333f5c743446b3733191bd01b1df4eaab528 Mon Sep 17 00:00:00 2001 From: Andre Pereira <219305055+cx-andre-pereira@users.noreply.github.com> Date: Wed, 5 Nov 2025 11:03:07 +0000 Subject: [PATCH 03/12] expected results fix --- .../test/positive2/positive_expected_result.json | 6 +++--- .../test/positive3/positive_expected_result.json | 4 ++-- .../test/positive4/positive_expected_result.json | 4 ++-- .../test/positive5/positive_expected_result.json | 2 +- .../test/positive_expected_result.json | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive2/positive_expected_result.json b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive2/positive_expected_result.json index 455f26ccd7c..545fa7848dc 100644 --- a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive2/positive_expected_result.json +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive2/positive_expected_result.json @@ -1,18 +1,18 @@ [ { - "queryName": "Beta - Activity Log Alert", + "queryName": "Beta - Activity Log Alert For Service Health", "severity": "MEDIUM", "line": 8, "fileName": "positive2_1.tf" }, { - "queryName": "Beta - Activity Log Alert", + "queryName": "Beta - Activity Log Alert For Service Health", "severity": "MEDIUM", "line": 28, "fileName": "positive2_1.tf" }, { - "queryName": "Beta - Activity Log Alert", + "queryName": "Beta - Activity Log Alert For Service Health", "severity": "MEDIUM", "line": 8, "fileName": "positive2_2.tf" diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive3/positive_expected_result.json b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive3/positive_expected_result.json index 63b1643c0d9..f04520dad90 100644 --- a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive3/positive_expected_result.json +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive3/positive_expected_result.json @@ -1,12 +1,12 @@ [ { - "queryName": "Beta - Activity Log Alert", + "queryName": "Beta - Activity Log Alert For Service Health", "severity": "MEDIUM", "line": 9, "fileName": "positive3_1.tf" }, { - "queryName": "Beta - Activity Log Alert", + "queryName": "Beta - Activity Log Alert For Service Health", "severity": "MEDIUM", "line": 9, "fileName": "positive3_2.tf" diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive4/positive_expected_result.json b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive4/positive_expected_result.json index 1c5c074c003..20fb51db65a 100644 --- a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive4/positive_expected_result.json +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive4/positive_expected_result.json @@ -1,12 +1,12 @@ [ { - "queryName": "Beta - Activity Log Alert", + "queryName": "Beta - Activity Log Alert For Service Health", "severity": "MEDIUM", "line": 9, "fileName": "positive4_1.tf" }, { - "queryName": "Beta - Activity Log Alert", + "queryName": "Beta - Activity Log Alert For Service Health", "severity": "MEDIUM", "line": 29, "fileName": "positive4_1.tf" diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive5/positive_expected_result.json b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive5/positive_expected_result.json index 827061b72c6..6cfe66b8d7b 100644 --- a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive5/positive_expected_result.json +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive5/positive_expected_result.json @@ -1,6 +1,6 @@ [ { - "queryName": "Beta - Activity Log Alert", + "queryName": "Beta - Activity Log Alert For Service Health", "severity": "MEDIUM", "line": 9, "fileName": "positive5_1.tf" diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive_expected_result.json b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive_expected_result.json index 0e1aa7d660b..1060d086da5 100644 --- a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive_expected_result.json +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive_expected_result.json @@ -1,12 +1,12 @@ [ { - "queryName": "Beta - Activity Log Alert", + "queryName": "Beta - Activity Log Alert For Service Health", "severity": "MEDIUM", "line": 8, "fileName": "positive1.tf" }, { - "queryName": "Beta - Activity Log Alert", + "queryName": "Beta - Activity Log Alert For Service Health", "severity": "MEDIUM", "line": 28, "fileName": "positive1.tf" From 0f31d9186b525014c7c791f67162828b7f1547df Mon Sep 17 00:00:00 2001 From: Andre Pereira <219305055+cx-andre-pereira@users.noreply.github.com> Date: Wed, 5 Nov 2025 12:08:04 +0000 Subject: [PATCH 04/12] improved logic part 1 --- .../query.rego | 34 ++++++++++++++++--- .../test/positive1.tf | 2 ++ .../test/positive2/positive2_1.tf | 2 ++ .../test/positive3/positive3_1.tf | 2 ++ .../test/positive4/positive4_1.tf | 2 ++ .../test/positive5/positive5_1.tf | 2 ++ 6 files changed, 40 insertions(+), 4 deletions(-) diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/query.rego b/assets/queries/terraform/azure/activity_log_alert_for_service_health/query.rego index 769ac9fdd00..43ffb080269 100644 --- a/assets/queries/terraform/azure/activity_log_alert_for_service_health/query.rego +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/query.rego @@ -9,8 +9,12 @@ CxPolicy[result] { resources := {input.document[index].id : log_alerts | log_alerts := input.document[index].resource.azurerm_monitor_activity_log_alert } + subscriptions := {input.document[index].id : subs | + subs := input.document[index].data.azurerm_subscription + } - value := at_least_one_valid_log_alert(resources) + subscriptions[doc_id][name] + value := at_least_one_valid_log_alert(resources, name) value.result != "has_valid_log" results := get_results(value)[_] @@ -21,22 +25,25 @@ CxPolicy[result] { "resourceName": tf_lib.get_resource_name(results.resource, results.name), "searchKey": sprintf("azurerm_monitor_activity_log_alert[%s].criteria", [results.name]), "issueType": "IncorrectValue", - "keyExpectedValue": "A 'azurerm_monitor_activity_log_alert' resource that monitors 'service health' events should be defined", + "keyExpectedValue": "A 'azurerm_monitor_activity_log_alert' resource that monitors 'service health' events should be defined for each subscription", "keyActualValue": results.keyActualValue, "searchLine": common_lib.build_search_line(["resource", "azurerm_monitor_activity_log_alert", results.name, "criteria"], []) } } -at_least_one_valid_log_alert(resources) = {"result" : "has_valid_log"} { +at_least_one_valid_log_alert(resources, subscription_name) = {"result" : "has_valid_log"} { + resources[doc_index][x].scopes == sprintf("[data.azurerm_subscription.%s.id]",[subscription_name]) resources[doc_index][x].criteria.category == "ServiceHealth" resources[doc_index][x].criteria.service_health.events[_] == "Incident" common_lib.valid_key(resources[doc_index][x].action, "action_group_id") + } else = {"result" : "has_log_without_action", "logs": logs} { logs := {doc_index: filtered | resources[doc_index] filtered := {key: resource | resource := resources[doc_index][key] + resource.scopes == sprintf("[data.azurerm_subscription.%s.id]",[subscription_name]) resource.criteria.category == "ServiceHealth" resource.criteria.service_health.events[_] == "Incident"} } @@ -47,11 +54,20 @@ at_least_one_valid_log_alert(resources) = {"result" : "has_valid_log"} { resources[doc_index] filtered := {key: resource | resource := resources[doc_index][key] + resource.scopes == sprintf("[data.azurerm_subscription.%s.id]",[subscription_name]) resource.criteria.category == "ServiceHealth"} } logs[_] != {} -} else = {"result" : "has_invalid_logs_only", "logs": resources} +} else = {"result" : "has_invalid_logs_only", "logs": logs} { + logs := {doc_index: filtered | + resources[doc_index] + filtered := {key: resource | + resource := resources[doc_index][key] + resource.scopes == sprintf("[data.azurerm_subscription.%s.id]",[subscription_name])} + } + logs[_] != {} +} else = {"result" : "subscription_without_logs"} get_results(value) = results { # Case of one or more resources failing due to not setting an "action.action_group_id" field value.result == "has_log_without_action" @@ -78,6 +94,16 @@ get_results(value) = results { # Case of one or more resources failing due t }] } else = results { # Case of all resources failing due to invalid category and/or operation_name + value.result == "has_invalid_logs_only" + results := [z | + log := value.logs[doc_id][name] + z := { + "doc_id" : doc_id, + "resource" : log, + "name" : name, + "keyActualValue" : "None of the 'azurerm_monitor_activity_log_alert' resources monitor 'service health' events" + }] +} else = results { results := [z | log := value.logs[doc_id][name] z := { diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive1.tf b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive1.tf index 856947d6529..0b99151f197 100644 --- a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive1.tf +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive1.tf @@ -37,3 +37,5 @@ resource "azurerm_monitor_activity_log_alert" "positive1_2" { action_group_id = azurerm_monitor_action_group.notify_team.id } } + +data "azurerm_subscription" "current" {} diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive2/positive2_1.tf b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive2/positive2_1.tf index 599d3971589..e215bde1d7f 100644 --- a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive2/positive2_1.tf +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive2/positive2_1.tf @@ -37,3 +37,5 @@ resource "azurerm_monitor_activity_log_alert" "positive2_2" { action_group_id = azurerm_monitor_action_group.notify_team.id } } + +data "azurerm_subscription" "current" {} diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive3/positive3_1.tf b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive3/positive3_1.tf index 346c730987d..59dda3f932c 100644 --- a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive3/positive3_1.tf +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive3/positive3_1.tf @@ -16,3 +16,5 @@ resource "azurerm_monitor_activity_log_alert" "positive3_1" { # Missing action } + +data "azurerm_subscription" "current" {} diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive4/positive4_1.tf b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive4/positive4_1.tf index 6e7d1e05248..f2af4ca338b 100644 --- a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive4/positive4_1.tf +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive4/positive4_1.tf @@ -38,3 +38,5 @@ resource "azurerm_monitor_activity_log_alert" "positive4_2" { action_group_id = azurerm_monitor_action_group.notify_team.id } } + +data "azurerm_subscription" "current" {} diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive5/positive5_1.tf b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive5/positive5_1.tf index eb1e01217cd..3417585781e 100644 --- a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive5/positive5_1.tf +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive5/positive5_1.tf @@ -36,3 +36,5 @@ resource "azurerm_monitor_activity_log_alert" "positive5_2" { action_group_id = azurerm_monitor_action_group.notify_team.id } } + +data "azurerm_subscription" "current" {} From f88251c6d74df8e0baa9f1cde4e9b484b6055797 Mon Sep 17 00:00:00 2001 From: Andre Pereira <219305055+cx-andre-pereira@users.noreply.github.com> Date: Wed, 5 Nov 2025 14:37:30 +0000 Subject: [PATCH 05/12] logic improvements --- .../query.rego | 77 ++++++++++++------- .../test/positive6/positive6_1.tf | 3 + .../test/positive6/positive6_2.tf | 19 +++++ .../positive6/positive_expected_result.json | 8 ++ 4 files changed, 78 insertions(+), 29 deletions(-) create mode 100644 assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive6/positive6_1.tf create mode 100644 assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive6/positive6_2.tf create mode 100644 assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive6/positive_expected_result.json diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/query.rego b/assets/queries/terraform/azure/activity_log_alert_for_service_health/query.rego index 43ffb080269..f415174001b 100644 --- a/assets/queries/terraform/azure/activity_log_alert_for_service_health/query.rego +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/query.rego @@ -6,33 +6,43 @@ import data.generic.terraform as tf_lib filter_fields := ["caller", "level", "levels", "status", "statuses", "sub_status", "sub_statuses"] CxPolicy[result] { - resources := {input.document[index].id : log_alerts | - log_alerts := input.document[index].resource.azurerm_monitor_activity_log_alert - } - subscriptions := {input.document[index].id : subs | - subs := input.document[index].data.azurerm_subscription - } + resources := {input.document[index].id : log_alerts | log_alerts := input.document[index].resource.azurerm_monitor_activity_log_alert} + subscriptions := {input.document[index].id : subs | subs := input.document[index].data.azurerm_subscription} subscriptions[doc_id][name] - value := at_least_one_valid_log_alert(resources, name) + value := at_least_one_valid_log_alert(resources, name, doc_id) value.result != "has_valid_log" results := get_results(value)[_] + dinamic_values := get_values(results) result := { "documentId": results.doc_id, "resourceType": "azurerm_monitor_activity_log_alert", - "resourceName": tf_lib.get_resource_name(results.resource, results.name), - "searchKey": sprintf("azurerm_monitor_activity_log_alert[%s].criteria", [results.name]), - "issueType": "IncorrectValue", - "keyExpectedValue": "A 'azurerm_monitor_activity_log_alert' resource that monitors 'service health' events should be defined for each subscription", + "resourceName": dinamic_values.resourceName, + "searchKey": dinamic_values.searchKey, + "issueType": results.issueType, + "keyExpectedValue": "A 'azurerm_monitor_activity_log_alert' resource that monitors 'ServiceHealth' events should be defined for each subscription", "keyActualValue": results.keyActualValue, - "searchLine": common_lib.build_search_line(["resource", "azurerm_monitor_activity_log_alert", results.name, "criteria"], []) + "searchLine": dinamic_values.searchLine } } -at_least_one_valid_log_alert(resources, subscription_name) = {"result" : "has_valid_log"} { - resources[doc_index][x].scopes == sprintf("[data.azurerm_subscription.%s.id]",[subscription_name]) +get_values(results) = dinamic_values { + results.no_log == true + dinamic_values := { + "resourceName": "", + "searchKey": sprintf("azurerm_subscription[%s]", [results.name]), + "searchLine": common_lib.build_search_line(["data", "azurerm_subscription", results.name], []) + } +} else = { + "resourceName": tf_lib.get_resource_name(results.resource, results.name), + "searchKey": sprintf("azurerm_monitor_activity_log_alert[%s].criteria", [results.name]), + "searchLine": common_lib.build_search_line(["resource", "azurerm_monitor_activity_log_alert", results.name, "criteria"], []) +} + +at_least_one_valid_log_alert(resources, subscription_name, doc_id_subs) = {"result" : "has_valid_log"} { + resources[doc_index][x].scopes[_] == sprintf("${data.azurerm_subscription.%s.id}",[subscription_name]) resources[doc_index][x].criteria.category == "ServiceHealth" resources[doc_index][x].criteria.service_health.events[_] == "Incident" common_lib.valid_key(resources[doc_index][x].action, "action_group_id") @@ -43,7 +53,7 @@ at_least_one_valid_log_alert(resources, subscription_name) = {"result" : "has_va resources[doc_index] filtered := {key: resource | resource := resources[doc_index][key] - resource.scopes == sprintf("[data.azurerm_subscription.%s.id]",[subscription_name]) + resources[doc_index][x].scopes[_] == sprintf("${data.azurerm_subscription.%s.id}",[subscription_name]) resource.criteria.category == "ServiceHealth" resource.criteria.service_health.events[_] == "Incident"} } @@ -54,7 +64,7 @@ at_least_one_valid_log_alert(resources, subscription_name) = {"result" : "has_va resources[doc_index] filtered := {key: resource | resource := resources[doc_index][key] - resource.scopes == sprintf("[data.azurerm_subscription.%s.id]",[subscription_name]) + resources[doc_index][x].scopes[_] == sprintf("${data.azurerm_subscription.%s.id}",[subscription_name]) resource.criteria.category == "ServiceHealth"} } logs[_] != {} @@ -64,10 +74,10 @@ at_least_one_valid_log_alert(resources, subscription_name) = {"result" : "has_va resources[doc_index] filtered := {key: resource | resource := resources[doc_index][key] - resource.scopes == sprintf("[data.azurerm_subscription.%s.id]",[subscription_name])} + resources[doc_index][x].scopes[_] == sprintf("${data.azurerm_subscription.%s.id}",[subscription_name])} } logs[_] != {} -} else = {"result" : "subscription_without_logs"} +} else = {"result" : "no_logs", "subscription" : subscription_name, "doc_id": doc_id_subs} get_results(value) = results { # Case of one or more resources failing due to not setting an "action.action_group_id" field value.result == "has_log_without_action" @@ -78,10 +88,11 @@ get_results(value) = results { # Case of one or more resources failing due t "doc_id" : doc_id, "resource" : log, "name" : name, - "keyActualValue" : sprintf("The 'azurerm_monitor_activity_log_alert[%s]' resource monitors 'service health' events but is missing an 'action.action_group_id' field", [name]) + "issueType": "MissingAttribute", + "keyActualValue" : sprintf("The 'azurerm_monitor_activity_log_alert[%s]' resource monitors 'ServiceHealth' events but is missing an 'action.action_group_id' field", [name]) }] -} else = results { # Case of one or more resources failing due to setting filter(s) +} else = results { # Case of one or more resources failing due to not including "Incident" in events array value.result == "has_log_without_incident_event" results := [z | @@ -90,26 +101,34 @@ get_results(value) = results { # Case of one or more resources failing due t "doc_id" : doc_id, "resource" : log, "name" : name, - "keyActualValue" : sprintf("The 'azurerm_monitor_activity_log_alert[%s]' resource monitors 'service health' events but does not include 'Incident' in the 'criteria.service_health.events' array", [name]) + "issueType": check_service_health_block_issue_type(log) , + "keyActualValue" : sprintf("The 'azurerm_monitor_activity_log_alert[%s]' resource monitors 'ServiceHealth' events but does not include 'Incident' in its 'criteria.service_health.events' array", [name]) }] } else = results { # Case of all resources failing due to invalid category and/or operation_name value.result == "has_invalid_logs_only" + results := [z | log := value.logs[doc_id][name] z := { "doc_id" : doc_id, "resource" : log, "name" : name, - "keyActualValue" : "None of the 'azurerm_monitor_activity_log_alert' resources monitor 'service health' events" + "issueType": "IncorrectValue", + "keyActualValue" : "None of the 'azurerm_monitor_activity_log_alert' resources monitor 'ServiceHealth' events" }] -} else = results { - results := [z | - log := value.logs[doc_id][name] - z := { - "doc_id" : doc_id, - "resource" : log, +} else = results { # Case of "subscription" defined without a single alert log associated with it + name := value.subscription + results := [{ + "doc_id" : value.doc_id, "name" : name, - "keyActualValue" : "None of the 'azurerm_monitor_activity_log_alert' resources monitor 'service health' events" + "issueType": "MissingAttribute", + "keyActualValue" : sprintf("There is not a single 'azurerm_monitor_activity_log_alert' resource associated with the '%s' subscription", [name]), + "no_log": true }] } + + +check_service_health_block_issue_type(log) = "IncorrectValue"{ # If events array is set but does not include "Incident" + common_lib.valid_key(log.criteria.service_health, "events") +} else = "MissingAttribute" # If "service_health" or "events" is undefined or null diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive6/positive6_1.tf b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive6/positive6_1.tf new file mode 100644 index 00000000000..bae71a01a6b --- /dev/null +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive6/positive6_1.tf @@ -0,0 +1,3 @@ +data "azurerm_subscription" "current" {} + +data "azurerm_subscription" "positive6" {} diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive6/positive6_2.tf b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive6/positive6_2.tf new file mode 100644 index 00000000000..3b01039b284 --- /dev/null +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive6/positive6_2.tf @@ -0,0 +1,19 @@ +resource "azurerm_monitor_activity_log_alert" "positive6_2" { + name = "ServiceHealthActivityLogAlert" + resource_group_name = var.resource_group_name + scopes = [data.azurerm_subscription.current.id] # "current" subscription has a valid log alert + description = "Alert for Azure Service Health events" + enabled = true + + criteria { + category = "ServiceHealth" + + service_health { + events = ["Incident"] + } + } + + action { + action_group_id = azurerm_monitor_action_group.notify_team.id + } +} diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive6/positive_expected_result.json b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive6/positive_expected_result.json new file mode 100644 index 00000000000..7feb2343c67 --- /dev/null +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive6/positive_expected_result.json @@ -0,0 +1,8 @@ +[ + { + "queryName": "Beta - Activity Log Alert For Service Health", + "severity": "MEDIUM", + "line": 3, + "fileName": "positive6_1.tf" + } +] From d3ae9e21f5cfd9fcbbd9910b6f1f8313d5e17750 Mon Sep 17 00:00:00 2001 From: Andre Pereira <219305055+cx-andre-pereira@users.noreply.github.com> Date: Wed, 5 Nov 2025 14:45:55 +0000 Subject: [PATCH 06/12] minor cleanup --- .../query.rego | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/query.rego b/assets/queries/terraform/azure/activity_log_alert_for_service_health/query.rego index f415174001b..fc5106cccce 100644 --- a/assets/queries/terraform/azure/activity_log_alert_for_service_health/query.rego +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/query.rego @@ -3,8 +3,6 @@ package Cx import data.generic.common as common_lib import data.generic.terraform as tf_lib -filter_fields := ["caller", "level", "levels", "status", "statuses", "sub_status", "sub_statuses"] - CxPolicy[result] { resources := {input.document[index].id : log_alerts | log_alerts := input.document[index].resource.azurerm_monitor_activity_log_alert} subscriptions := {input.document[index].id : subs | subs := input.document[index].data.azurerm_subscription} @@ -14,23 +12,23 @@ CxPolicy[result] { value.result != "has_valid_log" results := get_results(value)[_] - dinamic_values := get_values(results) + dynamic_values := get_values(results) result := { "documentId": results.doc_id, "resourceType": "azurerm_monitor_activity_log_alert", - "resourceName": dinamic_values.resourceName, - "searchKey": dinamic_values.searchKey, + "resourceName": dynamic_values.resourceName, + "searchKey": dynamic_values.searchKey, "issueType": results.issueType, "keyExpectedValue": "A 'azurerm_monitor_activity_log_alert' resource that monitors 'ServiceHealth' events should be defined for each subscription", "keyActualValue": results.keyActualValue, - "searchLine": dinamic_values.searchLine + "searchLine": dynamic_values.searchLine } } -get_values(results) = dinamic_values { +get_values(results) = dynamic_values { results.no_log == true - dinamic_values := { + dynamic_values := { "resourceName": "", "searchKey": sprintf("azurerm_subscription[%s]", [results.name]), "searchLine": common_lib.build_search_line(["data", "azurerm_subscription", results.name], []) From d40830e858cf6d3e762216384d43daaa616cf7ed Mon Sep 17 00:00:00 2001 From: Andre Pereira <219305055+cx-andre-pereira@users.noreply.github.com> Date: Wed, 5 Nov 2025 14:52:29 +0000 Subject: [PATCH 07/12] logic improvement --- .../azure/activity_log_alert_for_service_health/query.rego | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/query.rego b/assets/queries/terraform/azure/activity_log_alert_for_service_health/query.rego index fc5106cccce..177b6c3b614 100644 --- a/assets/queries/terraform/azure/activity_log_alert_for_service_health/query.rego +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health/query.rego @@ -45,13 +45,12 @@ at_least_one_valid_log_alert(resources, subscription_name, doc_id_subs) = {"resu resources[doc_index][x].criteria.service_health.events[_] == "Incident" common_lib.valid_key(resources[doc_index][x].action, "action_group_id") - } else = {"result" : "has_log_without_action", "logs": logs} { logs := {doc_index: filtered | resources[doc_index] filtered := {key: resource | resource := resources[doc_index][key] - resources[doc_index][x].scopes[_] == sprintf("${data.azurerm_subscription.%s.id}",[subscription_name]) + resource.scopes[_] == sprintf("${data.azurerm_subscription.%s.id}",[subscription_name]) resource.criteria.category == "ServiceHealth" resource.criteria.service_health.events[_] == "Incident"} } @@ -62,7 +61,7 @@ at_least_one_valid_log_alert(resources, subscription_name, doc_id_subs) = {"resu resources[doc_index] filtered := {key: resource | resource := resources[doc_index][key] - resources[doc_index][x].scopes[_] == sprintf("${data.azurerm_subscription.%s.id}",[subscription_name]) + resource.scopes[_] == sprintf("${data.azurerm_subscription.%s.id}",[subscription_name]) resource.criteria.category == "ServiceHealth"} } logs[_] != {} @@ -72,7 +71,7 @@ at_least_one_valid_log_alert(resources, subscription_name, doc_id_subs) = {"resu resources[doc_index] filtered := {key: resource | resource := resources[doc_index][key] - resources[doc_index][x].scopes[_] == sprintf("${data.azurerm_subscription.%s.id}",[subscription_name])} + resource.scopes[_] == sprintf("${data.azurerm_subscription.%s.id}",[subscription_name])} } logs[_] != {} } else = {"result" : "no_logs", "subscription" : subscription_name, "doc_id": doc_id_subs} From 6b822ad1d3fa5406404a2f877e5e9ff800aa56fe Mon Sep 17 00:00:00 2001 From: Andre Pereira <219305055+cx-andre-pereira@users.noreply.github.com> Date: Thu, 6 Nov 2025 10:47:19 +0000 Subject: [PATCH 08/12] query renaming --- .../metadata.json | 2 +- .../query.rego | 0 .../test/negative1.tf | 0 .../test/positive1.tf | 0 .../test/positive2/positive2_1.tf | 0 .../test/positive2/positive2_2.tf | 0 .../test/positive2/positive_expected_result.json | 6 +++--- .../test/positive3/positive3_1.tf | 0 .../test/positive3/positive3_2.tf | 0 .../test/positive3/positive_expected_result.json | 4 ++-- .../test/positive4/positive4_1.tf | 0 .../test/positive4/positive4_2.tf | 0 .../test/positive4/positive_expected_result.json | 4 ++-- .../test/positive5/positive5_1.tf | 0 .../test/positive5/positive5_2.tf | 0 .../test/positive5/positive_expected_result.json | 2 +- .../test/positive6/positive6_1.tf | 0 .../test/positive6/positive6_2.tf | 0 .../test/positive6/positive_expected_result.json | 2 +- .../test/positive_expected_result.json | 4 ++-- assets/similarityID_transition/terraform_azure.yaml | 2 +- 21 files changed, 13 insertions(+), 13 deletions(-) rename assets/queries/terraform/azure/{activity_log_alert_for_service_health => activity_log_alert_for_service_health_not_configured}/metadata.json (86%) rename assets/queries/terraform/azure/{activity_log_alert_for_service_health => activity_log_alert_for_service_health_not_configured}/query.rego (100%) rename assets/queries/terraform/azure/{activity_log_alert_for_service_health => activity_log_alert_for_service_health_not_configured}/test/negative1.tf (100%) rename assets/queries/terraform/azure/{activity_log_alert_for_service_health => activity_log_alert_for_service_health_not_configured}/test/positive1.tf (100%) rename assets/queries/terraform/azure/{activity_log_alert_for_service_health => activity_log_alert_for_service_health_not_configured}/test/positive2/positive2_1.tf (100%) rename assets/queries/terraform/azure/{activity_log_alert_for_service_health => activity_log_alert_for_service_health_not_configured}/test/positive2/positive2_2.tf (100%) rename assets/queries/terraform/azure/{activity_log_alert_for_service_health => activity_log_alert_for_service_health_not_configured}/test/positive2/positive_expected_result.json (51%) rename assets/queries/terraform/azure/{activity_log_alert_for_service_health => activity_log_alert_for_service_health_not_configured}/test/positive3/positive3_1.tf (100%) rename assets/queries/terraform/azure/{activity_log_alert_for_service_health => activity_log_alert_for_service_health_not_configured}/test/positive3/positive3_2.tf (100%) rename assets/queries/terraform/azure/{activity_log_alert_for_service_health => activity_log_alert_for_service_health_not_configured}/test/positive3/positive_expected_result.json (51%) rename assets/queries/terraform/azure/{activity_log_alert_for_service_health => activity_log_alert_for_service_health_not_configured}/test/positive4/positive4_1.tf (100%) rename assets/queries/terraform/azure/{activity_log_alert_for_service_health => activity_log_alert_for_service_health_not_configured}/test/positive4/positive4_2.tf (100%) rename assets/queries/terraform/azure/{activity_log_alert_for_service_health => activity_log_alert_for_service_health_not_configured}/test/positive4/positive_expected_result.json (51%) rename assets/queries/terraform/azure/{activity_log_alert_for_service_health => activity_log_alert_for_service_health_not_configured}/test/positive5/positive5_1.tf (100%) rename assets/queries/terraform/azure/{activity_log_alert_for_service_health => activity_log_alert_for_service_health_not_configured}/test/positive5/positive5_2.tf (100%) rename assets/queries/terraform/azure/{activity_log_alert_for_service_health => activity_log_alert_for_service_health_not_configured}/test/positive5/positive_expected_result.json (51%) rename assets/queries/terraform/azure/{activity_log_alert_for_service_health => activity_log_alert_for_service_health_not_configured}/test/positive6/positive6_1.tf (100%) rename assets/queries/terraform/azure/{activity_log_alert_for_service_health => activity_log_alert_for_service_health_not_configured}/test/positive6/positive6_2.tf (100%) rename assets/queries/terraform/azure/{activity_log_alert_for_service_health => activity_log_alert_for_service_health_not_configured}/test/positive6/positive_expected_result.json (51%) rename assets/queries/terraform/azure/{activity_log_alert_for_service_health => activity_log_alert_for_service_health_not_configured}/test/positive_expected_result.json (50%) diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/metadata.json b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/metadata.json similarity index 86% rename from assets/queries/terraform/azure/activity_log_alert_for_service_health/metadata.json rename to assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/metadata.json index f394481c476..bdb647610c4 100644 --- a/assets/queries/terraform/azure/activity_log_alert_for_service_health/metadata.json +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/metadata.json @@ -1,6 +1,6 @@ { "id": "f677bd92-3922-4e75-8f0c-2c0f8fbc9609", - "queryName": "Beta - Activity Log Alert For Service Health", + "queryName": "Beta - Activity Log Alert For Service Health Not Configured", "severity": "MEDIUM", "category": "Observability", "descriptionText": "There should be a 'azurerm_monitor_activity_log_alert' resource configured to capture service health events", diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/query.rego b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/query.rego similarity index 100% rename from assets/queries/terraform/azure/activity_log_alert_for_service_health/query.rego rename to assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/query.rego diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/negative1.tf b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/negative1.tf similarity index 100% rename from assets/queries/terraform/azure/activity_log_alert_for_service_health/test/negative1.tf rename to assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/negative1.tf diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive1.tf b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive1.tf similarity index 100% rename from assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive1.tf rename to assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive1.tf diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive2/positive2_1.tf b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive2/positive2_1.tf similarity index 100% rename from assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive2/positive2_1.tf rename to assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive2/positive2_1.tf diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive2/positive2_2.tf b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive2/positive2_2.tf similarity index 100% rename from assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive2/positive2_2.tf rename to assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive2/positive2_2.tf diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive2/positive_expected_result.json b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive2/positive_expected_result.json similarity index 51% rename from assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive2/positive_expected_result.json rename to assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive2/positive_expected_result.json index 545fa7848dc..8e854727ca9 100644 --- a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive2/positive_expected_result.json +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive2/positive_expected_result.json @@ -1,18 +1,18 @@ [ { - "queryName": "Beta - Activity Log Alert For Service Health", + "queryName": "Beta - Activity Log Alert For Service Health Not Configured", "severity": "MEDIUM", "line": 8, "fileName": "positive2_1.tf" }, { - "queryName": "Beta - Activity Log Alert For Service Health", + "queryName": "Beta - Activity Log Alert For Service Health Not Configured", "severity": "MEDIUM", "line": 28, "fileName": "positive2_1.tf" }, { - "queryName": "Beta - Activity Log Alert For Service Health", + "queryName": "Beta - Activity Log Alert For Service Health Not Configured", "severity": "MEDIUM", "line": 8, "fileName": "positive2_2.tf" diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive3/positive3_1.tf b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive3/positive3_1.tf similarity index 100% rename from assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive3/positive3_1.tf rename to assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive3/positive3_1.tf diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive3/positive3_2.tf b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive3/positive3_2.tf similarity index 100% rename from assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive3/positive3_2.tf rename to assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive3/positive3_2.tf diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive3/positive_expected_result.json b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive3/positive_expected_result.json similarity index 51% rename from assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive3/positive_expected_result.json rename to assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive3/positive_expected_result.json index f04520dad90..7f2aecf8f06 100644 --- a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive3/positive_expected_result.json +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive3/positive_expected_result.json @@ -1,12 +1,12 @@ [ { - "queryName": "Beta - Activity Log Alert For Service Health", + "queryName": "Beta - Activity Log Alert For Service Health Not Configured", "severity": "MEDIUM", "line": 9, "fileName": "positive3_1.tf" }, { - "queryName": "Beta - Activity Log Alert For Service Health", + "queryName": "Beta - Activity Log Alert For Service Health Not Configured", "severity": "MEDIUM", "line": 9, "fileName": "positive3_2.tf" diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive4/positive4_1.tf b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive4/positive4_1.tf similarity index 100% rename from assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive4/positive4_1.tf rename to assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive4/positive4_1.tf diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive4/positive4_2.tf b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive4/positive4_2.tf similarity index 100% rename from assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive4/positive4_2.tf rename to assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive4/positive4_2.tf diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive4/positive_expected_result.json b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive4/positive_expected_result.json similarity index 51% rename from assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive4/positive_expected_result.json rename to assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive4/positive_expected_result.json index 20fb51db65a..0063cec5071 100644 --- a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive4/positive_expected_result.json +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive4/positive_expected_result.json @@ -1,12 +1,12 @@ [ { - "queryName": "Beta - Activity Log Alert For Service Health", + "queryName": "Beta - Activity Log Alert For Service Health Not Configured", "severity": "MEDIUM", "line": 9, "fileName": "positive4_1.tf" }, { - "queryName": "Beta - Activity Log Alert For Service Health", + "queryName": "Beta - Activity Log Alert For Service Health Not Configured", "severity": "MEDIUM", "line": 29, "fileName": "positive4_1.tf" diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive5/positive5_1.tf b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive5/positive5_1.tf similarity index 100% rename from assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive5/positive5_1.tf rename to assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive5/positive5_1.tf diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive5/positive5_2.tf b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive5/positive5_2.tf similarity index 100% rename from assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive5/positive5_2.tf rename to assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive5/positive5_2.tf diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive5/positive_expected_result.json b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive5/positive_expected_result.json similarity index 51% rename from assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive5/positive_expected_result.json rename to assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive5/positive_expected_result.json index 6cfe66b8d7b..55b26065a68 100644 --- a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive5/positive_expected_result.json +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive5/positive_expected_result.json @@ -1,6 +1,6 @@ [ { - "queryName": "Beta - Activity Log Alert For Service Health", + "queryName": "Beta - Activity Log Alert For Service Health Not Configured", "severity": "MEDIUM", "line": 9, "fileName": "positive5_1.tf" diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive6/positive6_1.tf b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive6/positive6_1.tf similarity index 100% rename from assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive6/positive6_1.tf rename to assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive6/positive6_1.tf diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive6/positive6_2.tf b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive6/positive6_2.tf similarity index 100% rename from assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive6/positive6_2.tf rename to assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive6/positive6_2.tf diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive6/positive_expected_result.json b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive6/positive_expected_result.json similarity index 51% rename from assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive6/positive_expected_result.json rename to assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive6/positive_expected_result.json index 7feb2343c67..88278bcc16b 100644 --- a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive6/positive_expected_result.json +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive6/positive_expected_result.json @@ -1,6 +1,6 @@ [ { - "queryName": "Beta - Activity Log Alert For Service Health", + "queryName": "Beta - Activity Log Alert For Service Health Not Configured", "severity": "MEDIUM", "line": 3, "fileName": "positive6_1.tf" diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive_expected_result.json b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive_expected_result.json similarity index 50% rename from assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive_expected_result.json rename to assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive_expected_result.json index 1060d086da5..3947db2a18e 100644 --- a/assets/queries/terraform/azure/activity_log_alert_for_service_health/test/positive_expected_result.json +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive_expected_result.json @@ -1,12 +1,12 @@ [ { - "queryName": "Beta - Activity Log Alert For Service Health", + "queryName": "Beta - Activity Log Alert For Service Health Not Configured", "severity": "MEDIUM", "line": 8, "fileName": "positive1.tf" }, { - "queryName": "Beta - Activity Log Alert For Service Health", + "queryName": "Beta - Activity Log Alert For Service Health Not Configured", "severity": "MEDIUM", "line": 28, "fileName": "positive1.tf" diff --git a/assets/similarityID_transition/terraform_azure.yaml b/assets/similarityID_transition/terraform_azure.yaml index 962b29184e6..ecb1ec35870 100644 --- a/assets/similarityID_transition/terraform_azure.yaml +++ b/assets/similarityID_transition/terraform_azure.yaml @@ -4,6 +4,6 @@ similarityIDChangeList: observations: "" change: 5 - queryId: f677bd92-3922-4e75-8f0c-2c0f8fbc9609 - queryName: Beta - Activity Log Alert For Service Health + queryName: Beta - Activity Log Alert For Service Health Not Configured observations: "" change: 2 From 0c9bbfd1c29b3be35557f4881a23c673011de9ab Mon Sep 17 00:00:00 2001 From: Vasco Oliveira <200926503+cx-vasco-oliveira@users.noreply.github.com> Date: Thu, 4 Dec 2025 16:05:47 +0000 Subject: [PATCH 09/12] Added tests for complete QA Accuracy Validation for this query (#7897) --- .../test/negative1.tf | 39 ++++++++++++++++++- .../test/positive2/positive2_1.tf | 2 +- .../test/positive2/positive2_2.tf | 2 +- .../test/positive7/positive7.tf | 1 + .../positive7/positive_expected_result.json | 8 ++++ 5 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive7/positive7.tf create mode 100644 assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive7/positive_expected_result.json diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/negative1.tf b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/negative1.tf index d65bdf7abe3..7fde3967a5f 100644 --- a/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/negative1.tf +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/negative1.tf @@ -18,9 +18,34 @@ resource "azurerm_monitor_activity_log_alert" "negative1" { } } +resource "azurerm_monitor_activity_log_alert" "negative2" { + name = "ServiceHealthActivityLogAlert" + resource_group_name = var.resource_group_name + scopes = [data.azurerm_subscription.current.id] + description = "Alert for Azure Service Health events" + enabled = true + + criteria { + category = "ServiceHealth" + + service_health { + events = [ + "Incident", + "Maintenance", + "Security", + "Informational" + ] + } + } + + action { + action_group_id = azurerm_monitor_action_group.notify_team.id + } +} + data "azurerm_subscription" "current" {} -resource "azurerm_monitor_activity_log_alert" "negative2" { +resource "azurerm_monitor_activity_log_alert" "negative3" { name = "ServiceHealthActivityLogAlert" resource_group_name = var.resource_group_name scopes = [data.azurerm_subscription.secondary.id] @@ -43,3 +68,15 @@ resource "azurerm_monitor_activity_log_alert" "negative2" { data "azurerm_subscription" "secondary" { subscription_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" } + +resource "azurerm_monitor_activity_log_alert" "negative4" { + name = "ServiceHealthActivityLogAlert" + resource_group_name = var.resource_group_name + scopes = [azurerm_resource_group.example.id] # The scope needs to be a subscription + description = "Alert for Azure Service Health events" + enabled = true + + action { + action_group_id = azurerm_monitor_action_group.notify_team.id + } +} \ No newline at end of file diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive2/positive2_1.tf b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive2/positive2_1.tf index e215bde1d7f..10cdd06dde2 100644 --- a/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive2/positive2_1.tf +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive2/positive2_1.tf @@ -26,7 +26,7 @@ resource "azurerm_monitor_activity_log_alert" "positive2_2" { enabled = true criteria { - category = "ServiceHealth" # Wrong category + category = "ServiceHealth" service_health { # Missing 'events' diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive2/positive2_2.tf b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive2/positive2_2.tf index cefa62a1289..b69e20d4ddc 100644 --- a/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive2/positive2_2.tf +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive2/positive2_2.tf @@ -6,7 +6,7 @@ resource "azurerm_monitor_activity_log_alert" "positive2_3" { enabled = true criteria { - category = "ServiceHealth" # Wrong category + category = "ServiceHealth" # Missing 'service_health' } diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive7/positive7.tf b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive7/positive7.tf new file mode 100644 index 00000000000..53ffd847f28 --- /dev/null +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive7/positive7.tf @@ -0,0 +1 @@ +data "azurerm_subscription" "positive7" {} \ No newline at end of file diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive7/positive_expected_result.json b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive7/positive_expected_result.json new file mode 100644 index 00000000000..b7773a15a61 --- /dev/null +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive7/positive_expected_result.json @@ -0,0 +1,8 @@ +[ + { + "queryName": "Beta - Activity Log Alert For Service Health Not Configured", + "severity": "MEDIUM", + "line": 3, + "fileName": "positive7.tf" + } +] From 57dc0ad7936bc43f932e224be800301273bf8a58 Mon Sep 17 00:00:00 2001 From: Vasco Oliveira <200926503+cx-vasco-oliveira@users.noreply.github.com> Date: Thu, 4 Dec 2025 17:23:30 +0000 Subject: [PATCH 10/12] Fix test for complete QA Accuracy Validation for this query (#7898) --- .../test/positive7/positive_expected_result.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive7/positive_expected_result.json b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive7/positive_expected_result.json index b7773a15a61..831466147c6 100644 --- a/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive7/positive_expected_result.json +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive7/positive_expected_result.json @@ -2,7 +2,7 @@ { "queryName": "Beta - Activity Log Alert For Service Health Not Configured", "severity": "MEDIUM", - "line": 3, + "line": 1, "fileName": "positive7.tf" } ] From 9d787b3a90844859b646702bcb625d1dc3c0bc9c Mon Sep 17 00:00:00 2001 From: Vasco Oliveira <200926503+cx-vasco-oliveira@users.noreply.github.com> Date: Thu, 4 Dec 2025 18:00:05 +0000 Subject: [PATCH 11/12] Fixed test for complete QA Accuracy Validation for this query (#7900) --- .../test/negative1.tf | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/negative1.tf b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/negative1.tf index 7fde3967a5f..d4a16bd3edc 100644 --- a/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/negative1.tf +++ b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/negative1.tf @@ -67,16 +67,4 @@ resource "azurerm_monitor_activity_log_alert" "negative3" { data "azurerm_subscription" "secondary" { subscription_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -} - -resource "azurerm_monitor_activity_log_alert" "negative4" { - name = "ServiceHealthActivityLogAlert" - resource_group_name = var.resource_group_name - scopes = [azurerm_resource_group.example.id] # The scope needs to be a subscription - description = "Alert for Azure Service Health events" - enabled = true - - action { - action_group_id = azurerm_monitor_action_group.notify_team.id - } } \ No newline at end of file From 862810ed4546ecf1af0050dccc450b6e5dee4767 Mon Sep 17 00:00:00 2001 From: Vasco Oliveira <200926503+cx-vasco-oliveira@users.noreply.github.com> Date: Fri, 5 Dec 2025 10:24:15 +0000 Subject: [PATCH 12/12] Fixed test for complete QA Accuracy Validation for this query (#7902) --- .../test/positive7/positive7.tf | 1 - .../test/positive7/positive_expected_result.json | 8 -------- 2 files changed, 9 deletions(-) delete mode 100644 assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive7/positive7.tf delete mode 100644 assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive7/positive_expected_result.json diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive7/positive7.tf b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive7/positive7.tf deleted file mode 100644 index 53ffd847f28..00000000000 --- a/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive7/positive7.tf +++ /dev/null @@ -1 +0,0 @@ -data "azurerm_subscription" "positive7" {} \ No newline at end of file diff --git a/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive7/positive_expected_result.json b/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive7/positive_expected_result.json deleted file mode 100644 index 831466147c6..00000000000 --- a/assets/queries/terraform/azure/activity_log_alert_for_service_health_not_configured/test/positive7/positive_expected_result.json +++ /dev/null @@ -1,8 +0,0 @@ -[ - { - "queryName": "Beta - Activity Log Alert For Service Health Not Configured", - "severity": "MEDIUM", - "line": 1, - "fileName": "positive7.tf" - } -]