Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 11 additions & 9 deletions app/controlplane/internal/biz/attestation.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,14 @@ package biz
import (
"bytes"
"context"
"crypto/sha256"
"encoding/json"
"fmt"
"io"

"github.com/chainloop-dev/chainloop/internal/servicelogger"
"github.com/go-kratos/kratos/v2/log"

cr_v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/secure-systems-lab/go-securesystemslib/dsse"
)

Expand Down Expand Up @@ -71,20 +72,21 @@ func (uc *AttestationUseCase) FetchFromStore(ctx context.Context, secretID, dige
return &Attestation{Envelope: &envelope}, nil
}

func (uc *AttestationUseCase) UploadToCAS(ctx context.Context, envelope *dsse.Envelope, secretID, workflowRunID string) (string, error) {
func (uc *AttestationUseCase) UploadToCAS(ctx context.Context, envelope *dsse.Envelope, secretID, workflowRunID string) (*cr_v1.Hash, error) {
filename := fmt.Sprintf("attestation-%s.json", workflowRunID)
jsonContent, err := json.Marshal(envelope)
if err != nil {
return "", fmt.Errorf("marshaling the envelope: %w", err)
return nil, fmt.Errorf("marshaling the envelope: %w", err)
}

hash := sha256.New()
hash.Write(jsonContent)
digest := fmt.Sprintf("%x", hash.Sum(nil))
h, _, err := cr_v1.SHA256(bytes.NewBuffer(jsonContent))
if err != nil {
return nil, fmt.Errorf("calculating the digest: %w", err)
}

if err := uc.CASClient.Upload(ctx, secretID, bytes.NewBuffer(jsonContent), filename, digest); err != nil {
return "", fmt.Errorf("uploading to CAS: %w", err)
if err := uc.CASClient.Upload(ctx, secretID, bytes.NewBuffer(jsonContent), filename, h.String()); err != nil {
return nil, fmt.Errorf("uploading to CAS: %w", err)
}

return digest, nil
return &h, nil
}
12 changes: 6 additions & 6 deletions app/controlplane/internal/biz/attestation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (

"github.com/chainloop-dev/chainloop/app/controlplane/internal/biz"
"github.com/chainloop-dev/chainloop/app/controlplane/internal/biz/mocks"
cr_v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/uuid"
"github.com/secure-systems-lab/go-securesystemslib/dsse"
"github.com/stretchr/testify/assert"
Expand All @@ -35,32 +36,31 @@ import (
var runID = uuid.NewString()
var envelope = &dsse.Envelope{}

const expectedDigest = "f845058d865c3d4d491c9019f6afe9c543ad2cd11b31620cc512e341fb03d3d8"
var expectedDigest = cr_v1.Hash{Algorithm: "sha256", Hex: "f845058d865c3d4d491c9019f6afe9c543ad2cd11b31620cc512e341fb03d3d8"}

func (s *attestationTestSuite) TestUploadToCAS() {
ctx := context.Background()
s.casClient.On(
"Upload", ctx, "my-secret", mock.Anything,
fmt.Sprintf("attestation-%s.json", runID), expectedDigest,
fmt.Sprintf("attestation-%s.json", runID), expectedDigest.String(),
).Return(nil)

gotDigest, err := s.uc.UploadToCAS(ctx, envelope, "my-secret", runID)
assert.NoError(s.T(), err)
assert.Equal(s.T(), expectedDigest, gotDigest)
assert.Equal(s.T(), &expectedDigest, gotDigest)
}

func (s *attestationTestSuite) TestFetchFromStore() {
want := &biz.Attestation{Envelope: &dsse.Envelope{}}

ctx := context.Background()
s.casClient.On("Download", ctx, "my-secret", mock.Anything, expectedDigest).Return(nil).Run(
s.casClient.On("Download", ctx, "my-secret", mock.Anything, expectedDigest.String()).Return(nil).Run(
func(args mock.Arguments) {
buf := args.Get(2).(io.Writer)
err := json.NewEncoder(buf).Encode(want)
require.NoError(s.T(), err)
})

got, err := s.uc.FetchFromStore(ctx, "my-secret", expectedDigest)
got, err := s.uc.FetchFromStore(ctx, "my-secret", expectedDigest.String())
assert.NoError(s.T(), err)
assert.Equal(s.T(), want, got)
}
Expand Down
2 changes: 1 addition & 1 deletion app/controlplane/internal/service/attestation.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ func (s *AttestationService) Store(ctx context.Context, req *cpAPI.AttestationSe
}

// associate the attestation stored in the CAS with the workflow run
if err := s.wrUseCase.AssociateAttestation(ctx, req.WorkflowRunId, &biz.AttestationRef{Sha256: digest, SecretRef: repo.SecretName}); err != nil {
if err := s.wrUseCase.AssociateAttestation(ctx, req.WorkflowRunId, &biz.AttestationRef{Sha256: digest.Hex, SecretRef: repo.SecretName}); err != nil {
return err
}

Expand Down
3 changes: 2 additions & 1 deletion app/controlplane/internal/service/workflowrun.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package service

import (
"context"
"fmt"

pb "github.com/chainloop-dev/chainloop/app/controlplane/api/controlplane/v1"
craftingpb "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1"
Expand Down Expand Up @@ -115,7 +116,7 @@ func (s *WorkflowRunService) View(ctx context.Context, req *pb.WorkflowRunServic
var attestation *biz.Attestation
// Download the attestation if the workflow run is successful
if run.AttestationRef != nil {
attestation, err = s.attestationUseCase.FetchFromStore(ctx, run.AttestationRef.SecretRef, run.AttestationRef.Sha256)
attestation, err = s.attestationUseCase.FetchFromStore(ctx, run.AttestationRef.SecretRef, fmt.Sprintf("sha256:%s", run.AttestationRef.Sha256))
if err != nil {
// NOTE: For now we don't return an error if the attestation is not found
// since we do not have a good error recovery in place for assets
Expand Down