open-vault/command/revoke.go
Jeff Mitchell cd86226845 Add forced revocation.
In some situations, it can be impossible to revoke leases (for instance,
if someone has gone and manually removed users created by Vault). This
can not only cause Vault to cycle trying to revoke them, but it also
prevents mounts from being unmounted, leaving them in a tainted state
where the only operations allowed are to revoke (or rollback), which
will never successfully complete.

This adds a new endpoint that works similarly to `revoke-prefix` but
ignores errors coming from a backend upon revocation (it does not ignore
errors coming from within the expiration manager, such as errors
accessing the data store). This can be used to force Vault to abandon
leases.

Like `revoke-prefix`, this is a very sensitive operation and requires
`sudo`. It is implemented as a separate endpoint, rather than an
argument to `revoke-prefix`, to ensure that control can be delegated
appropriately, as even most administrators should not normally have
this privilege.

Fixes #1135
2016-03-03 10:13:59 -05:00

96 lines
2.2 KiB
Go

package command
import (
"fmt"
"strings"
)
// RevokeCommand is a Command that mounts a new mount.
type RevokeCommand struct {
Meta
}
func (c *RevokeCommand) Run(args []string) int {
var prefix, force bool
flags := c.Meta.FlagSet("revoke", FlagSetDefault)
flags.BoolVar(&prefix, "prefix", false, "")
flags.BoolVar(&force, "force", 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 {
flags.Usage()
c.Ui.Error(fmt.Sprintf(
"\nRevoke expects one argument: the ID to revoke"))
return 1
}
leaseId := args[0]
client, err := c.Client()
if err != nil {
c.Ui.Error(fmt.Sprintf(
"Error initializing client: %s", err))
return 2
}
switch {
case force && !prefix:
c.Ui.Error(fmt.Sprintf(
"-force requires -prefix"))
return 1
case force && prefix:
err = client.Sys().RevokeForce(leaseId)
case prefix:
err = client.Sys().RevokePrefix(leaseId)
default:
err = client.Sys().Revoke(leaseId)
}
if err != nil {
c.Ui.Error(fmt.Sprintf(
"Revoke error: %s", err))
return 1
}
c.Ui.Output(fmt.Sprintf("Key revoked with ID '%s'.", leaseId))
return 0
}
func (c *RevokeCommand) Synopsis() string {
return "Revoke a secret."
}
func (c *RevokeCommand) Help() string {
helpText := `
Usage: vault revoke [options] id
Revoke a secret by its lease ID.
This command revokes a secret by its lease ID that was returned with it. Once
the key is revoked, it is no longer valid.
With the -prefix flag, the revoke is done by prefix: any secret prefixed with
the given partial ID is revoked. Lease IDs are structured in such a way to
make revocation of prefixes useful.
With the -force flag, the lease is removed from Vault even if the revocation
fails. This is meant for certain recovery scenarios and should not be used
lightly. This option requires -prefix.
General Options:
` + generalOptionsUsage() + `
Revoke Options:
-prefix=true Revoke all secrets with the matching prefix. This
defaults to false: an exact revocation.
-force=true Delete the lease even if the actual revocation
operation fails.
`
return strings.TrimSpace(helpText)
}