From 0128f59344c90574ac766854cb47d0da4b6bd0a8 Mon Sep 17 00:00:00 2001 From: Gabriel Adrian Samfira Date: Thu, 25 Apr 2024 09:17:54 +0000 Subject: [PATCH] Add some credentials e2e tests Signed-off-by: Gabriel Adrian Samfira --- database/sql/github.go | 8 +- test/integration/e2e/client_utils.go | 20 +++ test/integration/e2e/credentials.go | 182 +++++++++++++++++++++++++++ test/integration/e2e/e2e.go | 9 ++ test/integration/e2e/endpoints.go | 61 +++++++++ test/integration/e2e/utils.go | 18 +++ test/integration/main.go | 9 ++ 7 files changed, 303 insertions(+), 4 deletions(-) diff --git a/database/sql/github.go b/database/sql/github.go index 2f38a7de..33dfe7da 100644 --- a/database/sql/github.go +++ b/database/sql/github.go @@ -279,8 +279,8 @@ func (s *sqlDatabase) CreateGithubCredentials(ctx context.Context, param params. return errors.Wrap(err, "fetching github endpoint") } - if err := tx.Where("name = ?", param.Name).First(&creds).Error; err == nil { - return errors.New("github credentials already exists") + if err := tx.Where("name = ? and user_id = ?", param.Name, userID).First(&creds).Error; err == nil { + return errors.Wrap(runnerErrors.ErrDuplicateEntity, "github credentials already exists") } var data []byte @@ -449,7 +449,7 @@ func (s *sqlDatabase) UpdateGithubCredentials(ctx context.Context, id uint, para } if param.App != nil { - return errors.New("cannot update app credentials for PAT") + return errors.Wrap(runnerErrors.ErrBadRequest, "cannot update app credentials for PAT") } case params.GithubAuthTypeApp: if param.App != nil { @@ -457,7 +457,7 @@ func (s *sqlDatabase) UpdateGithubCredentials(ctx context.Context, id uint, para } if param.PAT != nil { - return errors.New("cannot update PAT credentials for app") + return errors.Wrap(runnerErrors.ErrBadRequest, "cannot update PAT credentials for app") } } diff --git a/test/integration/e2e/client_utils.go b/test/integration/e2e/client_utils.go index 564a48c7..43a28ee7 100644 --- a/test/integration/e2e/client_utils.go +++ b/test/integration/e2e/client_utils.go @@ -77,6 +77,16 @@ func getGithubCredential(apiCli *client.GarmAPI, apiAuthToken runtime.ClientAuth return &getCredentialsResponse.Payload, nil } +func updateGithubCredentials(apiCli *client.GarmAPI, apiAuthToken runtime.ClientAuthInfoWriter, credentialsID int64, credentialsParams params.UpdateGithubCredentialsParams) (*params.GithubCredentials, error) { + updateCredentialsResponse, err := apiCli.Credentials.UpdateCredentials( + clientCredentials.NewUpdateCredentialsParams().WithID(credentialsID).WithBody(credentialsParams), + apiAuthToken) + if err != nil { + return nil, err + } + return &updateCredentialsResponse.Payload, nil +} + func createGithubEndpoint(apiCli *client.GarmAPI, apiAuthToken runtime.ClientAuthInfoWriter, endpointParams params.CreateGithubEndpointParams) (*params.GithubEndpoint, error) { createEndpointResponse, err := apiCli.Endpoints.CreateGithubEndpoint( clientEndpoints.NewCreateGithubEndpointParams().WithBody(endpointParams), @@ -113,6 +123,16 @@ func deleteGithubEndpoint(apiCli *client.GarmAPI, apiAuthToken runtime.ClientAut apiAuthToken) } +func updateGithubEndpoint(apiCli *client.GarmAPI, apiAuthToken runtime.ClientAuthInfoWriter, endpointName string, endpointParams params.UpdateGithubEndpointParams) (*params.GithubEndpoint, error) { + updateEndpointResponse, err := apiCli.Endpoints.UpdateGithubEndpoint( + clientEndpoints.NewUpdateGithubEndpointParams().WithName(endpointName).WithBody(endpointParams), + apiAuthToken) + if err != nil { + return nil, err + } + return &updateEndpointResponse.Payload, nil +} + // listProviders lists all the providers configured in GARM. func listProviders(apiCli *client.GarmAPI, apiAuthToken runtime.ClientAuthInfoWriter) (params.Providers, error) { listProvidersResponse, err := apiCli.Providers.ListProviders( diff --git a/test/integration/e2e/credentials.go b/test/integration/e2e/credentials.go index 54c60440..22c0e4fd 100644 --- a/test/integration/e2e/credentials.go +++ b/test/integration/e2e/credentials.go @@ -34,3 +34,185 @@ func createDummyCredentials(name, endpointName string) *params.GithubCredentials } return CreateGithubCredentials(createCredsParams) } + +func TestGithubCredentialsErrorOnDuplicateCredentialsName() { + name := "dummy" + endpointName := "github.com" + creds := createDummyCredentials(name, endpointName) + defer DeleteGithubCredential(int64(creds.ID)) + + createCredsParams := params.CreateGithubCredentialsParams{ + Name: name, + Endpoint: endpointName, + Description: "GARM test credentials", + AuthType: params.GithubAuthTypePAT, + PAT: params.GithubPAT{ + OAuth2Token: "dummy", + }, + } + if _, err := createGithubCredentials(cli, authToken, createCredsParams); err == nil { + panic("expected error when creating credentials with duplicate name") + } +} + +func TestGithubCredentialsFailsToDeleteWhenInUse() { + name := "dummy" + endpointName := "github.com" + creds := createDummyCredentials(name, endpointName) + + repo := CreateRepo("dummy-owner", "dummy-repo", creds.Name, "superSecret@123BlaBla") + defer func() { + deleteRepo(cli, authToken, repo.ID) + deleteGithubCredentials(cli, authToken, int64(creds.ID)) + }() + + if err := deleteGithubCredentials(cli, authToken, int64(creds.ID)); err == nil { + panic("expected error when deleting credentials in use") + } +} + +func TestGithubCredentialsFailsOnInvalidAuthType() { + name := "dummy" + endpointName := "github.com" + + createCredsParams := params.CreateGithubCredentialsParams{ + Name: name, + Endpoint: endpointName, + Description: "GARM test credentials", + AuthType: params.GithubAuthType("invalid"), + PAT: params.GithubPAT{ + OAuth2Token: "dummy", + }, + } + _, err := createGithubCredentials(cli, authToken, createCredsParams) + if err == nil { + panic("expected error when creating credentials with invalid auth type") + } + expectAPIStatusCode(err, 400) +} + +func TestGithubCredentialsFailsWhenAuthTypeParamsAreIncorrect() { + name := "dummy" + endpointName := "github.com" + + createCredsParams := params.CreateGithubCredentialsParams{ + Name: name, + Endpoint: endpointName, + Description: "GARM test credentials", + AuthType: params.GithubAuthTypePAT, + App: params.GithubApp{ + AppID: 123, + InstallationID: 456, + PrivateKeyBytes: getTestFileContents("certs/srv-key.pem"), + }, + } + _, err := createGithubCredentials(cli, authToken, createCredsParams) + if err == nil { + panic("expected error when creating credentials with invalid auth type params") + } + expectAPIStatusCode(err, 400) +} + +func TestGithubCredentialsFailsWhenAuthTypeParamsAreMissing() { + name := "dummy" + endpointName := "github.com" + + createCredsParams := params.CreateGithubCredentialsParams{ + Name: name, + Endpoint: endpointName, + Description: "GARM test credentials", + AuthType: params.GithubAuthTypeApp, + } + _, err := createGithubCredentials(cli, authToken, createCredsParams) + if err == nil { + panic("expected error when creating credentials with missing auth type params") + } + expectAPIStatusCode(err, 400) +} + +func TestGithubCredentialsUpdateFailsWhenBothPATAndAppAreSupplied() { + name := "dummy" + endpointName := "github.com" + creds := createDummyCredentials(name, endpointName) + defer DeleteGithubCredential(int64(creds.ID)) + + updateCredsParams := params.UpdateGithubCredentialsParams{ + PAT: ¶ms.GithubPAT{ + OAuth2Token: "dummy", + }, + App: ¶ms.GithubApp{ + AppID: 123, + InstallationID: 456, + PrivateKeyBytes: getTestFileContents("certs/srv-key.pem"), + }, + } + _, err := updateGithubCredentials(cli, authToken, int64(creds.ID), updateCredsParams) + if err == nil { + panic("expected error when updating credentials with both PAT and App") + } + expectAPIStatusCode(err, 400) +} + +func TestGithubCredentialsFailWhenAppKeyIsInvalid() { + name := "dummy" + endpointName := "github.com" + + createCredsParams := params.CreateGithubCredentialsParams{ + Name: name, + Endpoint: endpointName, + Description: "GARM test credentials", + AuthType: params.GithubAuthTypeApp, + App: params.GithubApp{ + AppID: 123, + InstallationID: 456, + PrivateKeyBytes: []byte("invalid"), + }, + } + _, err := createGithubCredentials(cli, authToken, createCredsParams) + if err == nil { + panic("expected error when creating credentials with invalid app key") + } + expectAPIStatusCode(err, 400) +} + +func TestGithubCredentialsFailWhenEndpointDoesntExist() { + name := "dummy" + endpointName := "nonexistent" + + createCredsParams := params.CreateGithubCredentialsParams{ + Name: name, + Endpoint: endpointName, + Description: "GARM test credentials", + AuthType: params.GithubAuthTypePAT, + PAT: params.GithubPAT{ + OAuth2Token: "dummy", + }, + } + _, err := createGithubCredentials(cli, authToken, createCredsParams) + if err == nil { + panic("expected error when creating credentials with invalid endpoint") + } + expectAPIStatusCode(err, 404) +} + +func TestGithubCredentialsFailsOnDuplicateName() { + name := "dummy" + endpointName := "github.com" + creds := createDummyCredentials(name, endpointName) + defer DeleteGithubCredential(int64(creds.ID)) + + createCredsParams := params.CreateGithubCredentialsParams{ + Name: name, + Endpoint: endpointName, + Description: "GARM test credentials", + AuthType: params.GithubAuthTypePAT, + PAT: params.GithubPAT{ + OAuth2Token: "dummy", + }, + } + _, err := createGithubCredentials(cli, authToken, createCredsParams) + if err == nil { + panic("expected error when creating credentials with duplicate name") + } + expectAPIStatusCode(err, 409) +} diff --git a/test/integration/e2e/e2e.go b/test/integration/e2e/e2e.go index 3bb2f7fe..84742a67 100644 --- a/test/integration/e2e/e2e.go +++ b/test/integration/e2e/e2e.go @@ -77,6 +77,15 @@ func DeleteGithubEndpoint(name string) { } } +func UpdateGithubEndpoint(name string, updateParams params.UpdateGithubEndpointParams) *params.GithubEndpoint { + slog.Info("Update GitHub endpoint") + updated, err := updateGithubEndpoint(cli, authToken, name, updateParams) + if err != nil { + panic(err) + } + return updated +} + func ListProviders() params.Providers { slog.Info("List providers") providers, err := listProviders(cli, authToken) diff --git a/test/integration/e2e/endpoints.go b/test/integration/e2e/endpoints.go index 433da53f..21c0dc1b 100644 --- a/test/integration/e2e/endpoints.go +++ b/test/integration/e2e/endpoints.go @@ -177,3 +177,64 @@ func TestGithubEndpointFailsOnDuplicateName() { panic("expected error when creating endpoint with duplicate name") } } + +func TestGithubEndpointUpdateEndpoint() { + slog.Info("Testing endpoint update") + endpoint := createDummyEndpoint("dummy") + defer DeleteGithubEndpoint(endpoint.Name) + + newDescription := "Updated description" + newBaseURL := "https://ghes2.example.com" + newAPIBaseURL := "https://api.ghes2.example.com/" + newUploadBaseURL := "https://uploads.ghes2.example.com/" + newCABundle := getTestFileContents("certs/srv-pub.pem") + + updateParams := params.UpdateGithubEndpointParams{ + Description: &newDescription, + BaseURL: &newBaseURL, + APIBaseURL: &newAPIBaseURL, + UploadBaseURL: &newUploadBaseURL, + CACertBundle: newCABundle, + } + + updated, err := updateGithubEndpoint(cli, authToken, endpoint.Name, updateParams) + if err != nil { + panic(err) + } + + if updated.Name != endpoint.Name { + panic("Endpoint name mismatch") + } + + if updated.Description != newDescription { + panic("Endpoint description mismatch") + } + + if updated.BaseURL != newBaseURL { + panic("Endpoint base URL mismatch") + } + + if updated.APIBaseURL != newAPIBaseURL { + panic("Endpoint API base URL mismatch") + } + + if updated.UploadBaseURL != newUploadBaseURL { + panic("Endpoint upload base URL mismatch") + } + + if string(updated.CACertBundle) != string(newCABundle) { + panic("Endpoint CA cert bundle mismatch") + } +} + +func createDummyEndpoint(name string) *params.GithubEndpoint { + endpointParams := params.CreateGithubEndpointParams{ + Name: name, + Description: "Dummy endpoint", + BaseURL: "https://ghes.example.com", + APIBaseURL: "https://api.ghes.example.com/", + UploadBaseURL: "https://uploads.ghes.example.com/", + } + + return CreateGithubEndpoint(endpointParams) +} diff --git a/test/integration/e2e/utils.go b/test/integration/e2e/utils.go index 37e48fe4..84c9f9e7 100644 --- a/test/integration/e2e/utils.go +++ b/test/integration/e2e/utils.go @@ -2,6 +2,7 @@ package e2e import ( "encoding/json" + "log" "log/slog" ) @@ -13,3 +14,20 @@ func printJSONResponse(resp interface{}) error { slog.Info(string(b)) return nil } + +type apiCodeGetter interface { + IsCode(code int) bool +} + +func expectAPIStatusCode(err error, expectedCode int) { + if err == nil { + panic("expected error") + } + apiErr, ok := err.(apiCodeGetter) + if !ok { + log.Fatalf("expected API error, got %v (%T)", err, err) + } + if !apiErr.IsCode(expectedCode) { + log.Fatalf("expected status code %d", expectedCode) + } +} diff --git a/test/integration/main.go b/test/integration/main.go index 711478b8..c1ab0de3 100644 --- a/test/integration/main.go +++ b/test/integration/main.go @@ -85,6 +85,15 @@ func main() { // Create test credentials e2e.EnsureTestCredentials(credentialsName, ghToken, "github.com") + e2e.TestGithubCredentialsErrorOnDuplicateCredentialsName() + e2e.TestGithubCredentialsFailsToDeleteWhenInUse() + e2e.TestGithubCredentialsFailsOnInvalidAuthType() + e2e.TestGithubCredentialsFailsWhenAuthTypeParamsAreIncorrect() + e2e.TestGithubCredentialsFailsWhenAuthTypeParamsAreMissing() + e2e.TestGithubCredentialsUpdateFailsWhenBothPATAndAppAreSupplied() + e2e.TestGithubCredentialsFailWhenAppKeyIsInvalid() + e2e.TestGithubCredentialsFailWhenEndpointDoesntExist() + e2e.TestGithubCredentialsFailsOnDuplicateName() // ////////////////// // controller info //