Add lease subcommand
This commit is contained in:
parent
02341c3b6a
commit
76de999b34
|
@ -0,0 +1,40 @@
|
|||
package command
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
||||
var _ cli.Command = (*LeaseCommand)(nil)
|
||||
|
||||
type LeaseCommand struct {
|
||||
*BaseCommand
|
||||
}
|
||||
|
||||
func (c *LeaseCommand) Synopsis() string {
|
||||
return "Interact with leases"
|
||||
}
|
||||
|
||||
func (c *LeaseCommand) Help() string {
|
||||
helpText := `
|
||||
Usage: vault lease <subcommand> [options] [args]
|
||||
|
||||
This command groups subcommands for interacting with leases. Users can revoke
|
||||
or renew leases.
|
||||
|
||||
Renew a lease:
|
||||
|
||||
$ vault lease renew database/creds/readonly/2f6a614c...
|
||||
|
||||
Revoke a lease:
|
||||
|
||||
$ vault lease revoke database/creds/readonly/2f6a614c...
|
||||
`
|
||||
|
||||
return strings.TrimSpace(helpText)
|
||||
}
|
||||
|
||||
func (c *LeaseCommand) Run(args []string) int {
|
||||
return cli.RunResultHelp
|
||||
}
|
|
@ -9,24 +9,22 @@ import (
|
|||
"github.com/posener/complete"
|
||||
)
|
||||
|
||||
// Ensure we are implementing the right interfaces.
|
||||
var _ cli.Command = (*RenewCommand)(nil)
|
||||
var _ cli.CommandAutocomplete = (*RenewCommand)(nil)
|
||||
var _ cli.Command = (*LeaseRenewCommand)(nil)
|
||||
var _ cli.CommandAutocomplete = (*LeaseRenewCommand)(nil)
|
||||
|
||||
// RenewCommand is a Command that mounts a new mount.
|
||||
type RenewCommand struct {
|
||||
type LeaseRenewCommand struct {
|
||||
*BaseCommand
|
||||
|
||||
flagIncrement time.Duration
|
||||
}
|
||||
|
||||
func (c *RenewCommand) Synopsis() string {
|
||||
func (c *LeaseRenewCommand) Synopsis() string {
|
||||
return "Renews the lease of a secret"
|
||||
}
|
||||
|
||||
func (c *RenewCommand) Help() string {
|
||||
func (c *LeaseRenewCommand) Help() string {
|
||||
helpText := `
|
||||
Usage: vault renew [options] ID
|
||||
Usage: vault lease renew [options] ID
|
||||
|
||||
Renews the lease on a secret, extending the time that it can be used before
|
||||
it is revoked by Vault.
|
||||
|
@ -38,7 +36,7 @@ Usage: vault renew [options] ID
|
|||
|
||||
Renew a secret:
|
||||
|
||||
$ vault renew database/creds/readonly/2f6a614c-4aa2-7b19-24b9-ad944a8d4de6
|
||||
$ 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.
|
||||
|
@ -50,7 +48,7 @@ Usage: vault renew [options] ID
|
|||
return strings.TrimSpace(helpText)
|
||||
}
|
||||
|
||||
func (c *RenewCommand) Flags() *FlagSets {
|
||||
func (c *LeaseRenewCommand) Flags() *FlagSets {
|
||||
set := c.flagSet(FlagSetHTTP | FlagSetOutputFormat)
|
||||
f := set.NewFlagSet("Command Options")
|
||||
|
||||
|
@ -67,15 +65,15 @@ func (c *RenewCommand) Flags() *FlagSets {
|
|||
return set
|
||||
}
|
||||
|
||||
func (c *RenewCommand) AutocompleteArgs() complete.Predictor {
|
||||
func (c *LeaseRenewCommand) AutocompleteArgs() complete.Predictor {
|
||||
return complete.PredictAnything
|
||||
}
|
||||
|
||||
func (c *RenewCommand) AutocompleteFlags() complete.Flags {
|
||||
func (c *LeaseRenewCommand) AutocompleteFlags() complete.Flags {
|
||||
return c.Flags().Completions()
|
||||
}
|
||||
|
||||
func (c *RenewCommand) Run(args []string) int {
|
||||
func (c *LeaseRenewCommand) Run(args []string) int {
|
||||
f := c.Flags()
|
||||
|
||||
if err := f.Parse(args); err != nil {
|
|
@ -8,20 +8,20 @@ import (
|
|||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
||||
func testRenewCommand(tb testing.TB) (*cli.MockUi, *RenewCommand) {
|
||||
func testLeaseRenewCommand(tb testing.TB) (*cli.MockUi, *LeaseRenewCommand) {
|
||||
tb.Helper()
|
||||
|
||||
ui := cli.NewMockUi()
|
||||
return ui, &RenewCommand{
|
||||
return ui, &LeaseRenewCommand{
|
||||
BaseCommand: &BaseCommand{
|
||||
UI: ui,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// testRenewCommandMountAndLease mounts a leased secret backend and returns
|
||||
// testLeaseRenewCommandMountAndLease mounts a leased secret backend and returns
|
||||
// the leaseID of an item.
|
||||
func testRenewCommandMountAndLease(tb testing.TB, client *api.Client) string {
|
||||
func testLeaseRenewCommandMountAndLease(tb testing.TB, client *api.Client) string {
|
||||
if err := client.Sys().Mount("testing", &api.MountInput{
|
||||
Type: "generic-leased",
|
||||
}); err != nil {
|
||||
|
@ -47,7 +47,7 @@ func testRenewCommandMountAndLease(tb testing.TB, client *api.Client) string {
|
|||
return secret.LeaseID
|
||||
}
|
||||
|
||||
func TestRenewCommand_Run(t *testing.T) {
|
||||
func TestLeaseRenewCommand_Run(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
cases := []struct {
|
||||
|
@ -100,9 +100,9 @@ func TestRenewCommand_Run(t *testing.T) {
|
|||
client, closer := testVaultServer(t)
|
||||
defer closer()
|
||||
|
||||
leaseID := testRenewCommandMountAndLease(t, client)
|
||||
leaseID := testLeaseRenewCommandMountAndLease(t, client)
|
||||
|
||||
ui, cmd := testRenewCommand(t)
|
||||
ui, cmd := testLeaseRenewCommand(t)
|
||||
cmd.client = client
|
||||
|
||||
if tc.args != nil {
|
||||
|
@ -127,9 +127,9 @@ func TestRenewCommand_Run(t *testing.T) {
|
|||
client, closer := testVaultServer(t)
|
||||
defer closer()
|
||||
|
||||
leaseID := testRenewCommandMountAndLease(t, client)
|
||||
leaseID := testLeaseRenewCommandMountAndLease(t, client)
|
||||
|
||||
_, cmd := testRenewCommand(t)
|
||||
_, cmd := testLeaseRenewCommand(t)
|
||||
cmd.client = client
|
||||
|
||||
code := cmd.Run([]string{leaseID})
|
||||
|
@ -144,7 +144,7 @@ func TestRenewCommand_Run(t *testing.T) {
|
|||
client, closer := testVaultServerBad(t)
|
||||
defer closer()
|
||||
|
||||
ui, cmd := testRenewCommand(t)
|
||||
ui, cmd := testLeaseRenewCommand(t)
|
||||
cmd.client = client
|
||||
|
||||
code := cmd.Run([]string{
|
||||
|
@ -164,7 +164,7 @@ func TestRenewCommand_Run(t *testing.T) {
|
|||
t.Run("no_tabs", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, cmd := testRenewCommand(t)
|
||||
_, cmd := testLeaseRenewCommand(t)
|
||||
assertNoTabs(t, cmd)
|
||||
})
|
||||
}
|
|
@ -8,50 +8,48 @@ import (
|
|||
"github.com/posener/complete"
|
||||
)
|
||||
|
||||
// Ensure we are implementing the right interfaces.
|
||||
var _ cli.Command = (*ReadCommand)(nil)
|
||||
var _ cli.CommandAutocomplete = (*ReadCommand)(nil)
|
||||
var _ cli.Command = (*LeaseRevokeCommand)(nil)
|
||||
var _ cli.CommandAutocomplete = (*LeaseRevokeCommand)(nil)
|
||||
|
||||
// RevokeCommand is a Command that mounts a new mount.
|
||||
type RevokeCommand struct {
|
||||
type LeaseRevokeCommand struct {
|
||||
*BaseCommand
|
||||
|
||||
flagForce bool
|
||||
flagPrefix bool
|
||||
}
|
||||
|
||||
func (c *RevokeCommand) Synopsis() string {
|
||||
func (c *LeaseRevokeCommand) Synopsis() string {
|
||||
return "Revokes leases and secrets"
|
||||
}
|
||||
|
||||
func (c *RevokeCommand) Help() string {
|
||||
func (c *LeaseRevokeCommand) Help() string {
|
||||
helpText := `
|
||||
Usage: vault revoke [options] ID
|
||||
Usage: vault lease revoke [options] ID
|
||||
|
||||
Revokes secrets by their lease ID. This command can revoke a single secret
|
||||
or multiple secrets based on a path-matched prefix.
|
||||
|
||||
Revoke a single lease:
|
||||
|
||||
$ vault revoke database/creds/readonly/2f6a614c...
|
||||
$ vault lease revoke database/creds/readonly/2f6a614c...
|
||||
|
||||
Revoke all leases for a role:
|
||||
|
||||
$ vault revoke -prefix aws/creds/deploy
|
||||
$ vault lease revoke -prefix aws/creds/deploy
|
||||
|
||||
Force delete leases from Vault even if backend revocation fails:
|
||||
Force delete leases from Vault even if secret engine revocation fails:
|
||||
|
||||
$ vault revoke -force -prefix consul/creds
|
||||
$ vault lease revoke -force -prefix consul/creds
|
||||
|
||||
For a full list of examples and paths, please see the documentation that
|
||||
corresponds to the secret backend in use.
|
||||
corresponds to the secret engine in use.
|
||||
|
||||
` + c.Flags().Help()
|
||||
|
||||
return strings.TrimSpace(helpText)
|
||||
}
|
||||
|
||||
func (c *RevokeCommand) Flags() *FlagSets {
|
||||
func (c *LeaseRevokeCommand) Flags() *FlagSets {
|
||||
set := c.flagSet(FlagSetHTTP)
|
||||
f := set.NewFlagSet("Command Options")
|
||||
|
||||
|
@ -60,10 +58,10 @@ func (c *RevokeCommand) Flags() *FlagSets {
|
|||
Aliases: []string{"f"},
|
||||
Target: &c.flagForce,
|
||||
Default: false,
|
||||
Usage: "Delete the lease from Vault even if the backend revocation " +
|
||||
Usage: "Delete the lease from Vault even if the secret engine revocation " +
|
||||
"fails. This is meant for recovery situations where the secret " +
|
||||
"in the backend was manually removed. If this flag is specified, " +
|
||||
"-prefix is also required.",
|
||||
"in the target secret engine was manually removed. If this flag is " +
|
||||
"specified, -prefix is also required.",
|
||||
})
|
||||
|
||||
f.BoolVar(&BoolVar{
|
||||
|
@ -77,15 +75,15 @@ func (c *RevokeCommand) Flags() *FlagSets {
|
|||
return set
|
||||
}
|
||||
|
||||
func (c *RevokeCommand) AutocompleteArgs() complete.Predictor {
|
||||
func (c *LeaseRevokeCommand) AutocompleteArgs() complete.Predictor {
|
||||
return c.PredictVaultFiles()
|
||||
}
|
||||
|
||||
func (c *RevokeCommand) AutocompleteFlags() complete.Flags {
|
||||
func (c *LeaseRevokeCommand) AutocompleteFlags() complete.Flags {
|
||||
return c.Flags().Completions()
|
||||
}
|
||||
|
||||
func (c *RevokeCommand) Run(args []string) int {
|
||||
func (c *LeaseRevokeCommand) Run(args []string) int {
|
||||
f := c.Flags()
|
||||
|
||||
if err := f.Parse(args); err != nil {
|
||||
|
@ -94,13 +92,11 @@ func (c *RevokeCommand) Run(args []string) int {
|
|||
}
|
||||
|
||||
args = f.Args()
|
||||
leaseID, remaining, err := extractID(args)
|
||||
if err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
switch {
|
||||
case len(args) < 1:
|
||||
c.UI.Error(fmt.Sprintf("Not enough arguments (expected 1, got %d)", len(args)))
|
||||
return 1
|
||||
}
|
||||
|
||||
if len(remaining) > 0 {
|
||||
case len(args) > 1:
|
||||
c.UI.Error(fmt.Sprintf("Too many arguments (expected 1, got %d)", len(args)))
|
||||
return 1
|
||||
}
|
||||
|
@ -116,10 +112,12 @@ func (c *RevokeCommand) Run(args []string) int {
|
|||
return 2
|
||||
}
|
||||
|
||||
leaseID := strings.TrimSpace(args[0])
|
||||
|
||||
switch {
|
||||
case c.flagForce && c.flagPrefix:
|
||||
c.UI.Warn(wrapAtLength("Warning! Force-removing leases can cause Vault " +
|
||||
"to become out of sync with credential backends!"))
|
||||
"to become out of sync with secret engines!"))
|
||||
if err := client.Sys().RevokeForce(leaseID); err != nil {
|
||||
c.UI.Error(fmt.Sprintf("Error force revoking leases with prefix %s: %s", leaseID, err))
|
||||
return 2
|
|
@ -8,18 +8,18 @@ import (
|
|||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
||||
func testRevokeCommand(tb testing.TB) (*cli.MockUi, *RevokeCommand) {
|
||||
func testLeaseRevokeCommand(tb testing.TB) (*cli.MockUi, *LeaseRevokeCommand) {
|
||||
tb.Helper()
|
||||
|
||||
ui := cli.NewMockUi()
|
||||
return ui, &RevokeCommand{
|
||||
return ui, &LeaseRevokeCommand{
|
||||
BaseCommand: &BaseCommand{
|
||||
UI: ui,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestRevokeCommand_Run(t *testing.T) {
|
||||
func TestLeaseRevokeCommand_Run(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
cases := []struct {
|
||||
|
@ -85,7 +85,7 @@ func TestRevokeCommand_Run(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ui, cmd := testRevokeCommand(t)
|
||||
ui, cmd := testLeaseRevokeCommand(t)
|
||||
cmd.client = client
|
||||
|
||||
tc.args = append(tc.args, secret.LeaseID)
|
||||
|
@ -108,7 +108,7 @@ func TestRevokeCommand_Run(t *testing.T) {
|
|||
client, closer := testVaultServerBad(t)
|
||||
defer closer()
|
||||
|
||||
ui, cmd := testRevokeCommand(t)
|
||||
ui, cmd := testLeaseRevokeCommand(t)
|
||||
cmd.client = client
|
||||
|
||||
code := cmd.Run([]string{
|
||||
|
@ -128,7 +128,7 @@ func TestRevokeCommand_Run(t *testing.T) {
|
|||
t.Run("no_tabs", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, cmd := testRevokeCommand(t)
|
||||
_, cmd := testLeaseRevokeCommand(t)
|
||||
assertNoTabs(t, cmd)
|
||||
})
|
||||
}
|
Loading…
Reference in New Issue