|
|
|
@ -334,6 +334,11 @@ func (m *Internal) KeyringOperation(
|
|
|
|
|
args *structs.KeyringRequest, |
|
|
|
|
reply *structs.KeyringResponses) error { |
|
|
|
|
|
|
|
|
|
// Error aggressively to be clear about LocalOnly behavior
|
|
|
|
|
if args.LocalOnly && args.Operation != structs.KeyringList { |
|
|
|
|
return fmt.Errorf("argument error: LocalOnly can only be used for List operations") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Check ACLs
|
|
|
|
|
identity, rule, err := m.srv.ResolveTokenToIdentityAndAuthorizer(args.Token) |
|
|
|
|
if err != nil { |
|
|
|
@ -361,44 +366,63 @@ func (m *Internal) KeyringOperation(
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Validate use of local-only
|
|
|
|
|
if args.LocalOnly && args.Operation != structs.KeyringList { |
|
|
|
|
// Error aggressively to be clear about LocalOnly behavior
|
|
|
|
|
return fmt.Errorf("argument error: LocalOnly can only be used for List operations") |
|
|
|
|
} |
|
|
|
|
if args.LocalOnly || args.Forwarded || m.srv.serfWAN == nil { |
|
|
|
|
// Handle operations that are localOnly, already forwarded or
|
|
|
|
|
// there is no serfWAN. If any of this is the case this
|
|
|
|
|
// operation shouldn't go out to other dcs or WAN pool.
|
|
|
|
|
reply.Responses = append(reply.Responses, m.executeKeyringOpLAN(args)...) |
|
|
|
|
} else { |
|
|
|
|
// Handle not already forwarded, non-local operations.
|
|
|
|
|
|
|
|
|
|
// Marking this as forwarded because this is what we are about
|
|
|
|
|
// to do. Prevents the same message from being fowarded by
|
|
|
|
|
// other servers.
|
|
|
|
|
args.Forwarded = true |
|
|
|
|
reply.Responses = append(reply.Responses, m.executeKeyringOpWAN(args)) |
|
|
|
|
reply.Responses = append(reply.Responses, m.executeKeyringOpLAN(args)...) |
|
|
|
|
|
|
|
|
|
// args.LocalOnly should always be false for non-GET requests
|
|
|
|
|
if !args.LocalOnly { |
|
|
|
|
// Only perform WAN keyring querying and RPC forwarding once
|
|
|
|
|
if !args.Forwarded && m.srv.serfWAN != nil { |
|
|
|
|
args.Forwarded = true |
|
|
|
|
m.executeKeyringOp(args, reply, true) |
|
|
|
|
return m.srv.globalRPC("Internal.KeyringOperation", args, reply) |
|
|
|
|
dcs := m.srv.router.GetRemoteDatacenters(m.srv.config.Datacenter) |
|
|
|
|
responses, err := m.srv.keyringRPCs("Internal.KeyringOperation", args, dcs) |
|
|
|
|
if err != nil { |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
reply.Add(responses) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Query the LAN keyring of this node's DC
|
|
|
|
|
m.executeKeyringOp(args, reply, false) |
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// executeKeyringOp executes the keyring-related operation in the request
|
|
|
|
|
// on either the WAN or LAN pools.
|
|
|
|
|
func (m *Internal) executeKeyringOp( |
|
|
|
|
args *structs.KeyringRequest, |
|
|
|
|
reply *structs.KeyringResponses, |
|
|
|
|
wan bool) { |
|
|
|
|
func (m *Internal) executeKeyringOpLAN(args *structs.KeyringRequest) []*structs.KeyringResponse { |
|
|
|
|
responses := []*structs.KeyringResponse{} |
|
|
|
|
segments := m.srv.LANSegments() |
|
|
|
|
for name, segment := range segments { |
|
|
|
|
mgr := segment.KeyManager() |
|
|
|
|
serfResp, err := m.executeKeyringOpMgr(mgr, args) |
|
|
|
|
resp := translateKeyResponseToKeyringResponse(serfResp, m.srv.config.Datacenter, err) |
|
|
|
|
resp.Segment = name |
|
|
|
|
responses = append(responses, &resp) |
|
|
|
|
} |
|
|
|
|
return responses |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if wan { |
|
|
|
|
mgr := m.srv.KeyManagerWAN() |
|
|
|
|
m.executeKeyringOpMgr(mgr, args, reply, wan, "") |
|
|
|
|
} else { |
|
|
|
|
segments := m.srv.LANSegments() |
|
|
|
|
for name, segment := range segments { |
|
|
|
|
mgr := segment.KeyManager() |
|
|
|
|
m.executeKeyringOpMgr(mgr, args, reply, wan, name) |
|
|
|
|
} |
|
|
|
|
func (m *Internal) executeKeyringOpWAN(args *structs.KeyringRequest) *structs.KeyringResponse { |
|
|
|
|
mgr := m.srv.KeyManagerWAN() |
|
|
|
|
serfResp, err := m.executeKeyringOpMgr(mgr, args) |
|
|
|
|
resp := translateKeyResponseToKeyringResponse(serfResp, m.srv.config.Datacenter, err) |
|
|
|
|
resp.WAN = true |
|
|
|
|
return &resp |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func translateKeyResponseToKeyringResponse(keyresponse *serf.KeyResponse, datacenter string, err error) structs.KeyringResponse { |
|
|
|
|
resp := structs.KeyringResponse{ |
|
|
|
|
Datacenter: datacenter, |
|
|
|
|
Messages: keyresponse.Messages, |
|
|
|
|
Keys: keyresponse.Keys, |
|
|
|
|
NumNodes: keyresponse.NumNodes, |
|
|
|
|
} |
|
|
|
|
if err != nil { |
|
|
|
|
resp.Error = err.Error() |
|
|
|
|
} |
|
|
|
|
return resp |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// executeKeyringOpMgr executes the appropriate keyring-related function based on
|
|
|
|
@ -407,9 +431,7 @@ func (m *Internal) executeKeyringOp(
|
|
|
|
|
func (m *Internal) executeKeyringOpMgr( |
|
|
|
|
mgr *serf.KeyManager, |
|
|
|
|
args *structs.KeyringRequest, |
|
|
|
|
reply *structs.KeyringResponses, |
|
|
|
|
wan bool, |
|
|
|
|
segment string) { |
|
|
|
|
) (*serf.KeyResponse, error) { |
|
|
|
|
var serfResp *serf.KeyResponse |
|
|
|
|
var err error |
|
|
|
|
|
|
|
|
@ -425,20 +447,7 @@ func (m *Internal) executeKeyringOpMgr(
|
|
|
|
|
serfResp, err = mgr.RemoveKeyWithOptions(args.Key, opts) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
errStr := "" |
|
|
|
|
if err != nil { |
|
|
|
|
errStr = err.Error() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
reply.Responses = append(reply.Responses, &structs.KeyringResponse{ |
|
|
|
|
WAN: wan, |
|
|
|
|
Datacenter: m.srv.config.Datacenter, |
|
|
|
|
Segment: segment, |
|
|
|
|
Messages: serfResp.Messages, |
|
|
|
|
Keys: serfResp.Keys, |
|
|
|
|
NumNodes: serfResp.NumNodes, |
|
|
|
|
Error: errStr, |
|
|
|
|
}) |
|
|
|
|
return serfResp, err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// aclAccessorID is used to convert an ACLToken's secretID to its accessorID for non-
|
|
|
|
|