From 20768e53fa60ea824cf5ac9bcc65d84d1beba7d9 Mon Sep 17 00:00:00 2001 From: James Strachan Date: Wed, 19 Jun 2019 17:15:34 +0100 Subject: [PATCH] fix: lets move URL handling into the secreturl.Client and add support for `vault:` for the vault client and `local:` for the local file system client Signed-off-by: James Strachan #4328 --- pkg/helm/helm_helpers.go | 2 +- pkg/secreturl/client.go | 3 +++ pkg/secreturl/helpers.go | 13 +++++++------ pkg/secreturl/localvault/client.go | 7 +++++++ pkg/vault/vault_client.go | 11 +++++++++++ 5 files changed, 29 insertions(+), 7 deletions(-) diff --git a/pkg/helm/helm_helpers.go b/pkg/helm/helm_helpers.go index 6c17c4aad9..60d5e8fc27 100644 --- a/pkg/helm/helm_helpers.go +++ b/pkg/helm/helm_helpers.go @@ -595,7 +595,7 @@ func DecorateWithSecrets(options *InstallChartOptions, vaultClient secreturl.Cli if err != nil { return cleanup, errors.Wrapf(err, "reading file %s", valueFile) } - newValues, err := secreturl.ReplaceURIs(string(bytes), vaultClient) + newValues, err := vaultClient.ReplaceURIs(string(bytes)) if err != nil { return cleanup, errors.Wrapf(err, "replacing vault URIs") } diff --git a/pkg/secreturl/client.go b/pkg/secreturl/client.go index 76c974e4c2..468c160f02 100644 --- a/pkg/secreturl/client.go +++ b/pkg/secreturl/client.go @@ -14,4 +14,7 @@ type Client interface { // WriteObject writes a generic named object to the vault. // The secret _must_ be serializable to JSON. WriteObject(secretName string, secret interface{}) (map[string]interface{}, error) + + // ReplaceURIs will replace any vault: URIs in a string (or whatever URL scheme the secret URL client supports + ReplaceURIs(text string) (string, error) } diff --git a/pkg/secreturl/helpers.go b/pkg/secreturl/helpers.go index fd1f5d9ab9..740ce24488 100644 --- a/pkg/secreturl/helpers.go +++ b/pkg/secreturl/helpers.go @@ -9,15 +9,16 @@ import ( "github.com/pkg/errors" ) -var vaultURIRegex = regexp.MustCompile(`vault:[-_\w\/:]*`) - -// ReplaceURIs will replace any vault: URIs in a string, using the vault client -func ReplaceURIs(s string, client Client) (string, error) { +// ReplaceURIs will replace any URIs with the given regular expression and scheme using the secret URL client +func ReplaceURIs(s string, client Client, r *regexp.Regexp, schemePrefix string) (string, error) { + if !strings.HasSuffix(schemePrefix, ":") { + return s, fmt.Errorf("the scheme prefix should end with ':' but was %s", schemePrefix) + } var err error - answer := vaultURIRegex.ReplaceAllStringFunc(s, func(found string) string { + answer := r.ReplaceAllStringFunc(s, func(found string) string { // Stop once we have an error if err == nil { - pathAndKey := strings.Trim(strings.TrimPrefix(found, "vault:"), "\"") + pathAndKey := strings.Trim(strings.TrimPrefix(found, schemePrefix), "\"") parts := strings.Split(pathAndKey, ":") if len(parts) != 2 { err = errors.Errorf("cannot parse %s as path:key", pathAndKey) diff --git a/pkg/secreturl/localvault/client.go b/pkg/secreturl/localvault/client.go index c048080780..53b12da716 100644 --- a/pkg/secreturl/localvault/client.go +++ b/pkg/secreturl/localvault/client.go @@ -4,6 +4,7 @@ import ( "fmt" "os" "path/filepath" + "regexp" "github.com/jenkins-x/jx/pkg/helm" "github.com/jenkins-x/jx/pkg/secreturl" @@ -11,6 +12,8 @@ import ( "github.com/pkg/errors" ) +var localURIRegex = regexp.MustCompile(`local:[-_\w\/:]*`) + // FileSystemClient a local file system based client loading/saving content from the given URL type FileSystemClient struct { Dir string @@ -66,6 +69,10 @@ func (c *FileSystemClient) WriteObject(secretName string, secret interface{}) (m return c.Read(secretName) } +func (c *FileSystemClient) ReplaceURIs(s string) (string, error) { + return secreturl.ReplaceURIs(s, c, localURIRegex, "local:") +} + func (c *FileSystemClient) fileName(secretName string) string { return filepath.Join(c.Dir, secretName+".yaml") } diff --git a/pkg/vault/vault_client.go b/pkg/vault/vault_client.go index 54a1b42e20..2a2948e01e 100644 --- a/pkg/vault/vault_client.go +++ b/pkg/vault/vault_client.go @@ -4,8 +4,10 @@ import ( "encoding/base64" "fmt" "net/url" + "regexp" "github.com/hashicorp/vault/api" + "github.com/jenkins-x/jx/pkg/secreturl" "github.com/jenkins-x/jx/pkg/util" "github.com/pkg/errors" ) @@ -14,6 +16,8 @@ const ( yamlDataKey = "yaml" ) +var vaultURIRegex = regexp.MustCompile(`vault:[-_\w\/:]*`) + // Client is an interface for interacting with Vault //go:generate pegomock generate github.com/jenkins-x/jx/pkg/vault Client -o mocks/vault_client.go type Client interface { @@ -42,6 +46,9 @@ type Client interface { // Config gets the config required for configuring the official Vault CLI Config() (vaultURL url.URL, vaultToken string, err error) + + // ReplaceURIs will replace any vault: URIs in a string (or whatever URL scheme the secret URL client supports + ReplaceURIs(text string) (string, error) } // client is a hand wrapper around the official Vault API @@ -171,3 +178,7 @@ func (v *client) Config() (vaultURL url.URL, vaultToken string, err error) { parsed, err := url.Parse(v.client.Address()) return *parsed, v.client.Token(), err } + +func (v *client) ReplaceURIs(s string) (string, error) { + return secreturl.ReplaceURIs(s, v, vaultURIRegex, "vault:") +}