diff --git a/cmd/import.go b/cmd/import.go index f9ce0e4..7d92f70 100644 --- a/cmd/import.go +++ b/cmd/import.go @@ -50,7 +50,7 @@ func Import(path, file, ver string) error { // Write each keypair to vault for _, item := range wrap.Data { - data := make(map[string]string) + data := make(map[string]interface{}) for _, kv := range item.Pairs { data[kv.Key] = kv.Value } diff --git a/cmd/json.go b/cmd/json.go index 26fe4ae..b4966aa 100644 --- a/cmd/json.go +++ b/cmd/json.go @@ -9,6 +9,6 @@ type Item struct { Pairs []Pair `json:"pairs"` } type Pair struct { - Key string `json:"key"` - Value string `json:"value"` + Key string `json:"key"` + Value interface{} `json:"value"` } diff --git a/go.mod b/go.mod index c8d3331..43b2e16 100644 --- a/go.mod +++ b/go.mod @@ -69,3 +69,5 @@ require ( gopkg.in/yaml.v2 v2.2.1 // indirect gotest.tools v2.1.0+incompatible // indirect ) + +go 1.13 diff --git a/it/integration_test.go b/it/integration_test.go index c73dcc8..e1a6bd2 100644 --- a/it/integration_test.go +++ b/it/integration_test.go @@ -72,10 +72,11 @@ func TestMigrator__integration(t *testing.T) { data := []struct { path string key string - value string + value interface{} }{ {"secret/foo", "foo", "YmFyCg=="}, // bar {"secret/bar/baz", "username", "YWRhbQo="}, // adam + {"secret/baz", "integer", 100}, } os.Setenv("VAULT_ADDR", "http://127.0.0.1:8200") os.Setenv("VAULT_TOKEN", token) @@ -86,9 +87,18 @@ func TestMigrator__integration(t *testing.T) { // write values for i := range data { - client.Write(data[i].path, map[string]string{ - data[i].key: data[i].value, - }, "1") + m := make(map[string]interface{}) + + switch d := data[i].value.(type) { + case int: + m[data[i].key] = d + case string: + m[data[i].key] = d + default: + t.Fatal("Error: unsupported data type") + } + client.Write(data[i].path, m, "1") + kv := client.Read(data[i].path) if kv[data[i].key] != data[i].value { t.Fatalf("path=%q, kv[%s]=%q, value=%q, err=%v", data[i].path, data[i].key, kv[data[i].key], data[i].value, err) diff --git a/vault/client.go b/vault/client.go index 918770c..921db0b 100644 --- a/vault/client.go +++ b/vault/client.go @@ -2,6 +2,7 @@ package vault import ( "encoding/base64" + "encoding/json" "fmt" "os" @@ -78,13 +79,38 @@ func (v *Vault) Read(path string) map[string]interface{} { } for k, v := range s.Data { switch t := v.(type) { + case json.Number: + if n, err := t.Int64(); err == nil { + out[k] = n + } else if f, err := t.Float64(); err == nil { + out[k] = f + } else { + out[k] = v + } case string: out[k] = base64.StdEncoding.EncodeToString([]byte(t)) case map[string]interface{}: if k == "data" { for x, y := range t { - if z, ok := y.(string); ok { - out[x] = base64.StdEncoding.EncodeToString([]byte(z)) + switch t := y.(type) { + case json.Number: + if n, err := t.Int64(); err == nil { + out[k] = n + } else if f, err := t.Float64(); err == nil { + out[k] = f + } else { + out[k] = y + } + case string: + out[x] = base64.StdEncoding.EncodeToString([]byte(t)) + case map[string]interface{}: + js, err := json.Marshal(&t) + if err != nil { + fmt.Println(err) + } + out[x] = base64.StdEncoding.EncodeToString(js) + default: + fmt.Printf("error reading value at %s, key=%s, type=%T\n", path, k, v) } } } @@ -97,16 +123,28 @@ func (v *Vault) Read(path string) map[string]interface{} { } // Write takes in a vault path and base64 encoded data to be written at that path. -func (v *Vault) Write(path string, data map[string]string, ver string) error { +func (v *Vault) Write(path string, data map[string]interface{}, ver string) error { body := make(map[string]interface{}) // Decode the base64 values for k, v := range data { - b, err := base64.StdEncoding.DecodeString(v) - if err != nil { - return err + stringv, ok := v.(string) + if ok { + b, err := base64.StdEncoding.DecodeString(stringv) + if err != nil { + return err + } + isValid := json.Valid(b) + if isValid { + var mapValue map[string]interface{} + json.Unmarshal(b, &mapValue) + body[k] = mapValue + } else { + body[k] = string(b) + } + } else { + body[k] = v } - body[k] = string(b) } var err error