Vault SSH: Added SSHAgent API
This commit is contained in:
parent
e782717ba8
commit
f84347c542
77
api/ssh_agent.go
Normal file
77
api/ssh_agent.go
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/mitchellh/mapstructure"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Default path at which SSH backend will be mounted
|
||||||
|
const SSHAgentDefaultMountPoint = "ssh"
|
||||||
|
|
||||||
|
// This is a structure representing an SSH agent which can talk to vault server
|
||||||
|
// in order to verify the OTP entered by the user. It contains the path at which
|
||||||
|
// SSH backend is mounted at the server.
|
||||||
|
type SSHAgent struct {
|
||||||
|
c *Client
|
||||||
|
MountPoint string
|
||||||
|
}
|
||||||
|
|
||||||
|
// SSHVerifyResp is a structure representing the fields in Vault server's
|
||||||
|
// response.
|
||||||
|
type SSHVerifyResponse struct {
|
||||||
|
Message string `mapstructure:"message"`
|
||||||
|
Username string `mapstructure:"username"`
|
||||||
|
IP string `mapstructure:"ip"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates an SSHAgent object which can talk to Vault server with SSH backend
|
||||||
|
// mounted at default path ("ssh").
|
||||||
|
func (c *Client) SSHAgent() *SSHAgent {
|
||||||
|
return c.SSHAgentWithMountPoint(SSHAgentDefaultMountPoint)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates an SSHAgent object which can talk to Vault server with SSH backend
|
||||||
|
// mounted at a specific mount point.
|
||||||
|
func (c *Client) SSHAgentWithMountPoint(mountPoint string) *SSHAgent {
|
||||||
|
return &SSHAgent{
|
||||||
|
c: c,
|
||||||
|
MountPoint: mountPoint,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verifies if the key provided by user is present in Vault server. If yes,
|
||||||
|
// the response will contain the IP address and username associated with the
|
||||||
|
// key.
|
||||||
|
func (c *SSHAgent) Verify(otp string) (*SSHVerifyResponse, error) {
|
||||||
|
data := map[string]interface{}{
|
||||||
|
"otp": otp,
|
||||||
|
}
|
||||||
|
verifyPath := fmt.Sprintf("/v1/%s/verify", c.MountPoint)
|
||||||
|
r := c.c.NewRequest("PUT", verifyPath)
|
||||||
|
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()
|
||||||
|
|
||||||
|
secret, err := ParseSecret(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if secret.Data == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var verifyResp SSHVerifyResponse
|
||||||
|
err = mapstructure.Decode(secret.Data, &verifyResp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &verifyResp, nil
|
||||||
|
}
|
|
@ -30,6 +30,9 @@ func pathVerify(b *backend) *framework.Path {
|
||||||
func (b *backend) pathVerifyWrite(req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
func (b *backend) pathVerifyWrite(req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||||
otp := d.Get("otp").(string)
|
otp := d.Get("otp").(string)
|
||||||
|
|
||||||
|
// If OTP is not a UUID and a string matching VerifyEchoRequest, then the
|
||||||
|
// response will be VerifyEchoResponse. This is used by agent to check if
|
||||||
|
// connection to Vault server is proper.
|
||||||
if otp == VerifyEchoRequest {
|
if otp == VerifyEchoRequest {
|
||||||
return &logical.Response{
|
return &logical.Response{
|
||||||
Data: map[string]interface{}{
|
Data: map[string]interface{}{
|
||||||
|
|
Loading…
Reference in a new issue