github.phpd.cn/hashicorp/consul@v1.4.5/agent/consul/internal_endpoint.go (about) 1 package consul 2 3 import ( 4 "fmt" 5 6 "github.com/hashicorp/consul/acl" 7 "github.com/hashicorp/consul/agent/consul/state" 8 "github.com/hashicorp/consul/agent/structs" 9 "github.com/hashicorp/go-memdb" 10 "github.com/hashicorp/go-multierror" 11 "github.com/hashicorp/serf/serf" 12 ) 13 14 // Internal endpoint is used to query the miscellaneous info that 15 // does not necessarily fit into the other systems. It is also 16 // used to hold undocumented APIs that users should not rely on. 17 type Internal struct { 18 srv *Server 19 } 20 21 // NodeInfo is used to retrieve information about a specific node. 22 func (m *Internal) NodeInfo(args *structs.NodeSpecificRequest, 23 reply *structs.IndexedNodeDump) error { 24 if done, err := m.srv.forward("Internal.NodeInfo", args, args, reply); done { 25 return err 26 } 27 28 return m.srv.blockingQuery( 29 &args.QueryOptions, 30 &reply.QueryMeta, 31 func(ws memdb.WatchSet, state *state.Store) error { 32 index, dump, err := state.NodeInfo(ws, args.Node) 33 if err != nil { 34 return err 35 } 36 37 reply.Index, reply.Dump = index, dump 38 return m.srv.filterACL(args.Token, reply) 39 }) 40 } 41 42 // NodeDump is used to generate information about all of the nodes. 43 func (m *Internal) NodeDump(args *structs.DCSpecificRequest, 44 reply *structs.IndexedNodeDump) error { 45 if done, err := m.srv.forward("Internal.NodeDump", args, args, reply); done { 46 return err 47 } 48 49 return m.srv.blockingQuery( 50 &args.QueryOptions, 51 &reply.QueryMeta, 52 func(ws memdb.WatchSet, state *state.Store) error { 53 index, dump, err := state.NodeDump(ws) 54 if err != nil { 55 return err 56 } 57 58 reply.Index, reply.Dump = index, dump 59 return m.srv.filterACL(args.Token, reply) 60 }) 61 } 62 63 // EventFire is a bit of an odd endpoint, but it allows for a cross-DC RPC 64 // call to fire an event. The primary use case is to enable user events being 65 // triggered in a remote DC. 66 func (m *Internal) EventFire(args *structs.EventFireRequest, 67 reply *structs.EventFireResponse) error { 68 if done, err := m.srv.forward("Internal.EventFire", args, args, reply); done { 69 return err 70 } 71 72 // Check ACLs 73 rule, err := m.srv.ResolveToken(args.Token) 74 if err != nil { 75 return err 76 } 77 78 if rule != nil && !rule.EventWrite(args.Name) { 79 m.srv.logger.Printf("[WARN] consul: user event %q blocked by ACLs", args.Name) 80 return acl.ErrPermissionDenied 81 } 82 83 // Set the query meta data 84 m.srv.setQueryMeta(&reply.QueryMeta) 85 86 // Add the consul prefix to the event name 87 eventName := userEventName(args.Name) 88 89 // Fire the event on all LAN segments 90 segments := m.srv.LANSegments() 91 var errs error 92 for name, segment := range segments { 93 err := segment.UserEvent(eventName, args.Payload, false) 94 if err != nil { 95 err = fmt.Errorf("error broadcasting event to segment %q: %v", name, err) 96 errs = multierror.Append(errs, err) 97 } 98 } 99 return errs 100 } 101 102 // KeyringOperation will query the WAN and LAN gossip keyrings of all nodes. 103 func (m *Internal) KeyringOperation( 104 args *structs.KeyringRequest, 105 reply *structs.KeyringResponses) error { 106 107 // Check ACLs 108 rule, err := m.srv.ResolveToken(args.Token) 109 if err != nil { 110 return err 111 } 112 if rule != nil { 113 switch args.Operation { 114 case structs.KeyringList: 115 if !rule.KeyringRead() { 116 return fmt.Errorf("Reading keyring denied by ACLs") 117 } 118 case structs.KeyringInstall: 119 fallthrough 120 case structs.KeyringUse: 121 fallthrough 122 case structs.KeyringRemove: 123 if !rule.KeyringWrite() { 124 return fmt.Errorf("Modifying keyring denied due to ACLs") 125 } 126 default: 127 panic("Invalid keyring operation") 128 } 129 } 130 131 // Only perform WAN keyring querying and RPC forwarding once 132 if !args.Forwarded && m.srv.serfWAN != nil { 133 args.Forwarded = true 134 m.executeKeyringOp(args, reply, true) 135 return m.srv.globalRPC("Internal.KeyringOperation", args, reply) 136 } 137 138 // Query the LAN keyring of this node's DC 139 m.executeKeyringOp(args, reply, false) 140 return nil 141 } 142 143 // executeKeyringOp executes the keyring-related operation in the request 144 // on either the WAN or LAN pools. 145 func (m *Internal) executeKeyringOp( 146 args *structs.KeyringRequest, 147 reply *structs.KeyringResponses, 148 wan bool) { 149 150 if wan { 151 mgr := m.srv.KeyManagerWAN() 152 m.executeKeyringOpMgr(mgr, args, reply, wan, "") 153 } else { 154 segments := m.srv.LANSegments() 155 for name, segment := range segments { 156 mgr := segment.KeyManager() 157 m.executeKeyringOpMgr(mgr, args, reply, wan, name) 158 } 159 } 160 } 161 162 // executeKeyringOpMgr executes the appropriate keyring-related function based on 163 // the type of keyring operation in the request. It takes the KeyManager as an 164 // argument, so it can handle any operation for either LAN or WAN pools. 165 func (m *Internal) executeKeyringOpMgr( 166 mgr *serf.KeyManager, 167 args *structs.KeyringRequest, 168 reply *structs.KeyringResponses, 169 wan bool, 170 segment string) { 171 var serfResp *serf.KeyResponse 172 var err error 173 174 opts := &serf.KeyRequestOptions{RelayFactor: args.RelayFactor} 175 switch args.Operation { 176 case structs.KeyringList: 177 serfResp, err = mgr.ListKeysWithOptions(opts) 178 case structs.KeyringInstall: 179 serfResp, err = mgr.InstallKeyWithOptions(args.Key, opts) 180 case structs.KeyringUse: 181 serfResp, err = mgr.UseKeyWithOptions(args.Key, opts) 182 case structs.KeyringRemove: 183 serfResp, err = mgr.RemoveKeyWithOptions(args.Key, opts) 184 } 185 186 errStr := "" 187 if err != nil { 188 errStr = err.Error() 189 } 190 191 reply.Responses = append(reply.Responses, &structs.KeyringResponse{ 192 WAN: wan, 193 Datacenter: m.srv.config.Datacenter, 194 Segment: segment, 195 Messages: serfResp.Messages, 196 Keys: serfResp.Keys, 197 NumNodes: serfResp.NumNodes, 198 Error: errStr, 199 }) 200 }