Vault 9800 Fix vault read handling for endpoints with no top-level data object (#17913)

* fix vault read

* changing json unmarshal

* adding changelog

* removing line

* removing format=raw

* add test

* fix tests

* add fix for resp.Errors

* adding comments
This commit is contained in:
akshya96 2022-11-17 10:51:37 -08:00 committed by GitHub
parent 59cec0a96c
commit 22029c696b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 75 additions and 1 deletions

View File

@ -2,8 +2,11 @@ package api
import (
"bytes"
"encoding/json"
"fmt"
"io"
"reflect"
"strings"
"time"
"github.com/hashicorp/errwrap"
@ -302,7 +305,15 @@ func ParseSecret(r io.Reader) (*Secret, error) {
// First read the data into a buffer. Not super efficient but we want to
// know if we actually have a body or not.
var buf bytes.Buffer
_, err := buf.ReadFrom(r)
// io.Reader is treated like a stream and cannot be read
// multiple times. Duplicating this stream using TeeReader
// to use this data in case there is no top-level data from
// api response
var teebuf bytes.Buffer
tee := io.TeeReader(r, &teebuf)
_, err := buf.ReadFrom(tee)
if err != nil {
return nil, err
}
@ -316,5 +327,38 @@ func ParseSecret(r io.Reader) (*Secret, error) {
return nil, err
}
// If the secret is null, add raw data to secret data if present
if reflect.DeepEqual(secret, Secret{}) {
data := make(map[string]interface{})
if err := jsonutil.DecodeJSONFromReader(&teebuf, &data); err != nil {
return nil, err
}
errRaw, errPresent := data["errors"]
// if only errors are present in the resp.Body return nil
// to return value not found as it does not have any raw data
if len(data) == 1 && errPresent {
return nil, nil
}
// if errors are present along with raw data return the error
if errPresent {
var errStrArray []string
errBytes, err := json.Marshal(errRaw)
if err != nil {
return nil, err
}
if err := json.Unmarshal(errBytes, &errStrArray); err != nil {
return nil, err
}
return nil, fmt.Errorf(strings.Join(errStrArray, " "))
}
// if any raw data is present in resp.Body, add it to secret
if len(data) > 0 {
secret.Data = data
}
}
return &secret, nil
}

3
changelog/17913.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:bug
cli: Fix vault read handling to return raw data as secret.Data when there is no top-level data object from api response.
```

View File

@ -128,6 +128,33 @@ func TestReadCommand_Run(t *testing.T) {
}
})
t.Run("no_data_object_from_api_response", func(t *testing.T) {
t.Parallel()
client, closer := testVaultServer(t)
defer closer()
ui, cmd := testReadCommand(t)
cmd.client = client
code := cmd.Run([]string{
"sys/health",
})
if exp := 0; code != exp {
t.Errorf("expected %d to be %d", code, exp)
}
combined := ui.OutputWriter.String() + ui.ErrorWriter.String()
expected := []string{
"cluster_id", "cluster_name", "initialized", "performance_standby", "replication_dr_mode", "replication_performance_mode", "sealed",
"server_time_utc", "standby", "version",
}
for _, expectedField := range expected {
if !strings.Contains(combined, expectedField) {
t.Errorf("expected %q to contain %q", combined, expected)
}
}
})
t.Run("no_tabs", func(t *testing.T) {
t.Parallel()