mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-11-02 11:38:02 +00:00
Input validations, help strings, default_user support
This commit is contained in:
@@ -2,7 +2,6 @@ package aws
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
|
|
||||||
"github.com/hashicorp/aws-sdk-go/aws"
|
"github.com/hashicorp/aws-sdk-go/aws"
|
||||||
"github.com/hashicorp/aws-sdk-go/gen/iam"
|
"github.com/hashicorp/aws-sdk-go/gen/iam"
|
||||||
@@ -33,8 +32,6 @@ func pathUser(b *backend) *framework.Path {
|
|||||||
func (b *backend) pathUserRead(
|
func (b *backend) pathUserRead(
|
||||||
req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||||
policyName := d.Get("name").(string)
|
policyName := d.Get("name").(string)
|
||||||
log.Printf("Vishal: policyName: %#v\n", policyName)
|
|
||||||
log.Printf("Vishal: data d: %#v\n", d)
|
|
||||||
|
|
||||||
// Read the policy
|
// Read the policy
|
||||||
policy, err := req.Storage.Get("policy/" + policyName)
|
policy, err := req.Storage.Get("policy/" + policyName)
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package ssh
|
package ssh
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/vault/logical"
|
"github.com/hashicorp/vault/logical"
|
||||||
@@ -13,7 +12,6 @@ func Factory(map[string]string) (logical.Backend, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Backend() *framework.Backend {
|
func Backend() *framework.Backend {
|
||||||
log.Printf("Vishal: ssh.Backend\n")
|
|
||||||
var b backend
|
var b backend
|
||||||
b.Backend = &framework.Backend{
|
b.Backend = &framework.Backend{
|
||||||
Help: strings.TrimSpace(backendHelp),
|
Help: strings.TrimSpace(backendHelp),
|
||||||
@@ -42,8 +40,12 @@ type backend struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const backendHelp = `
|
const backendHelp = `
|
||||||
The ssh backend enables secure connections to remote hosts.
|
The SSH backend dynamically generates SSH private keys for remote hosts.
|
||||||
|
The key generated has a configurable lease set and are automatically
|
||||||
|
revoked at the end of the lease.
|
||||||
|
|
||||||
After mounting this backend, configure it using the endpoints within
|
After mounting this backend, configure the lease using the 'config/lease'
|
||||||
the "config/" path.
|
endpoint. The shared SSH key belonging to any infrastructure should be
|
||||||
|
registered with the 'roles/' endpoint before dynamic keys for remote hosts
|
||||||
|
can be generated.
|
||||||
`
|
`
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package ssh
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/hashicorp/vault/logical"
|
"github.com/hashicorp/vault/logical"
|
||||||
@@ -10,7 +9,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func pathConfigLease(b *backend) *framework.Path {
|
func pathConfigLease(b *backend) *framework.Path {
|
||||||
log.Printf("Vishal: ssh.pathConfigLease\n")
|
|
||||||
return &framework.Path{
|
return &framework.Path{
|
||||||
Pattern: "config/lease",
|
Pattern: "config/lease",
|
||||||
Fields: map[string]*framework.FieldSchema{
|
Fields: map[string]*framework.FieldSchema{
|
||||||
@@ -25,7 +23,7 @@ func pathConfigLease(b *backend) *framework.Path {
|
|||||||
},
|
},
|
||||||
|
|
||||||
Callbacks: map[logical.Operation]framework.OperationFunc{
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
||||||
logical.WriteOperation: b.pathLeaseWrite,
|
logical.WriteOperation: b.pathConfigLeaseWrite,
|
||||||
},
|
},
|
||||||
|
|
||||||
HelpSynopsis: pathConfigLeaseHelpSyn,
|
HelpSynopsis: pathConfigLeaseHelpSyn,
|
||||||
@@ -33,10 +31,15 @@ func pathConfigLease(b *backend) *framework.Path {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *backend) pathLeaseWrite(req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
func (b *backend) pathConfigLeaseWrite(req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||||
log.Printf("Vishal: ssh.pathLeaseWrite\n")
|
|
||||||
leaseRaw := d.Get("lease").(string)
|
leaseRaw := d.Get("lease").(string)
|
||||||
leaseMaxRaw := d.Get("lease_max").(string)
|
leaseMaxRaw := d.Get("lease_max").(string)
|
||||||
|
if leaseRaw == "" {
|
||||||
|
return logical.ErrorResponse("Invalid 'lease'"), nil
|
||||||
|
}
|
||||||
|
if leaseMaxRaw == "" {
|
||||||
|
return logical.ErrorResponse("Invalid 'lease_max'"), nil
|
||||||
|
}
|
||||||
|
|
||||||
lease, err := time.ParseDuration(leaseRaw)
|
lease, err := time.ParseDuration(leaseRaw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -49,7 +52,6 @@ func (b *backend) pathLeaseWrite(req *logical.Request, d *framework.FieldData) (
|
|||||||
"Invalid lease: %s", err)), nil
|
"Invalid lease: %s", err)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store it
|
|
||||||
entry, err := logical.StorageEntryJSON("config/lease", &configLease{
|
entry, err := logical.StorageEntryJSON("config/lease", &configLease{
|
||||||
Lease: lease,
|
Lease: lease,
|
||||||
LeaseMax: leaseMax,
|
LeaseMax: leaseMax,
|
||||||
@@ -64,11 +66,6 @@ func (b *backend) pathLeaseWrite(req *logical.Request, d *framework.FieldData) (
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type configLease struct {
|
|
||||||
Lease time.Duration
|
|
||||||
LeaseMax time.Duration
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *backend) Lease(s logical.Storage) (*configLease, error) {
|
func (b *backend) Lease(s logical.Storage) (*configLease, error) {
|
||||||
entry, err := s.Get("config/lease")
|
entry, err := s.Get("config/lease")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -86,12 +83,17 @@ func (b *backend) Lease(s logical.Storage) (*configLease, error) {
|
|||||||
return &result, nil
|
return &result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type configLease struct {
|
||||||
|
Lease time.Duration
|
||||||
|
LeaseMax time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
const pathConfigLeaseHelpSyn = `
|
const pathConfigLeaseHelpSyn = `
|
||||||
Configure the default lease information for SSH one time keys.
|
Configure the default lease information for SSH one time keys.
|
||||||
`
|
`
|
||||||
|
|
||||||
const pathConfigLeaseHelpDesc = `
|
const pathConfigLeaseHelpDesc = `
|
||||||
This configures the default lease information used for SSH one time keys
|
This configures the default lease information used for SSH keys
|
||||||
generated by this backend. The lease specifies the duration that a
|
generated by this backend. The lease specifies the duration that a
|
||||||
credential will be valid for, as well as the maximum session for
|
credential will be valid for, as well as the maximum session for
|
||||||
a set of credentials.
|
a set of credentials.
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package ssh
|
package ssh
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"github.com/hashicorp/vault/logical"
|
"github.com/hashicorp/vault/logical"
|
||||||
@@ -8,7 +9,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func pathKeys(b *backend) *framework.Path {
|
func pathKeys(b *backend) *framework.Path {
|
||||||
log.Printf("Vishal: ssh.pathConfigAddHostKey\n")
|
|
||||||
return &framework.Path{
|
return &framework.Path{
|
||||||
Pattern: "keys/(?P<name>\\w+)",
|
Pattern: "keys/(?P<name>\\w+)",
|
||||||
Fields: map[string]*framework.FieldSchema{
|
Fields: map[string]*framework.FieldSchema{
|
||||||
@@ -26,14 +26,13 @@ func pathKeys(b *backend) *framework.Path {
|
|||||||
logical.WriteOperation: b.pathKeysWrite,
|
logical.WriteOperation: b.pathKeysWrite,
|
||||||
logical.DeleteOperation: b.pathKeysDelete,
|
logical.DeleteOperation: b.pathKeysDelete,
|
||||||
},
|
},
|
||||||
HelpSynopsis: pathConfigAddHostKeySyn,
|
HelpSynopsis: pathKeysSyn,
|
||||||
HelpDescription: pathConfigAddHostKeyDesc,
|
HelpDescription: pathKeysDesc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *backend) pathKeysRead(req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
func (b *backend) pathKeysRead(req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||||
keyName := d.Get("name").(string)
|
keyName := d.Get("name").(string)
|
||||||
log.Printf("Vishal: ssh.pathKeysRead: keyName: %#v\n", keyName)
|
|
||||||
keyPath := "keys/" + keyName
|
keyPath := "keys/" + keyName
|
||||||
entry, err := req.Storage.Get(keyPath)
|
entry, err := req.Storage.Get(keyPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -52,7 +51,6 @@ func (b *backend) pathKeysRead(req *logical.Request, d *framework.FieldData) (*l
|
|||||||
|
|
||||||
func (b *backend) pathKeysDelete(req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
func (b *backend) pathKeysDelete(req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||||
keyName := d.Get("name").(string)
|
keyName := d.Get("name").(string)
|
||||||
log.Printf("Vishal: ssh.pathKeysDelete: keyName: %#v\n", keyName)
|
|
||||||
keyPath := "keys/" + keyName
|
keyPath := "keys/" + keyName
|
||||||
err := req.Storage.Delete(keyPath)
|
err := req.Storage.Delete(keyPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -63,13 +61,16 @@ func (b *backend) pathKeysDelete(req *logical.Request, d *framework.FieldData) (
|
|||||||
|
|
||||||
func (b *backend) pathKeysWrite(req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
func (b *backend) pathKeysWrite(req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||||
log.SetFlags(log.LstdFlags | log.Lshortfile)
|
log.SetFlags(log.LstdFlags | log.Lshortfile)
|
||||||
log.Printf("Vishal: ssh.pathKeysWrite\n")
|
|
||||||
|
|
||||||
keyName := d.Get("name").(string)
|
keyName := d.Get("name").(string)
|
||||||
keyString := d.Get("key").(string)
|
keyString := d.Get("key").(string)
|
||||||
|
|
||||||
|
if keyString == "" {
|
||||||
|
return nil, fmt.Errorf("Invalid 'key'")
|
||||||
|
}
|
||||||
|
|
||||||
keyPath := "keys/" + keyName
|
keyPath := "keys/" + keyName
|
||||||
|
|
||||||
log.Printf("Vishal: ssh.path_keys.pathKeysWrite: keyPath: %#v\n", keyPath)
|
|
||||||
entry, err := logical.StorageEntryJSON(keyPath, &sshHostKey{
|
entry, err := logical.StorageEntryJSON(keyPath, &sshHostKey{
|
||||||
Key: keyString,
|
Key: keyString,
|
||||||
})
|
})
|
||||||
@@ -86,10 +87,11 @@ type sshHostKey struct {
|
|||||||
Key string
|
Key string
|
||||||
}
|
}
|
||||||
|
|
||||||
const pathConfigAddHostKeySyn = `
|
const pathKeysSyn = `
|
||||||
pathConfigAddHostKeySyn
|
Register a shared key which can be used to install dynamic key in remote machine.
|
||||||
`
|
`
|
||||||
|
|
||||||
const pathConfigAddHostKeyDesc = `
|
const pathKeysDesc = `
|
||||||
pathConfigAddHostKeyDesc
|
The shared key registered will be used to install and uninstall dynamic keys in remote machine.
|
||||||
|
This key should have "root" privileges which enables installing keys for unprivileged usernames.
|
||||||
`
|
`
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package ssh
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -11,7 +10,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func pathLookup(b *backend) *framework.Path {
|
func pathLookup(b *backend) *framework.Path {
|
||||||
log.Printf("Vishal: ssh.pathLookup\n")
|
|
||||||
return &framework.Path{
|
return &framework.Path{
|
||||||
Pattern: "lookup",
|
Pattern: "lookup",
|
||||||
Fields: map[string]*framework.FieldSchema{
|
Fields: map[string]*framework.FieldSchema{
|
||||||
@@ -29,20 +27,29 @@ func pathLookup(b *backend) *framework.Path {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *backend) pathLookupWrite(req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
func (b *backend) pathLookupWrite(req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||||
ip := d.Get("ip").(string)
|
ipAddr := d.Get("ip").(string)
|
||||||
//ip := "127.0.0.1"
|
if ipAddr == "" {
|
||||||
ipAddr := net.ParseIP(ip)
|
return logical.ErrorResponse("Missing 'ip'"), nil
|
||||||
if ipAddr == nil {
|
|
||||||
return logical.ErrorResponse(fmt.Sprintf("Invalid IP '%s'", ip)), nil
|
|
||||||
}
|
}
|
||||||
keys, _ := req.Storage.List("policy/")
|
ip := net.ParseIP(ipAddr)
|
||||||
|
if ip == nil {
|
||||||
|
return logical.ErrorResponse(fmt.Sprintf("Invalid IP '%s'", ip.String())), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
keys, err := req.Storage.List("policy/")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(keys) == 0 {
|
||||||
|
return nil, fmt.Errorf("No roles registered for IP '%s'", ip.String())
|
||||||
|
}
|
||||||
|
|
||||||
var matchingRoles []string
|
var matchingRoles []string
|
||||||
for _, item := range keys {
|
for _, item := range keys {
|
||||||
if contains, _ := containsIP(req.Storage, item, ip); contains {
|
if contains, _ := containsIP(req.Storage, item, ip.String()); contains {
|
||||||
matchingRoles = append(matchingRoles, item)
|
matchingRoles = append(matchingRoles, item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log.Printf("Vishal: req.Path: %#v \n Keys:%#v\n", req.Path, keys)
|
|
||||||
return &logical.Response{
|
return &logical.Response{
|
||||||
Data: map[string]interface{}{
|
Data: map[string]interface{}{
|
||||||
"roles": matchingRoles,
|
"roles": matchingRoles,
|
||||||
@@ -51,6 +58,9 @@ func (b *backend) pathLookupWrite(req *logical.Request, d *framework.FieldData)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func containsIP(s logical.Storage, roleName string, ip string) (bool, error) {
|
func containsIP(s logical.Storage, roleName string, ip string) (bool, error) {
|
||||||
|
if roleName == "" || ip == "" {
|
||||||
|
return false, fmt.Errorf("invalid parameters")
|
||||||
|
}
|
||||||
roleEntry, err := s.Get("policy/" + roleName)
|
roleEntry, err := s.Get("policy/" + roleName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Errorf("error retrieving role '%s'", err)
|
return false, fmt.Errorf("error retrieving role '%s'", err)
|
||||||
@@ -64,8 +74,10 @@ func containsIP(s logical.Storage, roleName string, ip string) (bool, error) {
|
|||||||
}
|
}
|
||||||
ipMatched := false
|
ipMatched := false
|
||||||
for _, item := range strings.Split(role.CIDR, ",") {
|
for _, item := range strings.Split(role.CIDR, ",") {
|
||||||
log.Println(item)
|
_, cidrIPNet, err := net.ParseCIDR(item)
|
||||||
_, cidrIPNet, _ := net.ParseCIDR(item)
|
if err != nil {
|
||||||
|
return false, fmt.Errorf(fmt.Sprintf("Invalid cidr entry '%s'", item))
|
||||||
|
}
|
||||||
ipMatched = cidrIPNet.Contains(net.ParseIP(ip))
|
ipMatched = cidrIPNet.Contains(net.ParseIP(ip))
|
||||||
if ipMatched {
|
if ipMatched {
|
||||||
break
|
break
|
||||||
@@ -75,9 +87,10 @@ func containsIP(s logical.Storage, roleName string, ip string) (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const pathLookupSyn = `
|
const pathLookupSyn = `
|
||||||
pathLookupSyn
|
Lists 'roles' that can be used to create a dynamic key.
|
||||||
`
|
`
|
||||||
|
|
||||||
const pathLookupDesc = `
|
const pathLookupDesc = `
|
||||||
pathLoookupDesc
|
CIDR blocks will be associated with multiple 'roles'.
|
||||||
|
This endpoint lists all the 'roles' that are associated with the supplied IP address.
|
||||||
`
|
`
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -13,7 +12,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func pathRoleCreate(b *backend) *framework.Path {
|
func pathRoleCreate(b *backend) *framework.Path {
|
||||||
log.Printf("Vishal: ssh.sshConnect\n")
|
|
||||||
return &framework.Path{
|
return &framework.Path{
|
||||||
Pattern: "creds/(?P<name>\\w+)",
|
Pattern: "creds/(?P<name>\\w+)",
|
||||||
Fields: map[string]*framework.FieldSchema{
|
Fields: map[string]*framework.FieldSchema{
|
||||||
@@ -33,19 +31,22 @@ func pathRoleCreate(b *backend) *framework.Path {
|
|||||||
Callbacks: map[logical.Operation]framework.OperationFunc{
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
||||||
logical.WriteOperation: b.pathRoleCreateWrite,
|
logical.WriteOperation: b.pathRoleCreateWrite,
|
||||||
},
|
},
|
||||||
HelpSynopsis: sshConnectHelpSyn,
|
HelpSynopsis: pathRoleCreateHelpSyn,
|
||||||
HelpDescription: sshConnectHelpDesc,
|
HelpDescription: pathRoleCreateHelpDesc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *backend) pathRoleCreateWrite(
|
func (b *backend) pathRoleCreateWrite(
|
||||||
req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||||
log.Printf("Vishal: ssh.pathRoleCreateWrite\n")
|
|
||||||
|
|
||||||
//fetch the parameters
|
|
||||||
roleName := d.Get("name").(string)
|
roleName := d.Get("name").(string)
|
||||||
username := d.Get("username").(string)
|
username := d.Get("username").(string)
|
||||||
ipRaw := d.Get("ip").(string)
|
ipRaw := d.Get("ip").(string)
|
||||||
|
if roleName == "" {
|
||||||
|
return logical.ErrorResponse("Invalid 'name'"), nil
|
||||||
|
}
|
||||||
|
if ipRaw == "" {
|
||||||
|
return logical.ErrorResponse("Invalid 'ip'"), nil
|
||||||
|
}
|
||||||
|
|
||||||
//find the role to be used for installing dynamic key
|
//find the role to be used for installing dynamic key
|
||||||
rolePath := "policy/" + roleName
|
rolePath := "policy/" + roleName
|
||||||
@@ -61,6 +62,10 @@ func (b *backend) pathRoleCreateWrite(
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if username == "" {
|
||||||
|
username = role.DefaultUser
|
||||||
|
}
|
||||||
|
|
||||||
//validate the IP address
|
//validate the IP address
|
||||||
ipAddr := net.ParseIP(ipRaw)
|
ipAddr := net.ParseIP(ipRaw)
|
||||||
if ipAddr == nil {
|
if ipAddr == nil {
|
||||||
@@ -70,8 +75,10 @@ func (b *backend) pathRoleCreateWrite(
|
|||||||
|
|
||||||
ipMatched := false
|
ipMatched := false
|
||||||
for _, item := range strings.Split(role.CIDR, ",") {
|
for _, item := range strings.Split(role.CIDR, ",") {
|
||||||
log.Println(item)
|
_, cidrIPNet, err := net.ParseCIDR(item)
|
||||||
_, cidrIPNet, _ := net.ParseCIDR(item)
|
if err != nil {
|
||||||
|
return logical.ErrorResponse(fmt.Sprintf("Invalid cidr entry '%s'", item)), nil
|
||||||
|
}
|
||||||
ipMatched = cidrIPNet.Contains(ipAddr)
|
ipMatched = cidrIPNet.Contains(ipAddr)
|
||||||
if ipMatched {
|
if ipMatched {
|
||||||
break
|
break
|
||||||
@@ -96,40 +103,30 @@ func (b *backend) pathRoleCreateWrite(
|
|||||||
hostKeyFileName := "./vault_ssh_" + username + "_" + ip + "_shared.pem"
|
hostKeyFileName := "./vault_ssh_" + username + "_" + ip + "_shared.pem"
|
||||||
err = ioutil.WriteFile(hostKeyFileName, []byte(hostKey.Key), 0600)
|
err = ioutil.WriteFile(hostKeyFileName, []byte(hostKey.Key), 0600)
|
||||||
|
|
||||||
otkPrivateKeyFileName := "vault_ssh_" + username + "_" + ip + "_otk.pem"
|
dynamicPrivateKeyFileName := "vault_ssh_" + username + "_" + ip + "_otk.pem"
|
||||||
otkPublicKeyFileName := otkPrivateKeyFileName + ".pub"
|
dynamicPublicKeyFileName := dynamicPrivateKeyFileName + ".pub"
|
||||||
|
|
||||||
//commands to be run on vault server
|
//delete the temporary files if they are already present
|
||||||
removeFile(otkPrivateKeyFileName)
|
err = removeFile(dynamicPrivateKeyFileName)
|
||||||
removeFile(otkPublicKeyFileName)
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf(fmt.Sprintf("Error removing dynamic private key file: '%s'", err))
|
||||||
|
}
|
||||||
|
err = removeFile(dynamicPublicKeyFileName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf(fmt.Sprintf("Error removing dynamic private key file: '%s'", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
//generate RSA key pair
|
||||||
dynamicPublicKey, dynamicPrivateKey, _ := generateRSAKeys()
|
dynamicPublicKey, dynamicPrivateKey, _ := generateRSAKeys()
|
||||||
ioutil.WriteFile(otkPrivateKeyFileName, []byte(dynamicPrivateKey), 0600)
|
|
||||||
ioutil.WriteFile(otkPublicKeyFileName, []byte(dynamicPublicKey), 0644)
|
|
||||||
|
|
||||||
uploadFileScp(otkPublicKeyFileName, username, ip, hostKey.Key)
|
//save the public key pair to a file
|
||||||
/*
|
ioutil.WriteFile(dynamicPublicKeyFileName, []byte(dynamicPublicKey), 0644)
|
||||||
otkPublicKeyFileNameBase := filepath.Base(otkPublicKeyFileName)
|
|
||||||
otkPublicKeyFile, _ := os.Open(otkPublicKeyFileName)
|
//send the public key to target machine
|
||||||
otkPublicKeyStat, err := otkPublicKeyFile.Stat()
|
err = uploadFileScp(dynamicPublicKeyFileName, username, ip, hostKey.Key)
|
||||||
if os.IsNotExist(err) {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("File does not exist")
|
return nil, err
|
||||||
}
|
}
|
||||||
session := createSSHPublicKeysSession(username, ip, hostKey.Key)
|
|
||||||
if session == nil {
|
|
||||||
return nil, fmt.Errorf("Invalid session object")
|
|
||||||
}
|
|
||||||
go func() {
|
|
||||||
w, _ := session.StdinPipe()
|
|
||||||
fmt.Fprintln(w, "C0644", otkPublicKeyStat.Size(), otkPublicKeyFileNameBase)
|
|
||||||
io.Copy(w, otkPublicKeyFile)
|
|
||||||
fmt.Fprint(w, "\x00")
|
|
||||||
w.Close()
|
|
||||||
}()
|
|
||||||
if err := session.Run(fmt.Sprintf("scp -vt %s", otkPublicKeyFileNameBase)); err != nil {
|
|
||||||
panic("Failed to run: " + err.Error())
|
|
||||||
}
|
|
||||||
session.Close()
|
|
||||||
*/
|
|
||||||
|
|
||||||
//connect to target machine
|
//connect to target machine
|
||||||
session, err := createSSHPublicKeysSession(username, ip, hostKey.Key)
|
session, err := createSSHPublicKeysSession(username, ip, hostKey.Key)
|
||||||
@@ -142,14 +139,14 @@ func (b *backend) pathRoleCreateWrite(
|
|||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
session.Stdout = &buf
|
session.Stdout = &buf
|
||||||
|
|
||||||
authKeysFileName := "~/.ssh/authorized_keys"
|
authKeysFileName := "/home/" + username + "/.ssh/authorized_keys"
|
||||||
tempKeysFileName := "~/temp_authorized_keys"
|
tempKeysFileName := "/home/" + username + "/temp_authorized_keys"
|
||||||
|
|
||||||
//commands to be run on target machine
|
//commands to be run on target machine
|
||||||
grepCmd := "grep -vFf " + otkPublicKeyFileName + " " + authKeysFileName + " > " + tempKeysFileName + ";"
|
grepCmd := "grep -vFf " + dynamicPublicKeyFileName + " " + authKeysFileName + " > " + tempKeysFileName + ";"
|
||||||
catCmdRemoveDuplicate := "cat " + tempKeysFileName + " > " + authKeysFileName + ";"
|
catCmdRemoveDuplicate := "cat " + tempKeysFileName + " > " + authKeysFileName + ";"
|
||||||
catCmdAppendNew := "cat " + otkPublicKeyFileName + " >> " + authKeysFileName + ";"
|
catCmdAppendNew := "cat " + dynamicPublicKeyFileName + " >> " + authKeysFileName + ";"
|
||||||
removeCmd := "rm -f " + tempKeysFileName + " " + otkPublicKeyFileName + ";"
|
removeCmd := "rm -f " + tempKeysFileName + " " + dynamicPublicKeyFileName + ";"
|
||||||
remoteCmdString := strings.Join([]string{
|
remoteCmdString := strings.Join([]string{
|
||||||
grepCmd,
|
grepCmd,
|
||||||
catCmdRemoveDuplicate,
|
catCmdRemoveDuplicate,
|
||||||
@@ -178,10 +175,17 @@ type sshCIDR struct {
|
|||||||
CIDR []string
|
CIDR []string
|
||||||
}
|
}
|
||||||
|
|
||||||
const sshConnectHelpSyn = `
|
const pathRoleCreateHelpSyn = `
|
||||||
sshConnectionHelpSyn
|
Creates a dynamic key for the target machine.
|
||||||
`
|
`
|
||||||
|
|
||||||
const sshConnectHelpDesc = `
|
const pathRoleCreateHelpDesc = `
|
||||||
rshConnectionHelpDesc
|
This path will generates a new key for establishing SSH session with
|
||||||
|
target host. Previously registered shared key belonging to target
|
||||||
|
infrastructure will be used to install the new key at the target. If
|
||||||
|
this backend is mounted at 'ssh', then "ssh/creds/role" would generate
|
||||||
|
a dynamic key for 'web' role.
|
||||||
|
|
||||||
|
The dynamic keys will have a lease associated with them. The access
|
||||||
|
keys can be revoked by using the lease ID.
|
||||||
`
|
`
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
package ssh
|
package ssh
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/vault/logical"
|
"github.com/hashicorp/vault/logical"
|
||||||
"github.com/hashicorp/vault/logical/framework"
|
"github.com/hashicorp/vault/logical/framework"
|
||||||
)
|
)
|
||||||
|
|
||||||
func pathRoles(b *backend) *framework.Path {
|
func pathRoles(b *backend) *framework.Path {
|
||||||
log.Printf("Vishal: ssh.pathRoles\n")
|
|
||||||
return &framework.Path{
|
return &framework.Path{
|
||||||
Pattern: "roles/(?P<name>\\w+)",
|
Pattern: "roles/(?P<name>\\w+)",
|
||||||
Fields: map[string]*framework.FieldSchema{
|
Fields: map[string]*framework.FieldSchema{
|
||||||
@@ -46,18 +47,38 @@ func pathRoles(b *backend) *framework.Path {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *backend) pathRoleWrite(req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
func (b *backend) pathRoleWrite(req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||||
log.Printf("Vishal: ssh.pathRoleWrite\n")
|
|
||||||
|
|
||||||
roleName := d.Get("name").(string)
|
roleName := d.Get("name").(string)
|
||||||
keyName := d.Get("key").(string)
|
keyName := d.Get("key").(string)
|
||||||
adminUser := d.Get("admin_user").(string)
|
adminUser := d.Get("admin_user").(string)
|
||||||
defaultUser := d.Get("default_user").(string)
|
defaultUser := d.Get("default_user").(string)
|
||||||
cidr := d.Get("cidr").(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)
|
//input validations
|
||||||
|
if roleName == "" {
|
||||||
|
return logical.ErrorResponse("Invalid 'roleName'"), nil
|
||||||
|
}
|
||||||
|
if keyName == "" {
|
||||||
|
return logical.ErrorResponse("Invalid 'key'"), nil
|
||||||
|
}
|
||||||
|
if adminUser == "" {
|
||||||
|
return logical.ErrorResponse("Invalid 'admin_user'"), nil
|
||||||
|
}
|
||||||
|
if cidr == "" {
|
||||||
|
return logical.ErrorResponse("Invalid 'cidr'"), nil
|
||||||
|
}
|
||||||
|
for _, item := range strings.Split(cidr, ",") {
|
||||||
|
_, _, err := net.ParseCIDR(item)
|
||||||
|
if err != nil {
|
||||||
|
return logical.ErrorResponse(fmt.Sprintf("Invalid cidr entry '%s'", item)), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rolePath := "policy/" + roleName
|
rolePath := "policy/" + roleName
|
||||||
|
|
||||||
|
if defaultUser == "" {
|
||||||
|
defaultUser = adminUser
|
||||||
|
}
|
||||||
|
|
||||||
entry, err := logical.StorageEntryJSON(rolePath, sshRole{
|
entry, err := logical.StorageEntryJSON(rolePath, sshRole{
|
||||||
KeyName: keyName,
|
KeyName: keyName,
|
||||||
AdminUser: adminUser,
|
AdminUser: adminUser,
|
||||||
@@ -69,7 +90,6 @@ func (b *backend) pathRoleWrite(req *logical.Request, d *framework.FieldData) (*
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("Vishal: entryJSON:%s\n", entry.Value)
|
|
||||||
if err := req.Storage.Put(entry); err != nil {
|
if err := req.Storage.Put(entry); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -78,7 +98,6 @@ func (b *backend) pathRoleWrite(req *logical.Request, d *framework.FieldData) (*
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *backend) pathRoleRead(req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
func (b *backend) pathRoleRead(req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||||
log.Printf("Vishal: ssh.pathRoleRead\n")
|
|
||||||
roleName := d.Get("name").(string)
|
roleName := d.Get("name").(string)
|
||||||
rolePath := "policy/" + roleName
|
rolePath := "policy/" + roleName
|
||||||
entry, err := req.Storage.Get(rolePath)
|
entry, err := req.Storage.Get(rolePath)
|
||||||
@@ -96,7 +115,6 @@ func (b *backend) pathRoleRead(req *logical.Request, d *framework.FieldData) (*l
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *backend) pathRoleDelete(req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
func (b *backend) pathRoleDelete(req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||||
log.Printf("Vishal: ssh.pathRoleDelete\n")
|
|
||||||
roleName := d.Get("name").(string)
|
roleName := d.Get("name").(string)
|
||||||
rolePath := "policy/" + roleName
|
rolePath := "policy/" + roleName
|
||||||
err := req.Storage.Delete(rolePath)
|
err := req.Storage.Delete(rolePath)
|
||||||
@@ -114,9 +132,13 @@ type sshRole struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const pathRoleHelpSyn = `
|
const pathRoleHelpSyn = `
|
||||||
Manage the roles that can be created with this backend.
|
Manage the 'roles' that can be created with this backend.
|
||||||
`
|
`
|
||||||
|
|
||||||
const pathRoleHelpDesc = `
|
const pathRoleHelpDesc = `
|
||||||
This path lets you manage the roles that can be created with this backend.
|
This path allows you to manage the roles that are used to create dynamic keys.
|
||||||
|
These roles will be having privileged access to all the hosts mentioned by CIDR blocks.
|
||||||
|
For example, if the backend is mounted at "ssh" and the role is created at "ssh/roles/web", then a user could request for a new key at "ssh/creds/web" for the supplied username and IP address.
|
||||||
|
|
||||||
|
The 'cidr' field takes comma seperated CIDR blocks. The 'admin_user' should have root access in all the hosts represented by the 'cidr' field. When the user requests key for an IP, the key will be installed for the user mentioned by 'default_user' field. The 'key' field takes a named key which can be configured by 'ssh/keys/' endpoint.
|
||||||
`
|
`
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
package ssh
|
package ssh
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -15,7 +13,6 @@ import (
|
|||||||
const SecretOneTimeKeyType = "secret_one_type_key_type"
|
const SecretOneTimeKeyType = "secret_one_type_key_type"
|
||||||
|
|
||||||
func secretSshKey(b *backend) *framework.Secret {
|
func secretSshKey(b *backend) *framework.Secret {
|
||||||
log.Printf("Vishal: ssh.secretPrivateKey\n")
|
|
||||||
return &framework.Secret{
|
return &framework.Secret{
|
||||||
Type: SecretOneTimeKeyType,
|
Type: SecretOneTimeKeyType,
|
||||||
Fields: map[string]*framework.FieldSchema{
|
Fields: map[string]*framework.FieldSchema{
|
||||||
@@ -28,15 +25,14 @@ func secretSshKey(b *backend) *framework.Secret {
|
|||||||
Description: "ip address of host",
|
Description: "ip address of host",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
DefaultDuration: 10 * time.Second, //TODO: change this
|
DefaultDuration: 5 * time.Second, //TODO: change this
|
||||||
DefaultGracePeriod: 10 * time.Second, //TODO: change this
|
DefaultGracePeriod: 1 * time.Second, //TODO: change this
|
||||||
Renew: b.secretSshKeyRenew,
|
Renew: b.secretSshKeyRenew,
|
||||||
Revoke: b.secretSshKeyRevoke,
|
Revoke: b.secretSshKeyRevoke,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *backend) secretSshKeyRenew(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)
|
lease, err := b.Lease(req.Storage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -49,8 +45,6 @@ func (b *backend) secretSshKeyRenew(req *logical.Request, d *framework.FieldData
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *backend) secretSshKeyRevoke(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 req: %#v\n", req)
|
|
||||||
//fetch the values from secret
|
|
||||||
usernameRaw, ok := req.Secret.InternalData["username"]
|
usernameRaw, ok := req.Secret.InternalData["username"]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("secret is missing internal data")
|
return nil, fmt.Errorf("secret is missing internal data")
|
||||||
@@ -83,7 +77,6 @@ func (b *backend) secretSshKeyRevoke(req *logical.Request, d *framework.FieldDat
|
|||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("secret is missing internal data")
|
return nil, fmt.Errorf("secret is missing internal data")
|
||||||
}
|
}
|
||||||
log.Printf("Vishal: username:%s ip:%s keyName:%s\n", username, ip, hostKeyName)
|
|
||||||
|
|
||||||
//fetch the host key using the key name
|
//fetch the host key using the key name
|
||||||
hostKeyPath := "keys/" + hostKeyName
|
hostKeyPath := "keys/" + hostKeyName
|
||||||
@@ -101,24 +94,23 @@ func (b *backend) secretSshKeyRevoke(req *logical.Request, d *framework.FieldDat
|
|||||||
err = ioutil.WriteFile(hostKeyFileName, []byte(hostKey.Key), 0400)
|
err = ioutil.WriteFile(hostKeyFileName, []byte(hostKey.Key), 0400)
|
||||||
|
|
||||||
//write dynamicPublicKey to file and use it as argument to scp command
|
//write dynamicPublicKey to file and use it as argument to scp command
|
||||||
otkPrivateKeyFileName := "vault_ssh_" + username + "_" + ip + "_otk.pem"
|
dynamicPrivateKeyFileName := "vault_ssh_" + username + "_" + ip + "_otk.pem"
|
||||||
otkPublicKeyFileName := otkPrivateKeyFileName + ".pub"
|
dynamicPublicKeyFileName := dynamicPrivateKeyFileName + ".pub"
|
||||||
err = ioutil.WriteFile(otkPublicKeyFileName, []byte(dynamicPublicKey), 0400)
|
err = ioutil.WriteFile(dynamicPublicKeyFileName, []byte(dynamicPublicKey), 0400)
|
||||||
|
|
||||||
//transfer the dynamic public key to target machine and use it to remove the entry from authorized_keys file
|
//transfer the dynamic public key to target machine and use it to remove the entry from authorized_keys file
|
||||||
scpCmd := "scp -i " + hostKeyFileName + " " + otkPublicKeyFileName + " " + username + "@" + ip + ":~;"
|
err = uploadFileScp(dynamicPublicKeyFileName, username, ip, hostKey.Key)
|
||||||
err = exec_command(scpCmd)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Errorf("Running command scp failed " + err.Error())
|
return nil, fmt.Errorf("Public key transfer failed: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
authKeysFileName := "~/.ssh/authorized_keys"
|
authKeysFileName := "~/.ssh/authorized_keys"
|
||||||
tempKeysFileName := "~/temp_authorized_keys"
|
tempKeysFileName := "~/temp_authorized_keys"
|
||||||
|
|
||||||
//commands to be run on target machine
|
//commands to be run on target machine
|
||||||
grepCmd := "grep -vFf " + otkPublicKeyFileName + " " + authKeysFileName + " > " + tempKeysFileName + ";"
|
grepCmd := "grep -vFf " + dynamicPublicKeyFileName + " " + authKeysFileName + " > " + tempKeysFileName + ";"
|
||||||
catCmdRemoveDuplicate := "cat " + tempKeysFileName + " > " + authKeysFileName + ";"
|
catCmdRemoveDuplicate := "cat " + tempKeysFileName + " > " + authKeysFileName + ";"
|
||||||
rmCmd := "rm -f " + tempKeysFileName + " " + otkPublicKeyFileName + ";"
|
rmCmd := "rm -f " + tempKeysFileName + " " + dynamicPublicKeyFileName + ";"
|
||||||
remoteCmdString := strings.Join([]string{
|
remoteCmdString := strings.Join([]string{
|
||||||
grepCmd,
|
grepCmd,
|
||||||
catCmdRemoveDuplicate,
|
catCmdRemoveDuplicate,
|
||||||
@@ -134,12 +126,10 @@ func (b *backend) secretSshKeyRevoke(req *logical.Request, d *framework.FieldDat
|
|||||||
return nil, fmt.Errorf("Invalid session object")
|
return nil, fmt.Errorf("Invalid session object")
|
||||||
}
|
}
|
||||||
|
|
||||||
var buf bytes.Buffer
|
//run the commands in target machine
|
||||||
session.Stdout = &buf
|
|
||||||
if err := session.Run(remoteCmdString); err != nil {
|
if err := session.Run(remoteCmdString); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
session.Close()
|
|
||||||
fmt.Println(buf.String())
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import (
|
|||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -16,6 +15,11 @@ import (
|
|||||||
"golang.org/x/crypto/ssh"
|
"golang.org/x/crypto/ssh"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
Executes the command represented by the input.
|
||||||
|
Multiple commands can be run by concatinating strings with ';'.
|
||||||
|
Currently, it is supported only for linux platforms and user bash shell.
|
||||||
|
*/
|
||||||
func exec_command(cmdString string) error {
|
func exec_command(cmdString string) error {
|
||||||
cmd := exec.Command("/bin/bash", "-c", cmdString)
|
cmd := exec.Command("/bin/bash", "-c", cmdString)
|
||||||
if _, err := cmd.Output(); err != nil {
|
if _, err := cmd.Output(); err != nil {
|
||||||
@@ -24,11 +28,16 @@ func exec_command(cmdString string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Transfers the file to the target machine by establishing an SSH session with the target.
|
||||||
|
Uses the public key authentication method and hence the parameter 'key' takes in the private key.
|
||||||
|
The fileName parameter takes an absolute path.
|
||||||
|
*/
|
||||||
func uploadFileScp(fileName, username, ip, key string) error {
|
func uploadFileScp(fileName, username, ip, key string) error {
|
||||||
nameBase := filepath.Base(fileName)
|
nameBase := filepath.Base(fileName)
|
||||||
file, err := os.Open(fileName)
|
file, err := os.Open(fileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Unable to open file")
|
return err
|
||||||
}
|
}
|
||||||
stat, err := file.Stat()
|
stat, err := file.Stat()
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
@@ -36,7 +45,7 @@ func uploadFileScp(fileName, username, ip, key string) error {
|
|||||||
}
|
}
|
||||||
session, err := createSSHPublicKeysSession(username, ip, key)
|
session, err := createSSHPublicKeysSession(username, ip, key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Unable to create SSH Session using public keys: %s", err)
|
return err
|
||||||
}
|
}
|
||||||
if session == nil {
|
if session == nil {
|
||||||
return fmt.Errorf("Invalid session object")
|
return fmt.Errorf("Invalid session object")
|
||||||
@@ -50,12 +59,19 @@ func uploadFileScp(fileName, username, ip, key string) error {
|
|||||||
w.Close()
|
w.Close()
|
||||||
}()
|
}()
|
||||||
if err := session.Run(fmt.Sprintf("scp -vt %s", nameBase)); err != nil {
|
if err := session.Run(fmt.Sprintf("scp -vt %s", nameBase)); err != nil {
|
||||||
return fmt.Errorf("Failed to run: %s", err)
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func createSSHPublicKeysSession(username string, ipAddr string, hostKey string) (*ssh.Session, error) {
|
/*
|
||||||
|
Creates a SSH session object which can be used to run commands in the target machine.
|
||||||
|
The session will use public key authentication method with port 22.
|
||||||
|
*/
|
||||||
|
func createSSHPublicKeysSession(username, ipAddr, hostKey string) (*ssh.Session, error) {
|
||||||
|
if username == "" || ipAddr == "" || hostKey == "" {
|
||||||
|
return nil, fmt.Errorf("Invalid parameters")
|
||||||
|
}
|
||||||
signer, err := ssh.ParsePrivateKey([]byte(hostKey))
|
signer, err := ssh.ParsePrivateKey([]byte(hostKey))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Parsing Private Key failed: %s", err)
|
return nil, fmt.Errorf("Parsing Private Key failed: %s", err)
|
||||||
@@ -70,7 +86,7 @@ func createSSHPublicKeysSession(username string, ipAddr string, hostKey string)
|
|||||||
|
|
||||||
client, err := ssh.Dial("tcp", ipAddr+":22", config)
|
client, err := ssh.Dial("tcp", ipAddr+":22", config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Dial Failed: %s", err)
|
return nil, err
|
||||||
}
|
}
|
||||||
if client == nil {
|
if client == nil {
|
||||||
return nil, fmt.Errorf("Invalid client object: %s", err)
|
return nil, fmt.Errorf("Invalid client object: %s", err)
|
||||||
@@ -78,35 +94,45 @@ func createSSHPublicKeysSession(username string, ipAddr string, hostKey string)
|
|||||||
|
|
||||||
session, err := client.NewSession()
|
session, err := client.NewSession()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Creating new client session failed: %s", err)
|
return nil, err
|
||||||
}
|
}
|
||||||
return session, nil
|
return session, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeFile(fileName string) {
|
/*
|
||||||
|
Deletes the file in the current directory.
|
||||||
|
The parameter is just the name of the file and not a path.
|
||||||
|
*/
|
||||||
|
func removeFile(fileName string) error {
|
||||||
|
if fileName == "" {
|
||||||
|
return fmt.Errorf("Invalid file name")
|
||||||
|
}
|
||||||
wd, err := os.Getwd()
|
wd, err := os.Getwd()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error fetching working directory:%s", err)
|
return err
|
||||||
return
|
|
||||||
}
|
}
|
||||||
absFileName := wd + "/" + fileName
|
absFileName := wd + "/" + fileName
|
||||||
|
|
||||||
if _, err := os.Stat(absFileName); err == nil {
|
if _, err := os.Stat(absFileName); err == nil {
|
||||||
err := os.Remove(absFileName)
|
err := os.Remove(absFileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf(fmt.Sprintf("Failed: %s", err))
|
return err
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateRSAKeys() (string, string, error) {
|
/*
|
||||||
|
Creates a new RSA key pair with key length of 2048.
|
||||||
|
The private key will be of pem format and the public key will be of OpenSSH format.
|
||||||
|
*/
|
||||||
|
func generateRSAKeys() (publicKeyRsa string, privateKeyRsa string, err error) {
|
||||||
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
|
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", fmt.Errorf("error generating RSA key-pair: %s", err)
|
return "", "", fmt.Errorf("error generating RSA key-pair: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
privateKeyRsa := string(pem.EncodeToMemory(&pem.Block{
|
privateKeyRsa = string(pem.EncodeToMemory(&pem.Block{
|
||||||
Type: "RSA PRIVATE KEY",
|
Type: "RSA PRIVATE KEY",
|
||||||
Bytes: x509.MarshalPKCS1PrivateKey(privateKey),
|
Bytes: x509.MarshalPKCS1PrivateKey(privateKey),
|
||||||
}))
|
}))
|
||||||
@@ -115,10 +141,6 @@ func generateRSAKeys() (string, string, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", fmt.Errorf("error generating RSA key-pair: %s", err)
|
return "", "", fmt.Errorf("error generating RSA key-pair: %s", err)
|
||||||
}
|
}
|
||||||
publicKeyRsa := "ssh-rsa " + base64.StdEncoding.EncodeToString(sshPublicKey.Marshal())
|
publicKeyRsa = "ssh-rsa " + base64.StdEncoding.EncodeToString(sshPublicKey.Marshal())
|
||||||
|
return
|
||||||
//ioutil.WriteFile("testkey.pem", []byte(privateKeyRsa), 0600)
|
|
||||||
//ioutil.WriteFile("testkey.pub", []byte(publicKeyRsa), 0600)
|
|
||||||
|
|
||||||
return publicKeyRsa, privateKeyRsa, nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package command
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -19,7 +18,6 @@ type WriteCommand struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *WriteCommand) Run(args []string) int {
|
func (c *WriteCommand) Run(args []string) int {
|
||||||
log.Printf("Vishal: writeCommand\n")
|
|
||||||
var format string
|
var format string
|
||||||
var force bool
|
var force bool
|
||||||
flags := c.Meta.FlagSet("write", FlagSetDefault)
|
flags := c.Meta.FlagSet("write", FlagSetDefault)
|
||||||
@@ -57,7 +55,6 @@ func (c *WriteCommand) Run(args []string) int {
|
|||||||
return 2
|
return 2
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("Vishal: write Path: %#v\n", path)
|
|
||||||
secret, err := client.Logical().Write(path, data)
|
secret, err := client.Logical().Write(path, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Ui.Error(fmt.Sprintf(
|
c.Ui.Error(fmt.Sprintf(
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package http
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -22,7 +21,6 @@ const AuthHeaderName = "X-Vault-Token"
|
|||||||
// its own to mount the Vault API within another web server.
|
// its own to mount the Vault API within another web server.
|
||||||
func Handler(core *vault.Core) http.Handler {
|
func Handler(core *vault.Core) http.Handler {
|
||||||
// Create the muxer to handle the actual endpoints
|
// Create the muxer to handle the actual endpoints
|
||||||
log.Printf("Vishal: http.handler.Handler\n")
|
|
||||||
mux := http.NewServeMux()
|
mux := http.NewServeMux()
|
||||||
mux.Handle("/v1/sys/init", handleSysInit(core))
|
mux.Handle("/v1/sys/init", handleSysInit(core))
|
||||||
mux.Handle("/v1/sys/seal-status", handleSysSealStatus(core))
|
mux.Handle("/v1/sys/seal-status", handleSysSealStatus(core))
|
||||||
@@ -77,7 +75,6 @@ func parseRequest(r *http.Request, out interface{}) error {
|
|||||||
// request is a helper to perform a request and properly exit in the
|
// request is a helper to perform a request and properly exit in the
|
||||||
// case of an error.
|
// case of an error.
|
||||||
func request(core *vault.Core, w http.ResponseWriter, rawReq *http.Request, r *logical.Request) (*logical.Response, bool) {
|
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)
|
resp, err := core.HandleRequest(r)
|
||||||
if err == vault.ErrStandby {
|
if err == vault.ErrStandby {
|
||||||
respondStandby(core, w, rawReq.URL)
|
respondStandby(core, w, rawReq.URL)
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package http
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
"log"
|
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -14,7 +13,6 @@ import (
|
|||||||
|
|
||||||
func handleLogical(core *vault.Core) http.Handler {
|
func handleLogical(core *vault.Core) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
log.Printf("Vishal: handleLogical called\n")
|
|
||||||
// Determine the path...
|
// Determine the path...
|
||||||
if !strings.HasPrefix(r.URL.Path, "/v1/") {
|
if !strings.HasPrefix(r.URL.Path, "/v1/") {
|
||||||
respondError(w, http.StatusNotFound, nil)
|
respondError(w, http.StatusNotFound, nil)
|
||||||
@@ -59,7 +57,6 @@ func handleLogical(core *vault.Core) http.Handler {
|
|||||||
// Make the internal request. We attach the connection info
|
// Make the internal request. We attach the connection info
|
||||||
// as well in case this is an authentication request that requires
|
// as well in case this is an authentication request that requires
|
||||||
// it. Vault core handles stripping this if we need to.
|
// 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{
|
resp, ok := request(core, w, r, requestAuth(r, &logical.Request{
|
||||||
Operation: op,
|
Operation: op,
|
||||||
Path: path,
|
Path: path,
|
||||||
|
|||||||
@@ -345,7 +345,6 @@ func (c *Core) Shutdown() error {
|
|||||||
|
|
||||||
// HandleRequest is used to handle a new incoming request
|
// HandleRequest is used to handle a new incoming request
|
||||||
func (c *Core) HandleRequest(req *logical.Request) (resp *logical.Response, err error) {
|
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()
|
c.stateLock.RLock()
|
||||||
defer c.stateLock.RUnlock()
|
defer c.stateLock.RUnlock()
|
||||||
if c.sealed {
|
if c.sealed {
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import (
|
|||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@@ -150,7 +149,6 @@ func (r *Router) Route(req *logical.Request) (*logical.Response, error) {
|
|||||||
r.l.RLock()
|
r.l.RLock()
|
||||||
mount, raw, ok := r.root.LongestPrefix(req.Path)
|
mount, raw, ok := r.root.LongestPrefix(req.Path)
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Printf("Vishal: vault.router.Route: here\n")
|
|
||||||
// Re-check for a backend by appending a slash. This lets "foo" mean
|
// 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.
|
// "foo/" at the root level which is almost always what we want.
|
||||||
req.Path += "/"
|
req.Path += "/"
|
||||||
|
|||||||
Reference in New Issue
Block a user