github.com/blend/go-sdk@v1.20220411.3/vault/kv2.go (about) 1 /* 2 3 Copyright (c) 2022 - Present. Blend Labs, Inc. All rights reserved 4 Use of this source code is governed by a MIT license that can be found in the LICENSE file. 5 6 */ 7 8 package vault 9 10 import ( 11 "context" 12 "encoding/json" 13 "path/filepath" 14 "strings" 15 ) 16 17 // assert kv1 implements kv. 18 var ( 19 _ KV = (*KV2)(nil) 20 ) 21 22 // KV2 defines key value version 2 interactions 23 type KV2 struct { 24 Client *APIClient 25 } 26 27 // Put puts a value. 28 func (kv2 KV2) Put(ctx context.Context, path string, data Values, options ...CallOption) error { 29 contents, err := kv2.Client.jsonBody(SecretData{Data: data}) 30 if err != nil { 31 return err 32 } 33 req := kv2.Client.createRequest(MethodPut, filepath.Join("/v1/", kv2.fixSecretDataPrefix(path)), options...).WithContext(ctx) 34 req.Body = contents 35 res, err := kv2.Client.send(req, OptTraceVaultOperation("kv2.put"), OptTraceKeyName(path)) 36 if err != nil { 37 return err 38 } 39 defer res.Close() 40 return nil 41 } 42 43 // Get gets a value at a given key. 44 func (kv2 KV2) Get(ctx context.Context, path string, options ...CallOption) (Values, error) { 45 req := kv2.Client.createRequest(MethodGet, filepath.Join("/v1/", kv2.fixSecretDataPrefix(path)), options...).WithContext(ctx) 46 res, err := kv2.Client.send(req, OptTraceVaultOperation("kv2.get"), OptTraceKeyName(path)) 47 if err != nil { 48 return nil, err 49 } 50 defer res.Close() 51 52 var response SecretV2 53 if err := json.NewDecoder(res).Decode(&response); err != nil { 54 return nil, err 55 } 56 return response.Data.Data, nil 57 } 58 59 // Delete deletes a secret. 60 func (kv2 KV2) Delete(ctx context.Context, path string, options ...CallOption) error { 61 req := kv2.Client.createRequest(MethodDelete, filepath.Join("/v1/", kv2.fixSecretDataPrefix(path)), options...).WithContext(ctx) 62 63 res, err := kv2.Client.send(req, OptTraceVaultOperation("kv2.delete"), OptTraceKeyName(path)) 64 if err != nil { 65 return err 66 } 67 defer res.Close() 68 return nil 69 } 70 71 // List returns a slice of key and subfolder names at this path. 72 func (kv2 KV2) List(ctx context.Context, path string, options ...CallOption) ([]string, error) { 73 req := kv2.Client.createRequest(MethodList, filepath.Join("/v1/", kv2.fixSecretDataPrefix(path)), options...).WithContext(ctx) 74 res, err := kv2.Client.send(req, OptTraceVaultOperation("kv2.list")) 75 if err != nil { 76 return nil, err 77 } 78 defer res.Close() 79 80 var response SecretListV2 81 if err := json.NewDecoder(res).Decode(&response); err != nil { 82 return nil, err 83 } 84 return response.Data.Keys, nil 85 } 86 87 // fixSecretDataPrefix ensures that a key is prefixed with secret/data/... 88 func (kv2 KV2) fixSecretDataPrefix(path string) string { 89 path = strings.TrimPrefix(path, "/") 90 if strings.HasPrefix(path, "secret/") && !strings.HasPrefix(path, "secret/data/") { 91 path = strings.TrimPrefix(path, "secret/") 92 path = "secret/data/" + path 93 } 94 return path 95 }