dynsec_helper.go 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. package mq
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "time"
  7. mqtt "github.com/eclipse/paho.mqtt.golang"
  8. "github.com/gravitl/netmaker/servercfg"
  9. )
  10. const (
  11. // constant for admin role
  12. adminRole = "admin"
  13. // constant for server role
  14. serverRole = "server"
  15. // constant for exporter role
  16. exporterRole = "exporter"
  17. // constant for node role
  18. NodeRole = "node"
  19. // const for dynamic security file
  20. dynamicSecurityFile = "dynamic-security.json"
  21. )
  22. var (
  23. // default configuration of dynamic security
  24. dynConfig = dynJSON{
  25. Clients: []client{
  26. {
  27. Username: mqAdminUserName,
  28. TextName: "netmaker admin user",
  29. Password: "",
  30. Salt: "",
  31. Iterations: 0,
  32. Roles: []clientRole{
  33. {
  34. Rolename: adminRole,
  35. },
  36. },
  37. },
  38. {
  39. Username: mqNetmakerServerUserName,
  40. TextName: "netmaker server user",
  41. Password: "",
  42. Salt: "",
  43. Iterations: 0,
  44. Roles: []clientRole{
  45. {
  46. Rolename: serverRole,
  47. },
  48. },
  49. },
  50. },
  51. Roles: []role{
  52. {
  53. Rolename: adminRole,
  54. Acls: fetchAdminAcls(),
  55. },
  56. {
  57. Rolename: serverRole,
  58. Acls: fetchServerAcls(),
  59. },
  60. {
  61. Rolename: NodeRole,
  62. Acls: fetchNodeAcls(),
  63. },
  64. },
  65. DefaultAcl: defaultAccessAcl{
  66. PublishClientSend: false,
  67. PublishClientReceive: true,
  68. Subscribe: false,
  69. Unsubscribe: true,
  70. },
  71. }
  72. exporterMQClient = client{
  73. Username: mqExporterUserName,
  74. TextName: "netmaker metrics exporter",
  75. Password: "",
  76. Salt: "",
  77. Iterations: 101,
  78. Roles: []clientRole{
  79. {
  80. Rolename: exporterRole,
  81. },
  82. },
  83. }
  84. exporterMQRole = role{
  85. Rolename: exporterRole,
  86. Acls: fetchExporterAcls(),
  87. }
  88. )
  89. // DynListCLientsCmdResp - struct for list clients response from MQ
  90. type DynListCLientsCmdResp struct {
  91. Responses []struct {
  92. Command string `json:"command"`
  93. Error string `json:"error"`
  94. Data ListClientsData `json:"data"`
  95. } `json:"responses"`
  96. }
  97. // ListClientsData - struct for list clients data
  98. type ListClientsData struct {
  99. Clients []string `json:"clients"`
  100. TotalCount int `json:"totalCount"`
  101. }
  102. // GetAdminClient - fetches admin client of the MQ
  103. func GetAdminClient() (mqtt.Client, error) {
  104. opts := mqtt.NewClientOptions()
  105. setMqOptions(mqAdminUserName, servercfg.GetMqAdminPassword(), opts)
  106. mqclient := mqtt.NewClient(opts)
  107. var connecterr error
  108. if token := mqclient.Connect(); !token.WaitTimeout(MQ_TIMEOUT*time.Second) || token.Error() != nil {
  109. if token.Error() == nil {
  110. connecterr = errors.New("connect timeout")
  111. } else {
  112. connecterr = token.Error()
  113. }
  114. }
  115. return mqclient, connecterr
  116. }
  117. // ListClients - to list all clients in the MQ
  118. func ListClients(client mqtt.Client) (ListClientsData, error) {
  119. respChan := make(chan mqtt.Message, 10)
  120. defer close(respChan)
  121. command := "listClients"
  122. resp := ListClientsData{}
  123. msg := MqDynsecPayload{
  124. Commands: []MqDynSecCmd{
  125. {
  126. Command: command,
  127. },
  128. },
  129. }
  130. client.Subscribe("$CONTROL/dynamic-security/v1/response", 2, mqtt.MessageHandler(func(c mqtt.Client, m mqtt.Message) {
  131. respChan <- m
  132. }))
  133. defer client.Unsubscribe()
  134. d, _ := json.Marshal(msg)
  135. token := client.Publish("$CONTROL/dynamic-security/v1", 2, true, d)
  136. if !token.WaitTimeout(30) || token.Error() != nil {
  137. var err error
  138. if token.Error() == nil {
  139. err = errors.New("connection timeout")
  140. } else {
  141. err = token.Error()
  142. }
  143. return resp, err
  144. }
  145. for m := range respChan {
  146. msg := DynListCLientsCmdResp{}
  147. json.Unmarshal(m.Payload(), &msg)
  148. for _, mI := range msg.Responses {
  149. if mI.Command == command {
  150. return mI.Data, nil
  151. }
  152. }
  153. }
  154. return resp, errors.New("resp not found")
  155. }
  156. // FetchNetworkAcls - fetches network acls
  157. func FetchNetworkAcls(network string) []Acl {
  158. return []Acl{
  159. {
  160. AclType: "publishClientReceive",
  161. Topic: fmt.Sprintf("update/%s/#", network),
  162. Priority: -1,
  163. Allow: true,
  164. },
  165. {
  166. AclType: "publishClientReceive",
  167. Topic: fmt.Sprintf("peers/%s/#", network),
  168. Priority: -1,
  169. Allow: true,
  170. },
  171. {
  172. AclType: "subscribePattern",
  173. Topic: "#",
  174. Priority: -1,
  175. Allow: true,
  176. },
  177. {
  178. AclType: "unsubscribePattern",
  179. Topic: "#",
  180. Priority: -1,
  181. Allow: true,
  182. },
  183. }
  184. }
  185. // serverAcls - fetches server role related acls
  186. func fetchServerAcls() []Acl {
  187. return []Acl{
  188. {
  189. AclType: "publishClientSend",
  190. Topic: "peers/#",
  191. Priority: -1,
  192. Allow: true,
  193. },
  194. {
  195. AclType: "publishClientSend",
  196. Topic: "update/#",
  197. Priority: -1,
  198. Allow: true,
  199. },
  200. {
  201. AclType: "publishClientSend",
  202. Topic: "metrics_exporter",
  203. Priority: -1,
  204. Allow: true,
  205. },
  206. {
  207. AclType: "publishClientReceive",
  208. Topic: "ping/#",
  209. Priority: -1,
  210. Allow: true,
  211. },
  212. {
  213. AclType: "publishClientReceive",
  214. Topic: "update/#",
  215. Priority: -1,
  216. Allow: true,
  217. },
  218. {
  219. AclType: "publishClientReceive",
  220. Topic: "signal/#",
  221. Priority: -1,
  222. Allow: true,
  223. },
  224. {
  225. AclType: "publishClientReceive",
  226. Topic: "metrics/#",
  227. Priority: -1,
  228. Allow: true,
  229. },
  230. {
  231. AclType: "subscribePattern",
  232. Topic: "#",
  233. Priority: -1,
  234. Allow: true,
  235. },
  236. {
  237. AclType: "unsubscribePattern",
  238. Topic: "#",
  239. Priority: -1,
  240. Allow: true,
  241. },
  242. }
  243. }
  244. // fetchNodeAcls - fetches node related acls
  245. func fetchNodeAcls() []Acl {
  246. // keeping node acls generic as of now.
  247. return []Acl{
  248. {
  249. AclType: "publishClientSend",
  250. Topic: "signal/#",
  251. Priority: -1,
  252. Allow: true,
  253. },
  254. {
  255. AclType: "publishClientSend",
  256. Topic: "update/#",
  257. Priority: -1,
  258. Allow: true,
  259. },
  260. {
  261. AclType: "publishClientSend",
  262. Topic: "ping/#",
  263. Priority: -1,
  264. Allow: true,
  265. },
  266. {
  267. AclType: "publishClientSend",
  268. Topic: "metrics/#",
  269. Priority: -1,
  270. Allow: true,
  271. },
  272. {
  273. AclType: "subscribePattern",
  274. Topic: "#",
  275. Priority: -1,
  276. Allow: true,
  277. },
  278. {
  279. AclType: "unsubscribePattern",
  280. Topic: "#",
  281. Priority: -1,
  282. Allow: true,
  283. },
  284. }
  285. }
  286. // fetchExporterAcls - fetch exporter role related acls
  287. func fetchExporterAcls() []Acl {
  288. return []Acl{
  289. {
  290. AclType: "publishClientReceive",
  291. Topic: "metrics_exporter",
  292. Allow: true,
  293. Priority: -1,
  294. },
  295. {
  296. AclType: "subscribePattern",
  297. Topic: "#",
  298. Priority: -1,
  299. Allow: true,
  300. },
  301. {
  302. AclType: "unsubscribePattern",
  303. Topic: "#",
  304. Priority: -1,
  305. Allow: true,
  306. },
  307. }
  308. }
  309. // fetchAdminAcls - fetches admin role related acls
  310. func fetchAdminAcls() []Acl {
  311. return []Acl{
  312. {
  313. AclType: "publishClientSend",
  314. Topic: "$CONTROL/dynamic-security/#",
  315. Priority: -1,
  316. Allow: true,
  317. },
  318. {
  319. AclType: "publishClientReceive",
  320. Topic: "$CONTROL/dynamic-security/#",
  321. Priority: -1,
  322. Allow: true,
  323. },
  324. {
  325. AclType: "subscribePattern",
  326. Topic: "$CONTROL/dynamic-security/#",
  327. Priority: -1,
  328. Allow: true,
  329. },
  330. {
  331. AclType: "publishClientReceive",
  332. Topic: "$SYS/#",
  333. Priority: -1,
  334. Allow: true,
  335. },
  336. {
  337. AclType: "subscribePattern",
  338. Topic: "$SYS/#",
  339. Priority: -1,
  340. Allow: true,
  341. },
  342. {
  343. AclType: "publishClientReceive",
  344. Topic: "#",
  345. Priority: -1,
  346. Allow: true,
  347. },
  348. {
  349. AclType: "subscribePattern",
  350. Topic: "#",
  351. Priority: -1,
  352. Allow: true,
  353. },
  354. {
  355. AclType: "unsubscribePattern",
  356. Topic: "#",
  357. Priority: -1,
  358. Allow: true,
  359. },
  360. {
  361. AclType: "publishClientSend",
  362. Topic: "#",
  363. Priority: -1,
  364. Allow: true,
  365. },
  366. }
  367. }