Skip to content

Commit a9b8bd7

Browse files
committed
Formalize attestation push
Signed-off-by: Adolfo García Veytia (Puerco) <puerco@carabiner.dev>
1 parent 36314bf commit a9b8bd7

7 files changed

Lines changed: 261 additions & 102 deletions

File tree

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ go 1.25.8
44

55
require (
66
github.com/carabiner-dev/attestation v0.2.1
7-
github.com/carabiner-dev/collector v0.2.10-0.20260309053530-b55bbe428700
8-
github.com/carabiner-dev/signer v0.3.7
7+
github.com/carabiner-dev/collector v0.2.10-0.20260310234513-8d637f10649f
8+
github.com/carabiner-dev/signer v0.3.8-0.20260310160610-a37998585604
99
github.com/carabiner-dev/vcslocator v0.4.0
1010
github.com/fatih/color v1.18.0
1111
github.com/go-git/go-billy/v6 v6.0.0-20260226131633-45bd0956d66f

go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ github.com/carabiner-dev/attestation v0.2.1 h1:VhjV5YlO9TsW50Sr/Zd54bdbZhhDAqgxC
8989
github.com/carabiner-dev/attestation v0.2.1/go.mod h1:O84vF84RZG3pJO/6BYrPs718bZviHF5DKajP1HsrDpw=
9090
github.com/carabiner-dev/collector v0.2.10-0.20260309053530-b55bbe428700 h1:S4NFLl3/UJvA4aUuPVY3MECUQS0jhHdT//+excPvWUc=
9191
github.com/carabiner-dev/collector v0.2.10-0.20260309053530-b55bbe428700/go.mod h1:ltqIryrtd+Ev+zAW9Q2h/UHNVMhT2nR1Fmchk+8lbs8=
92+
github.com/carabiner-dev/collector v0.2.10-0.20260310234513-8d637f10649f h1:2Q5VzbSVNKPwhP9rUjwH3ZWajDYwxB+3ZT0MTU/80ho=
93+
github.com/carabiner-dev/collector v0.2.10-0.20260310234513-8d637f10649f/go.mod h1:nqe5n0soDuenKtOt9i4G8D/anZiRTiZywzo3pNqf5As=
9294
github.com/carabiner-dev/ghrfs v0.3.4 h1:XJoDXkuw+8KQPTC4oI0da8vLpnx7cfQBGgyjzo+Eqrc=
9395
github.com/carabiner-dev/ghrfs v0.3.4/go.mod h1:u9We7molIUX6sCe4ox70juKOnbNAUpDv+B5Cerbqhio=
9496
github.com/carabiner-dev/github v0.2.2 h1:Ykrlcct71fRQm4j37LhAz9FyzG4n1nlm2e+V62MIoJM=
@@ -107,6 +109,8 @@ github.com/carabiner-dev/predicates v0.1.0 h1:t6tQF9gFdr6TIccWtuNk3kFasx8eu88INF
107109
github.com/carabiner-dev/predicates v0.1.0/go.mod h1:jL6EAD+LiI6GW/rOdRYAJF4HaA88/V2Q4n7yUGNQ7XM=
108110
github.com/carabiner-dev/signer v0.3.7 h1:oEmOg17Szs5+x0oVVGXluPNsVaQyROlXrBPxgwxfOHg=
109111
github.com/carabiner-dev/signer v0.3.7/go.mod h1:gReZbCZlINz8Pm/hrD1HtRcGFaO9MGUAu/v+iZp7R6Y=
112+
github.com/carabiner-dev/signer v0.3.8-0.20260310160610-a37998585604 h1:2PeAzIFCqbCF/upSb4Hqj5HwTvuJ6D6KjP2F5yH7WrA=
113+
github.com/carabiner-dev/signer v0.3.8-0.20260310160610-a37998585604/go.mod h1:kqmUAFHKgQXFsIsIFjbk4UlOMXNte7J1IVxIgKAnY/M=
110114
github.com/carabiner-dev/vcslocator v0.4.0 h1:HxU8F7FWJatnIhR6NowsPpfki8xw2uNDRLuikcBHFao=
111115
github.com/carabiner-dev/vcslocator v0.4.0/go.mod h1:B3JFnwypdrRVQPJKNK3BOlRw6DbgmsiHGmoT3ZELpp8=
112116
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=

internal/cmd/checklevelprov.go

Lines changed: 3 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,6 @@ import (
1111
"slices"
1212
"strings"
1313

14-
"github.com/carabiner-dev/attestation"
15-
"github.com/carabiner-dev/collector"
16-
"github.com/carabiner-dev/collector/envelope"
17-
"github.com/carabiner-dev/collector/repository/github"
18-
"github.com/carabiner-dev/collector/repository/note"
1914
"github.com/spf13/cobra"
2015
"google.golang.org/protobuf/encoding/protojson"
2116

@@ -59,61 +54,6 @@ func (po *pushOptions) AddFlags(cmd *cobra.Command) {
5954
cmd.PersistentFlags().StringSliceVar(&po.pushLocation, "push", []string{}, fmt.Sprintf("Push signed attestations to storage %v", supportedPushRepos))
6055
}
6156

62-
func (po *pushOptions) GetCollectorAgent(opts commitOptions, token string) (*collector.Agent, error) {
63-
if len(po.pushLocation) == 0 {
64-
return nil, nil
65-
}
66-
67-
// Create the attestation storage repositories
68-
agent, err := collector.New()
69-
if err != nil {
70-
return nil, err
71-
}
72-
73-
for _, uri := range po.pushLocation {
74-
var repo attestation.Repository
75-
var err error
76-
77-
// Translate just "note" or "github" to the full repo spec acting on
78-
// the sepcified commit
79-
switch uri {
80-
case note.TypeMoniker:
81-
uri = fmt.Sprintf(
82-
"note:git+https://github.com/%s/%s@%s",
83-
opts.owner, opts.repository, opts.commit,
84-
)
85-
case github.TypeMoniker:
86-
uri = fmt.Sprintf("github:%s/%s", opts.owner, opts.repository)
87-
}
88-
switch {
89-
case strings.HasPrefix(uri, "github:"):
90-
repo, err = github.New(
91-
// Initialize the github repository
92-
github.WithInit(uri),
93-
// We pass the token to use in the githu client
94-
github.WithToken(token),
95-
)
96-
case strings.HasPrefix(uri, "note:"):
97-
repo, err = note.New(
98-
// Initialize the notes repository
99-
note.WithInit(uri),
100-
// Push is enabled as we will append the note to the remote
101-
note.WithPush(true),
102-
// Push via http, using the GH access token
103-
note.WithHttpAuth("x-access-token", token),
104-
)
105-
default:
106-
return nil, fmt.Errorf("repository type not supported")
107-
}
108-
if err != nil {
109-
return nil, fmt.Errorf("creating storage repository: %w", err)
110-
}
111-
agent.AddRepository(repo) //nolint:errcheck,gosec // always returns nil
112-
}
113-
114-
return agent, nil
115-
}
116-
11757
type checkLevelProvOpts struct {
11858
commitOptions
11959
verifierOptions
@@ -187,18 +127,15 @@ and pushed to its remote (--push=note).
187127
return err
188128
}
189129

190-
t, err := authenticator.ReadToken()
191-
if err != nil {
192-
return err
193-
}
194-
195130
// Create a new sourcetool object
196131
srctool, err := sourcetool.New(
197132
sourcetool.WithAuthenticator(authenticator),
198133
sourcetool.WithAllowMergeCommits(opts.allowMergeCommits),
134+
sourcetool.WithNotesStorer(slices.Contains(opts.pushLocation, "notes")),
135+
sourcetool.WithGithubStorer(slices.Contains(opts.pushLocation, "github")),
199136
)
200137
if err != nil {
201-
return err
138+
return fmt.Errorf("creating sourcetool: %w", err)
202139
}
203140

204141
// Create the provenance attestation
@@ -272,30 +209,6 @@ and pushed to its remote (--push=note).
272209
return fmt.Errorf("writing bundle data: %w", err)
273210
}
274211
}
275-
276-
cl, err := opts.GetCollectorAgent(opts.commitOptions, t)
277-
if err != nil {
278-
return fmt.Errorf("creating storage repositories: %w", err)
279-
}
280-
281-
// If there are any storage repositories configured, push the attestations
282-
if cl != nil {
283-
// Parse the attestations into envelopes
284-
envProv, err := envelope.Parsers.Parse(strings.NewReader(signedProv))
285-
if err != nil || len(envProv) == 0 {
286-
return fmt.Errorf("parsing provenance: %w", err)
287-
}
288-
envVsa, err := envelope.Parsers.Parse(strings.NewReader(signedVsa))
289-
if err != nil || len(envVsa) == 0 {
290-
return fmt.Errorf("parsing VSA: %w", err)
291-
}
292-
293-
// And store them
294-
err = cl.Store(cmd.Context(), []attestation.Envelope{envProv[0], envVsa[0]})
295-
if err != nil {
296-
return fmt.Errorf("storing attestations: %w", err)
297-
}
298-
}
299212
default:
300213
log.Printf("unsigned prov: %s\n", unsignedProv)
301214
log.Printf("unsigned vsa: %s\n", unsignedVsa)

