diff --git a/cli/append.go b/cli/append.go index 29bff567..a1d54207 100644 --- a/cli/append.go +++ b/cli/append.go @@ -139,8 +139,9 @@ func (cmd *AppendCommand) createDummySecret(target string) error { dummy := make(map[string]interface{}) dummy["placeholder"] = struct{}{} + dummySecret := client.NewSecret(&api.Secret{Data: dummy}) if targetSecret == nil { - if err = cmd.client.Write(target, &api.Secret{Data: dummy}); err != nil { + if err = cmd.client.Write(target, dummySecret); err != nil { return err } } @@ -159,32 +160,17 @@ func (cmd *AppendCommand) mergeSecrets(source string, target string) error { } onConflict := cmd.Mode - merged := make(map[string]interface{}) + merged := targetSecret.GetData() skippedKeys := make([]string, 0) - for k, v := range targetSecret.Data { - if rec, ok := v.(map[string]interface{}); ok { - for kk, vv := range rec { - merged[kk] = vv - } - } else { - merged[k] = v - } + for k, v := range sourceSecret.GetData() { + skipped := addKey(merged, onConflict, k, v) + skippedKeys = append(skippedKeys, skipped...) } - for k, v := range sourceSecret.Data { - if rec, ok := v.(map[string]interface{}); ok { - for kk, vv := range rec { - skipped := addKey(merged, onConflict, kk, vv) - skippedKeys = append(skippedKeys, skipped...) - } - } else { - skipped := addKey(merged, onConflict, k, v) - skippedKeys = append(skippedKeys, skipped...) - } - } // write - if err := cmd.client.Write(target, &api.Secret{Data: merged}); err != nil { + resultSecret := client.NewSecret(&api.Secret{Data: merged}) + if err := cmd.client.Write(target, resultSecret); err != nil { fmt.Println(err) return err } diff --git a/cli/cat.go b/cli/cat.go index e9df2f07..4e0576a4 100644 --- a/cli/cat.go +++ b/cli/cat.go @@ -57,16 +57,8 @@ func (cmd *CatCommand) Run() int { return 1 } - for k, v := range secret.Data { - if rec, ok := v.(map[string]interface{}); ok { - // KV 2 - for kk, vv := range rec { - log.UserInfo("%s = %s", kk, vv) - } - } else { - // KV 1 - log.UserInfo("%s = %s", k, v) - } + for k, v := range secret.GetData() { + log.UserInfo("%s = %s", k, v) } } else { log.UserError("Not a valid path for operation: %s", absPath) diff --git a/cli/grep.go b/cli/grep.go index 55a62430..8dad0409 100644 --- a/cli/grep.go +++ b/cli/grep.go @@ -147,16 +147,8 @@ func (cmd *GrepCommand) grepFile(search string, path string) (matches []*Match, return matches, err } - for k, v := range secret.Data { - if rec, ok := v.(map[string]interface{}); ok { - // KV 2 - for kk, vv := range rec { - matches = append(matches, cmd.doMatch(path, kk, fmt.Sprintf("%v", vv), search)...) - } - } else { - // KV 1 - matches = append(matches, cmd.doMatch(path, k, fmt.Sprintf("%v", v), search)...) - } + for k, v := range secret.GetData() { + matches = append(matches, cmd.doMatch(path, k, fmt.Sprintf("%v", v), search)...) } } diff --git a/client/client.go b/client/client.go index b1983305..a2abd218 100644 --- a/client/client.go +++ b/client/client.go @@ -95,22 +95,25 @@ func NewClient(conf *VaultConfig) (*Client, error) { } // Read returns secret at given path, using given Client -func (client *Client) Read(absolutePath string) (secret *api.Secret, err error) { +func (client *Client) Read(absolutePath string) (secret *Secret, err error) { + var apiSecret *api.Secret if client.isTopLevelPath(absolutePath) { - secret, err = client.topLevelRead(normalizedVaultPath(absolutePath)) + apiSecret, err = client.topLevelRead(normalizedVaultPath(absolutePath)) } else { - secret, err = client.lowLevelRead(normalizedVaultPath(absolutePath)) + apiSecret, err = client.lowLevelRead(normalizedVaultPath(absolutePath)) + } + if apiSecret != nil { + secret = NewSecret(apiSecret) } - return secret, err } // Write writes secret to given path, using given Client -func (client *Client) Write(absolutePath string, secret *api.Secret) (err error) { +func (client *Client) Write(absolutePath string, secret *Secret) (err error) { if client.isTopLevelPath(absolutePath) { err = client.topLevelWrite(normalizedVaultPath(absolutePath)) } else { - err = client.lowLevelWrite(normalizedVaultPath(absolutePath), secret) + err = client.lowLevelWrite(normalizedVaultPath(absolutePath), secret.GetAPISecret()) } return err diff --git a/client/secret.go b/client/secret.go new file mode 100644 index 00000000..f9589c63 --- /dev/null +++ b/client/secret.go @@ -0,0 +1,46 @@ +package client + +import ( + "github.com/hashicorp/vault/api" +) + +// Secret holds vault secret and offers operations to simplify KV abstraction +type Secret struct { + vaultSecret *api.Secret +} + +// NewSecret create a new Secret object +func NewSecret(vaultSecret *api.Secret) *Secret { + return &Secret{ + vaultSecret: vaultSecret, + } +} + +// GetAPISecret getter method for vault secret in Secret object +func (secret *Secret) GetAPISecret() *api.Secret { + return secret.vaultSecret +} + +// GetData returns the secret data as a map and is KV agnostic +func (secret *Secret) GetData() map[string]interface{} { + data := make(map[string]interface{}) + for k, v := range secret.vaultSecret.Data { + if rec, ok := v.(map[string]interface{}); ok { + // KV 2 + if k == "data" { + for kk, vv := range rec { + data[kk] = vv + } + } + } else { + // KV 1 + data[k] = v + } + } + return data +} + +// SetData set given data as vault secret data and is KV agnostic +func (secret *Secret) SetData(data map[string]interface{}) { + secret.vaultSecret.Data = data +} diff --git a/test/suites/commands/cat.bats b/test/suites/commands/cat.bats index 70249140..49343996 100644 --- a/test/suites/commands/cat.bats +++ b/test/suites/commands/cat.bats @@ -8,6 +8,9 @@ load ../../bin/plugins/bats-assert/load run ${APP_BIN} -c "cat ${KV_BACKEND}/src/dev/1" assert_success assert_line "value = 1" + refute_line --partial "created_time" + refute_line --partial "deletion_time" + refute_line --partial "destroyed" ####################################### echo "==== case: cat non-existing file ====" @@ -30,6 +33,9 @@ load ../../bin/plugins/bats-assert/load assert_line "value = tooling" assert_line "drink = beer" assert_line "key = A" + refute_line --partial "created_time" + refute_line --partial "deletion_time" + refute_line --partial "destroyed" ####################################### echo "==== case: cat ambiguous directory ===="