diff --git a/command/agent/keyring.go b/command/agent/keyring.go index 827aa76bc..f6d80a9dc 100644 --- a/command/agent/keyring.go +++ b/command/agent/keyring.go @@ -84,26 +84,30 @@ func (a *Agent) keyringProcess( func (a *Agent) ListKeys() (*structs.KeyringResponses, error) { args := structs.KeyringRequest{} args.AllowStale = true - return a.keyringProcess("Internal.ListKeys", &args) + args.Operation = structs.KeyringList + return a.keyringProcess("Internal.KeyringOperation", &args) } // InstallKey installs a new gossip encryption key func (a *Agent) InstallKey(key string) (*structs.KeyringResponses, error) { args := structs.KeyringRequest{Key: key} args.AllowStale = true - return a.keyringProcess("Internal.InstallKey", &args) + args.Operation = structs.KeyringInstall + return a.keyringProcess("Internal.KeyringOperation", &args) } // UseKey changes the primary encryption key used to encrypt messages func (a *Agent) UseKey(key string) (*structs.KeyringResponses, error) { args := structs.KeyringRequest{Key: key} args.AllowStale = true - return a.keyringProcess("Internal.UseKey", &args) + args.Operation = structs.KeyringUse + return a.keyringProcess("Internal.KeyringOperation", &args) } // RemoveKey will remove a gossip encryption key from the keyring func (a *Agent) RemoveKey(key string) (*structs.KeyringResponses, error) { args := structs.KeyringRequest{Key: key} args.AllowStale = true - return a.keyringProcess("Internal.RemoveKey", &args) + args.Operation = structs.KeyringRemove + return a.keyringProcess("Internal.KeyringOperation", &args) } diff --git a/consul/internal_endpoint.go b/consul/internal_endpoint.go index 223b8eeff..f9bed288c 100644 --- a/consul/internal_endpoint.go +++ b/consul/internal_endpoint.go @@ -12,6 +12,15 @@ type Internal struct { srv *Server } +type KeyringOperation uint8 + +const ( + listKeysOperation KeyringOperation = iota + installKeyOperation + useKeyOperation + removeKeyOperation +) + // ChecksInState is used to get all the checks in a given state func (m *Internal) NodeInfo(args *structs.NodeSpecificRequest, reply *structs.IndexedNodeDump) error { @@ -66,85 +75,42 @@ func (m *Internal) EventFire(args *structs.EventFireRequest, // ListKeys will query the WAN and LAN gossip keyrings of all nodes, adding // results into a collective response as we go. -func (m *Internal) ListKeys( +func (m *Internal) KeyringOperation( args *structs.KeyringRequest, reply *structs.KeyringResponses) error { dc := m.srv.config.Datacenter - respLAN, err := m.srv.KeyManagerLAN().ListKeys() + + respLAN, err := m.doKeyringOperation(args, m.srv.KeyManagerLAN()) ingestKeyringResponse(respLAN, reply, dc, false, err) if !args.Forwarded { - respWAN, err := m.srv.KeyManagerWAN().ListKeys() + respWAN, err := m.doKeyringOperation(args, m.srv.KeyManagerWAN()) ingestKeyringResponse(respWAN, reply, dc, true, err) args.Forwarded = true - m.srv.globalRPC("Internal.ListKeys", args, reply) + return m.srv.globalRPC("Internal.KeyringOperation", args, reply) } return nil } -// InstallKey broadcasts a new encryption key to all nodes. This involves -// installing a new key on every node across all datacenters. -func (m *Internal) InstallKey( +func (m *Internal) doKeyringOperation( args *structs.KeyringRequest, - reply *structs.KeyringResponses) error { + mgr *serf.KeyManager) (r *serf.KeyResponse, err error) { - dc := m.srv.config.Datacenter - respLAN, err := m.srv.KeyManagerLAN().InstallKey(args.Key) - ingestKeyringResponse(respLAN, reply, dc, false, err) - - if !args.Forwarded { - respWAN, err := m.srv.KeyManagerWAN().InstallKey(args.Key) - ingestKeyringResponse(respWAN, reply, dc, true, err) - - args.Forwarded = true - m.srv.globalRPC("Internal.InstallKey", args, reply) + switch args.Operation { + case structs.KeyringList: + r, err = mgr.ListKeys() + case structs.KeyringInstall: + r, err = mgr.InstallKey(args.Key) + case structs.KeyringUse: + r, err = mgr.UseKey(args.Key) + case structs.KeyringRemove: + r, err = mgr.RemoveKey(args.Key) } - return nil -} - -// UseKey instructs all nodes to change the key they are using to -// encrypt gossip messages. -func (m *Internal) UseKey( - args *structs.KeyringRequest, - reply *structs.KeyringResponses) error { - - dc := m.srv.config.Datacenter - respLAN, err := m.srv.KeyManagerLAN().UseKey(args.Key) - ingestKeyringResponse(respLAN, reply, dc, false, err) - - if !args.Forwarded { - respWAN, err := m.srv.KeyManagerWAN().UseKey(args.Key) - ingestKeyringResponse(respWAN, reply, dc, true, err) - - args.Forwarded = true - m.srv.globalRPC("Internal.UseKey", args, reply) - } - - return nil -} - -// RemoveKey instructs all nodes to drop the specified key from the keyring. -func (m *Internal) RemoveKey( - args *structs.KeyringRequest, - reply *structs.KeyringResponses) error { - - dc := m.srv.config.Datacenter - respLAN, err := m.srv.KeyManagerLAN().RemoveKey(args.Key) - ingestKeyringResponse(respLAN, reply, dc, false, err) - - if !args.Forwarded { - respWAN, err := m.srv.KeyManagerWAN().RemoveKey(args.Key) - ingestKeyringResponse(respWAN, reply, dc, true, err) - - args.Forwarded = true - m.srv.globalRPC("Internal.RemoveKey", args, reply) - } - - return nil + return r, err } // ingestKeyringResponse is a helper method to pick the relative information diff --git a/consul/structs/structs.go b/consul/structs/structs.go index 1b3ead960..d655adf79 100644 --- a/consul/structs/structs.go +++ b/consul/structs/structs.go @@ -554,9 +554,19 @@ type CompoundResponse interface { New() interface{} } +type KeyringOp string + +const ( + KeyringList KeyringOp = "list" + KeyringInstall = "install" + KeyringUse = "use" + KeyringRemove = "remove" +) + // KeyringRequest encapsulates a request to modify an encryption keyring. // It can be used for install, remove, or use key type operations. type KeyringRequest struct { + Operation KeyringOp Key string Datacenter string Forwarded bool