From c703d44acf065d2cd122b0018604d7a34c736cfb Mon Sep 17 00:00:00 2001 From: Miguel Martinez Trivino Date: Wed, 22 Mar 2023 13:17:59 +0100 Subject: [PATCH 1/3] fix: new cas uploader digest Signed-off-by: Miguel Martinez Trivino --- app/controlplane/internal/biz/attestation.go | 6 +++--- app/controlplane/internal/service/workflowrun.go | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/app/controlplane/internal/biz/attestation.go b/app/controlplane/internal/biz/attestation.go index 99669622f..379d27283 100644 --- a/app/controlplane/internal/biz/attestation.go +++ b/app/controlplane/internal/biz/attestation.go @@ -80,11 +80,11 @@ func (uc *AttestationUseCase) UploadToCAS(ctx context.Context, envelope *dsse.En hash := sha256.New() hash.Write(jsonContent) - digest := fmt.Sprintf("%x", hash.Sum(nil)) + sha256sum := fmt.Sprintf("%x", hash.Sum(nil)) - if err := uc.CASClient.Upload(ctx, secretID, bytes.NewBuffer(jsonContent), filename, digest); err != nil { + if err := uc.CASClient.Upload(ctx, secretID, bytes.NewBuffer(jsonContent), filename, fmt.Sprintf("sha256:%s", sha256sum)); err != nil { return "", fmt.Errorf("uploading to CAS: %w", err) } - return digest, nil + return sha256sum, nil } 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 From 38f4dabeeac5423c0ef06884c20ac27a0fec3a4c Mon Sep 17 00:00:00 2001 From: Miguel Martinez Trivino Date: Wed, 22 Mar 2023 13:56:53 +0100 Subject: [PATCH 2/3] chore: fix tests Signed-off-by: Miguel Martinez Trivino --- app/controlplane/internal/biz/attestation.go | 24 ++++++++++--------- .../internal/biz/attestation_test.go | 12 +++++----- .../internal/service/attestation.go | 2 +- .../internal/service/workflowrun.go | 4 ++-- 4 files changed, 22 insertions(+), 20 deletions(-) diff --git a/app/controlplane/internal/biz/attestation.go b/app/controlplane/internal/biz/attestation.go index 379d27283..16b74a3b1 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" ) @@ -55,11 +56,11 @@ func NewAttestationUseCase(client CASClient, logger log.Logger) *AttestationUseC } } -func (uc *AttestationUseCase) FetchFromStore(ctx context.Context, secretID, digest string) (*Attestation, error) { +func (uc *AttestationUseCase) FetchFromStore(ctx context.Context, secretID string, digest *cr_v1.Hash) (*Attestation, error) { uc.logger.Infow("msg", "downloading attestation", "digest", digest) buf := bytes.NewBuffer(nil) - if err := uc.CASClient.Download(ctx, secretID, buf, digest); err != nil { + if err := uc.CASClient.Download(ctx, secretID, buf, digest.String()); err != nil { return nil, fmt.Errorf("downloading from CAS: %w", err) } @@ -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) - sha256sum := 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, fmt.Sprintf("sha256:%s", sha256sum)); 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 sha256sum, nil + return &h, nil } diff --git a/app/controlplane/internal/biz/attestation_test.go b/app/controlplane/internal/biz/attestation_test.go index c6fcb7958..b4afc2fa7 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) 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 2facbd659..d63cee3f7 100644 --- a/app/controlplane/internal/service/workflowrun.go +++ b/app/controlplane/internal/service/workflowrun.go @@ -17,7 +17,6 @@ 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" @@ -26,6 +25,7 @@ import ( "github.com/chainloop-dev/chainloop/internal/credentials" sl "github.com/chainloop-dev/chainloop/internal/servicelogger" errors "github.com/go-kratos/kratos/v2/errors" + cr_v1 "github.com/google/go-containerregistry/pkg/v1" "google.golang.org/protobuf/types/known/timestamppb" ) @@ -116,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, fmt.Sprintf("sha256:%s", run.AttestationRef.Sha256)) + attestation, err = s.attestationUseCase.FetchFromStore(ctx, run.AttestationRef.SecretRef, &cr_v1.Hash{Algorithm: "sha256", Hex: 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 From b629428d5032ea50468fbf59ebdadd13b6eb57f1 Mon Sep 17 00:00:00 2001 From: Miguel Martinez Trivino Date: Wed, 22 Mar 2023 14:00:14 +0100 Subject: [PATCH 3/3] chore: fix tests Signed-off-by: Miguel Martinez Trivino --- app/controlplane/internal/biz/attestation.go | 4 ++-- app/controlplane/internal/biz/attestation_test.go | 2 +- app/controlplane/internal/service/workflowrun.go | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/controlplane/internal/biz/attestation.go b/app/controlplane/internal/biz/attestation.go index 16b74a3b1..ec717fcfd 100644 --- a/app/controlplane/internal/biz/attestation.go +++ b/app/controlplane/internal/biz/attestation.go @@ -56,11 +56,11 @@ func NewAttestationUseCase(client CASClient, logger log.Logger) *AttestationUseC } } -func (uc *AttestationUseCase) FetchFromStore(ctx context.Context, secretID string, digest *cr_v1.Hash) (*Attestation, error) { +func (uc *AttestationUseCase) FetchFromStore(ctx context.Context, secretID, digest string) (*Attestation, error) { uc.logger.Infow("msg", "downloading attestation", "digest", digest) buf := bytes.NewBuffer(nil) - if err := uc.CASClient.Download(ctx, secretID, buf, digest.String()); err != nil { + if err := uc.CASClient.Download(ctx, secretID, buf, digest); err != nil { return nil, fmt.Errorf("downloading from CAS: %w", err) } diff --git a/app/controlplane/internal/biz/attestation_test.go b/app/controlplane/internal/biz/attestation_test.go index b4afc2fa7..20265e153 100644 --- a/app/controlplane/internal/biz/attestation_test.go +++ b/app/controlplane/internal/biz/attestation_test.go @@ -60,7 +60,7 @@ func (s *attestationTestSuite) TestFetchFromStore() { 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/workflowrun.go b/app/controlplane/internal/service/workflowrun.go index d63cee3f7..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" @@ -25,7 +26,6 @@ import ( "github.com/chainloop-dev/chainloop/internal/credentials" sl "github.com/chainloop-dev/chainloop/internal/servicelogger" errors "github.com/go-kratos/kratos/v2/errors" - cr_v1 "github.com/google/go-containerregistry/pkg/v1" "google.golang.org/protobuf/types/known/timestamppb" ) @@ -116,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, &cr_v1.Hash{Algorithm: "sha256", Hex: 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