--- # promtool unit tests for platform/vuln-scanner/alerts.yaml (R-VULN-06). # # Found by platform/monitoring/tests/run.sh through the COMPANION convention. Run just this file with # platform/monitoring/tests/run.sh platform/vuln-scanner/alerts.promtool-test.yaml # # Each rule is pinned both ways. VulnScanStale and VulnTriageBotSilent additionally pin the two cases # the spec names by hand: the metric ABSENT must FIRE, and a metric that vanishes must RE-FIRE. # conformance/tests/l0-static/vuln-alerts-unit-tested reads this file and fails if any of those cases # is removed. # # Timestamps: promtool evaluates from t=0, so a timestamp series can equal its own evaluation time # with `0+60x` at a 1m interval (time() - value == 0: fresh). rule_files: - alerts.rules.yaml evaluation_interval: 1m tests: - interval: 1m name: healthy - fresh run, fresh database, heartbeat, zero backlog, nothing fires input_series: - series: 'vuln_scanner_last_complete_run_timestamp_seconds{namespace="vuln-scanner"}' values: '0+60x60' - series: 'vuln_scanner_database_updated_timestamp_seconds{namespace="vuln-scanner"}' values: '0+60x60' - series: 'vuln_scanner_triage_heartbeat_timestamp_seconds{namespace="vuln-scanner"}' values: '0+60x60' - series: 'vuln_scanner_failed_targets_over_24h{namespace="vuln-scanner"}' values: '0x60' - series: 'vuln_scanner_critical_fix_overdue{namespace="vuln-scanner"}' values: '0x60' promql_expr_test: - expr: 'count(ALERTS{alertname=~"Vuln.*"})' eval_time: 50m exp_samples: [] - interval: 1m name: scan stale - last complete run older than 26h fires after the for window input_series: - series: 'vuln_scanner_last_complete_run_timestamp_seconds{namespace="vuln-scanner"}' values: '0x1600' promql_expr_test: - expr: 'ALERTS{alertname="VulnScanStale", alertstate="firing"}' eval_time: 1559m exp_samples: [] - expr: 'ALERTS{alertname="VulnScanStale", alertstate="firing"}' eval_time: 1590m exp_samples: - labels: 'ALERTS{alertname="VulnScanStale", alertstate="firing", severity="warning"}' value: 1 - interval: 1m name: scan stale ABSENT - metric never existed, VulnScanStale still fires input_series: # A healthy, unrelated metric proves this is the absent() arm, not a broken test file. - series: 'vuln_scanner_failed_targets_over_24h{namespace="vuln-scanner"}' values: '0x60' promql_expr_test: - expr: 'ALERTS{alertname="VulnScanStale", alertstate="firing"}' eval_time: 20m exp_samples: - labels: 'ALERTS{alertname="VulnScanStale", alertstate="firing", severity="warning"}' value: 1 - interval: 1m name: scan metric VANISHES - a scanner that dies re-fires instead of latching clear input_series: - series: 'vuln_scanner_last_complete_run_timestamp_seconds{namespace="vuln-scanner"}' values: '0+60x20 stale' promql_expr_test: - expr: 'ALERTS{alertname="VulnScanStale", alertstate="firing"}' eval_time: 18m exp_samples: [] - expr: 'ALERTS{alertname="VulnScanStale", alertstate="firing"}' eval_time: 40m exp_samples: - labels: 'ALERTS{alertname="VulnScanStale", alertstate="firing", severity="warning"}' value: 1 - interval: 1m name: database stale - older than 48h fires after the for window input_series: - series: 'vuln_scanner_database_updated_timestamp_seconds{namespace="vuln-scanner"}' values: '0x2960' promql_expr_test: - expr: 'ALERTS{alertname="VulnDatabaseStale", alertstate="firing"}' eval_time: 2870m exp_samples: [] - expr: 'ALERTS{alertname="VulnDatabaseStale", alertstate="firing"}' eval_time: 2900m exp_samples: - labels: 'ALERTS{alertname="VulnDatabaseStale", alertstate="firing", severity="warning"}' value: 1 - interval: 1m name: coverage gap - a failed target over 24h fires, zero is quiet input_series: - series: 'vuln_scanner_failed_targets_over_24h{namespace="vuln-scanner"}' values: '0x20 3x40' promql_expr_test: - expr: 'ALERTS{alertname="VulnCoverageGap", alertstate="firing"}' eval_time: 25m exp_samples: [] - expr: 'ALERTS{alertname="VulnCoverageGap", alertstate="firing"}' eval_time: 40m exp_samples: - labels: 'ALERTS{alertname="VulnCoverageGap", alertstate="firing", severity="warning"}' value: 1 - interval: 1m name: critical fix overdue - fires, one grouped alert instance input_series: - series: 'vuln_scanner_critical_fix_overdue{namespace="vuln-scanner"}' values: '0x20 12x40' promql_expr_test: - expr: 'ALERTS{alertname="VulnCriticalFixAvailable", alertstate="firing"}' eval_time: 25m exp_samples: [] - expr: 'ALERTS{alertname="VulnCriticalFixAvailable", alertstate="firing"}' eval_time: 40m exp_samples: - labels: 'ALERTS{alertname="VulnCriticalFixAvailable", alertstate="firing", severity="warning"}' value: 1 - expr: 'count(ALERTS{alertname="VulnCriticalFixAvailable", alertstate="firing"})' eval_time: 40m exp_samples: - labels: '{}' value: 1 - interval: 1m name: triage bot silent - last heartbeat older than 26h fires after the for window input_series: - series: 'vuln_scanner_triage_heartbeat_timestamp_seconds{namespace="vuln-scanner"}' values: '0x1600' promql_expr_test: - expr: 'ALERTS{alertname="VulnTriageBotSilent", alertstate="firing"}' eval_time: 1559m exp_samples: [] - expr: 'ALERTS{alertname="VulnTriageBotSilent", alertstate="firing"}' eval_time: 1590m exp_samples: - labels: 'ALERTS{alertname="VulnTriageBotSilent", alertstate="firing", severity="warning"}' value: 1 - interval: 1m name: triage bot silent ABSENT - no heartbeat metric ever, VulnTriageBotSilent still fires input_series: - series: 'vuln_scanner_failed_targets_over_24h{namespace="vuln-scanner"}' values: '0x60' promql_expr_test: - expr: 'ALERTS{alertname="VulnTriageBotSilent", alertstate="firing"}' eval_time: 20m exp_samples: - labels: 'ALERTS{alertname="VulnTriageBotSilent", alertstate="firing", severity="warning"}' value: 1 - interval: 1m name: triage heartbeat VANISHES - re-fires instead of latching clear input_series: - series: 'vuln_scanner_triage_heartbeat_timestamp_seconds{namespace="vuln-scanner"}' values: '0+60x20 stale' promql_expr_test: - expr: 'ALERTS{alertname="VulnTriageBotSilent", alertstate="firing"}' eval_time: 40m exp_samples: - labels: 'ALERTS{alertname="VulnTriageBotSilent", alertstate="firing", severity="warning"}' value: 1