Vault SSH: Support OTP key type from CLI

This commit is contained in:
Vishal Nayak
2015-07-23 17:20:28 -04:00
parent 795d1a8d40
commit 3a1eaf1869
3 changed files with 28 additions and 47 deletions

View File

@@ -1,9 +1,6 @@
package api package api
import ( import "fmt"
"encoding/json"
"fmt"
)
// SSH is used to return a client to invoke operations on SSH backend. // SSH is used to return a client to invoke operations on SSH backend.
type SSH struct { type SSH struct {
@@ -40,32 +37,3 @@ func (c *SSH) KeyCreate(role string, data map[string]interface{}) (*Secret, erro
return ParseSecret(resp.Body) return ParseSecret(resp.Body)
} }
// Invokes the SSH backend API to list the roles associated with given IP address.
func (c *SSH) Lookup(data map[string]interface{}) (*SSHRoles, error) {
r := c.c.NewRequest("PUT", "/v1/ssh/lookup")
if err := r.SetJSONBody(data); err != nil {
return nil, err
}
resp, err := c.c.RawRequest(r)
if err != nil {
return nil, err
}
defer resp.Body.Close()
var roles SSHRoles
dec := json.NewDecoder(resp.Body)
if err := dec.Decode(&roles); err != nil {
return nil, err
}
return &roles, nil
}
// Structures for the requests/resposne are all down here. They aren't
// individually documentd because the map almost directly to the raw HTTP API
// documentation. Please refer to that documentation for more details.
type SSHRoles struct {
Data map[string]interface{} `json:"data"`
}

View File

@@ -95,7 +95,8 @@ func (b *backend) pathRoleCreateWrite(
return nil, err return nil, err
} }
result = b.Secret(SecretOTPType).Response(map[string]interface{}{ result = b.Secret(SecretOTPType).Response(map[string]interface{}{
"otp": otp, "key_type": role.KeyType,
"key": otp,
}, map[string]interface{}{ }, map[string]interface{}{
"otp": otp, "otp": otp,
}) })
@@ -134,9 +135,9 @@ func (b *backend) pathRoleCreateWrite(
return nil, fmt.Errorf("error creating OTP:'%s'", err) return nil, fmt.Errorf("error creating OTP:'%s'", err)
} }
result = b.Secret(SecretDynamicKeyType).Response(map[string]interface{}{ result = b.Secret(SecretDynamicKeyType).Response(map[string]interface{}{
"key": dynamicPrivateKey, "key": dynamicPrivateKey,
"key_type": role.KeyType,
}, map[string]interface{}{ }, map[string]interface{}{
"key_type": role.KeyType,
"username": username, "username": username,
"ip": ip, "ip": ip,
"host_key_name": role.KeyName, "host_key_name": role.KeyName,

View File

@@ -9,6 +9,7 @@ import (
"strings" "strings"
"github.com/hashicorp/vault/api" "github.com/hashicorp/vault/api"
"github.com/hashicorp/vault/builtin/logical/ssh"
) )
// SSHCommand is a Command that establishes a SSH connection with target by generating a dynamic key // SSHCommand is a Command that establishes a SSH connection with target by generating a dynamic key
@@ -19,6 +20,8 @@ type SSHCommand struct {
func (c *SSHCommand) Run(args []string) int { func (c *SSHCommand) Run(args []string) int {
var role string var role string
var port string var port string
var sshCmdArgs []string
var sshDynamicKeyFileName string
flags := c.Meta.FlagSet("ssh", FlagSetDefault) flags := c.Meta.FlagSet("ssh", FlagSetDefault)
flags.StringVar(&role, "role", "", "") flags.StringVar(&role, "role", "", "")
flags.StringVar(&port, "port", "22", "") flags.StringVar(&port, "port", "22", "")
@@ -64,15 +67,22 @@ func (c *SSHCommand) Run(args []string) int {
return 2 return 2
} }
sshDynamicKey := string(keySecret.Data["key"].(string)) if keySecret.Data["key_type"].(string) == ssh.KeyTypeDynamic {
if len(sshDynamicKey) == 0 { sshDynamicKey := string(keySecret.Data["key"].(string))
c.Ui.Error(fmt.Sprintf("Invalid key")) if len(sshDynamicKey) == 0 {
return 2 c.Ui.Error(fmt.Sprintf("Invalid key"))
} return 2
sshDynamicKeyFileName := fmt.Sprintf("vault_temp_file_%s_%s", username, ip.String()) }
err = ioutil.WriteFile(sshDynamicKeyFileName, []byte(sshDynamicKey), 0600) sshDynamicKeyFileName = fmt.Sprintf("vault_temp_file_%s_%s", username, ip.String())
err = ioutil.WriteFile(sshDynamicKeyFileName, []byte(sshDynamicKey), 0600)
sshCmdArgs = append(sshCmdArgs, []string{"-i", sshDynamicKeyFileName}...)
sshCmdArgs := []string{"-p", port, "-i", sshDynamicKeyFileName} } else if keySecret.Data["key_type"].(string) == ssh.KeyTypeOTP {
fmt.Printf("OTP for the session is %s\n", string(keySecret.Data["key"].(string)))
} else {
c.Ui.Error("Key not present")
}
sshCmdArgs = append(sshCmdArgs, []string{"-p", port}...)
sshCmdArgs = append(sshCmdArgs, args...) sshCmdArgs = append(sshCmdArgs, args...)
sshCmd := exec.Command("ssh", sshCmdArgs...) sshCmd := exec.Command("ssh", sshCmdArgs...)
@@ -84,9 +94,11 @@ func (c *SSHCommand) Run(args []string) int {
c.Ui.Error(fmt.Sprintf("Error while running ssh command:%s", err)) c.Ui.Error(fmt.Sprintf("Error while running ssh command:%s", err))
} }
err = os.Remove(sshDynamicKeyFileName) if keySecret.Data["key_type"].(string) == ssh.KeyTypeDynamic {
if err != nil { err = os.Remove(sshDynamicKeyFileName)
c.Ui.Error("Error cleaning up") // Intentionally not mentioning the exact error if err != nil {
c.Ui.Error("Error cleaning up") // Intentionally not mentioning the exact error
}
} }
err = client.SSH().KeyRevoke(keySecret.LeaseID) err = client.SSH().KeyRevoke(keySecret.LeaseID)