helpers.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734
  1. //TODO: Consider restructuring this file/folder "github.com/gorilla/handlers"
  2. //It may make more sense to split into different files and not call it "helpers"
  3. package functions
  4. import (
  5. "encoding/base64"
  6. "encoding/json"
  7. "errors"
  8. "fmt"
  9. "log"
  10. "math/rand"
  11. "net"
  12. "strings"
  13. "time"
  14. "github.com/gravitl/netmaker/database"
  15. "github.com/gravitl/netmaker/models"
  16. "github.com/gravitl/netmaker/servercfg"
  17. )
  18. func PrintUserLog(username string, message string, loglevel int) {
  19. log.SetFlags(log.Flags() &^ (log.Llongfile | log.Lshortfile))
  20. if int32(loglevel) <= servercfg.GetVerbose() && servercfg.GetVerbose() != 0 {
  21. log.Println(username, message)
  22. }
  23. }
  24. func ParseNetwork(value string) (models.Network, error) {
  25. var network models.Network
  26. err := json.Unmarshal([]byte(value), &network)
  27. return network, err
  28. }
  29. func ParseNode(value string) (models.Node, error) {
  30. var node models.Node
  31. err := json.Unmarshal([]byte(value), &node)
  32. return node, err
  33. }
  34. func ParseExtClient(value string) (models.ExtClient, error) {
  35. var extClient models.ExtClient
  36. err := json.Unmarshal([]byte(value), &extClient)
  37. return extClient, err
  38. }
  39. func ParseIntClient(value string) (models.IntClient, error) {
  40. var intClient models.IntClient
  41. err := json.Unmarshal([]byte(value), &intClient)
  42. return intClient, err
  43. }
  44. //Takes in an arbitrary field and value for field and checks to see if any other
  45. //node has that value for the same field within the network
  46. func GetUser(username string) (models.User, error) {
  47. var user models.User
  48. record, err := database.FetchRecord(database.USERS_TABLE_NAME, username)
  49. if err != nil {
  50. return user, err
  51. }
  52. if err = json.Unmarshal([]byte(record), &user); err != nil {
  53. return models.User{}, err
  54. }
  55. return user, err
  56. }
  57. func SliceContains(slice []string, item string) bool {
  58. set := make(map[string]struct{}, len(slice))
  59. for _, s := range slice {
  60. set[s] = struct{}{}
  61. }
  62. _, ok := set[item]
  63. return ok
  64. }
  65. func CreateServerToken(netID string) (string, error) {
  66. var network models.Network
  67. var accesskey models.AccessKey
  68. network, err := GetParentNetwork(netID)
  69. if err != nil {
  70. return "", err
  71. }
  72. var accessToken models.AccessToken
  73. servervals := models.ServerConfig{
  74. APIConnString: "127.0.0.1:" + servercfg.GetAPIPort(),
  75. GRPCConnString: "127.0.0.1:" + servercfg.GetGRPCPort(),
  76. GRPCSSL: "off",
  77. }
  78. accessToken.ServerConfig = servervals
  79. accessToken.ClientConfig.Network = netID
  80. accessToken.ClientConfig.Key = GenKey()
  81. accesskey.Name = GenKeyName()
  82. accesskey.Value = GenKey()
  83. accesskey.Uses = 1
  84. tokenjson, err := json.Marshal(accessToken)
  85. if err != nil {
  86. return accesskey.AccessString, err
  87. }
  88. accesskey.AccessString = base64.StdEncoding.EncodeToString([]byte(tokenjson))
  89. network.AccessKeys = append(network.AccessKeys, accesskey)
  90. if data, err := json.Marshal(network); err != nil {
  91. return "", err
  92. } else {
  93. database.Insert(netID, string(data), database.NETWORKS_TABLE_NAME)
  94. }
  95. return accesskey.AccessString, nil
  96. }
  97. func GetPeersList(networkName string) ([]models.PeersResponse, error) {
  98. var peers []models.PeersResponse
  99. collection, err := database.FetchRecords(database.NODES_TABLE_NAME)
  100. if err != nil {
  101. return peers, err
  102. }
  103. for _, value := range collection {
  104. var peer models.PeersResponse
  105. err := json.Unmarshal([]byte(value), &peer)
  106. if err != nil {
  107. continue // try the rest
  108. }
  109. peers = append(peers, peer)
  110. }
  111. return peers, err
  112. }
  113. func GetIntPeersList() ([]models.PeersResponse, error) {
  114. var peers []models.PeersResponse
  115. records, err := database.FetchRecords(database.INT_CLIENTS_TABLE_NAME)
  116. if err != nil {
  117. return peers, err
  118. }
  119. // parse the peers
  120. for _, value := range records {
  121. var peer models.PeersResponse
  122. err := json.Unmarshal([]byte(value), &peer)
  123. if err != nil {
  124. log.Fatal(err)
  125. }
  126. // add the node to our node array
  127. //maybe better to just return this? But then that's just GetNodes...
  128. peers = append(peers, peer)
  129. }
  130. return peers, err
  131. }
  132. func GetServerIntClient() (*models.IntClient, error) {
  133. intClients, err := database.FetchRecords(database.INT_CLIENTS_TABLE_NAME)
  134. for _, value := range intClients {
  135. var intClient models.IntClient
  136. err = json.Unmarshal([]byte(value), &intClient)
  137. if err != nil {
  138. return nil, err
  139. }
  140. if intClient.IsServer == "yes" && intClient.Network == "comms" {
  141. return &intClient, nil
  142. }
  143. }
  144. return nil, err
  145. }
  146. func NetworkExists(name string) (bool, error) {
  147. var network string
  148. var err error
  149. if network, err = database.FetchRecord(database.NETWORKS_TABLE_NAME, name); err != nil {
  150. return false, err
  151. }
  152. return len(network) > 0, nil
  153. }
  154. func GetRecordKey(id string, network string) (string, error) {
  155. if id == "" || network == "" {
  156. return "", errors.New("unable to get record key")
  157. }
  158. return id + "###" + network, nil
  159. }
  160. //TODO: This is very inefficient (N-squared). Need to find a better way.
  161. //Takes a list of nodes in a network and iterates through
  162. //for each node, it gets a unique address. That requires checking against all other nodes once more
  163. func UpdateNetworkNodeAddresses(networkName string) error {
  164. collections, err := database.FetchRecords(database.NODES_TABLE_NAME)
  165. if err != nil {
  166. return err
  167. }
  168. for _, value := range collections {
  169. var node models.Node
  170. err := json.Unmarshal([]byte(value), &node)
  171. if err != nil {
  172. fmt.Println("error in node address assignment!")
  173. return err
  174. }
  175. ipaddr, iperr := UniqueAddress(networkName)
  176. if iperr != nil {
  177. fmt.Println("error in node address assignment!")
  178. return iperr
  179. }
  180. node.Address = ipaddr
  181. data, err := json.Marshal(&node)
  182. if err != nil {
  183. return err
  184. }
  185. database.Insert(node.MacAddress, string(data), database.NODES_TABLE_NAME)
  186. }
  187. return nil
  188. }
  189. func UpdateNetworkLocalAddresses(networkName string) error {
  190. collection, err := database.FetchRecords(database.NODES_TABLE_NAME)
  191. if err != nil {
  192. return err
  193. }
  194. for _, value := range collection {
  195. var node models.Node
  196. err := json.Unmarshal([]byte(value), &node)
  197. if err != nil {
  198. fmt.Println("error in node address assignment!")
  199. return err
  200. }
  201. ipaddr, iperr := UniqueAddress(networkName)
  202. if iperr != nil {
  203. fmt.Println("error in node address assignment!")
  204. return iperr
  205. }
  206. node.Address = ipaddr
  207. newNodeData, err := json.Marshal(&node)
  208. if err != nil {
  209. fmt.Println("error in node address assignment!")
  210. return err
  211. }
  212. database.Insert(node.MacAddress, string(newNodeData), database.NODES_TABLE_NAME)
  213. }
  214. return nil
  215. }
  216. func IsNetworkDisplayNameUnique(name string) (bool, error) {
  217. isunique := true
  218. dbs, err := models.GetNetworks()
  219. if err != nil {
  220. return false, err
  221. }
  222. for i := 0; i < len(dbs); i++ {
  223. if name == dbs[i].DisplayName {
  224. isunique = false
  225. }
  226. }
  227. return isunique, nil
  228. }
  229. func IsMacAddressUnique(macaddress string, networkName string) (bool, error) {
  230. collection, err := database.FetchRecords(database.NODES_TABLE_NAME)
  231. if err != nil {
  232. return false, err
  233. }
  234. for _, value := range collection {
  235. var node models.Node
  236. if err = json.Unmarshal([]byte(value), &node); err != nil {
  237. return false, err
  238. } else {
  239. if node.MacAddress == macaddress && node.Network == networkName {
  240. return false, nil
  241. }
  242. }
  243. }
  244. return true, nil
  245. }
  246. func GetNetworkNodeNumber(networkName string) (int, error) {
  247. collection, err := database.FetchRecords(database.NODES_TABLE_NAME)
  248. count := 0
  249. if err != nil {
  250. return count, err
  251. }
  252. for _, value := range collection {
  253. var node models.Node
  254. if err = json.Unmarshal([]byte(value), &node); err != nil {
  255. return count, err
  256. } else {
  257. if node.Network == networkName {
  258. count++
  259. }
  260. }
  261. }
  262. return count, nil
  263. }
  264. //Checks to see if access key is valid
  265. //Does so by checking against all keys and seeing if any have the same value
  266. //may want to hash values before comparing...consider this
  267. //TODO: No error handling!!!!
  268. func IsKeyValid(networkname string, keyvalue string) bool {
  269. network, _ := GetParentNetwork(networkname)
  270. var key models.AccessKey
  271. foundkey := false
  272. isvalid := false
  273. for i := len(network.AccessKeys) - 1; i >= 0; i-- {
  274. currentkey := network.AccessKeys[i]
  275. if currentkey.Value == keyvalue {
  276. key = currentkey
  277. foundkey = true
  278. }
  279. }
  280. if foundkey {
  281. if key.Uses > 0 {
  282. isvalid = true
  283. }
  284. }
  285. return isvalid
  286. }
  287. func IsKeyValidGlobal(keyvalue string) bool {
  288. networks, _ := models.GetNetworks()
  289. var key models.AccessKey
  290. foundkey := false
  291. isvalid := false
  292. for _, network := range networks {
  293. for i := len(network.AccessKeys) - 1; i >= 0; i-- {
  294. currentkey := network.AccessKeys[i]
  295. if currentkey.Value == keyvalue {
  296. key = currentkey
  297. foundkey = true
  298. break
  299. }
  300. }
  301. if foundkey {
  302. break
  303. }
  304. }
  305. if foundkey {
  306. if key.Uses > 0 {
  307. isvalid = true
  308. }
  309. }
  310. return isvalid
  311. }
  312. //TODO: Contains a fatal error return. Need to change
  313. //This just gets a network object from a network name
  314. //Should probably just be GetNetwork. kind of a dumb name.
  315. //Used in contexts where it's not the Parent network.
  316. func GetParentNetwork(networkname string) (models.Network, error) {
  317. var network models.Network
  318. networkData, err := database.FetchRecord(database.NETWORKS_TABLE_NAME, networkname)
  319. if err != nil {
  320. return network, err
  321. }
  322. if err = json.Unmarshal([]byte(networkData), &network); err != nil {
  323. return models.Network{}, err
  324. }
  325. return network, nil
  326. }
  327. func IsIpNet(host string) bool {
  328. return net.ParseIP(host) != nil
  329. }
  330. //Similar to above but checks if Cidr range is valid
  331. //At least this guy's got some print statements
  332. //still not good error handling
  333. func IsIpCIDR(host string) bool {
  334. ip, ipnet, err := net.ParseCIDR(host)
  335. if err != nil {
  336. fmt.Println(err)
  337. fmt.Println("Address Range is not valid!")
  338. return false
  339. }
  340. return ip != nil && ipnet != nil
  341. }
  342. //This is used to validate public keys (make sure they're base64 encoded like all public keys should be).
  343. func IsBase64(s string) bool {
  344. _, err := base64.StdEncoding.DecodeString(s)
  345. return err == nil
  346. }
  347. //This checks to make sure a network name is valid.
  348. //Switch to REGEX?
  349. func NameInNetworkCharSet(name string) bool {
  350. charset := "abcdefghijklmnopqrstuvwxyz1234567890-_."
  351. for _, char := range name {
  352. if !strings.Contains(charset, strings.ToLower(string(char))) {
  353. return false
  354. }
  355. }
  356. return true
  357. }
  358. func NameInDNSCharSet(name string) bool {
  359. charset := "abcdefghijklmnopqrstuvwxyz1234567890-."
  360. for _, char := range name {
  361. if !strings.Contains(charset, strings.ToLower(string(char))) {
  362. return false
  363. }
  364. }
  365. return true
  366. }
  367. func NameInNodeCharSet(name string) bool {
  368. charset := "abcdefghijklmnopqrstuvwxyz1234567890-"
  369. for _, char := range name {
  370. if !strings.Contains(charset, strings.ToLower(string(char))) {
  371. return false
  372. }
  373. }
  374. return true
  375. }
  376. //This returns a node based on its mac address.
  377. //The mac address acts as the Unique ID for nodes.
  378. //Is this a dumb thing to do? I thought it was cool but maybe it's dumb.
  379. //It doesn't really provide a tangible benefit over a random ID
  380. func GetNodeByMacAddress(network string, macaddress string) (models.Node, error) {
  381. var node models.Node
  382. key, err := GetRecordKey(macaddress, network)
  383. if err != nil {
  384. return node, err
  385. }
  386. record, err := database.FetchRecord(database.NODES_TABLE_NAME, key)
  387. if err != nil {
  388. return models.Node{}, err
  389. }
  390. if err = json.Unmarshal([]byte(record), &node); err != nil {
  391. return models.Node{}, err
  392. }
  393. return node, nil
  394. }
  395. func DeleteAllIntClients() error {
  396. err := database.DeleteAllRecords(database.INT_CLIENTS_TABLE_NAME)
  397. if err != nil {
  398. return err
  399. }
  400. return nil
  401. }
  402. func GetAllIntClients() ([]models.IntClient, error) {
  403. var clients []models.IntClient
  404. collection, err := database.FetchRecords(database.INT_CLIENTS_TABLE_NAME)
  405. if err != nil {
  406. return clients, err
  407. }
  408. for _, value := range collection {
  409. var client models.IntClient
  410. err := json.Unmarshal([]byte(value), &client)
  411. if err != nil {
  412. return []models.IntClient{}, err
  413. }
  414. // add node to our array
  415. clients = append(clients, client)
  416. }
  417. return clients, nil
  418. }
  419. func GetAllExtClients() ([]models.ExtClient, error) {
  420. var extclients []models.ExtClient
  421. collection, err := database.FetchRecords(database.EXT_CLIENT_TABLE_NAME)
  422. if err != nil {
  423. return extclients, err
  424. }
  425. for _, value := range collection {
  426. var extclient models.ExtClient
  427. err := json.Unmarshal([]byte(value), &extclient)
  428. if err != nil {
  429. return []models.ExtClient{}, err
  430. }
  431. // add node to our array
  432. extclients = append(extclients, extclient)
  433. }
  434. return extclients, nil
  435. }
  436. //This returns a unique address for a node to use
  437. //it iterates through the list of IP's in the subnet
  438. //and checks against all nodes to see if it's taken, until it finds one.
  439. //TODO: We do not handle a case where we run out of addresses.
  440. //We will need to handle that eventually
  441. func UniqueAddress(networkName string) (string, error) {
  442. var network models.Network
  443. network, err := GetParentNetwork(networkName)
  444. if err != nil {
  445. fmt.Println("UniqueAddress encountered an error")
  446. return "666", err
  447. }
  448. offset := true
  449. ip, ipnet, err := net.ParseCIDR(network.AddressRange)
  450. if err != nil {
  451. fmt.Println("UniqueAddress encountered an error")
  452. return "666", err
  453. }
  454. for ip := ip.Mask(ipnet.Mask); ipnet.Contains(ip); Inc(ip) {
  455. if offset {
  456. offset = false
  457. continue
  458. }
  459. if networkName == "comms" {
  460. if IsIPUnique(networkName, ip.String(), database.INT_CLIENTS_TABLE_NAME, false) {
  461. return ip.String(), err
  462. }
  463. } else {
  464. if IsIPUnique(networkName, ip.String(), database.NODES_TABLE_NAME, false) && IsIPUnique(networkName, ip.String(), database.EXT_CLIENT_TABLE_NAME, false) {
  465. return ip.String(), err
  466. }
  467. }
  468. }
  469. //TODO
  470. err1 := errors.New("ERROR: No unique addresses available. Check network subnet.")
  471. return "W1R3: NO UNIQUE ADDRESSES AVAILABLE", err1
  472. }
  473. func UniqueAddress6(networkName string) (string, error) {
  474. var network models.Network
  475. network, err := GetParentNetwork(networkName)
  476. if err != nil {
  477. fmt.Println("Network Not Found")
  478. return "", err
  479. }
  480. if network.IsDualStack == "no" {
  481. if networkName != "comms" {
  482. return "", nil
  483. }
  484. }
  485. offset := true
  486. ip, ipnet, err := net.ParseCIDR(network.AddressRange6)
  487. if err != nil {
  488. fmt.Println("UniqueAddress6 encountered an error")
  489. return "666", err
  490. }
  491. for ip := ip.Mask(ipnet.Mask); ipnet.Contains(ip); Inc(ip) {
  492. if offset {
  493. offset = false
  494. continue
  495. }
  496. if networkName == "comms" {
  497. if IsIPUnique(networkName, ip.String(), database.INT_CLIENTS_TABLE_NAME, true) {
  498. return ip.String(), err
  499. }
  500. } else {
  501. if IsIPUnique(networkName, ip.String(), database.NODES_TABLE_NAME, true) {
  502. return ip.String(), err
  503. }
  504. }
  505. }
  506. //TODO
  507. err1 := errors.New("ERROR: No unique addresses available. Check network subnet.")
  508. return "W1R3: NO UNIQUE ADDRESSES AVAILABLE", err1
  509. }
  510. //generate an access key value
  511. func GenKey() string {
  512. var seededRand *rand.Rand = rand.New(
  513. rand.NewSource(time.Now().UnixNano()))
  514. length := 16
  515. charset := "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
  516. b := make([]byte, length)
  517. for i := range b {
  518. b[i] = charset[seededRand.Intn(len(charset))]
  519. }
  520. return string(b)
  521. }
  522. //generate a key value
  523. //we should probably just have 1 random string generator
  524. //that can be used across all functions
  525. //have a "base string" a "length" and a "charset"
  526. func GenKeyName() string {
  527. var seededRand *rand.Rand = rand.New(
  528. rand.NewSource(time.Now().UnixNano()))
  529. length := 5
  530. charset := "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
  531. b := make([]byte, length)
  532. for i := range b {
  533. b[i] = charset[seededRand.Intn(len(charset))]
  534. }
  535. return "key" + string(b)
  536. }
  537. func IsIPUnique(network string, ip string, tableName string, isIpv6 bool) bool {
  538. isunique := true
  539. collection, err := database.FetchRecords(tableName)
  540. if err != nil {
  541. return isunique
  542. }
  543. for _, value := range collection { // filter
  544. var node models.Node
  545. if err = json.Unmarshal([]byte(value), &node); err != nil {
  546. continue
  547. }
  548. if isIpv6 {
  549. if node.Address6 == ip && node.Network == network {
  550. return false
  551. }
  552. } else {
  553. if node.Address == ip && node.Network == network {
  554. return false
  555. }
  556. }
  557. }
  558. return isunique
  559. }
  560. //called once key has been used by createNode
  561. //reduces value by one and deletes if necessary
  562. func DecrimentKey(networkName string, keyvalue string) {
  563. var network models.Network
  564. network, err := GetParentNetwork(networkName)
  565. if err != nil {
  566. return
  567. }
  568. for i := len(network.AccessKeys) - 1; i >= 0; i-- {
  569. currentkey := network.AccessKeys[i]
  570. if currentkey.Value == keyvalue {
  571. network.AccessKeys[i].Uses--
  572. if network.AccessKeys[i].Uses < 1 {
  573. network.AccessKeys = append(network.AccessKeys[:i],
  574. network.AccessKeys[i+1:]...)
  575. break
  576. }
  577. }
  578. }
  579. if newNetworkData, err := json.Marshal(&network); err != nil {
  580. PrintUserLog("netmaker", "failed to decrement key", 2)
  581. return
  582. } else {
  583. database.Insert(network.NetID, string(newNetworkData), database.NETWORKS_TABLE_NAME)
  584. }
  585. }
  586. //takes the logic from controllers.deleteKey
  587. func DeleteKey(network models.Network, i int) {
  588. network.AccessKeys = append(network.AccessKeys[:i],
  589. network.AccessKeys[i+1:]...)
  590. if networkData, err := json.Marshal(&network); err != nil {
  591. return
  592. } else {
  593. database.Insert(network.NetID, string(networkData), database.NETWORKS_TABLE_NAME)
  594. }
  595. }
  596. //increments an IP over the previous
  597. func Inc(ip net.IP) {
  598. for j := len(ip) - 1; j >= 0; j-- {
  599. ip[j]++
  600. if ip[j] > 0 {
  601. break
  602. }
  603. }
  604. }