# ----------------------------------------------------------------------------- # release-aggregate.rego # Sprint: SPRINT_20260118_027_Policy_cve_release_gates # Task: TASK-027-08 - OPA/Rego Policy Examples # Description: Aggregate CVE count limits per release # ----------------------------------------------------------------------------- package stellaops.gates.aggregate import future.keywords.if import future.keywords.in # Default allow if all counts within limits default allow = true # Block if any severity count exceeds limit allow = false if { counts.critical > max_critical } allow = false if { counts.high > max_high } allow = false if { counts.medium > max_medium } allow = false if { max_low != null counts.low > max_low } allow = false if { max_total != null counts.total > max_total } # Get CVEs to count (optionally filtered) counted_cves := [cve | some cve in input.cve_findings should_count(cve) ] # Determine if CVE should be counted should_count(cve) if { not config_only_reachable not config_exclude_suppressed } should_count(cve) if { config_only_reachable cve.is_reachable == true not config_exclude_suppressed } should_count(cve) if { not config_only_reachable config_exclude_suppressed not cve.is_suppressed } should_count(cve) if { config_only_reachable cve.is_reachable == true config_exclude_suppressed not cve.is_suppressed } # Classify severity from CVSS score severity(cve) := "critical" if { cve.cvss_score >= 9.0 } severity(cve) := "high" if { cve.cvss_score >= 7.0 cve.cvss_score < 9.0 } severity(cve) := "medium" if { cve.cvss_score >= 4.0 cve.cvss_score < 7.0 } severity(cve) := "low" if { cve.cvss_score >= 0.1 cve.cvss_score < 4.0 } severity(cve) := "unknown" if { not cve.cvss_score } # Count CVEs by severity counts := { "critical": count([c | some c in counted_cves; severity(c) == "critical"]), "high": count([c | some c in counted_cves; severity(c) == "high"]), "medium": count([c | some c in counted_cves; severity(c) == "medium"]), "low": count([c | some c in counted_cves; severity(c) == "low"]), "unknown": count([c | some c in counted_cves; severity(c) == "unknown"]), "total": count(counted_cves), } # Get limits with environment override support max_critical := env_config.max_critical if { env_config := input.config.environments[input.environment] env_config.max_critical != null } else := input.config.max_critical if { input.config.max_critical != null } else := 0 # Default: no critical allowed max_high := env_config.max_high if { env_config := input.config.environments[input.environment] env_config.max_high != null } else := input.config.max_high if { input.config.max_high != null } else := 3 # Default: max 3 high max_medium := env_config.max_medium if { env_config := input.config.environments[input.environment] env_config.max_medium != null } else := input.config.max_medium if { input.config.max_medium != null } else := 20 # Default: max 20 medium max_low := env_config.max_low if { env_config := input.config.environments[input.environment] env_config.max_low != null } else := input.config.max_low if { input.config.max_low != null } else := null # Default: unlimited max_total := env_config.max_total if { env_config := input.config.environments[input.environment] env_config.max_total != null } else := input.config.max_total if { input.config.max_total != null } else := null # Default: unlimited # Configuration flags config_only_reachable if { input.config.only_reachable == true } config_exclude_suppressed if { input.config.count_suppressed == false } config_exclude_suppressed if { not input.config.count_suppressed } # Denial messages deny[msg] if { counts.critical > max_critical msg := sprintf("Critical CVE count exceeds limit: %d > %d", [counts.critical, max_critical]) } deny[msg] if { counts.high > max_high msg := sprintf("High CVE count exceeds limit: %d > %d", [counts.high, max_high]) } deny[msg] if { counts.medium > max_medium msg := sprintf("Medium CVE count exceeds limit: %d > %d", [counts.medium, max_medium]) } deny[msg] if { max_low != null counts.low > max_low msg := sprintf("Low CVE count exceeds limit: %d > %d", [counts.low, max_low]) } deny[msg] if { max_total != null counts.total > max_total msg := sprintf("Total CVE count exceeds limit: %d > %d", [counts.total, max_total]) } # Summary for reporting summary := { "counts": counts, "limits": { "max_critical": max_critical, "max_high": max_high, "max_medium": max_medium, "max_low": max_low, "max_total": max_total, }, "environment": input.environment, }