2015-06-17 16:39:49 +00:00
|
|
|
package command
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2015-06-18 00:33:03 +00:00
|
|
|
"io/ioutil"
|
2015-06-24 22:13:12 +00:00
|
|
|
"net"
|
2015-06-18 00:33:03 +00:00
|
|
|
"os"
|
|
|
|
"os/exec"
|
2015-06-17 16:39:49 +00:00
|
|
|
"strings"
|
2015-06-18 00:33:03 +00:00
|
|
|
"syscall"
|
2015-06-17 16:39:49 +00:00
|
|
|
)
|
|
|
|
|
2015-07-01 15:58:49 +00:00
|
|
|
type SSHCommand struct {
|
2015-06-17 16:39:49 +00:00
|
|
|
Meta
|
|
|
|
}
|
|
|
|
|
2015-07-01 15:58:49 +00:00
|
|
|
func (c *SSHCommand) Run(args []string) int {
|
2015-06-26 18:08:03 +00:00
|
|
|
var role string
|
2015-06-30 02:00:08 +00:00
|
|
|
flags := c.Meta.FlagSet("ssh", FlagSetDefault)
|
2015-06-26 18:08:03 +00:00
|
|
|
flags.StringVar(&role, "role", "", "")
|
2015-06-17 16:39:49 +00:00
|
|
|
flags.Usage = func() { c.Ui.Error(c.Help()) }
|
|
|
|
if err := flags.Parse(args); err != nil {
|
|
|
|
return 1
|
|
|
|
}
|
2015-06-26 18:08:03 +00:00
|
|
|
args = flags.Args()
|
|
|
|
if len(args) < 1 {
|
|
|
|
c.Ui.Error("ssh expects at least one argument")
|
|
|
|
return 2
|
|
|
|
}
|
2015-06-30 02:00:08 +00:00
|
|
|
|
2015-06-17 16:39:49 +00:00
|
|
|
client, err := c.Client()
|
|
|
|
if err != nil {
|
|
|
|
c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err))
|
|
|
|
return 2
|
|
|
|
}
|
2015-06-24 22:13:12 +00:00
|
|
|
input := strings.Split(args[0], "@")
|
|
|
|
username := input[0]
|
2015-06-30 02:00:08 +00:00
|
|
|
ip, err := net.ResolveIPAddr("ip4", input[1])
|
|
|
|
if err != nil {
|
|
|
|
c.Ui.Error(fmt.Sprintf("Error resolving IP Address: %s", err))
|
|
|
|
return 2
|
|
|
|
}
|
|
|
|
|
|
|
|
if role == "" {
|
|
|
|
data := map[string]interface{}{
|
|
|
|
"ip": ip.String(),
|
|
|
|
}
|
|
|
|
secret, err := client.Logical().Write("ssh/lookup", data)
|
|
|
|
if err != nil {
|
|
|
|
c.Ui.Error(fmt.Sprintf("Error finding roles for IP:%s Error:%s", ip.String(), err))
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
|
|
|
if secret.Data["roles"] == nil {
|
|
|
|
c.Ui.Error(fmt.Sprintf("IP '%s' not registered under any role", ip.String()))
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(secret.Data["roles"].([]interface{})) == 1 {
|
|
|
|
role = secret.Data["roles"].([]interface{})[0].(string)
|
|
|
|
c.Ui.Output(fmt.Sprintf("Using role[%s]\n", role))
|
|
|
|
} else {
|
|
|
|
c.Ui.Error(fmt.Sprintf("Multiple roles for IP '%s'. Select one of '%s' using '-role' option", ip, secret.Data["roles"]))
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-24 22:13:12 +00:00
|
|
|
data := map[string]interface{}{
|
|
|
|
"username": username,
|
2015-06-30 02:00:08 +00:00
|
|
|
"ip": ip.String(),
|
2015-06-24 22:13:12 +00:00
|
|
|
}
|
2015-07-01 15:58:49 +00:00
|
|
|
keySecret, err := client.SSH().KeyCreate(role, data)
|
2015-06-17 16:39:49 +00:00
|
|
|
if err != nil {
|
2015-06-30 02:00:08 +00:00
|
|
|
c.Ui.Error(fmt.Sprintf("Error getting key for SSH session:%s", err))
|
2015-06-17 16:39:49 +00:00
|
|
|
return 2
|
|
|
|
}
|
2015-06-30 02:00:08 +00:00
|
|
|
|
|
|
|
sshDynamicKey := string(keySecret.Data["key"].(string))
|
|
|
|
if len(sshDynamicKey) == 0 {
|
|
|
|
c.Ui.Error(fmt.Sprintf("Invalid key"))
|
|
|
|
return 2
|
|
|
|
}
|
2015-07-02 00:35:11 +00:00
|
|
|
sshDynamicKeyFileName := fmt.Sprintf("vault_ssh_key_%s_%s.pem", username, ip.String())
|
2015-06-30 02:00:08 +00:00
|
|
|
err = ioutil.WriteFile(sshDynamicKeyFileName, []byte(sshDynamicKey), 0600)
|
2015-06-18 00:33:03 +00:00
|
|
|
sshBinary, err := exec.LookPath("ssh")
|
|
|
|
if err != nil {
|
2015-06-30 02:00:08 +00:00
|
|
|
c.Ui.Error("ssh binary not found in PATH\n")
|
|
|
|
return 2
|
2015-06-18 00:33:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
sshEnv := os.Environ()
|
|
|
|
|
2015-06-30 02:00:08 +00:00
|
|
|
sshCmdArgs := []string{"ssh", "-i", sshDynamicKeyFileName, args[0]}
|
2015-06-18 00:33:03 +00:00
|
|
|
|
|
|
|
if err := syscall.Exec(sshBinary, sshCmdArgs, sshEnv); err != nil {
|
2015-07-02 00:35:11 +00:00
|
|
|
c.Ui.Error(fmt.Sprintf("Could not launch 'ssh' binary:'%s", err))
|
|
|
|
return 2
|
2015-06-18 00:33:03 +00:00
|
|
|
}
|
2015-06-17 16:39:49 +00:00
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
2015-06-24 22:13:12 +00:00
|
|
|
type OneTimeKey struct {
|
|
|
|
Key string
|
|
|
|
}
|
|
|
|
|
2015-07-01 15:58:49 +00:00
|
|
|
func (c *SSHCommand) Synopsis() string {
|
2015-06-17 16:39:49 +00:00
|
|
|
return "Initiate a SSH session"
|
|
|
|
}
|
|
|
|
|
2015-07-01 15:58:49 +00:00
|
|
|
func (c *SSHCommand) Help() string {
|
2015-06-17 16:39:49 +00:00
|
|
|
helpText := `
|
2015-07-01 15:58:49 +00:00
|
|
|
SSHCommand Help String
|
2015-06-17 16:39:49 +00:00
|
|
|
`
|
|
|
|
return strings.TrimSpace(helpText)
|
|
|
|
}
|