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  }