Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add command to look up a lease by ID #11129

Merged
merged 8 commits into from Mar 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
21 changes: 21 additions & 0 deletions api/sys_leases.go
Expand Up @@ -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{}{
Expand Down
3 changes: 3 additions & 0 deletions changelog/11129.txt
@@ -0,0 +1,3 @@
```release-note:feature
cli/api: Add lease lookup command
```
5 changes: 5 additions & 0 deletions command/commands.go
Expand Up @@ -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(),
Expand Down
89 changes: 89 additions & 0 deletions command/lease_lookup.go
@@ -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)
}
100 changes: 100 additions & 0 deletions command/lease_lookup_test.go
@@ -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)
})
}
21 changes: 21 additions & 0 deletions vendor/github.com/hashicorp/vault/api/sys_leases.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions website/content/docs/commands/lease.mdx
Expand Up @@ -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
Expand All @@ -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
```
Expand Down
15 changes: 15 additions & 0 deletions website/content/docs/commands/lease/index.mdx
Expand Up @@ -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
Expand All @@ -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
```
Expand Down
35 changes: 35 additions & 0 deletions website/content/docs/commands/lease/lookup.mdx
@@ -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.