Skip to content

Commit

Permalink
refactor: consolidate credentials service interface (#25)
Browse files Browse the repository at this point in the history
---------

Signed-off-by: Miguel Martinez Trivino <[email protected]>
  • Loading branch information
migmartri authored Mar 13, 2023
1 parent a027e86 commit e770fae
Show file tree
Hide file tree
Showing 20 changed files with 248 additions and 362 deletions.
8 changes: 4 additions & 4 deletions app/cli/cmd/workflow_contract_describe.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ func encodeContractOutput(run *action.WorkflowContractWithVersionItem) error {

switch flagOutputFormat {
case formatContract:
marshaller := protojson.MarshalOptions{Indent: " "}
rawBody, err := marshaller.Marshal(run.Revision.BodyV1)
marshaler := protojson.MarshalOptions{Indent: " "}
rawBody, err := marshaler.Marshal(run.Revision.BodyV1)
if err != nil {
return err
}
Expand All @@ -86,8 +86,8 @@ func encodeContractOutput(run *action.WorkflowContractWithVersionItem) error {
func contractDescribeTableOutput(contractWithVersion *action.WorkflowContractWithVersionItem) error {
revision := contractWithVersion.Revision

marshaller := protojson.MarshalOptions{Indent: " "}
rawBody, err := marshaller.Marshal(revision.BodyV1)
marshaler := protojson.MarshalOptions{Indent: " "}
rawBody, err := marshaler.Marshal(revision.BodyV1)
if err != nil {
return err
}
Expand Down
6 changes: 3 additions & 3 deletions app/cli/internal/action/workflow_run_describe.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ func (action *WorkflowRunDescribe) Run(runID string, verify bool, publicKey stri
}

if err := json.Unmarshal(decodedPayload, statement); err != nil {
return nil, fmt.Errorf("unmarshalling predicate: %w", err)
return nil, fmt.Errorf("un-marshaling predicate: %w", err)
}

var predicate *renderer.ChainloopProvenancePredicateV1
Expand Down Expand Up @@ -159,12 +159,12 @@ func (action *WorkflowRunDescribe) Run(runID string, verify bool, publicKey stri
func extractPredicateV1(statement *in_toto.Statement) (*renderer.ChainloopProvenancePredicateV1, error) {
jsonPredicate, err := json.Marshal(statement.Predicate)
if err != nil {
return nil, fmt.Errorf("unmarshalling predicate: %w", err)
return nil, fmt.Errorf("un-marshaling predicate: %w", err)
}

predicate := &renderer.ChainloopProvenancePredicateV1{}
if err := json.Unmarshal(jsonPredicate, predicate); err != nil {
return nil, fmt.Errorf("unmarshalling predicate: %w", err)
return nil, fmt.Errorf("un-marshaling predicate: %w", err)
}

return predicate, nil
Expand Down
2 changes: 1 addition & 1 deletion app/controlplane/internal/biz/attestation.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ func doUploadToOCI(ctx context.Context, backend backend.Uploader, runID string,
fileName := fmt.Sprintf("attestation-%s.json", runID)
jsonContent, err := json.Marshal(envelope)
if err != nil {
return "", fmt.Errorf("marshalling the envelope: %w", err)
return "", fmt.Errorf("marshaling the envelope: %w", err)
}

hash := sha256.New()
Expand Down
16 changes: 13 additions & 3 deletions app/controlplane/internal/biz/integration.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,14 @@ func (uc *IntegrationUseCase) AddDependencyTrack(ctx context.Context, orgID, hos
return nil, NewErrInvalidUUID(err)
}

// Validate Credentials before saving them
creds := &credentials.APICreds{Host: host, Key: apiKey}
if err := creds.Validate(); err != nil {
return nil, newErrValidation(err)
}

// Create the secret in the external secrets manager
secretID, err := uc.credsRW.SaveAPICreds(ctx, orgID, &credentials.APICreds{Host: host, Key: apiKey})
secretID, err := uc.credsRW.SaveCredentials(ctx, orgID, creds)
if err != nil {
return nil, fmt.Errorf("storing the credentials: %w", err)
}
Expand Down Expand Up @@ -160,7 +166,7 @@ func (uc *IntegrationUseCase) Delete(ctx context.Context, orgID, integrationID s

if integration.SecretName != "" {
uc.logger.Infow("msg", "deleting integration external secrets", "ID", integrationID, "secretName", integration.SecretName)
if err := uc.credsRW.DeleteCreds(ctx, integration.SecretName); err != nil {
if err := uc.credsRW.DeleteCredentials(ctx, integration.SecretName); err != nil {
return fmt.Errorf("deleting the credentials: %w", err)
}
}
Expand Down Expand Up @@ -274,10 +280,14 @@ func validateAttachment(ctx context.Context, integration *Integration, credsR cr

// Check with the actual remote data that an upload would be possible
creds := &credentials.APICreds{}
if err := credsR.ReadAPICreds(ctx, integration.SecretName, creds); err != nil {
if err := credsR.ReadCredentials(ctx, integration.SecretName, creds); err != nil {
return err
}

if err := creds.Validate(); err != nil {
return newErrValidation(err)
}

// Instantiate an actual uploader to see if it would work with the current configuration
d, err := dependencytrack.NewSBOMUploader(c.DependencyTrack.GetDomain(), creds.Key,
nil, ac.GetDependencyTrack().GetProjectId(), ac.GetDependencyTrack().GetProjectName())
Expand Down
11 changes: 8 additions & 3 deletions app/controlplane/internal/biz/ocirepository.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,13 @@ func (uc *OCIRepositoryUseCase) CreateOrUpdate(ctx context.Context, orgID, repoU
return nil, NewErrInvalidUUID(err)
}

// Create the secret in the external secrets manager
secretName, err := uc.credsRW.SaveOCICreds(ctx, orgID, &credentials.OCIKeypair{Repo: repoURL, Username: username, Password: password})
// Validate and store the secret in the external secrets manager
creds := &credentials.OCIKeypair{Repo: repoURL, Username: username, Password: password}
if err := creds.Validate(); err != nil {
return nil, newErrValidation(err)
}

secretName, err := uc.credsRW.SaveCredentials(ctx, orgID, creds)
if err != nil {
return nil, fmt.Errorf("storing the credentials: %w", err)
}
Expand Down Expand Up @@ -167,7 +172,7 @@ func (uc *OCIRepositoryUseCase) Delete(ctx context.Context, id string) error {

uc.logger.Infow("msg", "deleting OCI repository external secrets", "ID", id, "secretName", repo.SecretName)
// Delete the secret in the external secrets manager
if err := uc.credsRW.DeleteCreds(ctx, repo.SecretName); err != nil {
if err := uc.credsRW.DeleteCredentials(ctx, repo.SecretName); err != nil {
return fmt.Errorf("deleting the credentials: %w", err)
}

Expand Down
4 changes: 2 additions & 2 deletions app/controlplane/internal/biz/ocirepository_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ func (s *ociRepositoryTestSuite) TestSaveMainRepoAlreadyExist() {
r := &biz.OCIRepository{ID: s.validUUID.String()}
ctx := context.Background()
s.repo.On("FindMainRepo", ctx, s.validUUID).Return(r, nil)
s.credsRW.On("SaveOCICreds", ctx, s.validUUID.String(), mock.Anything).Return("secret-key", nil)
s.credsRW.On("SaveCredentials", ctx, s.validUUID.String(), mock.Anything).Return("secret-key", nil)
s.repo.On("Update", ctx, &biz.OCIRepoUpdateOpts{
ID: s.validUUID,
OCIRepoOpts: &biz.OCIRepoOpts{
Expand All @@ -105,7 +105,7 @@ func (s *ociRepositoryTestSuite) TestSaveMainRepoOk() {
const repo, username, password = "repo", "username", "pass"

s.repo.On("FindMainRepo", ctx, s.validUUID).Return(nil, nil)
s.credsRW.On("SaveOCICreds", ctx, s.validUUID.String(), mock.Anything).Return("secret-key", nil)
s.credsRW.On("SaveCredentials", ctx, s.validUUID.String(), mock.Anything).Return("secret-key", nil)

newRepo := &biz.OCIRepository{}
s.repo.On("Create", ctx, &biz.OCIRepoCreateOpts{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ func (s *OrgIntegrationTestSuite) TestDeleteOrg() {

s.T().Run("org, integrations and repositories deletion", func(t *testing.T) {
// Mock calls to credentials deletion for both the integration and the OCI repository
s.mockedCredsReaderWriter.On("DeleteCreds", ctx, "stored-integration-secret").Return(nil)
s.mockedCredsReaderWriter.On("DeleteCreds", ctx, "stored-OCI-secret").Return(nil)
s.mockedCredsReaderWriter.On("DeleteCredentials", ctx, "stored-integration-secret").Return(nil)
s.mockedCredsReaderWriter.On("DeleteCredentials", ctx, "stored-OCI-secret").Return(nil)

err := s.Organization.Delete(ctx, s.org.ID)
assert.NoError(err)
Expand Down Expand Up @@ -102,12 +102,12 @@ func (s *OrgIntegrationTestSuite) SetupTest() {

// Dependency-track integration credentials
s.mockedCredsReaderWriter.On(
"SaveAPICreds", ctx, mock.Anything, &credentials.APICreds{Host: "host", Key: "key"},
"SaveCredentials", ctx, mock.Anything, &credentials.APICreds{Host: "host", Key: "key"},
).Return("stored-integration-secret", nil)

// OCI repository credentials
s.mockedCredsReaderWriter.On(
"SaveOCICreds", ctx, mock.Anything, &credentials.OCIKeypair{Repo: "repo", Username: "username", Password: "pass"},
"SaveCredentials", ctx, mock.Anything, &credentials.OCIKeypair{Repo: "repo", Username: "username", Password: "pass"},
).Return("stored-OCI-secret", nil)

s.TestingUseCases = testhelpers.NewTestingUseCases(t, testhelpers.WithCredsReaderWriter(s.mockedCredsReaderWriter))
Expand Down
8 changes: 4 additions & 4 deletions app/controlplane/internal/service/attestation.go
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ func extractPredicate(envelope *dsse.Envelope) (*renderer.ChainloopProvenancePre

statement := &in_toto.Statement{}
if err := json.Unmarshal(decodedPayload, statement); err != nil {
return nil, fmt.Errorf("unmarshalling predicate: %w", err)
return nil, fmt.Errorf("un-marshaling predicate: %w", err)
}

var predicate *renderer.ChainloopProvenancePredicateV1
Expand Down Expand Up @@ -370,12 +370,12 @@ func extractMaterials(in []*renderer.ChainloopProvenanceMaterial) []*cpAPI.Attes
func extractPredicateV1(statement *in_toto.Statement) (*renderer.ChainloopProvenancePredicateV1, error) {
jsonPredicate, err := json.Marshal(statement.Predicate)
if err != nil {
return nil, fmt.Errorf("unmarshalling predicate: %w", err)
return nil, fmt.Errorf("un-marshaling predicate: %w", err)
}

predicate := &renderer.ChainloopProvenancePredicateV1{}
if err := json.Unmarshal(jsonPredicate, predicate); err != nil {
return nil, fmt.Errorf("unmarshalling predicate: %w", err)
return nil, fmt.Errorf("un-marshaling predicate: %w", err)
}

return predicate, nil
Expand Down Expand Up @@ -503,7 +503,7 @@ func doSendToDependencyTrack(ctx context.Context, credsReader credentials.Reader
attachmentConfig := i.IntegrationAttachment.Config.GetDependencyTrack()

creds := &credentials.APICreds{}
if err := credsReader.ReadAPICreds(ctx, i.SecretName, creds); err != nil {
if err := credsReader.ReadCredentials(ctx, i.SecretName, creds); err != nil {
return err
}

Expand Down
6 changes: 3 additions & 3 deletions internal/attestation/crafter/crafter.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ func NewCrafter(opts ...NewOpt) *Crafter {
type InitOpts struct {
// Control plane workflow metadata
WfInfo *api.WorkflowMetadata
// already marshalled schema
// already marshaled schema
SchemaV1 *schemaapi.CraftingSchema
// do not record, upload or push attestation
DryRun bool
Expand Down Expand Up @@ -243,8 +243,8 @@ func initialCraftingState(schema *schemaapi.CraftingSchema, wf *api.WorkflowMeta
}

func persistCraftingState(craftState *api.CraftingState, stateFilePath string) error {
marshaller := protojson.MarshalOptions{Indent: " "}
raw, err := marshaller.Marshal(craftState)
marshaler := protojson.MarshalOptions{Indent: " "}
raw, err := marshaler.Marshal(craftState)
if err != nil {
return err
}
Expand Down
7 changes: 6 additions & 1 deletion internal/blobmanager/oci/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package oci

import (
"context"
"fmt"

backend "github.com/chainloop-dev/chainloop/internal/blobmanager"
"github.com/chainloop-dev/chainloop/internal/credentials"
Expand All @@ -35,10 +36,14 @@ func NewBackendProvider(cReader credentials.Reader) *BackendProvider {

func (p *BackendProvider) FromCredentials(ctx context.Context, secretName string) (backend.UploaderDownloader, error) {
creds := &credentials.OCIKeypair{}
if err := p.cReader.ReadOCICreds(ctx, secretName, creds); err != nil {
if err := p.cReader.ReadCredentials(ctx, secretName, creds); err != nil {
return nil, err
}

if err := creds.Validate(); err != nil {
return nil, fmt.Errorf("invalid credentials retrieved from storage: %w", err)
}

k, err := ociauth.NewCredentials(creds.Repo, creds.Username, creds.Password)
if err != nil {
return nil, err
Expand Down
2 changes: 1 addition & 1 deletion internal/blobmanager/oci/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func TestFromCredentials(t *testing.T) {
r := mocks.NewReader(t)
const repo, password, username = "repo", "password", "username"

r.On("ReadOCICreds", ctx, "secretName", mock.AnythingOfType("*credentials.OCIKeypair")).Return(nil).Run(
r.On("ReadCredentials", ctx, "secretName", mock.AnythingOfType("*credentials.OCIKeypair")).Return(nil).Run(
func(args mock.Arguments) {
credentials := args.Get(2).(*credentials.OCIKeypair)
credentials.Repo = repo
Expand Down
66 changes: 17 additions & 49 deletions internal/credentials/aws/secretmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,55 +83,15 @@ func NewManager(opts *NewManagerOpts) (*Manager, error) {
}, nil
}

func (m *Manager) SaveOCICreds(ctx context.Context, orgID string, creds *credentials.OCIKeypair) (string, error) {
if err := creds.Validate(); err != nil {
return "", fmt.Errorf("validating OCI keypair: %w", err)
}

return m.save(ctx, orgID, creds)
}

func (m *Manager) SaveAPICreds(ctx context.Context, orgID string, creds *credentials.APICreds) (string, error) {
if err := creds.Validate(); err != nil {
return "", fmt.Errorf("validating API creds: %w", err)
}

return m.save(ctx, orgID, creds)
}

func (m *Manager) ReadAPICreds(ctx context.Context, secretID string, creds *credentials.APICreds) error {
raw, err := m.read(ctx, secretID)
if err != nil {
return fmt.Errorf("getting the secret from AWS: %w", err)
}

return json.Unmarshal(raw, creds)
}

func (m *Manager) ReadOCICreds(ctx context.Context, secretID string, creds *credentials.OCIKeypair) error {
raw, err := m.read(ctx, secretID)
if err != nil {
return fmt.Errorf("getting the secret from AWS: %w", err)
}

return json.Unmarshal(raw, creds)
}

func (m *Manager) DeleteCreds(ctx context.Context, secretID string) error {
_, err := m.client.DeleteSecret(ctx, &secretsmanager.DeleteSecretInput{
SecretId: aws.String(secretID),
})

return err
}

func (m *Manager) save(ctx context.Context, orgID string, creds interface{}) (string, error) {
// Save Credentials, this is a generic function that can be used to save any type of credentials
// as long as they can be passed to json.Marshal
func (m *Manager) SaveCredentials(ctx context.Context, orgID string, creds any) (string, error) {
secretName := strings.Join([]string{m.secretPrefix, orgID, uuid.Generate().String()}, "/")

// Store the credentials as json keypairs
// Store the credentials as json key pairs
c, err := json.Marshal(creds)
if err != nil {
return "", fmt.Errorf("marshalling credentials to be stored: %w", err)
return "", fmt.Errorf("marshaling credentials to be stored: %w", err)
}

if _, err = m.client.CreateSecret(ctx, &secretsmanager.CreateSecretInput{
Expand All @@ -143,7 +103,7 @@ func (m *Manager) save(ctx context.Context, orgID string, creds interface{}) (st
return secretName, nil
}

func (m *Manager) read(ctx context.Context, secretID string) ([]byte, error) {
func (m *Manager) ReadCredentials(ctx context.Context, secretID string, creds any) error {
resp, err := m.client.GetSecretValue(ctx, &secretsmanager.GetSecretValueInput{
SecretId: aws.String(secretID),
})
Expand All @@ -153,12 +113,20 @@ func (m *Manager) read(ctx context.Context, secretID string) ([]byte, error) {
if errors.As(err, &apiErr) {
switch apiErr.ErrorCode() {
case (&types.ResourceNotFoundException{}).ErrorCode():
return nil, fmt.Errorf("%w: path=%s", credentials.ErrNotFound, secretID)
return fmt.Errorf("%w: path=%s", credentials.ErrNotFound, secretID)
default:
return nil, err
return err
}
}
}

return []byte(*resp.SecretString), nil
return json.Unmarshal([]byte(*resp.SecretString), creds)
}

func (m *Manager) DeleteCredentials(ctx context.Context, secretID string) error {
_, err := m.client.DeleteSecret(ctx, &secretsmanager.DeleteSecretInput{
SecretId: aws.String(secretID),
})

return err
}
Loading

0 comments on commit e770fae

Please sign in to comment.