Skip to content

Commit 38505dc

Browse files
authored
refactor: migrate to intoto/attestations go library -> in-toto 1.0 bump (#397)
Signed-off-by: Miguel Martinez Trivino <[email protected]>
1 parent 7e1a3c4 commit 38505dc

File tree

18 files changed

+437
-586
lines changed

18 files changed

+437
-586
lines changed

app/cli/internal/action/attestation_push.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,14 @@ import (
1919
"context"
2020
"encoding/json"
2121
"fmt"
22+
"time"
2223

2324
pb "github.com/chainloop-dev/chainloop/app/controlplane/api/controlplane/v1"
2425
"github.com/chainloop-dev/chainloop/internal/attestation/crafter"
2526
"github.com/chainloop-dev/chainloop/internal/attestation/renderer"
2627
"github.com/secure-systems-lab/go-securesystemslib/dsse"
2728
"google.golang.org/grpc"
29+
"google.golang.org/protobuf/types/known/timestamppb"
2830
)
2931

3032
type AttestationPushOpts struct {
@@ -107,6 +109,9 @@ func (action *AttestationPush) Run(runtimeAnnotations map[string]string) (*Attes
107109

108110
action.Logger.Debug().Msg("validation completed")
109111

112+
// Indicate that we are done with the attestation
113+
action.c.CraftingState.Attestation.FinishedAt = timestamppb.New(time.Now())
114+
110115
renderer, err := renderer.NewAttestationRenderer(action.c.CraftingState, action.keyPath, action.cliVersion, action.cliDigest, renderer.WithLogger(action.Logger))
111116
if err != nil {
112117
return nil, err

app/cli/internal/action/workflow_run_describe.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import (
2626
"github.com/chainloop-dev/chainloop/internal/attestation/renderer/chainloop"
2727
sigs "github.com/sigstore/cosign/v2/pkg/signature"
2828

29-
"github.com/in-toto/in-toto-golang/in_toto"
29+
intoto "github.com/in-toto/attestation/go/v1"
3030
"github.com/secure-systems-lab/go-securesystemslib/dsse"
3131
sigdsee "github.com/sigstore/sigstore/pkg/signature/dsse"
3232
)
@@ -46,7 +46,7 @@ type WorkflowRunAttestationItem struct {
4646
ID string `json:"id"`
4747
CreatedAt *time.Time `json:"createdAt"`
4848
Envelope *dsse.Envelope `json:"envelope"`
49-
statement *in_toto.Statement
49+
statement *intoto.Statement
5050
Materials []*Material `json:"materials,omitempty"`
5151
EnvVars []*EnvVar `json:"envvars,omitempty"`
5252
Annotations []*Annotation `json:"annotations,omitempty"`
@@ -75,7 +75,7 @@ type Annotation struct {
7575
Value string `json:"value"`
7676
}
7777

78-
func (i *WorkflowRunAttestationItem) Statement() *in_toto.Statement {
78+
func (i *WorkflowRunAttestationItem) Statement() *intoto.Statement {
7979
return i.statement
8080
}
8181

app/controlplane/plugins/sdk/v1/fanout.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import (
3131
"github.com/chainloop-dev/chainloop/internal/attestation/renderer/chainloop"
3232
"github.com/chainloop-dev/chainloop/internal/servicelogger"
3333
"github.com/go-kratos/kratos/v2/log"
34-
"github.com/in-toto/in-toto-golang/in_toto"
34+
intoto "github.com/in-toto/attestation/go/v1"
3535
"github.com/invopop/jsonschema"
3636
schema_validator "github.com/santhosh-tekuri/jsonschema/v5"
3737

@@ -152,7 +152,7 @@ type ExecuteAttestation struct {
152152
Envelope *dsse.Envelope
153153
// Hash of the envelope
154154
Hash crv1.Hash
155-
Statement *in_toto.Statement
155+
Statement *intoto.Statement
156156
Predicate chainloop.NormalizablePredicate
157157
}
158158

go.mod

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ require (
3535
github.com/hashicorp/vault/api v1.9.2
3636
github.com/hedwigz/entviz v0.0.0-20221011080911-9d47f6f1d818
3737
github.com/improbable-eng/grpc-web v0.15.0
38-
github.com/in-toto/in-toto-golang v0.9.0
38+
github.com/in-toto/in-toto-golang v0.9.0 // indirect
3939
github.com/jedib0t/go-pretty/v6 v6.4.7
4040
github.com/joshdk/go-junit v1.0.0
4141
github.com/lib/pq v1.10.9
@@ -69,6 +69,7 @@ require (
6969
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.1
7070
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0
7171
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.1.0
72+
github.com/in-toto/attestation v0.1.1-0.20231010121940-09a03152c04a
7273
github.com/invopop/jsonschema v0.7.0
7374
github.com/jackc/pgx/v5 v5.4.3
7475
github.com/muesli/reflow v0.3.0

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,8 @@ github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
742742
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
743743
github.com/improbable-eng/grpc-web v0.15.0 h1:BN+7z6uNXZ1tQGcNAuaU1YjsLTApzkjt2tzCixLaUPQ=
744744
github.com/improbable-eng/grpc-web v0.15.0/go.mod h1:1sy9HKV4Jt9aEs9JSnkWlRJPuPtwNr0l57L4f878wP8=
745+
github.com/in-toto/attestation v0.1.1-0.20231010121940-09a03152c04a h1:y4ZRSC/GJWAFi+u9t7sNxjNsQKQvFKca1qc3Wr1ZX6Q=
746+
github.com/in-toto/attestation v0.1.1-0.20231010121940-09a03152c04a/go.mod h1:hCR5COCuENh5+VfojEkJnt7caOymbEgvyZdKifD6pOw=
745747
github.com/in-toto/in-toto-golang v0.9.0 h1:tHny7ac4KgtsfrG6ybU8gVOZux2H8jN05AXJ9EBM1XU=
746748
github.com/in-toto/in-toto-golang v0.9.0/go.mod h1:xsBVrVsHNsB61++S6Dy2vWosKhuA3lUTQd+eF9HdeMo=
747749
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=

internal/attestation/renderer/chainloop/chainloop.go

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ import (
2222

2323
v1 "github.com/chainloop-dev/chainloop/app/cli/api/attestation/v1"
2424
"github.com/secure-systems-lab/go-securesystemslib/dsse"
25+
"google.golang.org/protobuf/encoding/protojson"
2526

2627
crv1 "github.com/google/go-containerregistry/pkg/v1"
27-
"github.com/in-toto/in-toto-golang/in_toto"
28-
slsacommon "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/common"
28+
intoto "github.com/in-toto/attestation/go/v1"
2929
)
3030

3131
// TODO: Figure out a more appropriate meaning
@@ -61,12 +61,12 @@ type NormalizedMaterial struct {
6161
}
6262

6363
type ProvenancePredicateCommon struct {
64-
Metadata *Metadata `json:"metadata"`
65-
Builder *slsacommon.ProvenanceBuilder `json:"builder"`
66-
BuildType string `json:"buildType"`
67-
Env map[string]string `json:"env,omitempty"`
68-
RunnerType string `json:"runnerType"`
69-
RunnerURL string `json:"runnerURL,omitempty"`
64+
Metadata *Metadata `json:"metadata"`
65+
Builder *builder `json:"builder"`
66+
BuildType string `json:"buildType"`
67+
Env map[string]string `json:"env,omitempty"`
68+
RunnerType string `json:"runnerType"`
69+
RunnerURL string `json:"runnerURL,omitempty"`
7070
// Custom annotations
7171
Annotations map[string]string `json:"annotations,omitempty"`
7272
}
@@ -90,6 +90,10 @@ type builderInfo struct {
9090
version, digest string
9191
}
9292

93+
type builder struct {
94+
ID string `json:"id"`
95+
}
96+
9397
type RendererCommon struct {
9498
predicateType string
9599
att *v1.Attestation
@@ -99,7 +103,7 @@ type RendererCommon struct {
99103
func predicateCommon(builderInfo *builderInfo, att *v1.Attestation) *ProvenancePredicateCommon {
100104
return &ProvenancePredicateCommon{
101105
BuildType: chainloopBuildType,
102-
Builder: &slsacommon.ProvenanceBuilder{ID: fmt.Sprintf(builderIDFmt, builderInfo.version, builderInfo.digest)},
106+
Builder: &builder{ID: fmt.Sprintf(builderIDFmt, builderInfo.version, builderInfo.digest)},
103107
Metadata: getChainloopMeta(att),
104108
Env: att.EnvVars,
105109
RunnerType: att.GetRunnerType().String(),
@@ -110,11 +114,9 @@ func predicateCommon(builderInfo *builderInfo, att *v1.Attestation) *ProvenanceP
110114

111115
func getChainloopMeta(att *v1.Attestation) *Metadata {
112116
initializedAt := att.InitializedAt.AsTime()
117+
finishedAt := att.GetFinishedAt().AsTime()
113118
wfMeta := att.GetWorkflow()
114119

115-
// Finished at is set at the time of render
116-
finishedAt := time.Now()
117-
118120
return &Metadata{
119121
InitializedAt: &initializedAt,
120122
FinishedAt: &finishedAt,
@@ -126,15 +128,15 @@ func getChainloopMeta(att *v1.Attestation) *Metadata {
126128
}
127129
}
128130

129-
func ExtractStatement(envelope *dsse.Envelope) (*in_toto.Statement, error) {
131+
func ExtractStatement(envelope *dsse.Envelope) (*intoto.Statement, error) {
130132
decodedPayload, err := envelope.DecodeB64Payload()
131133
if err != nil {
132134
return nil, err
133135
}
134136

135137
// 1 - Extract the in-toto statement
136-
statement := &in_toto.Statement{}
137-
if err := json.Unmarshal(decodedPayload, statement); err != nil {
138+
statement := &intoto.Statement{}
139+
if err := protojson.Unmarshal(decodedPayload, statement); err != nil {
138140
return nil, fmt.Errorf("un-marshaling predicate: %w", err)
139141
}
140142

@@ -156,13 +158,6 @@ func ExtractPredicate(envelope *dsse.Envelope) (NormalizablePredicate, error) {
156158

157159
// 2 - Extract the Chainloop predicate from the in-toto statement
158160
switch statement.PredicateType {
159-
case PredicateTypeV01:
160-
var predicate *ProvenancePredicateV01
161-
if err = extractPredicate(statement, &predicate); err != nil {
162-
return nil, fmt.Errorf("extracting predicate: %w", err)
163-
}
164-
165-
return predicate, nil
166161
case PredicateTypeV02:
167162
var predicate *ProvenancePredicateV02
168163
if err = extractPredicate(statement, &predicate); err != nil {
@@ -175,8 +170,8 @@ func ExtractPredicate(envelope *dsse.Envelope) (NormalizablePredicate, error) {
175170
}
176171
}
177172

178-
func extractPredicate(statement *in_toto.Statement, v any) error {
179-
jsonPredicate, err := json.Marshal(statement.Predicate)
173+
func extractPredicate(statement *intoto.Statement, v any) error {
174+
jsonPredicate, err := protojson.Marshal(statement.Predicate)
180175
if err != nil {
181176
return fmt.Errorf("un-marshaling predicate: %w", err)
182177
}

internal/attestation/renderer/chainloop/chainloop_test.go

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -34,28 +34,6 @@ func TestExtractPredicate(t *testing.T) {
3434
materials []*NormalizedMaterial
3535
wantErr bool
3636
}{
37-
{
38-
name: "valid envelope v1",
39-
envelopePath: "testdata/valid.envelope.v1.json",
40-
envVars: map[string]string{"GITHUB_ACTOR": "migmartri", "GITHUB_REF": "refs/tags/v0.0.39", "GITHUB_REPOSITORY": "chainloop-dev/integration-demo", "GITHUB_REPOSITORY_OWNER": "chainloop-dev", "GITHUB_RUN_ID": "4410543365", "GITHUB_SHA": "0accc9392fb1f9b258167c18ffa0aeb626973f1c", "RUNNER_NAME": "Hosted Agent", "RUNNER_OS": "Linux"},
41-
materials: []*NormalizedMaterial{
42-
{
43-
Name: "binary", Type: "ARTIFACT",
44-
Value: "integration-demo_0.0.39_linux_amd64.tar.gz",
45-
Hash: &crv1.Hash{Algorithm: "sha256", Hex: "b155cdfc328b273c4b741c08b3b84ac441b0562ca51893f23495b35abf89ea87"},
46-
},
47-
{
48-
Name: "image", Type: "CONTAINER_IMAGE",
49-
Value: "ghcr.io/chainloop-dev/integration-demo",
50-
Hash: &crv1.Hash{Algorithm: "sha256", Hex: "e0d8179991dd735baf0961901b33476a76a0f300bc4ea07e3d7ae7c24e147193"},
51-
},
52-
{
53-
Name: "sbom", Type: "SBOM_CYCLONEDX_JSON",
54-
Value: "sbom.cyclonedx.json",
55-
Hash: &crv1.Hash{Algorithm: "sha256", Hex: "b50f38961cc2e97d0903f4683a40e2528f7f6c9d382e8c6048b0363af95b7080"},
56-
},
57-
},
58-
},
5937
{
6038
name: "valid envelope v2",
6139
envelopePath: "testdata/valid.envelope.v2.json",
@@ -114,6 +92,7 @@ func TestExtractPredicate(t *testing.T) {
11492
return
11593
}
11694

95+
require.NoError(t, err)
11796
gotVars := gotPredicate.GetEnvVars()
11897
assert.Equal(t, tc.envVars, gotVars)
11998

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
{
2+
"type": "https://in-toto.io/Statement/v1",
3+
"subject": [
4+
{
5+
"name": "chainloop.workflow.test-new-types",
6+
"digest": {
7+
"sha256": "f1fad10a3399754f2ea93265601bf25788d5abf6c447e08d1fc4c9ffc043c19e"
8+
}
9+
},
10+
{
11+
"name": "git.head",
12+
"digest": {
13+
"sha1": "78ac366c9e8a300d51808d581422ca61f7b5b721"
14+
}
15+
},
16+
{
17+
"name": "index.docker.io/bitnami/nginx",
18+
"digest": {
19+
"sha256": "fbd9335f55d83d8aaf9ab1a539b0f2a87b444e8c54f34c9a1ca9d7df15605db4"
20+
}
21+
}
22+
],
23+
"predicate_type": "chainloop.dev/attestation/v0.2",
24+
"predicate": {
25+
"buildType": "chainloop.dev/workflowrun/v0.1",
26+
"builder": {
27+
"id": "chainloop.dev/cli/dev@sha256:59e14f1a9de709cdd0e91c36b33e54fcca95f7dba1dc7169a7f81986e02108e5"
28+
},
29+
"materials": [
30+
{
31+
"annotations": {
32+
"chainloop.material.name": "image",
33+
"chainloop.material.type": "CONTAINER_IMAGE"
34+
},
35+
"digest": {
36+
"sha256": "fbd9335f55d83d8aaf9ab1a539b0f2a87b444e8c54f34c9a1ca9d7df15605db4"
37+
},
38+
"name": "index.docker.io/bitnami/nginx"
39+
},
40+
{
41+
"annotations": {
42+
"chainloop.material.cas": true,
43+
"chainloop.material.name": "rootfs",
44+
"chainloop.material.type": "ARTIFACT"
45+
},
46+
"digest": {
47+
"sha256": "385c4188b9c080499413f2e0fa0b3951ed107b5f0cb35c2f2b1f07a7be9a7512"
48+
},
49+
"name": "download.gif"
50+
},
51+
{
52+
"annotations": {
53+
"chainloop.material.cas": true,
54+
"chainloop.material.name": "sarif",
55+
"chainloop.material.type": "SARIF"
56+
},
57+
"digest": {
58+
"sha256": "c4a63494f9289dd9fd44f841efb4f5b52765c2de6332f2d86e5f6c0340b40a95"
59+
},
60+
"name": "report.sarif"
61+
},
62+
{
63+
"annotations": {
64+
"chainloop.material.cas": true,
65+
"chainloop.material.name": "sbom",
66+
"chainloop.material.type": "SBOM_CYCLONEDX_JSON"
67+
},
68+
"digest": {
69+
"sha256": "16159bb881eb4ab7eb5d8afc5350b0feeed1e31c0a268e355e74f9ccbe885e0c"
70+
},
71+
"name": "sbom.cyclonedx.json"
72+
},
73+
{
74+
"annotations": {
75+
"chainloop.material.cas": true,
76+
"chainloop.material.name": "vex",
77+
"chainloop.material.type": "OPENVEX"
78+
},
79+
"digest": {
80+
"sha256": "b4bd86d5855f94bcac0a92d3100ae7b85d050bd2e5fb9037a200e5f5f0b073a2"
81+
},
82+
"name": "openvex_v0.2.0.json"
83+
}
84+
],
85+
"metadata": {
86+
"finishedAt": "2023-10-20T12:58:10.562093962Z",
87+
"initializedAt": "2023-10-20T12:57:10.562093962Z",
88+
"name": "test-new-types",
89+
"project": "test",
90+
"team": "",
91+
"workflowID": "ab98be70-041b-4a82-97f3-daa56f61262b",
92+
"workflowRunID": "f97a0680-e64b-478a-9eea-df8864fa27f8"
93+
},
94+
"runnerType": "RUNNER_TYPE_UNSPECIFIED"
95+
}
96+
}

0 commit comments

Comments
 (0)