command: renamed keys to keyring to disambiguate usage

This commit is contained in:
Ryan Uber 2014-09-12 20:08:54 -07:00
parent 530f3ba747
commit 67d78628a3
5 changed files with 63 additions and 123 deletions

View File

@ -14,13 +14,13 @@ import (
"github.com/ryanuber/columnize"
)
// KeysCommand is a Command implementation that handles querying, installing,
// KeyringCommand is a Command implementation that handles querying, installing,
// and removing gossip encryption keys from a keyring.
type KeysCommand struct {
type KeyringCommand struct {
Ui cli.Ui
}
func (c *KeysCommand) Run(args []string) int {
func (c *KeyringCommand) Run(args []string) int {
var installKey, useKey, removeKey, init, dataDir string
var listKeys bool
@ -150,9 +150,12 @@ func (c *KeysCommand) Run(args []string) int {
return 0
}
// keyFunc is a function which manipulates gossip encryption keyrings. This is
// used for key installation, removal, and primary key changes.
type keyFunc func(string) (map[string]string, error)
func (c *KeysCommand) keyOperation(key string, fn keyFunc) int {
// keyOperation is a unified process for manipulating the gossip keyrings.
func (c *KeyringCommand) keyOperation(key string, fn keyFunc) int {
var out []string
failures, err := fn(key)
@ -172,9 +175,12 @@ func (c *KeysCommand) keyOperation(key string, fn keyFunc) int {
return 0
}
// listKeysFunc is a function which handles querying lists of gossip keys
type listKeysFunc func() (map[string]int, int, map[string]string, error)
func (c *KeysCommand) listKeysOperation(fn listKeysFunc) int {
// listKeysOperation is a unified process for querying and
// displaying gossip keys.
func (c *KeyringCommand) listKeysOperation(fn listKeysFunc) int {
var out []string
keys, numNodes, failures, err := fn()
@ -233,9 +239,9 @@ func initializeKeyring(path, key string) error {
return nil
}
func (c *KeysCommand) Help() string {
func (c *KeyringCommand) Help() string {
helpText := `
Usage: consul keys [options]
Usage: consul keyring [options]
Manages encryption keys used for gossip messages. Gossip encryption is
optional. When enabled, this command may be used to examine active encryption
@ -243,6 +249,9 @@ Usage: consul keys [options]
functionality provides the ability to perform key rotation cluster-wide,
without disrupting the cluster.
With the exception of the -init argument, all other operations performed by
this command can only be run against server nodes.
Options:
-install=<key> Install a new encryption key. This will broadcast
@ -254,19 +263,14 @@ Options:
operation may only be performed on keys which are
not currently the primary key.
-list List all keys currently in use within the cluster.
-wan If talking with a server node, this flag can be used
to operate on the WAN gossip layer.
-init=<key> Create an initial keyring file for Consul to use
containing the provided key. By default, this option
will only initialize the LAN keyring. If the -wan
option is also passed, then the wan keyring will be
created as well. The -data-dir argument is required
with this option.
containing the provided key. The -data-dir argument
is required with this option.
-rpc-addr=127.0.0.1:8400 RPC address of the Consul agent.
`
return strings.TrimSpace(helpText)
}
func (c *KeysCommand) Synopsis() string {
func (c *KeyringCommand) Synopsis() string {
return "Manages gossip layer encryption keys"
}

View File

@ -8,14 +8,13 @@ import (
"github.com/mitchellh/cli"
)
func TestKeysCommand_implements(t *testing.T) {
var _ cli.Command = &KeysCommand{}
func TestKeyringCommand_implements(t *testing.T) {
var _ cli.Command = &KeyringCommand{}
}
func TestKeysCommandRun(t *testing.T) {
func TestKeyringCommandRun(t *testing.T) {
key1 := "HS5lJ+XuTlYKWaeGYyG+/A=="
key2 := "kZyFABeAmc64UMTrm9XuKA=="
key3 := "2k5VRlBIIKUPc1v77rsswg=="
// Begin with a single key
conf := agent.Config{EncryptKey: key1}
@ -23,7 +22,7 @@ func TestKeysCommandRun(t *testing.T) {
defer a1.Shutdown()
// The keyring was initialized with only the provided key
out := listKeys(t, a1.addr, false)
out := listKeys(t, a1.addr)
if !strings.Contains(out, key1) {
t.Fatalf("bad: %#v", out)
}
@ -31,83 +30,36 @@ func TestKeysCommandRun(t *testing.T) {
t.Fatalf("bad: %#v", out)
}
// The key was installed on the WAN gossip layer also
out = listKeys(t, a1.addr, true)
if !strings.Contains(out, key1) {
t.Fatalf("bad: %#v", out)
}
if strings.Contains(out, key3) {
t.Fatalf("bad: %#v", out)
}
// Install the second key onto the keyring
installKey(t, a1.addr, false, key2)
installKey(t, a1.addr, key2)
// Both keys should be present
out = listKeys(t, a1.addr, false)
out = listKeys(t, a1.addr)
for _, key := range []string{key1, key2} {
if !strings.Contains(out, key) {
t.Fatalf("bad: %#v", out)
}
}
// Second key should not be installed on WAN
out = listKeys(t, a1.addr, true)
if strings.Contains(out, key2) {
t.Fatalf("bad: %#v", out)
}
// Change out the primary key
useKey(t, a1.addr, false, key2)
useKey(t, a1.addr, key2)
// Remove the original key
removeKey(t, a1.addr, false, key1)
removeKey(t, a1.addr, key1)
// Make sure only the new key is present
out = listKeys(t, a1.addr, false)
out = listKeys(t, a1.addr)
if strings.Contains(out, key1) {
t.Fatalf("bad: %#v", out)
}
if !strings.Contains(out, key2) {
t.Fatalf("bad: %#v", out)
}
// Original key still remains on WAN keyring
out = listKeys(t, a1.addr, true)
if !strings.Contains(out, key1) {
t.Fatalf("bad: %#v", out)
}
// Install second key on WAN keyring
installKey(t, a1.addr, true, key3)
// Two keys now present on WAN keyring
out = listKeys(t, a1.addr, true)
for _, key := range []string{key1, key3} {
if !strings.Contains(out, key) {
t.Fatalf("bad: %#v", out)
}
}
// Change WAN primary key
useKey(t, a1.addr, true, key3)
// Remove original key from WAN keyring
removeKey(t, a1.addr, true, key1)
// Only new key should exist on WAN keyring
out = listKeys(t, a1.addr, true)
if !strings.Contains(out, key3) {
t.Fatalf("bad: %#v", out)
}
if strings.Contains(out, key1) {
t.Fatalf("bad: %#v", out)
}
}
func TestKeysCommandRun_help(t *testing.T) {
func TestKeyringCommandRun_help(t *testing.T) {
ui := new(cli.MockUi)
c := &KeysCommand{Ui: ui}
c := &KeyringCommand{Ui: ui}
code := c.Run(nil)
if code != 1 {
t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
@ -119,9 +71,9 @@ func TestKeysCommandRun_help(t *testing.T) {
}
}
func TestKeysCommandRun_failedConnection(t *testing.T) {
func TestKeyringCommandRun_failedConnection(t *testing.T) {
ui := new(cli.MockUi)
c := &KeysCommand{Ui: ui}
c := &KeyringCommand{Ui: ui}
args := []string{"-list", "-rpc-addr=127.0.0.1:0"}
code := c.Run(args)
if code != 1 {
@ -132,14 +84,11 @@ func TestKeysCommandRun_failedConnection(t *testing.T) {
}
}
func listKeys(t *testing.T, addr string, wan bool) string {
func listKeys(t *testing.T, addr string) string {
ui := new(cli.MockUi)
c := &KeysCommand{Ui: ui}
c := &KeyringCommand{Ui: ui}
args := []string{"-list", "-rpc-addr=" + addr}
if wan {
args = append(args, "-wan")
}
code := c.Run(args)
if code != 0 {
@ -149,45 +98,33 @@ func listKeys(t *testing.T, addr string, wan bool) string {
return ui.OutputWriter.String()
}
func installKey(t *testing.T, addr string, wan bool, key string) {
func installKey(t *testing.T, addr string, key string) {
ui := new(cli.MockUi)
c := &KeysCommand{Ui: ui}
c := &KeyringCommand{Ui: ui}
args := []string{"-install=" + key, "-rpc-addr=" + addr}
if wan {
args = append(args, "-wan")
}
code := c.Run(args)
if code != 0 {
t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
}
}
func useKey(t *testing.T, addr string, wan bool, key string) {
func useKey(t *testing.T, addr string, key string) {
ui := new(cli.MockUi)
c := &KeysCommand{Ui: ui}
c := &KeyringCommand{Ui: ui}
args := []string{"-use=" + key, "-rpc-addr=" + addr}
if wan {
args = append(args, "-wan")
}
code := c.Run(args)
if code != 0 {
t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
}
}
func removeKey(t *testing.T, addr string, wan bool, key string) {
func removeKey(t *testing.T, addr string, key string) {
ui := new(cli.MockUi)
c := &KeysCommand{Ui: ui}
c := &KeyringCommand{Ui: ui}
args := []string{"-remove=" + key, "-rpc-addr=" + addr}
if wan {
args = append(args, "-wan")
}
code := c.Run(args)
if code != 0 {
t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())

View File

@ -56,8 +56,8 @@ func init() {
}, nil
},
"keys": func() (cli.Command, error) {
return &command.KeysCommand{
"keyring": func() (cli.Command, error) {
return &command.KeyringCommand{
Ui: ui,
}, nil
},

View File

@ -1,21 +1,21 @@
---
layout: "docs"
page_title: "Commands: Keys"
sidebar_current: "docs-commands-keys"
page_title: "Commands: Keyring"
sidebar_current: "docs-commands-keyring"
---
# Consul Keys
# Consul Keyring
Command: `consul keys`
Command: `consul keyring`
The `keys` command is used to examine and modify the encryption keys used in
The `keyring` command is used to examine and modify the encryption keys used in
Consul's [Gossip Pools](/docs/internals/gossip.html). It is capable of
distributing new encryption keys to the cluster, revoking old encryption keys,
and changing the key used by the cluster to encrypt messages.
Because Consul utilizes multiple gossip pools, this command will operate on only
a single pool at a time. The pool can be specified using the arguments
documented below.
Because Consul utilizes multiple gossip pools, this command will only operate
against a server node for most operations. The only operation which may be used
on client machines is the `-init` argument for initial key configuration.
Consul allows multiple encryption keys to be in use simultaneously. This is
intended to provide a transition state while the cluster converges. It is the
@ -23,23 +23,27 @@ responsibility of the operator to ensure that only the required encryption keys
are installed on the cluster. You can ensure that a key is not installed using
the `-list` and `-remove` options.
By default, modifications made using this command will **NOT** be persisted, and
will be lost when the agent shuts down. You can alter this behavior via the
`-persist-keyring` option in the
[Agent Configuration](/docs/agent/options.html).
All variations of the keys command will return 0 if all nodes reply and there
are no errors. If any node fails to reply or reports failure, the exit code will
be 1.
## Usage
Usage: `consul keys [options]`
Usage: `consul keyring [options]`
Exactly one of `-list`, `-install`, `-remove`, or `-update` must be provided.
Only one actionable argument may be specified per run, including `-init`,
`-list`, `-install`, `-remove`, and `-update`.
The list of available flags are:
* `-init` - Creates the keyring file(s). This is useful to configure initial
encryption keyrings, which can later be mutated using the other arguments in
this command. This argument accepts an ASCII key, which can be generated using
the [keygen command](/docs/commands/keygen.html).
This operation can be run on both client and server nodes and requires no
network connectivity.
* `-install` - Install a new encryption key. This will broadcast the new key to
all members in the cluster.
@ -51,9 +55,4 @@ The list of available flags are:
* `-list` - List all keys currently in use within the cluster.
* `-wan` - If talking with a server node, this flag can be used to operate on
the WAN gossip layer. By default, this command operates on the LAN layer. More
information about the different gossip layers can be found on the
[gossip protocol](/docs/internals/gossip.html) page.
* `-rpc-addr` - RPC address of the Consul agent.

View File

@ -79,8 +79,8 @@
<a href="/docs/commands/keygen.html">keygen</a>
</li>
<li<%= sidebar_current("docs-commands-keys") %>>
<a href="/docs/commands/keys.html">keys</a>
<li<%= sidebar_current("docs-commands-keyring") %>>
<a href="/docs/commands/keyring.html">keyring</a>
</li>
<li<%= sidebar_current("docs-commands-leave") %>>