pkg/attest/attester.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010
"slices"
1111
"time"
1212

13-
"github.com/carabiner-dev/attestation"
1413
intoto "github.com/in-toto/attestation/go/v1"
1514
"google.golang.org/protobuf/encoding/protojson"
1615
"google.golang.org/protobuf/proto"
@@ -24,12 +23,15 @@ import (
2423
)
2524

2625
type AttesterOptions struct {
27-
// Initialize dynamic notes collector
26+
// Initialize dynamic notes fetcher and storer
2827
InitNotesCollector bool
29-
// Initialize attestations store collector
28+
29+
// Initialize attestations store collector and storer
3030
InitGHCollector bool
31+
3132
// Additional read repositories
3233
Repos []string
34+
3335
// Times to retry fetching attestations
3436
Retries uint8
3537
}
@@ -43,7 +45,6 @@ type Attester struct {
4345
verifier Verifier
4446
backend models.VcsBackend
4547
Options AttesterOptions
46-
storer attestation.Storer
4748
authenticator *auth.Authenticator
4849
}
4950

@@ -106,22 +107,22 @@ func WithNotesCollector(yesno bool) optFn {
106107
// Validate checks that the attester configuration is complete
107108
func (a *Attester) Validate() error {
108109
errs := []error{}
110+
111+
// Check a backend is configured
109112
if a.backend == nil {
110113
errs = append(errs, errors.New("attester has no backend defined"))
111114
}
112115

116+
// Check we have attestation repos to read
113117
if len(a.Options.Repos) == 0 && !a.Options.InitGHCollector && !a.Options.InitNotesCollector {
114118
errs = append(errs, errors.New("no attestation repository configured"))
115119
}
116120

121+
// Check we have a signature verifier
117122
if a.verifier == nil {
118123
errs = append(errs, errors.New("attester has no verifier"))
119124
}
120125

121-
if a.storer == nil {
122-
// errs = append(errs, errors.New("attester has no attestation storer defined"))
123-
}
124-
125126
return errors.Join(errs...)
126127
}
127128

pkg/sourcetool/options.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,34 @@ func WithGithubCollector(yesno bool) ConfigFn {
1818
}
1919
}
2020

