Add command to look up a lease by ID (#11129)
* snapshot * basic test * update command and add documentation * update help text * typo * add changelog for lease lookup command * run go mod vendor * remove tabs from help output
This commit is contained in:
parent
eb36b68710
commit
5353279e75
|
@ -27,6 +27,27 @@ func (c *Sys) Renew(id string, increment int) (*Secret, error) {
|
|||
return ParseSecret(resp.Body)
|
||||
}
|
||||
|
||||
func (c *Sys) Lookup(id string) (*Secret, error) {
|
||||
r := c.c.NewRequest("PUT", "/v1/sys/leases/lookup")
|
||||
|
||||
body := map[string]interface{}{
|
||||
"lease_id": id,
|
||||
}
|
||||
if err := r.SetJSONBody(body); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
return ParseSecret(resp.Body)
|
||||
}
|
||||
|
||||
func (c *Sys) Revoke(id string) error {
|
||||
r := c.c.NewRequest("PUT", "/v1/sys/leases/revoke")
|
||||
body := map[string]interface{}{
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
```release-note:feature
|
||||
cli/api: Add lease lookup command
|
||||
```
|
|
@ -286,6 +286,11 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
|
|||
BaseCommand: getBaseCommand(),
|
||||
}, nil
|
||||
},
|
||||
"lease lookup": func() (cli.Command, error) {
|
||||
return &LeaseLookupCommand{
|
||||
BaseCommand: getBaseCommand(),
|
||||
}, nil
|
||||
},
|
||||
"lease revoke": func() (cli.Command, error) {
|
||||
return &LeaseRevokeCommand{
|
||||
BaseCommand: getBaseCommand(),
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
package command
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/posener/complete"
|
||||
)
|
||||
|
||||
var _ cli.Command = (*LeaseLookupCommand)(nil)
|
||||
var _ cli.CommandAutocomplete = (*LeaseLookupCommand)(nil)
|
||||
|
||||
type LeaseLookupCommand struct {
|
||||
*BaseCommand
|
||||
}
|
||||
|
||||
func (c *LeaseLookupCommand) Synopsis() string {
|
||||
return "Lookup the lease of a secret"
|
||||
}
|
||||
|
||||
func (c *LeaseLookupCommand) Help() string {
|
||||
helpText := `
|
||||
Usage: vault lease lookup ID
|
||||
|
||||
Lookup the lease information of a secret.
|
||||
|
||||
Every secret in Vault has a lease associated with it. Users can look up
|
||||
information on the lease by referencing the lease ID.
|
||||
|
||||
Lookup lease of a secret:
|
||||
|
||||
$ vault lease lookup database/creds/readonly/2f6a614c...
|
||||
|
||||
` + c.Flags().Help()
|
||||
|
||||
return strings.TrimSpace(helpText)
|
||||
}
|
||||
|
||||
func (c *LeaseLookupCommand) Flags() *FlagSets {
|
||||
set := c.flagSet(FlagSetHTTP | FlagSetOutputFormat)
|
||||
|
||||
return set
|
||||
}
|
||||
|
||||
func (c *LeaseLookupCommand) AutocompleteArgs() complete.Predictor {
|
||||
return complete.PredictAnything
|
||||
}
|
||||
|
||||
func (c *LeaseLookupCommand) AutocompleteFlags() complete.Flags {
|
||||
return c.Flags().Completions()
|
||||
}
|
||||
|
||||
func (c *LeaseLookupCommand) Run(args []string) int {
|
||||
f := c.Flags()
|
||||
|
||||
if err := f.Parse(args); err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return 1
|
||||
}
|
||||
|
||||
leaseID := ""
|
||||
|
||||
args = f.Args()
|
||||
switch len(args) {
|
||||
case 0:
|
||||
c.UI.Error("Missing ID!")
|
||||
return 1
|
||||
case 1:
|
||||
leaseID = strings.TrimSpace(args[0])
|
||||
default:
|
||||
c.UI.Error(fmt.Sprintf("Too many arguments (expected 1, got %d)", len(args)))
|
||||
return 1
|
||||
}
|
||||
|
||||
client, err := c.Client()
|
||||
if err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return 2
|
||||
}
|
||||
|
||||
secret, err := client.Sys().Lookup(leaseID)
|
||||
if err != nil {
|
||||
c.UI.Error(fmt.Sprintf("error looking up lease id %s: %s", leaseID, err))
|
||||
return 2
|
||||
}
|
||||
|
||||
return OutputSecret(c.UI, secret)
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
package command
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/vault/api"
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
||||
func testLeaseLookupCommand(tb testing.TB) (*cli.MockUi, *LeaseLookupCommand) {
|
||||
tb.Helper()
|
||||
|
||||
ui := cli.NewMockUi()
|
||||
return ui, &LeaseLookupCommand{
|
||||
BaseCommand: &BaseCommand{
|
||||
UI: ui,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// testLeaseLookupCommandMountAndLease mounts a leased secret backend and returns
|
||||
// the leaseID of an item.
|
||||
func testLeaseLookupCommandMountAndLease(tb testing.TB, client *api.Client) string {
|
||||
if err := client.Sys().Mount("testing", &api.MountInput{
|
||||
Type: "generic-leased",
|
||||
}); err != nil {
|
||||
tb.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := client.Logical().Write("testing/foo", map[string]interface{}{
|
||||
"key": "value",
|
||||
"lease": "5m",
|
||||
}); err != nil {
|
||||
tb.Fatal(err)
|
||||
}
|
||||
|
||||
// Read the secret back to get the leaseID
|
||||
secret, err := client.Logical().Read("testing/foo")
|
||||
if err != nil {
|
||||
tb.Fatal(err)
|
||||
}
|
||||
if secret == nil || secret.LeaseID == "" {
|
||||
tb.Fatalf("missing secret or lease: %#v", secret)
|
||||
}
|
||||
|
||||
return secret.LeaseID
|
||||
}
|
||||
|
||||
// TestLeaseLookupCommand_Run tests basic lookup
|
||||
func TestLeaseLookupCommand_Run(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("empty", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
client, closer := testVaultServer(t)
|
||||
defer closer()
|
||||
|
||||
_ = testLeaseLookupCommandMountAndLease(t, client)
|
||||
|
||||
ui, cmd := testLeaseLookupCommand(t)
|
||||
cmd.client = client
|
||||
|
||||
code := cmd.Run(nil)
|
||||
if exp := 1; code != exp {
|
||||
t.Errorf("expected %d to be %d", code, exp)
|
||||
}
|
||||
|
||||
combined := ui.OutputWriter.String() + ui.ErrorWriter.String()
|
||||
expectedMsg := "Missing ID!"
|
||||
if !strings.Contains(combined, expectedMsg) {
|
||||
t.Errorf("expected %q to contain %q", combined, expectedMsg)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("integration", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
client, closer := testVaultServer(t)
|
||||
defer closer()
|
||||
|
||||
leaseID := testLeaseLookupCommandMountAndLease(t, client)
|
||||
|
||||
_, cmd := testLeaseLookupCommand(t)
|
||||
cmd.client = client
|
||||
|
||||
code := cmd.Run([]string{leaseID})
|
||||
if exp := 0; code != exp {
|
||||
t.Errorf("expected %d to be %d", code, exp)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("no_tabs", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, cmd := testLeaseLookupCommand(t)
|
||||
assertNoTabs(t, cmd)
|
||||
})
|
||||
}
|
|
@ -27,6 +27,27 @@ func (c *Sys) Renew(id string, increment int) (*Secret, error) {
|
|||
return ParseSecret(resp.Body)
|
||||
}
|
||||
|
||||
func (c *Sys) Lookup(id string) (*Secret, error) {
|
||||
r := c.c.NewRequest("PUT", "/v1/sys/leases/lookup")
|
||||
|
||||
body := map[string]interface{}{
|
||||
"lease_id": id,
|
||||
}
|
||||
if err := r.SetJSONBody(body); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
return ParseSecret(resp.Body)
|
||||
}
|
||||
|
||||
func (c *Sys) Revoke(id string) error {
|
||||
r := c.c.NewRequest("PUT", "/v1/sys/leases/revoke")
|
||||
body := map[string]interface{}{
|
||||
|
|
|
@ -14,6 +14,20 @@ secrets. For leases attached to tokens, use the [`vault token`](/docs/commands/t
|
|||
|
||||
## Examples
|
||||
|
||||
Lookup a lease:
|
||||
|
||||
```shell-session
|
||||
$ vault lease lookup database/creds/readonly/27e1b9a1-27b8-83d9-9fe0-d99d786bdc83
|
||||
Key Value
|
||||
--- -----
|
||||
expire_time 2021-03-17T11:55:50.755313-05:00
|
||||
id database/creds/readonly/27e1b9a1-27b8-83d9-9fe0-d99d786bdc83
|
||||
issue_time 2021-03-17T11:45:50.755312-05:00
|
||||
last_renewal <nil>
|
||||
renewable true
|
||||
ttl 9m52s
|
||||
```
|
||||
|
||||
Renew a lease:
|
||||
|
||||
```shell-session
|
||||
|
@ -40,6 +54,7 @@ Usage: vault lease <subcommand> [options] [args]
|
|||
# ...
|
||||
|
||||
Subcommands:
|
||||
lookup Lookup lease information by lease id
|
||||
renew Renews the lease of a secret
|
||||
revoke Revokes leases and secrets
|
||||
```
|
||||
|
|
|
@ -14,6 +14,20 @@ secrets. For leases attached to tokens, use the [`vault token`](/docs/commands/t
|
|||
|
||||
## Examples
|
||||
|
||||
Lookup a lease:
|
||||
|
||||
```shell-session
|
||||
$ vault lease lookup database/creds/readonly/27e1b9a1-27b8-83d9-9fe0-d99d786bdc83
|
||||
Key Value
|
||||
--- -----
|
||||
expire_time 2021-03-17T11:55:50.755313-05:00
|
||||
id database/creds/readonly/27e1b9a1-27b8-83d9-9fe0-d99d786bdc83
|
||||
issue_time 2021-03-17T11:45:50.755312-05:00
|
||||
last_renewal <nil>
|
||||
renewable true
|
||||
ttl 9m52s
|
||||
```
|
||||
|
||||
Renew a lease:
|
||||
|
||||
```shell-session
|
||||
|
@ -40,6 +54,7 @@ Usage: vault lease <subcommand> [options] [args]
|
|||
# ...
|
||||
|
||||
Subcommands:
|
||||
lookup Lookup lease information by lease id
|
||||
renew Renews the lease of a secret
|
||||
revoke Revokes leases and secrets
|
||||
```
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
---
|
||||
layout: docs
|
||||
page_title: lease lookup - Command
|
||||
sidebar_title: <code>lookup</code>
|
||||
description: |-
|
||||
The "lease lookup" command retrieves information about a lease.
|
||||
---
|
||||
|
||||
# lease lookup
|
||||
|
||||
The `lease lookup` command retrieves information on the lease of a secret.
|
||||
|
||||
Every secret in Vault has a lease associated with it. Users can look up
|
||||
information on the lease by referencing the lease ID.
|
||||
|
||||
## Examples
|
||||
|
||||
Lookup a lease:
|
||||
|
||||
```shell-session
|
||||
$ vault lease lookup database/creds/readonly/27e1b9a1-27b8-83d9-9fe0-d99d786bdc83
|
||||
Key Value
|
||||
--- -----
|
||||
expire_time 2021-03-17T11:55:50.755313-05:00
|
||||
id database/creds/readonly/27e1b9a1-27b8-83d9-9fe0-d99d786bdc83
|
||||
issue_time 2021-03-17T11:45:50.755312-05:00
|
||||
last_renewal <nil>
|
||||
renewable true
|
||||
ttl 9m52s
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
There are no flags beyond the [standard set of flags](/docs/commands)
|
||||
included on all commands.
|
Loading…
Reference in New Issue