mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-10-31 18:48:08 +00:00 
			
		
		
		
	Vault SSH: Support OTP key type from CLI
This commit is contained in:
		
							
								
								
									
										34
									
								
								api/ssh.go
									
									
									
									
									
								
							
							
						
						
									
										34
									
								
								api/ssh.go
									
									
									
									
									
								
							| @@ -1,9 +1,6 @@ | ||||
| package api | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| ) | ||||
| import "fmt" | ||||
|  | ||||
| // SSH is used to return a client to invoke operations on SSH backend. | ||||
| type SSH struct { | ||||
| @@ -40,32 +37,3 @@ func (c *SSH) KeyCreate(role string, data map[string]interface{}) (*Secret, erro | ||||
|  | ||||
| 	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"` | ||||
| } | ||||
|   | ||||
| @@ -95,7 +95,8 @@ func (b *backend) pathRoleCreateWrite( | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		result = b.Secret(SecretOTPType).Response(map[string]interface{}{ | ||||
| 			"otp": otp, | ||||
| 			"key_type": role.KeyType, | ||||
| 			"key":      otp, | ||||
| 		}, map[string]interface{}{ | ||||
| 			"otp": otp, | ||||
| 		}) | ||||
| @@ -134,9 +135,9 @@ func (b *backend) pathRoleCreateWrite( | ||||
| 			return nil, fmt.Errorf("error creating OTP:'%s'", err) | ||||
| 		} | ||||
| 		result = b.Secret(SecretDynamicKeyType).Response(map[string]interface{}{ | ||||
| 			"key": dynamicPrivateKey, | ||||
| 			"key":      dynamicPrivateKey, | ||||
| 			"key_type": role.KeyType, | ||||
| 		}, map[string]interface{}{ | ||||
| 			"key_type":           role.KeyType, | ||||
| 			"username":           username, | ||||
| 			"ip":                 ip, | ||||
| 			"host_key_name":      role.KeyName, | ||||
|   | ||||
| @@ -9,6 +9,7 @@ import ( | ||||
| 	"strings" | ||||
|  | ||||
| 	"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 | ||||
| @@ -19,6 +20,8 @@ type SSHCommand struct { | ||||
| func (c *SSHCommand) Run(args []string) int { | ||||
| 	var role string | ||||
| 	var port string | ||||
| 	var sshCmdArgs []string | ||||
| 	var sshDynamicKeyFileName string | ||||
| 	flags := c.Meta.FlagSet("ssh", FlagSetDefault) | ||||
| 	flags.StringVar(&role, "role", "", "") | ||||
| 	flags.StringVar(&port, "port", "22", "") | ||||
| @@ -64,15 +67,22 @@ func (c *SSHCommand) Run(args []string) int { | ||||
| 		return 2 | ||||
| 	} | ||||
|  | ||||
| 	sshDynamicKey := string(keySecret.Data["key"].(string)) | ||||
| 	if len(sshDynamicKey) == 0 { | ||||
| 		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) | ||||
| 	if keySecret.Data["key_type"].(string) == ssh.KeyTypeDynamic { | ||||
| 		sshDynamicKey := string(keySecret.Data["key"].(string)) | ||||
| 		if len(sshDynamicKey) == 0 { | ||||
| 			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) | ||||
| 		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...) | ||||
|  | ||||
| 	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)) | ||||
| 	} | ||||
|  | ||||
| 	err = os.Remove(sshDynamicKeyFileName) | ||||
| 	if err != nil { | ||||
| 		c.Ui.Error("Error cleaning up") // Intentionally not mentioning the exact error | ||||
| 	if keySecret.Data["key_type"].(string) == ssh.KeyTypeDynamic { | ||||
| 		err = os.Remove(sshDynamicKeyFileName) | ||||
| 		if err != nil { | ||||
| 			c.Ui.Error("Error cleaning up") // Intentionally not mentioning the exact error | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	err = client.SSH().KeyRevoke(keySecret.LeaseID) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Vishal Nayak
					Vishal Nayak