command: allow wan ring to be modified separately from lan pools

This commit is contained in:
Ryan Uber 2014-09-21 11:52:28 -07:00
parent 72fc1ceead
commit 03012e8ac6
4 changed files with 103 additions and 56 deletions

View File

@ -1,17 +1,12 @@
package agent
import (
<<<<<<< HEAD
"fmt"
"io/ioutil"
"log"
"os"
=======
"github.com/hashicorp/consul/testutil"
"github.com/mitchellh/cli"
"io/ioutil"
"path/filepath"
>>>>>>> command: test generated keyring file content and conflicting args for agent
"strings"
"testing"
"github.com/hashicorp/consul/testutil"
@ -45,7 +40,6 @@ func TestValidDatacenter(t *testing.T) {
}
}
<<<<<<< HEAD
func TestRetryJoin(t *testing.T) {
dir, agent := makeAgent(t, nextConfig())
defer os.RemoveAll(dir)
@ -169,7 +163,9 @@ func TestRetryJoinWanFail(t *testing.T) {
if code := cmd.Run(args); code == 0 {
t.Fatalf("bad: %d", code)
=======
}
}
func TestArgConflict(t *testing.T) {
ui := new(cli.MockUi)
c := &Command{Ui: ui}
@ -196,6 +192,5 @@ func TestArgConflict(t *testing.T) {
}
if !strings.Contains(ui.ErrorWriter.String(), "keyring files exist") {
t.Fatalf("bad: %#v", ui.ErrorWriter.String())
>>>>>>> command: test generated keyring file content and conflicting args for agent
}
}

View File

@ -22,7 +22,7 @@ type KeyringCommand struct {
func (c *KeyringCommand) Run(args []string) int {
var installKey, useKey, removeKey, init, dataDir string
var listKeys bool
var listKeys, wan bool
cmdFlags := flag.NewFlagSet("keys", flag.ContinueOnError)
cmdFlags.Usage = func() { c.Ui.Output(c.Help()) }
@ -33,6 +33,7 @@ func (c *KeyringCommand) Run(args []string) int {
cmdFlags.BoolVar(&listKeys, "list", false, "list keys")
cmdFlags.StringVar(&init, "init", "", "initialize keyring")
cmdFlags.StringVar(&dataDir, "data-dir", "", "data directory")
cmdFlags.BoolVar(&wan, "wan", false, "operate on wan keyring")
rpcAddr := RPCAddrFlag(cmdFlags)
if err := cmdFlags.Parse(args); err != nil {
@ -105,51 +106,57 @@ func (c *KeyringCommand) Run(args []string) int {
}
if listKeys {
c.Ui.Info("Asking all WAN members for installed keys...")
if rval := c.listKeysOperation(client.ListKeysWAN); rval != 0 {
return rval
if wan {
c.Ui.Info("Asking all WAN members for installed keys...")
return c.listKeysOperation(client.ListKeysWAN)
}
c.Ui.Info("Asking all LAN members for installed keys...")
if rval := c.listKeysOperation(client.ListKeysLAN); rval != 0 {
return rval
}
return 0
return c.listKeysOperation(client.ListKeysLAN)
}
if installKey != "" {
c.Ui.Info("Installing new WAN gossip encryption key...")
if rval := c.keyOperation(installKey, client.InstallKeyWAN); rval != 0 {
return rval
}
c.Ui.Info("Installing new LAN gossip encryption key...")
if rval := c.keyOperation(installKey, client.InstallKeyLAN); rval != 0 {
return rval
if wan {
c.Ui.Info("Installing new WAN gossip encryption key...")
if rval := c.keyOperation(installKey, client.InstallKeyWAN); rval != 0 {
return rval
}
} else {
c.Ui.Info("Installing new LAN gossip encryption key...")
if rval := c.keyOperation(installKey, client.InstallKeyLAN); rval != 0 {
return rval
}
}
c.Ui.Info("Successfully installed key!")
return 0
}
if useKey != "" {
c.Ui.Info("Changing primary WAN gossip encryption key...")
if rval := c.keyOperation(useKey, client.UseKeyWAN); rval != 0 {
return rval
}
c.Ui.Info("Changing primary LAN gossip encryption key...")
if rval := c.keyOperation(useKey, client.UseKeyLAN); rval != 0 {
return rval
if wan {
c.Ui.Info("Changing primary WAN gossip encryption key...")
if rval := c.keyOperation(useKey, client.UseKeyWAN); rval != 0 {
return rval
}
} else {
c.Ui.Info("Changing primary LAN gossip encryption key...")
if rval := c.keyOperation(useKey, client.UseKeyLAN); rval != 0 {
return rval
}
}
c.Ui.Info("Successfully changed primary key!")
return 0
}
if removeKey != "" {
c.Ui.Info("Removing WAN gossip encryption key...")
if rval := c.keyOperation(removeKey, client.RemoveKeyWAN); rval != 0 {
return rval
}
c.Ui.Info("Removing LAN gossip encryption key...")
if rval := c.keyOperation(removeKey, client.RemoveKeyLAN); rval != 0 {
return rval
if wan {
c.Ui.Info("Removing WAN gossip encryption key...")
if rval := c.keyOperation(removeKey, client.RemoveKeyWAN); rval != 0 {
return rval
}
} else {
c.Ui.Info("Removing LAN gossip encryption key...")
if rval := c.keyOperation(removeKey, client.RemoveKeyLAN); rval != 0 {
return rval
}
}
c.Ui.Info("Successfully removed key!")
return 0
@ -258,8 +265,9 @@ Usage: consul keyring [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.
With the exception of the -init argument, all operations performed by this
command can only be run against server nodes. All operations default to the
LAN gossip pool.
Options:
@ -275,6 +283,8 @@ Options:
-init=<key> Create the initial keyring files for Consul to use
containing the provided key. The -data-dir argument
is required with this option.
-wan Operate on the WAN keyring instead of the LAN
keyring (default).
-rpc-addr=127.0.0.1:8400 RPC address of the Consul agent.
`
return strings.TrimSpace(helpText)

View File

@ -25,7 +25,7 @@ func TestKeyringCommandRun(t *testing.T) {
defer a1.Shutdown()
// The keyring was initialized with only the provided key
out := listKeys(t, a1.addr)
out := listKeys(t, a1.addr, false)
if !strings.Contains(out, key1) {
t.Fatalf("bad: %#v", out)
}
@ -34,30 +34,56 @@ func TestKeyringCommandRun(t *testing.T) {
}
// Install the second key onto the keyring
installKey(t, a1.addr, key2)
installKey(t, a1.addr, key2, false)
// Both keys should be present
out = listKeys(t, a1.addr)
out = listKeys(t, a1.addr, false)
for _, key := range []string{key1, key2} {
if !strings.Contains(out, key) {
t.Fatalf("bad: %#v", out)
}
}
// WAN keyring is untouched
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, key2)
useKey(t, a1.addr, key2, false)
// Remove the original key
removeKey(t, a1.addr, key1)
removeKey(t, a1.addr, key1, false)
// Make sure only the new key is present
out = listKeys(t, a1.addr)
out = listKeys(t, a1.addr, false)
if strings.Contains(out, key1) {
t.Fatalf("bad: %#v", out)
}
if !strings.Contains(out, key2) {
t.Fatalf("bad: %#v", out)
}
// WAN keyring is still untouched
out = listKeys(t, a1.addr, true)
if !strings.Contains(out, key1) {
t.Fatalf("bad: %#v", out)
}
// Rotate out the WAN key
installKey(t, a1.addr, key2, true)
useKey(t, a1.addr, key2, true)
removeKey(t, a1.addr, key1, true)
// WAN keyring now has only the proper key
out = listKeys(t, a1.addr, true)
if !strings.Contains(out, key2) {
t.Fatalf("bad: %#v", out)
}
if strings.Contains(out, key1) {
t.Fatalf("bad: %#v", out)
}
}
func TestKeyringCommandRun_help(t *testing.T) {
@ -87,7 +113,7 @@ func TestKeyringCommandRun_failedConnection(t *testing.T) {
}
}
func TestKeyCommandRun_initKeyringFail(t *testing.T) {
func TestKeyringCommandRun_initKeyringFail(t *testing.T) {
ui := new(cli.MockUi)
c := &KeyringCommand{Ui: ui}
@ -106,7 +132,7 @@ func TestKeyCommandRun_initKeyringFail(t *testing.T) {
}
}
func TestKeyCommandRun_initKeyring(t *testing.T) {
func TestKeyringCommandRun_initKeyring(t *testing.T) {
ui := new(cli.MockUi)
c := &KeyringCommand{Ui: ui}
@ -153,11 +179,14 @@ func TestKeyCommandRun_initKeyring(t *testing.T) {
}
}
func listKeys(t *testing.T, addr string) string {
func listKeys(t *testing.T, addr string, wan bool) string {
ui := new(cli.MockUi)
c := &KeyringCommand{Ui: ui}
args := []string{"-list", "-rpc-addr=" + addr}
if wan {
args = append(args, "-wan")
}
code := c.Run(args)
if code != 0 {
@ -167,33 +196,45 @@ func listKeys(t *testing.T, addr string) string {
return ui.OutputWriter.String()
}
func installKey(t *testing.T, addr string, key string) {
func installKey(t *testing.T, addr string, key string, wan bool) {
ui := new(cli.MockUi)
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, key string) {
func useKey(t *testing.T, addr string, key string, wan bool) {
ui := new(cli.MockUi)
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, key string) {
func removeKey(t *testing.T, addr string, key string, wan bool) {
ui := new(cli.MockUi)
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

@ -14,10 +14,9 @@ distributing new encryption keys to the cluster, retiring old encryption keys,
and changing the keys used by the cluster to encrypt messages.
Because Consul utilizes multiple gossip pools, this command will only operate
against a server node for most operations. All members in a Consul cluster,
regardless of operational mode (client or server) or datacenter, will be
modified/queried each time this command is run. This helps maintain operational
simplicity by managing the multiple pools as a single unit.
against a server node for most operations. By default, all operations carried
out by this command are run against the LAN gossip pool in the datacenter of the
agent.
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
@ -60,4 +59,6 @@ The list of available flags are:
* `-list` - List all keys currently in use within the cluster.
* `-wan` - Operate on the WAN keyring instead of the LAN keyring (default)
* `-rpc-addr` - RPC address of the Consul agent.