common.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. package common
  2. import (
  3. "bytes"
  4. "context"
  5. "encoding/json"
  6. "fmt"
  7. "io"
  8. "log"
  9. "net"
  10. "net/http"
  11. "os"
  12. "os/exec"
  13. "strings"
  14. "time"
  15. "github.com/gravitl/netmaker/models"
  16. "github.com/gravitl/netmaker/netclient/config"
  17. "github.com/gravitl/netmaker/netclient/ncutils"
  18. "github.com/gravitl/netmaker/nm-proxy/wg"
  19. "golang.zx2c4.com/wireguard/wgctrl/wgtypes"
  20. )
  21. const (
  22. NmProxyPort = 51722
  23. )
  24. type Conn struct {
  25. Config ConnConfig
  26. Proxy Proxy
  27. }
  28. // ConnConfig is a peer Connection configuration
  29. type ConnConfig struct {
  30. // Key is a public key of a remote peer
  31. Key string
  32. // LocalKey is a public key of a local peer
  33. LocalKey string
  34. LocalWgPort int
  35. RemoteProxyIP net.IP
  36. RemoteWgPort int
  37. RemoteProxyPort int
  38. }
  39. type Config struct {
  40. Port int
  41. BodySize int
  42. Addr string
  43. RemoteKey string
  44. WgInterface *wg.WGIface
  45. AllowedIps []net.IPNet
  46. PreSharedKey *wgtypes.Key
  47. }
  48. // Proxy - WireguardProxy proxies
  49. type Proxy struct {
  50. Ctx context.Context
  51. Cancel context.CancelFunc
  52. Config Config
  53. RemoteConn *net.UDPAddr
  54. LocalConn net.Conn
  55. }
  56. type RemotePeer struct {
  57. PeerKey string
  58. Interface string
  59. }
  60. var WgIFaceMap = make(map[string]map[string]*Conn)
  61. var PeerKeyHashMap = make(map[string]RemotePeer)
  62. // RunCmd - runs a local command
  63. func RunCmd(command string, printerr bool) (string, error) {
  64. args := strings.Fields(command)
  65. cmd := exec.Command(args[0], args[1:]...)
  66. cmd.Wait()
  67. out, err := cmd.CombinedOutput()
  68. if err != nil && printerr {
  69. log.Println("error running command: ", command)
  70. log.Println(strings.TrimSuffix(string(out), "\n"))
  71. }
  72. return string(out), err
  73. }
  74. // API function to interact with netmaker api endpoints. response from endpoint is returned
  75. func API(data interface{}, method, url, authorization string) (*http.Response, error) {
  76. var request *http.Request
  77. var err error
  78. if data != "" {
  79. payload, err := json.Marshal(data)
  80. if err != nil {
  81. return nil, fmt.Errorf("error encoding data %w", err)
  82. }
  83. request, err = http.NewRequest(method, url, bytes.NewBuffer(payload))
  84. if err != nil {
  85. return nil, fmt.Errorf("error creating http request %w", err)
  86. }
  87. request.Header.Set("Content-Type", "application/json")
  88. } else {
  89. request, err = http.NewRequest(method, url, nil)
  90. if err != nil {
  91. return nil, fmt.Errorf("error creating http request %w", err)
  92. }
  93. }
  94. if authorization != "" {
  95. request.Header.Set("authorization", "Bearer "+authorization)
  96. }
  97. request.Header.Set("requestfrom", "node")
  98. var httpClient http.Client
  99. httpClient.Timeout = time.Minute
  100. return httpClient.Do(request)
  101. }
  102. // Authenticate authenticates with api to permit subsequent interactions with the api
  103. func Authenticate(cfg *config.ClientConfig) (string, error) {
  104. pass, err := os.ReadFile(ncutils.GetNetclientPathSpecific() + "secret-" + cfg.Network)
  105. if err != nil {
  106. return "", fmt.Errorf("could not read secrets file %w", err)
  107. }
  108. data := models.AuthParams{
  109. MacAddress: cfg.Node.MacAddress,
  110. ID: cfg.Node.ID,
  111. Password: string(pass),
  112. }
  113. url := "https://" + cfg.Server.API + "/api/nodes/adm/" + cfg.Network + "/authenticate"
  114. response, err := API(data, http.MethodPost, url, "")
  115. if err != nil {
  116. return "", err
  117. }
  118. defer response.Body.Close()
  119. if response.StatusCode != http.StatusOK {
  120. bodybytes, _ := io.ReadAll(response.Body)
  121. return "", fmt.Errorf("failed to authenticate %s %s", response.Status, string(bodybytes))
  122. }
  123. resp := models.SuccessResponse{}
  124. if err := json.NewDecoder(response.Body).Decode(&resp); err != nil {
  125. return "", fmt.Errorf("error decoding respone %w", err)
  126. }
  127. tokenData := resp.Response.(map[string]interface{})
  128. token := tokenData["AuthToken"]
  129. return token.(string), nil
  130. }