Files
shhh/pkg/secretsclient/cli.go
T

151 lines
2.9 KiB
Go

package secretsclient
import (
"bytes"
"encoding/base64"
"encoding/json"
"errors"
"io"
"net/http"
)
type Client interface {
GetString(key string) (string, error)
PutString(key string, val string) error
GetStringArr(key string) ([]string, error)
PutStringArr(key string, val []string) error
GetStringMap(key string) (map[string]string, error)
PutStringMap(key string, val map[string]string) error
Delete(key string) error
}
func New(base, ca, cert, certKey string) (Client, error) {
h, err := newMTLSClient(ca, cert, certKey)
if err != nil {
return nil, err
}
return &client{
base: base,
h: h,
}, nil
}
// TODO: Propagate errors to the callers.
type client struct {
base string
h *http.Client
}
func (c *client) GetString(key string) (string, error) {
res, err := c.get(key)
if err != nil {
return "", err
}
return string(res), nil
}
func (c *client) PutString(key, val string) error {
return c.put(key, []byte(val))
}
func (c *client) GetStringArr(key string) ([]string, error) {
arrBytes, err := c.get(key)
if err != nil {
return nil, err
}
var res []string
err = json.Unmarshal(arrBytes, &res)
if err != nil {
return nil, err
}
return res, nil
}
func (c *client) PutStringArr(key string, val []string) error {
arrBytes, err := json.Marshal(val)
if err != nil {
return err
}
return c.put(key, arrBytes)
}
func (c *client) GetStringMap(key string) (map[string]string, error) {
mapBytes, err := c.get(key)
if err != nil {
return nil, err
}
var res map[string]string
err = json.Unmarshal(mapBytes, &res)
if err != nil {
return nil, err
}
return res, nil
}
func (c *client) PutStringMap(key string, val map[string]string) error {
mapBytes, err := json.Marshal(val)
if err != nil {
return err
}
return c.put(key, mapBytes)
}
func (c *client) get(key string) ([]byte, error) {
res, err := c.h.Get(c.urlFromKey(key))
if err != nil {
return nil, err
}
if res.StatusCode != http.StatusOK {
return nil, errors.New("request did not succeed")
}
val, err := io.ReadAll(res.Body)
if err != nil {
return nil, err
}
defer res.Body.Close()
return val, nil
}
func (c *client) put(key string, val []byte) error {
body := bytes.NewBuffer(val)
req, err := http.NewRequest("PUT", c.urlFromKey(key), body)
if err != nil {
return err
}
res, err := c.h.Do(req)
if err != nil {
return err
}
if res.StatusCode != http.StatusOK {
return errors.New("request did not succeed")
}
return nil
}
func (c *client) Delete(key string) error {
req, err := http.NewRequest("DELETE", c.urlFromKey(key), nil)
if err != nil {
return err
}
res, err := c.h.Do(req)
if err != nil {
return err
}
if res.StatusCode != http.StatusOK {
return errors.New("request did not succeed")
}
return nil
}
func (c *client) urlFromKey(key string) string {
b64Key := base64.RawURLEncoding.EncodeToString([]byte(key))
return c.base + "?key=" + b64Key
}