From 1872f3c267ecf1c91ea06ddff5d7c37fe2d0f21f Mon Sep 17 00:00:00 2001 From: catsby Date: Mon, 15 Mar 2021 13:34:20 -0500 Subject: [PATCH 1/8] snapshot --- api/sys_leases.go | 21 +++++ command/commands.go | 5 ++ command/lease_lookup.go | 100 ++++++++++++++++++++++ command/lease_lookup_test.go | 156 +++++++++++++++++++++++++++++++++++ 4 files changed, 282 insertions(+) create mode 100644 command/lease_lookup.go create mode 100644 command/lease_lookup_test.go diff --git a/api/sys_leases.go b/api/sys_leases.go index 40826a7d23f1..e018015deddd 100644 --- a/api/sys_leases.go +++ b/api/sys_leases.go @@ -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{}{ diff --git a/command/commands.go b/command/commands.go index 0635cf1b6d30..6fb676b64cba 100644 --- a/command/commands.go +++ b/command/commands.go @@ -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(), diff --git a/command/lease_lookup.go b/command/lease_lookup.go new file mode 100644 index 000000000000..102307e2d736 --- /dev/null +++ b/command/lease_lookup.go @@ -0,0 +1,100 @@ +package command + +import ( + "fmt" + "strings" + "time" + + "github.com/mitchellh/cli" + "github.com/posener/complete" +) + +var _ cli.Command = (*LeaseLookupCommand)(nil) +var _ cli.CommandAutocomplete = (*LeaseLookupCommand)(nil) + +type LeaseLookupCommand struct { + *BaseCommand + + flagIncrement time.Duration +} + +func (c *LeaseLookupCommand) Synopsis() string { + return "Lookup the lease of a secret" +} + +func (c *LeaseLookupCommand) Help() string { + helpText := ` +Usage: vault lease lookup ID + + Renews the lease on a secret, extending the time that it can be used before + it is revoked by Vault. + + Every secret in Vault has a lease associated with it. If the owner of the + secret wants to use it longer than the lease, then it must be renewed. + Renewing the lease does not change the contents of the secret. The ID is the + full path lease ID. + + Renew a secret: + + $ vault lease renew database/creds/readonly/2f6a614c... + + Lease renewal will fail if the secret is not renewable, the secret has already + been revoked, or if the secret has already reached its maximum TTL. + + For a full list of examples, please see the documentation. + +` + 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 renewing %s: %s", leaseID, err)) + return 2 + } + + return OutputSecret(c.UI, secret) +} diff --git a/command/lease_lookup_test.go b/command/lease_lookup_test.go new file mode 100644 index 000000000000..3ab3f6723996 --- /dev/null +++ b/command/lease_lookup_test.go @@ -0,0 +1,156 @@ +package command + +import ( + "testing" + + "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 +// } + +// func TestLeaseLookupCommand_Run(t *testing.T) { +// t.Parallel() + +// cases := []struct { +// name string +// args []string +// out string +// code int +// }{ +// { +// "empty", +// nil, +// "Missing ID!", +// 1, +// }, +// { +// "increment", +// []string{"-increment", "60s"}, +// "foo", +// 0, +// }, +// { +// "increment_no_suffix", +// []string{"-increment", "60"}, +// "foo", +// 0, +// }, +// } + +// t.Run("group", func(t *testing.T) { +// t.Parallel() + +// for _, tc := range cases { +// tc := tc + +// t.Run(tc.name, func(t *testing.T) { +// t.Parallel() + +// client, closer := testVaultServer(t) +// defer closer() + +// leaseID := testLeaseLookupCommandMountAndLease(t, client) + +// ui, cmd := testLeaseLookupCommand(t) +// cmd.client = client + +// if tc.args != nil { +// tc.args = append(tc.args, leaseID) +// } +// code := cmd.Run(tc.args) +// if code != tc.code { +// t.Errorf("expected %d to be %d", code, tc.code) +// } + +// combined := ui.OutputWriter.String() + ui.ErrorWriter.String() +// if !strings.Contains(combined, tc.out) { +// t.Errorf("expected %q to contain %q", combined, tc.out) +// } +// }) +// } +// }) + +// 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("communication_failure", func(t *testing.T) { +// t.Parallel() + +// client, closer := testVaultServerBad(t) +// defer closer() + +// ui, cmd := testLeaseLookupCommand(t) +// cmd.client = client + +// code := cmd.Run([]string{ +// "foo/bar", +// }) +// if exp := 2; code != exp { +// t.Errorf("expected %d to be %d", code, exp) +// } + +// expected := "Error renewing foo/bar: " +// combined := ui.OutputWriter.String() + ui.ErrorWriter.String() +// if !strings.Contains(combined, expected) { +// t.Errorf("expected %q to contain %q", combined, expected) +// } +// }) + +// t.Run("no_tabs", func(t *testing.T) { +// t.Parallel() + +// _, cmd := testLeaseLookupCommand(t) +// assertNoTabs(t, cmd) +// }) +// } From e3678ee3d573083421d649e2dc11ece3dda1de3d Mon Sep 17 00:00:00 2001 From: catsby Date: Mon, 15 Mar 2021 16:48:12 -0500 Subject: [PATCH 2/8] basic test --- command/lease_lookup_test.go | 218 +++++++++++++---------------------- 1 file changed, 81 insertions(+), 137 deletions(-) diff --git a/command/lease_lookup_test.go b/command/lease_lookup_test.go index 3ab3f6723996..4de63200f5ce 100644 --- a/command/lease_lookup_test.go +++ b/command/lease_lookup_test.go @@ -1,8 +1,10 @@ package command import ( + "strings" "testing" + "github.com/hashicorp/vault/api" "github.com/mitchellh/cli" ) @@ -17,140 +19,82 @@ func testLeaseLookupCommand(tb testing.TB) (*cli.MockUi, *LeaseLookupCommand) { } } -// // 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 -// } - -// func TestLeaseLookupCommand_Run(t *testing.T) { -// t.Parallel() - -// cases := []struct { -// name string -// args []string -// out string -// code int -// }{ -// { -// "empty", -// nil, -// "Missing ID!", -// 1, -// }, -// { -// "increment", -// []string{"-increment", "60s"}, -// "foo", -// 0, -// }, -// { -// "increment_no_suffix", -// []string{"-increment", "60"}, -// "foo", -// 0, -// }, -// } - -// t.Run("group", func(t *testing.T) { -// t.Parallel() - -// for _, tc := range cases { -// tc := tc - -// t.Run(tc.name, func(t *testing.T) { -// t.Parallel() - -// client, closer := testVaultServer(t) -// defer closer() - -// leaseID := testLeaseLookupCommandMountAndLease(t, client) - -// ui, cmd := testLeaseLookupCommand(t) -// cmd.client = client - -// if tc.args != nil { -// tc.args = append(tc.args, leaseID) -// } -// code := cmd.Run(tc.args) -// if code != tc.code { -// t.Errorf("expected %d to be %d", code, tc.code) -// } - -// combined := ui.OutputWriter.String() + ui.ErrorWriter.String() -// if !strings.Contains(combined, tc.out) { -// t.Errorf("expected %q to contain %q", combined, tc.out) -// } -// }) -// } -// }) - -// 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("communication_failure", func(t *testing.T) { -// t.Parallel() - -// client, closer := testVaultServerBad(t) -// defer closer() - -// ui, cmd := testLeaseLookupCommand(t) -// cmd.client = client - -// code := cmd.Run([]string{ -// "foo/bar", -// }) -// if exp := 2; code != exp { -// t.Errorf("expected %d to be %d", code, exp) -// } - -// expected := "Error renewing foo/bar: " -// combined := ui.OutputWriter.String() + ui.ErrorWriter.String() -// if !strings.Contains(combined, expected) { -// t.Errorf("expected %q to contain %q", combined, expected) -// } -// }) - -// t.Run("no_tabs", func(t *testing.T) { -// t.Parallel() - -// _, cmd := testLeaseLookupCommand(t) -// assertNoTabs(t, cmd) -// }) -// } +// 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) + }) +} From c41696113aa981bdbd8031ffce78782a2f6dd0e4 Mon Sep 17 00:00:00 2001 From: catsby Date: Wed, 17 Mar 2021 11:59:52 -0500 Subject: [PATCH 3/8] update command and add documentation --- command/lease_lookup.go | 2 +- website/content/docs/commands/lease.mdx | 15 ++++++++ website/content/docs/commands/lease/index.mdx | 15 ++++++++ .../content/docs/commands/lease/lookup.mdx | 35 +++++++++++++++++++ 4 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 website/content/docs/commands/lease/lookup.mdx diff --git a/command/lease_lookup.go b/command/lease_lookup.go index 102307e2d736..e2ac873438fc 100644 --- a/command/lease_lookup.go +++ b/command/lease_lookup.go @@ -92,7 +92,7 @@ func (c *LeaseLookupCommand) Run(args []string) int { secret, err := client.Sys().Lookup(leaseID) if err != nil { - c.UI.Error(fmt.Sprintf("Error renewing %s: %s", leaseID, err)) + c.UI.Error(fmt.Sprintf("error looking up lease id %s: %s", leaseID, err)) return 2 } diff --git a/website/content/docs/commands/lease.mdx b/website/content/docs/commands/lease.mdx index a67671daafe2..f76e197e8f70 100644 --- a/website/content/docs/commands/lease.mdx +++ b/website/content/docs/commands/lease.mdx @@ -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 +renewable true +ttl 9m52s +``` + Renew a lease: ```shell-session @@ -40,6 +54,7 @@ Usage: vault lease [options] [args] # ... Subcommands: + lookup Lookup lease information by lease id renew Renews the lease of a secret revoke Revokes leases and secrets ``` diff --git a/website/content/docs/commands/lease/index.mdx b/website/content/docs/commands/lease/index.mdx index a67671daafe2..f76e197e8f70 100644 --- a/website/content/docs/commands/lease/index.mdx +++ b/website/content/docs/commands/lease/index.mdx @@ -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 +renewable true +ttl 9m52s +``` + Renew a lease: ```shell-session @@ -40,6 +54,7 @@ Usage: vault lease [options] [args] # ... Subcommands: + lookup Lookup lease information by lease id renew Renews the lease of a secret revoke Revokes leases and secrets ``` diff --git a/website/content/docs/commands/lease/lookup.mdx b/website/content/docs/commands/lease/lookup.mdx new file mode 100644 index 000000000000..62f16cbaae12 --- /dev/null +++ b/website/content/docs/commands/lease/lookup.mdx @@ -0,0 +1,35 @@ +--- +layout: docs +page_title: lease lookup - Command +sidebar_title: lookup +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 +renewable true +ttl 9m52s +``` + +## Usage + +There are no flags beyond the [standard set of flags](/docs/commands) +included on all commands. From de57cbcbf675655fb4a7519ddffd0c8128be5244 Mon Sep 17 00:00:00 2001 From: catsby Date: Wed, 17 Mar 2021 12:03:21 -0500 Subject: [PATCH 4/8] update help text --- command/lease_lookup.go | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/command/lease_lookup.go b/command/lease_lookup.go index e2ac873438fc..3cf8fabf20aa 100644 --- a/command/lease_lookup.go +++ b/command/lease_lookup.go @@ -3,7 +3,6 @@ package command import ( "fmt" "strings" - "time" "github.com/mitchellh/cli" "github.com/posener/complete" @@ -14,8 +13,6 @@ var _ cli.CommandAutocomplete = (*LeaseLookupCommand)(nil) type LeaseLookupCommand struct { *BaseCommand - - flagIncrement time.Duration } func (c *LeaseLookupCommand) Synopsis() string { @@ -26,22 +23,14 @@ func (c *LeaseLookupCommand) Help() string { helpText := ` Usage: vault lease lookup ID - Renews the lease on a secret, extending the time that it can be used before - it is revoked by Vault. - - Every secret in Vault has a lease associated with it. If the owner of the - secret wants to use it longer than the lease, then it must be renewed. - Renewing the lease does not change the contents of the secret. The ID is the - full path lease ID. - - Renew a secret: + Look the lease information of a secret. - $ vault lease renew database/creds/readonly/2f6a614c... + Every secret in Vault has a lease associated with it. Users can look up + information on the lease by referencing the lease ID. - Lease renewal will fail if the secret is not renewable, the secret has already - been revoked, or if the secret has already reached its maximum TTL. + Lookup lease of a secret: - For a full list of examples, please see the documentation. + $ vault lease lookup database/creds/readonly/2f6a614c... ` + c.Flags().Help() From 3bf825eff6e86a50df56ac880eb72a04857c3322 Mon Sep 17 00:00:00 2001 From: catsby Date: Wed, 17 Mar 2021 12:05:54 -0500 Subject: [PATCH 5/8] typo --- command/lease_lookup.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/command/lease_lookup.go b/command/lease_lookup.go index 3cf8fabf20aa..63b4d9cf014e 100644 --- a/command/lease_lookup.go +++ b/command/lease_lookup.go @@ -23,7 +23,7 @@ func (c *LeaseLookupCommand) Help() string { helpText := ` Usage: vault lease lookup ID - Look the lease information of a secret. + 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. From a16e2ce4df960e33a1adbdb6531fdc7a30dd9d56 Mon Sep 17 00:00:00 2001 From: catsby Date: Wed, 17 Mar 2021 16:20:02 -0500 Subject: [PATCH 6/8] add changelog for lease lookup command --- changelog/11129.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 changelog/11129.txt diff --git a/changelog/11129.txt b/changelog/11129.txt new file mode 100644 index 000000000000..8faedf23a6eb --- /dev/null +++ b/changelog/11129.txt @@ -0,0 +1,3 @@ +```release-note:feature +cli/api: Add lease lookup command +``` From 1689c7c48e2b7402cf79608cdfa5e96292587e1a Mon Sep 17 00:00:00 2001 From: catsby Date: Wed, 17 Mar 2021 19:56:10 -0500 Subject: [PATCH 7/8] run go mod vendor --- .../hashicorp/vault/api/sys_leases.go | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/vendor/github.com/hashicorp/vault/api/sys_leases.go b/vendor/github.com/hashicorp/vault/api/sys_leases.go index 40826a7d23f1..e018015deddd 100644 --- a/vendor/github.com/hashicorp/vault/api/sys_leases.go +++ b/vendor/github.com/hashicorp/vault/api/sys_leases.go @@ -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{}{ From d562850b8546b1b0da2f20f2e42713db95158486 Mon Sep 17 00:00:00 2001 From: catsby Date: Thu, 18 Mar 2021 08:23:40 -0500 Subject: [PATCH 8/8] remove tabs from help output --- command/lease_lookup.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/command/lease_lookup.go b/command/lease_lookup.go index 63b4d9cf014e..4d5aa6da3336 100644 --- a/command/lease_lookup.go +++ b/command/lease_lookup.go @@ -25,8 +25,8 @@ 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. + 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: