mirror of
https://github.com/semaphoreui/semaphore.git
synced 2025-01-20 15:29:28 +01:00
feat(secrets): use ssh agent for git
This commit is contained in:
parent
58850e9129
commit
43b342b3e8
@ -7,11 +7,14 @@ import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/ansible-semaphore/semaphore/lib"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math/big"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/ansible-semaphore/semaphore/util"
|
||||
)
|
||||
@ -64,15 +67,20 @@ const (
|
||||
|
||||
type AccessKeyInstallation struct {
|
||||
InstallationKey int64
|
||||
SshAgent *lib.SshAgent
|
||||
}
|
||||
|
||||
func (key AccessKeyInstallation) Destroy() error {
|
||||
path := key.GetPath()
|
||||
_, err := os.Stat(path)
|
||||
if key.SshAgent != nil {
|
||||
return key.SshAgent.Close()
|
||||
}
|
||||
|
||||
installPath := key.GetPath()
|
||||
_, err := os.Stat(installPath)
|
||||
if os.IsNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
return os.Remove(path)
|
||||
return os.Remove(installPath)
|
||||
}
|
||||
|
||||
// GetPath returns the location of the access key once written to disk
|
||||
@ -80,7 +88,23 @@ func (key AccessKeyInstallation) GetPath() string {
|
||||
return util.Config.TmpPath + "/access_key_" + strconv.FormatInt(key.InstallationKey, 10)
|
||||
}
|
||||
|
||||
func (key *AccessKey) Install(usage AccessKeyRole) (installation AccessKeyInstallation, err error) {
|
||||
func (key *AccessKey) startSshAgent(logger lib.Logger) (lib.SshAgent, error) {
|
||||
|
||||
sshAgent := lib.SshAgent{
|
||||
Logger: logger,
|
||||
Keys: []lib.SshAgentKey{
|
||||
{
|
||||
Key: []byte(key.SshKey.PrivateKey),
|
||||
Passphrase: []byte(key.SshKey.Passphrase),
|
||||
},
|
||||
},
|
||||
SocketFile: path.Join(util.Config.TmpPath, fmt.Sprintf("ssh-agent-%d-%d.sock", time.Now().Unix(), 0)),
|
||||
}
|
||||
|
||||
return sshAgent, sshAgent.Listen()
|
||||
}
|
||||
|
||||
func (key *AccessKey) Install(usage AccessKeyRole, logger lib.Logger) (installation AccessKeyInstallation, err error) {
|
||||
rnd, err := rand.Int(rand.Reader, big.NewInt(1000000000))
|
||||
if err != nil {
|
||||
return
|
||||
@ -92,7 +116,7 @@ func (key *AccessKey) Install(usage AccessKeyRole) (installation AccessKeyInstal
|
||||
return
|
||||
}
|
||||
|
||||
path := installation.GetPath()
|
||||
installationPath := installation.GetPath()
|
||||
|
||||
err = key.DeserializeSecret()
|
||||
|
||||
@ -104,12 +128,16 @@ func (key *AccessKey) Install(usage AccessKeyRole) (installation AccessKeyInstal
|
||||
case AccessKeyRoleGit:
|
||||
switch key.Type {
|
||||
case AccessKeySSH:
|
||||
err = ioutil.WriteFile(path, []byte(key.SshKey.PrivateKey+"\n"), 0600)
|
||||
var agent lib.SshAgent
|
||||
agent, err = key.startSshAgent(logger)
|
||||
installation.SshAgent = &agent
|
||||
|
||||
//err = ioutil.WriteFile(installationPath, []byte(key.SshKey.PrivateKey+"\n"), 0600)
|
||||
}
|
||||
case AccessKeyRoleAnsiblePasswordVault:
|
||||
switch key.Type {
|
||||
case AccessKeyLoginPassword:
|
||||
err = ioutil.WriteFile(path, []byte(key.LoginPassword.Password), 0600)
|
||||
err = ioutil.WriteFile(installationPath, []byte(key.LoginPassword.Password), 0600)
|
||||
}
|
||||
case AccessKeyRoleAnsibleBecomeUser:
|
||||
switch key.Type {
|
||||
@ -122,14 +150,17 @@ func (key *AccessKey) Install(usage AccessKeyRole) (installation AccessKeyInstal
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = ioutil.WriteFile(path, bytes, 0600)
|
||||
err = ioutil.WriteFile(installationPath, bytes, 0600)
|
||||
default:
|
||||
err = fmt.Errorf("access key type not supported for ansible user")
|
||||
}
|
||||
case AccessKeyRoleAnsibleUser:
|
||||
switch key.Type {
|
||||
case AccessKeySSH:
|
||||
err = ioutil.WriteFile(path, []byte(key.SshKey.PrivateKey+"\n"), 0600)
|
||||
var agent lib.SshAgent
|
||||
agent, err = key.startSshAgent(logger)
|
||||
installation.SshAgent = &agent
|
||||
//err = ioutil.WriteFile(installationPath, []byte(key.SshKey.PrivateKey+"\n"), 0600)
|
||||
case AccessKeyLoginPassword:
|
||||
content := make(map[string]string)
|
||||
content["ansible_user"] = key.LoginPassword.Login
|
||||
@ -139,7 +170,7 @@ func (key *AccessKey) Install(usage AccessKeyRole) (installation AccessKeyInstal
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = ioutil.WriteFile(path, bytes, 0600)
|
||||
err = ioutil.WriteFile(installationPath, bytes, 0600)
|
||||
|
||||
default:
|
||||
err = fmt.Errorf("access key type not supported for ansible user")
|
||||
|
@ -1,14 +1,5 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/ansible-semaphore/semaphore/lib"
|
||||
"path"
|
||||
"time"
|
||||
|
||||
"github.com/ansible-semaphore/semaphore/util"
|
||||
)
|
||||
|
||||
const (
|
||||
InventoryStatic = "static"
|
||||
InventoryStaticYaml = "static-yaml"
|
||||
@ -33,28 +24,28 @@ type Inventory struct {
|
||||
Type string `db:"type" json:"type"`
|
||||
}
|
||||
|
||||
func (i *Inventory) StartSshAgent(logger lib.Logger) (lib.SshAgent, error) {
|
||||
|
||||
sshAgent := lib.SshAgent{
|
||||
Logger: logger,
|
||||
Keys: []lib.SshAgentKey{
|
||||
{
|
||||
Key: []byte(i.SSHKey.SshKey.PrivateKey),
|
||||
Passphrase: []byte(i.SSHKey.SshKey.Passphrase),
|
||||
},
|
||||
},
|
||||
SocketFile: path.Join(util.Config.TmpPath, fmt.Sprintf("ssh-agent-%d-%d.sock", time.Now().Unix(), 0)),
|
||||
}
|
||||
|
||||
if i.BecomeKeyID != nil {
|
||||
sshAgent.Keys = append(sshAgent.Keys, lib.SshAgentKey{
|
||||
Key: []byte(i.BecomeKey.SshKey.PrivateKey),
|
||||
Passphrase: []byte(i.BecomeKey.SshKey.Passphrase),
|
||||
})
|
||||
}
|
||||
|
||||
return sshAgent, sshAgent.Listen()
|
||||
}
|
||||
//func (i *Inventory) StartSshAgent(logger lib.Logger) (lib.SshAgent, error) {
|
||||
//
|
||||
// sshAgent := lib.SshAgent{
|
||||
// Logger: logger,
|
||||
// Keys: []lib.SshAgentKey{
|
||||
// {
|
||||
// Key: []byte(i.SSHKey.SshKey.PrivateKey),
|
||||
// Passphrase: []byte(i.SSHKey.SshKey.Passphrase),
|
||||
// },
|
||||
// },
|
||||
// SocketFile: path.Join(util.Config.TmpPath, fmt.Sprintf("ssh-agent-%d-%d.sock", time.Now().Unix(), 0)),
|
||||
// }
|
||||
//
|
||||
// if i.BecomeKeyID != nil {
|
||||
// sshAgent.Keys = append(sshAgent.Keys, lib.SshAgentKey{
|
||||
// Key: []byte(i.BecomeKey.SshKey.PrivateKey),
|
||||
// Passphrase: []byte(i.BecomeKey.SshKey.Passphrase),
|
||||
// })
|
||||
// }
|
||||
//
|
||||
// return sshAgent, sshAgent.Listen()
|
||||
//}
|
||||
|
||||
func FillInventory(d Store, inventory *Inventory) (err error) {
|
||||
if inventory.SSHKeyID != nil {
|
||||
|
@ -20,7 +20,8 @@ func (c CmdGitClient) makeCmd(r GitRepository, targetDir GitRepositoryDirType, a
|
||||
cmd.Env = os.Environ()
|
||||
cmd.Env = append(cmd.Env, fmt.Sprintln("GIT_TERMINAL_PROMPT=0"))
|
||||
if r.Repository.SSHKey.Type == db.AccessKeySSH {
|
||||
sshCmd := "ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i " + c.keyInstallation.GetPath()
|
||||
cmd.Env = append(cmd.Env, fmt.Sprintf("SSH_AUTH_SOCK=%s", c.keyInstallation.SshAgent.SocketFile))
|
||||
sshCmd := "ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"
|
||||
if util.Config.SshConfigPath != "" {
|
||||
sshCmd += " -F " + util.Config.SshConfigPath
|
||||
}
|
||||
@ -43,7 +44,7 @@ func (c CmdGitClient) makeCmd(r GitRepository, targetDir GitRepositoryDirType, a
|
||||
|
||||
func (c CmdGitClient) run(r GitRepository, targetDir GitRepositoryDirType, args ...string) error {
|
||||
var err error
|
||||
c.keyInstallation, err = r.Repository.SSHKey.Install(db.AccessKeyRoleGit)
|
||||
c.keyInstallation, err = r.Repository.SSHKey.Install(db.AccessKeyRoleGit, r.Logger)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
@ -59,7 +60,7 @@ func (c CmdGitClient) run(r GitRepository, targetDir GitRepositoryDirType, args
|
||||
}
|
||||
|
||||
func (c CmdGitClient) output(r GitRepository, targetDir GitRepositoryDirType, args ...string) (out string, err error) {
|
||||
c.keyInstallation, err = r.Repository.SSHKey.Install(db.AccessKeyRoleGit)
|
||||
c.keyInstallation, err = r.Repository.SSHKey.Install(db.AccessKeyRoleGit, r.Logger)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -10,14 +10,14 @@ import (
|
||||
|
||||
func (t *LocalJob) installInventory() (err error) {
|
||||
if t.Inventory.SSHKeyID != nil {
|
||||
t.sshKeyInstallation, err = t.Inventory.SSHKey.Install(db.AccessKeyRoleAnsibleUser)
|
||||
t.sshKeyInstallation, err = t.Inventory.SSHKey.Install(db.AccessKeyRoleAnsibleUser, t.Logger)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if t.Inventory.BecomeKeyID != nil {
|
||||
t.becomeKeyInstallation, err = t.Inventory.BecomeKey.Install(db.AccessKeyRoleAnsibleBecomeUser)
|
||||
t.becomeKeyInstallation, err = t.Inventory.BecomeKey.Install(db.AccessKeyRoleAnsibleBecomeUser, t.Logger)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@ -41,3 +41,20 @@ func (t *LocalJob) installStaticInventory() error {
|
||||
// create inventory file
|
||||
return ioutil.WriteFile(path, []byte(t.Inventory.Inventory), 0664)
|
||||
}
|
||||
|
||||
func (t *LocalJob) destroyKeys() {
|
||||
err := t.sshKeyInstallation.Destroy()
|
||||
if err != nil {
|
||||
t.Log("Can't destroy inventory user key, error: " + err.Error())
|
||||
}
|
||||
|
||||
err = t.becomeKeyInstallation.Destroy()
|
||||
if err != nil {
|
||||
t.Log("Can't destroy inventory become user key, error: " + err.Error())
|
||||
}
|
||||
|
||||
err = t.vaultFileInstallation.Destroy()
|
||||
if err != nil {
|
||||
t.Log("Can't destroy inventory vault password file, error: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
@ -216,23 +216,6 @@ func (t *LocalJob) getPlaybookArgs(username string, incomingVersion *string) (ar
|
||||
return
|
||||
}
|
||||
|
||||
func (t *LocalJob) destroyKeys() {
|
||||
err := t.sshKeyInstallation.Destroy()
|
||||
if err != nil {
|
||||
t.Log("Can't destroy inventory user key, error: " + err.Error())
|
||||
}
|
||||
|
||||
err = t.becomeKeyInstallation.Destroy()
|
||||
if err != nil {
|
||||
t.Log("Can't destroy inventory become user key, error: " + err.Error())
|
||||
}
|
||||
|
||||
err = t.vaultFileInstallation.Destroy()
|
||||
if err != nil {
|
||||
t.Log("Can't destroy inventory vault password file, error: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func (t *LocalJob) Run(username string, incomingVersion *string) (err error) {
|
||||
|
||||
t.SetStatus(lib.TaskRunningStatus)
|
||||
@ -258,16 +241,16 @@ func (t *LocalJob) Run(username string, incomingVersion *string) (err error) {
|
||||
|
||||
if t.Inventory.SSHKey.Type == db.AccessKeySSH && t.Inventory.SSHKeyID != nil {
|
||||
|
||||
var sshAgent lib.SshAgent
|
||||
sshAgent, err = t.Inventory.StartSshAgent(t.Logger)
|
||||
//var sshAgent lib.SshAgent
|
||||
//sshAgent, err = t.Inventory.StartSshAgent(t.Logger)
|
||||
//
|
||||
//if err != nil {
|
||||
// return
|
||||
//}
|
||||
//
|
||||
//defer sshAgent.Close()
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer sshAgent.Close()
|
||||
|
||||
environmentVariables = append(environmentVariables, fmt.Sprintf("SSH_AUTH_SOCK=%s", sshAgent.SocketFile))
|
||||
environmentVariables = append(environmentVariables, fmt.Sprintf("SSH_AUTH_SOCK=%s", t.sshKeyInstallation.SshAgent.SocketFile))
|
||||
}
|
||||
|
||||
return t.Playbook.RunPlaybook(args, &environmentVariables, func(p *os.Process) {
|
||||
@ -484,7 +467,7 @@ func (t *LocalJob) installVaultKeyFile() (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
t.vaultFileInstallation, err = t.Template.VaultKey.Install(db.AccessKeyRoleAnsiblePasswordVault)
|
||||
t.vaultFileInstallation, err = t.Template.VaultKey.Install(db.AccessKeyRoleAnsiblePasswordVault, t.Logger)
|
||||
|
||||
return
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user