main.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. package main
  2. import (
  3. "errors"
  4. "github.com/gravitl/netmaker/netclient/command"
  5. "github.com/gravitl/netmaker/netclient/config"
  6. "github.com/urfave/cli/v2"
  7. "log"
  8. "os"
  9. "os/exec"
  10. "strconv"
  11. )
  12. func main() {
  13. app := cli.NewApp()
  14. app.Name = "Netclient CLI"
  15. app.Usage = "Netmaker's netclient agent and CLI. Used to perform interactions with Netmaker server and set local WireGuard config."
  16. app.Version = "v0.5.11"
  17. cliFlags := []cli.Flag{
  18. &cli.StringFlag{
  19. Name: "network",
  20. Aliases: []string{"n"},
  21. EnvVars: []string{"NETCLIENT_NETWORK"},
  22. Value: "all",
  23. Usage: "Network to perform specified action against.",
  24. },
  25. &cli.StringFlag{
  26. Name: "password",
  27. Aliases: []string{"p"},
  28. EnvVars: []string{"NETCLIENT_PASSWORD"},
  29. Value: "badpassword",
  30. Usage: "Password for authenticating with netmaker.",
  31. },
  32. &cli.StringFlag{
  33. Name: "endpoint",
  34. Aliases: []string{"e"},
  35. EnvVars: []string{"NETCLIENT_ENDPOINT"},
  36. Value: "",
  37. Usage: "Reachable (usually public) address for WireGuard (not the private WG address).",
  38. },
  39. &cli.StringFlag{
  40. Name: "macaddress",
  41. Aliases: []string{"m"},
  42. EnvVars: []string{"NETCLIENT_MACADDRESS"},
  43. Value: "",
  44. Usage: "Mac Address for this machine. Used as a unique identifier within Netmaker network.",
  45. },
  46. &cli.StringFlag{
  47. Name: "publickey",
  48. Aliases: []string{"pubkey"},
  49. EnvVars: []string{"NETCLIENT_PUBLICKEY"},
  50. Value: "",
  51. Usage: "Public Key for WireGuard Interface.",
  52. },
  53. &cli.StringFlag{
  54. Name: "privatekey",
  55. Aliases: []string{"privkey"},
  56. EnvVars: []string{"NETCLIENT_PRIVATEKEY"},
  57. Value: "",
  58. Usage: "Private Key for WireGuard Interface.",
  59. },
  60. &cli.StringFlag{
  61. Name: "port",
  62. EnvVars: []string{"NETCLIENT_PORT"},
  63. Value: "",
  64. Usage: "Port for WireGuard Interface.",
  65. },
  66. &cli.IntFlag{
  67. Name: "keepalive",
  68. EnvVars: []string{"NETCLIENT_KEEPALIVE"},
  69. Value: 0,
  70. Usage: "Default PersistentKeepAlive for Peers in WireGuard Interface.",
  71. },
  72. &cli.StringFlag{
  73. Name: "operatingsystem",
  74. Aliases: []string{"os"},
  75. EnvVars: []string{"NETCLIENT_OS"},
  76. Value: "",
  77. Usage: "Identifiable name for machine within Netmaker network.",
  78. },
  79. &cli.StringFlag{
  80. Name: "name",
  81. EnvVars: []string{"NETCLIENT_NAME"},
  82. Value: "",
  83. Usage: "Identifiable name for machine within Netmaker network.",
  84. },
  85. &cli.StringFlag{
  86. Name: "localaddress",
  87. EnvVars: []string{"NETCLIENT_LOCALADDRESS"},
  88. Value: "",
  89. Usage: "Local address for machine. Can be used in place of Endpoint for machines on the same LAN.",
  90. },
  91. &cli.StringFlag{
  92. Name: "address",
  93. Aliases: []string{"a"},
  94. EnvVars: []string{"NETCLIENT_ADDRESS"},
  95. Value: "",
  96. Usage: "WireGuard address for machine within Netmaker network.",
  97. },
  98. &cli.StringFlag{
  99. Name: "addressIPv6",
  100. Aliases: []string{"a6"},
  101. EnvVars: []string{"NETCLIENT_ADDRESSIPV6"},
  102. Value: "",
  103. Usage: "WireGuard address for machine within Netmaker network.",
  104. },
  105. &cli.StringFlag{
  106. Name: "interface",
  107. Aliases: []string{"i"},
  108. EnvVars: []string{"NETCLIENT_INTERFACE"},
  109. Value: "",
  110. Usage: "WireGuard local network interface name.",
  111. },
  112. &cli.StringFlag{
  113. Name: "apiserver",
  114. EnvVars: []string{"NETCLIENT_API_SERVER"},
  115. Value: "",
  116. Usage: "Address + GRPC Port (e.g. 1.2.3.4:50051) of Netmaker server.",
  117. },
  118. &cli.StringFlag{
  119. Name: "grpcserver",
  120. EnvVars: []string{"NETCLIENT_GRPC_SERVER"},
  121. Value: "",
  122. Usage: "Address + API Port (e.g. 1.2.3.4:8081) of Netmaker server.",
  123. },
  124. &cli.StringFlag{
  125. Name: "key",
  126. Aliases: []string{"k"},
  127. EnvVars: []string{"NETCLIENT_ACCESSKEY"},
  128. Value: "",
  129. Usage: "Access Key for signing up machine with Netmaker server during initial 'add'.",
  130. },
  131. &cli.StringFlag{
  132. Name: "token",
  133. Aliases: []string{"t"},
  134. EnvVars: []string{"NETCLIENT_ACCESSTOKEN"},
  135. Value: "",
  136. Usage: "Access Token for signing up machine with Netmaker server during initial 'add'.",
  137. },
  138. &cli.StringFlag{
  139. Name: "localrange",
  140. EnvVars: []string{"NETCLIENT_LOCALRANGE"},
  141. Value: "",
  142. Usage: "Local Range if network is local, for instance 192.168.1.0/24.",
  143. },
  144. &cli.StringFlag{
  145. Name: "dns",
  146. EnvVars: []string{"NETCLIENT_DNS"},
  147. Value: "on",
  148. Usage: "Sets private dns if 'on'. Ignores if 'off'. Will retrieve from network if unset.",
  149. },
  150. &cli.StringFlag{
  151. Name: "islocal",
  152. EnvVars: []string{"NETCLIENT_IS_LOCAL"},
  153. Value: "",
  154. Usage: "Sets endpoint to local address if 'yes'. Ignores if 'no'. Will retrieve from network if unset.",
  155. },
  156. &cli.StringFlag{
  157. Name: "isdualstack",
  158. EnvVars: []string{"NETCLIENT_IS_DUALSTACK"},
  159. Value: "",
  160. Usage: "Sets ipv6 address if 'yes'. Ignores if 'no'. Will retrieve from network if unset.",
  161. },
  162. &cli.StringFlag{
  163. Name: "ipforwarding",
  164. EnvVars: []string{"NETCLIENT_IPFORWARDING"},
  165. Value: "on",
  166. Usage: "Sets ip forwarding on if 'on'. Ignores if 'off'. On by default.",
  167. },
  168. &cli.StringFlag{
  169. Name: "postup",
  170. EnvVars: []string{"NETCLIENT_POSTUP"},
  171. Value: "",
  172. Usage: "Sets PostUp command for WireGuard.",
  173. },
  174. &cli.StringFlag{
  175. Name: "postdown",
  176. EnvVars: []string{"NETCLIENT_POSTDOWN"},
  177. Value: "",
  178. Usage: "Sets PostDown command for WireGuard.",
  179. },
  180. &cli.StringFlag{
  181. Name: "daemon",
  182. EnvVars: []string{"NETCLIENT_DAEMON"},
  183. Value: "on",
  184. Usage: "Installs daemon if 'on'. Ignores if 'off'. On by default.",
  185. },
  186. &cli.StringFlag{
  187. Name: "roaming",
  188. EnvVars: []string{"NETCLIENT_ROAMING"},
  189. Value: "on",
  190. Usage: "Checks for IP changes if 'on'. Ignores if 'off'. On by default.",
  191. },
  192. }
  193. app.Commands = []*cli.Command{
  194. {
  195. Name: "register",
  196. Usage: "Register with Netmaker Server for secure GRPC communications.",
  197. Flags: cliFlags,
  198. Action: func(c *cli.Context) error {
  199. cfg, err := config.GetCLIConfigRegister(c)
  200. if err != nil {
  201. return err
  202. }
  203. if cfg.GRPCWireGuard == "off" {
  204. log.Println("Server is not using WireGuard to secure GRPC. Skipping.")
  205. return err
  206. }
  207. if cfg.Client.ServerPrivateAddress == "" {
  208. err = errors.New("No server address provided.")
  209. return err
  210. }
  211. err = command.Register(cfg)
  212. return err
  213. },
  214. },
  215. {
  216. Name: "join",
  217. Usage: "Join a Netmaker network.",
  218. Flags: cliFlags,
  219. Action: func(c *cli.Context) error {
  220. cfg, err := config.GetCLIConfig(c)
  221. if err != nil {
  222. return err
  223. }
  224. if cfg.Network == "all" {
  225. err = errors.New("No network provided.")
  226. return err
  227. }
  228. if cfg.Server.GRPCAddress == "" {
  229. err = errors.New("No server address provided.")
  230. return err
  231. }
  232. err = command.Join(cfg)
  233. return err
  234. },
  235. },
  236. {
  237. Name: "leave",
  238. Usage: "Leave a Netmaker network.",
  239. Flags: cliFlags,
  240. // the action, or code that will be executed when
  241. // we execute our `ns` command
  242. Action: func(c *cli.Context) error {
  243. cfg, err := config.GetCLIConfig(c)
  244. if err != nil {
  245. return err
  246. }
  247. err = command.Leave(cfg)
  248. return err
  249. },
  250. },
  251. {
  252. Name: "checkin",
  253. Usage: "Checks for local changes and then checks into the specified Netmaker network to ask about remote changes.",
  254. Flags: cliFlags,
  255. // the action, or code that will be executed when
  256. // we execute our `ns` command
  257. Action: func(c *cli.Context) error {
  258. cfg, err := config.GetCLIConfig(c)
  259. if err != nil {
  260. return err
  261. }
  262. err = command.CheckIn(cfg)
  263. return err
  264. },
  265. },
  266. {
  267. Name: "push",
  268. Usage: "Push configuration changes to server.",
  269. Flags: cliFlags,
  270. // the action, or code that will be executed when
  271. // we execute our `ns` command
  272. Action: func(c *cli.Context) error {
  273. cfg, err := config.GetCLIConfig(c)
  274. if err != nil {
  275. return err
  276. }
  277. err = command.Push(cfg)
  278. return err
  279. },
  280. },
  281. {
  282. Name: "pull",
  283. Usage: "Pull latest configuration and peers from server.",
  284. Flags: cliFlags,
  285. // the action, or code that will be executed when
  286. // we execute our `ns` command
  287. Action: func(c *cli.Context) error {
  288. cfg, err := config.GetCLIConfig(c)
  289. if err != nil {
  290. return err
  291. }
  292. err = command.Pull(cfg)
  293. return err
  294. },
  295. },
  296. {
  297. Name: "list",
  298. Usage: "Get list of networks.",
  299. Flags: cliFlags,
  300. // the action, or code that will be executed when
  301. // we execute our `ns` command
  302. Action: func(c *cli.Context) error {
  303. cfg, err := config.GetCLIConfig(c)
  304. if err != nil {
  305. return err
  306. }
  307. err = command.List(cfg)
  308. return err
  309. },
  310. },
  311. {
  312. Name: "uninstall",
  313. Usage: "Uninstall the netclient system service.",
  314. Flags: cliFlags,
  315. // the action, or code that will be executed when
  316. // we execute our `ns` command
  317. Action: func(c *cli.Context) error {
  318. cfg, err := config.ReadGlobalConfig()
  319. if err != nil {
  320. return err
  321. }
  322. var gconf config.GlobalConfig
  323. gconf = *cfg
  324. err = command.Uninstall(gconf)
  325. return err
  326. },
  327. },
  328. {
  329. Name: "unregister",
  330. Usage: "Unregister the netclient from secure server GRPC.",
  331. Flags: cliFlags,
  332. // the action, or code that will be executed when
  333. // we execute our `ns` command
  334. Action: func(c *cli.Context) error {
  335. cfg, err := config.ReadGlobalConfig()
  336. if err != nil {
  337. return err
  338. }
  339. var gconf config.GlobalConfig
  340. gconf = *cfg
  341. err = command.Unregister(gconf)
  342. return err
  343. },
  344. },
  345. }
  346. // start our application
  347. getID := exec.Command("id", "-u")
  348. out, err := getID.Output()
  349. if err != nil {
  350. log.Fatal(err)
  351. }
  352. id, err := strconv.Atoi(string(out[:len(out)-1]))
  353. if err != nil {
  354. log.Fatal(err)
  355. }
  356. if id != 0 {
  357. log.Fatal("This program must be run with elevated privileges (sudo). This program installs a SystemD service and configures WireGuard and networking rules. Please re-run with sudo/root.")
  358. }
  359. _, err = exec.LookPath("wg")
  360. if err != nil {
  361. log.Println(err)
  362. log.Fatal("WireGuard not installed. Please install WireGuard (wireguard-tools) and try again.")
  363. }
  364. err = app.Run(os.Args)
  365. if err != nil {
  366. log.Fatal(err)
  367. }
  368. }