accesskeys.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. package logic
  2. import (
  3. "crypto/rand"
  4. "encoding/base64"
  5. "encoding/json"
  6. "errors"
  7. "math/big"
  8. "strings"
  9. "sync"
  10. "github.com/go-playground/validator/v10"
  11. "github.com/gravitl/netmaker/database"
  12. "github.com/gravitl/netmaker/logger"
  13. "github.com/gravitl/netmaker/models"
  14. "github.com/gravitl/netmaker/servercfg"
  15. )
  16. const (
  17. charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
  18. )
  19. // CreateAccessKey - create access key
  20. func CreateAccessKey(accesskey models.AccessKey, network models.Network) (models.AccessKey, error) {
  21. if accesskey.Name == "" {
  22. accesskey.Name = genKeyName()
  23. }
  24. if accesskey.Value == "" {
  25. accesskey.Value = GenKey()
  26. }
  27. if accesskey.Uses == 0 {
  28. accesskey.Uses = 1
  29. }
  30. checkkeys, err := GetKeys(network.NetID)
  31. if err != nil {
  32. return models.AccessKey{}, errors.New("could not retrieve network keys")
  33. }
  34. for _, key := range checkkeys {
  35. if key.Name == accesskey.Name {
  36. return models.AccessKey{}, errors.New("duplicate AccessKey Name")
  37. }
  38. }
  39. privAddr := ""
  40. if network.IsLocal != "" {
  41. privAddr = network.LocalRange
  42. }
  43. netID := network.NetID
  44. var accessToken models.AccessToken
  45. s := servercfg.GetServerConfig()
  46. servervals := models.ServerConfig{
  47. Server: s.Server,
  48. APIConnString: s.APIConnString,
  49. }
  50. accessToken.ServerConfig = servervals
  51. accessToken.ClientConfig.Network = netID
  52. accessToken.ClientConfig.Key = accesskey.Value
  53. accessToken.ClientConfig.LocalRange = privAddr
  54. tokenjson, err := json.Marshal(accessToken)
  55. if err != nil {
  56. return accesskey, err
  57. }
  58. accesskey.AccessString = base64.StdEncoding.EncodeToString([]byte(tokenjson))
  59. //validate accesskey
  60. v := validator.New()
  61. err = v.Struct(accesskey)
  62. if err != nil {
  63. for _, e := range err.(validator.ValidationErrors) {
  64. logger.Log(1, "validator", e.Error())
  65. }
  66. return models.AccessKey{}, err
  67. }
  68. network.AccessKeys = append(network.AccessKeys, accesskey)
  69. data, err := json.Marshal(&network)
  70. if err != nil {
  71. return models.AccessKey{}, err
  72. }
  73. if err = database.Insert(network.NetID, string(data), database.NETWORKS_TABLE_NAME); err != nil {
  74. return models.AccessKey{}, err
  75. }
  76. return accesskey, nil
  77. }
  78. // DeleteKey - deletes a key
  79. func DeleteKey(keyname, netname string) error {
  80. network, err := GetParentNetwork(netname)
  81. if err != nil {
  82. return err
  83. }
  84. //basically, turn the list of access keys into the list of access keys before and after the item
  85. //have not done any error handling for if there's like...1 item. I think it works? need to test.
  86. found := false
  87. var updatedKeys []models.AccessKey
  88. for _, currentkey := range network.AccessKeys {
  89. if currentkey.Name == keyname {
  90. found = true
  91. } else {
  92. updatedKeys = append(updatedKeys, currentkey)
  93. }
  94. }
  95. if !found {
  96. return errors.New("key " + keyname + " does not exist")
  97. }
  98. network.AccessKeys = updatedKeys
  99. data, err := json.Marshal(&network)
  100. if err != nil {
  101. return err
  102. }
  103. if err := database.Insert(network.NetID, string(data), database.NETWORKS_TABLE_NAME); err != nil {
  104. return err
  105. }
  106. return nil
  107. }
  108. // GetKeys - fetches keys for network
  109. func GetKeys(net string) ([]models.AccessKey, error) {
  110. record, err := database.FetchRecord(database.NETWORKS_TABLE_NAME, net)
  111. if err != nil {
  112. return []models.AccessKey{}, err
  113. }
  114. network, err := ParseNetwork(record)
  115. if err != nil {
  116. return []models.AccessKey{}, err
  117. }
  118. return network.AccessKeys, nil
  119. }
  120. // DecrimentKey - decriments key uses
  121. func DecrimentKey(networkName string, keyvalue string) {
  122. var network models.Network
  123. network, err := GetParentNetwork(networkName)
  124. if err != nil {
  125. return
  126. }
  127. for i := len(network.AccessKeys) - 1; i >= 0; i-- {
  128. currentkey := network.AccessKeys[i]
  129. if currentkey.Value == keyvalue {
  130. network.AccessKeys[i].Uses--
  131. if network.AccessKeys[i].Uses < 1 {
  132. network.AccessKeys = append(network.AccessKeys[:i],
  133. network.AccessKeys[i+1:]...)
  134. break
  135. }
  136. }
  137. }
  138. if newNetworkData, err := json.Marshal(&network); err != nil {
  139. logger.Log(2, "failed to decrement key")
  140. return
  141. } else {
  142. database.Insert(network.NetID, string(newNetworkData), database.NETWORKS_TABLE_NAME)
  143. }
  144. }
  145. // IsKeyValid - check if key is valid
  146. func IsKeyValid(networkname string, keyvalue string) bool {
  147. network, err := GetParentNetwork(networkname)
  148. if err != nil {
  149. return false
  150. }
  151. accesskeys := network.AccessKeys
  152. var key models.AccessKey
  153. foundkey := false
  154. isvalid := false
  155. for i := len(accesskeys) - 1; i >= 0; i-- {
  156. currentkey := accesskeys[i]
  157. if currentkey.Value == keyvalue {
  158. key = currentkey
  159. foundkey = true
  160. }
  161. }
  162. if foundkey {
  163. if key.Uses > 0 {
  164. isvalid = true
  165. }
  166. }
  167. return isvalid
  168. }
  169. // RemoveKeySensitiveInfo - remove sensitive key info
  170. func RemoveKeySensitiveInfo(keys []models.AccessKey) []models.AccessKey {
  171. var returnKeys []models.AccessKey
  172. for _, key := range keys {
  173. key.Value = models.PLACEHOLDER_KEY_TEXT
  174. key.AccessString = models.PLACEHOLDER_TOKEN_TEXT
  175. returnKeys = append(returnKeys, key)
  176. }
  177. return returnKeys
  178. }
  179. const (
  180. maxr string = "ff578f57c15bb743beaa77d27637e02b598dffa9aebd15889187fe6eb3bdca516c3fa1a52eabef31f33b4b8c2e5b5524f1aa4f3329393912f40dbbe23d7f39723e0be05b6696b11f8eea0abe365a11d9f2735ac7e5b4e015ab19b35b84893685b37a9a0a62a566d6571d7e00d4241687f5c804f37cde9bf311c0781f51cc007c5a01a94f6cfcecea640b8e9ab7bd43e73e5df5d0e1eeb4d9b6cc44be67b7cad80808b17869561b579ffe0bbdeca5c83139e458000000000000000000000000000000000000000000000000000000000000000"
  181. )
  182. var (
  183. uno sync.Once
  184. maxentropy *big.Int
  185. )
  186. func init() {
  187. uno.Do(func() {
  188. maxentropy, _ = new(big.Int).SetString(maxr, 16)
  189. })
  190. }
  191. // == private methods ==
  192. func genKeyName() string {
  193. entropy, _ := rand.Int(rand.Reader, maxentropy)
  194. return strings.Join([]string{"key", entropy.Text(16)[:16]}, "-")
  195. }
  196. func GenKey() string {
  197. entropy, _ := rand.Int(rand.Reader, maxentropy)
  198. return entropy.Text(16)[:16]
  199. }
  200. func getAllAccessKeys() []models.AccessKey {
  201. var accesskeys = make([]models.AccessKey, 0)
  202. networks, err := GetNetworks()
  203. if err != nil {
  204. return accesskeys
  205. }
  206. for i := range networks {
  207. accesskeys = append(accesskeys, networks[i].AccessKeys...)
  208. }
  209. return accesskeys
  210. }