Skip to content

Commit f55f1ff

Browse files
committed
implement multiple rules
Signed-off-by: tdruez <tdruez@aboutcode.org>
1 parent 76b0a21 commit f55f1ff

1 file changed

Lines changed: 60 additions & 7 deletions

File tree

policy/rules.py

Lines changed: 60 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,30 +15,83 @@ class BaseRule:
1515
rule_type = None
1616
label = None
1717
description = None
18+
parameters_schema = {}
1819

1920
def count_violations(self, policy_rule, product):
2021
"""Count objects violating the rule for the given product."""
2122
raise NotImplementedError
2223

2324

24-
class ComplianceAlertRule(BaseRule):
25-
rule_type = "compliance_alert"
26-
label = "Compliance Alert"
25+
class PackageBaseRule(BaseRule):
26+
"""Base for rules that count packages matching a fixed filter within a product."""
27+
28+
package_filter = {}
29+
30+
def count_violations(self, policy_rule, product):
31+
Package = apps.get_model("component_catalog", "package")
32+
33+
count = Package.objects.filter(
34+
productpackages__product=product,
35+
**self.package_filter,
36+
).count()
37+
38+
return count if count > policy_rule.threshold else 0
39+
40+
41+
class LicensePolicyErrorRule(PackageBaseRule):
42+
rule_type = "license_policy_error"
43+
label = "License Policy Error"
2744
description = (
2845
"Detects packages assigned a usage policy with a compliance alert level of 'error'."
2946
)
47+
package_filter = {"usage_policy__compliance_alert": "error"}
48+
49+
50+
class LicensePolicyWarningRule(PackageBaseRule):
51+
rule_type = "license_policy_warning"
52+
label = "License Policy Warning"
53+
description = (
54+
"Detects packages assigned a usage policy with a compliance alert level of 'warning'."
55+
)
56+
package_filter = {"usage_policy__compliance_alert": "warning"}
57+
58+
59+
class LicenseCoverageGapRule(PackageBaseRule):
60+
rule_type = "license_coverage_gap"
61+
label = "License Coverage Gap"
62+
description = (
63+
"Detects packages with no license expression, indicating a gap in license coverage."
64+
)
65+
package_filter = {"license_expression": ""}
66+
67+
68+
class VulnerabilityDetectedRule(BaseRule):
69+
rule_type = "vulnerability_detected"
70+
label = "Vulnerability Detected"
71+
description = "Detects packages with at least one known vulnerability (non-null risk score)."
72+
parameters_schema = {
73+
"min_risk_score": "Minimum risk score (0.0-10.0). Default: any vulnerability.",
74+
}
3075

3176
def count_violations(self, policy_rule, product):
3277
Package = apps.get_model("component_catalog", "package")
3378

34-
count = Package.objects.filter(
79+
packages = Package.objects.filter(
3580
productpackages__product=product,
36-
usage_policy__compliance_alert="error",
37-
).count()
81+
risk_score__isnull=False,
82+
)
83+
84+
min_risk_score = policy_rule.parameters.get("min_risk_score")
85+
if min_risk_score is not None:
86+
packages = packages.filter(risk_score__gte=min_risk_score)
3887

88+
count = packages.count()
3989
return count if count > policy_rule.threshold else 0
4090

4191

4292
RULE_REGISTRY = {
43-
ComplianceAlertRule.rule_type: ComplianceAlertRule(),
93+
LicensePolicyErrorRule.rule_type: LicensePolicyErrorRule(),
94+
LicensePolicyWarningRule.rule_type: LicensePolicyWarningRule(),
95+
LicenseCoverageGapRule.rule_type: LicenseCoverageGapRule(),
96+
VulnerabilityDetectedRule.rule_type: VulnerabilityDetectedRule(),
4497
}

0 commit comments

Comments
 (0)