From 4b07eba48796d225ce9c685f96538e4d64470b4d Mon Sep 17 00:00:00 2001 From: Vishal Nayak Date: Wed, 24 Jun 2015 18:13:12 -0400 Subject: [PATCH] POC: Rework. Doing away with policy file. --- api/logical.go | 3 + api/sys_ssh.go | 40 ++++---- builtin/logical/aws/path_user.go | 3 + builtin/logical/ssh/backend.go | 7 +- .../logical/ssh/path_config_add_host_key.go | 69 -------------- .../ssh/path_config_remove_host_key.go | 51 ---------- builtin/logical/ssh/path_keys.go | 95 +++++++++++++++++++ .../{ssh_connect.go => path_role_create.go} | 59 +++++++----- builtin/logical/ssh/path_roles.go | 83 +++++++++++----- ...cret_one_time_key.go => secret_ssh_key.go} | 10 +- builtin/logical/ssh/ssh_util.go | 5 +- command/ssh.go | 24 ++++- command/write.go | 3 + http/handler.go | 4 +- http/logical.go | 3 + http/sys_ssh.go | 7 +- vault/core.go | 2 + vault/router.go | 3 + 18 files changed, 258 insertions(+), 213 deletions(-) delete mode 100644 builtin/logical/ssh/path_config_add_host_key.go delete mode 100644 builtin/logical/ssh/path_config_remove_host_key.go create mode 100644 builtin/logical/ssh/path_keys.go rename builtin/logical/ssh/{ssh_connect.go => path_role_create.go} (66%) rename builtin/logical/ssh/{secret_one_time_key.go => secret_ssh_key.go} (73%) diff --git a/api/logical.go b/api/logical.go index a633df4b96..20bd1ea59f 100644 --- a/api/logical.go +++ b/api/logical.go @@ -1,5 +1,7 @@ package api +import "log" + // Logical is used to perform logical backend operations on Vault. type Logical struct { c *Client @@ -25,6 +27,7 @@ func (c *Logical) Read(path string) (*Secret, error) { } func (c *Logical) Write(path string, data map[string]interface{}) (*Secret, error) { + log.Printf("Vishal: api.logical.Write(): invoking Put() on %#v\n", path) r := c.c.NewRequest("PUT", "/v1/"+path) if err := r.SetJSONBody(data); err != nil { return nil, err diff --git a/api/sys_ssh.go b/api/sys_ssh.go index 99fd1b164a..bce918072d 100644 --- a/api/sys_ssh.go +++ b/api/sys_ssh.go @@ -1,24 +1,10 @@ package api -import ( - "fmt" - "log" - "net" - "strings" -) +import "fmt" -func (c *Sys) Ssh(target string) (*OneTimeKey, error) { - r := c.c.NewRequest("POST", fmt.Sprintf("/v1/ssh/connect")) - input := strings.Split(target, "@") - username := input[0] - ipAddr := input[1] - ip4Addr, err := net.ResolveIPAddr("ip4", ipAddr) - log.Printf("Vishal: ssh.Ssh ipAddr_resolved: %#v\n", ip4Addr.String()) - body := map[string]interface{}{ - "username": username, - "address": ip4Addr.String(), - } - if err := r.SetJSONBody(body); err != nil { +func (c *Sys) Ssh(data map[string]interface{}) (*Secret, error) { + r := c.c.NewRequest("PUT", fmt.Sprintf("/v1/ssh/creds/web")) + if err := r.SetJSONBody(data); err != nil { return nil, err } @@ -28,11 +14,17 @@ func (c *Sys) Ssh(target string) (*OneTimeKey, error) { } defer resp.Body.Close() - var result OneTimeKey - err = resp.DecodeJSON(&result) - return &result, err -} + return ParseSecret(resp.Body) -type OneTimeKey struct { - Key string + /* + result := new(Secret) + err = resp.DecodeJSON(&result) + log.Printf("Vishal: api.sys_ssh.Ssh: result:%#v\n", result.Data) + + var oneTimeKey OneTimeKey + err = result.Data.DecodeJSON(&oneTimeKey) + log.Printf("Vishal: oneTimeKey:%#v\n", oneTimeKey) + return &oneTimeKey, err + */ + //return result, err } diff --git a/builtin/logical/aws/path_user.go b/builtin/logical/aws/path_user.go index 007ca6a2bc..4352aa882f 100644 --- a/builtin/logical/aws/path_user.go +++ b/builtin/logical/aws/path_user.go @@ -2,6 +2,7 @@ package aws import ( "fmt" + "log" "github.com/hashicorp/aws-sdk-go/aws" "github.com/hashicorp/aws-sdk-go/gen/iam" @@ -32,6 +33,8 @@ func pathUser(b *backend) *framework.Path { func (b *backend) pathUserRead( req *logical.Request, d *framework.FieldData) (*logical.Response, error) { policyName := d.Get("name").(string) + log.Printf("Vishal: policyName: %#v\n", policyName) + log.Printf("Vishal: data d: %#v\n", d) // Read the policy policy, err := req.Storage.Get("policy/" + policyName) diff --git a/builtin/logical/ssh/backend.go b/builtin/logical/ssh/backend.go index b0e30869c4..33e414722c 100644 --- a/builtin/logical/ssh/backend.go +++ b/builtin/logical/ssh/backend.go @@ -24,14 +24,13 @@ func Backend() *framework.Backend { Paths: []*framework.Path{ pathConfigLease(&b), - pathConfigAddHostKey(&b), - pathConfigRemoveHostKey(&b), + pathKeys(&b), pathRoles(&b), - sshConnect(&b), + pathRoleCreate(&b), }, Secrets: []*framework.Secret{ - secretOneTimeKey(&b), + secretSshKey(&b), }, } return b.Backend diff --git a/builtin/logical/ssh/path_config_add_host_key.go b/builtin/logical/ssh/path_config_add_host_key.go deleted file mode 100644 index 849d8ee8ce..0000000000 --- a/builtin/logical/ssh/path_config_add_host_key.go +++ /dev/null @@ -1,69 +0,0 @@ -package ssh - -import ( - "log" - - "github.com/hashicorp/vault/logical" - "github.com/hashicorp/vault/logical/framework" -) - -func pathConfigAddHostKey(b *backend) *framework.Path { - log.Printf("Vishal: ssh.pathConfigAddHostKey\n") - return &framework.Path{ - Pattern: "config/addhostkey", - Fields: map[string]*framework.FieldSchema{ - "username": &framework.FieldSchema{ - Type: framework.TypeString, - Description: "Username in host.", - }, - "ip": &framework.FieldSchema{ - Type: framework.TypeString, - Description: "IP address of host.", - }, - "key": &framework.FieldSchema{ - Type: framework.TypeString, - Description: "SSH private key for host.", - }, - }, - Callbacks: map[logical.Operation]framework.OperationFunc{ - logical.WriteOperation: b.pathAddHostKeyWrite, - }, - HelpSynopsis: pathConfigAddHostKeySyn, - HelpDescription: pathConfigAddHostKeyDesc, - } -} - -func (b *backend) pathAddHostKeyWrite(req *logical.Request, d *framework.FieldData) (*logical.Response, error) { - log.SetFlags(log.LstdFlags | log.Lshortfile) - log.Printf("Vishal: ssh.pathAddHostKeyWrite\n") - username := d.Get("username").(string) - ip := d.Get("ip").(string) - //TODO: parse ip into ipv4 address and validate it - key := d.Get("key").(string) - //log.Printf("Vishal: ssh.pathAddHostKeyWrite username:%#v ip:%#v key:%#v\n", username, ip, key) - - hostKeyPath := "hosts/" + ip + "/" + username - log.Printf("Vishal: hostKeyPath: %#v\n", hostKeyPath) - entry, err := logical.StorageEntryJSON("hosts/"+ip+"/"+username, &sshHostKey{ - Key: key, - }) - if err != nil { - return nil, err - } - if err := req.Storage.Put(entry); err != nil { - return nil, err - } - return nil, nil -} - -type sshHostKey struct { - Key string -} - -const pathConfigAddHostKeySyn = ` -pathConfigAddHostKeySyn -` - -const pathConfigAddHostKeyDesc = ` -pathConfigAddHostKeyDesc -` diff --git a/builtin/logical/ssh/path_config_remove_host_key.go b/builtin/logical/ssh/path_config_remove_host_key.go deleted file mode 100644 index e48f0a5720..0000000000 --- a/builtin/logical/ssh/path_config_remove_host_key.go +++ /dev/null @@ -1,51 +0,0 @@ -package ssh - -import ( - "log" - - "github.com/hashicorp/vault/logical" - "github.com/hashicorp/vault/logical/framework" -) - -func pathConfigRemoveHostKey(b *backend) *framework.Path { - log.Printf("Vishal: ssh.pathConfigRemoveHostKey\n") - return &framework.Path{ - Pattern: "config/removehostkey", - Fields: map[string]*framework.FieldSchema{ - "username": &framework.FieldSchema{ - Type: framework.TypeString, - Description: "Username in host.", - }, - "ip": &framework.FieldSchema{ - Type: framework.TypeString, - Description: "IP address of host.", - }, - }, - Callbacks: map[logical.Operation]framework.OperationFunc{ - logical.WriteOperation: b.pathRemoveHostKeyWrite, - }, - HelpSynopsis: pathConfigRemoveHostKeySyn, - HelpDescription: pathConfigRemoveHostKeyDesc, - } -} - -func (b *backend) pathRemoveHostKeyWrite(req *logical.Request, d *framework.FieldData) (*logical.Response, error) { - log.Printf("Vishal: ssh.pathRemoveHostKeyWrite\n") - username := d.Get("username").(string) - ip := d.Get("ip").(string) - //TODO: parse ip into ipv4 address and validate it - log.Printf("Vishal: ssh.pathRemoveHostKeyWrite username:%#v ip:%#v\n", username, ip) - err := req.Storage.Delete("hosts/" + ip + "/" + username) - if err != nil { - return nil, err - } - return nil, nil -} - -const pathConfigRemoveHostKeySyn = ` -pathConfigRemoveHostKeySyn -` - -const pathConfigRemoveHostKeyDesc = ` -pathConfigRemoveHostKeyDesc -` diff --git a/builtin/logical/ssh/path_keys.go b/builtin/logical/ssh/path_keys.go new file mode 100644 index 0000000000..7272ce7f22 --- /dev/null +++ b/builtin/logical/ssh/path_keys.go @@ -0,0 +1,95 @@ +package ssh + +import ( + "log" + + "github.com/hashicorp/vault/logical" + "github.com/hashicorp/vault/logical/framework" +) + +func pathKeys(b *backend) *framework.Path { + log.Printf("Vishal: ssh.pathConfigAddHostKey\n") + return &framework.Path{ + Pattern: "keys/(?P\\w+)", + Fields: map[string]*framework.FieldSchema{ + "name": &framework.FieldSchema{ + Type: framework.TypeString, + Description: "IP address of host.", + }, + "key": &framework.FieldSchema{ + Type: framework.TypeString, + Description: "SSH private key for host.", + }, + }, + Callbacks: map[logical.Operation]framework.OperationFunc{ + logical.ReadOperation: b.pathKeysRead, + logical.WriteOperation: b.pathKeysWrite, + logical.DeleteOperation: b.pathKeysDelete, + }, + HelpSynopsis: pathConfigAddHostKeySyn, + HelpDescription: pathConfigAddHostKeyDesc, + } +} + +func (b *backend) pathKeysRead(req *logical.Request, d *framework.FieldData) (*logical.Response, error) { + keyName := d.Get("name").(string) + log.Printf("Vishal: ssh.pathKeysRead: keyName: %#v\n", keyName) + keyPath := "keys/" + keyName + entry, err := req.Storage.Get(keyPath) + if err != nil { + return nil, err + } + if entry == nil { + return nil, nil + } + + return &logical.Response{ + Data: map[string]interface{}{ + "key": string(entry.Value), + }, + }, nil +} + +func (b *backend) pathKeysDelete(req *logical.Request, d *framework.FieldData) (*logical.Response, error) { + keyName := d.Get("name").(string) + log.Printf("Vishal: ssh.pathKeysDelete: keyName: %#v\n", keyName) + keyPath := "keys/" + keyName + err := req.Storage.Delete(keyPath) + if err != nil { + return nil, err + } + return nil, nil +} + +func (b *backend) pathKeysWrite(req *logical.Request, d *framework.FieldData) (*logical.Response, error) { + log.SetFlags(log.LstdFlags | log.Lshortfile) + log.Printf("Vishal: ssh.pathKeysWrite\n") + + keyName := d.Get("name").(string) + keyString := d.Get("key").(string) + keyPath := "keys/" + keyName + + log.Printf("Vishal: ssh.path_keys.pathKeysWrite: keyPath: %#v\n", keyPath) + entry, err := logical.StorageEntryJSON(keyPath, &sshHostKey{ + Key: keyString, + }) + if err != nil { + return nil, err + } + if err := req.Storage.Put(entry); err != nil { + return nil, err + } + return nil, nil +} + +type sshHostKey struct { + Key string +} + +const pathConfigAddHostKeySyn = ` +pathConfigAddHostKeySyn +` + +const pathConfigAddHostKeyDesc = ` +pathConfigAddHostKeyDesc +` diff --git a/builtin/logical/ssh/ssh_connect.go b/builtin/logical/ssh/path_role_create.go similarity index 66% rename from builtin/logical/ssh/ssh_connect.go rename to builtin/logical/ssh/path_role_create.go index 27f111b067..c2afb60c4b 100644 --- a/builtin/logical/ssh/ssh_connect.go +++ b/builtin/logical/ssh/path_role_create.go @@ -11,51 +11,70 @@ import ( "github.com/hashicorp/vault/logical/framework" ) -func sshConnect(b *backend) *framework.Path { +func pathRoleCreate(b *backend) *framework.Path { log.Printf("Vishal: ssh.sshConnect\n") return &framework.Path{ - Pattern: "connect", + Pattern: "creds/(?P\\w+)", Fields: map[string]*framework.FieldSchema{ + "name": &framework.FieldSchema{ + Type: framework.TypeString, + Description: "name of the policy", + }, "username": &framework.FieldSchema{ Type: framework.TypeString, - Description: "username at SSH host", + Description: "username in target", }, - "address": &framework.FieldSchema{ + "ip": &framework.FieldSchema{ Type: framework.TypeString, - Description: "IPv4 address of SSH host", + Description: "IP of the target machine", }, }, Callbacks: map[logical.Operation]framework.OperationFunc{ - logical.WriteOperation: b.sshConnectWrite, + logical.WriteOperation: b.pathRoleCreateWrite, }, HelpSynopsis: sshConnectHelpSyn, HelpDescription: sshConnectHelpDesc, } } -func (b *backend) sshConnectWrite( +func (b *backend) pathRoleCreateWrite( req *logical.Request, d *framework.FieldData) (*logical.Response, error) { - username := d.Get("username").(string) - ipAddr := d.Get("address").(string) - log.Printf("Vishal: ssh.sshConnectWrite username:%#v address:%#v\n", username, ipAddr) + log.Printf("Vishal: ssh.pathRoleCreateWrite\n") - hostKeyPath := "hosts/" + ipAddr + "/" + username - entry, err := req.Storage.Get(hostKeyPath) + roleName := d.Get("name").(string) + username := d.Get("username").(string) + ipAddr := d.Get("ip").(string) + + rolePath := "policy/" + roleName + roleEntry, err := req.Storage.Get(rolePath) if err != nil { + return nil, fmt.Errorf("error retrieving role: %s", err) + } + if roleEntry == nil { + return logical.ErrorResponse(fmt.Sprintf("Role '%s' not found", roleName)), nil + } + + var role sshRole + if err := roleEntry.DecodeJSON(&role); err != nil { return nil, err } - if entry == nil { - return nil, fmt.Errorf("Host key is not configured. Please configure them at the config/addhostkey endpoint") + log.Printf("Vishal: ssh.pathRoleCreateWrite username:%#v address:%#v name:%#v result:%s\n", username, ipAddr, roleName, role) + //TODO: do the role verification here + + keyPath := "keys/" + role.KeyName + keyEntry, err := req.Storage.Get(keyPath) + if err != nil { + return nil, fmt.Errorf("Key '%s' not found error:%s", role.KeyName, err) } + + log.Printf("Vishal: KeyName:%s keyPath:%s\n", role.KeyName, keyPath) var hostKey sshHostKey - if err := entry.DecodeJSON(&hostKey); err != nil { + if err := keyEntry.DecodeJSON(&hostKey); err != nil { return nil, fmt.Errorf("Error reading the host key: %s", err) } log.Printf("Vishal: host key previously configured: \n---------------\n%#v\n--------------\n", hostKey.Key) - //TODO: save th entry in a file - //TODO: read the hosts path and get the key //TODO: Input validation for the commands below hostKeyFileName := "./vault_ssh_" + username + "_" + ipAddr + "_shared.pem" err = ioutil.WriteFile(hostKeyFileName, []byte(hostKey.Key), 0400) @@ -95,12 +114,6 @@ func (b *backend) sshConnectWrite( return b.Secret(SecretOneTimeKeyType).Response(map[string]interface{}{ "key": oneTimeKey, }, nil), nil - /*return &logical.Response{ - Data: map[string]interface{}{ - "key": oneTimeKey, - }, - }, nil - */ } const sshConnectHelpSyn = ` diff --git a/builtin/logical/ssh/path_roles.go b/builtin/logical/ssh/path_roles.go index 9e53e3575d..a6781fb2c4 100644 --- a/builtin/logical/ssh/path_roles.go +++ b/builtin/logical/ssh/path_roles.go @@ -1,9 +1,6 @@ package ssh import ( - "bytes" - "encoding/json" - "fmt" "log" "github.com/hashicorp/vault/logical" @@ -19,9 +16,21 @@ func pathRoles(b *backend) *framework.Path { Type: framework.TypeString, Description: "Name of the role", }, - "policy": &framework.FieldSchema{ + "key": &framework.FieldSchema{ Type: framework.TypeString, - Description: "String representing the policy for the role. See help for more info.", + Description: "Named key in Vault", + }, + "admin_user": &framework.FieldSchema{ + Type: framework.TypeString, + Description: "Admin user at target address", + }, + "default_user": &framework.FieldSchema{ + Type: framework.TypeString, + Description: "Default user to whom the dynamic key is installed", + }, + "cidr": &framework.FieldSchema{ + Type: framework.TypeString, + Description: "CIDR blocks and IP addresses", }, }, @@ -36,9 +45,43 @@ func pathRoles(b *backend) *framework.Path { } } +func (b *backend) pathRoleWrite(req *logical.Request, d *framework.FieldData) (*logical.Response, error) { + log.Printf("Vishal: ssh.pathRoleWrite\n") + + roleName := d.Get("name").(string) + keyName := d.Get("key").(string) + adminUser := d.Get("admin_user").(string) + defaultUser := d.Get("default_user").(string) + cidr := d.Get("cidr").(string) + + log.Printf("Vishal: name[%s] key[%s] admin_user[%s] default_user[%s] cidr[%s]\n", roleName, keyName, adminUser, defaultUser, cidr) + + rolePath := "policy/" + roleName + + entry, err := logical.StorageEntryJSON(rolePath, sshRole{ + KeyName: keyName, + AdminUser: adminUser, + DefaultUser: defaultUser, + CIDR: cidr, + }) + + if err != nil { + return nil, err + } + + log.Printf("Vishal: entryJSON:%s\n", entry.Value) + if err := req.Storage.Put(entry); err != nil { + return nil, err + } + + return nil, nil +} + func (b *backend) pathRoleRead(req *logical.Request, d *framework.FieldData) (*logical.Response, error) { log.Printf("Vishal: ssh.pathRoleRead\n") - entry, err := req.Storage.Get("policy/" + d.Get("name").(string)) + roleName := d.Get("name").(string) + rolePath := "policy/" + roleName + entry, err := req.Storage.Get(rolePath) if err != nil { return nil, err } @@ -52,30 +95,22 @@ func (b *backend) pathRoleRead(req *logical.Request, d *framework.FieldData) (*l }, nil } -func (b *backend) pathRoleWrite(req *logical.Request, d *framework.FieldData) (*logical.Response, error) { - log.Printf("Vishal: ssh.pathRoleWrite\n") - var buf bytes.Buffer - if err := json.Compact(&buf, []byte(d.Get("policy").(string))); err != nil { - return logical.ErrorResponse(fmt.Sprintf("Error compacting policy: %s", err)), nil - } - - err := req.Storage.Put(&logical.StorageEntry{ - Key: "policy/" + d.Get("name").(string), - Value: buf.Bytes(), - }) +func (b *backend) pathRoleDelete(req *logical.Request, d *framework.FieldData) (*logical.Response, error) { + log.Printf("Vishal: ssh.pathRoleDelete\n") + roleName := d.Get("name").(string) + rolePath := "policy/" + roleName + err := req.Storage.Delete(rolePath) if err != nil { return nil, err } return nil, nil } -func (b *backend) pathRoleDelete(req *logical.Request, d *framework.FieldData) (*logical.Response, error) { - log.Printf("Vishal: ssh.pathRoleDelete\n") - err := req.Storage.Delete("policy/" + d.Get("name").(string)) - if err != nil { - return nil, err - } - return nil, nil +type sshRole struct { + KeyName string `json:"key"` + AdminUser string `json:"admin_user"` + DefaultUser string `json:"default_user"` + CIDR string `json: "cidr"` } const pathRoleHelpSyn = ` diff --git a/builtin/logical/ssh/secret_one_time_key.go b/builtin/logical/ssh/secret_ssh_key.go similarity index 73% rename from builtin/logical/ssh/secret_one_time_key.go rename to builtin/logical/ssh/secret_ssh_key.go index f28902dcbb..e1a644e7f1 100644 --- a/builtin/logical/ssh/secret_one_time_key.go +++ b/builtin/logical/ssh/secret_ssh_key.go @@ -10,7 +10,7 @@ import ( const SecretOneTimeKeyType = "secret_one_type_key_type" -func secretOneTimeKey(b *backend) *framework.Secret { +func secretSshKey(b *backend) *framework.Secret { log.Printf("Vishal: ssh.secretPrivateKey\n") return &framework.Secret{ Type: SecretOneTimeKeyType, @@ -26,12 +26,12 @@ func secretOneTimeKey(b *backend) *framework.Secret { }, DefaultDuration: 1 * time.Hour, DefaultGracePeriod: 10 * time.Minute, - Renew: b.secretPrivateKeyRenew, - Revoke: b.secretPrivateKeyRevoke, + Renew: b.secretSshKeyRenew, + Revoke: b.secretSshKeyRevoke, } } -func (b *backend) secretPrivateKeyRenew(req *logical.Request, d *framework.FieldData) (*logical.Response, error) { +func (b *backend) secretSshKeyRenew(req *logical.Request, d *framework.FieldData) (*logical.Response, error) { log.Printf("Vishal: ssh.secretPrivateKeyRenew\n") lease, err := b.Lease(req.Storage) if err != nil { @@ -44,7 +44,7 @@ func (b *backend) secretPrivateKeyRenew(req *logical.Request, d *framework.Field return f(req, d) } -func (b *backend) secretPrivateKeyRevoke(req *logical.Request, d *framework.FieldData) (*logical.Response, error) { +func (b *backend) secretSshKeyRevoke(req *logical.Request, d *framework.FieldData) (*logical.Response, error) { log.Printf("Vishal: ssh.secretPrivateKeyRevoke\n") //TODO: implement here return nil, nil diff --git a/builtin/logical/ssh/ssh_util.go b/builtin/logical/ssh/ssh_util.go index 59429d8772..f998330e17 100644 --- a/builtin/logical/ssh/ssh_util.go +++ b/builtin/logical/ssh/ssh_util.go @@ -34,12 +34,9 @@ func installSshOtkInTarget(session *ssh.Session, username string, ipAddr string) log.Printf("Vishal: grepCmd:%#v\n catCmdRemoveDuplicate:%#v\n catCmdAppendNew:%#v\n rmCmd: %#v\n", grepCmd, catCmdRemoveDuplicate, catCmdAppendNew, rmCmd) remoteCmdString := strings.Join([]string{ grepCmd, - "echo 1;", catCmdRemoveDuplicate, - "echo 2;", catCmdAppendNew, - "echo 3;", - //rmCmd, + rmCmd, }, "") if err := session.Run(remoteCmdString); err != nil { diff --git a/command/ssh.go b/command/ssh.go index 49f01710ed..f9752109ae 100644 --- a/command/ssh.go +++ b/command/ssh.go @@ -4,6 +4,7 @@ import ( "fmt" "io/ioutil" "log" + "net" "os" "os/exec" "strings" @@ -30,16 +31,25 @@ func (c *SshCommand) Run(args []string) int { } //if len(args) < 3, fail log.Printf("Vishal: sshCommand.Run: args[0]: %#v\n", args[0]) - sshOneTimeKey, err := client.Sys().Ssh(args[0]) - if err != nil { - c.Ui.Error(fmt.Sprintf("Error getting one-time-key for establishing SSH session", err)) - return 2 + input := strings.Split(args[0], "@") + username := input[0] + ipAddr, err := net.ResolveIPAddr("ip4", input[1]) + log.Printf("Vishal: ssh.Ssh ipAddr_resolved: %#v\n", ipAddr.String()) + data := map[string]interface{}{ + "username": username, + "ip": ipAddr.String(), } + keySecret, err := client.Sys().Ssh(data) + if err != nil { + c.Ui.Error(fmt.Sprintf("Error getting key for establishing SSH session", err)) + return 2 + } + sshOneTimeKey := string(keySecret.Data["key"].(string)) log.Printf("Vishal: command.ssh.Run returned! OTK:%#v\n", sshOneTimeKey) ag := strings.Split(args[0], "@") sshOtkFileName := "vault_ssh_otk_" + ag[0] + "_" + ag[1] + ".pem" - err = ioutil.WriteFile(sshOtkFileName, []byte(sshOneTimeKey.Key), 0400) + err = ioutil.WriteFile(sshOtkFileName, []byte(sshOneTimeKey), 0400) //if sshOneTimeKey is empty, fail //Establish a session directly from client to the target using the one time key received without making the vault server the middle guy:w sshBinary, err := exec.LookPath("ssh") @@ -60,6 +70,10 @@ func (c *SshCommand) Run(args []string) int { return 0 } +type OneTimeKey struct { + Key string +} + func (c *SshCommand) Synopsis() string { return "Initiate a SSH session" } diff --git a/command/write.go b/command/write.go index ba0fdd823d..cdab754136 100644 --- a/command/write.go +++ b/command/write.go @@ -3,6 +3,7 @@ package command import ( "fmt" "io" + "log" "os" "strings" @@ -18,6 +19,7 @@ type WriteCommand struct { } func (c *WriteCommand) Run(args []string) int { + log.Printf("Vishal: writeCommand\n") var format string var force bool flags := c.Meta.FlagSet("write", FlagSetDefault) @@ -55,6 +57,7 @@ func (c *WriteCommand) Run(args []string) int { return 2 } + log.Printf("Vishal: write Path: %#v\n", path) secret, err := client.Logical().Write(path, data) if err != nil { c.Ui.Error(fmt.Sprintf( diff --git a/http/handler.go b/http/handler.go index 835087a5bd..4961f27d9b 100644 --- a/http/handler.go +++ b/http/handler.go @@ -3,6 +3,7 @@ package http import ( "encoding/json" "fmt" + "log" "net/http" "net/url" "strings" @@ -21,6 +22,7 @@ const AuthHeaderName = "X-Vault-Token" // its own to mount the Vault API within another web server. func Handler(core *vault.Core) http.Handler { // Create the muxer to handle the actual endpoints + log.Printf("Vishal: http.handler.Handler\n") mux := http.NewServeMux() mux.Handle("/v1/sys/init", handleSysInit(core)) mux.Handle("/v1/sys/seal-status", handleSysSealStatus(core)) @@ -44,7 +46,6 @@ func Handler(core *vault.Core) http.Handler { mux.Handle("/v1/sys/key-status", handleSysKeyStatus(core)) mux.Handle("/v1/sys/rekey/init", handleSysRekeyInit(core)) mux.Handle("/v1/sys/rekey/update", handleSysRekeyUpdate(core)) - mux.Handle("/v1/ssh/connect", handleSysSsh(core)) mux.Handle("/v1/", handleLogical(core)) // Wrap the handler in another handler to trigger all help paths. @@ -76,6 +77,7 @@ func parseRequest(r *http.Request, out interface{}) error { // request is a helper to perform a request and properly exit in the // case of an error. func request(core *vault.Core, w http.ResponseWriter, rawReq *http.Request, r *logical.Request) (*logical.Response, bool) { + log.Printf("Vishal: http.handler.request: \n") resp, err := core.HandleRequest(r) if err == vault.ErrStandby { respondStandby(core, w, rawReq.URL) diff --git a/http/logical.go b/http/logical.go index 70d0535ab1..a420342aa2 100644 --- a/http/logical.go +++ b/http/logical.go @@ -2,6 +2,7 @@ package http import ( "io" + "log" "net" "net/http" "strings" @@ -13,6 +14,7 @@ import ( func handleLogical(core *vault.Core) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + log.Printf("Vishal: handleLogical called\n") // Determine the path... if !strings.HasPrefix(r.URL.Path, "/v1/") { respondError(w, http.StatusNotFound, nil) @@ -64,6 +66,7 @@ func handleLogical(core *vault.Core) http.Handler { // Make the internal request. We attach the connection info // as well in case this is an authentication request that requires // it. Vault core handles stripping this if we need to. + log.Printf("Vishal: http.logical.handleLogical: requesting\n") resp, ok := request(core, w, r, requestAuth(r, &logical.Request{ Operation: op, Path: path, diff --git a/http/sys_ssh.go b/http/sys_ssh.go index 80a43efaec..d739699871 100644 --- a/http/sys_ssh.go +++ b/http/sys_ssh.go @@ -9,12 +9,13 @@ import ( ) func handleSysSsh(core *vault.Core) http.Handler { + log.Printf("Vishal: http.sys_ssh.handleSysSsh!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n") return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.Method != "POST" { + if r.Method != "PUT" { respondError(w, http.StatusMethodNotAllowed, nil) return } - log.Printf("Vishal: http.sys_ssh.handleSysSsh\n") + log.Printf("Vishal: http.sys_ssh.handleSysSsh: requesting\n") var req SshRequest if err := parseRequest(r, &req); err != nil { respondError(w, http.StatusBadRequest, err) @@ -23,7 +24,7 @@ func handleSysSsh(core *vault.Core) http.Handler { resp, ok := request(core, w, r, requestAuth(r, &logical.Request{ Operation: logical.WriteOperation, - Path: "ssh/connect", + Path: "ssh/creds/web", Data: map[string]interface{}{ "username": req.Username, "address": req.Address, diff --git a/vault/core.go b/vault/core.go index 3c67f63fad..de7d93983d 100644 --- a/vault/core.go +++ b/vault/core.go @@ -345,6 +345,7 @@ func (c *Core) Shutdown() error { // HandleRequest is used to handle a new incoming request func (c *Core) HandleRequest(req *logical.Request) (resp *logical.Response, err error) { + log.Printf("Vishal: vault.core.HandleRequest: req.Path:%#v\n", req.Path) c.stateLock.RLock() defer c.stateLock.RUnlock() if c.sealed { @@ -373,6 +374,7 @@ func (c *Core) HandleRequest(req *logical.Request) (resp *logical.Response, err } func (c *Core) handleRequest(req *logical.Request) (*logical.Response, error) { + log.Printf("Vishal: vault.core.handleRequest\n") defer metrics.MeasureSince([]string{"core", "handle_request"}, time.Now()) // Validate the token auth, err := c.checkToken(req.Operation, req.Path, req.ClientToken) diff --git a/vault/router.go b/vault/router.go index 653d5aa5dc..0d6eaf7c3b 100644 --- a/vault/router.go +++ b/vault/router.go @@ -4,6 +4,7 @@ import ( "crypto/sha1" "encoding/hex" "fmt" + "log" "strings" "sync" "time" @@ -145,10 +146,12 @@ func (r *Router) MatchingView(path string) *BarrierView { // Route is used to route a given request func (r *Router) Route(req *logical.Request) (*logical.Response, error) { + log.Printf("Vishal: vault.router.Route: req.Path:%#v\n", req.Path) // Find the mount point r.l.RLock() mount, raw, ok := r.root.LongestPrefix(req.Path) if !ok { + log.Printf("Vishal: vault.router.Route: here\n") // Re-check for a backend by appending a slash. This lets "foo" mean // "foo/" at the root level which is almost always what we want. req.Path += "/"