diff --git a/api/projects/keys.go b/api/projects/keys.go index ebd16e401..151deb1c3 100644 --- a/api/projects/keys.go +++ b/api/projects/keys.go @@ -120,6 +120,7 @@ func (c *KeyController) AddKey(w http.ResponseWriter, r *http.Request) { helpers.WriteError(w, err) return } + key.Plain = newKey.Plain helpers.WriteJSON(w, http.StatusCreated, key) } diff --git a/db/AccessKey.go b/db/AccessKey.go index 88a572b1a..5c6ee1f0b 100644 --- a/db/AccessKey.go +++ b/db/AccessKey.go @@ -37,6 +37,7 @@ type AccessKey struct { String string `db:"-" json:"string"` LoginPassword LoginPassword `db:"-" json:"login_password"` SshKey SshKey `db:"-" json:"ssh"` + GenerateSSHKey bool `db:"-" json:"generate_ssh_key,omitempty"` OverrideSecret bool `db:"-" json:"override_secret,omitempty"` StorageID *int `db:"storage_id" json:"-" backup:"-"` diff --git a/db/bolt/access_key.go b/db/bolt/access_key.go index b77406050..a04efc93b 100644 --- a/db/bolt/access_key.go +++ b/db/bolt/access_key.go @@ -44,6 +44,7 @@ func (d *BoltDb) UpdateAccessKey(key db.AccessKey) error { return err2 } oldKey.Name = key.Name + //oldKey.Plain = key.Plain key = oldKey } diff --git a/db/sql/access_key.go b/db/sql/access_key.go index e965dbc5b..daca984de 100644 --- a/db/sql/access_key.go +++ b/db/sql/access_key.go @@ -67,9 +67,10 @@ func (d *SqlDb) UpdateAccessKey(key db.AccessKey) error { args = append(args, key.Name) if key.OverrideSecret { - query += ", type=?, secret=?" + query += ", type=?, secret=?, plain=?" args = append(args, key.Type) args = append(args, key.Secret) + args = append(args, key.Plain) } query += " where id=?" @@ -96,16 +97,18 @@ func (d *SqlDb) CreateAccessKey(key db.AccessKey) (newKey db.AccessKey, err erro "type, "+ "project_id, "+ "secret, "+ + "plain, "+ "environment_id, "+ "owner, "+ "storage_id, "+ "source_storage_id, "+ "source_storage_key) "+ - "values (?, ?, ?, ?, ?, ?, ?, ?, ?)", + "values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", key.Name, key.Type, key.ProjectID, key.Secret, + key.Plain, key.EnvironmentID, key.Owner, key.StorageID, diff --git a/services/server/access_key_svc.go b/services/server/access_key_svc.go index 2c1aaf895..f730c7a59 100644 --- a/services/server/access_key_svc.go +++ b/services/server/access_key_svc.go @@ -1,9 +1,13 @@ package server import ( + "bufio" + "bytes" + "encoding/json" "errors" "github.com/semaphoreui/semaphore/db" + "github.com/semaphoreui/semaphore/util" ) type AccessKeyService interface { @@ -61,7 +65,48 @@ func (s *AccessKeyServiceImpl) GetAll(projectID int, options db.GetAccessKeyOpti return s.accessKeyRepo.GetAccessKeys(projectID, options, params) } +func maybeGenerateSSHPrivateKey(key *db.AccessKey) error { + if !key.GenerateSSHKey || key.Type != db.AccessKeySSH { + key.Plain = nil + return nil + } + + var b bytes.Buffer + privateKeyFile := bufio.NewWriter(&b) + + publicKey, err := util.GeneratePrivateKey(privateKeyFile) + if err != nil { + return err + } + + err = privateKeyFile.Flush() + if err != nil { + return err + } + + key.SshKey.PrivateKey = b.String() + + type sshPublicKey struct { + PublicKey string `json:"public_key"` + } + + plainBytes, err := json.Marshal(sshPublicKey{ + PublicKey: publicKey, + }) + if err != nil { + return err + } + + plain := string(plainBytes) + key.Plain = &plain + return nil +} + func (s *AccessKeyServiceImpl) Create(key db.AccessKey) (newKey db.AccessKey, err error) { + err = maybeGenerateSSHPrivateKey(&key) + if err != nil { + return + } err = s.encryptionService.SerializeSecret(&key) if err != nil && !errors.Is(err, ErrReadOnlyStorage) { @@ -73,7 +118,13 @@ func (s *AccessKeyServiceImpl) Create(key db.AccessKey) (newKey db.AccessKey, er } func (s *AccessKeyServiceImpl) Update(key db.AccessKey) (err error) { + if key.OverrideSecret { + err = maybeGenerateSSHPrivateKey(&key) + if err != nil { + return + } + err = s.encryptionService.SerializeSecret(&key) if errors.Is(err, ErrReadOnlyStorage) { key.OverrideSecret = false diff --git a/web/src/components/KeyForm.vue b/web/src/components/KeyForm.vue index 500b34e27..09c05a4e3 100644 --- a/web/src/components/KeyForm.vue +++ b/web/src/components/KeyForm.vue @@ -109,15 +109,47 @@ dense /> + + +
+ +
+
{{ publicKey }}
+ + +
+
+