diff --git a/infrastructure/modules/key-vault/alerts.tf b/infrastructure/modules/key-vault/alerts.tf index 2f0200ee..623c2380 100644 --- a/infrastructure/modules/key-vault/alerts.tf +++ b/infrastructure/modules/key-vault/alerts.tf @@ -95,3 +95,101 @@ QUERY ] } } + +resource "azurerm_monitor_scheduled_query_rules_alert_v2" "kv_certificate_near_expiry" { + count = var.enable_alerting == true ? 1 : 0 + + name = "${azurerm_key_vault.keyvault.name}-certificate-near-expiry" + resource_group_name = var.resource_group_name_monitoring != null ? var.resource_group_name_monitoring : var.resource_group_name + location = var.location + + evaluation_frequency = var.certificate_near_expiry_alert.evaluation_frequency + window_duration = var.certificate_near_expiry_alert.window_duration + scopes = [azurerm_key_vault.keyvault.id] + severity = 2 + + criteria { + query = <<-QUERY +AzureDiagnostics +| where ResourceProvider == "MICROSOFT.KEYVAULT" +| where OperationName contains "CertificateNearExpiry" +| project + CertificateName = column_ifexists("eventGridEventProperties_data_ObjectName_s","") +| summarize Events=count() by CertificateName +QUERY + + time_aggregation_method = "Total" + threshold = var.certificate_near_expiry_alert.threshold + operator = "GreaterThanOrEqual" + + resource_id_column = "CertificateName" + metric_measure_column = "Events" + + dimension { + name = "CertificateName" + operator = "Include" + values = ["*"] + } + } + + description = "The Key Vault certificate is nearing expiration." + + action { + action_groups = [var.action_group_id] + } + + lifecycle { + ignore_changes = [ + tags + ] + } +} + +resource "azurerm_monitor_scheduled_query_rules_alert_v2" "kv_certificate_expired" { + count = var.enable_alerting == true ? 1 : 0 + + name = "${azurerm_key_vault.keyvault.name}-certificate-expired" + resource_group_name = var.resource_group_name_monitoring != null ? var.resource_group_name_monitoring : var.resource_group_name + location = var.location + + evaluation_frequency = var.certificate_expired_alert.evaluation_frequency + window_duration = var.certificate_expired_alert.window_duration + scopes = [azurerm_key_vault.keyvault.id] + severity = 2 + + criteria { + query = <<-QUERY +AzureDiagnostics +| where ResourceProvider == "MICROSOFT.KEYVAULT" +| where OperationName contains "CertificateExpired" +| project + CertificateName = column_ifexists("eventGridEventProperties_data_ObjectName_s","") +| summarize Events=count() by CertificateName +QUERY + + time_aggregation_method = "Total" + threshold = var.certificate_expired_alert.threshold + operator = "GreaterThanOrEqual" + + resource_id_column = "CertificateName" + metric_measure_column = "Events" + + dimension { + name = "CertificateName" + operator = "Include" + values = ["*"] + } + } + + description = "The Key Vault certificate has expired." + + action { + action_groups = [var.action_group_id] + } + + lifecycle { + ignore_changes = [ + tags + ] + } +} diff --git a/infrastructure/modules/key-vault/tfdocs.md b/infrastructure/modules/key-vault/tfdocs.md index 8dd88bd2..0bb170a1 100644 --- a/infrastructure/modules/key-vault/tfdocs.md +++ b/infrastructure/modules/key-vault/tfdocs.md @@ -184,6 +184,34 @@ object({ }) ``` +### [certificate\_near\_expiry\_alert](#input\_certificate\_near\_expiry\_alert) + +Description: Configuration for the Key Vault certificate near expiry alert. + +Type: + +```hcl +object({ + evaluation_frequency = string + window_duration = string + threshold = number +}) +``` + +### [secret\_certificate\_alert](#input\_certificate\_expired\_alert) + +Description: Configuration for the Key Vault certificate expired alert. + +Type: + +```hcl +object({ + evaluation_frequency = string + window_duration = string + threshold = number +}) +``` + ## Modules The following Modules are called: diff --git a/infrastructure/modules/key-vault/variables.tf b/infrastructure/modules/key-vault/variables.tf index 36e3e690..0ce79d0e 100644 --- a/infrastructure/modules/key-vault/variables.tf +++ b/infrastructure/modules/key-vault/variables.tf @@ -105,6 +105,54 @@ variable "secret_expired_alert" { } } +variable "certificate_near_expiry_alert" { + type = object({ + evaluation_frequency = string + window_duration = string + threshold = number + }) + + validation { + condition = contains( + ["PT1M", "PT5M", "PT15M", "PT30M", "PT1H", "PT6H", "PT12H", "P1D"], + var.certificate_near_expiry_alert.evaluation_frequency + ) + error_message = "certificate_near_expiry_alert.evaluation_frequency must be one of: PT1M, PT5M, PT15M, PT30M, PT1H, PT6H, PT12H, P1D" + } + + validation { + condition = contains( + ["PT1M", "PT5M", "PT15M", "PT30M", "PT1H", "PT6H", "PT12H", "P1D"], + var.certificate_near_expiry_alert.window_duration + ) + error_message = "certificate_near_expiry_alert.window_duration must be one of: PT1M, PT5M, PT15M, PT30M, PT1H, PT6H, PT12H, P1D" + } +} + +variable "certificate_expired_alert" { + type = object({ + evaluation_frequency = string + window_duration = string + threshold = number + }) + + validation { + condition = contains( + ["PT1M", "PT5M", "PT15M", "PT30M", "PT1H", "PT6H", "PT12H", "P1D"], + var.certificate_expired_alert.evaluation_frequency + ) + error_message = "certificate_expired_alert.evaluation_frequency must be one of: PT1M, PT5M, PT15M, PT30M, PT1H, PT6H, PT12H, P1D" + } + + validation { + condition = contains( + ["PT1M", "PT5M", "PT15M", "PT30M", "PT1H", "PT6H", "PT12H", "P1D"], + var.certificate_expired_alert.window_duration + ) + error_message = "certificate_expired_alert.window_duration must be one of: PT1M, PT5M, PT15M, PT30M, PT1H, PT6H, PT12H, P1D" + } +} + variable "name" { description = "The name of the Key Vault." type = string