Skip to content

Commit 3e83aa4

Browse files
authored
feat(controlplane): expose has_policy_violations through referrer API (#1708)
Signed-off-by: Miguel Martinez <[email protected]>
1 parent 3d78a28 commit 3e83aa4

File tree

9 files changed

+178
-79
lines changed

9 files changed

+178
-79
lines changed

app/controlplane/pkg/biz/referrer.go

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//
2-
// Copyright 2024 The Chainloop Authors.
2+
// Copyright 2024-2025 The Chainloop Authors.
33
//
44
// Licensed under the Apache License, Version 2.0 (the "License");
55
// you may not use this file except in compliance with the License.
@@ -280,12 +280,15 @@ func extractReferrers(att *dsse.Envelope, repo ReferrerRepo) ([]*Referrer, error
280280
attestationReferrer.Annotations = predicate.GetAnnotations()
281281
attestationReferrer.Metadata = map[string]string{
282282
// workflow name, team and project
283-
"name": predicate.GetMetadata().Name,
284-
"team": predicate.GetMetadata().Team,
285-
"project": predicate.GetMetadata().Project,
286-
"organization": predicate.GetMetadata().Organization,
287-
"contractName": predicate.GetMetadata().ContractName,
288-
"contractVersion": predicate.GetMetadata().ContractVersion,
283+
"name": predicate.GetMetadata().Name,
284+
"team": predicate.GetMetadata().Team,
285+
"project": predicate.GetMetadata().Project,
286+
"hasPolicyViolations": fmt.Sprintf("%t", predicate.HasPolicyViolations()),
287+
"projectVersion": predicate.GetMetadata().ProjectVersion,
288+
"projectVersionPrerelease": fmt.Sprintf("%t", predicate.GetMetadata().ProjectVersionPrerelease),
289+
"organization": predicate.GetMetadata().Organization,
290+
"contractName": predicate.GetMetadata().ContractName,
291+
"contractVersion": predicate.GetMetadata().ContractVersion,
289292
}
290293

291294
// Create new referrers for each material

app/controlplane/pkg/biz/referrer_integration_test.go

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//
2-
// Copyright 2024 The Chainloop Authors.
2+
// Copyright 2024-2025 The Chainloop Authors.
33
//
44
// Licensed under the Apache License, Version 2.0 (the "License");
55
// you may not use this file except in compliance with the License.
@@ -49,12 +49,12 @@ func (s *referrerIntegrationTestSuite) TestGetFromRootInPublicSharedIndex() {
4949

5050
// We'll store the attestation in the private only index
5151
ctx := context.Background()
52-
s.T().Run("public endpoint fails if feature not enabled", func(t *testing.T) {
52+
s.Run("public endpoint fails if feature not enabled", func() {
5353
_, err := s.Referrer.GetFromRootInPublicSharedIndex(ctx, wantReferrerAtt.Digest, "")
5454
s.ErrorContains(err, "not enabled")
5555
})
5656

57-
s.T().Run("storing it associated with a private workflow keeps it private and not in the index", func(t *testing.T) {
57+
s.Run("storing it associated with a private workflow keeps it private and not in the index", func() {
5858
err = s.sharedEnabledUC.ExtractAndPersist(ctx, envelope, s.workflow1.ID.String())
5959
require.NoError(s.T(), err)
6060
ref, err := s.Referrer.GetFromRootUser(ctx, wantReferrerAtt.Digest, "", s.user.ID)
@@ -243,11 +243,15 @@ func (s *referrerIntegrationTestSuite) TestExtractAndPersists() {
243243
s.Equal(wantReferrerAtt.Kind, got.Kind)
244244
// It has metadata
245245
s.Equal(map[string]string{
246-
"contractName": "", "contractVersion": "",
247-
"name": "test-new-types",
248-
"project": "test",
249-
"team": "my-team",
250-
"organization": "my-org",
246+
"contractName": "",
247+
"contractVersion": "",
248+
"name": "test-new-types",
249+
"project": "test",
250+
"team": "my-team",
251+
"organization": "my-org",
252+
"hasPolicyViolations": "false",
253+
"projectVersion": "",
254+
"projectVersionPrerelease": "false",
251255
}, got.Metadata)
252256
// it has all the references
253257
require.Len(t, got.References, 6)

app/controlplane/pkg/biz/referrer_test.go

Lines changed: 37 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//
2-
// Copyright 2024 The Chainloop Authors.
2+
// Copyright 2024-2025 The Chainloop Authors.
33
//
44
// Licensed under the Apache License, Version 2.0 (the "License");
55
// you may not use this file except in compliance with the License.
@@ -109,12 +109,15 @@ func (s *referrerTestSuite) TestExtractReferrers() {
109109
Kind: "ATTESTATION",
110110
Downloadable: true,
111111
Metadata: map[string]string{
112-
"contractName": "",
113-
"contractVersion": "",
114-
"name": "only-sbom",
115-
"organization": "",
116-
"team": "",
117-
"project": "foo",
112+
"contractName": "",
113+
"contractVersion": "",
114+
"name": "only-sbom",
115+
"organization": "",
116+
"team": "",
117+
"project": "foo",
118+
"projectVersion": "",
119+
"projectVersionPrerelease": "false",
120+
"hasPolicyViolations": "false",
118121
},
119122
Annotations: map[string]string{
120123
"branch": "stable",
@@ -160,12 +163,15 @@ func (s *referrerTestSuite) TestExtractReferrers() {
160163
},
161164
},
162165
Metadata: map[string]string{
163-
"contractName": "",
164-
"contractVersion": "",
165-
"name": "test",
166-
"organization": "",
167-
"team": "",
168-
"project": "bar",
166+
"contractName": "",
167+
"contractVersion": "",
168+
"name": "test",
169+
"organization": "",
170+
"team": "",
171+
"project": "bar",
172+
"projectVersion": "",
173+
"projectVersionPrerelease": "false",
174+
"hasPolicyViolations": "false",
169175
},
170176
Annotations: map[string]string{
171177
"version": "oss",
@@ -193,12 +199,15 @@ func (s *referrerTestSuite) TestExtractReferrers() {
193199
Kind: "ATTESTATION",
194200
Downloadable: true,
195201
Metadata: map[string]string{
196-
"contractName": "",
197-
"contractVersion": "",
198-
"name": "only-sbom",
199-
"organization": "",
200-
"team": "",
201-
"project": "foo",
202+
"contractName": "",
203+
"contractVersion": "",
204+
"name": "only-sbom",
205+
"organization": "",
206+
"team": "",
207+
"project": "foo",
208+
"projectVersion": "",
209+
"projectVersionPrerelease": "false",
210+
"hasPolicyViolations": "false",
202211
},
203212
Annotations: map[string]string{
204213
"branch": "stable",
@@ -254,12 +263,15 @@ func (s *referrerTestSuite) TestExtractReferrers() {
254263
Kind: "ATTESTATION",
255264
Downloadable: true,
256265
Metadata: map[string]string{
257-
"contractName": "",
258-
"contractVersion": "",
259-
"name": "test-new-types",
260-
"organization": "my-org",
261-
"team": "my-team",
262-
"project": "test",
266+
"contractName": "",
267+
"contractVersion": "",
268+
"name": "test-new-types",
269+
"organization": "my-org",
270+
"team": "my-team",
271+
"project": "test",
272+
"projectVersion": "",
273+
"projectVersionPrerelease": "false",
274+
"hasPolicyViolations": "false",
263275
},
264276
References: []*Referrer{
265277
{

pkg/attestation/renderer/chainloop/chainloop.go

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//
2-
// Copyright 2024 The Chainloop Authors.
2+
// Copyright 2024-2025 The Chainloop Authors.
33
//
44
// Licensed under the Apache License, Version 2.0 (the "License");
55
// you may not use this file except in compliance with the License.
@@ -42,6 +42,7 @@ type NormalizablePredicate interface {
4242
GetRunLink() string
4343
GetMetadata() *Metadata
4444
GetPolicyEvaluations() map[string][]*PolicyEvaluation
45+
HasPolicyViolations() bool
4546
}
4647

4748
type NormalizedMaterial struct {
@@ -77,16 +78,18 @@ type ProvenancePredicateCommon struct {
7778
}
7879

7980
type Metadata struct {
80-
Name string `json:"name"`
81-
Project string `json:"project"`
82-
Team string `json:"team"`
83-
InitializedAt *time.Time `json:"initializedAt"`
84-
FinishedAt *time.Time `json:"finishedAt"`
85-
WorkflowRunID string `json:"workflowRunID"`
86-
WorkflowID string `json:"workflowID"`
87-
Organization string `json:"organization"`
88-
ContractName string `json:"contractName"`
89-
ContractVersion string `json:"contractVersion"`
81+
Name string `json:"name"`
82+
Project string `json:"project"`
83+
ProjectVersion string `json:"projectVersion"`
84+
ProjectVersionPrerelease bool `json:"projectVersionPrerelease"`
85+
Team string `json:"team"`
86+
InitializedAt *time.Time `json:"initializedAt"`
87+
FinishedAt *time.Time `json:"finishedAt"`
88+
WorkflowRunID string `json:"workflowRunID"`
89+
WorkflowID string `json:"workflowID"`
90+
Organization string `json:"organization"`
91+
ContractName string `json:"contractName"`
92+
ContractVersion string `json:"contractVersion"`
9093
}
9194

9295
type Maintainer struct {
@@ -126,16 +129,18 @@ func getChainloopMeta(att *v1.Attestation) *Metadata {
126129
wfMeta := att.GetWorkflow()
127130

128131
return &Metadata{
129-
InitializedAt: &initializedAt,
130-
FinishedAt: &finishedAt,
131-
Name: wfMeta.GetName(),
132-
Team: wfMeta.GetTeam(),
133-
Project: wfMeta.GetProject(),
134-
WorkflowRunID: wfMeta.GetWorkflowRunId(),
135-
WorkflowID: wfMeta.GetWorkflowId(),
136-
Organization: wfMeta.GetOrganization(),
137-
ContractName: wfMeta.GetContractName(),
138-
ContractVersion: wfMeta.GetSchemaRevision(),
132+
InitializedAt: &initializedAt,
133+
FinishedAt: &finishedAt,
134+
Name: wfMeta.GetName(),
135+
Team: wfMeta.GetTeam(),
136+
Project: wfMeta.GetProject(),
137+
WorkflowRunID: wfMeta.GetWorkflowRunId(),
138+
WorkflowID: wfMeta.GetWorkflowId(),
139+
Organization: wfMeta.GetOrganization(),
140+
ContractName: wfMeta.GetContractName(),
141+
ContractVersion: wfMeta.GetSchemaRevision(),
142+
ProjectVersion: wfMeta.GetVersion().GetVersion(),
143+
ProjectVersionPrerelease: wfMeta.GetVersion().GetPrerelease(),
139144
}
140145
}
141146

pkg/attestation/renderer/chainloop/testdata/attestation.output-2.v0.2.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@
111111
"name": "test-new-types",
112112
"organization": "my-org",
113113
"project": "test",
114+
"projectVersion": "",
115+
"projectVersionPrerelease": false,
114116
"team": "",
115117
"workflowID": "ab98be70-041b-4a82-97f3-daa56f61262b",
116118
"workflowRunID": "f97a0680-e64b-478a-9eea-df8864fa27f8"

pkg/attestation/renderer/chainloop/testdata/attestation.output.v0.2.json

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
"type": "https://in-toto.io/Statement/v1",
33
"subject": [
44
{
5-
"name": "chainloop.workflow.foo",
5+
"name": "chainloop.workflow.skipped",
66
"digest": {
7-
"sha256": "163c004d6210ba71f5b3e8c53f3e026ce245dbe3ddffc68e5bb1fe1f7e76d4c7"
7+
"sha256": "9a2d6343065c60508002a90468b98bd05bb63a40e8b9aefe2a712dbdf946e828"
88
}
99
},
1010
{
@@ -66,19 +66,55 @@
6666
}
6767
],
6868
"metadata": {
69-
"contractName": "",
69+
"contractName": "chainloop-skipped",
7070
"contractVersion": "1",
7171
"finishedAt": "2023-05-03T17:25:12.743426076Z",
7272
"initializedAt": "2023-05-03T17:22:12.743426076Z",
73-
"name": "foo",
74-
"organization": "",
75-
"project": "bar",
73+
"name": "skipped",
74+
"organization": "foobar",
75+
"project": "chainloop",
76+
"projectVersion": "v0.150.0",
77+
"projectVersionPrerelease": true,
7678
"team": "",
77-
"workflowID": "54ea7c5c-7592-48ac-9a9f-084b72447184",
78-
"workflowRunID": ""
79+
"workflowID": "94208094-b8d3-4b38-b1f1-c609c47c49ea",
80+
"workflowRunID": "e4cec971-6f4f-442a-8de0-d12ddc4667f2"
7981
},
8082
"policy_block_on_violation": false,
81-
"policy_has_violations": false,
83+
"policy_evaluations": {
84+
"sbom": [
85+
{
86+
"annotations": {
87+
"category": "sbom"
88+
},
89+
"description": "Checks that the SBOM is not older than a specified threshold. Supports CycloneDX.\n",
90+
"material_name": "sbom",
91+
"name": "sbom-freshness",
92+
"policy_reference": {
93+
"annotations": {
94+
"name": "sbom-freshness",
95+
"organization": ""
96+
},
97+
"digest": {
98+
"sha256": "e9b750847ba8a5439a0a43963d22cb5c5a9568de5fdcd2db21d9615c76870c2a"
99+
},
100+
"name": "sbom-freshness",
101+
"uri": "file://policy-sbom-freshness.yaml"
102+
},
103+
"skipped": false,
104+
"type": "SBOM_CYCLONEDX_JSON",
105+
"violations": [
106+
{
107+
"message": "SBOM created at: 2020-08-02T21:27:04Z which is too old (freshness limit set to 5 days)",
108+
"subject": "sbom-freshness"
109+
}
110+
],
111+
"with": {
112+
"limit": "5"
113+
}
114+
}
115+
]
116+
},
117+
"policy_has_violations": true,
82118
"runnerType": "GITHUB_ACTION"
83119
}
84120
}

pkg/attestation/renderer/chainloop/testdata/attestation.source.json

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,7 @@
2525
"name": "skynet-sbom"
2626
}
2727
],
28-
"envAllowList": [
29-
"CUSTOM_VAR"
30-
],
28+
"envAllowList": ["CUSTOM_VAR"],
3129
"runner": {
3230
"type": "GITHUB_ACTION"
3331
}
@@ -36,11 +34,46 @@
3634
"initializedAt": "2023-05-03T17:22:12.743426076Z",
3735
"finishedAt": "2023-05-03T17:25:12.743426076Z",
3836
"workflow": {
39-
"name": "foo",
40-
"project": "bar",
41-
"workflowId": "54ea7c5c-7592-48ac-9a9f-084b72447184",
42-
"schemaRevision": "1"
37+
"name": "skipped",
38+
"project": "chainloop",
39+
"version": {
40+
"version": "v0.150.0",
41+
"prerelease": true
42+
},
43+
"workflowId": "94208094-b8d3-4b38-b1f1-c609c47c49ea",
44+
"workflowRunId": "e4cec971-6f4f-442a-8de0-d12ddc4667f2",
45+
"schemaRevision": "1",
46+
"contractName": "chainloop-skipped",
47+
"organization": "foobar"
4348
},
49+
"policyEvaluations": [
50+
{
51+
"name": "sbom-freshness",
52+
"materialName": "sbom",
53+
"sources": [],
54+
"referenceDigest": "sha256:e9b750847ba8a5439a0a43963d22cb5c5a9568de5fdcd2db21d9615c76870c2a",
55+
"referenceName": "file://policy-sbom-freshness.yaml",
56+
"description": "Checks that the SBOM is not older than a specified threshold. Supports CycloneDX.\n",
57+
"annotations": {
58+
"category": "sbom"
59+
},
60+
"violations": [
61+
{
62+
"subject": "sbom-freshness",
63+
"message": "SBOM created at: 2020-08-02T21:27:04Z which is too old (freshness limit set to 5 days)"
64+
}
65+
],
66+
"with": {
67+
"limit": "5"
68+
},
69+
"type": "SBOM_CYCLONEDX_JSON",
70+
"policyReference": {
71+
"name": "sbom-freshness",
72+
"digest": "sha256:e9b750847ba8a5439a0a43963d22cb5c5a9568de5fdcd2db21d9615c76870c2a",
73+
"uri": "file://policy-sbom-freshness.yaml"
74+
}
75+
}
76+
],
4477
"materials": {
4578
"build-ref": {
4679
"string": {
@@ -83,4 +116,4 @@
83116
"runnerType": "GITHUB_ACTION"
84117
},
85118
"dryRun": true
86-
}
119+
}

0 commit comments

Comments
 (0)