|
1 | | -// Copyright 2025 The Chainloop Authors. |
| 1 | +// Copyright 2025-2026 The Chainloop Authors. |
2 | 2 | // |
3 | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | 4 | // you may not use this file except in compliance with the License. |
|
15 | 15 | package policydevel |
16 | 16 |
|
17 | 17 | import ( |
| 18 | + "encoding/json" |
18 | 19 | "os" |
19 | 20 | "path/filepath" |
20 | 21 | "testing" |
@@ -148,6 +149,49 @@ func TestEvaluateSimplifiedPolicies(t *testing.T) { |
148 | 149 | assert.Contains(t, result.Result.Violations[0], "at least 2 components") |
149 | 150 | }) |
150 | 151 |
|
| 152 | + t.Run("structured violations populated for policies with finding_type", func(t *testing.T) { |
| 153 | + opts := &EvalOptions{ |
| 154 | + PolicyPath: "testdata/sbom-structured-vuln-policy.yaml", |
| 155 | + MaterialPath: sbomPath, |
| 156 | + } |
| 157 | + |
| 158 | + result, err := Evaluate(opts, logger) |
| 159 | + require.NoError(t, err) |
| 160 | + require.NotNil(t, result) |
| 161 | + assert.False(t, result.Result.Skipped) |
| 162 | + |
| 163 | + // Both fields populated: violations (messages) and structured_violations (proto JSON) |
| 164 | + require.Len(t, result.Result.Violations, 1) |
| 165 | + assert.Contains(t, result.Result.Violations[0], "Vulnerability found in test-component@1.0.0") |
| 166 | + |
| 167 | + require.Len(t, result.Result.StructuredViolations, 1) |
| 168 | + var sv map[string]any |
| 169 | + require.NoError(t, json.Unmarshal(result.Result.StructuredViolations[0], &sv)) |
| 170 | + assert.Contains(t, sv["message"], "Vulnerability found in test-component@1.0.0") |
| 171 | + |
| 172 | + vuln, ok := sv["vulnerability"].(map[string]any) |
| 173 | + require.True(t, ok, "expected vulnerability finding in structured violation") |
| 174 | + assert.Equal(t, "CVE-2024-1234", vuln["external_id"]) |
| 175 | + assert.Equal(t, "pkg:generic/test-component@1.0.0", vuln["package_purl"]) |
| 176 | + assert.Equal(t, "HIGH", vuln["severity"]) |
| 177 | + assert.InDelta(t, 7.5, vuln["cvss_v3_score"], 0.001) |
| 178 | + }) |
| 179 | + |
| 180 | + t.Run("no structured violations for plain string policies", func(t *testing.T) { |
| 181 | + opts := &EvalOptions{ |
| 182 | + PolicyPath: "testdata/sbom-min-components-policy.yaml", |
| 183 | + MaterialPath: sbomPath, |
| 184 | + } |
| 185 | + |
| 186 | + result, err := Evaluate(opts, logger) |
| 187 | + require.NoError(t, err) |
| 188 | + require.NotNil(t, result) |
| 189 | + require.Len(t, result.Result.Violations, 1) |
| 190 | + assert.Contains(t, result.Result.Violations[0], "at least 2 components") |
| 191 | + // No structured_violations when policy returns plain strings |
| 192 | + assert.Empty(t, result.Result.StructuredViolations) |
| 193 | + }) |
| 194 | + |
151 | 195 | t.Run("sbom metadata component policy", func(t *testing.T) { |
152 | 196 | opts := &EvalOptions{ |
153 | 197 | PolicyPath: "testdata/sbom-metadata-component-policy.yaml", |
|
0 commit comments