Initial import
This commit is contained in:
89
vault.go
Normal file
89
vault.go
Normal file
@@ -0,0 +1,89 @@
|
||||
package secret
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
vault "github.com/hashicorp/vault/api"
|
||||
)
|
||||
|
||||
type vaultProvider struct{}
|
||||
|
||||
// Vault provider uses Hashicorp Vault for secrets storage.
|
||||
//
|
||||
// The secretKey is used to
|
||||
func Vault() Provider {
|
||||
return vaultProvider{}
|
||||
}
|
||||
|
||||
func (p vaultProvider) GetSecret(key string) (value []byte, err error) {
|
||||
var (
|
||||
config = vault.DefaultConfig()
|
||||
client *vault.Client
|
||||
)
|
||||
if client, err = vault.NewClient(config); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var mounts map[string]*vault.MountOutput
|
||||
if mounts, err = client.Sys().ListMounts(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
mount *vault.MountOutput
|
||||
location string
|
||||
)
|
||||
if mount, location, err = p.split(key, mounts); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
switch mount.Type {
|
||||
case "generic", "kv":
|
||||
// Supported
|
||||
default:
|
||||
return nil, fmt.Errorf("secret: mount type %q is not supported", mount.Type)
|
||||
}
|
||||
|
||||
var secret *vault.Secret
|
||||
if secret, err = client.Logical().Read(location); err != nil {
|
||||
return
|
||||
} else if secret == nil || len(secret.Data) == 0 {
|
||||
return nil, NotFound{Key: key}
|
||||
}
|
||||
|
||||
data, ok := secret.Data["data"].(map[string]interface{})
|
||||
if !ok {
|
||||
return nil, NotFound{Key: key}
|
||||
}
|
||||
|
||||
if len(data) == 1 {
|
||||
for _, item := range data {
|
||||
switch data := item.(type) {
|
||||
case []byte:
|
||||
return data, nil
|
||||
case string:
|
||||
return []byte(data), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("secret: unexpected return type %T", data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil, AmbiguousKey{Key: key}
|
||||
}
|
||||
|
||||
func (p vaultProvider) split(key string, mounts map[string]*vault.MountOutput) (mount *vault.MountOutput, location string, err error) {
|
||||
location = strings.TrimPrefix(key, "/")
|
||||
|
||||
var tree string
|
||||
for tree, mount = range mounts {
|
||||
if strings.HasPrefix(location, tree) {
|
||||
if mount.Type == "kv" && mount.Options["version"] == "2" {
|
||||
location = tree + "data/" + location[len(tree):]
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
return nil, "", fmt.Errorf("secret: no Vault mount found for secret path %q", key)
|
||||
}
|
Reference in New Issue
Block a user