From a9933b1a039e9c826bf4e3aab4439fe85dad2173 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adolfo=20Garc=C3=ADa=20Veytia=20=28Puerco=29?= Date: Fri, 5 Jun 2026 18:03:20 -0600 Subject: [PATCH] Push attestation from memory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit modifies the attestation push logic to ship the attestations from memory instead of the bolted-on mechanism we had earlier where we would write to disk, reparse and push. Signed-off-by: Adolfo GarcĂ­a Veytia (Puerco) --- pkg/sourcetool/tool.go | 42 +++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/pkg/sourcetool/tool.go b/pkg/sourcetool/tool.go index b967213..d433378 100644 --- a/pkg/sourcetool/tool.go +++ b/pkg/sourcetool/tool.go @@ -6,6 +6,7 @@ package sourcetool import ( + "bytes" "context" "errors" "fmt" @@ -14,7 +15,9 @@ import ( "strings" "time" + "github.com/carabiner-dev/attestation" "github.com/carabiner-dev/collector" + "github.com/carabiner-dev/collector/envelope" cgithub "github.com/carabiner-dev/collector/repository/github" "github.com/carabiner-dev/collector/repository/note" "google.golang.org/protobuf/encoding/protojson" @@ -501,30 +504,31 @@ func (t *Tool) AttestRevision( fmt.Printf("%s\n%s\n", string(provenanceData), vsaData) } - fpath := opts.OutputPath - if fpath == "" { - f, err := os.CreateTemp("", "attestations-") - if err != nil { - return nil, fmt.Errorf("opening tmp file: %w", err) + // Write the bundle to disk only when an output path was requested. The push + // below works from memory, so there is no longer a need for a temp file. + if opts.OutputPath != "" { + if err := os.WriteFile( + opts.OutputPath, fmt.Appendf(nil, "%s\n%s\n", string(provenanceData), vsaData), os.FileMode(0o600), + ); err != nil { + return nil, fmt.Errorf("writing attestations: %w", err) } - f.Close() //nolint:errcheck,gosec - fpath = f.Name() } - defer func() { - if opts.OutputPath == "" { - os.Remove(fpath) //nolint:errcheck,gosec + if opts.Push { + // Push the attestations from memory rather than re-reading the bundle + // file: the file holds two records (provenance + VSA) as JSONL, which the + // storer's single-document parser can't ingest. Parse each signed bundle + // individually and store the envelopes directly. + var envelopes []attestation.Envelope + for _, data := range [][]byte{provenanceData, []byte(vsaData)} { + parsed, err := envelope.Parsers.Parse(bytes.NewReader(data)) + if err != nil { + return nil, fmt.Errorf("parsing attestation to push: %w", err) + } + envelopes = append(envelopes, parsed...) } - }() - - if err := os.WriteFile( - fpath, fmt.Appendf(nil, "%s\n%s\n", string(provenanceData), vsaData), os.FileMode(0o600), - ); err != nil { - return nil, fmt.Errorf("writing attestations: %w", err) - } - if opts.Push { - if err := agent.StoreFromFiles(ctx, []string{fpath}); err != nil { + if err := agent.Store(ctx, envelopes); err != nil { return nil, fmt.Errorf("pushing attestations: %w", err) } }