dynsec_helper.go 8.4 KB

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