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
8 changes: 4 additions & 4 deletions app/controlplane/pkg/auditor/events/casbackend.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ type CASBackendBase struct {
CASBackendName string `json:"cas_backend_name,omitempty"`
Provider string `json:"provider,omitempty"`
Location string `json:"location,omitempty"`
Default bool `json:"default,omitempty"`
Default bool `json:"default"`
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've removed all omitempty from the bool fields so they are properly serialized in JSON when stored in the database with the proper value.

}

func (c *CASBackendBase) RequiresActor() bool {
Expand Down Expand Up @@ -100,8 +100,8 @@ func (c *CASBackendCreated) Description() string {
type CASBackendUpdated struct {
*CASBackendBase
NewDescription *string `json:"new_description,omitempty"`
CredentialsChanged bool `json:"credentials_changed,omitempty"`
PreviousDefault bool `json:"previous_default,omitempty"`
CredentialsChanged bool `json:"credentials_changed"`
PreviousDefault bool `json:"previous_default"`
}

func (c *CASBackendUpdated) ActionType() string {
Expand Down Expand Up @@ -184,7 +184,7 @@ type CASBackendStatusChanged struct {
PreviousStatus string `json:"previous_status,omitempty"`
NewStatus string `json:"new_status,omitempty"`
StatusError string `json:"status_error,omitempty"`
IsRecovery bool `json:"is_recovery,omitempty"`
IsRecovery bool `json:"is_recovery"`
}

func (c *CASBackendStatusChanged) ActionType() string {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
"location": "test-location",
"default": true,
"previous_status": "OK",
"new_status": "Invalid"
"new_status": "Invalid",
"is_recovery": false
},
"Digest": "sha256:2112ea486d9e36c40a6869efcbf745836742c70dc97a17cffe30ae3651b0579c"
"Digest": "sha256:496bc2b996945222ab4f96cf62d3ff5c08dcc92a4647a6e4bdd3def7de7288ab"
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
"location": "test-location",
"default": true,
"new_description": "test description",
"credentials_changed": true
"credentials_changed": true,
"previous_default": false
},
"Digest": "sha256:2c738aacd42a4257f9496c270586c1edf0be13d0d10160e8c564a96fedf0a726"
"Digest": "sha256:5d893a99885dcb465c30558736487493c5f24a61a7f28d1738b9b237f4c8fdc5"
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@
"cas_backend_name": "test-backend",
"provider": "OCI",
"location": "test-location",
"default": false,
"new_description": "test description",
"credentials_changed": false,
"previous_default": true
},
"Digest": "sha256:c229b657b7f984a60a2e7c5b6eab1137f026e50eecd76bc718f6548c006d625f"
"Digest": "sha256:8d7db84ea1e85b5c033ccb0c7b553bd57292554383498094fd1eb36d4dc3c1cd"
}
41 changes: 35 additions & 6 deletions app/controlplane/pkg/biz/casbackend.go
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,7 @@ func (uc *CASBackendUseCase) Update(ctx context.Context, orgID, id, description
}

var secretName string
credentialsUpdated := creds != nil
// We want to rotate credentials
if creds != nil {
secretName, err = uc.credsRW.SaveCredentials(ctx, orgID, creds)
Expand All @@ -344,18 +345,46 @@ func (uc *CASBackendUseCase) Update(ctx context.Context, orgID, id, description
}
}

after, err := uc.repo.Update(ctx, &CASBackendUpdateOpts{
// Update the backend without modifying validation status directly
// The validation status will be updated through PerformValidation if needed
// Don't set validation status here - let PerformValidation handle it
updateOpts := &CASBackendUpdateOpts{
ID: uuid,
CASBackendOpts: &CASBackendOpts{
SecretName: secretName, Default: defaultB, Description: description, OrgID: orgUUID,
ValidationStatus: CASBackendValidationOK,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this was a hack. Thanks for taking care.

ValidationError: ToPtr(""),
SecretName: secretName,
Default: defaultB,
Description: description,
OrgID: orgUUID,
},
})
}

// If we're not updating credentials, preserve the current validation status
if !credentialsUpdated {
updateOpts.ValidationStatus = before.ValidationStatus
updateOpts.ValidationError = before.ValidationError
}

after, err := uc.repo.Update(ctx, updateOpts)
if err != nil {
return nil, err
}

