github.com/craicoverflow/tyk@v2.9.6-rc3+incompatible/storage/storage.go (about) 1 package storage 2 3 import ( 4 "crypto/sha256" 5 "encoding/base64" 6 "encoding/hex" 7 "errors" 8 "fmt" 9 "hash" 10 "strings" 11 12 "github.com/buger/jsonparser" 13 uuid "github.com/satori/go.uuid" 14 15 "github.com/TykTechnologies/murmur3" 16 "github.com/TykTechnologies/tyk/config" 17 logger "github.com/TykTechnologies/tyk/log" 18 ) 19 20 var log = logger.Get() 21 22 // ErrKeyNotFound is a standard error for when a key is not found in the storage engine 23 var ErrKeyNotFound = errors.New("key not found") 24 25 // Handler is a standard interface to a storage backend, used by 26 // AuthorisationManager to read and write key values to the backend 27 type Handler interface { 28 GetKey(string) (string, error) // Returned string is expected to be a JSON object (user.SessionState) 29 GetMultiKey([]string) ([]string, error) 30 GetRawKey(string) (string, error) 31 SetKey(string, string, int64) error // Second input string is expected to be a JSON object (user.SessionState) 32 SetRawKey(string, string, int64) error 33 SetExp(string, int64) error // Set key expiration 34 GetExp(string) (int64, error) // Returns expiry of a key 35 GetKeys(string) []string 36 DeleteKey(string) bool 37 DeleteAllKeys() bool 38 DeleteRawKey(string) bool 39 Connect() bool 40 GetKeysAndValues() map[string]string 41 GetKeysAndValuesWithFilter(string) map[string]string 42 DeleteKeys([]string) bool 43 Decrement(string) 44 IncrememntWithExpire(string, int64) int64 45 SetRollingWindow(key string, per int64, val string, pipeline bool) (int, []interface{}) 46 GetRollingWindow(key string, per int64, pipeline bool) (int, []interface{}) 47 GetSet(string) (map[string]string, error) 48 AddToSet(string, string) 49 AppendToSetPipelined(string, []string) 50 GetAndDeleteSet(string) []interface{} 51 RemoveFromSet(string, string) 52 DeleteScanMatch(string) bool 53 GetKeyPrefix() string 54 AddToSortedSet(string, string, float64) 55 GetSortedSetRange(string, string, string) ([]string, []float64, error) 56 RemoveSortedSetRange(string, string, string) error 57 GetListRange(string, int64, int64) ([]string, error) 58 RemoveFromList(string, string) error 59 AppendToSet(string, string) 60 Exists(string) (bool, error) 61 } 62 63 const defaultHashAlgorithm = "murmur64" 64 65 // If hashing algorithm is empty, use legacy key generation 66 func GenerateToken(orgID, keyID, hashAlgorithm string) (string, error) { 67 if keyID == "" { 68 keyID = strings.Replace(uuid.NewV4().String(), "-", "", -1) 69 } 70 71 if hashAlgorithm != "" { 72 _, err := hashFunction(hashAlgorithm) 73 if err != nil { 74 hashAlgorithm = defaultHashAlgorithm 75 } 76 77 jsonToken := fmt.Sprintf(`{"org":"%s","id":"%s","h":"%s"}`, orgID, keyID, hashAlgorithm) 78 return base64.StdEncoding.EncodeToString([]byte(jsonToken)), err 79 } 80 81 // Legacy keys 82 return orgID + keyID, nil 83 } 84 85 // `{"` in base64 86 const B64JSONPrefix = "ey" 87 88 func TokenHashAlgo(token string) string { 89 // Legacy tokens not b64 and not JSON records 90 if strings.HasPrefix(token, B64JSONPrefix) { 91 if jsonToken, err := base64.StdEncoding.DecodeString(token); err == nil { 92 hashAlgo, _ := jsonparser.GetString(jsonToken, "h") 93 return hashAlgo 94 } 95 } 96 97 return "" 98 } 99 100 func TokenOrg(token string) string { 101 if strings.HasPrefix(token, B64JSONPrefix) { 102 if jsonToken, err := base64.StdEncoding.DecodeString(token); err == nil { 103 // Checking error in case if it is a legacy tooken which just by accided has the same b64JSON prefix 104 if org, err := jsonparser.GetString(jsonToken, "org"); err == nil { 105 return org 106 } 107 } 108 } 109 110 // 24 is mongo bson id length 111 if len(token) > 24 { 112 return token[:24] 113 } 114 115 return "" 116 } 117 118 var ( 119 HashSha256 = "sha256" 120 HashMurmur32 = "murmur32" 121 HashMurmur64 = "murmur64" 122 HashMurmur128 = "murmur128" 123 ) 124 125 func hashFunction(algorithm string) (hash.Hash, error) { 126 switch algorithm { 127 case HashSha256: 128 return sha256.New(), nil 129 case HashMurmur64: 130 return murmur3.New64(), nil 131 case HashMurmur128: 132 return murmur3.New128(), nil 133 case "", HashMurmur32: 134 return murmur3.New32(), nil 135 default: 136 return murmur3.New32(), fmt.Errorf("Unknown key hash function: %s. Falling back to murmur32.", algorithm) 137 } 138 } 139 140 func HashStr(in string, withAlg ...string) string { 141 var algo string 142 if len(withAlg) > 0 && withAlg[0] != "" { 143 algo = withAlg[0] 144 } else { 145 algo = TokenHashAlgo(in) 146 } 147 148 h, _ := hashFunction(algo) 149 h.Write([]byte(in)) 150 return hex.EncodeToString(h.Sum(nil)) 151 } 152 153 func HashKey(in string) string { 154 if !config.Global().HashKeys { 155 // Not hashing? Return the raw key 156 return in 157 } 158 return HashStr(in) 159 }