action_user.go 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. package main
  2. import (
  3. "context"
  4. "fmt"
  5. "net"
  6. "net/url"
  7. "os"
  8. "time"
  9. "github.com/Sirupsen/logrus"
  10. "github.com/cad/ovpm"
  11. "github.com/cad/ovpm/api/pb"
  12. "github.com/cad/ovpm/errors"
  13. humanize "github.com/dustin/go-humanize"
  14. "github.com/olekukonko/tablewriter"
  15. )
  16. // userListAction lists existing VPN users on the terminal.
  17. //
  18. // List includes additional information about users in addition to usernames
  19. // such as; their IP addresses, the time the user is created at etc...
  20. func userListAction(rpcServURLStr string) error {
  21. // Parse RPC Server's URL.
  22. rpcSrvURL, err := url.Parse(rpcServURLStr)
  23. if err != nil {
  24. return errors.BadURL(rpcServURLStr, err)
  25. }
  26. // Create a gRPC connection to the server.
  27. rpcConn, err := grpcConnect(rpcSrvURL)
  28. if err != nil {
  29. exit(1)
  30. return err
  31. }
  32. defer rpcConn.Close()
  33. // Get services.
  34. var userSvc = pb.NewUserServiceClient(rpcConn)
  35. var vpnSvc = pb.NewVPNServiceClient(rpcConn)
  36. // Request vpn status and user list from the services.
  37. vpnStatusResp, err := vpnSvc.Status(context.Background(), &pb.VPNStatusRequest{})
  38. if err != nil {
  39. err := errors.UnknownGRPCError(err)
  40. exit(1)
  41. return err
  42. }
  43. userListResp, err := userSvc.List(context.Background(), &pb.UserListRequest{})
  44. if err != nil {
  45. err := errors.UnknownGRPCError(err)
  46. exit(1)
  47. return err
  48. }
  49. // Prepare table data.
  50. header := []string{"#", "username", "ip", "created", "crt", "push gw", "admin"}
  51. rows := [][]string{}
  52. for i, user := range userListResp.Users {
  53. isConnected := " "
  54. if user.IsConnected {
  55. //isConnected = fmt.Sprintf("%s●%s", "\x1b[32m", "\x1b[0m\x1b[0m") // green ascii dot
  56. isConnected = fmt.Sprintf("%s●%s", "", "") // colorless ascii dot
  57. }
  58. static := ""
  59. if user.HostId != 0 {
  60. static = "s"
  61. }
  62. isAdmin := "✘"
  63. if user.IsAdmin {
  64. isAdmin = "✔"
  65. }
  66. isValidCRT := "✘"
  67. if user.ServerSerialNumber == vpnStatusResp.SerialNumber {
  68. isValidCRT = "✔"
  69. }
  70. isPushGW := "✘"
  71. if !user.NoGw {
  72. isPushGW = "✔"
  73. }
  74. createdAt := user.CreatedAt
  75. if t, err := time.Parse(time.RFC3339, user.CreatedAt); err == nil {
  76. createdAt = humanize.Time(t)
  77. }
  78. row := []string{
  79. fmt.Sprintf("%v", i+1),
  80. isConnected + " " + user.Username,
  81. fmt.Sprintf("%s %s", user.IpNet, static),
  82. createdAt,
  83. isValidCRT,
  84. isPushGW,
  85. isAdmin,
  86. }
  87. rows = append(rows, row)
  88. }
  89. // Draw the table on the terminal.
  90. table := tablewriter.NewWriter(os.Stdout)
  91. table.SetHeader(header)
  92. table.AppendBulk(rows)
  93. table.Render()
  94. return nil
  95. }
  96. // userCreateAction creates a new VPN user from the terminal.
  97. func userCreateAction(rpcSrvURLStr string, username string, password string, ipAddr *net.IP, noGW bool, isAdmin bool) error {
  98. // Parse RPC Server's URL.
  99. rpcSrvURL, err := url.Parse(rpcSrvURLStr)
  100. if err != nil {
  101. return errors.BadURL(rpcSrvURLStr, err)
  102. }
  103. // Create a gRPC connection to the server.
  104. rpcConn, err := grpcConnect(rpcSrvURL)
  105. if err != nil {
  106. exit(1)
  107. return err
  108. }
  109. defer rpcConn.Close()
  110. // hostid is the integer representation of an IPv4 address.
  111. // OVPM uses it to send, receive and persist IP addresses instead of
  112. // sending dotted string representation.
  113. //
  114. // If it is 0, that means no IP address is set.
  115. var hostid uint32
  116. // Determine the hostid according to the provided ipAddr.
  117. if ipAddr != nil {
  118. hostid = ovpm.IP2HostID(ipAddr.To4())
  119. if hostid == 0 {
  120. // hostid being 0 means dynamic ip addr(no static ip address provided),
  121. // hence ambiguous meaning here.
  122. // This is perceived as an error.
  123. return errors.ConflictingDemands("hostid is 0, but user is trying to allocate a static ip addr")
  124. }
  125. }
  126. // Prepare a service caller.
  127. var userSvc = pb.NewUserServiceClient(rpcConn)
  128. // Send a user creation request to the server.
  129. userCreateResp, err := userSvc.Create(context.Background(), &pb.UserCreateRequest{
  130. Username: username,
  131. Password: password,
  132. NoGw: noGW,
  133. HostId: hostid,
  134. IsAdmin: isAdmin,
  135. })
  136. if err != nil {
  137. err := errors.UnknownGRPCError(err)
  138. exit(1)
  139. return err
  140. }
  141. logrus.Infof("user created: %s", userCreateResp.Users[0].Username)
  142. return nil
  143. }
  144. // userUpdateAction creates a new VPN user from the terminal.
  145. func userUpdateAction(rpcSrvURLStr string, username string, password *string, ipAddr *net.IP, isStatic *bool, noGW *bool, isAdmin *bool) error {
  146. // Parse RPC Server's URL.
  147. rpcSrvURL, err := url.Parse(rpcSrvURLStr)
  148. if err != nil {
  149. return errors.BadURL(rpcSrvURLStr, err)
  150. }
  151. // Create a gRPC connection to the server.
  152. rpcConn, err := grpcConnect(rpcSrvURL)
  153. if err != nil {
  154. exit(1)
  155. return err
  156. }
  157. defer rpcConn.Close()
  158. // Set target password.
  159. targetPassword := ""
  160. if password != nil {
  161. targetPassword = *password
  162. }
  163. // Set targeted static IP addr.
  164. targetHostid := uint32(0)
  165. targetStaticPref := pb.UserUpdateRequest_NOPREFSTATIC
  166. if isStatic != nil {
  167. if *isStatic {
  168. targetHostid = ovpm.IP2HostID(ipAddr.To4())
  169. if targetHostid == 0 {
  170. // hostid being 0 means dynamic ip addr(no static ip address provided),
  171. // hence ambiguous meaning here.
  172. // This is perceived as an error.
  173. return errors.ConflictingDemands("hostid is 0, but user is trying to allocate a static ip addr")
  174. }
  175. targetStaticPref = pb.UserUpdateRequest_STATIC
  176. } else {
  177. targetStaticPref = pb.UserUpdateRequest_NOSTATIC
  178. }
  179. }
  180. // Set targeted gwPref.
  181. targetGWPref := pb.UserUpdateRequest_NOPREF
  182. if noGW != nil {
  183. if *noGW {
  184. targetGWPref = pb.UserUpdateRequest_NOGW
  185. } else {
  186. targetGWPref = pb.UserUpdateRequest_GW
  187. }
  188. }
  189. // Set targeted adminPref.
  190. targetAdminPref := pb.UserUpdateRequest_NOPREFADMIN
  191. if isAdmin != nil {
  192. if *isAdmin {
  193. targetAdminPref = pb.UserUpdateRequest_ADMIN
  194. } else {
  195. targetAdminPref = pb.UserUpdateRequest_NOADMIN
  196. }
  197. }
  198. // Prepare a service caller.
  199. var userSvc = pb.NewUserServiceClient(rpcConn)
  200. // Send a user update request to the server.
  201. userUpdateResp, err := userSvc.Update(context.Background(), &pb.UserUpdateRequest{
  202. Username: username,
  203. Password: targetPassword,
  204. Gwpref: targetGWPref,
  205. StaticPref: targetStaticPref,
  206. HostId: targetHostid,
  207. AdminPref: targetAdminPref,
  208. })
  209. if err != nil {
  210. err := errors.UnknownGRPCError(err)
  211. exit(1)
  212. return err
  213. }
  214. logrus.Infof("user updated: %s", userUpdateResp.Users[0].Username)
  215. return nil
  216. }
  217. // userDeleteAction deletes a VPN user.
  218. func userDeleteAction(rpcSrvURLStr string, username string) error {
  219. // Parse RPC Server's URL.
  220. rpcSrvURL, err := url.Parse(rpcSrvURLStr)
  221. if err != nil {
  222. return errors.BadURL(rpcSrvURLStr, err)
  223. }
  224. // Create a gRPC connection to the server.
  225. rpcConn, err := grpcConnect(rpcSrvURL)
  226. if err != nil {
  227. exit(1)
  228. return err
  229. }
  230. defer rpcConn.Close()
  231. // Prepare a service caller.
  232. var userSvc = pb.NewUserServiceClient(rpcConn)
  233. // Send a user delete request to the server.
  234. userDeleteRequest, err := userSvc.Delete(context.Background(), &pb.UserDeleteRequest{Username: username})
  235. if err != nil {
  236. err := errors.UnknownGRPCError(err)
  237. exit(1)
  238. return err
  239. }
  240. logrus.Infof("user deleted: %s", userDeleteRequest.Users[0].Username)
  241. return nil
  242. }
  243. // userRenewAction renews a VPN user.
  244. func userRenewAction(rpcSrvURLStr string, username string) error {
  245. // Parse RPC Server's URL.
  246. rpcSrvURL, err := url.Parse(rpcSrvURLStr)
  247. if err != nil {
  248. return errors.BadURL(rpcSrvURLStr, err)
  249. }
  250. // Create a gRPC connection to the server.
  251. rpcConn, err := grpcConnect(rpcSrvURL)
  252. if err != nil {
  253. exit(1)
  254. return err
  255. }
  256. defer rpcConn.Close()
  257. // Prepare a service caller.
  258. var userSvc = pb.NewUserServiceClient(rpcConn)
  259. // Send a user renew request to the server.
  260. userRenewResp, err := userSvc.Renew(context.Background(), &pb.UserRenewRequest{Username: username})
  261. if err != nil {
  262. err := errors.UnknownGRPCError(err)
  263. exit(1)
  264. return err
  265. }
  266. logrus.Infof("user renewed: %s", userRenewResp.Users[0].Username)
  267. return nil
  268. }
  269. // userGenconfigAction generates ovpn configs for a VPN user.
  270. func userGenconfigAction(rpcSrvURLStr string, username string, outPath *string) error {
  271. // Parse RPC Server's URL.
  272. rpcSrvURL, err := url.Parse(rpcSrvURLStr)
  273. if err != nil {
  274. return errors.BadURL(rpcSrvURLStr, err)
  275. }
  276. // Create a gRPC connection to the server.
  277. rpcConn, err := grpcConnect(rpcSrvURL)
  278. if err != nil {
  279. exit(1)
  280. return err
  281. }
  282. defer rpcConn.Close()
  283. // If no outPath is provided, then use the default one with
  284. // the username.
  285. if outPath == nil {
  286. tmp := fmt.Sprintf("%s.ovpn", username)
  287. outPath = &tmp
  288. }
  289. // Prepare a service caller.
  290. var userSvc = pb.NewUserServiceClient(rpcConn)
  291. // Send a user genconfig request to the server.
  292. userGenconfigResp, err := userSvc.GenConfig(context.Background(), &pb.UserGenConfigRequest{Username: username})
  293. if err != nil {
  294. err := errors.UnknownGRPCError(err)
  295. exit(1)
  296. return err
  297. }
  298. // Write out the contents of the vpn profile
  299. // to the filesystem.
  300. if err := emitToFile(*outPath, userGenconfigResp.ClientConfig, 0); err != nil {
  301. err := errors.UnknownFileIOError(err)
  302. exit(1)
  303. return err
  304. }
  305. logrus.Infof("exported to %s", *outPath)
  306. return nil
  307. }