mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-11-01 19:17:58 +00:00
Roles, key renewal handled. End-to-end basic flow working.
This commit is contained in:
@@ -34,17 +34,18 @@ func pathConfigAddHostKey(b *backend) *framework.Path {
|
||||
}
|
||||
|
||||
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)
|
||||
//log.Printf("Vishal: ssh.pathAddHostKeyWrite username:%#v ip:%#v key:%#v\n", username, ip, key)
|
||||
|
||||
entry, err := logical.StorageEntryJSON("hosts/"+ip+"/"+username, &sshAddHostKey{
|
||||
Username: username,
|
||||
IP: ip,
|
||||
Key: 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
|
||||
@@ -55,10 +56,8 @@ func (b *backend) pathAddHostKeyWrite(req *logical.Request, d *framework.FieldDa
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
type sshAddHostKey struct {
|
||||
Username string
|
||||
IP string
|
||||
Key string
|
||||
type sshHostKey struct {
|
||||
Key string
|
||||
}
|
||||
|
||||
const pathConfigAddHostKeySyn = `
|
||||
|
||||
@@ -70,6 +70,23 @@ type configLease struct {
|
||||
LeaseMax time.Duration
|
||||
}
|
||||
|
||||
func (b *backend) Lease(s logical.Storage) (*configLease, error) {
|
||||
entry, err := s.Get("config/lease")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if entry == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var result configLease
|
||||
if err := entry.DecodeJSON(&result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
const pathConfigLeaseHelpSyn = `
|
||||
Configure the default lease information for SSH one time keys.
|
||||
`
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package ssh
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/hashicorp/vault/logical"
|
||||
@@ -33,18 +36,45 @@ func pathRoles(b *backend) *framework.Path {
|
||||
}
|
||||
}
|
||||
|
||||
func (b *backend) pathRoleRead(req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
||||
func (b *backend) pathRoleRead(req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||
log.Printf("Vishal: ssh.pathRoleRead\n")
|
||||
return nil, nil
|
||||
entry, err := req.Storage.Get("policy/" + d.Get("name").(string))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if entry == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return &logical.Response{
|
||||
Data: map[string]interface{}{
|
||||
"policy": string(entry.Value),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (b *backend) pathRoleWrite(req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
||||
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(),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (b *backend) pathRoleDelete(req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
@@ -8,12 +8,12 @@ import (
|
||||
"github.com/hashicorp/vault/logical/framework"
|
||||
)
|
||||
|
||||
const SecretOneTimeKeyType = "one_time_key"
|
||||
const SecretSshHostKeyType = "secret_ssh_host_key_type"
|
||||
|
||||
func secretOneTimeKey(b *backend) *framework.Secret {
|
||||
log.Printf("Vishal: ssh.secretPrivateKey\n")
|
||||
return &framework.Secret{
|
||||
Type: SecretOneTimeKeyType,
|
||||
Type: SecretSshHostKeyType,
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"username": &framework.FieldSchema{
|
||||
Type: framework.TypeString,
|
||||
@@ -23,19 +23,29 @@ func secretOneTimeKey(b *backend) *framework.Secret {
|
||||
Type: framework.TypeString,
|
||||
Description: "ip address of host",
|
||||
},
|
||||
"one_time_key": &framework.FieldSchema{
|
||||
Type: framework.TypeString,
|
||||
Description: "SSH one-time-key for host",
|
||||
},
|
||||
},
|
||||
DefaultDuration: 1 * time.Hour,
|
||||
DefaultGracePeriod: 10 * time.Minute,
|
||||
Renew: framework.LeaseExtend(1*time.Hour, 0, false),
|
||||
Renew: b.secretPrivateKeyRenew,
|
||||
Revoke: b.secretPrivateKeyRevoke,
|
||||
}
|
||||
}
|
||||
|
||||
func (b *backend) secretPrivateKeyRenew(req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||
log.Printf("Vishal: ssh.secretPrivateKeyRenew\n")
|
||||
lease, err := b.Lease(req.Storage)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if lease == nil {
|
||||
lease = &configLease{Lease: 1 * time.Hour}
|
||||
}
|
||||
f := framework.LeaseExtend(lease.Lease, lease.LeaseMax, false)
|
||||
return f(req, d)
|
||||
}
|
||||
|
||||
func (b *backend) secretPrivateKeyRevoke(req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||
log.Printf("Vishal: ssh.secretPrivateKeyRevoke\n")
|
||||
//TODO: implement here
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/vault/logical"
|
||||
"github.com/hashicorp/vault/logical/framework"
|
||||
@@ -34,24 +35,45 @@ func sshConnect(b *backend) *framework.Path {
|
||||
|
||||
func (b *backend) sshConnectWrite(
|
||||
req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||
log.Printf("Vishal: ssh.sshConnectWrite username:%#v address:%#v\n", d.Get("username").(string), d.Get("address").(string))
|
||||
username := d.Get("username").(string)
|
||||
ipAddr := d.Get("address").(string)
|
||||
log.Printf("Vishal: ssh.sshConnectWrite username:%#v address:%#v\n", username, ipAddr)
|
||||
|
||||
//username := d.Get("username").(string)
|
||||
//ip := d.Get("ip").(string)
|
||||
//key := d.Get("key").(string)
|
||||
//log.Printf("Vishal: ssh.pathAddHostKeyWrite username:%#v ip:%#v key:%#v\n", username, ip, key)
|
||||
localCmdString := `
|
||||
rm -f vault_ssh_otk.pem vault_ssh_otk.pem.pub;
|
||||
ssh-keygen -f vault_ssh_otk.pem -t rsa -N '';
|
||||
chmod 400 vault_ssh_otk.pem;
|
||||
scp -i vault_ssh_shared.pem vault_ssh_otk.pem.pub vishal@localhost:/home/vishal
|
||||
echo done!
|
||||
`
|
||||
err := exec_command(localCmdString)
|
||||
hostKeyPath := "hosts/" + ipAddr + "/" + username
|
||||
entry, err := req.Storage.Get(hostKeyPath)
|
||||
if 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")
|
||||
}
|
||||
var hostKey sshHostKey
|
||||
if err := entry.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
|
||||
|
||||
rmCmd := "rm -f " + "vault_ssh_otk.pem" + " " + "vault_ssh_otk.pem.pub" + ";"
|
||||
sshKeygenCmd := "ssh-keygen -f " + "vault_ssh_otk.pem" + " -t rsa -N ''" + ";"
|
||||
chmodCmd := "chmod 400 " + "vault_ssh_otk.pem" + ";"
|
||||
scpCmd := "scp -i " + "vault_ssh_shared.pem" + " " + "vault_ssh_otk.pem.pub" + " " + username + "@" + ipAddr + ":~;"
|
||||
|
||||
localCmdString := strings.Join([]string{
|
||||
rmCmd,
|
||||
sshKeygenCmd,
|
||||
chmodCmd,
|
||||
scpCmd,
|
||||
}, "")
|
||||
err = exec_command(localCmdString)
|
||||
if err != nil {
|
||||
fmt.Errorf("Running command failed " + err.Error())
|
||||
}
|
||||
session := createSSHPublicKeysSession("vishal", "127.0.0.1")
|
||||
session := createSSHPublicKeysSession(username, ipAddr)
|
||||
var buf bytes.Buffer
|
||||
session.Stdout = &buf
|
||||
if err := installSshOtkInTarget(session); err != nil {
|
||||
@@ -61,11 +83,16 @@ func (b *backend) sshConnectWrite(
|
||||
fmt.Println(buf.String())
|
||||
keyBytes, err := ioutil.ReadFile("vault_ssh_otk.pem")
|
||||
oneTimeKey := string(keyBytes)
|
||||
return &logical.Response{
|
||||
log.Printf("Vishal: Returning:%s\n", oneTimeKey)
|
||||
return b.Secret(SecretSshHostKeyType).Response(map[string]interface{}{
|
||||
"key": oneTimeKey,
|
||||
}, nil), nil
|
||||
/*return &logical.Response{
|
||||
Data: map[string]interface{}{
|
||||
"key": oneTimeKey,
|
||||
},
|
||||
}, nil
|
||||
*/
|
||||
}
|
||||
|
||||
const sshConnectHelpSyn = `
|
||||
@@ -73,5 +100,5 @@ sshConnectionHelpSyn
|
||||
`
|
||||
|
||||
const sshConnectHelpDesc = `
|
||||
sshConnectionHelpDesc
|
||||
rshConnectionHelpDesc
|
||||
`
|
||||
|
||||
@@ -3,7 +3,9 @@ package ssh
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
@@ -17,12 +19,19 @@ func exec_command(cmdString string) error {
|
||||
}
|
||||
|
||||
func installSshOtkInTarget(session *ssh.Session) error {
|
||||
remoteCmdString := `
|
||||
grep -vFf vault_ssh_otk.pem.pub ~/.ssh/authorized_keys > ./temp_authorized_keys
|
||||
cat ./temp_authorized_keys > ~/.ssh/authorized_keys
|
||||
cat ./vault_ssh_otk.pem.pub >> ~/.ssh/authorized_keys
|
||||
rm -f ./temp_authorized_keys ./vault_ssh_otk.pem.pub
|
||||
`
|
||||
log.Printf("Vishal: ssh.installSshOtkInTarget\n")
|
||||
|
||||
grepCmd := "grep -vFf " + "vault_ssh_otk.pem.pub" + " " + "~/.ssh/authorized_keys" + " > " + "./temp_authorized_keys" + ";"
|
||||
catCmdRemoveDuplicate := "cat " + "./temp_authorized_keys" + " > " + "~/.ssh/authorized_keys" + ";"
|
||||
catCmdAppendNew := "cat " + "./vault_ssh_otk.pem.pub" + " >> " + "~/.ssh/authorized_keys" + ";"
|
||||
rmCmd := "rm -f " + "./temp_authorized_keys" + " " + "./vault_ssh_otk.pem.pub" + ";"
|
||||
remoteCmdString := strings.Join([]string{
|
||||
grepCmd,
|
||||
catCmdRemoveDuplicate,
|
||||
catCmdAppendNew,
|
||||
rmCmd,
|
||||
}, "")
|
||||
|
||||
if err := session.Run(remoteCmdString); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -47,7 +47,9 @@ func (c *SshCommand) Run(args []string) int {
|
||||
|
||||
sshEnv := os.Environ()
|
||||
|
||||
sshCmdArgs := []string{"ssh", "-i", "vault_ssh_otk_" + args[0] + ".pem", "vishal@localhost"}
|
||||
sshNew := "ssh -i " + "vault_ssh_otk_" + args[0] + ".pem " + args[0]
|
||||
log.Printf("Vishal: sshNew:%#v\n", sshNew)
|
||||
sshCmdArgs := []string{"ssh", "-i", "vault_ssh_otk_" + args[0] + ".pem", args[0]}
|
||||
defer os.Remove("vault_ssh_otk_" + args[0] + ".pem")
|
||||
|
||||
if err := syscall.Exec(sshBinary, sshCmdArgs, sshEnv); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user