diff --git a/api/projects/keys.go b/api/projects/keys.go index f1887d330..c466a8f56 100644 --- a/api/projects/keys.go +++ b/api/projects/keys.go @@ -160,7 +160,7 @@ func (c *KeyController) UpdateKey(w http.ResponseWriter, r *http.Request) { } for _, repo := range repos { - if repo.SSHKeyID != key.ID { + if repo.SSHKeyID == nil || *repo.SSHKeyID != key.ID { continue } err = repo.ClearCache() diff --git a/api/projects/projects.go b/api/projects/projects.go index 840882ed8..35887a34d 100644 --- a/api/projects/projects.go +++ b/api/projects/projects.go @@ -102,7 +102,7 @@ func (c *ProjectsController) createDemoProject(projectID int, noneKeyID int, sto ProjectID: projectID, GitURL: "https://github.com/semaphoreui/semaphore-demo.git", GitBranch: "main", - SSHKeyID: noneKeyID, + SSHKeyID: nil, }) if err != nil { diff --git a/api/runners/runners.go b/api/runners/runners.go index 27d696059..128770c1b 100644 --- a/api/runners/runners.go +++ b/api/runners/runners.go @@ -207,8 +207,8 @@ func (c *RunnerController) GetRunner(w http.ResponseWriter, r *http.Request) { } } - if tsk.Inventory.RepositoryID != nil { - err := c.encryptionService.DeserializeSecret(&tsk.Inventory.Repository.SSHKey) + if tsk.Inventory.RepositoryID != nil && tsk.Inventory.Repository.SSHKeyID != nil { + err := c.encryptionService.DeserializeSecret(tsk.Inventory.Repository.SSHKey) if err != nil { log.WithFields(log.Fields{ "runner_id": runner.ID, @@ -220,10 +220,12 @@ func (c *RunnerController) GetRunner(w http.ResponseWriter, r *http.Request) { helpers.WriteError(w, err) return } - data.AccessKeys[tsk.Inventory.Repository.SSHKeyID] = tsk.Inventory.Repository.SSHKey + data.AccessKeys[*tsk.Inventory.Repository.SSHKeyID] = *tsk.Inventory.Repository.SSHKey } - data.AccessKeys[tsk.Repository.SSHKeyID] = tsk.Repository.SSHKey + if tsk.Repository.SSHKeyID != nil { + data.AccessKeys[*tsk.Repository.SSHKeyID] = *tsk.Repository.SSHKey + } } else { data.CurrentJobs = append(data.CurrentJobs, runners.JobState{ diff --git a/db/Migration.go b/db/Migration.go index 03a67e118..75d1902ee 100644 --- a/db/Migration.go +++ b/db/Migration.go @@ -126,6 +126,7 @@ func GetMigrations(dialect string) []Migration { {Version: "2.18.2"}, {Version: "2.18.4"}, {Version: "2.18.5"}, + {Version: "2.18.7"}, } return append(initScripts, commonScripts...) diff --git a/db/Repository.go b/db/Repository.go index 9d41885e4..19ad77b59 100644 --- a/db/Repository.go +++ b/db/Repository.go @@ -27,9 +27,9 @@ type Repository struct { ProjectID int `db:"project_id" json:"project_id" backup:"-"` GitURL string `db:"git_url" json:"git_url" binding:"required"` GitBranch string `db:"git_branch" json:"git_branch" binding:"required"` - SSHKeyID int `db:"ssh_key_id" json:"ssh_key_id" binding:"required" backup:"-"` + SSHKeyID *int `db:"ssh_key_id" json:"ssh_key_id" binding:"required" backup:"-"` - SSHKey AccessKey `db:"-" json:"-" backup:"-"` + SSHKey *AccessKey `db:"-" json:"-" backup:"-"` } func (r Repository) ClearCache() error { diff --git a/db/Repository_test.go b/db/Repository_test.go index 740c12bb4..da9d5c2ee 100644 --- a/db/Repository_test.go +++ b/db/Repository_test.go @@ -47,7 +47,7 @@ func TestRepository_GetGitURL(t *testing.T) { ExpectedGitUrl string }{ { - Repository: Repository{GitURL: "https://github.com/user/project.git", SSHKey: AccessKey{ + Repository: Repository{GitURL: "https://github.com/user/project.git", SSHKey: &AccessKey{ Type: AccessKeyLoginPassword, LoginPassword: LoginPassword{ Login: "login", @@ -58,7 +58,7 @@ func TestRepository_GetGitURL(t *testing.T) { ExpectedGitUrl: "https://login:password@github.com/user/project.git", }, { - Repository: Repository{GitURL: "https://github.com/user/project.git", SSHKey: AccessKey{ + Repository: Repository{GitURL: "https://github.com/user/project.git", SSHKey: &AccessKey{ Type: AccessKeyLoginPassword, LoginPassword: LoginPassword{ Password: "password", diff --git a/db/Store.go b/db/Store.go index 566f39997..95cd862e2 100644 --- a/db/Store.go +++ b/db/Store.go @@ -790,7 +790,11 @@ func StoreSession(store Store, token string, callback func()) { } func ValidateRepository(store Store, repo *Repository) (err error) { - _, err = store.GetAccessKey(repo.ProjectID, repo.SSHKeyID) + if repo.SSHKeyID == nil { + return + } + + _, err = store.GetAccessKey(repo.ProjectID, *repo.SSHKeyID) return } diff --git a/db/bolt/repository.go b/db/bolt/repository.go index 31e128eaa..a1fdfa611 100644 --- a/db/bolt/repository.go +++ b/db/bolt/repository.go @@ -9,7 +9,12 @@ func (d *BoltDb) GetRepository(projectID int, repositoryID int) (repository db.R if err != nil { return } - repository.SSHKey, err = d.GetAccessKey(projectID, repository.SSHKeyID) + + if repository.SSHKeyID != nil { + var k db.AccessKey + k, err = d.GetAccessKey(projectID, *repository.SSHKeyID) + repository.SSHKey = &k + } return } diff --git a/db/sql/migration.go b/db/sql/migration.go index a6921b0a5..ad60ad593 100644 --- a/db/sql/migration.go +++ b/db/sql/migration.go @@ -190,6 +190,13 @@ func (d *SqlDb) ApplyMigration(migration db.Migration) error { } } + if d.GetDialect() == util.DbDriverSQLite { + _, err = d.Sql().Exec("PRAGMA foreign_keys = OFF") + if err != nil { + panic(err) + } + } + tx, err := d.Sql().Begin() if err != nil { return err @@ -249,7 +256,16 @@ func (d *SqlDb) ApplyMigration(migration db.Migration) error { fmt.Println() - return tx.Commit() + res := tx.Commit() + + if d.GetDialect() == util.DbDriverSQLite { + _, err = d.Sql().Exec("PRAGMA foreign_keys = ON") + if err != nil { + panic(err) + } + } + + return res } // TryRollbackMigration attempts to rollback the database to an earlier version if a rollback exists diff --git a/db/sql/migrations/v.2.18.7.err.sql b/db/sql/migrations/v.2.18.7.err.sql new file mode 100644 index 000000000..346c3e31d --- /dev/null +++ b/db/sql/migrations/v.2.18.7.err.sql @@ -0,0 +1 @@ +-- do nothing \ No newline at end of file diff --git a/db/sql/migrations/v2.18.7.sql b/db/sql/migrations/v2.18.7.sql new file mode 100644 index 000000000..a4c313fe0 --- /dev/null +++ b/db/sql/migrations/v2.18.7.sql @@ -0,0 +1,31 @@ +{{if .Sqlite}} +create table project__repository_dg_tmp +( + id INTEGER + primary key autoincrement, + project_id INTEGER not null + references project + on delete cascade, + git_url TEXT not null, + ssh_key_id INTEGER + references access_key, + name VARCHAR(255), + git_branch VARCHAR(255) default '' not null +); + +insert into project__repository_dg_tmp(id, project_id, git_url, ssh_key_id, name, git_branch) +select id, project_id, git_url, ssh_key_id, name, git_branch +from project__repository; + +drop table project__repository; + +alter table project__repository_dg_tmp rename to project__repository; + +create index project__repository__project_id on project__repository (project_id); + +create index project__repository__ssh_key_id on project__repository (ssh_key_id); +{{else if .Mysql}} +alter table project__repository modify ssh_key_id int null; +{{else if .Postgresql}} +alter table public.project__repository alter column ssh_key_id drop not null; +{{end}} diff --git a/db/sql/repository.go b/db/sql/repository.go index 1c2ed5247..4a990b684 100644 --- a/db/sql/repository.go +++ b/db/sql/repository.go @@ -13,7 +13,11 @@ func (d *SqlDb) GetRepository(projectID int, repositoryID int) (db.Repository, e return repository, err } - repository.SSHKey, err = d.GetAccessKey(projectID, repository.SSHKeyID) + if repository.SSHKeyID != nil { + var key db.AccessKey + key, err = d.GetAccessKey(projectID, *repository.SSHKeyID) + repository.SSHKey = &key + } return repository, err } diff --git a/db_lib/CmdGitClient.go b/db_lib/CmdGitClient.go index cb6465fe0..c4e35e2b1 100644 --- a/db_lib/CmdGitClient.go +++ b/db_lib/CmdGitClient.go @@ -61,10 +61,14 @@ func (c CmdGitClient) makeCmd( func (c CmdGitClient) run(r GitRepository, targetDir GitRepositoryDirType, args ...string) error { var err error - keyInstallation, err := c.keyInstaller.Install(r.Repository.SSHKey, db.AccessKeyRoleGit, r.Logger) + var keyInstallation ssh.AccessKeyInstallation - if err != nil { - return err + if r.Repository.SSHKey != nil { + keyInstallation, err = c.keyInstaller.Install(*r.Repository.SSHKey, db.AccessKeyRoleGit, r.Logger) + + if err != nil { + return err + } } defer keyInstallation.Destroy() //nolint: errcheck @@ -77,9 +81,15 @@ func (c CmdGitClient) run(r GitRepository, targetDir GitRepositoryDirType, args } func (c CmdGitClient) output(r GitRepository, targetDir GitRepositoryDirType, args ...string) (out string, err error) { - keyInstallation, err := c.keyInstaller.Install(r.Repository.SSHKey, db.AccessKeyRoleGit, r.Logger) - if err != nil { - return + + var keyInstallation ssh.AccessKeyInstallation + + if r.Repository.SSHKey != nil { + keyInstallation, err = c.keyInstaller.Install(*r.Repository.SSHKey, db.AccessKeyRoleGit, r.Logger) + + if err != nil { + return + } } defer keyInstallation.Destroy() //nolint: errcheck diff --git a/db_lib/GoGitClient.go b/db_lib/GoGitClient.go index cb4c29400..a2f2bb785 100644 --- a/db_lib/GoGitClient.go +++ b/db_lib/GoGitClient.go @@ -39,15 +39,21 @@ func (t ProgressWrapper) Write(p []byte) (n int, err error) { } func (c GoGitClient) getAuthMethod(r GitRepository) (transport.AuthMethod, error) { + if r.Repository.SSHKey == nil { + return nil, nil + } + switch r.Repository.SSHKey.Type { case db.AccessKeySSH: - install, err := c.keyInstaller.Install(r.Repository.SSHKey, db.AccessKeyRoleGit, r.Logger) - if err != nil { - return nil, err - } + if r.Repository.SSHKey != nil { + install, err := c.keyInstaller.Install(*r.Repository.SSHKey, db.AccessKeyRoleGit, r.Logger) + if err != nil { + return nil, err + } - defer install.Destroy() + defer install.Destroy() + } var sshKeyBuff = r.Repository.SSHKey.SshKey.PrivateKey diff --git a/services/export/Repository.go b/services/export/Repository.go index 1393c90ce..c40d88991 100644 --- a/services/export/Repository.go +++ b/services/export/Repository.go @@ -45,9 +45,13 @@ func (e *RepositoryExporter) restoreValue(val EntityObject[db.Repository], store return err } - old.SSHKeyID, err = exporter.getNewKeyInt(AccessKey, val.scope, old.SSHKeyID) - if err != nil { - return err + if old.SSHKeyID != nil { + var k int + k, err = exporter.getNewKeyInt(AccessKey, val.scope, *old.SSHKeyID) + if err != nil { + return err + } + old.SSHKeyID = &k } newObj, err := store.CreateRepository(old) diff --git a/services/project/backup.go b/services/project/backup.go index 1bc1fd90d..e9e76528e 100644 --- a/services/project/backup.go +++ b/services/project/backup.go @@ -352,10 +352,13 @@ func (b *BackupDB) format() (*BackupFormat, error) { repositories := make([]BackupRepository, len(b.repositories)) for i, o := range b.repositories { - SSHKey, _ := findNameByID[db.AccessKey](o.SSHKeyID, b.keys) + var key *string + if o.SSHKeyID != nil { + key, _ = findNameByID[db.AccessKey](*o.SSHKeyID, b.keys) + } repositories[i] = BackupRepository{ Repository: o, - SSHKey: SSHKey, + SSHKey: key, } } diff --git a/services/project/backup_test.go b/services/project/backup_test.go index f954fedeb..ace2c1a19 100644 --- a/services/project/backup_test.go +++ b/services/project/backup_test.go @@ -35,7 +35,7 @@ func TestBackupProject(t *testing.T) { repo, err := store.CreateRepository(db.Repository{ ProjectID: proj.ID, - SSHKeyID: key.ID, + SSHKeyID: &key.ID, Name: "Test", GitURL: "git@example.com:test/test", GitBranch: "master", diff --git a/services/project/restore.go b/services/project/restore.go index 30f3750a1..52677e47c 100644 --- a/services/project/restore.go +++ b/services/project/restore.go @@ -218,11 +218,14 @@ func (e BackupRepository) Verify(backup *BackupFormat) error { } func (e BackupRepository) Restore(store db.Store, b *BackupDB) error { - var SSHKeyID int - if k := findEntityByName[db.AccessKey](e.SSHKey, b.keys); k == nil { - return fmt.Errorf("SSHKey does not exist in keys[].Name") - } else { - SSHKeyID = (*k).ID + var SSHKeyID *int + + if e.SSHKey != nil { + if k := findEntityByName[db.AccessKey](e.SSHKey, b.keys); k == nil { + return fmt.Errorf("SSHKey does not exist in keys[].Name") + } else { + SSHKeyID = &(*k).ID + } } repo := e.Repository diff --git a/services/runners/job_pool.go b/services/runners/job_pool.go index f626ad5df..6eff9bc25 100644 --- a/services/runners/job_pool.go +++ b/services/runners/job_pool.go @@ -679,7 +679,10 @@ func (p *JobPool) checkNewJobs() { }, } - taskRunner.job.Repository.SSHKey = response.AccessKeys[taskRunner.job.Repository.SSHKeyID] + if taskRunner.job.Repository.SSHKeyID != nil { + k := response.AccessKeys[*taskRunner.job.Repository.SSHKeyID] + taskRunner.job.Repository.SSHKey = &k + } if taskRunner.job.Inventory.SSHKeyID != nil { taskRunner.job.Inventory.SSHKey = response.AccessKeys[*taskRunner.job.Inventory.SSHKeyID] @@ -702,8 +705,9 @@ func (p *JobPool) checkNewJobs() { } taskRunner.job.Template.Vaults = vaults - if taskRunner.job.Inventory.RepositoryID != nil { - taskRunner.job.Inventory.Repository.SSHKey = response.AccessKeys[taskRunner.job.Inventory.Repository.SSHKeyID] + if taskRunner.job.Inventory.RepositoryID != nil && taskRunner.job.Inventory.Repository.SSHKeyID != nil { + k := response.AccessKeys[*taskRunner.job.Inventory.Repository.SSHKeyID] + taskRunner.job.Inventory.Repository.SSHKey = &k } p.queue = append(p.queue, &taskRunner) diff --git a/services/schedules/SchedulePool.go b/services/schedules/SchedulePool.go index 3e87ecfb5..9a10ec373 100644 --- a/services/schedules/SchedulePool.go +++ b/services/schedules/SchedulePool.go @@ -64,7 +64,9 @@ func (r ScheduleRunner) tryUpdateScheduleCommitHash(schedule db.Schedule) (updat return } - err = r.pool.encryptionService.DeserializeSecret(&repo.SSHKey) + if repo.SSHKey != nil { + err = r.pool.encryptionService.DeserializeSecret(repo.SSHKey) + } if err != nil { return } diff --git a/services/server/inventory_svc.go b/services/server/inventory_svc.go index 2b4249652..7abd14280 100644 --- a/services/server/inventory_svc.go +++ b/services/server/inventory_svc.go @@ -61,7 +61,10 @@ func (s *InventoryServiceImpl) fillInventory(inventory *db.Inventory) (err error return } - err = s.encryptionService.DeserializeSecret(&repo.SSHKey) + if repo.SSHKeyID != nil { + err = s.encryptionService.DeserializeSecret(repo.SSHKey) + } + if err != nil { return } diff --git a/services/tasks/TaskRunner.go b/services/tasks/TaskRunner.go index 790b2dc99..9a741ea04 100644 --- a/services/tasks/TaskRunner.go +++ b/services/tasks/TaskRunner.go @@ -297,7 +297,7 @@ func (t *TaskRunner) populateTaskEnvironment() (err error) { } tplEnvironment := make(map[string]any) - + if t.Environment.JSON != "" { err = json.Unmarshal([]byte(t.Environment.JSON), &tplEnvironment) } @@ -407,8 +407,10 @@ func (t *TaskRunner) populateDetails() error { return err } - if err = t.pool.encryptionService.DeserializeSecret(&t.Repository.SSHKey); err != nil { - return err + if t.Repository.SSHKey != nil { + if err = t.pool.encryptionService.DeserializeSecret(t.Repository.SSHKey); err != nil { + return err + } } // load and merge all configured environments diff --git a/services/tasks/TaskRunner_test.go b/services/tasks/TaskRunner_test.go index d2d78c655..1d92eaac8 100644 --- a/services/tasks/TaskRunner_test.go +++ b/services/tasks/TaskRunner_test.go @@ -237,7 +237,7 @@ func TestPopulateDetails(t *testing.T) { repo, err := store.CreateRepository(db.Repository{ ProjectID: proj.ID, - SSHKeyID: key.ID, + SSHKeyID: &key.ID, Name: "Test", GitURL: "git@example.com:test/test", GitBranch: "master", @@ -263,11 +263,11 @@ func TestPopulateDetails(t *testing.T) { } tpl, err := store.CreateTemplate(db.Template{ - Name: "Test", - Playbook: "test.yml", - ProjectID: proj.ID, - RepositoryID: repo.ID, - InventoryID: &inv.ID, + Name: "Test", + Playbook: "test.yml", + ProjectID: proj.ID, + RepositoryID: repo.ID, + InventoryID: &inv.ID, EnvironmentIDs: []int{env.ID}, }) @@ -335,7 +335,7 @@ func TestPopulateDetailsInventory(t *testing.T) { repo, err := store.CreateRepository(db.Repository{ ProjectID: proj.ID, - SSHKeyID: key.ID, + SSHKeyID: &key.ID, Name: "Test", GitURL: "git@example.com:test/test", GitBranch: "master", @@ -368,11 +368,11 @@ func TestPopulateDetailsInventory(t *testing.T) { } tpl, err := store.CreateTemplate(db.Template{ - Name: "Test", - Playbook: "test.yml", - ProjectID: proj.ID, - RepositoryID: repo.ID, - InventoryID: &inv.ID, + Name: "Test", + Playbook: "test.yml", + ProjectID: proj.ID, + RepositoryID: repo.ID, + InventoryID: &inv.ID, EnvironmentIDs: []int{env.ID}, TaskParams: map[string]any{ "allow_override_inventory": true, @@ -444,7 +444,7 @@ func TestPopulateDetailsInventory1(t *testing.T) { repo, err := store.CreateRepository(db.Repository{ ProjectID: proj.ID, - SSHKeyID: key.ID, + SSHKeyID: &key.ID, Name: "Test", GitURL: "git@example.com:test/test", GitBranch: "master", @@ -470,11 +470,11 @@ func TestPopulateDetailsInventory1(t *testing.T) { } tpl, err := store.CreateTemplate(db.Template{ - Name: "Test", - Playbook: "test.yml", - ProjectID: proj.ID, - RepositoryID: repo.ID, - InventoryID: &inv.ID, + Name: "Test", + Playbook: "test.yml", + ProjectID: proj.ID, + RepositoryID: repo.ID, + InventoryID: &inv.ID, EnvironmentIDs: []int{env.ID}, })