From b982365fbb82d1014102f805ca438f81acad0962 Mon Sep 17 00:00:00 2001 From: Seth Vargo Date: Thu, 7 Sep 2017 22:03:12 -0400 Subject: [PATCH] Add "operator" subcommand --- command/operator.go | 47 ++++++++++++ ...rate_root.go => operator_generate_root.go} | 56 +++++++-------- ...test.go => operator_generate_root_test.go} | 32 ++++----- command/{init.go => operator_init.go} | 40 +++++------ .../{init_test.go => operator_init_test.go} | 22 +++--- .../{key_status.go => operator_key_status.go} | 22 +++--- ...us_test.go => operator_key_status_test.go} | 14 ++-- command/{rekey.go => operator_rekey.go} | 71 ++++++++----------- .../{rekey_test.go => operator_rekey_test.go} | 38 +++++----- command/{seal.go => operator_seal.go} | 25 +++---- .../{seal_test.go => operator_seal_test.go} | 14 ++-- .../{step_down.go => operator_step_down.go} | 27 +++---- ...own_test.go => operator_step_down_test.go} | 12 ++-- command/{unseal.go => operator_unseal.go} | 30 ++++---- ...unseal_test.go => operator_unseal_test.go} | 16 ++--- command/rotate.go | 24 +++---- command/rotate_test.go | 14 ++-- 17 files changed, 255 insertions(+), 249 deletions(-) create mode 100644 command/operator.go rename command/{generate_root.go => operator_generate_root.go} (87%) rename command/{generate_root_test.go => operator_generate_root_test.go} (91%) rename command/{init.go => operator_init.go} (93%) rename command/{init_test.go => operator_init_test.go} (93%) rename command/{key_status.go => operator_key_status.go} (61%) rename command/{key_status_test.go => operator_key_status_test.go} (83%) rename command/{rekey.go => operator_rekey.go} (89%) rename command/{rekey_test.go => operator_rekey_test.go} (92%) rename command/{seal.go => operator_seal.go} (68%) rename command/{seal_test.go => operator_seal_test.go} (86%) rename command/{step_down.go => operator_step_down.go} (63%) rename command/{step_down_test.go => operator_step_down_test.go} (82%) rename command/{unseal.go => operator_unseal.go} (80%) rename command/{unseal_test.go => operator_unseal_test.go} (87%) diff --git a/command/operator.go b/command/operator.go new file mode 100644 index 000000000..ad1bb439f --- /dev/null +++ b/command/operator.go @@ -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 [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 +} diff --git a/command/generate_root.go b/command/operator_generate_root.go similarity index 87% rename from command/generate_root.go rename to command/operator_generate_root.go index 58f744256..6eb17042a 100644 --- a/command/generate_root.go +++ b/command/operator_generate_root.go @@ -18,12 +18,10 @@ import ( "github.com/posener/complete" ) -// Ensure we are implementing the right interfaces. -var _ cli.Command = (*GenerateRootCommand)(nil) -var _ cli.CommandAutocomplete = (*GenerateRootCommand)(nil) +var _ cli.Command = (*OperatorGenerateRootCommand)(nil) +var _ cli.CommandAutocomplete = (*OperatorGenerateRootCommand)(nil) -// GenerateRootCommand is a Command that generates a new root token. -type GenerateRootCommand struct { +type OperatorGenerateRootCommand struct { *BaseCommand flagInit bool @@ -36,26 +34,26 @@ type GenerateRootCommand struct { flagGenerateOTP bool // Deprecation - // TODO: remove in 0.9.9 + // TODO: remove in 0.9.0 flagGenOTP bool testStdin io.Reader // for tests } -func (c *GenerateRootCommand) Synopsis() string { +func (c *OperatorGenerateRootCommand) Synopsis() string { return "Generates a new root token" } -func (c *GenerateRootCommand) Help() string { +func (c *OperatorGenerateRootCommand) Help() string { 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 the following must be provided to start the root token generation: - A base64-encoded one-time-password (OTP) provided via the "-otp" flag. 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. - 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: - $ vault generate-root -generate-otp + $ vault operator generate-root -generate-otp Start a root token generation: - $ vault generate-root -init -otp="..." - $ vault generate-root -init -pgp-key="..." + $ vault operator generate-root -init -otp="..." + $ vault operator generate-root -init -pgp-key="..." Enter an unseal key to progress root token generation: - $ vault generate-root -otp="..." - - For a full list of examples, please see the documentation. + $ vault operator generate-root -otp="..." ` + c.Flags().Help() return strings.TrimSpace(helpText) } -func (c *GenerateRootCommand) Flags() *FlagSets { +func (c *OperatorGenerateRootCommand) Flags() *FlagSets { set := c.flagSet(FlagSetHTTP) f := set.NewFlagSet("Command Options") @@ -115,7 +111,7 @@ func (c *GenerateRootCommand) Flags() *FlagSets { Default: false, EnvVar: "", 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.", }) @@ -183,15 +179,15 @@ func (c *GenerateRootCommand) Flags() *FlagSets { return set } -func (c *GenerateRootCommand) AutocompleteArgs() complete.Predictor { +func (c *OperatorGenerateRootCommand) AutocompleteArgs() complete.Predictor { return nil } -func (c *GenerateRootCommand) AutocompleteFlags() complete.Flags { +func (c *OperatorGenerateRootCommand) AutocompleteFlags() complete.Flags { return c.Flags().Completions() } -func (c *GenerateRootCommand) Run(args []string) int { +func (c *OperatorGenerateRootCommand) Run(args []string) int { f := c.Flags() 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. -func (c *GenerateRootCommand) verifyOTP(otp string) error { +func (c *OperatorGenerateRootCommand) verifyOTP(otp string) error { if len(otp) == 0 { 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. -func (c *GenerateRootCommand) generateOTP() int { +func (c *OperatorGenerateRootCommand) generateOTP() int { buf := make([]byte, 16) readLen, err := rand.Read(buf) if err != nil { @@ -276,7 +272,7 @@ func (c *GenerateRootCommand) generateOTP() int { } // 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 == "" { c.UI.Error("Missing encoded value: use -decode= to supply it") return 1 @@ -302,7 +298,7 @@ func (c *GenerateRootCommand) decode(encoded, otp string) int { } // 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. switch { 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 // 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() if err != nil { 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 -func (c *GenerateRootCommand) cancel(client *api.Client) int { +func (c *OperatorGenerateRootCommand) cancel(client *api.Client) int { if err := client.Sys().GenerateRootCancel(); err != nil { c.UI.Error(fmt.Sprintf("Error canceling root token generation: %s", err)) return 2 @@ -423,7 +419,7 @@ func (c *GenerateRootCommand) cancel(client *api.Client) int { } // 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() if err != nil { 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 -func (c *GenerateRootCommand) printStatus(status *api.GenerateRootStatusResponse) int { +func (c *OperatorGenerateRootCommand) printStatus(status *api.GenerateRootStatusResponse) int { out := []string{} out = append(out, fmt.Sprintf("Nonce | %s", status.Nonce)) 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)) } - output := columnOutput(out) + output := columnOutput(out, nil) c.UI.Output(output) return 0 } diff --git a/command/generate_root_test.go b/command/operator_generate_root_test.go similarity index 91% rename from command/generate_root_test.go rename to command/operator_generate_root_test.go index ba13f6b47..ad5e67e23 100644 --- a/command/generate_root_test.go +++ b/command/operator_generate_root_test.go @@ -11,18 +11,18 @@ import ( "github.com/mitchellh/cli" ) -func testGenerateRootCommand(tb testing.TB) (*cli.MockUi, *GenerateRootCommand) { +func testOperatorGenerateRootCommand(tb testing.TB) (*cli.MockUi, *OperatorGenerateRootCommand) { tb.Helper() ui := cli.NewMockUi() - return ui, &GenerateRootCommand{ + return ui, &OperatorGenerateRootCommand{ BaseCommand: &BaseCommand{ UI: ui, }, } } -func TestGenerateRootCommand_Run(t *testing.T) { +func TestOperatorGenerateRootCommand_Run(t *testing.T) { t.Parallel() cases := []struct { @@ -88,7 +88,7 @@ func TestGenerateRootCommand_Run(t *testing.T) { t.Run(tc.name, func(t *testing.T) { t.Parallel() - ui, cmd := testGenerateRootCommand(t) + ui, cmd := testOperatorGenerateRootCommand(t) code := cmd.Run(tc.args) if code != tc.code { @@ -106,7 +106,7 @@ func TestGenerateRootCommand_Run(t *testing.T) { t.Run("generate_otp", func(t *testing.T) { t.Parallel() - ui, cmd := testGenerateRootCommand(t) + ui, cmd := testOperatorGenerateRootCommand(t) code := cmd.Run([]string{ "-generate-otp", @@ -127,7 +127,7 @@ func TestGenerateRootCommand_Run(t *testing.T) { encoded := "L9MaZ/4mQanpOV6QeWd84g==" otp := "dIeeezkjpDUv3fy7MYPOLQ==" - ui, cmd := testGenerateRootCommand(t) + ui, cmd := testOperatorGenerateRootCommand(t) code := cmd.Run([]string{ "-decode", encoded, @@ -157,7 +157,7 @@ func TestGenerateRootCommand_Run(t *testing.T) { t.Fatal(err) } - ui, cmd := testGenerateRootCommand(t) + ui, cmd := testOperatorGenerateRootCommand(t) cmd.client = client code := cmd.Run([]string{ @@ -191,7 +191,7 @@ func TestGenerateRootCommand_Run(t *testing.T) { client, closer := testVaultServer(t) defer closer() - ui, cmd := testGenerateRootCommand(t) + ui, cmd := testOperatorGenerateRootCommand(t) cmd.client = client code := cmd.Run([]string{ @@ -227,7 +227,7 @@ func TestGenerateRootCommand_Run(t *testing.T) { client, closer := testVaultServer(t) defer closer() - ui, cmd := testGenerateRootCommand(t) + ui, cmd := testOperatorGenerateRootCommand(t) cmd.client = client code := cmd.Run([]string{ @@ -263,7 +263,7 @@ func TestGenerateRootCommand_Run(t *testing.T) { client, closer := testVaultServer(t) defer closer() - ui, cmd := testGenerateRootCommand(t) + ui, cmd := testOperatorGenerateRootCommand(t) cmd.client = client code := cmd.Run([]string{ @@ -297,7 +297,7 @@ func TestGenerateRootCommand_Run(t *testing.T) { // Supply the first n-1 unseal keys for _, key := range keys[:len(keys)-1] { - _, cmd := testGenerateRootCommand(t) + _, cmd := testOperatorGenerateRootCommand(t) cmd.client = client 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 code := cmd.Run([]string{ @@ -364,7 +364,7 @@ func TestGenerateRootCommand_Run(t *testing.T) { stdinW.Close() }() - _, cmd := testGenerateRootCommand(t) + _, cmd := testOperatorGenerateRootCommand(t) cmd.client = client cmd.testStdin = stdinR @@ -383,7 +383,7 @@ func TestGenerateRootCommand_Run(t *testing.T) { stdinW.Close() }() - ui, cmd := testGenerateRootCommand(t) + ui, cmd := testOperatorGenerateRootCommand(t) cmd.client = client cmd.testStdin = stdinR @@ -422,7 +422,7 @@ func TestGenerateRootCommand_Run(t *testing.T) { client, closer := testVaultServerBad(t) defer closer() - ui, cmd := testGenerateRootCommand(t) + ui, cmd := testOperatorGenerateRootCommand(t) cmd.client = client code := cmd.Run([]string{ @@ -442,7 +442,7 @@ func TestGenerateRootCommand_Run(t *testing.T) { t.Run("no_tabs", func(t *testing.T) { t.Parallel() - _, cmd := testGenerateRootCommand(t) + _, cmd := testOperatorGenerateRootCommand(t) assertNoTabs(t, cmd) }) } diff --git a/command/init.go b/command/operator_init.go similarity index 93% rename from command/init.go rename to command/operator_init.go index c2d112081..cf3aaf31d 100644 --- a/command/init.go +++ b/command/operator_init.go @@ -16,12 +16,10 @@ import ( consulapi "github.com/hashicorp/consul/api" ) -// Ensure we are implementing the right interfaces. -var _ cli.Command = (*InitCommand)(nil) -var _ cli.CommandAutocomplete = (*InitCommand)(nil) +var _ cli.Command = (*OperatorInitCommand)(nil) +var _ cli.CommandAutocomplete = (*OperatorInitCommand)(nil) -// InitCommand is a Command that initializes a new Vault server. -type InitCommand struct { +type OperatorInitCommand struct { *BaseCommand flagStatus bool @@ -46,13 +44,13 @@ type InitCommand struct { flagCheck bool } -func (c *InitCommand) Synopsis() string { +func (c *OperatorInitCommand) Synopsis() string { return "Initializes a server" } -func (c *InitCommand) Help() string { +func (c *OperatorInitCommand) Help() string { helpText := ` -Usage: vault init [options] +Usage: vault operator init [options] 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 @@ -69,26 +67,24 @@ Usage: vault init [options] Start initialization with the default options: - $ vault init + $ vault operator init Initialize, but encrypt the unseal keys with pgp keys: - $ vault init \ + $ vault operator init \ -key-shares=3 \ -key-threshold=2 \ -pgp-keys="keybase:hashicorp,keybase:jefferai,keybase:sethvargo" Encrypt the initial root token using a pgp key: - $ vault init -root-token-pgp-key="keybase:hashicorp" - - For a complete list of examples, please see the documentation. + $ vault operator init -root-token-pgp-key="keybase:hashicorp" ` + c.Flags().Help() return strings.TrimSpace(helpText) } -func (c *InitCommand) Flags() *FlagSets { +func (c *OperatorInitCommand) Flags() *FlagSets { set := c.flagSet(FlagSetHTTP | FlagSetOutputFormat) // Common Options @@ -231,15 +227,15 @@ func (c *InitCommand) Flags() *FlagSets { return set } -func (c *InitCommand) AutocompleteArgs() complete.Predictor { +func (c *OperatorInitCommand) AutocompleteArgs() complete.Predictor { return nil } -func (c *InitCommand) AutocompleteFlags() complete.Flags { +func (c *OperatorInitCommand) AutocompleteFlags() complete.Flags { return c.Flags().Completions() } -func (c *InitCommand) Run(args []string) int { +func (c *OperatorInitCommand) Run(args []string) int { f := c.Flags() if err := f.Parse(args); err != nil { @@ -293,7 +289,7 @@ func (c *InitCommand) Run(args []string) int { } // 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 originalAddr := client.Address() 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) if err != nil { 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. -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)) if err != nil { 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. -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)) if err != nil { 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 // code and message. -func (c *InitCommand) status(client *api.Client) int { +func (c *OperatorInitCommand) status(client *api.Client) int { inited, err := client.Sys().InitStatus() if err != nil { c.UI.Error(fmt.Sprintf("Error checking init status: %s", err)) diff --git a/command/init_test.go b/command/operator_init_test.go similarity index 93% rename from command/init_test.go rename to command/operator_init_test.go index c0f88e58d..f398dd375 100644 --- a/command/init_test.go +++ b/command/operator_init_test.go @@ -13,18 +13,18 @@ import ( "github.com/mitchellh/cli" ) -func testInitCommand(tb testing.TB) (*cli.MockUi, *InitCommand) { +func testOperatorInitCommand(tb testing.TB) (*cli.MockUi, *OperatorInitCommand) { tb.Helper() ui := cli.NewMockUi() - return ui, &InitCommand{ + return ui, &OperatorInitCommand{ BaseCommand: &BaseCommand{ UI: ui, }, } } -func TestInitCommand_Run(t *testing.T) { +func TestOperatorInitCommand_Run(t *testing.T) { t.Parallel() cases := []struct { @@ -100,7 +100,7 @@ func TestInitCommand_Run(t *testing.T) { client, closer := testVaultServer(t) defer closer() - ui, cmd := testInitCommand(t) + ui, cmd := testOperatorInitCommand(t) cmd.client = client code := cmd.Run(tc.args) @@ -122,7 +122,7 @@ func TestInitCommand_Run(t *testing.T) { client, closer := testVaultServerUninit(t) defer closer() - ui, cmd := testInitCommand(t) + ui, cmd := testOperatorInitCommand(t) cmd.client = client // Verify the non-init response code @@ -142,7 +142,7 @@ func TestInitCommand_Run(t *testing.T) { } // Verify the init response code - ui, cmd = testInitCommand(t) + ui, cmd = testOperatorInitCommand(t) cmd.client = client code = cmd.Run([]string{ "-status", @@ -158,7 +158,7 @@ func TestInitCommand_Run(t *testing.T) { client, closer := testVaultServerUninit(t) defer closer() - ui, cmd := testInitCommand(t) + ui, cmd := testOperatorInitCommand(t) cmd.client = client code := cmd.Run([]string{}) @@ -217,7 +217,7 @@ func TestInitCommand_Run(t *testing.T) { client, closer := testVaultServerUninit(t) defer closer() - ui, cmd := testInitCommand(t) + ui, cmd := testOperatorInitCommand(t) cmd.client = client code := cmd.Run([]string{ @@ -283,7 +283,7 @@ func TestInitCommand_Run(t *testing.T) { client, closer := testVaultServerUninit(t) defer closer() - ui, cmd := testInitCommand(t) + ui, cmd := testOperatorInitCommand(t) cmd.client = client code := cmd.Run([]string{ @@ -335,7 +335,7 @@ func TestInitCommand_Run(t *testing.T) { client, closer := testVaultServerBad(t) defer closer() - ui, cmd := testInitCommand(t) + ui, cmd := testOperatorInitCommand(t) cmd.client = client code := cmd.Run([]string{ @@ -355,7 +355,7 @@ func TestInitCommand_Run(t *testing.T) { t.Run("no_tabs", func(t *testing.T) { t.Parallel() - _, cmd := testInitCommand(t) + _, cmd := testOperatorInitCommand(t) assertNoTabs(t, cmd) }) } diff --git a/command/key_status.go b/command/operator_key_status.go similarity index 61% rename from command/key_status.go rename to command/operator_key_status.go index b870035b7..6558290ca 100644 --- a/command/key_status.go +++ b/command/operator_key_status.go @@ -8,22 +8,20 @@ import ( "github.com/posener/complete" ) -// Ensure we are implementing the right interfaces. -var _ cli.Command = (*KeyStatusCommand)(nil) -var _ cli.CommandAutocomplete = (*KeyStatusCommand)(nil) +var _ cli.Command = (*OperatorKeyStatusCommand)(nil) +var _ cli.CommandAutocomplete = (*OperatorKeyStatusCommand)(nil) -// KeyStatusCommand is a Command that provides information about the key status -type KeyStatusCommand struct { +type OperatorKeyStatusCommand struct { *BaseCommand } -func (c *KeyStatusCommand) Synopsis() string { +func (c *OperatorKeyStatusCommand) Synopsis() string { return "Provides information about the active encryption key" } -func (c *KeyStatusCommand) Help() string { +func (c *OperatorKeyStatusCommand) Help() string { helpText := ` -Usage: vault key-status [options] +Usage: vault operator key-status [options] Provides information about the active encryption key. Specifically, the current key term and the key installation time. @@ -33,19 +31,19 @@ Usage: vault key-status [options] return strings.TrimSpace(helpText) } -func (c *KeyStatusCommand) Flags() *FlagSets { +func (c *OperatorKeyStatusCommand) Flags() *FlagSets { return c.flagSet(FlagSetHTTP) } -func (c *KeyStatusCommand) AutocompleteArgs() complete.Predictor { +func (c *OperatorKeyStatusCommand) AutocompleteArgs() complete.Predictor { return nil } -func (c *KeyStatusCommand) AutocompleteFlags() complete.Flags { +func (c *OperatorKeyStatusCommand) AutocompleteFlags() complete.Flags { return c.Flags().Completions() } -func (c *KeyStatusCommand) Run(args []string) int { +func (c *OperatorKeyStatusCommand) Run(args []string) int { f := c.Flags() if err := f.Parse(args); err != nil { diff --git a/command/key_status_test.go b/command/operator_key_status_test.go similarity index 83% rename from command/key_status_test.go rename to command/operator_key_status_test.go index 640cef7bb..5c1aada3e 100644 --- a/command/key_status_test.go +++ b/command/operator_key_status_test.go @@ -7,18 +7,18 @@ import ( "github.com/mitchellh/cli" ) -func testKeyStatusCommand(tb testing.TB) (*cli.MockUi, *KeyStatusCommand) { +func testOperatorKeyStatusCommand(tb testing.TB) (*cli.MockUi, *OperatorKeyStatusCommand) { tb.Helper() ui := cli.NewMockUi() - return ui, &KeyStatusCommand{ + return ui, &OperatorKeyStatusCommand{ BaseCommand: &BaseCommand{ UI: ui, }, } } -func TestKeyStatusCommand_Run(t *testing.T) { +func TestOperatorKeyStatusCommand_Run(t *testing.T) { t.Parallel() cases := []struct { @@ -44,7 +44,7 @@ func TestKeyStatusCommand_Run(t *testing.T) { t.Run(tc.name, func(t *testing.T) { t.Parallel() - ui, cmd := testKeyStatusCommand(t) + ui, cmd := testOperatorKeyStatusCommand(t) code := cmd.Run(tc.args) if code != tc.code { @@ -65,7 +65,7 @@ func TestKeyStatusCommand_Run(t *testing.T) { client, closer := testVaultServer(t) defer closer() - ui, cmd := testKeyStatusCommand(t) + ui, cmd := testOperatorKeyStatusCommand(t) cmd.client = client code := cmd.Run([]string{}) @@ -86,7 +86,7 @@ func TestKeyStatusCommand_Run(t *testing.T) { client, closer := testVaultServerBad(t) defer closer() - ui, cmd := testKeyStatusCommand(t) + ui, cmd := testOperatorKeyStatusCommand(t) cmd.client = client code := cmd.Run([]string{}) @@ -104,7 +104,7 @@ func TestKeyStatusCommand_Run(t *testing.T) { t.Run("no_tabs", func(t *testing.T) { t.Parallel() - _, cmd := testKeyStatusCommand(t) + _, cmd := testOperatorKeyStatusCommand(t) assertNoTabs(t, cmd) }) } diff --git a/command/rekey.go b/command/operator_rekey.go similarity index 89% rename from command/rekey.go rename to command/operator_rekey.go index b4b5195ec..c80845820 100644 --- a/command/rekey.go +++ b/command/operator_rekey.go @@ -15,24 +15,12 @@ import ( "github.com/posener/complete" ) -// Ensure we are implementing the right interfaces. -var _ cli.Command = (*RekeyCommand)(nil) -var _ cli.CommandAutocomplete = (*RekeyCommand)(nil) +var _ cli.Command = (*OperatorRekeyCommand)(nil) +var _ cli.CommandAutocomplete = (*OperatorRekeyCommand)(nil) -// RekeyCommand is a Command that rekeys the vault. -type RekeyCommand struct { +type OperatorRekeyCommand struct { *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 flagInit bool flagKeyShares int @@ -56,11 +44,11 @@ type RekeyCommand struct { testStdin io.Reader // for tests } -func (c *RekeyCommand) Synopsis() string { +func (c *OperatorRekeyCommand) Synopsis() string { return "Generates new unseal keys" } -func (c *RekeyCommand) Help() string { +func (c *OperatorRekeyCommand) Help() string { helpText := ` Usage: vault rekey [options] [KEY] @@ -75,14 +63,14 @@ Usage: vault rekey [options] [KEY] Initialize a rekey: - $ vault rekey \ + $ vault operator rekey \ -init \ -key-shares=15 \ -key-threshold=9 Rekey and encrypt the resulting unseal keys with PGP: - $ vault rekey \ + $ vault operator rekey \ -init \ -key-shares=3 \ -key-threshold=2 \ @@ -90,29 +78,27 @@ Usage: vault rekey [options] [KEY] Store encrypted PGP keys in Vault's core: - $ vault rekey \ + $ vault operator rekey \ -init \ -pgp-keys="..." \ -backup Retrieve backed-up unseal keys: - $ vault rekey -backup-retrieve + $ vault operator rekey -backup-retrieve Delete backed-up unseal keys: - $ vault rekey -backup-delete - - For a full list of examples, please see the documentation. + $ vault operator rekey -backup-delete ` + c.Flags().Help() return strings.TrimSpace(helpText) } -func (c *RekeyCommand) Flags() *FlagSets { +func (c *OperatorRekeyCommand) Flags() *FlagSets { set := c.flagSet(FlagSetHTTP) - f := set.NewFlagSet("Command Options") + f := set.NewFlagSet("Common Options") f.BoolVar(&BoolVar{ Name: "init", @@ -136,7 +122,7 @@ func (c *RekeyCommand) Flags() *FlagSets { Name: "status", Target: &c.flagStatus, 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.", }) @@ -188,8 +174,7 @@ func (c *RekeyCommand) Flags() *FlagSets { "public GPG keys OR a comma-separated list of Keybase usernames using " + "the format \"keybase:\". When supplied, the generated " + "unseal keys will be encrypted and base64-encoded in the order " + - "specified in this list. The number of entires must match -key-shares, " + - "unless -store-shares are used.", + "specified in this list.", }) f = set.NewFlagSet("Backup Options") @@ -216,7 +201,7 @@ func (c *RekeyCommand) Flags() *FlagSets { Name: "backup-retrieve", Target: &c.flagBackupRetrieve, 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.", }) @@ -249,15 +234,15 @@ func (c *RekeyCommand) Flags() *FlagSets { return set } -func (c *RekeyCommand) AutocompleteArgs() complete.Predictor { +func (c *OperatorRekeyCommand) AutocompleteArgs() complete.Predictor { return complete.PredictAnything } -func (c *RekeyCommand) AutocompleteFlags() complete.Flags { +func (c *OperatorRekeyCommand) AutocompleteFlags() complete.Flags { return c.Flags().Completions() } -func (c *RekeyCommand) Run(args []string) int { +func (c *OperatorRekeyCommand) Run(args []string) int { f := c.Flags() if err := f.Parse(args); err != nil { @@ -324,7 +309,7 @@ func (c *RekeyCommand) Run(args []string) int { } // 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 var fn func(*api.RekeyInitRequest) (*api.RekeyStatusResponse, error) 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. -func (c *RekeyCommand) cancel(client *api.Client) int { +func (c *OperatorRekeyCommand) cancel(client *api.Client) int { // Handle the different API requests var fn func() error 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 // 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 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. -func (c *RekeyCommand) status(client *api.Client) int { +func (c *OperatorRekeyCommand) status(client *api.Client) int { // Handle the different API requests var fn func() (*api.RekeyStatusResponse, error) 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. -func (c *RekeyCommand) backupRetrieve(client *api.Client) int { +func (c *OperatorRekeyCommand) backupRetrieve(client *api.Client) int { // Handle the different API requests var fn func() (*api.RekeyRetrieveResponse, error) 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. -func (c *RekeyCommand) backupDelete(client *api.Client) int { +func (c *OperatorRekeyCommand) backupDelete(client *api.Client) int { // Handle the different API requests var fn func() error 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 -func (c *RekeyCommand) printStatus(status *api.RekeyStatusResponse) int { +func (c *OperatorRekeyCommand) printStatus(status *api.RekeyStatusResponse) int { out := []string{} out = append(out, fmt.Sprintf("Nonce | %s", status.Nonce)) 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)) } - output := columnOutput(out) + output := columnOutput(out, nil) c.UI.Output(output) 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 c.UI.Output("") @@ -633,7 +618,7 @@ func (c *RekeyCommand) printUnsealKeys(status *api.RekeyStatusResponse, resp *ap c.UI.Output("") c.UI.Output(wrapAtLength(fmt.Sprintf( "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 " + "these keys.", ))) diff --git a/command/rekey_test.go b/command/operator_rekey_test.go similarity index 92% rename from command/rekey_test.go rename to command/operator_rekey_test.go index 7c08287d0..47154c73e 100644 --- a/command/rekey_test.go +++ b/command/operator_rekey_test.go @@ -11,18 +11,18 @@ import ( "github.com/mitchellh/cli" ) -func testRekeyCommand(tb testing.TB) (*cli.MockUi, *RekeyCommand) { +func testOperatorRekeyCommand(tb testing.TB) (*cli.MockUi, *OperatorRekeyCommand) { tb.Helper() ui := cli.NewMockUi() - return ui, &RekeyCommand{ + return ui, &OperatorRekeyCommand{ BaseCommand: &BaseCommand{ UI: ui, }, } } -func TestRekeyCommand_Run(t *testing.T) { +func TestOperatorRekeyCommand_Run(t *testing.T) { t.Parallel() cases := []struct { @@ -75,7 +75,7 @@ func TestRekeyCommand_Run(t *testing.T) { client, closer := testVaultServer(t) defer closer() - ui, cmd := testRekeyCommand(t) + ui, cmd := testOperatorRekeyCommand(t) cmd.client = client code := cmd.Run(tc.args) @@ -97,7 +97,7 @@ func TestRekeyCommand_Run(t *testing.T) { client, closer := testVaultServer(t) defer closer() - ui, cmd := testRekeyCommand(t) + ui, cmd := testOperatorRekeyCommand(t) cmd.client = client // Verify the non-init response @@ -123,7 +123,7 @@ func TestRekeyCommand_Run(t *testing.T) { } // Verify the init response - ui, cmd = testRekeyCommand(t) + ui, cmd = testOperatorRekeyCommand(t) cmd.client = client code = cmd.Run([]string{ "-status", @@ -153,7 +153,7 @@ func TestRekeyCommand_Run(t *testing.T) { t.Fatal(err) } - ui, cmd := testRekeyCommand(t) + ui, cmd := testOperatorRekeyCommand(t) cmd.client = client code := cmd.Run([]string{ @@ -185,7 +185,7 @@ func TestRekeyCommand_Run(t *testing.T) { client, closer := testVaultServer(t) defer closer() - ui, cmd := testRekeyCommand(t) + ui, cmd := testOperatorRekeyCommand(t) cmd.client = client code := cmd.Run([]string{ @@ -221,7 +221,7 @@ func TestRekeyCommand_Run(t *testing.T) { client, closer := testVaultServer(t) defer closer() - ui, cmd := testRekeyCommand(t) + ui, cmd := testOperatorRekeyCommand(t) cmd.client = client code := cmd.Run([]string{ @@ -270,7 +270,7 @@ func TestRekeyCommand_Run(t *testing.T) { // Supply the first n-1 unseal keys for _, key := range keys[:len(keys)-1] { - ui, cmd := testRekeyCommand(t) + ui, cmd := testOperatorRekeyCommand(t) cmd.client = client 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 code := cmd.Run([]string{ @@ -338,7 +338,7 @@ func TestRekeyCommand_Run(t *testing.T) { stdinW.Close() }() - ui, cmd := testRekeyCommand(t) + ui, cmd := testOperatorRekeyCommand(t) cmd.client = client cmd.testStdin = stdinR @@ -357,7 +357,7 @@ func TestRekeyCommand_Run(t *testing.T) { stdinW.Close() }() - ui, cmd := testRekeyCommand(t) + ui, cmd := testOperatorRekeyCommand(t) cmd.client = client cmd.testStdin = stdinR @@ -399,7 +399,7 @@ func TestRekeyCommand_Run(t *testing.T) { client, keys, closer := testVaultServerUnseal(t) defer closer() - ui, cmd := testRekeyCommand(t) + ui, cmd := testOperatorRekeyCommand(t) cmd.client = client code := cmd.Run([]string{ @@ -423,7 +423,7 @@ func TestRekeyCommand_Run(t *testing.T) { var combined string // Supply the unseal keys for _, key := range keys { - ui, cmd := testRekeyCommand(t) + ui, cmd := testOperatorRekeyCommand(t) cmd.client = client code := cmd.Run([]string{ @@ -448,7 +448,7 @@ func TestRekeyCommand_Run(t *testing.T) { fingerprint, encryptedKey := match[0][1], match[0][2] // Get the backup - ui, cmd = testRekeyCommand(t) + ui, cmd = testOperatorRekeyCommand(t) cmd.client = client code = cmd.Run([]string{ @@ -467,7 +467,7 @@ func TestRekeyCommand_Run(t *testing.T) { } // Delete the backup - ui, cmd = testRekeyCommand(t) + ui, cmd = testOperatorRekeyCommand(t) cmd.client = client code = cmd.Run([]string{ @@ -489,7 +489,7 @@ func TestRekeyCommand_Run(t *testing.T) { client, closer := testVaultServerBad(t) defer closer() - ui, cmd := testRekeyCommand(t) + ui, cmd := testOperatorRekeyCommand(t) cmd.client = client code := cmd.Run([]string{ @@ -509,7 +509,7 @@ func TestRekeyCommand_Run(t *testing.T) { t.Run("no_tabs", func(t *testing.T) { t.Parallel() - _, cmd := testRekeyCommand(t) + _, cmd := testOperatorRekeyCommand(t) assertNoTabs(t, cmd) }) } diff --git a/command/seal.go b/command/operator_seal.go similarity index 68% rename from command/seal.go rename to command/operator_seal.go index 97f102a58..b5fe3b8eb 100644 --- a/command/seal.go +++ b/command/operator_seal.go @@ -8,20 +8,18 @@ import ( "github.com/posener/complete" ) -// Ensure we are implementing the right interfaces. -var _ cli.Command = (*SealCommand)(nil) -var _ cli.CommandAutocomplete = (*SealCommand)(nil) +var _ cli.Command = (*OperatorSealCommand)(nil) +var _ cli.CommandAutocomplete = (*OperatorSealCommand)(nil) -// SealCommand is a Command that seals the vault. -type SealCommand struct { +type OperatorSealCommand struct { *BaseCommand } -func (c *SealCommand) Synopsis() string { +func (c *OperatorSealCommand) Synopsis() string { return "Seals the Vault server" } -func (c *SealCommand) Help() string { +func (c *OperatorSealCommand) Help() string { helpText := ` Usage: vault seal [options] @@ -37,29 +35,26 @@ Usage: vault seal [options] Seal the Vault server: - $ vault seal - - For a full list of examples and why you might want to seal the Vault, please - see the documentation. + $ vault operator seal ` + c.Flags().Help() return strings.TrimSpace(helpText) } -func (c *SealCommand) Flags() *FlagSets { +func (c *OperatorSealCommand) Flags() *FlagSets { return c.flagSet(FlagSetHTTP) } -func (c *SealCommand) AutocompleteArgs() complete.Predictor { +func (c *OperatorSealCommand) AutocompleteArgs() complete.Predictor { return nil } -func (c *SealCommand) AutocompleteFlags() complete.Flags { +func (c *OperatorSealCommand) AutocompleteFlags() complete.Flags { return c.Flags().Completions() } -func (c *SealCommand) Run(args []string) int { +func (c *OperatorSealCommand) Run(args []string) int { f := c.Flags() if err := f.Parse(args); err != nil { diff --git a/command/seal_test.go b/command/operator_seal_test.go similarity index 86% rename from command/seal_test.go rename to command/operator_seal_test.go index a0cf37332..86722d2e8 100644 --- a/command/seal_test.go +++ b/command/operator_seal_test.go @@ -7,18 +7,18 @@ import ( "github.com/mitchellh/cli" ) -func testSealCommand(tb testing.TB) (*cli.MockUi, *SealCommand) { +func testOperatorSealCommand(tb testing.TB) (*cli.MockUi, *OperatorSealCommand) { tb.Helper() ui := cli.NewMockUi() - return ui, &SealCommand{ + return ui, &OperatorSealCommand{ BaseCommand: &BaseCommand{ UI: ui, }, } } -func TestSealCommand_Run(t *testing.T) { +func TestOperatorSealCommand_Run(t *testing.T) { t.Parallel() cases := []struct { @@ -47,7 +47,7 @@ func TestSealCommand_Run(t *testing.T) { client, closer := testVaultServer(t) defer closer() - ui, cmd := testSealCommand(t) + ui, cmd := testOperatorSealCommand(t) cmd.client = client code := cmd.Run(tc.args) @@ -69,7 +69,7 @@ func TestSealCommand_Run(t *testing.T) { client, closer := testVaultServer(t) defer closer() - ui, cmd := testSealCommand(t) + ui, cmd := testOperatorSealCommand(t) cmd.client = client code := cmd.Run([]string{}) @@ -98,7 +98,7 @@ func TestSealCommand_Run(t *testing.T) { client, closer := testVaultServerBad(t) defer closer() - ui, cmd := testSealCommand(t) + ui, cmd := testOperatorSealCommand(t) cmd.client = client code := cmd.Run([]string{}) @@ -116,7 +116,7 @@ func TestSealCommand_Run(t *testing.T) { t.Run("no_tabs", func(t *testing.T) { t.Parallel() - _, cmd := testSealCommand(t) + _, cmd := testOperatorSealCommand(t) assertNoTabs(t, cmd) }) } diff --git a/command/step_down.go b/command/operator_step_down.go similarity index 63% rename from command/step_down.go rename to command/operator_step_down.go index 6b2f3114f..63208faf0 100644 --- a/command/step_down.go +++ b/command/operator_step_down.go @@ -8,23 +8,20 @@ import ( "github.com/posener/complete" ) -// Ensure we are implementing the right interfaces. -var _ cli.Command = (*StepDownCommand)(nil) -var _ cli.CommandAutocomplete = (*StepDownCommand)(nil) +var _ cli.Command = (*OperatorStepDownCommand)(nil) +var _ cli.CommandAutocomplete = (*OperatorStepDownCommand)(nil) -// StepDownCommand is a Command that tells the Vault server to give up its -// leadership -type StepDownCommand struct { +type OperatorStepDownCommand struct { *BaseCommand } -func (c *StepDownCommand) Synopsis() string { +func (c *OperatorStepDownCommand) Synopsis() string { return "Forces Vault to resign active duty" } -func (c *StepDownCommand) Help() string { +func (c *OperatorStepDownCommand) Help() string { 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. 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: - $ vault step-down - - For a full list of examples, please see the documentation. + $ vault operator step-down ` + c.Flags().Help() return strings.TrimSpace(helpText) } -func (c *StepDownCommand) Flags() *FlagSets { +func (c *OperatorStepDownCommand) Flags() *FlagSets { return c.flagSet(FlagSetHTTP) } -func (c *StepDownCommand) AutocompleteArgs() complete.Predictor { +func (c *OperatorStepDownCommand) AutocompleteArgs() complete.Predictor { return nil } -func (c *StepDownCommand) AutocompleteFlags() complete.Flags { +func (c *OperatorStepDownCommand) AutocompleteFlags() complete.Flags { return c.Flags().Completions() } -func (c *StepDownCommand) Run(args []string) int { +func (c *OperatorStepDownCommand) Run(args []string) int { f := c.Flags() if err := f.Parse(args); err != nil { diff --git a/command/step_down_test.go b/command/operator_step_down_test.go similarity index 82% rename from command/step_down_test.go rename to command/operator_step_down_test.go index 6141e08a8..93117a856 100644 --- a/command/step_down_test.go +++ b/command/operator_step_down_test.go @@ -7,18 +7,18 @@ import ( "github.com/mitchellh/cli" ) -func testStepDownCommand(tb testing.TB) (*cli.MockUi, *StepDownCommand) { +func testOperatorStepDownCommand(tb testing.TB) (*cli.MockUi, *OperatorStepDownCommand) { tb.Helper() ui := cli.NewMockUi() - return ui, &StepDownCommand{ + return ui, &OperatorStepDownCommand{ BaseCommand: &BaseCommand{ UI: ui, }, } } -func TestStepDownCommand_Run(t *testing.T) { +func TestOperatorStepDownCommand_Run(t *testing.T) { t.Parallel() cases := []struct { @@ -53,7 +53,7 @@ func TestStepDownCommand_Run(t *testing.T) { client, closer := testVaultServer(t) defer closer() - ui, cmd := testStepDownCommand(t) + ui, cmd := testOperatorStepDownCommand(t) cmd.client = client code := cmd.Run(tc.args) @@ -75,7 +75,7 @@ func TestStepDownCommand_Run(t *testing.T) { client, closer := testVaultServerBad(t) defer closer() - ui, cmd := testStepDownCommand(t) + ui, cmd := testOperatorStepDownCommand(t) cmd.client = client code := cmd.Run([]string{}) @@ -93,7 +93,7 @@ func TestStepDownCommand_Run(t *testing.T) { t.Run("no_tabs", func(t *testing.T) { t.Parallel() - _, cmd := testStepDownCommand(t) + _, cmd := testOperatorStepDownCommand(t) assertNoTabs(t, cmd) }) } diff --git a/command/unseal.go b/command/operator_unseal.go similarity index 80% rename from command/unseal.go rename to command/operator_unseal.go index 495bf6e6c..86c78005d 100644 --- a/command/unseal.go +++ b/command/operator_unseal.go @@ -12,12 +12,10 @@ import ( "github.com/posener/complete" ) -// Ensure we are implementing the right interfaces. -var _ cli.Command = (*UnsealCommand)(nil) -var _ cli.CommandAutocomplete = (*UnsealCommand)(nil) +var _ cli.Command = (*OperatorUnsealCommand)(nil) +var _ cli.CommandAutocomplete = (*OperatorUnsealCommand)(nil) -// UnsealCommand is a Command that unseals the vault. -type UnsealCommand struct { +type OperatorUnsealCommand struct { *BaseCommand flagReset bool @@ -25,13 +23,13 @@ type UnsealCommand struct { testOutput io.Writer // for tests } -func (c *UnsealCommand) Synopsis() string { +func (c *OperatorUnsealCommand) Synopsis() string { return "Unseals the Vault server" } -func (c *UnsealCommand) Help() string { +func (c *OperatorUnsealCommand) Help() string { 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 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 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: - $ vault unseal + $ vault operator unseal Key (will be hidden): IXyR0OJnSFobekZMMCKCoVEpT7wI6l+USMzE3IcyDyo= - For a full list of examples, please see the documentation. - ` + c.Flags().Help() return strings.TrimSpace(helpText) } -func (c *UnsealCommand) Flags() *FlagSets { +func (c *OperatorUnsealCommand) Flags() *FlagSets { set := c.flagSet(FlagSetHTTP) f := set.NewFlagSet("Command Options") @@ -72,15 +68,15 @@ func (c *UnsealCommand) Flags() *FlagSets { return set } -func (c *UnsealCommand) AutocompleteArgs() complete.Predictor { +func (c *OperatorUnsealCommand) AutocompleteArgs() complete.Predictor { return c.PredictVaultFiles() } -func (c *UnsealCommand) AutocompleteFlags() complete.Flags { +func (c *OperatorUnsealCommand) AutocompleteFlags() complete.Flags { return c.Flags().Completions() } -func (c *UnsealCommand) Run(args []string) int { +func (c *OperatorUnsealCommand) Run(args []string) int { f := c.Flags() if err := f.Parse(args); err != nil { @@ -151,7 +147,7 @@ func (c *UnsealCommand) Run(args []string) int { 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("Key Shares: %d", status.N)) c.UI.Output(fmt.Sprintf("Key Threshold: %d", status.T)) diff --git a/command/unseal_test.go b/command/operator_unseal_test.go similarity index 87% rename from command/unseal_test.go rename to command/operator_unseal_test.go index bc8d2e8d2..9091ae40e 100644 --- a/command/unseal_test.go +++ b/command/operator_unseal_test.go @@ -9,24 +9,24 @@ import ( "github.com/mitchellh/cli" ) -func testUnsealCommand(tb testing.TB) (*cli.MockUi, *UnsealCommand) { +func testOperatorUnsealCommand(tb testing.TB) (*cli.MockUi, *OperatorUnsealCommand) { tb.Helper() ui := cli.NewMockUi() - return ui, &UnsealCommand{ + return ui, &OperatorUnsealCommand{ BaseCommand: &BaseCommand{ UI: ui, }, } } -func TestUnsealCommand_Run(t *testing.T) { +func TestOperatorUnsealCommand_Run(t *testing.T) { t.Parallel() t.Run("error_non_terminal", func(t *testing.T) { t.Parallel() - ui, cmd := testUnsealCommand(t) + ui, cmd := testOperatorUnsealCommand(t) cmd.testOutput = ioutil.Discard code := cmd.Run(nil) @@ -57,7 +57,7 @@ func TestUnsealCommand_Run(t *testing.T) { t.Fatal(err) } - ui, cmd := testUnsealCommand(t) + ui, cmd := testOperatorUnsealCommand(t) cmd.client = client cmd.testOutput = ioutil.Discard @@ -87,7 +87,7 @@ func TestUnsealCommand_Run(t *testing.T) { } for i, key := range keys { - ui, cmd := testUnsealCommand(t) + ui, cmd := testOperatorUnsealCommand(t) cmd.client = client cmd.testOutput = ioutil.Discard @@ -112,7 +112,7 @@ func TestUnsealCommand_Run(t *testing.T) { client, closer := testVaultServerBad(t) defer closer() - ui, cmd := testUnsealCommand(t) + ui, cmd := testOperatorUnsealCommand(t) cmd.client = client code := cmd.Run([]string{ @@ -132,7 +132,7 @@ func TestUnsealCommand_Run(t *testing.T) { t.Run("no_tabs", func(t *testing.T) { t.Parallel() - _, cmd := testUnsealCommand(t) + _, cmd := testOperatorUnsealCommand(t) assertNoTabs(t, cmd) }) } diff --git a/command/rotate.go b/command/rotate.go index eed0bc40e..77bc0602b 100644 --- a/command/rotate.go +++ b/command/rotate.go @@ -8,20 +8,18 @@ import ( "github.com/posener/complete" ) -// Ensure we are implementing the right interfaces. -var _ cli.Command = (*RotateCommand)(nil) -var _ cli.CommandAutocomplete = (*RotateCommand)(nil) +var _ cli.Command = (*OperatorRotateCommand)(nil) +var _ cli.CommandAutocomplete = (*OperatorRotateCommand)(nil) -// RotateCommand is a Command that rotates the encryption key being used -type RotateCommand struct { +type OperatorRotateCommand struct { *BaseCommand } -func (c *RotateCommand) Synopsis() string { +func (c *OperatorRotateCommand) Synopsis() string { return "Rotates the underlying encryption key" } -func (c *RotateCommand) Help() string { +func (c *OperatorRotateCommand) Help() string { helpText := ` Usage: vault rotate [options] @@ -31,8 +29,8 @@ Usage: vault rotate [options] decrypt older data. 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 - storeage backend. + per-cluster (not per-server), since Vault servers in HA mode share the same + storage backend. Rotate Vault's encryption key: @@ -45,19 +43,19 @@ Usage: vault rotate [options] return strings.TrimSpace(helpText) } -func (c *RotateCommand) Flags() *FlagSets { +func (c *OperatorRotateCommand) Flags() *FlagSets { return c.flagSet(FlagSetHTTP) } -func (c *RotateCommand) AutocompleteArgs() complete.Predictor { +func (c *OperatorRotateCommand) AutocompleteArgs() complete.Predictor { return nil } -func (c *RotateCommand) AutocompleteFlags() complete.Flags { +func (c *OperatorRotateCommand) AutocompleteFlags() complete.Flags { return c.Flags().Completions() } -func (c *RotateCommand) Run(args []string) int { +func (c *OperatorRotateCommand) Run(args []string) int { f := c.Flags() if err := f.Parse(args); err != nil { diff --git a/command/rotate_test.go b/command/rotate_test.go index 30790691c..8f9756de0 100644 --- a/command/rotate_test.go +++ b/command/rotate_test.go @@ -7,18 +7,18 @@ import ( "github.com/mitchellh/cli" ) -func testRotateCommand(tb testing.TB) (*cli.MockUi, *RotateCommand) { +func testOperatorRotateCommand(tb testing.TB) (*cli.MockUi, *OperatorRotateCommand) { tb.Helper() ui := cli.NewMockUi() - return ui, &RotateCommand{ + return ui, &OperatorRotateCommand{ BaseCommand: &BaseCommand{ UI: ui, }, } } -func TestRotateCommand_Run(t *testing.T) { +func TestOperatorRotateCommand_Run(t *testing.T) { t.Parallel() cases := []struct { @@ -44,7 +44,7 @@ func TestRotateCommand_Run(t *testing.T) { t.Run(tc.name, func(t *testing.T) { t.Parallel() - ui, cmd := testRotateCommand(t) + ui, cmd := testOperatorRotateCommand(t) code := cmd.Run(tc.args) if code != tc.code { @@ -65,7 +65,7 @@ func TestRotateCommand_Run(t *testing.T) { client, closer := testVaultServer(t) defer closer() - ui, cmd := testRotateCommand(t) + ui, cmd := testOperatorRotateCommand(t) cmd.client = client code := cmd.Run([]string{}) @@ -94,7 +94,7 @@ func TestRotateCommand_Run(t *testing.T) { client, closer := testVaultServerBad(t) defer closer() - ui, cmd := testRotateCommand(t) + ui, cmd := testOperatorRotateCommand(t) cmd.client = client code := cmd.Run([]string{}) @@ -112,7 +112,7 @@ func TestRotateCommand_Run(t *testing.T) { t.Run("no_tabs", func(t *testing.T) { t.Parallel() - _, cmd := testRotateCommand(t) + _, cmd := testOperatorRotateCommand(t) assertNoTabs(t, cmd) }) }