diff --git a/app/controlplane/internal/biz/attestation.go b/app/controlplane/internal/biz/attestation.go index 99669622f..ec717fcfd 100644 --- a/app/controlplane/internal/biz/attestation.go +++ b/app/controlplane/internal/biz/attestation.go @@ -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" ) @@ -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 } diff --git a/app/controlplane/internal/biz/attestation_test.go b/app/controlplane/internal/biz/attestation_test.go index c6fcb7958..20265e153 100644 --- a/app/controlplane/internal/biz/attestation_test.go +++ b/app/controlplane/internal/biz/attestation_test.go @@ -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" @@ -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) } diff --git a/app/controlplane/internal/service/attestation.go b/app/controlplane/internal/service/attestation.go index a46f5815f..b26406c83 100644 --- a/app/controlplane/internal/service/attestation.go +++ b/app/controlplane/internal/service/attestation.go @@ -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 } diff --git a/app/controlplane/internal/service/workflowrun.go b/app/controlplane/internal/service/workflowrun.go index 7ebcf7ac4..2facbd659 100644 --- a/app/controlplane/internal/service/workflowrun.go +++ b/app/controlplane/internal/service/workflowrun.go @@ -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" @@ -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