Updates and documentation
This commit is contained in:
parent
d17c3f4407
commit
5341cb69cc
|
@ -27,7 +27,8 @@ func (c *Logical) Read(path string) (*Secret, error) {
|
|||
}
|
||||
|
||||
func (c *Logical) List(path string) (*Secret, error) {
|
||||
r := c.c.NewRequest("LIST", "/v1/"+path)
|
||||
r := c.c.NewRequest("GET", "/v1/"+path)
|
||||
r.Params.Set("list", "true")
|
||||
resp, err := c.c.RawRequest(r)
|
||||
if resp != nil {
|
||||
defer resp.Body.Close()
|
||||
|
|
|
@ -161,7 +161,12 @@ func Commands(metaPtr *command.Meta) map[string]cli.CommandFactory {
|
|||
"read": func() (cli.Command, error) {
|
||||
return &command.ReadCommand{
|
||||
Meta: meta,
|
||||
List: false,
|
||||
}, nil
|
||||
},
|
||||
|
||||
"list": func() (cli.Command, error) {
|
||||
return &command.ListCommand{
|
||||
Meta: meta,
|
||||
}, nil
|
||||
},
|
||||
|
||||
|
@ -177,13 +182,6 @@ func Commands(metaPtr *command.Meta) map[string]cli.CommandFactory {
|
|||
}, nil
|
||||
},
|
||||
|
||||
"list": func() (cli.Command, error) {
|
||||
return &command.ReadCommand{
|
||||
Meta: meta,
|
||||
List: true,
|
||||
}, nil
|
||||
},
|
||||
|
||||
"rekey": func() (cli.Command, error) {
|
||||
return &command.RekeyCommand{
|
||||
Meta: meta,
|
||||
|
|
|
@ -28,6 +28,22 @@ func OutputSecret(ui cli.Ui, format string, secret *api.Secret) int {
|
|||
}
|
||||
}
|
||||
|
||||
func OutputList(ui cli.Ui, format string, secret *api.Secret) int {
|
||||
switch format {
|
||||
case "json":
|
||||
return outputFormatJSONList(ui, secret)
|
||||
case "yaml":
|
||||
return outputFormatYAMLList(ui, secret)
|
||||
case "table":
|
||||
return outputFormatTableList(ui, secret, false)
|
||||
case "bare":
|
||||
return outputFormatTableList(ui, secret, true)
|
||||
default:
|
||||
ui.Error(fmt.Sprintf("Invalid output format: %s", format))
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
func outputFormatJSON(ui cli.Ui, s *api.Secret) int {
|
||||
b, err := json.Marshal(s)
|
||||
if err != nil {
|
||||
|
@ -42,6 +58,20 @@ func outputFormatJSON(ui cli.Ui, s *api.Secret) int {
|
|||
return 0
|
||||
}
|
||||
|
||||
func outputFormatJSONList(ui cli.Ui, s *api.Secret) int {
|
||||
b, err := json.Marshal(s.Data["keys"])
|
||||
if err != nil {
|
||||
ui.Error(fmt.Sprintf(
|
||||
"Error formatting keys: %s", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
var out bytes.Buffer
|
||||
json.Indent(&out, b, "", "\t")
|
||||
ui.Output(out.String())
|
||||
return 0
|
||||
}
|
||||
|
||||
func outputFormatYAML(ui cli.Ui, s *api.Secret) int {
|
||||
b, err := yaml.Marshal(s)
|
||||
if err != nil {
|
||||
|
@ -54,6 +84,18 @@ func outputFormatYAML(ui cli.Ui, s *api.Secret) int {
|
|||
return 0
|
||||
}
|
||||
|
||||
func outputFormatYAMLList(ui cli.Ui, s *api.Secret) int {
|
||||
b, err := yaml.Marshal(s.Data["keys"])
|
||||
if err != nil {
|
||||
ui.Error(fmt.Sprintf(
|
||||
"Error formatting secret: %s", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
ui.Output(strings.TrimSpace(string(b)))
|
||||
return 0
|
||||
}
|
||||
|
||||
func outputFormatTable(ui cli.Ui, s *api.Secret, whitespace bool) int {
|
||||
config := columnize.DefaultConfig()
|
||||
config.Delim = "♨"
|
||||
|
@ -107,3 +149,41 @@ func outputFormatTable(ui cli.Ui, s *api.Secret, whitespace bool) int {
|
|||
ui.Output(columnize.Format(input, config))
|
||||
return 0
|
||||
}
|
||||
|
||||
func outputFormatTableList(ui cli.Ui, s *api.Secret, bare bool) int {
|
||||
config := columnize.DefaultConfig()
|
||||
config.Delim = "♨"
|
||||
config.Glue = "\t"
|
||||
config.Prefix = ""
|
||||
|
||||
input := make([]string, 0, 5)
|
||||
|
||||
if !bare {
|
||||
input = append(input, "Keys")
|
||||
}
|
||||
|
||||
keys := make([]string, 0, len(s.Data["keys"].([]string)))
|
||||
for _, k := range s.Data["keys"].([]string) {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
|
||||
for _, k := range keys {
|
||||
input = append(input, fmt.Sprintf("%s", k))
|
||||
}
|
||||
|
||||
if !bare && len(s.Warnings) != 0 {
|
||||
input = append(input, "")
|
||||
for _, warning := range s.Warnings {
|
||||
input = append(input, fmt.Sprintf("* %s", warning))
|
||||
}
|
||||
}
|
||||
|
||||
if bare {
|
||||
for _, line := range input {
|
||||
ui.Output(line)
|
||||
}
|
||||
} else {
|
||||
ui.Output(columnize.Format(input, config))
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
package command
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/vault/api"
|
||||
)
|
||||
|
||||
// ListCommand is a Command that lists data from the Vault.
|
||||
type ListCommand struct {
|
||||
Meta
|
||||
}
|
||||
|
||||
func (c *ListCommand) Run(args []string) int {
|
||||
var format string
|
||||
var bare bool
|
||||
var err error
|
||||
var secret *api.Secret
|
||||
var flags *flag.FlagSet
|
||||
flags = c.Meta.FlagSet("list", FlagSetDefault)
|
||||
flags.StringVar(&format, "format", "table", "")
|
||||
flags.BoolVar(&bare, "bare", false, "")
|
||||
flags.Usage = func() { c.Ui.Error(c.Help()) }
|
||||
if err := flags.Parse(args); err != nil {
|
||||
return 1
|
||||
}
|
||||
|
||||
args = flags.Args()
|
||||
if len(args) != 1 || len(args[0]) == 0 {
|
||||
c.Ui.Error("read expects one argument")
|
||||
flags.Usage()
|
||||
return 1
|
||||
}
|
||||
|
||||
path := args[0]
|
||||
if path[0] == '/' {
|
||||
path = path[1:]
|
||||
}
|
||||
|
||||
client, err := c.Client()
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf(
|
||||
"Error initializing client: %s", err))
|
||||
return 2
|
||||
}
|
||||
|
||||
secret, err = client.Logical().List(path)
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf(
|
||||
"Error reading %s: %s", path, err))
|
||||
return 1
|
||||
}
|
||||
if secret == nil {
|
||||
c.Ui.Error(fmt.Sprintf(
|
||||
"No value found at %s", path))
|
||||
return 1
|
||||
}
|
||||
if secret.Data["keys"] == nil {
|
||||
if !bare {
|
||||
c.Ui.Error("No entries found")
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
if bare {
|
||||
return OutputList(c.Ui, "bare", secret)
|
||||
}
|
||||
|
||||
return OutputList(c.Ui, format, secret)
|
||||
}
|
||||
|
||||
func (c *ListCommand) Synopsis() string {
|
||||
return "List data or secrets in Vault"
|
||||
}
|
||||
|
||||
func (c *ListCommand) Help() string {
|
||||
helpText :=
|
||||
`
|
||||
Usage: vault list [options] path
|
||||
|
||||
List data from Vault.
|
||||
|
||||
Retrieve a listing of available data. The data returned, if any, is backend-
|
||||
and endpoint-specific.
|
||||
|
||||
General Options:
|
||||
|
||||
` + generalOptionsUsage() + `
|
||||
|
||||
Read Options:
|
||||
|
||||
-format=table The format for output. By default it is a whitespace-
|
||||
delimited table. This can also be json or yaml.
|
||||
|
||||
-bare Causes the key values to be output raw to stdout,
|
||||
without formatting (except for newlines).
|
||||
`
|
||||
return strings.TrimSpace(helpText)
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
package command
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/vault/http"
|
||||
"github.com/hashicorp/vault/vault"
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
||||
func TestList(t *testing.T) {
|
||||
core, _, token := vault.TestCoreUnsealed(t)
|
||||
ln, addr := http.TestServer(t, core)
|
||||
defer ln.Close()
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &ReadCommand{
|
||||
Meta: Meta{
|
||||
ClientToken: token,
|
||||
Ui: ui,
|
||||
},
|
||||
}
|
||||
|
||||
args := []string{
|
||||
"-address", addr,
|
||||
"-format", "json",
|
||||
"secret",
|
||||
}
|
||||
|
||||
// Run once so the client is setup, ignore errors
|
||||
c.Run(args)
|
||||
|
||||
// Get the client so we can write data
|
||||
client, err := c.Client()
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
data := map[string]interface{}{"value": "bar"}
|
||||
if _, err := client.Logical().Write("secret/foo", data); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
data = map[string]interface{}{"value": "bar"}
|
||||
if _, err := client.Logical().Write("secret/foo/bar", data); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
secret, err := client.Logical().List("secret/")
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
if secret == nil {
|
||||
t.Fatalf("err: No value found at secret/")
|
||||
}
|
||||
|
||||
if secret.Data == nil {
|
||||
t.Fatalf("err: Data not found")
|
||||
}
|
||||
|
||||
exp := map[string]interface{}{
|
||||
"keys": []interface{}{"secret/foo", "secret/foo/"},
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(secret.Data, exp) {
|
||||
t.Fatalf("err: expected %#v, got %#v", exp, secret.Data)
|
||||
}
|
||||
}
|
|
@ -13,7 +13,6 @@ import (
|
|||
// ReadCommand is a Command that reads data from the Vault.
|
||||
type ReadCommand struct {
|
||||
Meta
|
||||
List bool
|
||||
}
|
||||
|
||||
func (c *ReadCommand) Run(args []string) int {
|
||||
|
@ -22,11 +21,7 @@ func (c *ReadCommand) Run(args []string) int {
|
|||
var err error
|
||||
var secret *api.Secret
|
||||
var flags *flag.FlagSet
|
||||
if c.List {
|
||||
flags = c.Meta.FlagSet("list", FlagSetDefault)
|
||||
} else {
|
||||
flags = c.Meta.FlagSet("read", FlagSetDefault)
|
||||
}
|
||||
flags = c.Meta.FlagSet("read", FlagSetDefault)
|
||||
flags.StringVar(&format, "format", "table", "")
|
||||
flags.StringVar(&field, "field", "", "")
|
||||
flags.Usage = func() { c.Ui.Error(c.Help()) }
|
||||
|
@ -53,11 +48,7 @@ func (c *ReadCommand) Run(args []string) int {
|
|||
return 2
|
||||
}
|
||||
|
||||
if c.List {
|
||||
secret, err = client.Logical().List(path)
|
||||
} else {
|
||||
secret, err = client.Logical().Read(path)
|
||||
}
|
||||
secret, err = client.Logical().Read(path)
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf(
|
||||
"Error reading %s: %s", path, err))
|
||||
|
@ -94,9 +85,6 @@ func (c *ReadCommand) Run(args []string) int {
|
|||
}
|
||||
|
||||
func (c *ReadCommand) Synopsis() string {
|
||||
if c.List {
|
||||
return "List data in Vault"
|
||||
}
|
||||
return "Read data or secrets from Vault"
|
||||
}
|
||||
|
||||
|
@ -110,21 +98,7 @@ Usage: vault read [options] path
|
|||
secrets and configuration as well as generate dynamic values from
|
||||
materialized backends. Please reference the documentation for the
|
||||
backends in use to determine key structure.
|
||||
`
|
||||
|
||||
if c.List {
|
||||
helpText =
|
||||
`
|
||||
Usage: vault list [options] path
|
||||
|
||||
List data from Vault.
|
||||
|
||||
Retrieve a listing of available data. The data returned is
|
||||
backend-specific, and not all backends implement listing capability.
|
||||
`
|
||||
}
|
||||
|
||||
helpText += `
|
||||
General Options:
|
||||
|
||||
` + generalOptionsUsage() + `
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package command
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/vault/http"
|
||||
|
@ -135,64 +134,3 @@ func TestRead_field_notFound(t *testing.T) {
|
|||
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestList(t *testing.T) {
|
||||
core, _, token := vault.TestCoreUnsealed(t)
|
||||
ln, addr := http.TestServer(t, core)
|
||||
defer ln.Close()
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &ReadCommand{
|
||||
Meta: Meta{
|
||||
ClientToken: token,
|
||||
Ui: ui,
|
||||
},
|
||||
List: true,
|
||||
}
|
||||
|
||||
args := []string{
|
||||
"-address", addr,
|
||||
"-format", "json",
|
||||
"secret",
|
||||
}
|
||||
|
||||
// Run once so the client is setup, ignore errors
|
||||
c.Run(args)
|
||||
|
||||
// Get the client so we can write data
|
||||
client, err := c.Client()
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
data := map[string]interface{}{"value": "bar"}
|
||||
if _, err := client.Logical().Write("secret/foo", data); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
data = map[string]interface{}{"value": "bar"}
|
||||
if _, err := client.Logical().Write("secret/foo/bar", data); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
secret, err := client.Logical().List("secret/")
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
if secret == nil {
|
||||
t.Fatalf("err: No value found at secret/")
|
||||
}
|
||||
|
||||
if secret.Data == nil {
|
||||
t.Fatalf("err: Data not found")
|
||||
}
|
||||
|
||||
exp := map[string]interface{}{
|
||||
"keys": []interface{}{"foo", "foo/"},
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(secret.Data, exp) {
|
||||
t.Fatalf("err: expected %#v, got %#v", exp, secret.Data)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,13 +29,16 @@ func handleLogical(core *vault.Core, dataOnly bool) http.Handler {
|
|||
case "DELETE":
|
||||
op = logical.DeleteOperation
|
||||
case "GET":
|
||||
// Need to call ParseForm to get query params loaded
|
||||
err := r.ParseForm()
|
||||
if err != nil {
|
||||
respondError(w, http.StatusBadRequest, err)
|
||||
}
|
||||
if r.Form.Get("list") == "true" {
|
||||
op = logical.ListOperation
|
||||
} else {
|
||||
op = logical.ReadOperation
|
||||
}
|
||||
case "LIST":
|
||||
op = logical.ListOperation
|
||||
case "POST", "PUT":
|
||||
op = logical.UpdateOperation
|
||||
case "LIST":
|
||||
|
@ -71,7 +74,7 @@ func handleLogical(core *vault.Core, dataOnly bool) http.Handler {
|
|||
if !ok {
|
||||
return
|
||||
}
|
||||
if op == logical.ReadOperation && resp == nil {
|
||||
if (op == logical.ReadOperation || op == logical.ListOperation) && resp == nil {
|
||||
respondError(w, http.StatusNotFound, nil)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -141,9 +141,11 @@ func ErrorResponse(text string) *Response {
|
|||
|
||||
// ListResponse is used to format a response to a list operation.
|
||||
func ListResponse(keys []string) *Response {
|
||||
return &Response{
|
||||
Data: map[string]interface{}{
|
||||
"keys": keys,
|
||||
},
|
||||
resp := &Response{
|
||||
Data: map[string]interface{}{},
|
||||
}
|
||||
if keys != nil {
|
||||
resp.Data["keys"] = keys
|
||||
}
|
||||
return resp
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package vault
|
|||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/vault/logical"
|
||||
|
@ -153,17 +154,22 @@ func (b *CubbyholeBackend) handleList(
|
|||
if req.ClientToken == "" {
|
||||
return nil, fmt.Errorf("[ERR] cubbyhole list: Client token empty")
|
||||
}
|
||||
|
||||
// List the keys at the prefix given by the request
|
||||
keys, err := req.Storage.List(req.ClientToken + "/" + req.Path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
strippedKeys := []string{}
|
||||
for _, key := range keys {
|
||||
strippedKeys = append(strippedKeys, strings.TrimPrefix(key, req.ClientToken+"/"))
|
||||
// Strip the token; also, add the path for the same reason as in
|
||||
// passthrough
|
||||
strippedKeys := make([]string, len(keys))
|
||||
for i, key := range keys {
|
||||
strippedKeys[i] = req.MountPoint + req.Path + strings.TrimPrefix(key, req.ClientToken+"/")
|
||||
}
|
||||
|
||||
sort.Strings(strippedKeys)
|
||||
|
||||
// Generate the response
|
||||
return logical.ListResponse(strippedKeys), nil
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package vault
|
|||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
@ -218,8 +219,19 @@ func (b *PassthroughBackend) handleList(
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// A list of an actual key returns "" in the list, which can cause nasty
|
||||
// things downstream with JSON conversion, including in Go. So, prepend the
|
||||
// path and let users do what they wish.
|
||||
retKeys := make([]string, len(keys))
|
||||
for i, k := range keys {
|
||||
retKeys[i] = req.MountPoint + req.Path + k
|
||||
}
|
||||
|
||||
// Sort
|
||||
sort.Strings(retKeys)
|
||||
|
||||
// Generate the response
|
||||
return logical.ListResponse(keys), nil
|
||||
return logical.ListResponse(retKeys), nil
|
||||
}
|
||||
|
||||
func (b *PassthroughBackend) GeneratesLeases() bool {
|
||||
|
|
|
@ -23,7 +23,7 @@ Also unlike the `generic` backend, because the cubbyhole's lifetime is linked
|
|||
to an authentication token, there is no concept of a lease or lease TTL for
|
||||
values contained in the token's cubbyhole.
|
||||
|
||||
Writing to a key in the `cubbyhole/` backend will replace the old value,
|
||||
Writing to a key in the `cubbyhole` backend will replace the old value;
|
||||
the sub-fields are not merged together.
|
||||
|
||||
## Quick Start
|
||||
|
@ -52,7 +52,6 @@ As expected, the value previously set is returned to us.
|
|||
|
||||
## API
|
||||
|
||||
### /cubbyhole
|
||||
#### GET
|
||||
|
||||
<dl class="api">
|
||||
|
@ -90,6 +89,47 @@ As expected, the value previously set is returned to us.
|
|||
</dd>
|
||||
</dl>
|
||||
|
||||
#### LIST
|
||||
|
||||
<dl class="api">
|
||||
<dt>Description</dt>
|
||||
<dd>
|
||||
Returns a list of secret entries at the specified location. Folders are
|
||||
suffixed with `/`.
|
||||
</dd>
|
||||
|
||||
<dt>Method</dt>
|
||||
<dd>GET</dd>
|
||||
|
||||
<dt>URL</dt>
|
||||
<dd>`/cubbyhole/<path>?list=true`</dd>
|
||||
|
||||
<dt>Parameters</dt>
|
||||
<dd>
|
||||
None
|
||||
</dd>
|
||||
|
||||
<dt>Returns</dt>
|
||||
<dd>
|
||||
The example below shows output for a query path of `cubbyhole/` when there
|
||||
are secrets at `cubbyhole/foo` and `cubbyhole/foo/bar`; note the difference
|
||||
in the two entries.
|
||||
|
||||
```javascript
|
||||
{
|
||||
"auth": null,
|
||||
"data": {
|
||||
"keys": ["cubbyhole/foo", "cubbyhole/foo/"]
|
||||
},
|
||||
"lease_duration": 2592000,
|
||||
"lease_id": "",
|
||||
"renewable": false
|
||||
}
|
||||
```
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
#### POST/PUT
|
||||
|
||||
<dl class="api">
|
||||
|
|
|
@ -16,7 +16,7 @@ the getting started guide, you interacted with a generic secret backend
|
|||
via the `secret/` prefix that Vault mounts by default. You can mount as many
|
||||
of these backends at different mount points as you like.
|
||||
|
||||
Writing to a key in the `secret/` backend will replace the old value;
|
||||
Writing to a key in the `generic` backend will replace the old value;
|
||||
sub-fields are not merged together.
|
||||
|
||||
This backend honors the distinction between the `create` and `update`
|
||||
|
@ -39,9 +39,6 @@ to the Vault server if it results in clients accessing the value very frequently
|
|||
Also note that setting `ttl` does not actually expire the data; it is
|
||||
informational only.
|
||||
|
||||
N.B.: Prior to version 0.3, the `ttl` parameter was called `lease`. Both will
|
||||
work for 0.3, but in 0.4 `lease` will be removed.
|
||||
|
||||
As an example, we can write a new key "foo" to the generic backend
|
||||
mounted at "secret/" by default:
|
||||
|
||||
|
@ -58,8 +55,7 @@ We can test this by doing a read:
|
|||
```
|
||||
$ vault read secret/foo
|
||||
Key Value
|
||||
ttl_seconds 3600
|
||||
ttl 1h
|
||||
lease_duration 3600
|
||||
zip zap
|
||||
```
|
||||
|
||||
|
@ -69,7 +65,6 @@ seconds (one hour) as specified.
|
|||
|
||||
## API
|
||||
|
||||
### /secret
|
||||
#### GET
|
||||
|
||||
<dl class="api">
|
||||
|
@ -107,6 +102,47 @@ seconds (one hour) as specified.
|
|||
</dd>
|
||||
</dl>
|
||||
|
||||
#### LIST
|
||||
|
||||
<dl class="api">
|
||||
<dt>Description</dt>
|
||||
<dd>
|
||||
Returns a list of secret entries at the specified location. Folders are
|
||||
suffixed with `/`.
|
||||
</dd>
|
||||
|
||||
<dt>Method</dt>
|
||||
<dd>GET</dd>
|
||||
|
||||
<dt>URL</dt>
|
||||
<dd>`/secret/<path>?list=true`</dd>
|
||||
|
||||
<dt>Parameters</dt>
|
||||
<dd>
|
||||
None
|
||||
</dd>
|
||||
|
||||
<dt>Returns</dt>
|
||||
<dd>
|
||||
The example below shows output for a query path of `secret/` when there are
|
||||
secrets at `secret/foo` and `secret/foo/bar`; note the difference in the two
|
||||
entries.
|
||||
|
||||
```javascript
|
||||
{
|
||||
"auth": null,
|
||||
"data": {
|
||||
"keys": ["secret/foo", "secret/foo/"]
|
||||
},
|
||||
"lease_duration": 2592000,
|
||||
"lease_id": "",
|
||||
"renewable": false
|
||||
}
|
||||
```
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
#### POST/PUT
|
||||
|
||||
<dl class="api">
|
||||
|
|
Loading…
Reference in New Issue