Skip to content
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"id": "b3b9ce2f-c229-4133-9a2b-4e649cf2347e",
"queryName": "Beta - Activity Log Alert For Delete Public IP Address Rule Not Configured",
"severity": "MEDIUM",
"category": "Observability",
"descriptionText": "There should be a 'azurerm_monitor_activity_log_alert' resource configured to capture 'delete public ip address rule' events",
"descriptionUrl": "https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/monitor_activity_log_alert",
"platform": "Terraform",
"descriptionID": "b3b9ce2f",
"cloudProvider": "azure",
"cwe": "778",
"riskScore": "3.0",
"experimental": "true"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
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": results.issueType,
"keyExpectedValue": "A 'azurerm_monitor_activity_log_alert' resource that monitors 'delete public ip address rule' 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 == "Administrative"
resources[doc_index][x].criteria.operation_name == "Microsoft.Network/publicIPAddresses/delete"
not has_filter(resources[doc_index][x].criteria)
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 == "Administrative"
resource.criteria.operation_name == "Microsoft.Network/publicIPAddresses/delete"
not has_filter(resource.criteria)}
}
logs[_] != {}

} else = {"result" : "has_log_with_filter", "logs": logs} {
logs := {doc_index: filtered |
resources[doc_index]
filtered := {key: resource |
resource := resources[doc_index][key]
resource.criteria.category == "Administrative"
resource.criteria.operation_name == "Microsoft.Network/publicIPAddresses/delete"}
}
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"

results := [z |
log := value.logs[doc_id][name]
z := {
"doc_id" : doc_id,
"resource" : log,
"issueType": "MissingAttribute",
"name" : name,
"keyActualValue" : sprintf("The 'azurerm_monitor_activity_log_alert[%s]' resource monitors 'delete public ip address rule' 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_with_filter"

results := [z |
filters = get_filters(value.logs[doc_id][name].criteria)
z := {
"doc_id" : doc_id,
"resource" : value.logs[doc_id][name],
"issueType": "IncorrectValue",
"name" : name,
"keyActualValue" : sprintf("The 'azurerm_monitor_activity_log_alert[%s]' resource monitors 'delete public ip address rule' events but sets %d filter(s): %s", [name, count(filters),concat(", ",filters)])
}]

}

has_filter(criteria) {
common_lib.valid_key(criteria, filter_fields[_])
}

get_filters(criteria) = [x |
y := filter_fields[_]
common_lib.valid_key(criteria, y)
x := y
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
resource "azurerm_monitor_activity_log_alert" "negative1" {
name = "example-activitylogalert"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
scopes = [azurerm_resource_group.example.id]
description = "Negative sample"

criteria {
resource_id = azurerm_storage_account.to_monitor.id
operation_name = "Microsoft.Network/publicIPAddresses/delete"
category = "Administrative"
}

action {
action_group_id = azurerm_monitor_action_group.main.id

webhook_properties = {
from = "terraform"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# In the future this should flag the project (currently impossible) and request for a valid "log_alert" to be defined
resource "azurerm_monitor_activity_log_alert" "positive1_1" {
name = "example-activitylogalert"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
scopes = [azurerm_resource_group.example.id]
description = "Positive sample"

criteria {
resource_id = azurerm_storage_account.to_monitor.id
operation_name = "Microsoft.Storage/storageAccounts/write" # wrong operation name
category = "Administrative"
}

action {
action_group_id = azurerm_monitor_action_group.main.id
}
}

resource "azurerm_monitor_activity_log_alert" "positive1_2" {
name = "example-activitylogalert"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
scopes = [azurerm_resource_group.example.id]
description = "Positive sample"

criteria {
resource_id = azurerm_storage_account.to_monitor.id
operation_name = "Microsoft.Network/publicIPAddresses/delete"
category = "Policy" # wrong category
}

action {
action_group_id = azurerm_monitor_action_group.main.id
}
}

resource "azurerm_monitor_activity_log_alert" "positive1_3" {
name = "example-activitylogalert"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
scopes = [azurerm_resource_group.example.id]
description = "Positive sample"

criteria {
resource_id = azurerm_storage_account.to_monitor.id
operation_name = "Microsoft.Storage/storageAccounts/write" # wrong operation name
category = "Policy" # wrong category
}

action {
action_group_id = azurerm_monitor_action_group.main.id
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Case of correct "operation_name" and "category" but a type of filter is set
resource "azurerm_monitor_activity_log_alert" "positive2_1" {
name = "example-activitylogalert"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
scopes = [azurerm_resource_group.example.id]
description = "Positive sample"

criteria {
resource_id = azurerm_storage_account.to_monitor.id
operation_name = "Microsoft.Network/publicIPAddresses/delete"
category = "Administrative"
caller = "admin@contoso.com" # filters by caller
}

action {
action_group_id = azurerm_monitor_action_group.main.id
}
}

resource "azurerm_monitor_activity_log_alert" "positive2_2" {
name = "example-activitylogalert"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
scopes = [azurerm_resource_group.example.id]
description = "Positive sample"

criteria {
resource_id = azurerm_storage_account.to_monitor.id
operation_name = "Microsoft.Network/publicIPAddresses/delete"
category = "Administrative"
level = "Informational" # filters by level
}

action {
action_group_id = azurerm_monitor_action_group.main.id
}
}

resource "azurerm_monitor_activity_log_alert" "positive2_3" {
name = "example-activitylogalert"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
scopes = [azurerm_resource_group.example.id]
description = "Positive sample"

criteria {
resource_id = azurerm_storage_account.to_monitor.id
operation_name = "Microsoft.Network/publicIPAddresses/delete"
category = "Administrative"
levels = ["Informational", "Warning"] # filters by levels
}

action {
action_group_id = azurerm_monitor_action_group.main.id
}
}

resource "azurerm_monitor_activity_log_alert" "positive2_4" {
name = "example-activitylogalert"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
scopes = [azurerm_resource_group.example.id]
description = "Positive sample"

criteria {
resource_id = azurerm_storage_account.to_monitor.id
operation_name = "Microsoft.Network/publicIPAddresses/delete"
category = "Administrative"
status = "Succeeded" # filters by status
}

action {
action_group_id = azurerm_monitor_action_group.main.id
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
resource "azurerm_monitor_activity_log_alert" "positive2_5" {
name = "example-activitylogalert"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
scopes = [azurerm_resource_group.example.id]
description = "Positive sample"

criteria {
resource_id = azurerm_storage_account.to_monitor.id
operation_name = "Microsoft.Network/publicIPAddresses/delete"
category = "Administrative"
statuses = ["Succeeded", "Failed"] # filters by statuses
}

action {
action_group_id = azurerm_monitor_action_group.main.id
}
}

resource "azurerm_monitor_activity_log_alert" "positive2_6" {
name = "example-activitylogalert"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
scopes = [azurerm_resource_group.example.id]
description = "Positive sample"

criteria {
resource_id = azurerm_storage_account.to_monitor.id
operation_name = "Microsoft.Network/publicIPAddresses/delete"
category = "Administrative"
sub_status = "Accepted" # filters by sub_status
}

action {
action_group_id = azurerm_monitor_action_group.main.id
}
}

resource "azurerm_monitor_activity_log_alert" "positive2_7" {
name = "example-activitylogalert"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
scopes = [azurerm_resource_group.example.id]
description = "Positive sample"

criteria {
resource_id = azurerm_storage_account.to_monitor.id
operation_name = "Microsoft.Network/publicIPAddresses/delete"
category = "Administrative"
sub_statuses = ["Accepted", "Conflict"] # filters by sub_statuses
}

action {
action_group_id = azurerm_monitor_action_group.main.id
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
[
{
"queryName": "Beta - Activity Log Alert For Delete Public IP Address Rule Not Configured",
"severity": "MEDIUM",
"line": 9,
"fileName": "positive2_1.tf"
},
{
"queryName": "Beta - Activity Log Alert For Delete Public IP Address Rule Not Configured",
"severity": "MEDIUM",
"line": 28,
"fileName": "positive2_1.tf"
},
{
"queryName": "Beta - Activity Log Alert For Delete Public IP Address Rule Not Configured",
"severity": "MEDIUM",
"line": 47,
"fileName": "positive2_1.tf"
},
{
"queryName": "Beta - Activity Log Alert For Delete Public IP Address Rule Not Configured",
"severity": "MEDIUM",
"line": 66,
"fileName": "positive2_1.tf"
},
{
"queryName": "Beta - Activity Log Alert For Delete Public IP Address Rule Not Configured",
"severity": "MEDIUM",
"line": 8,
"fileName": "positive2_2.tf"
},
{
"queryName": "Beta - Activity Log Alert For Delete Public IP Address Rule Not Configured",
"severity": "MEDIUM",
"line": 27,
"fileName": "positive2_2.tf"
},
{
"queryName": "Beta - Activity Log Alert For Delete Public IP Address Rule Not Configured",
"severity": "MEDIUM",
"line": 46,
"fileName": "positive2_2.tf"
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Case of correct "operation_name" and "category" but the "action.action_group_id" field is missing
resource "azurerm_monitor_activity_log_alert" "positive3_1" {
name = "example-activitylogalert"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
scopes = [azurerm_resource_group.example.id]
description = "Positive sample"

criteria {
resource_id = azurerm_storage_account.to_monitor.id
operation_name = "Microsoft.Network/publicIPAddresses/delete"
category = "Administrative"
}

# Missing action
}
Loading
Loading