21+
func WithGithubStorer(yesno bool) ConfigFn {
22+
return func(t *Tool) error {
23+
t.Options.InitGHStorer = yesno
24+
return nil
25+
}
26+
}
27+
2128
func WithNotesCollector(yesno bool) ConfigFn {
2229
return func(t *Tool) error {
2330
t.Options.InitNotesCollector = yesno
2431
return nil
2532
}
2633
}
2734

35+
func WithNotesStorer(yesno bool) ConfigFn {
36+
return func(t *Tool) error {
37+
t.Options.InitNotesStorer = yesno
38+
return nil
39+
}
40+
}
41+
42+
func WithStorageLocation(l ...string) ConfigFn {
43+
return func(t *Tool) error {
44+
t.Options.StorageLocations = l
45+
return nil
46+
}
47+
}
48+
2849
func WithAuthenticator(a *auth.Authenticator) ConfigFn {
2950
return func(t *Tool) error {
3051
if a == nil {

pkg/sourcetool/options/options.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,15 @@ type Options struct {
2222
// PolicyRepo is the repository where the policies are stored
2323
PolicyRepo string
2424

25-
// Initialize GitHub attestations store collector
25+
// Initialize GitHub attestations storer and fetcher
2626
InitGHCollector bool
27+
InitGHStorer bool
2728

28-
// Initialize Dynamic notes collector
29+
// Initialize Dynamic notes storer and fetcher
2930
InitNotesCollector bool
31+
InitNotesStorer bool
32+
33+
StorageLocations []string
3034

3135
models.BackendOptions
3236
}

0 commit comments

Comments
 (0)