Add "operator" subcommand

This commit is contained in:
Seth Vargo
2017-09-07 22:03:12 -04:00
parent 387cce957e
commit ef86e95eff
17 changed files with 255 additions and 249 deletions

47
command/operator.go Normal file
View File

@@ -0,0 +1,47 @@
package command
import (
"strings"
"github.com/mitchellh/cli"
)
var _ cli.Command = (*OperatorCommand)(nil)
type OperatorCommand struct {
*BaseCommand
}
func (c *OperatorCommand) Synopsis() string {
return "Perform operator-specific tasks"
}
func (c *OperatorCommand) Help() string {
helpText := `
Usage: vault operator <subcommand> [options] [args]
This command groups subcommands for operators interacting with Vault. Most
users will not need to interact with these commands. Here are a few examples
of the operator commands:
Initialize a new Vault cluster:
$ vault operator init
Force a Vault to resign leadership in a cluster:
$ vault operator step-down
Rotate Vault's underlying encryption key:
$ vault operator rotate
Please see the individual subcommand help for detailed usage information.
`
return strings.TrimSpace(helpText)
}
func (c *OperatorCommand) Run(args []string) int {
return cli.RunResultHelp
}

View File

@@ -18,12 +18,10 @@ import (
"github.com/posener/complete" "github.com/posener/complete"
) )
// Ensure we are implementing the right interfaces. var _ cli.Command = (*OperatorGenerateRootCommand)(nil)
var _ cli.Command = (*GenerateRootCommand)(nil) var _ cli.CommandAutocomplete = (*OperatorGenerateRootCommand)(nil)
var _ cli.CommandAutocomplete = (*GenerateRootCommand)(nil)
// GenerateRootCommand is a Command that generates a new root token. type OperatorGenerateRootCommand struct {
type GenerateRootCommand struct {
*BaseCommand *BaseCommand
flagInit bool flagInit bool
@@ -36,26 +34,26 @@ type GenerateRootCommand struct {
flagGenerateOTP bool flagGenerateOTP bool
// Deprecation // Deprecation
// TODO: remove in 0.9.9 // TODO: remove in 0.9.0
flagGenOTP bool flagGenOTP bool
testStdin io.Reader // for tests testStdin io.Reader // for tests
} }
func (c *GenerateRootCommand) Synopsis() string { func (c *OperatorGenerateRootCommand) Synopsis() string {
return "Generates a new root token" return "Generates a new root token"
} }
func (c *GenerateRootCommand) Help() string { func (c *OperatorGenerateRootCommand) Help() string {
helpText := ` helpText := `
Usage: vault generate-root [options] [KEY] Usage: vault operator generate-root [options] [KEY]
Generates a new root token by combining a quorum of share holders. One of Generates a new root token by combining a quorum of share holders. One of
the following must be provided to start the root token generation: the following must be provided to start the root token generation:
- A base64-encoded one-time-password (OTP) provided via the "-otp" flag. - A base64-encoded one-time-password (OTP) provided via the "-otp" flag.
Use the "-generate-otp" flag to generate a usable value. The resulting Use the "-generate-otp" flag to generate a usable value. The resulting
token is XORed with this value when it is returend. Use the "-decode" token is XORed with this value when it is returned. Use the "-decode"
flag to output the final value. flag to output the final value.
- A file containing a PGP key or a keybase username in the "-pgp-key" - A file containing a PGP key or a keybase username in the "-pgp-key"
@@ -67,24 +65,22 @@ Usage: vault generate-root [options] [KEY]
Generate an OTP code for the final token: Generate an OTP code for the final token:
$ vault generate-root -generate-otp $ vault operator generate-root -generate-otp
Start a root token generation: Start a root token generation:
$ vault generate-root -init -otp="..." $ vault operator generate-root -init -otp="..."
$ vault generate-root -init -pgp-key="..." $ vault operator generate-root -init -pgp-key="..."
Enter an unseal key to progress root token generation: Enter an unseal key to progress root token generation:
$ vault generate-root -otp="..." $ vault operator generate-root -otp="..."
For a full list of examples, please see the documentation.
` + c.Flags().Help() ` + c.Flags().Help()
return strings.TrimSpace(helpText) return strings.TrimSpace(helpText)
} }
func (c *GenerateRootCommand) Flags() *FlagSets { func (c *OperatorGenerateRootCommand) Flags() *FlagSets {
set := c.flagSet(FlagSetHTTP) set := c.flagSet(FlagSetHTTP)
f := set.NewFlagSet("Command Options") f := set.NewFlagSet("Command Options")
@@ -115,7 +111,7 @@ func (c *GenerateRootCommand) Flags() *FlagSets {
Default: false, Default: false,
EnvVar: "", EnvVar: "",
Completion: complete.PredictNothing, Completion: complete.PredictNothing,
Usage: "Print the status of the current attempt without provding an " + Usage: "Print the status of the current attempt without providing an " +
"unseal key.", "unseal key.",
}) })
@@ -183,15 +179,15 @@ func (c *GenerateRootCommand) Flags() *FlagSets {
return set return set
} }
func (c *GenerateRootCommand) AutocompleteArgs() complete.Predictor { func (c *OperatorGenerateRootCommand) AutocompleteArgs() complete.Predictor {
return nil return nil
} }
func (c *GenerateRootCommand) AutocompleteFlags() complete.Flags { func (c *OperatorGenerateRootCommand) AutocompleteFlags() complete.Flags {
return c.Flags().Completions() return c.Flags().Completions()
} }
func (c *GenerateRootCommand) Run(args []string) int { func (c *OperatorGenerateRootCommand) Run(args []string) int {
f := c.Flags() f := c.Flags()
if err := f.Parse(args); err != nil { if err := f.Parse(args); err != nil {
@@ -243,7 +239,7 @@ func (c *GenerateRootCommand) Run(args []string) int {
} }
// verifyOTP verifies the given OTP code is exactly 16 bytes. // verifyOTP verifies the given OTP code is exactly 16 bytes.
func (c *GenerateRootCommand) verifyOTP(otp string) error { func (c *OperatorGenerateRootCommand) verifyOTP(otp string) error {
if len(otp) == 0 { if len(otp) == 0 {
return fmt.Errorf("No OTP passed in") return fmt.Errorf("No OTP passed in")
} }
@@ -259,7 +255,7 @@ func (c *GenerateRootCommand) verifyOTP(otp string) error {
} }
// generateOTP generates a suitable OTP code for generating a root token. // generateOTP generates a suitable OTP code for generating a root token.
func (c *GenerateRootCommand) generateOTP() int { func (c *OperatorGenerateRootCommand) generateOTP() int {
buf := make([]byte, 16) buf := make([]byte, 16)
readLen, err := rand.Read(buf) readLen, err := rand.Read(buf)
if err != nil { if err != nil {
@@ -276,7 +272,7 @@ func (c *GenerateRootCommand) generateOTP() int {
} }
// decode decodes the given value using the otp. // decode decodes the given value using the otp.
func (c *GenerateRootCommand) decode(encoded, otp string) int { func (c *OperatorGenerateRootCommand) decode(encoded, otp string) int {
if encoded == "" { if encoded == "" {
c.UI.Error("Missing encoded value: use -decode=<string> to supply it") c.UI.Error("Missing encoded value: use -decode=<string> to supply it")
return 1 return 1
@@ -302,7 +298,7 @@ func (c *GenerateRootCommand) decode(encoded, otp string) int {
} }
// init is used to start the generation process // init is used to start the generation process
func (c *GenerateRootCommand) init(client *api.Client, otp string, pgpKey string) int { func (c *OperatorGenerateRootCommand) init(client *api.Client, otp string, pgpKey string) int {
// Validate incoming fields. Either OTP OR PGP keys must be supplied. // Validate incoming fields. Either OTP OR PGP keys must be supplied.
switch { switch {
case otp == "" && pgpKey == "": case otp == "" && pgpKey == "":
@@ -331,7 +327,7 @@ func (c *GenerateRootCommand) init(client *api.Client, otp string, pgpKey string
// provide prompts the user for the seal key and posts it to the update root // provide prompts the user for the seal key and posts it to the update root
// endpoint. If this is the last unseal, this function outputs it. // endpoint. If this is the last unseal, this function outputs it.
func (c *GenerateRootCommand) provide(client *api.Client, key string) int { func (c *OperatorGenerateRootCommand) provide(client *api.Client, key string) int {
status, err := client.Sys().GenerateRootStatus() status, err := client.Sys().GenerateRootStatus()
if err != nil { if err != nil {
c.UI.Error(fmt.Sprintf("Error getting root generation status: %s", err)) c.UI.Error(fmt.Sprintf("Error getting root generation status: %s", err))
@@ -413,7 +409,7 @@ func (c *GenerateRootCommand) provide(client *api.Client, key string) int {
} }
// cancel cancels the root token generation // cancel cancels the root token generation
func (c *GenerateRootCommand) cancel(client *api.Client) int { func (c *OperatorGenerateRootCommand) cancel(client *api.Client) int {
if err := client.Sys().GenerateRootCancel(); err != nil { if err := client.Sys().GenerateRootCancel(); err != nil {
c.UI.Error(fmt.Sprintf("Error canceling root token generation: %s", err)) c.UI.Error(fmt.Sprintf("Error canceling root token generation: %s", err))
return 2 return 2
@@ -423,7 +419,7 @@ func (c *GenerateRootCommand) cancel(client *api.Client) int {
} }
// status is used just to fetch and dump the status // status is used just to fetch and dump the status
func (c *GenerateRootCommand) status(client *api.Client) int { func (c *OperatorGenerateRootCommand) status(client *api.Client) int {
status, err := client.Sys().GenerateRootStatus() status, err := client.Sys().GenerateRootStatus()
if err != nil { if err != nil {
c.UI.Error(fmt.Sprintf("Error getting root generation status: %s", err)) c.UI.Error(fmt.Sprintf("Error getting root generation status: %s", err))
@@ -433,7 +429,7 @@ func (c *GenerateRootCommand) status(client *api.Client) int {
} }
// printStatus dumps the status to output // printStatus dumps the status to output
func (c *GenerateRootCommand) printStatus(status *api.GenerateRootStatusResponse) int { func (c *OperatorGenerateRootCommand) printStatus(status *api.GenerateRootStatusResponse) int {
out := []string{} out := []string{}
out = append(out, fmt.Sprintf("Nonce | %s", status.Nonce)) out = append(out, fmt.Sprintf("Nonce | %s", status.Nonce))
out = append(out, fmt.Sprintf("Started | %t", status.Started)) out = append(out, fmt.Sprintf("Started | %t", status.Started))
@@ -446,7 +442,7 @@ func (c *GenerateRootCommand) printStatus(status *api.GenerateRootStatusResponse
out = append(out, fmt.Sprintf("Root Token | %s", status.EncodedRootToken)) out = append(out, fmt.Sprintf("Root Token | %s", status.EncodedRootToken))
} }
output := columnOutput(out) output := columnOutput(out, nil)
c.UI.Output(output) c.UI.Output(output)
return 0 return 0
} }

View File

@@ -11,18 +11,18 @@ import (
"github.com/mitchellh/cli" "github.com/mitchellh/cli"
) )
func testGenerateRootCommand(tb testing.TB) (*cli.MockUi, *GenerateRootCommand) { func testOperatorGenerateRootCommand(tb testing.TB) (*cli.MockUi, *OperatorGenerateRootCommand) {
tb.Helper() tb.Helper()
ui := cli.NewMockUi() ui := cli.NewMockUi()
return ui, &GenerateRootCommand{ return ui, &OperatorGenerateRootCommand{
BaseCommand: &BaseCommand{ BaseCommand: &BaseCommand{
UI: ui, UI: ui,
}, },
} }
} }
func TestGenerateRootCommand_Run(t *testing.T) { func TestOperatorGenerateRootCommand_Run(t *testing.T) {
t.Parallel() t.Parallel()
cases := []struct { cases := []struct {
@@ -88,7 +88,7 @@ func TestGenerateRootCommand_Run(t *testing.T) {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
t.Parallel() t.Parallel()
ui, cmd := testGenerateRootCommand(t) ui, cmd := testOperatorGenerateRootCommand(t)
code := cmd.Run(tc.args) code := cmd.Run(tc.args)
if code != tc.code { if code != tc.code {
@@ -106,7 +106,7 @@ func TestGenerateRootCommand_Run(t *testing.T) {
t.Run("generate_otp", func(t *testing.T) { t.Run("generate_otp", func(t *testing.T) {
t.Parallel() t.Parallel()
ui, cmd := testGenerateRootCommand(t) ui, cmd := testOperatorGenerateRootCommand(t)
code := cmd.Run([]string{ code := cmd.Run([]string{
"-generate-otp", "-generate-otp",
@@ -127,7 +127,7 @@ func TestGenerateRootCommand_Run(t *testing.T) {
encoded := "L9MaZ/4mQanpOV6QeWd84g==" encoded := "L9MaZ/4mQanpOV6QeWd84g=="
otp := "dIeeezkjpDUv3fy7MYPOLQ==" otp := "dIeeezkjpDUv3fy7MYPOLQ=="
ui, cmd := testGenerateRootCommand(t) ui, cmd := testOperatorGenerateRootCommand(t)
code := cmd.Run([]string{ code := cmd.Run([]string{
"-decode", encoded, "-decode", encoded,
@@ -157,7 +157,7 @@ func TestGenerateRootCommand_Run(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
ui, cmd := testGenerateRootCommand(t) ui, cmd := testOperatorGenerateRootCommand(t)
cmd.client = client cmd.client = client
code := cmd.Run([]string{ code := cmd.Run([]string{
@@ -191,7 +191,7 @@ func TestGenerateRootCommand_Run(t *testing.T) {
client, closer := testVaultServer(t) client, closer := testVaultServer(t)
defer closer() defer closer()
ui, cmd := testGenerateRootCommand(t) ui, cmd := testOperatorGenerateRootCommand(t)
cmd.client = client cmd.client = client
code := cmd.Run([]string{ code := cmd.Run([]string{
@@ -227,7 +227,7 @@ func TestGenerateRootCommand_Run(t *testing.T) {
client, closer := testVaultServer(t) client, closer := testVaultServer(t)
defer closer() defer closer()
ui, cmd := testGenerateRootCommand(t) ui, cmd := testOperatorGenerateRootCommand(t)
cmd.client = client cmd.client = client
code := cmd.Run([]string{ code := cmd.Run([]string{
@@ -263,7 +263,7 @@ func TestGenerateRootCommand_Run(t *testing.T) {
client, closer := testVaultServer(t) client, closer := testVaultServer(t)
defer closer() defer closer()
ui, cmd := testGenerateRootCommand(t) ui, cmd := testOperatorGenerateRootCommand(t)
cmd.client = client cmd.client = client
code := cmd.Run([]string{ code := cmd.Run([]string{
@@ -297,7 +297,7 @@ func TestGenerateRootCommand_Run(t *testing.T) {
// Supply the first n-1 unseal keys // Supply the first n-1 unseal keys
for _, key := range keys[:len(keys)-1] { for _, key := range keys[:len(keys)-1] {
_, cmd := testGenerateRootCommand(t) _, cmd := testOperatorGenerateRootCommand(t)
cmd.client = client cmd.client = client
code := cmd.Run([]string{ code := cmd.Run([]string{
@@ -309,7 +309,7 @@ func TestGenerateRootCommand_Run(t *testing.T) {
} }
} }
ui, cmd := testGenerateRootCommand(t) ui, cmd := testOperatorGenerateRootCommand(t)
cmd.client = client cmd.client = client
code := cmd.Run([]string{ code := cmd.Run([]string{
@@ -364,7 +364,7 @@ func TestGenerateRootCommand_Run(t *testing.T) {
stdinW.Close() stdinW.Close()
}() }()
_, cmd := testGenerateRootCommand(t) _, cmd := testOperatorGenerateRootCommand(t)
cmd.client = client cmd.client = client
cmd.testStdin = stdinR cmd.testStdin = stdinR
@@ -383,7 +383,7 @@ func TestGenerateRootCommand_Run(t *testing.T) {
stdinW.Close() stdinW.Close()
}() }()
ui, cmd := testGenerateRootCommand(t) ui, cmd := testOperatorGenerateRootCommand(t)
cmd.client = client cmd.client = client
cmd.testStdin = stdinR cmd.testStdin = stdinR
@@ -422,7 +422,7 @@ func TestGenerateRootCommand_Run(t *testing.T) {
client, closer := testVaultServerBad(t) client, closer := testVaultServerBad(t)
defer closer() defer closer()
ui, cmd := testGenerateRootCommand(t) ui, cmd := testOperatorGenerateRootCommand(t)
cmd.client = client cmd.client = client
code := cmd.Run([]string{ code := cmd.Run([]string{
@@ -442,7 +442,7 @@ func TestGenerateRootCommand_Run(t *testing.T) {
t.Run("no_tabs", func(t *testing.T) { t.Run("no_tabs", func(t *testing.T) {
t.Parallel() t.Parallel()
_, cmd := testGenerateRootCommand(t) _, cmd := testOperatorGenerateRootCommand(t)
assertNoTabs(t, cmd) assertNoTabs(t, cmd)
}) })
} }

View File

@@ -16,12 +16,10 @@ import (
consulapi "github.com/hashicorp/consul/api" consulapi "github.com/hashicorp/consul/api"
) )
// Ensure we are implementing the right interfaces. var _ cli.Command = (*OperatorInitCommand)(nil)
var _ cli.Command = (*InitCommand)(nil) var _ cli.CommandAutocomplete = (*OperatorInitCommand)(nil)
var _ cli.CommandAutocomplete = (*InitCommand)(nil)
// InitCommand is a Command that initializes a new Vault server. type OperatorInitCommand struct {
type InitCommand struct {
*BaseCommand *BaseCommand
flagStatus bool flagStatus bool
@@ -46,13 +44,13 @@ type InitCommand struct {
flagCheck bool flagCheck bool
} }
func (c *InitCommand) Synopsis() string { func (c *OperatorInitCommand) Synopsis() string {
return "Initializes a server" return "Initializes a server"
} }
func (c *InitCommand) Help() string { func (c *OperatorInitCommand) Help() string {
helpText := ` helpText := `
Usage: vault init [options] Usage: vault operator init [options]
Initializes a Vault server. Initialization is the process by which Vault's Initializes a Vault server. Initialization is the process by which Vault's
storage backend is prepared to receive data. Since Vault server's share the storage backend is prepared to receive data. Since Vault server's share the
@@ -69,26 +67,24 @@ Usage: vault init [options]
Start initialization with the default options: Start initialization with the default options:
$ vault init $ vault operator init
Initialize, but encrypt the unseal keys with pgp keys: Initialize, but encrypt the unseal keys with pgp keys:
$ vault init \ $ vault operator init \
-key-shares=3 \ -key-shares=3 \
-key-threshold=2 \ -key-threshold=2 \
-pgp-keys="keybase:hashicorp,keybase:jefferai,keybase:sethvargo" -pgp-keys="keybase:hashicorp,keybase:jefferai,keybase:sethvargo"
Encrypt the initial root token using a pgp key: Encrypt the initial root token using a pgp key:
$ vault init -root-token-pgp-key="keybase:hashicorp" $ vault operator init -root-token-pgp-key="keybase:hashicorp"
For a complete list of examples, please see the documentation.
` + c.Flags().Help() ` + c.Flags().Help()
return strings.TrimSpace(helpText) return strings.TrimSpace(helpText)
} }
func (c *InitCommand) Flags() *FlagSets { func (c *OperatorInitCommand) Flags() *FlagSets {
set := c.flagSet(FlagSetHTTP | FlagSetOutputFormat) set := c.flagSet(FlagSetHTTP | FlagSetOutputFormat)
// Common Options // Common Options
@@ -231,15 +227,15 @@ func (c *InitCommand) Flags() *FlagSets {
return set return set
} }
func (c *InitCommand) AutocompleteArgs() complete.Predictor { func (c *OperatorInitCommand) AutocompleteArgs() complete.Predictor {
return nil return nil
} }
func (c *InitCommand) AutocompleteFlags() complete.Flags { func (c *OperatorInitCommand) AutocompleteFlags() complete.Flags {
return c.Flags().Completions() return c.Flags().Completions()
} }
func (c *InitCommand) Run(args []string) int { func (c *OperatorInitCommand) Run(args []string) int {
f := c.Flags() f := c.Flags()
if err := f.Parse(args); err != nil { if err := f.Parse(args); err != nil {
@@ -293,7 +289,7 @@ func (c *InitCommand) Run(args []string) int {
} }
// consulAuto enables auto-joining via Consul. // consulAuto enables auto-joining via Consul.
func (c *InitCommand) consulAuto(client *api.Client, req *api.InitRequest) int { func (c *OperatorInitCommand) consulAuto(client *api.Client, req *api.InitRequest) int {
// Capture the client original address and reset it // Capture the client original address and reset it
originalAddr := client.Address() originalAddr := client.Address()
defer client.SetAddress(originalAddr) defer client.SetAddress(originalAddr)
@@ -432,7 +428,7 @@ func (c *InitCommand) consulAuto(client *api.Client, req *api.InitRequest) int {
} }
} }
func (c *InitCommand) init(client *api.Client, req *api.InitRequest) int { func (c *OperatorInitCommand) init(client *api.Client, req *api.InitRequest) int {
resp, err := client.Sys().Init(req) resp, err := client.Sys().Init(req)
if err != nil { if err != nil {
c.UI.Error(fmt.Sprintf("Error initializing: %s", err)) c.UI.Error(fmt.Sprintf("Error initializing: %s", err))
@@ -509,7 +505,7 @@ func (c *InitCommand) init(client *api.Client, req *api.InitRequest) int {
} }
// initOutputYAML outputs the init output as YAML. // initOutputYAML outputs the init output as YAML.
func (c *InitCommand) initOutputYAML(req *api.InitRequest, resp *api.InitResponse) int { func (c *OperatorInitCommand) initOutputYAML(req *api.InitRequest, resp *api.InitResponse) int {
b, err := yaml.Marshal(newMachineInit(req, resp)) b, err := yaml.Marshal(newMachineInit(req, resp))
if err != nil { if err != nil {
c.UI.Error(fmt.Sprintf("Error marshaling YAML: %s", err)) c.UI.Error(fmt.Sprintf("Error marshaling YAML: %s", err))
@@ -519,7 +515,7 @@ func (c *InitCommand) initOutputYAML(req *api.InitRequest, resp *api.InitRespons
} }
// initOutputJSON outputs the init output as JSON. // initOutputJSON outputs the init output as JSON.
func (c *InitCommand) initOutputJSON(req *api.InitRequest, resp *api.InitResponse) int { func (c *OperatorInitCommand) initOutputJSON(req *api.InitRequest, resp *api.InitResponse) int {
b, err := json.Marshal(newMachineInit(req, resp)) b, err := json.Marshal(newMachineInit(req, resp))
if err != nil { if err != nil {
c.UI.Error(fmt.Sprintf("Error marshaling JSON: %s", err)) c.UI.Error(fmt.Sprintf("Error marshaling JSON: %s", err))
@@ -530,7 +526,7 @@ func (c *InitCommand) initOutputJSON(req *api.InitRequest, resp *api.InitRespons
// status inspects the init status of vault and returns an appropriate error // status inspects the init status of vault and returns an appropriate error
// code and message. // code and message.
func (c *InitCommand) status(client *api.Client) int { func (c *OperatorInitCommand) status(client *api.Client) int {
inited, err := client.Sys().InitStatus() inited, err := client.Sys().InitStatus()
if err != nil { if err != nil {
c.UI.Error(fmt.Sprintf("Error checking init status: %s", err)) c.UI.Error(fmt.Sprintf("Error checking init status: %s", err))

View File

@@ -13,18 +13,18 @@ import (
"github.com/mitchellh/cli" "github.com/mitchellh/cli"
) )
func testInitCommand(tb testing.TB) (*cli.MockUi, *InitCommand) { func testOperatorInitCommand(tb testing.TB) (*cli.MockUi, *OperatorInitCommand) {
tb.Helper() tb.Helper()
ui := cli.NewMockUi() ui := cli.NewMockUi()
return ui, &InitCommand{ return ui, &OperatorInitCommand{
BaseCommand: &BaseCommand{ BaseCommand: &BaseCommand{
UI: ui, UI: ui,
}, },
} }
} }
func TestInitCommand_Run(t *testing.T) { func TestOperatorInitCommand_Run(t *testing.T) {
t.Parallel() t.Parallel()
cases := []struct { cases := []struct {
@@ -100,7 +100,7 @@ func TestInitCommand_Run(t *testing.T) {
client, closer := testVaultServer(t) client, closer := testVaultServer(t)
defer closer() defer closer()
ui, cmd := testInitCommand(t) ui, cmd := testOperatorInitCommand(t)
cmd.client = client cmd.client = client
code := cmd.Run(tc.args) code := cmd.Run(tc.args)
@@ -122,7 +122,7 @@ func TestInitCommand_Run(t *testing.T) {
client, closer := testVaultServerUninit(t) client, closer := testVaultServerUninit(t)
defer closer() defer closer()
ui, cmd := testInitCommand(t) ui, cmd := testOperatorInitCommand(t)
cmd.client = client cmd.client = client
// Verify the non-init response code // Verify the non-init response code
@@ -142,7 +142,7 @@ func TestInitCommand_Run(t *testing.T) {
} }
// Verify the init response code // Verify the init response code
ui, cmd = testInitCommand(t) ui, cmd = testOperatorInitCommand(t)
cmd.client = client cmd.client = client
code = cmd.Run([]string{ code = cmd.Run([]string{
"-status", "-status",
@@ -158,7 +158,7 @@ func TestInitCommand_Run(t *testing.T) {
client, closer := testVaultServerUninit(t) client, closer := testVaultServerUninit(t)
defer closer() defer closer()
ui, cmd := testInitCommand(t) ui, cmd := testOperatorInitCommand(t)
cmd.client = client cmd.client = client
code := cmd.Run([]string{}) code := cmd.Run([]string{})
@@ -217,7 +217,7 @@ func TestInitCommand_Run(t *testing.T) {
client, closer := testVaultServerUninit(t) client, closer := testVaultServerUninit(t)
defer closer() defer closer()
ui, cmd := testInitCommand(t) ui, cmd := testOperatorInitCommand(t)
cmd.client = client cmd.client = client
code := cmd.Run([]string{ code := cmd.Run([]string{
@@ -283,7 +283,7 @@ func TestInitCommand_Run(t *testing.T) {
client, closer := testVaultServerUninit(t) client, closer := testVaultServerUninit(t)
defer closer() defer closer()
ui, cmd := testInitCommand(t) ui, cmd := testOperatorInitCommand(t)
cmd.client = client cmd.client = client
code := cmd.Run([]string{ code := cmd.Run([]string{
@@ -335,7 +335,7 @@ func TestInitCommand_Run(t *testing.T) {
client, closer := testVaultServerBad(t) client, closer := testVaultServerBad(t)
defer closer() defer closer()
ui, cmd := testInitCommand(t) ui, cmd := testOperatorInitCommand(t)
cmd.client = client cmd.client = client
code := cmd.Run([]string{ code := cmd.Run([]string{
@@ -355,7 +355,7 @@ func TestInitCommand_Run(t *testing.T) {
t.Run("no_tabs", func(t *testing.T) { t.Run("no_tabs", func(t *testing.T) {
t.Parallel() t.Parallel()
_, cmd := testInitCommand(t) _, cmd := testOperatorInitCommand(t)
assertNoTabs(t, cmd) assertNoTabs(t, cmd)
}) })
} }

View File

@@ -8,22 +8,20 @@ import (
"github.com/posener/complete" "github.com/posener/complete"
) )
// Ensure we are implementing the right interfaces. var _ cli.Command = (*OperatorKeyStatusCommand)(nil)
var _ cli.Command = (*KeyStatusCommand)(nil) var _ cli.CommandAutocomplete = (*OperatorKeyStatusCommand)(nil)
var _ cli.CommandAutocomplete = (*KeyStatusCommand)(nil)
// KeyStatusCommand is a Command that provides information about the key status type OperatorKeyStatusCommand struct {
type KeyStatusCommand struct {
*BaseCommand *BaseCommand
} }
func (c *KeyStatusCommand) Synopsis() string { func (c *OperatorKeyStatusCommand) Synopsis() string {
return "Provides information about the active encryption key" return "Provides information about the active encryption key"
} }
func (c *KeyStatusCommand) Help() string { func (c *OperatorKeyStatusCommand) Help() string {
helpText := ` helpText := `
Usage: vault key-status [options] Usage: vault operator key-status [options]
Provides information about the active encryption key. Specifically, Provides information about the active encryption key. Specifically,
the current key term and the key installation time. the current key term and the key installation time.
@@ -33,19 +31,19 @@ Usage: vault key-status [options]
return strings.TrimSpace(helpText) return strings.TrimSpace(helpText)
} }
func (c *KeyStatusCommand) Flags() *FlagSets { func (c *OperatorKeyStatusCommand) Flags() *FlagSets {
return c.flagSet(FlagSetHTTP) return c.flagSet(FlagSetHTTP)
} }
func (c *KeyStatusCommand) AutocompleteArgs() complete.Predictor { func (c *OperatorKeyStatusCommand) AutocompleteArgs() complete.Predictor {
return nil return nil
} }
func (c *KeyStatusCommand) AutocompleteFlags() complete.Flags { func (c *OperatorKeyStatusCommand) AutocompleteFlags() complete.Flags {
return c.Flags().Completions() return c.Flags().Completions()
} }
func (c *KeyStatusCommand) Run(args []string) int { func (c *OperatorKeyStatusCommand) Run(args []string) int {
f := c.Flags() f := c.Flags()
if err := f.Parse(args); err != nil { if err := f.Parse(args); err != nil {

View File

@@ -7,18 +7,18 @@ import (
"github.com/mitchellh/cli" "github.com/mitchellh/cli"
) )
func testKeyStatusCommand(tb testing.TB) (*cli.MockUi, *KeyStatusCommand) { func testOperatorKeyStatusCommand(tb testing.TB) (*cli.MockUi, *OperatorKeyStatusCommand) {
tb.Helper() tb.Helper()
ui := cli.NewMockUi() ui := cli.NewMockUi()
return ui, &KeyStatusCommand{ return ui, &OperatorKeyStatusCommand{
BaseCommand: &BaseCommand{ BaseCommand: &BaseCommand{
UI: ui, UI: ui,
}, },
} }
} }
func TestKeyStatusCommand_Run(t *testing.T) { func TestOperatorKeyStatusCommand_Run(t *testing.T) {
t.Parallel() t.Parallel()
cases := []struct { cases := []struct {
@@ -44,7 +44,7 @@ func TestKeyStatusCommand_Run(t *testing.T) {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
t.Parallel() t.Parallel()
ui, cmd := testKeyStatusCommand(t) ui, cmd := testOperatorKeyStatusCommand(t)
code := cmd.Run(tc.args) code := cmd.Run(tc.args)
if code != tc.code { if code != tc.code {
@@ -65,7 +65,7 @@ func TestKeyStatusCommand_Run(t *testing.T) {
client, closer := testVaultServer(t) client, closer := testVaultServer(t)
defer closer() defer closer()
ui, cmd := testKeyStatusCommand(t) ui, cmd := testOperatorKeyStatusCommand(t)
cmd.client = client cmd.client = client
code := cmd.Run([]string{}) code := cmd.Run([]string{})
@@ -86,7 +86,7 @@ func TestKeyStatusCommand_Run(t *testing.T) {
client, closer := testVaultServerBad(t) client, closer := testVaultServerBad(t)
defer closer() defer closer()
ui, cmd := testKeyStatusCommand(t) ui, cmd := testOperatorKeyStatusCommand(t)
cmd.client = client cmd.client = client
code := cmd.Run([]string{}) code := cmd.Run([]string{})
@@ -104,7 +104,7 @@ func TestKeyStatusCommand_Run(t *testing.T) {
t.Run("no_tabs", func(t *testing.T) { t.Run("no_tabs", func(t *testing.T) {
t.Parallel() t.Parallel()
_, cmd := testKeyStatusCommand(t) _, cmd := testOperatorKeyStatusCommand(t)
assertNoTabs(t, cmd) assertNoTabs(t, cmd)
}) })
} }

View File

@@ -15,24 +15,12 @@ import (
"github.com/posener/complete" "github.com/posener/complete"
) )
// Ensure we are implementing the right interfaces. var _ cli.Command = (*OperatorRekeyCommand)(nil)
var _ cli.Command = (*RekeyCommand)(nil) var _ cli.CommandAutocomplete = (*OperatorRekeyCommand)(nil)
var _ cli.CommandAutocomplete = (*RekeyCommand)(nil)
// RekeyCommand is a Command that rekeys the vault. type OperatorRekeyCommand struct {
type RekeyCommand struct {
*BaseCommand *BaseCommand
// Key can be used to pre-seed the key. If it is set, it will not
// be asked with the `password` helper.
Key string
// The nonce for the rekey request to send along
Nonce string
// Whether to use the recovery key instead of barrier key, if available
RecoveryKey bool
flagCancel bool flagCancel bool
flagInit bool flagInit bool
flagKeyShares int flagKeyShares int
@@ -56,11 +44,11 @@ type RekeyCommand struct {
testStdin io.Reader // for tests testStdin io.Reader // for tests
} }
func (c *RekeyCommand) Synopsis() string { func (c *OperatorRekeyCommand) Synopsis() string {
return "Generates new unseal keys" return "Generates new unseal keys"
} }
func (c *RekeyCommand) Help() string { func (c *OperatorRekeyCommand) Help() string {
helpText := ` helpText := `
Usage: vault rekey [options] [KEY] Usage: vault rekey [options] [KEY]
@@ -75,14 +63,14 @@ Usage: vault rekey [options] [KEY]
Initialize a rekey: Initialize a rekey:
$ vault rekey \ $ vault operator rekey \
-init \ -init \
-key-shares=15 \ -key-shares=15 \
-key-threshold=9 -key-threshold=9
Rekey and encrypt the resulting unseal keys with PGP: Rekey and encrypt the resulting unseal keys with PGP:
$ vault rekey \ $ vault operator rekey \
-init \ -init \
-key-shares=3 \ -key-shares=3 \
-key-threshold=2 \ -key-threshold=2 \
@@ -90,29 +78,27 @@ Usage: vault rekey [options] [KEY]
Store encrypted PGP keys in Vault's core: Store encrypted PGP keys in Vault's core:
$ vault rekey \ $ vault operator rekey \
-init \ -init \
-pgp-keys="..." \ -pgp-keys="..." \
-backup -backup
Retrieve backed-up unseal keys: Retrieve backed-up unseal keys:
$ vault rekey -backup-retrieve $ vault operator rekey -backup-retrieve
Delete backed-up unseal keys: Delete backed-up unseal keys:
$ vault rekey -backup-delete $ vault operator rekey -backup-delete
For a full list of examples, please see the documentation.
` + c.Flags().Help() ` + c.Flags().Help()
return strings.TrimSpace(helpText) return strings.TrimSpace(helpText)
} }
func (c *RekeyCommand) Flags() *FlagSets { func (c *OperatorRekeyCommand) Flags() *FlagSets {
set := c.flagSet(FlagSetHTTP) set := c.flagSet(FlagSetHTTP)
f := set.NewFlagSet("Command Options") f := set.NewFlagSet("Common Options")
f.BoolVar(&BoolVar{ f.BoolVar(&BoolVar{
Name: "init", Name: "init",
@@ -136,7 +122,7 @@ func (c *RekeyCommand) Flags() *FlagSets {
Name: "status", Name: "status",
Target: &c.flagStatus, Target: &c.flagStatus,
Default: false, Default: false,
Usage: "Print the status of the current attempt without provding an " + Usage: "Print the status of the current attempt without providing an " +
"unseal key.", "unseal key.",
}) })
@@ -188,8 +174,7 @@ func (c *RekeyCommand) Flags() *FlagSets {
"public GPG keys OR a comma-separated list of Keybase usernames using " + "public GPG keys OR a comma-separated list of Keybase usernames using " +
"the format \"keybase:<username>\". When supplied, the generated " + "the format \"keybase:<username>\". When supplied, the generated " +
"unseal keys will be encrypted and base64-encoded in the order " + "unseal keys will be encrypted and base64-encoded in the order " +
"specified in this list. The number of entires must match -key-shares, " + "specified in this list.",
"unless -store-shares are used.",
}) })
f = set.NewFlagSet("Backup Options") f = set.NewFlagSet("Backup Options")
@@ -216,7 +201,7 @@ func (c *RekeyCommand) Flags() *FlagSets {
Name: "backup-retrieve", Name: "backup-retrieve",
Target: &c.flagBackupRetrieve, Target: &c.flagBackupRetrieve,
Default: false, Default: false,
Usage: "Retrieve the backed-up unseal keys. This option is only avaiable " + Usage: "Retrieve the backed-up unseal keys. This option is only available " +
"if the PGP keys were provided and the backup has not been deleted.", "if the PGP keys were provided and the backup has not been deleted.",
}) })
@@ -249,15 +234,15 @@ func (c *RekeyCommand) Flags() *FlagSets {
return set return set
} }
func (c *RekeyCommand) AutocompleteArgs() complete.Predictor { func (c *OperatorRekeyCommand) AutocompleteArgs() complete.Predictor {
return complete.PredictAnything return complete.PredictAnything
} }
func (c *RekeyCommand) AutocompleteFlags() complete.Flags { func (c *OperatorRekeyCommand) AutocompleteFlags() complete.Flags {
return c.Flags().Completions() return c.Flags().Completions()
} }
func (c *RekeyCommand) Run(args []string) int { func (c *OperatorRekeyCommand) Run(args []string) int {
f := c.Flags() f := c.Flags()
if err := f.Parse(args); err != nil { if err := f.Parse(args); err != nil {
@@ -324,7 +309,7 @@ func (c *RekeyCommand) Run(args []string) int {
} }
// init starts the rekey process. // init starts the rekey process.
func (c *RekeyCommand) init(client *api.Client) int { func (c *OperatorRekeyCommand) init(client *api.Client) int {
// Handle the different API requests // Handle the different API requests
var fn func(*api.RekeyInitRequest) (*api.RekeyStatusResponse, error) var fn func(*api.RekeyInitRequest) (*api.RekeyStatusResponse, error)
switch strings.ToLower(strings.TrimSpace(c.flagTarget)) { switch strings.ToLower(strings.TrimSpace(c.flagTarget)) {
@@ -377,7 +362,7 @@ func (c *RekeyCommand) init(client *api.Client) int {
} }
// cancel is used to abort the rekey process. // cancel is used to abort the rekey process.
func (c *RekeyCommand) cancel(client *api.Client) int { func (c *OperatorRekeyCommand) cancel(client *api.Client) int {
// Handle the different API requests // Handle the different API requests
var fn func() error var fn func() error
switch strings.ToLower(strings.TrimSpace(c.flagTarget)) { switch strings.ToLower(strings.TrimSpace(c.flagTarget)) {
@@ -402,7 +387,7 @@ func (c *RekeyCommand) cancel(client *api.Client) int {
// provide prompts the user for the seal key and posts it to the update root // provide prompts the user for the seal key and posts it to the update root
// endpoint. If this is the last unseal, this function outputs it. // endpoint. If this is the last unseal, this function outputs it.
func (c *RekeyCommand) provide(client *api.Client, key string) int { func (c *OperatorRekeyCommand) provide(client *api.Client, key string) int {
var statusFn func() (*api.RekeyStatusResponse, error) var statusFn func() (*api.RekeyStatusResponse, error)
var updateFn func(string, string) (*api.RekeyUpdateResponse, error) var updateFn func(string, string) (*api.RekeyUpdateResponse, error)
@@ -504,7 +489,7 @@ func (c *RekeyCommand) provide(client *api.Client, key string) int {
} }
// status is used just to fetch and dump the status. // status is used just to fetch and dump the status.
func (c *RekeyCommand) status(client *api.Client) int { func (c *OperatorRekeyCommand) status(client *api.Client) int {
// Handle the different API requests // Handle the different API requests
var fn func() (*api.RekeyStatusResponse, error) var fn func() (*api.RekeyStatusResponse, error)
switch strings.ToLower(strings.TrimSpace(c.flagTarget)) { switch strings.ToLower(strings.TrimSpace(c.flagTarget)) {
@@ -528,7 +513,7 @@ func (c *RekeyCommand) status(client *api.Client) int {
} }
// backupRetrieve retrieves the stored backup keys. // backupRetrieve retrieves the stored backup keys.
func (c *RekeyCommand) backupRetrieve(client *api.Client) int { func (c *OperatorRekeyCommand) backupRetrieve(client *api.Client) int {
// Handle the different API requests // Handle the different API requests
var fn func() (*api.RekeyRetrieveResponse, error) var fn func() (*api.RekeyRetrieveResponse, error)
switch strings.ToLower(strings.TrimSpace(c.flagTarget)) { switch strings.ToLower(strings.TrimSpace(c.flagTarget)) {
@@ -556,7 +541,7 @@ func (c *RekeyCommand) backupRetrieve(client *api.Client) int {
} }
// backupDelete deletes the stored backup keys. // backupDelete deletes the stored backup keys.
func (c *RekeyCommand) backupDelete(client *api.Client) int { func (c *OperatorRekeyCommand) backupDelete(client *api.Client) int {
// Handle the different API requests // Handle the different API requests
var fn func() error var fn func() error
switch strings.ToLower(strings.TrimSpace(c.flagTarget)) { switch strings.ToLower(strings.TrimSpace(c.flagTarget)) {
@@ -580,7 +565,7 @@ func (c *RekeyCommand) backupDelete(client *api.Client) int {
} }
// printStatus dumps the status to output // printStatus dumps the status to output
func (c *RekeyCommand) printStatus(status *api.RekeyStatusResponse) int { func (c *OperatorRekeyCommand) printStatus(status *api.RekeyStatusResponse) int {
out := []string{} out := []string{}
out = append(out, fmt.Sprintf("Nonce | %s", status.Nonce)) out = append(out, fmt.Sprintf("Nonce | %s", status.Nonce))
out = append(out, fmt.Sprintf("Started | %t", status.Started)) out = append(out, fmt.Sprintf("Started | %t", status.Started))
@@ -596,12 +581,12 @@ func (c *RekeyCommand) printStatus(status *api.RekeyStatusResponse) int {
out = append(out, fmt.Sprintf("Backup | %t", status.Backup)) out = append(out, fmt.Sprintf("Backup | %t", status.Backup))
} }
output := columnOutput(out) output := columnOutput(out, nil)
c.UI.Output(output) c.UI.Output(output)
return 0 return 0
} }
func (c *RekeyCommand) printUnsealKeys(status *api.RekeyStatusResponse, resp *api.RekeyUpdateResponse) int { func (c *OperatorRekeyCommand) printUnsealKeys(status *api.RekeyStatusResponse, resp *api.RekeyUpdateResponse) int {
// Space between the key prompt, if any, and the output // Space between the key prompt, if any, and the output
c.UI.Output("") c.UI.Output("")
@@ -633,7 +618,7 @@ func (c *RekeyCommand) printUnsealKeys(status *api.RekeyStatusResponse, resp *ap
c.UI.Output("") c.UI.Output("")
c.UI.Output(wrapAtLength(fmt.Sprintf( c.UI.Output(wrapAtLength(fmt.Sprintf(
"The encrypted unseal keys are backed up to \"core/unseal-keys-backup\"" + "The encrypted unseal keys are backed up to \"core/unseal-keys-backup\"" +
"in the physical backend. Remove these keys at any time using " + "in the storage backend. Remove these keys at any time using " +
"\"vault rekey -delete-backup\". Vault does not automatically remove " + "\"vault rekey -delete-backup\". Vault does not automatically remove " +
"these keys.", "these keys.",
))) )))

View File

@@ -11,18 +11,18 @@ import (
"github.com/mitchellh/cli" "github.com/mitchellh/cli"
) )
func testRekeyCommand(tb testing.TB) (*cli.MockUi, *RekeyCommand) { func testOperatorRekeyCommand(tb testing.TB) (*cli.MockUi, *OperatorRekeyCommand) {
tb.Helper() tb.Helper()
ui := cli.NewMockUi() ui := cli.NewMockUi()
return ui, &RekeyCommand{ return ui, &OperatorRekeyCommand{
BaseCommand: &BaseCommand{ BaseCommand: &BaseCommand{
UI: ui, UI: ui,
}, },
} }
} }
func TestRekeyCommand_Run(t *testing.T) { func TestOperatorRekeyCommand_Run(t *testing.T) {
t.Parallel() t.Parallel()
cases := []struct { cases := []struct {
@@ -75,7 +75,7 @@ func TestRekeyCommand_Run(t *testing.T) {
client, closer := testVaultServer(t) client, closer := testVaultServer(t)
defer closer() defer closer()
ui, cmd := testRekeyCommand(t) ui, cmd := testOperatorRekeyCommand(t)
cmd.client = client cmd.client = client
code := cmd.Run(tc.args) code := cmd.Run(tc.args)
@@ -97,7 +97,7 @@ func TestRekeyCommand_Run(t *testing.T) {
client, closer := testVaultServer(t) client, closer := testVaultServer(t)
defer closer() defer closer()
ui, cmd := testRekeyCommand(t) ui, cmd := testOperatorRekeyCommand(t)
cmd.client = client cmd.client = client
// Verify the non-init response // Verify the non-init response
@@ -123,7 +123,7 @@ func TestRekeyCommand_Run(t *testing.T) {
} }
// Verify the init response // Verify the init response
ui, cmd = testRekeyCommand(t) ui, cmd = testOperatorRekeyCommand(t)
cmd.client = client cmd.client = client
code = cmd.Run([]string{ code = cmd.Run([]string{
"-status", "-status",
@@ -153,7 +153,7 @@ func TestRekeyCommand_Run(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
ui, cmd := testRekeyCommand(t) ui, cmd := testOperatorRekeyCommand(t)
cmd.client = client cmd.client = client
code := cmd.Run([]string{ code := cmd.Run([]string{
@@ -185,7 +185,7 @@ func TestRekeyCommand_Run(t *testing.T) {
client, closer := testVaultServer(t) client, closer := testVaultServer(t)
defer closer() defer closer()
ui, cmd := testRekeyCommand(t) ui, cmd := testOperatorRekeyCommand(t)
cmd.client = client cmd.client = client
code := cmd.Run([]string{ code := cmd.Run([]string{
@@ -221,7 +221,7 @@ func TestRekeyCommand_Run(t *testing.T) {
client, closer := testVaultServer(t) client, closer := testVaultServer(t)
defer closer() defer closer()
ui, cmd := testRekeyCommand(t) ui, cmd := testOperatorRekeyCommand(t)
cmd.client = client cmd.client = client
code := cmd.Run([]string{ code := cmd.Run([]string{
@@ -270,7 +270,7 @@ func TestRekeyCommand_Run(t *testing.T) {
// Supply the first n-1 unseal keys // Supply the first n-1 unseal keys
for _, key := range keys[:len(keys)-1] { for _, key := range keys[:len(keys)-1] {
ui, cmd := testRekeyCommand(t) ui, cmd := testOperatorRekeyCommand(t)
cmd.client = client cmd.client = client
code := cmd.Run([]string{ code := cmd.Run([]string{
@@ -282,7 +282,7 @@ func TestRekeyCommand_Run(t *testing.T) {
} }
} }
ui, cmd := testRekeyCommand(t) ui, cmd := testOperatorRekeyCommand(t)
cmd.client = client cmd.client = client
code := cmd.Run([]string{ code := cmd.Run([]string{
@@ -338,7 +338,7 @@ func TestRekeyCommand_Run(t *testing.T) {
stdinW.Close() stdinW.Close()
}() }()
ui, cmd := testRekeyCommand(t) ui, cmd := testOperatorRekeyCommand(t)
cmd.client = client cmd.client = client
cmd.testStdin = stdinR cmd.testStdin = stdinR
@@ -357,7 +357,7 @@ func TestRekeyCommand_Run(t *testing.T) {
stdinW.Close() stdinW.Close()
}() }()
ui, cmd := testRekeyCommand(t) ui, cmd := testOperatorRekeyCommand(t)
cmd.client = client cmd.client = client
cmd.testStdin = stdinR cmd.testStdin = stdinR
@@ -399,7 +399,7 @@ func TestRekeyCommand_Run(t *testing.T) {
client, keys, closer := testVaultServerUnseal(t) client, keys, closer := testVaultServerUnseal(t)
defer closer() defer closer()
ui, cmd := testRekeyCommand(t) ui, cmd := testOperatorRekeyCommand(t)
cmd.client = client cmd.client = client
code := cmd.Run([]string{ code := cmd.Run([]string{
@@ -423,7 +423,7 @@ func TestRekeyCommand_Run(t *testing.T) {
var combined string var combined string
// Supply the unseal keys // Supply the unseal keys
for _, key := range keys { for _, key := range keys {
ui, cmd := testRekeyCommand(t) ui, cmd := testOperatorRekeyCommand(t)
cmd.client = client cmd.client = client
code := cmd.Run([]string{ code := cmd.Run([]string{
@@ -448,7 +448,7 @@ func TestRekeyCommand_Run(t *testing.T) {
fingerprint, encryptedKey := match[0][1], match[0][2] fingerprint, encryptedKey := match[0][1], match[0][2]
// Get the backup // Get the backup
ui, cmd = testRekeyCommand(t) ui, cmd = testOperatorRekeyCommand(t)
cmd.client = client cmd.client = client
code = cmd.Run([]string{ code = cmd.Run([]string{
@@ -467,7 +467,7 @@ func TestRekeyCommand_Run(t *testing.T) {
} }
// Delete the backup // Delete the backup
ui, cmd = testRekeyCommand(t) ui, cmd = testOperatorRekeyCommand(t)
cmd.client = client cmd.client = client
code = cmd.Run([]string{ code = cmd.Run([]string{
@@ -489,7 +489,7 @@ func TestRekeyCommand_Run(t *testing.T) {
client, closer := testVaultServerBad(t) client, closer := testVaultServerBad(t)
defer closer() defer closer()
ui, cmd := testRekeyCommand(t) ui, cmd := testOperatorRekeyCommand(t)
cmd.client = client cmd.client = client
code := cmd.Run([]string{ code := cmd.Run([]string{
@@ -509,7 +509,7 @@ func TestRekeyCommand_Run(t *testing.T) {
t.Run("no_tabs", func(t *testing.T) { t.Run("no_tabs", func(t *testing.T) {
t.Parallel() t.Parallel()
_, cmd := testRekeyCommand(t) _, cmd := testOperatorRekeyCommand(t)
assertNoTabs(t, cmd) assertNoTabs(t, cmd)
}) })
} }

View File

@@ -8,20 +8,18 @@ import (
"github.com/posener/complete" "github.com/posener/complete"
) )
// Ensure we are implementing the right interfaces. var _ cli.Command = (*OperatorSealCommand)(nil)
var _ cli.Command = (*SealCommand)(nil) var _ cli.CommandAutocomplete = (*OperatorSealCommand)(nil)
var _ cli.CommandAutocomplete = (*SealCommand)(nil)
// SealCommand is a Command that seals the vault. type OperatorSealCommand struct {
type SealCommand struct {
*BaseCommand *BaseCommand
} }
func (c *SealCommand) Synopsis() string { func (c *OperatorSealCommand) Synopsis() string {
return "Seals the Vault server" return "Seals the Vault server"
} }
func (c *SealCommand) Help() string { func (c *OperatorSealCommand) Help() string {
helpText := ` helpText := `
Usage: vault seal [options] Usage: vault seal [options]
@@ -37,29 +35,26 @@ Usage: vault seal [options]
Seal the Vault server: Seal the Vault server:
$ vault seal $ vault operator seal
For a full list of examples and why you might want to seal the Vault, please
see the documentation.
` + c.Flags().Help() ` + c.Flags().Help()
return strings.TrimSpace(helpText) return strings.TrimSpace(helpText)
} }
func (c *SealCommand) Flags() *FlagSets { func (c *OperatorSealCommand) Flags() *FlagSets {
return c.flagSet(FlagSetHTTP) return c.flagSet(FlagSetHTTP)
} }
func (c *SealCommand) AutocompleteArgs() complete.Predictor { func (c *OperatorSealCommand) AutocompleteArgs() complete.Predictor {
return nil return nil
} }
func (c *SealCommand) AutocompleteFlags() complete.Flags { func (c *OperatorSealCommand) AutocompleteFlags() complete.Flags {
return c.Flags().Completions() return c.Flags().Completions()
} }
func (c *SealCommand) Run(args []string) int { func (c *OperatorSealCommand) Run(args []string) int {
f := c.Flags() f := c.Flags()
if err := f.Parse(args); err != nil { if err := f.Parse(args); err != nil {

View File

@@ -7,18 +7,18 @@ import (
"github.com/mitchellh/cli" "github.com/mitchellh/cli"
) )
func testSealCommand(tb testing.TB) (*cli.MockUi, *SealCommand) { func testOperatorSealCommand(tb testing.TB) (*cli.MockUi, *OperatorSealCommand) {
tb.Helper() tb.Helper()
ui := cli.NewMockUi() ui := cli.NewMockUi()
return ui, &SealCommand{ return ui, &OperatorSealCommand{
BaseCommand: &BaseCommand{ BaseCommand: &BaseCommand{
UI: ui, UI: ui,
}, },
} }
} }
func TestSealCommand_Run(t *testing.T) { func TestOperatorSealCommand_Run(t *testing.T) {
t.Parallel() t.Parallel()
cases := []struct { cases := []struct {
@@ -47,7 +47,7 @@ func TestSealCommand_Run(t *testing.T) {
client, closer := testVaultServer(t) client, closer := testVaultServer(t)
defer closer() defer closer()
ui, cmd := testSealCommand(t) ui, cmd := testOperatorSealCommand(t)
cmd.client = client cmd.client = client
code := cmd.Run(tc.args) code := cmd.Run(tc.args)
@@ -69,7 +69,7 @@ func TestSealCommand_Run(t *testing.T) {
client, closer := testVaultServer(t) client, closer := testVaultServer(t)
defer closer() defer closer()
ui, cmd := testSealCommand(t) ui, cmd := testOperatorSealCommand(t)
cmd.client = client cmd.client = client
code := cmd.Run([]string{}) code := cmd.Run([]string{})
@@ -98,7 +98,7 @@ func TestSealCommand_Run(t *testing.T) {
client, closer := testVaultServerBad(t) client, closer := testVaultServerBad(t)
defer closer() defer closer()
ui, cmd := testSealCommand(t) ui, cmd := testOperatorSealCommand(t)
cmd.client = client cmd.client = client
code := cmd.Run([]string{}) code := cmd.Run([]string{})
@@ -116,7 +116,7 @@ func TestSealCommand_Run(t *testing.T) {
t.Run("no_tabs", func(t *testing.T) { t.Run("no_tabs", func(t *testing.T) {
t.Parallel() t.Parallel()
_, cmd := testSealCommand(t) _, cmd := testOperatorSealCommand(t)
assertNoTabs(t, cmd) assertNoTabs(t, cmd)
}) })
} }

View File

@@ -8,23 +8,20 @@ import (
"github.com/posener/complete" "github.com/posener/complete"
) )
// Ensure we are implementing the right interfaces. var _ cli.Command = (*OperatorStepDownCommand)(nil)
var _ cli.Command = (*StepDownCommand)(nil) var _ cli.CommandAutocomplete = (*OperatorStepDownCommand)(nil)
var _ cli.CommandAutocomplete = (*StepDownCommand)(nil)
// StepDownCommand is a Command that tells the Vault server to give up its type OperatorStepDownCommand struct {
// leadership
type StepDownCommand struct {
*BaseCommand *BaseCommand
} }
func (c *StepDownCommand) Synopsis() string { func (c *OperatorStepDownCommand) Synopsis() string {
return "Forces Vault to resign active duty" return "Forces Vault to resign active duty"
} }
func (c *StepDownCommand) Help() string { func (c *OperatorStepDownCommand) Help() string {
helpText := ` helpText := `
Usage: vault step-down [options] Usage: vault operator step-down [options]
Forces the Vault server at the given address to step down from active duty. Forces the Vault server at the given address to step down from active duty.
While the affected node will have a delay before attempting to acquire the While the affected node will have a delay before attempting to acquire the
@@ -34,28 +31,26 @@ Usage: vault step-down [options]
Force Vault to step down as the leader: Force Vault to step down as the leader:
$ vault step-down $ vault operator step-down
For a full list of examples, please see the documentation.
` + c.Flags().Help() ` + c.Flags().Help()
return strings.TrimSpace(helpText) return strings.TrimSpace(helpText)
} }
func (c *StepDownCommand) Flags() *FlagSets { func (c *OperatorStepDownCommand) Flags() *FlagSets {
return c.flagSet(FlagSetHTTP) return c.flagSet(FlagSetHTTP)
} }
func (c *StepDownCommand) AutocompleteArgs() complete.Predictor { func (c *OperatorStepDownCommand) AutocompleteArgs() complete.Predictor {
return nil return nil
} }
func (c *StepDownCommand) AutocompleteFlags() complete.Flags { func (c *OperatorStepDownCommand) AutocompleteFlags() complete.Flags {
return c.Flags().Completions() return c.Flags().Completions()
} }
func (c *StepDownCommand) Run(args []string) int { func (c *OperatorStepDownCommand) Run(args []string) int {
f := c.Flags() f := c.Flags()
if err := f.Parse(args); err != nil { if err := f.Parse(args); err != nil {

View File

@@ -7,18 +7,18 @@ import (
"github.com/mitchellh/cli" "github.com/mitchellh/cli"
) )
func testStepDownCommand(tb testing.TB) (*cli.MockUi, *StepDownCommand) { func testOperatorStepDownCommand(tb testing.TB) (*cli.MockUi, *OperatorStepDownCommand) {
tb.Helper() tb.Helper()
ui := cli.NewMockUi() ui := cli.NewMockUi()
return ui, &StepDownCommand{ return ui, &OperatorStepDownCommand{
BaseCommand: &BaseCommand{ BaseCommand: &BaseCommand{
UI: ui, UI: ui,
}, },
} }
} }
func TestStepDownCommand_Run(t *testing.T) { func TestOperatorStepDownCommand_Run(t *testing.T) {
t.Parallel() t.Parallel()
cases := []struct { cases := []struct {
@@ -53,7 +53,7 @@ func TestStepDownCommand_Run(t *testing.T) {
client, closer := testVaultServer(t) client, closer := testVaultServer(t)
defer closer() defer closer()
ui, cmd := testStepDownCommand(t) ui, cmd := testOperatorStepDownCommand(t)
cmd.client = client cmd.client = client
code := cmd.Run(tc.args) code := cmd.Run(tc.args)
@@ -75,7 +75,7 @@ func TestStepDownCommand_Run(t *testing.T) {
client, closer := testVaultServerBad(t) client, closer := testVaultServerBad(t)
defer closer() defer closer()
ui, cmd := testStepDownCommand(t) ui, cmd := testOperatorStepDownCommand(t)
cmd.client = client cmd.client = client
code := cmd.Run([]string{}) code := cmd.Run([]string{})
@@ -93,7 +93,7 @@ func TestStepDownCommand_Run(t *testing.T) {
t.Run("no_tabs", func(t *testing.T) { t.Run("no_tabs", func(t *testing.T) {
t.Parallel() t.Parallel()
_, cmd := testStepDownCommand(t) _, cmd := testOperatorStepDownCommand(t)
assertNoTabs(t, cmd) assertNoTabs(t, cmd)
}) })
} }

View File

@@ -12,12 +12,10 @@ import (
"github.com/posener/complete" "github.com/posener/complete"
) )
// Ensure we are implementing the right interfaces. var _ cli.Command = (*OperatorUnsealCommand)(nil)
var _ cli.Command = (*UnsealCommand)(nil) var _ cli.CommandAutocomplete = (*OperatorUnsealCommand)(nil)
var _ cli.CommandAutocomplete = (*UnsealCommand)(nil)
// UnsealCommand is a Command that unseals the vault. type OperatorUnsealCommand struct {
type UnsealCommand struct {
*BaseCommand *BaseCommand
flagReset bool flagReset bool
@@ -25,13 +23,13 @@ type UnsealCommand struct {
testOutput io.Writer // for tests testOutput io.Writer // for tests
} }
func (c *UnsealCommand) Synopsis() string { func (c *OperatorUnsealCommand) Synopsis() string {
return "Unseals the Vault server" return "Unseals the Vault server"
} }
func (c *UnsealCommand) Help() string { func (c *OperatorUnsealCommand) Help() string {
helpText := ` helpText := `
Usage: vault unseal [options] [KEY] Usage: vault operator unseal [options] [KEY]
Provide a portion of the master key to unseal a Vault server. Vault starts Provide a portion of the master key to unseal a Vault server. Vault starts
in a sealed state. It cannot perform operations until it is unsealed. This in a sealed state. It cannot perform operations until it is unsealed. This
@@ -40,21 +38,19 @@ Usage: vault unseal [options] [KEY]
The unseal key can be supplied as an argument to the command, but this is The unseal key can be supplied as an argument to the command, but this is
not recommended as the unseal key will be available in your history: not recommended as the unseal key will be available in your history:
$ vault unseal IXyR0OJnSFobekZMMCKCoVEpT7wI6l+USMzE3IcyDyo= $ vault operator unseal IXyR0OJnSFobekZMMCKCoVEpT7wI6l+USMzE3IcyDyo=
Instead, run the command with no arguments and it will prompt for the key: Instead, run the command with no arguments and it will prompt for the key:
$ vault unseal $ vault operator unseal
Key (will be hidden): IXyR0OJnSFobekZMMCKCoVEpT7wI6l+USMzE3IcyDyo= Key (will be hidden): IXyR0OJnSFobekZMMCKCoVEpT7wI6l+USMzE3IcyDyo=
For a full list of examples, please see the documentation.
` + c.Flags().Help() ` + c.Flags().Help()
return strings.TrimSpace(helpText) return strings.TrimSpace(helpText)
} }
func (c *UnsealCommand) Flags() *FlagSets { func (c *OperatorUnsealCommand) Flags() *FlagSets {
set := c.flagSet(FlagSetHTTP) set := c.flagSet(FlagSetHTTP)
f := set.NewFlagSet("Command Options") f := set.NewFlagSet("Command Options")
@@ -72,15 +68,15 @@ func (c *UnsealCommand) Flags() *FlagSets {
return set return set
} }
func (c *UnsealCommand) AutocompleteArgs() complete.Predictor { func (c *OperatorUnsealCommand) AutocompleteArgs() complete.Predictor {
return c.PredictVaultFiles() return c.PredictVaultFiles()
} }
func (c *UnsealCommand) AutocompleteFlags() complete.Flags { func (c *OperatorUnsealCommand) AutocompleteFlags() complete.Flags {
return c.Flags().Completions() return c.Flags().Completions()
} }
func (c *UnsealCommand) Run(args []string) int { func (c *OperatorUnsealCommand) Run(args []string) int {
f := c.Flags() f := c.Flags()
if err := f.Parse(args); err != nil { if err := f.Parse(args); err != nil {
@@ -151,7 +147,7 @@ func (c *UnsealCommand) Run(args []string) int {
return 0 return 0
} }
func (c *UnsealCommand) prettySealStatus(status *api.SealStatusResponse) { func (c *OperatorUnsealCommand) prettySealStatus(status *api.SealStatusResponse) {
c.UI.Output(fmt.Sprintf("Sealed: %t", status.Sealed)) c.UI.Output(fmt.Sprintf("Sealed: %t", status.Sealed))
c.UI.Output(fmt.Sprintf("Key Shares: %d", status.N)) c.UI.Output(fmt.Sprintf("Key Shares: %d", status.N))
c.UI.Output(fmt.Sprintf("Key Threshold: %d", status.T)) c.UI.Output(fmt.Sprintf("Key Threshold: %d", status.T))

View File

@@ -9,24 +9,24 @@ import (
"github.com/mitchellh/cli" "github.com/mitchellh/cli"
) )
func testUnsealCommand(tb testing.TB) (*cli.MockUi, *UnsealCommand) { func testOperatorUnsealCommand(tb testing.TB) (*cli.MockUi, *OperatorUnsealCommand) {
tb.Helper() tb.Helper()
ui := cli.NewMockUi() ui := cli.NewMockUi()
return ui, &UnsealCommand{ return ui, &OperatorUnsealCommand{
BaseCommand: &BaseCommand{ BaseCommand: &BaseCommand{
UI: ui, UI: ui,
}, },
} }
} }
func TestUnsealCommand_Run(t *testing.T) { func TestOperatorUnsealCommand_Run(t *testing.T) {
t.Parallel() t.Parallel()
t.Run("error_non_terminal", func(t *testing.T) { t.Run("error_non_terminal", func(t *testing.T) {
t.Parallel() t.Parallel()
ui, cmd := testUnsealCommand(t) ui, cmd := testOperatorUnsealCommand(t)
cmd.testOutput = ioutil.Discard cmd.testOutput = ioutil.Discard
code := cmd.Run(nil) code := cmd.Run(nil)
@@ -57,7 +57,7 @@ func TestUnsealCommand_Run(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
ui, cmd := testUnsealCommand(t) ui, cmd := testOperatorUnsealCommand(t)
cmd.client = client cmd.client = client
cmd.testOutput = ioutil.Discard cmd.testOutput = ioutil.Discard
@@ -87,7 +87,7 @@ func TestUnsealCommand_Run(t *testing.T) {
} }
for i, key := range keys { for i, key := range keys {
ui, cmd := testUnsealCommand(t) ui, cmd := testOperatorUnsealCommand(t)
cmd.client = client cmd.client = client
cmd.testOutput = ioutil.Discard cmd.testOutput = ioutil.Discard
@@ -112,7 +112,7 @@ func TestUnsealCommand_Run(t *testing.T) {
client, closer := testVaultServerBad(t) client, closer := testVaultServerBad(t)
defer closer() defer closer()
ui, cmd := testUnsealCommand(t) ui, cmd := testOperatorUnsealCommand(t)
cmd.client = client cmd.client = client
code := cmd.Run([]string{ code := cmd.Run([]string{
@@ -132,7 +132,7 @@ func TestUnsealCommand_Run(t *testing.T) {
t.Run("no_tabs", func(t *testing.T) { t.Run("no_tabs", func(t *testing.T) {
t.Parallel() t.Parallel()
_, cmd := testUnsealCommand(t) _, cmd := testOperatorUnsealCommand(t)
assertNoTabs(t, cmd) assertNoTabs(t, cmd)
}) })
} }

View File

@@ -8,20 +8,18 @@ import (
"github.com/posener/complete" "github.com/posener/complete"
) )
// Ensure we are implementing the right interfaces. var _ cli.Command = (*OperatorRotateCommand)(nil)
var _ cli.Command = (*RotateCommand)(nil) var _ cli.CommandAutocomplete = (*OperatorRotateCommand)(nil)
var _ cli.CommandAutocomplete = (*RotateCommand)(nil)
// RotateCommand is a Command that rotates the encryption key being used type OperatorRotateCommand struct {
type RotateCommand struct {
*BaseCommand *BaseCommand
} }
func (c *RotateCommand) Synopsis() string { func (c *OperatorRotateCommand) Synopsis() string {
return "Rotates the underlying encryption key" return "Rotates the underlying encryption key"
} }
func (c *RotateCommand) Help() string { func (c *OperatorRotateCommand) Help() string {
helpText := ` helpText := `
Usage: vault rotate [options] Usage: vault rotate [options]
@@ -31,8 +29,8 @@ Usage: vault rotate [options]
decrypt older data. decrypt older data.
This is an online operation and does not cause downtime. This command is run This is an online operation and does not cause downtime. This command is run
per-cluser (not per-server), since Vault servers in HA mode share the same per-cluster (not per-server), since Vault servers in HA mode share the same
storeage backend. storage backend.
Rotate Vault's encryption key: Rotate Vault's encryption key:
@@ -45,19 +43,19 @@ Usage: vault rotate [options]
return strings.TrimSpace(helpText) return strings.TrimSpace(helpText)
} }
func (c *RotateCommand) Flags() *FlagSets { func (c *OperatorRotateCommand) Flags() *FlagSets {
return c.flagSet(FlagSetHTTP) return c.flagSet(FlagSetHTTP)
} }
func (c *RotateCommand) AutocompleteArgs() complete.Predictor { func (c *OperatorRotateCommand) AutocompleteArgs() complete.Predictor {
return nil return nil
} }
func (c *RotateCommand) AutocompleteFlags() complete.Flags { func (c *OperatorRotateCommand) AutocompleteFlags() complete.Flags {
return c.Flags().Completions() return c.Flags().Completions()
} }
func (c *RotateCommand) Run(args []string) int { func (c *OperatorRotateCommand) Run(args []string) int {
f := c.Flags() f := c.Flags()
if err := f.Parse(args); err != nil { if err := f.Parse(args); err != nil {

View File

@@ -7,18 +7,18 @@ import (
"github.com/mitchellh/cli" "github.com/mitchellh/cli"
) )
func testRotateCommand(tb testing.TB) (*cli.MockUi, *RotateCommand) { func testOperatorRotateCommand(tb testing.TB) (*cli.MockUi, *OperatorRotateCommand) {
tb.Helper() tb.Helper()
ui := cli.NewMockUi() ui := cli.NewMockUi()
return ui, &RotateCommand{ return ui, &OperatorRotateCommand{
BaseCommand: &BaseCommand{ BaseCommand: &BaseCommand{
UI: ui, UI: ui,
}, },
} }
} }
func TestRotateCommand_Run(t *testing.T) { func TestOperatorRotateCommand_Run(t *testing.T) {
t.Parallel() t.Parallel()
cases := []struct { cases := []struct {
@@ -44,7 +44,7 @@ func TestRotateCommand_Run(t *testing.T) {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
t.Parallel() t.Parallel()
ui, cmd := testRotateCommand(t) ui, cmd := testOperatorRotateCommand(t)
code := cmd.Run(tc.args) code := cmd.Run(tc.args)
if code != tc.code { if code != tc.code {
@@ -65,7 +65,7 @@ func TestRotateCommand_Run(t *testing.T) {
client, closer := testVaultServer(t) client, closer := testVaultServer(t)
defer closer() defer closer()
ui, cmd := testRotateCommand(t) ui, cmd := testOperatorRotateCommand(t)
cmd.client = client cmd.client = client
code := cmd.Run([]string{}) code := cmd.Run([]string{})
@@ -94,7 +94,7 @@ func TestRotateCommand_Run(t *testing.T) {
client, closer := testVaultServerBad(t) client, closer := testVaultServerBad(t)
defer closer() defer closer()
ui, cmd := testRotateCommand(t) ui, cmd := testOperatorRotateCommand(t)
cmd.client = client cmd.client = client
code := cmd.Run([]string{}) code := cmd.Run([]string{})
@@ -112,7 +112,7 @@ func TestRotateCommand_Run(t *testing.T) {
t.Run("no_tabs", func(t *testing.T) { t.Run("no_tabs", func(t *testing.T) {
t.Parallel() t.Parallel()
_, cmd := testRotateCommand(t) _, cmd := testOperatorRotateCommand(t)
assertNoTabs(t, cmd) assertNoTabs(t, cmd)
}) })
} }