dynsec_helper.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  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. // HostGenericRole constant for host role
  20. HostGenericRole = "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. },
  58. {
  59. Rolename: serverRole,
  60. },
  61. {
  62. Rolename: HostGenericRole,
  63. },
  64. exporterMQRole,
  65. },
  66. DefaultAcl: defaultAccessAcl{
  67. PublishClientSend: false,
  68. PublishClientReceive: true,
  69. Subscribe: false,
  70. Unsubscribe: true,
  71. },
  72. }
  73. exporterMQClient = client{
  74. Username: mqExporterUserName,
  75. TextName: "netmaker metrics exporter",
  76. Password: "",
  77. Salt: "",
  78. Iterations: 101,
  79. Roles: []clientRole{
  80. {
  81. Rolename: exporterRole,
  82. },
  83. },
  84. }
  85. exporterMQRole = role{
  86. Rolename: exporterRole,
  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. // DeleteNetworkRole - deletes a network role from DynSec system
  157. func DeleteNetworkRole(network string) error {
  158. // Deletes the network role from MQ
  159. event := MqDynsecPayload{
  160. Commands: []MqDynSecCmd{
  161. {
  162. Command: DeleteRoleCmd,
  163. RoleName: network,
  164. },
  165. },
  166. }
  167. return publishEventToDynSecTopic(event)
  168. }
  169. func deleteHostRole(hostID string) error {
  170. // Deletes the hostID role from MQ
  171. event := MqDynsecPayload{
  172. Commands: []MqDynSecCmd{
  173. {
  174. Command: DeleteRoleCmd,
  175. RoleName: getHostRoleName(hostID),
  176. },
  177. },
  178. }
  179. return publishEventToDynSecTopic(event)
  180. }
  181. // CreateNetworkRole - createss a network role from DynSec system
  182. func CreateNetworkRole(network string) error {
  183. // Create Role with acls for the network
  184. event := MqDynsecPayload{
  185. Commands: []MqDynSecCmd{
  186. {
  187. Command: CreateRoleCmd,
  188. RoleName: network,
  189. Textname: "Network wide role with Acls for nodes",
  190. },
  191. },
  192. }
  193. return publishEventToDynSecTopic(event)
  194. }
  195. // creates role for the host with ID.
  196. func createHostRole(hostID string) error {
  197. // Create Role with acls for the host
  198. event := MqDynsecPayload{
  199. Commands: []MqDynSecCmd{
  200. {
  201. Command: CreateRoleCmd,
  202. RoleName: getHostRoleName(hostID),
  203. Textname: "host role with Acls for hosts",
  204. },
  205. },
  206. }
  207. return publishEventToDynSecTopic(event)
  208. }
  209. func getHostRoleName(hostID string) string {
  210. return fmt.Sprintf("host-%s", hostID)
  211. }