// If credentials were updated, perform validation to check if they work
// This will properly update validation status and send events
if credentialsUpdated {
if err := uc.PerformValidation(ctx, id); err != nil {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This part was missing, if we rotate the credentials from the Update, we need to perform a validation to update and send the proper status. The PerformValidation takes care of updating the status of the CAS Backend.

// Log the validation error but don't fail the update operation
// The validation status will be updated by PerformValidation
uc.logger.Warnw("msg", "validation failed after credential update", "ID", id, "error", err)
}

// Reload the backend to get the updated validation status
after, err = uc.repo.FindByIDInOrg(ctx, orgUUID, uuid)
if err != nil {
return nil, fmt.Errorf("reloading backend after validation: %w", err)
}
}

// If we just updated the backend from default=true => default=false, we need to set up the fallback as default
if before.Default && !after.Default {
if _, err := uc.defaultFallbackBackend(ctx, orgID); err != nil {
Expand All @@ -374,7 +403,7 @@ func (uc *CASBackendUseCase) Update(ctx context.Context, orgID, id, description
Default: after.Default,
},
NewDescription: &description,
CredentialsChanged: creds != nil,
CredentialsChanged: credentialsUpdated,
PreviousDefault: before.Default,
}, &orgUUID)
}
Expand Down
14 changes: 13 additions & 1 deletion app/controlplane/pkg/biz/casbackend_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import (

"github.com/chainloop-dev/chainloop/app/controlplane/pkg/biz"
"github.com/chainloop-dev/chainloop/app/controlplane/pkg/biz/testhelpers"
backends "github.com/chainloop-dev/chainloop/pkg/blobmanager"
blobM "github.com/chainloop-dev/chainloop/pkg/blobmanager/mocks"
"github.com/chainloop-dev/chainloop/pkg/blobmanager/oci"
creds "github.com/chainloop-dev/chainloop/pkg/credentials/mocks"
"github.com/google/go-cmp/cmp"
Expand Down Expand Up @@ -317,6 +319,8 @@ func (s *CASBackendIntegrationTestSuite) TestUpdate() {
ctx := context.TODO()
s.credsWriter.Mock = mock.Mock{}
s.credsWriter.On("SaveCredentials", ctx, s.orgNoBackend.ID, creds).Return("new-secret", nil)
s.credsWriter.On("ReadCredentials", ctx, "new-secret", mock.Anything).Return(nil)
s.backendProvider.On("ValidateAndExtractCredentials", location, mock.Anything).Return(nil, nil)
defaultB, err = s.CASBackend.Update(ctx, s.orgNoBackend.ID, defaultB.ID.String(), description, creds, true)
assert.NoError(err)
assert.Equal(description, defaultB.Description)
Expand Down Expand Up @@ -439,7 +443,14 @@ func (s *CASBackendIntegrationTestSuite) SetupTest() {
"SaveCredentials", mock.Anything, mock.Anything, mock.Anything,
).Return("stored-OCI-secret", nil)

s.TestingUseCases = testhelpers.NewTestingUseCases(s.T(), testhelpers.WithCredsReaderWriter(s.credsWriter))
// Create backend provider mock
s.backendProvider = blobM.NewProvider(s.T())

s.TestingUseCases = testhelpers.NewTestingUseCases(s.T(),
testhelpers.WithCredsReaderWriter(s.credsWriter),
testhelpers.WithBackendProviders(backends.Providers{
"OCI": s.backendProvider,
}))

s.orgOne, err = s.Organization.Create(ctx, "testing-org-1-with-one-backend")
assert.NoError(err)
Expand All @@ -465,6 +476,7 @@ type CASBackendIntegrationTestSuite struct {
orgTwo, orgOne, orgNoBackend *biz.Organization
casBackend1, casBackend2, casBackend3 *biz.CASBackend
credsWriter *creds.ReaderWriter
backendProvider *blobM.Provider
}

func TestIntegrationCASBackend(t *testing.T) {
Expand Down
6 changes: 6 additions & 0 deletions app/controlplane/pkg/biz/testhelpers/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,12 @@ func WithOnboardingConfiguration(conf []*config.OnboardingSpec) NewTestingUCOpt
}
}

func WithBackendProviders(providers backends.Providers) NewTestingUCOpt {
return func(tu *newTestingOpts) {
tu.providers = providers
}
}

func NewTestingUseCases(t *testing.T, opts ...NewTestingUCOpt) *TestingUseCases {
// default args
newArgs := &newTestingOpts{credsReaderWriter: creds.NewReaderWriter(t),
Expand Down
Loading