validate.rego
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# Catalog integrity validation =================================================
# Validates catalog.json structure and field values before policy evaluation.

# Run with:
#  DENY EVAL: opa eval --data policies/ --format raw "data.validate.deny[_].summary"
#  WARN EVAL: opa eval --data policies/ --format raw "data.validate.warn[_].summary"

package validate

# Local violation printer ------------------------------------------------------

violation(policy_id, check, message) := {
	"rule_id": policy_id,
	"check": check,
	"message": message,
	"summary": sprintf("%s [%s] %s", [policy_id, check, message]),
}

# Valid value sets --------------------------------------------------------------

valid_statuses := {"active", "disabled", "deprecated"}
valid_severities := {"CRITICAL", "HIGH", "MEDIUM", "LOW"}
required_fields := {"title", "description", "remediation", "severity", "status", "references"}

# Deny rules -------------------------------------------------------------------

deny contains violation(id, "invalid_status", sprintf("expected one of %v got: '%s'", [valid_statuses, policy.status])) if {
	some id, policy in data.policies
	not valid_statuses[policy.status]
}

deny contains violation(id, "invalid_severity", sprintf("expected one of %v got: '%s'", [valid_severities, policy.severity])) if {
	some id, policy in data.policies
	not valid_severities[policy.severity]
}

deny contains violation(id, "invalid_id_format", sprintf("expected ICP-TF-{PROVIDER}-{CATEGORY}-{NNN} got: '%s'", [id])) if {
	some id, _ in data.policies
	count(split(id, "-")) != 5
}

deny contains violation(id, "unknown_provider", sprintf("'%s' is not a known provider", [parts[2]])) if {
	some id, _ in data.policies
	parts := split(id, "-")
	count(parts) == 5
	not data.providers[parts[2]]
}

deny contains violation(id, "unknown_category", sprintf("'%s' is not a valid category", [parts[3]])) if {
	some id, _ in data.policies
	parts := split(id, "-")
	count(parts) == 5
	not data.categories[parts[3]]
}

deny contains violation(id, "missing_field", sprintf("required field '%s' is absent", [field])) if {
	some id, policy in data.policies
	some field in required_fields
	not policy[field]
}

# Warn rules -------------------------------------------------------------------

warn contains violation(id, "empty_references", "no references provided - at least one is recommended") if {
	some id, policy in data.policies
	count(policy.references) == 0
}