mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 18:43:34 +00:00
rebase: update libopenstorage/secrets
libopenstorage has added a new feature that makes it possible to destroy the contents of a key/value in the Hashicorp Vault kv-v2 secrets backend. See-also: https://github.com/libopenstorage/secrets/pull/55 Signed-off-by: Niels de Vos <ndevos@redhat.com>
This commit is contained in:
committed by
mergify[bot]
parent
2782878ea2
commit
d7bcb42481
6
vendor/github.com/libopenstorage/secrets/.travis.yml
generated
vendored
Normal file
6
vendor/github.com/libopenstorage/secrets/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
language: go
|
||||
go:
|
||||
- 1.14.6
|
||||
script:
|
||||
- |
|
||||
make unit-test
|
6
vendor/github.com/libopenstorage/secrets/Makefile
generated
vendored
6
vendor/github.com/libopenstorage/secrets/Makefile
generated
vendored
@ -1,2 +1,8 @@
|
||||
generate:
|
||||
go generate ./...
|
||||
|
||||
unit-test:
|
||||
go test ./...
|
||||
|
||||
ci-test:
|
||||
go test -timeout 1800s -v github.com/libopenstorage/secrets/vault -tags ci
|
||||
|
46
vendor/github.com/libopenstorage/secrets/go.mod
generated
vendored
46
vendor/github.com/libopenstorage/secrets/go.mod
generated
vendored
@ -3,9 +3,53 @@ module github.com/libopenstorage/secrets
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
github.com/Azure/azure-sdk-for-go v36.2.0+incompatible
|
||||
github.com/Azure/go-autorest/autorest v0.9.2
|
||||
github.com/Azure/go-autorest/autorest/adal v0.7.0
|
||||
github.com/Azure/go-autorest/autorest/to v0.3.0
|
||||
github.com/IBM/keyprotect-go-client v0.5.1
|
||||
github.com/aws/aws-sdk-go v1.25.41
|
||||
github.com/golang/mock v1.4.3
|
||||
github.com/hashicorp/go-hclog v0.14.1
|
||||
github.com/hashicorp/vault v1.4.2
|
||||
github.com/hashicorp/vault/api v1.0.5-0.20200902155336-f9d5ce5a171a
|
||||
github.com/pborman/uuid v1.2.0
|
||||
github.com/portworx/dcos-secrets v0.0.0-20180616013705-8e8ec3f66611
|
||||
github.com/portworx/kvdb v0.0.0-20200929023115-b312c7519467
|
||||
github.com/portworx/sched-ops v0.0.0-20200831185134-3e8010dc7056
|
||||
github.com/sirupsen/logrus v1.4.2
|
||||
github.com/stretchr/testify v1.4.0
|
||||
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45
|
||||
google.golang.org/api v0.14.0
|
||||
google.golang.org/protobuf v1.25.0 // indirect
|
||||
)
|
||||
|
||||
replace (
|
||||
github.com/Azure/go-autorest => github.com/Azure/go-autorest v14.2.0+incompatible
|
||||
github.com/hashicorp/consul => github.com/hashicorp/consul v1.5.1
|
||||
github.com/kubernetes-incubator/external-storage => github.com/libopenstorage/external-storage v5.1.0-openstorage+incompatible
|
||||
github.com/kubernetes-incubator/external-storage v0.0.0-00010101000000-000000000000 => github.com/libopenstorage/external-storage v5.1.0-openstorage+incompatible
|
||||
github.com/prometheus/prometheus => github.com/prometheus/prometheus v1.8.2-0.20190424153033-d3245f150225
|
||||
k8s.io/api => k8s.io/api v0.15.11
|
||||
k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.15.11
|
||||
k8s.io/apimachinery => k8s.io/apimachinery v0.15.11
|
||||
k8s.io/apiserver => k8s.io/apiserver v0.15.11
|
||||
k8s.io/cli-runtime => k8s.io/cli-runtime v0.15.11
|
||||
k8s.io/client-go => k8s.io/client-go v0.15.11
|
||||
k8s.io/cloud-provider => k8s.io/cloud-provider v0.15.11
|
||||
k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.15.11
|
||||
k8s.io/code-generator => k8s.io/code-generator v0.15.11
|
||||
k8s.io/component-base => k8s.io/component-base v0.15.11
|
||||
k8s.io/cri-api => k8s.io/cri-api v0.15.11
|
||||
k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.15.11
|
||||
k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.15.11
|
||||
k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.15.11
|
||||
k8s.io/kube-proxy => k8s.io/kube-proxy v0.15.11
|
||||
k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.15.11
|
||||
k8s.io/kubectl => k8s.io/kubectl v0.15.11
|
||||
k8s.io/kubelet => k8s.io/kubelet v0.15.11
|
||||
k8s.io/kubernetes => k8s.io/kubernetes v1.16.0
|
||||
k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.15.11
|
||||
k8s.io/metrics => k8s.io/metrics v0.15.11
|
||||
k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.15.11
|
||||
)
|
||||
|
861
vendor/github.com/libopenstorage/secrets/go.sum
generated
vendored
861
vendor/github.com/libopenstorage/secrets/go.sum
generated
vendored
File diff suppressed because it is too large
Load Diff
26
vendor/github.com/libopenstorage/secrets/secrets.go
generated
vendored
26
vendor/github.com/libopenstorage/secrets/secrets.go
generated
vendored
@ -21,6 +21,8 @@ var (
|
||||
ErrSecretExists = errors.New("Secret Id already exists")
|
||||
// ErrInvalidSecretData is returned when no secret data is found
|
||||
ErrInvalidSecretData = errors.New("Secret Data cannot be empty when CustomSecretData|PublicSecretData flag is set")
|
||||
// ErrInvalidKvdbProvided is returned when an incorrect KVDB implementation is provided for persistence store.
|
||||
ErrInvalidKvdbProvided = errors.New("Invalid kvdb provided. secret store works in conjuction with a kvdb")
|
||||
)
|
||||
|
||||
const (
|
||||
@ -40,20 +42,26 @@ const (
|
||||
)
|
||||
|
||||
const (
|
||||
TypeAWS = "aws-kms"
|
||||
TypeAzure = "azure-kv"
|
||||
TypeDCOS = "dcos"
|
||||
TypeDocker = "docker"
|
||||
TypeGCloud = "gcloud-kms"
|
||||
TypeIBM = "ibm-kp"
|
||||
TypeK8s = "k8s"
|
||||
TypeKVDB = "kvdb"
|
||||
TypeVault = "vault"
|
||||
TypeAWS = "aws-kms"
|
||||
TypeAzure = "azure-kv"
|
||||
TypeDCOS = "dcos"
|
||||
TypeDocker = "docker"
|
||||
TypeGCloud = "gcloud-kms"
|
||||
TypeIBM = "ibm-kp"
|
||||
TypeK8s = "k8s"
|
||||
TypeKVDB = "kvdb"
|
||||
TypeVault = "vault"
|
||||
TypeVaultTransit = "vault-transit"
|
||||
)
|
||||
|
||||
const (
|
||||
// KeyVaultNamespace is a keyContext parameter for vault secrets.
|
||||
KeyVaultNamespace = "vault-namespace"
|
||||
|
||||
// DestroySecret is a keyContext parameter for Vault secrets indicating whether the Secret should be destroyed
|
||||
// This is only valid when Vault's KV Secret Engine is running on version 2 since by default keys are versioned and soft-deleted
|
||||
// Activating this will PERMANENTLY delete all metadata and versions for a key
|
||||
DestroySecret = "destroy-all-secret-versions"
|
||||
)
|
||||
|
||||
// Secrets interface implemented by backend Key Management Systems (KMS)
|
||||
|
192
vendor/github.com/libopenstorage/secrets/vault/utils/utils.go
generated
vendored
Normal file
192
vendor/github.com/libopenstorage/secrets/vault/utils/utils.go
generated
vendored
Normal file
@ -0,0 +1,192 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/go-hclog"
|
||||
"github.com/hashicorp/vault/api"
|
||||
"github.com/hashicorp/vault/command/agent/auth"
|
||||
"github.com/hashicorp/vault/command/agent/auth/kubernetes"
|
||||
)
|
||||
|
||||
const (
|
||||
vaultAddressPrefix = "http"
|
||||
|
||||
// AuthMethodKubernetes is a named auth method.
|
||||
AuthMethodKubernetes = "kubernetes"
|
||||
// AuthMethod is a vault authentication method used.
|
||||
// https://www.vaultproject.io/docs/auth#auth-methods
|
||||
AuthMethod = "VAULT_AUTH_METHOD"
|
||||
// AuthMountPath defines a custom auth mount path.
|
||||
AuthMountPath = "VAULT_AUTH_MOUNT_PATH"
|
||||
// AuthKubernetesRole is the role to authenticate against on Vault
|
||||
AuthKubernetesRole = "VAULT_AUTH_KUBERNETES_ROLE"
|
||||
// AuthKubernetesTokenPath is the file path to a custom JWT token to use for authentication.
|
||||
// If omitted, the default service account token path is used.
|
||||
AuthKubernetesTokenPath = "VAULT_AUTH_KUBERNETES_TOKEN_PATH"
|
||||
// AuthKubernetesMountPath
|
||||
AuthKubernetesMountPath = "kubernetes"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrVaultAuthParamsNotSet = errors.New("VAULT_TOKEN or VAULT_AUTH_METHOD not set")
|
||||
ErrVaultAddressNotSet = errors.New("VAULT_ADDR not set")
|
||||
ErrInvalidVaultToken = errors.New("VAULT_TOKEN is invalid")
|
||||
ErrInvalidSkipVerify = errors.New("VAULT_SKIP_VERIFY is invalid")
|
||||
ErrInvalidVaultAddress = errors.New("VAULT_ADDRESS is invalid. " +
|
||||
"Should be of the form http(s)://<ip>:<port>")
|
||||
|
||||
ErrAuthMethodUnknown = errors.New("unknown auth method")
|
||||
ErrKubernetesRole = errors.New(AuthKubernetesRole + " not set")
|
||||
)
|
||||
|
||||
// IsValidAddr checks address has the correct format.
|
||||
func IsValidAddr(address string) error {
|
||||
// Vault fails if address is not in correct format
|
||||
if !strings.HasPrefix(address, vaultAddressPrefix) {
|
||||
return ErrInvalidVaultAddress
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetVaultParam retrieves a named parameter from the config or tried to get it from the environment variables.
|
||||
func GetVaultParam(secretConfig map[string]interface{}, name string) string {
|
||||
if tokenIntf, exists := secretConfig[name]; exists {
|
||||
tokenStr, ok := tokenIntf.(string)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
return strings.TrimSpace(tokenStr)
|
||||
} else {
|
||||
return strings.TrimSpace(os.Getenv(name))
|
||||
}
|
||||
}
|
||||
|
||||
// ConfigureTLS adds tls parameters to the vault configuration.
|
||||
func ConfigureTLS(config *api.Config, secretConfig map[string]interface{}) error {
|
||||
tlsConfig := api.TLSConfig{}
|
||||
skipVerify := GetVaultParam(secretConfig, api.EnvVaultInsecure)
|
||||
if skipVerify != "" {
|
||||
insecure, err := strconv.ParseBool(skipVerify)
|
||||
if err != nil {
|
||||
return ErrInvalidSkipVerify
|
||||
}
|
||||
tlsConfig.Insecure = insecure
|
||||
}
|
||||
|
||||
cacert := GetVaultParam(secretConfig, api.EnvVaultCACert)
|
||||
tlsConfig.CACert = cacert
|
||||
|
||||
capath := GetVaultParam(secretConfig, api.EnvVaultCAPath)
|
||||
tlsConfig.CAPath = capath
|
||||
|
||||
clientcert := GetVaultParam(secretConfig, api.EnvVaultClientCert)
|
||||
tlsConfig.ClientCert = clientcert
|
||||
|
||||
clientkey := GetVaultParam(secretConfig, api.EnvVaultClientKey)
|
||||
tlsConfig.ClientKey = clientkey
|
||||
|
||||
tlsserverName := GetVaultParam(secretConfig, api.EnvVaultTLSServerName)
|
||||
tlsConfig.TLSServerName = tlsserverName
|
||||
|
||||
return config.ConfigureTLS(&tlsConfig)
|
||||
}
|
||||
|
||||
// CloseIdleConnections ensures that the vault idle connections are closed.
|
||||
func CloseIdleConnections(cfg *api.Config) {
|
||||
if cfg == nil || cfg.HttpClient == nil {
|
||||
return
|
||||
}
|
||||
// close connection in case of error (a fix for go version < 1.12)
|
||||
if tp, ok := cfg.HttpClient.Transport.(*http.Transport); ok {
|
||||
tp.CloseIdleConnections()
|
||||
}
|
||||
}
|
||||
|
||||
// Authenticate gets vault authentication parameters for the provided configuration.
|
||||
func Authenticate(client *api.Client, config map[string]interface{}) (token string, autoAuth bool, err error) {
|
||||
// use VAULT_TOKEN if it's provided
|
||||
if token = GetVaultParam(config, api.EnvVaultToken); token != "" {
|
||||
return token, false, nil
|
||||
}
|
||||
|
||||
// or try to use the kubernetes auth method
|
||||
if GetVaultParam(config, AuthMethod) != "" {
|
||||
token, err = GetAuthToken(client, config)
|
||||
return token, true, err
|
||||
}
|
||||
|
||||
return "", false, ErrVaultAuthParamsNotSet
|
||||
}
|
||||
|
||||
// GetAuthToken tries to get the vault token for the provided authentication method.
|
||||
func GetAuthToken(client *api.Client, config map[string]interface{}) (string, error) {
|
||||
path, _, data, err := authenticate(client, config)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
secret, err := client.Logical().Write(path, data)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if secret == nil || secret.Auth == nil {
|
||||
return "", errors.New("authentication returned nil auth info")
|
||||
}
|
||||
if secret.Auth.ClientToken == "" {
|
||||
return "", errors.New("authentication returned empty client token")
|
||||
}
|
||||
|
||||
return secret.Auth.ClientToken, err
|
||||
}
|
||||
|
||||
func authenticate(client *api.Client, config map[string]interface{}) (string, http.Header, map[string]interface{}, error) {
|
||||
method := GetVaultParam(config, AuthMethod)
|
||||
switch method {
|
||||
case AuthMethodKubernetes:
|
||||
return authKubernetes(client, config)
|
||||
}
|
||||
return "", nil, nil, fmt.Errorf("%s method: %s", method, ErrAuthMethodUnknown)
|
||||
}
|
||||
|
||||
func authKubernetes(client *api.Client, config map[string]interface{}) (string, http.Header, map[string]interface{}, error) {
|
||||
authConfig, err := buildAuthConfig(config)
|
||||
if err != nil {
|
||||
return "", nil, nil, err
|
||||
}
|
||||
method, err := kubernetes.NewKubernetesAuthMethod(authConfig)
|
||||
if err != nil {
|
||||
return "", nil, nil, err
|
||||
}
|
||||
|
||||
return method.Authenticate(context.TODO(), client)
|
||||
}
|
||||
|
||||
func buildAuthConfig(config map[string]interface{}) (*auth.AuthConfig, error) {
|
||||
role := GetVaultParam(config, AuthKubernetesRole)
|
||||
if role == "" {
|
||||
return nil, ErrKubernetesRole
|
||||
}
|
||||
mountPath := GetVaultParam(config, AuthMountPath)
|
||||
if mountPath == "" {
|
||||
mountPath = AuthKubernetesMountPath
|
||||
}
|
||||
tokenPath := GetVaultParam(config, AuthKubernetesTokenPath)
|
||||
|
||||
authMountPath := path.Join("auth", mountPath)
|
||||
return &auth.AuthConfig{
|
||||
Logger: hclog.NewNullLogger(),
|
||||
MountPath: authMountPath,
|
||||
Config: map[string]interface{}{
|
||||
"role": role,
|
||||
"token_path": tokenPath,
|
||||
},
|
||||
}, nil
|
||||
}
|
257
vendor/github.com/libopenstorage/secrets/vault/vault.go
generated
vendored
257
vendor/github.com/libopenstorage/secrets/vault/vault.go
generated
vendored
@ -1,21 +1,14 @@
|
||||
package vault
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/hashicorp/go-hclog"
|
||||
"github.com/hashicorp/vault/api"
|
||||
"github.com/hashicorp/vault/command/agent/auth"
|
||||
"github.com/hashicorp/vault/command/agent/auth/kubernetes"
|
||||
"github.com/libopenstorage/secrets"
|
||||
"github.com/libopenstorage/secrets/vault/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -23,40 +16,25 @@ const (
|
||||
DefaultBackendPath = "secret/"
|
||||
VaultBackendPathKey = "VAULT_BACKEND_PATH"
|
||||
VaultBackendKey = "VAULT_BACKEND"
|
||||
vaultAddressPrefix = "http"
|
||||
kvVersionKey = "version"
|
||||
kvDataKey = "data"
|
||||
kvMetadataKey = "metadata"
|
||||
kvVersion1 = "kv"
|
||||
kvVersion2 = "kv-v2"
|
||||
|
||||
AuthMethodKubernetes = "kubernetes"
|
||||
|
||||
// AuthMethod is a vault authentication method used.
|
||||
// https://www.vaultproject.io/docs/auth#auth-methods
|
||||
AuthMethod = "VAULT_AUTH_METHOD"
|
||||
// AuthMountPath defines a custom auth mount path.
|
||||
AuthMountPath = "VAULT_AUTH_MOUNT_PATH"
|
||||
// AuthKubernetesRole is the role to authenticate against on Vault
|
||||
AuthKubernetesRole = "VAULT_AUTH_KUBERNETES_ROLE"
|
||||
// AuthKubernetesTokenPath is the file path to a custom JWT token to use for authentication.
|
||||
// If omitted, the default service account token path is used.
|
||||
AuthKubernetesTokenPath = "VAULT_AUTH_KUBERNETES_TOKEN_PATH"
|
||||
|
||||
// AuthKubernetesMountPath
|
||||
AuthKubernetesMountPath = "kubernetes"
|
||||
AuthMethodKubernetes = utils.AuthMethodKubernetes
|
||||
AuthMethod = utils.AuthMethod
|
||||
AuthMountPath = utils.AuthMountPath
|
||||
AuthKubernetesRole = utils.AuthKubernetesRole
|
||||
AuthKubernetesTokenPath = utils.AuthKubernetesTokenPath
|
||||
AuthKubernetesMountPath = utils.AuthKubernetesMountPath
|
||||
)
|
||||
|
||||
var (
|
||||
ErrVaultTokenNotSet = errors.New("VAULT_TOKEN not set.")
|
||||
ErrVaultAddressNotSet = errors.New("VAULT_ADDR not set.")
|
||||
ErrInvalidVaultToken = errors.New("VAULT_TOKEN is invalid")
|
||||
ErrInvalidSkipVerify = errors.New("VAULT_SKIP_VERIFY is invalid")
|
||||
ErrInvalidVaultAddress = errors.New("VAULT_ADDRESS is invalid. " +
|
||||
"Should be of the form http(s)://<ip>:<port>")
|
||||
|
||||
ErrAuthMethodUnknown = fmt.Errorf("unknown auth method")
|
||||
ErrKubernetesRole = fmt.Errorf("%s not set", AuthKubernetesRole)
|
||||
)
|
||||
func init() {
|
||||
if err := secrets.Register(Name, New); err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
type vaultSecrets struct {
|
||||
mu sync.RWMutex
|
||||
@ -89,17 +67,16 @@ func New(
|
||||
return nil, config.Error
|
||||
}
|
||||
|
||||
address := getVaultParam(secretConfig, api.EnvVaultAddress)
|
||||
address := utils.GetVaultParam(secretConfig, api.EnvVaultAddress)
|
||||
if address == "" {
|
||||
return nil, ErrVaultAddressNotSet
|
||||
return nil, utils.ErrVaultAddressNotSet
|
||||
}
|
||||
// Vault fails if address is not in correct format
|
||||
if !strings.HasPrefix(address, vaultAddressPrefix) {
|
||||
return nil, ErrInvalidVaultAddress
|
||||
if err := utils.IsValidAddr(address); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.Address = address
|
||||
|
||||
if err := configureTLS(config, secretConfig); err != nil {
|
||||
if err := utils.ConfigureTLS(config, secretConfig); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -108,7 +85,7 @@ func New(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
namespace := getVaultParam(secretConfig, api.EnvVaultNamespace)
|
||||
namespace := utils.GetVaultParam(secretConfig, api.EnvVaultNamespace)
|
||||
if len(namespace) > 0 {
|
||||
// use a namespace as a header for setup purposes
|
||||
// later use it as a key prefix
|
||||
@ -116,32 +93,20 @@ func New(
|
||||
defer client.SetNamespace("")
|
||||
}
|
||||
|
||||
var autoAuth bool
|
||||
var token string
|
||||
if getVaultParam(secretConfig, AuthMethod) != "" {
|
||||
token, err = getAuthToken(client, secretConfig)
|
||||
if err != nil {
|
||||
closeIdleConnections(config)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
autoAuth = true
|
||||
} else {
|
||||
token = getVaultParam(secretConfig, api.EnvVaultToken)
|
||||
}
|
||||
if token == "" {
|
||||
closeIdleConnections(config)
|
||||
return nil, ErrVaultTokenNotSet
|
||||
token, autoAuth, err := utils.Authenticate(client, secretConfig)
|
||||
if err != nil {
|
||||
utils.CloseIdleConnections(config)
|
||||
return nil, fmt.Errorf("failed to get the authentication token: %w", err)
|
||||
}
|
||||
client.SetToken(token)
|
||||
|
||||
backendPath := getVaultParam(secretConfig, VaultBackendPathKey)
|
||||
backendPath := utils.GetVaultParam(secretConfig, VaultBackendPathKey)
|
||||
if backendPath == "" {
|
||||
backendPath = DefaultBackendPath
|
||||
}
|
||||
|
||||
var isBackendV2 bool
|
||||
backend := getVaultParam(secretConfig, VaultBackendKey)
|
||||
backend := utils.GetVaultParam(secretConfig, VaultBackendKey)
|
||||
if backend == kvVersion1 {
|
||||
isBackendV2 = false
|
||||
} else if backend == kvVersion2 {
|
||||
@ -150,7 +115,7 @@ func New(
|
||||
// TODO: Handle backends other than kv
|
||||
isBackendV2, err = isKvV2(client, backendPath)
|
||||
if err != nil {
|
||||
closeIdleConnections(config)
|
||||
utils.CloseIdleConnections(config)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@ -170,15 +135,29 @@ func (v *vaultSecrets) String() string {
|
||||
return Name
|
||||
}
|
||||
|
||||
func (v *vaultSecrets) keyPath(secretID, namespace string) keyPath {
|
||||
if namespace == "" {
|
||||
func (v *vaultSecrets) keyPath(secretID string, keyContext map[string]string) keyPath {
|
||||
backendPath := v.backendPath
|
||||
var namespace string
|
||||
var ok bool
|
||||
if namespace, ok = keyContext[secrets.KeyVaultNamespace]; !ok {
|
||||
namespace = v.namespace
|
||||
}
|
||||
|
||||
var isDestroyKey bool
|
||||
if v.isKvBackendV2 {
|
||||
if destroyAllSecrets, ok := keyContext[secrets.DestroySecret]; ok {
|
||||
// checking for any value seems sufficient to assume 'destroy' is requested
|
||||
if destroyAllSecrets != "" {
|
||||
isDestroyKey = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return keyPath{
|
||||
backendPath: v.backendPath,
|
||||
isBackendV2: v.isKvBackendV2,
|
||||
namespace: namespace,
|
||||
secretID: secretID,
|
||||
backendPath: backendPath,
|
||||
isBackendV2: v.isKvBackendV2,
|
||||
namespace: namespace,
|
||||
secretID: secretID,
|
||||
isDestroyKey: isDestroyKey,
|
||||
}
|
||||
}
|
||||
|
||||
@ -186,7 +165,7 @@ func (v *vaultSecrets) GetSecret(
|
||||
secretID string,
|
||||
keyContext map[string]string,
|
||||
) (map[string]interface{}, error) {
|
||||
key := v.keyPath(secretID, keyContext[secrets.KeyVaultNamespace])
|
||||
key := v.keyPath(secretID, keyContext)
|
||||
secretValue, err := v.read(key)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get secret: %s: %s", key, err)
|
||||
@ -218,7 +197,7 @@ func (v *vaultSecrets) PutSecret(
|
||||
}
|
||||
}
|
||||
|
||||
key := v.keyPath(secretID, keyContext[secrets.KeyVaultNamespace])
|
||||
key := v.keyPath(secretID, keyContext)
|
||||
if _, err := v.write(key, secretData); err != nil {
|
||||
return fmt.Errorf("failed to put secret: %s: %s", key, err)
|
||||
}
|
||||
@ -229,7 +208,7 @@ func (v *vaultSecrets) DeleteSecret(
|
||||
secretID string,
|
||||
keyContext map[string]string,
|
||||
) error {
|
||||
key := v.keyPath(secretID, keyContext[secrets.KeyVaultNamespace])
|
||||
key := v.keyPath(secretID, keyContext)
|
||||
if _, err := v.delete(key); err != nil {
|
||||
return fmt.Errorf("failed to delete secret: %s: %s", key, err)
|
||||
}
|
||||
@ -355,7 +334,7 @@ func (v *vaultSecrets) renewToken(namespace string) error {
|
||||
v.client.SetNamespace(namespace)
|
||||
defer v.client.SetNamespace("")
|
||||
}
|
||||
token, err := getAuthToken(v.client, v.config)
|
||||
token, err := utils.GetAuthToken(v.client, v.config)
|
||||
if err != nil {
|
||||
return fmt.Errorf("get auth token for %s namespace: %s", namespace, err)
|
||||
}
|
||||
@ -403,131 +382,25 @@ func isKvBackendV2(client *api.Client, backendPath string) (bool, error) {
|
||||
backendPath)
|
||||
}
|
||||
|
||||
func getVaultParam(secretConfig map[string]interface{}, name string) string {
|
||||
if tokenIntf, exists := secretConfig[name]; exists {
|
||||
tokenStr, ok := tokenIntf.(string)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
return strings.TrimSpace(tokenStr)
|
||||
} else {
|
||||
return strings.TrimSpace(os.Getenv(name))
|
||||
}
|
||||
}
|
||||
|
||||
func configureTLS(config *api.Config, secretConfig map[string]interface{}) error {
|
||||
tlsConfig := api.TLSConfig{}
|
||||
skipVerify := getVaultParam(secretConfig, api.EnvVaultInsecure)
|
||||
if skipVerify != "" {
|
||||
insecure, err := strconv.ParseBool(skipVerify)
|
||||
if err != nil {
|
||||
return ErrInvalidSkipVerify
|
||||
}
|
||||
tlsConfig.Insecure = insecure
|
||||
}
|
||||
|
||||
cacert := getVaultParam(secretConfig, api.EnvVaultCACert)
|
||||
tlsConfig.CACert = cacert
|
||||
|
||||
capath := getVaultParam(secretConfig, api.EnvVaultCAPath)
|
||||
tlsConfig.CAPath = capath
|
||||
|
||||
clientcert := getVaultParam(secretConfig, api.EnvVaultClientCert)
|
||||
tlsConfig.ClientCert = clientcert
|
||||
|
||||
clientkey := getVaultParam(secretConfig, api.EnvVaultClientKey)
|
||||
tlsConfig.ClientKey = clientkey
|
||||
|
||||
tlsserverName := getVaultParam(secretConfig, api.EnvVaultTLSServerName)
|
||||
tlsConfig.TLSServerName = tlsserverName
|
||||
|
||||
return config.ConfigureTLS(&tlsConfig)
|
||||
}
|
||||
|
||||
func getAuthToken(client *api.Client, config map[string]interface{}) (string, error) {
|
||||
path, _, data, err := authenticate(client, config)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
secret, err := client.Logical().Write(path, data)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if secret == nil || secret.Auth == nil {
|
||||
return "", errors.New("authentication returned nil auth info")
|
||||
}
|
||||
if secret.Auth.ClientToken == "" {
|
||||
return "", errors.New("authentication returned empty client token")
|
||||
}
|
||||
|
||||
return secret.Auth.ClientToken, err
|
||||
}
|
||||
|
||||
func authenticate(client *api.Client, config map[string]interface{}) (string, http.Header, map[string]interface{}, error) {
|
||||
method := getVaultParam(config, AuthMethod)
|
||||
switch method {
|
||||
case AuthMethodKubernetes:
|
||||
return authKubernetes(client, config)
|
||||
}
|
||||
return "", nil, nil, fmt.Errorf("%s method: %s", method, ErrAuthMethodUnknown)
|
||||
}
|
||||
|
||||
func authKubernetes(client *api.Client, config map[string]interface{}) (string, http.Header, map[string]interface{}, error) {
|
||||
authConfig, err := buildAuthConfig(config)
|
||||
if err != nil {
|
||||
return "", nil, nil, err
|
||||
}
|
||||
method, err := kubernetes.NewKubernetesAuthMethod(authConfig)
|
||||
if err != nil {
|
||||
return "", nil, nil, err
|
||||
}
|
||||
|
||||
return method.Authenticate(context.TODO(), client)
|
||||
}
|
||||
|
||||
func buildAuthConfig(config map[string]interface{}) (*auth.AuthConfig, error) {
|
||||
role := getVaultParam(config, AuthKubernetesRole)
|
||||
if role == "" {
|
||||
return nil, ErrKubernetesRole
|
||||
}
|
||||
mountPath := getVaultParam(config, AuthMountPath)
|
||||
if mountPath == "" {
|
||||
mountPath = AuthKubernetesMountPath
|
||||
}
|
||||
tokenPath := getVaultParam(config, AuthKubernetesTokenPath)
|
||||
|
||||
authMountPath := path.Join("auth", mountPath)
|
||||
return &auth.AuthConfig{
|
||||
Logger: hclog.NewNullLogger(),
|
||||
MountPath: authMountPath,
|
||||
Config: map[string]interface{}{
|
||||
"role": role,
|
||||
"token_path": tokenPath,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func trimSlash(in string) string {
|
||||
return strings.Trim(in, "/")
|
||||
}
|
||||
|
||||
func init() {
|
||||
if err := secrets.Register(Name, New); err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
type keyPath struct {
|
||||
backendPath string
|
||||
isBackendV2 bool
|
||||
namespace string
|
||||
secretID string
|
||||
backendPath string
|
||||
isBackendV2 bool
|
||||
namespace string
|
||||
secretID string
|
||||
isDestroyKey bool
|
||||
}
|
||||
|
||||
func (k keyPath) Path() string {
|
||||
if k.isBackendV2 {
|
||||
return path.Join(k.namespace, k.backendPath, kvDataKey, k.secretID)
|
||||
keyType := kvDataKey
|
||||
if k.isDestroyKey {
|
||||
keyType = kvMetadataKey
|
||||
}
|
||||
return path.Join(k.namespace, k.backendPath, keyType, k.secretID)
|
||||
}
|
||||
return path.Join(k.namespace, k.backendPath, k.secretID)
|
||||
}
|
||||
@ -539,13 +412,3 @@ func (k keyPath) Namespace() string {
|
||||
func (k keyPath) String() string {
|
||||
return fmt.Sprintf("backendPath=%s, backendV2=%t, namespace=%s, secretID=%s", k.backendPath, k.isBackendV2, k.namespace, k.secretID)
|
||||
}
|
||||
|
||||
func closeIdleConnections(cfg *api.Config) {
|
||||
if cfg == nil || cfg.HttpClient == nil {
|
||||
return
|
||||
}
|
||||
// close connection in case of error (a fix for go version < 1.12)
|
||||
if tp, ok := cfg.HttpClient.Transport.(*http.Transport); ok {
|
||||
tp.CloseIdleConnections()
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user