Add SSH deploy keys generator
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
Adam Štrauch 2023-04-11 22:49:50 +02:00
parent f3f50b0ace
commit df5a390680
Signed by: cx
GPG key ID: 018304FFA8988F8D
3 changed files with 140 additions and 0 deletions

View file

@ -231,6 +231,71 @@ func (c *Container) SetPassword(password string) error {
return err
}
// Generate SSH keys and copies it into authorized keys
// Returns true if the key was generated in this call and error if there is any.
func (c *Container) GenerateDeploySSHKeys() (bool, error) {
driver := c.getDriver()
privateKey, pubKey, _ := c.GetDeploySSHKeys()
if privateKey != "" || pubKey != "" {
return false, nil
}
_, err := driver.Exec(c.App.Name, []string{"mkdir", "-p", "/srv/.ssh"}, "", []string{}, false)
if err != nil {
return false, err
}
_, err = driver.Exec(c.App.Name, []string{"ssh-keygen", "-f", "/srv/.ssh/id_rsa", "-P", ""}, "", []string{}, false)
if err != nil {
return false, err
}
_, err = driver.Exec(c.App.Name, []string{"chown", "app:app", "-R", "/srv/.ssh"}, "", []string{}, false)
if err != nil {
return false, err
}
return true, nil
}
// Generate SSH keys and copies it into authorized keys
// Return private key, public key and error.
func (c *Container) GetDeploySSHKeys() (string, string, error) {
driver := c.getDriver()
privateKey, err := driver.Exec(c.App.Name, []string{"cat ", "/srv/.ssh/id_rsa"}, "", []string{}, true)
if err != nil {
return "", "", err
}
pubKey, err := driver.Exec(c.App.Name, []string{"cat ", "/srv/.ssh/id_rsa.pub"}, "", []string{}, true)
if err != nil {
return "", "", err
}
if privateKey != nil || pubKey != nil {
return string(*privateKey), string(*pubKey), nil
}
return "", "", nil
}
func (c *Container) AppendOfFile(filename string, text string, mode string) error {
driver := c.getDriver()
_, err := driver.Exec(c.App.Name, []string{"tee", "-a", filename}, text, []string{}, false)
if err != nil {
return err
}
_, err = driver.Exec(c.App.Name, []string{"chmod", mode, filename}, "", []string{}, false)
if err != nil {
return err
}
return nil
}
// SetAppPort changes application port in the container
func (c *Container) SetAppPort(port int) error {
driver := c.getDriver()

View file

@ -484,6 +484,41 @@ func (p *Processor) SetPassword(password string) error {
return nil
}
// Generate SSH key and adds it into authorized_keys
// These pair of keys is used for deployment.
// Returns private key, pubkey and error.
// Keys are returned every time even if it was already generated
func (p *Processor) GenerateDeploySSHKeys() (string, string, error) {
err := p.waitForApp()
if err != nil {
return "", "", err
}
container, err := p.getContainer()
if err != nil {
return "", "", err
}
created, err := container.GenerateDeploySSHKeys()
if err != nil {
return "", "", err
}
privateKey, pubKey, err := container.GetDeploySSHKeys()
if err != nil {
return "", "", err
}
if created {
err = container.AppendOfFile(sshPubKeysLocation, pubKey+"\n", "0600")
if err != nil {
return "", "", err
}
}
return privateKey, pubKey, nil
}
// Processes returns list of supervisord processes
func (p *Processor) Processes() ([]docker.Process, error) {
container, err := p.getContainer()

View file

@ -50,6 +50,7 @@ func _messageHandler(m *nats.Msg) error {
"stop": stopEventHandler,
"start": startEventHandler,
"restart": restartEventHandler,
"get_deploy_ssh_keys": getDeploySSHKeysEventHandler,
"update_keys": updateKeysEventHandler,
"set_password": setPasswordEventHandler,
"processes": processesEventHandler,
@ -398,6 +399,45 @@ func restartEventHandler(m *nats.Msg, message *RequestMessage) error {
return nil
}
func getDeploySSHKeysEventHandler(m *nats.Msg, message *RequestMessage) error {
processor := glue.Processor{
AppName: message.AppName,
DB: common.GetDBConnection(),
SnapshotProcessor: &snapshotProcessor,
DockerSock: config.DockerSocket,
BindIPHTTP: config.AppsBindIPHTTP,
BindIPSSH: config.AppsBindIPSSH,
AppsPath: config.AppsPath,
}
privateKey, pubKey, err := processor.GenerateDeploySSHKeys()
if err != nil {
log.Printf("backend error: %v\n", err)
return errorReplyFormater(m, "backend error", err)
}
// Assembling reply message
reply := ReplyMessage{
Payload: struct{ PrivateKey, PublicKey string }{
PrivateKey: privateKey,
PublicKey: pubKey,
},
}
data, err := json.Marshal(reply)
if err != nil {
return errorReplyFormater(m, "reply formatter error", err)
}
err = m.Respond(data)
if err != nil {
log.Println("ERROR: get app:", err.Error())
return err
}
return nil
}
// Copies body of the request into /srv/.ssh/authorized_keys
func updateKeysEventHandler(m *nats.Msg, message *RequestMessage) error {
body := message.Payload