github.com/Tyktechnologies/tyk@v2.9.5+incompatible/gateway/auth_manager.go (about) 1 package gateway 2 3 import ( 4 "encoding/base64" 5 "encoding/json" 6 "strings" 7 "sync" 8 "time" 9 10 "github.com/TykTechnologies/tyk/config" 11 "github.com/TykTechnologies/tyk/storage" 12 "github.com/TykTechnologies/tyk/user" 13 uuid "github.com/satori/go.uuid" 14 "github.com/sirupsen/logrus" 15 ) 16 17 // SessionHandler handles all update/create/access session functions and deals exclusively with 18 // user.SessionState objects, not identity 19 type SessionHandler interface { 20 Init(store storage.Handler) 21 Store() storage.Handler 22 UpdateSession(keyName string, session *user.SessionState, resetTTLTo int64, hashed bool) error 23 RemoveSession(keyName string, hashed bool) bool 24 SessionDetail(keyName string, hashed bool) (user.SessionState, bool) 25 KeyExpired(newSession *user.SessionState) bool 26 Sessions(filter string) []string 27 ResetQuota(string, *user.SessionState, bool) 28 Stop() 29 } 30 31 type DefaultSessionManager struct { 32 store storage.Handler 33 orgID string 34 } 35 36 func (b *DefaultSessionManager) Init(store storage.Handler) { 37 b.store = store 38 b.store.Connect() 39 } 40 41 // KeyExpired checks if a key has expired, if the value of user.SessionState.Expires is 0, it will be ignored 42 func (b *DefaultSessionManager) KeyExpired(newSession *user.SessionState) bool { 43 if newSession.Expires >= 1 { 44 return time.Now().After(time.Unix(newSession.Expires, 0)) 45 } 46 return false 47 } 48 49 func (b *DefaultSessionManager) Store() storage.Handler { 50 return b.store 51 } 52 53 func (b *DefaultSessionManager) ResetQuota(keyName string, session *user.SessionState, isHashed bool) { 54 origKeyName := keyName 55 if !isHashed { 56 keyName = storage.HashKey(keyName) 57 } 58 59 rawKey := QuotaKeyPrefix + keyName 60 log.WithFields(logrus.Fields{ 61 "prefix": "auth-mgr", 62 "inbound-key": obfuscateKey(origKeyName), 63 "key": rawKey, 64 }).Info("Reset quota for key.") 65 66 rateLimiterSentinelKey := RateLimitKeyPrefix + keyName + ".BLOCKED" 67 // Clear the rate limiter 68 go b.store.DeleteRawKey(rateLimiterSentinelKey) 69 // Fix the raw key 70 go b.store.DeleteRawKey(rawKey) 71 //go b.store.SetKey(rawKey, "0", session.QuotaRenewalRate) 72 73 for _, acl := range session.GetAccessRights() { 74 rawKey = QuotaKeyPrefix + acl.AllowanceScope + "-" + keyName 75 go b.store.DeleteRawKey(rawKey) 76 } 77 } 78 79 func (b *DefaultSessionManager) clearCacheForKey(keyName string, hashed bool) { 80 cacheKey := keyName 81 if !hashed { 82 cacheKey = storage.HashKey(keyName) 83 } 84 85 // Delete current gateway's cache immediately 86 SessionCache.Delete(cacheKey) 87 88 // Notify gateways in cluster to flush cache 89 n := Notification{ 90 Command: KeySpaceUpdateNotification, 91 Payload: cacheKey, 92 } 93 MainNotifier.Notify(n) 94 } 95 96 // UpdateSession updates the session state in the storage engine 97 func (b *DefaultSessionManager) UpdateSession(keyName string, session *user.SessionState, 98 resetTTLTo int64, hashed bool) error { 99 defer b.clearCacheForKey(keyName, hashed) 100 101 v, err := json.Marshal(session) 102 if err != nil { 103 log.Error("Error marshalling session for sync update") 104 return err 105 } 106 107 // sync update 108 if hashed { 109 keyName = b.store.GetKeyPrefix() + keyName 110 err = b.store.SetRawKey(keyName, string(v), resetTTLTo) 111 } else { 112 err = b.store.SetKey(keyName, string(v), resetTTLTo) 113 } 114 115 return err 116 } 117 118 // RemoveSession removes session from storage 119 func (b *DefaultSessionManager) RemoveSession(keyName string, hashed bool) bool { 120 defer b.clearCacheForKey(keyName, hashed) 121 122 if hashed { 123 return b.store.DeleteRawKey(b.store.GetKeyPrefix() + keyName) 124 } else { 125 // support both old and new key hashing 126 res1 := b.store.DeleteKey(keyName) 127 res2 := b.store.DeleteKey(generateToken(b.orgID, keyName)) 128 return res1 || res2 129 } 130 } 131 132 // SessionDetail returns the session detail using the storage engine (either in memory or Redis) 133 func (b *DefaultSessionManager) SessionDetail(keyName string, hashed bool) (user.SessionState, bool) { 134 var jsonKeyVal string 135 var err error 136 session := user.SessionState{Mutex: &sync.RWMutex{}} 137 // get session by key 138 if hashed { 139 jsonKeyVal, err = b.store.GetRawKey(b.store.GetKeyPrefix() + keyName) 140 } else { 141 if storage.TokenOrg(keyName) != b.orgID { 142 // try to get legacy and new format key at once 143 toSearchList := []string{generateToken(b.orgID, keyName), keyName} 144 for _, fallback := range config.Global().HashKeyFunctionFallback { 145 toSearchList = append(toSearchList, generateToken(b.orgID, keyName, fallback)) 146 } 147 148 var jsonKeyValList []string 149 jsonKeyValList, err = b.store.GetMultiKey(toSearchList) 150 151 // pick the 1st non empty from the returned list 152 for _, val := range jsonKeyValList { 153 if val != "" { 154 jsonKeyVal = val 155 break 156 } 157 } 158 } else { 159 // key is not an imported one 160 jsonKeyVal, err = b.store.GetKey(keyName) 161 } 162 } 163 164 if err != nil { 165 log.WithFields(logrus.Fields{ 166 "prefix": "auth-mgr", 167 "inbound-key": obfuscateKey(keyName), 168 "err": err, 169 }).Debug("Could not get session detail, key not found") 170 return session, false 171 } 172 173 if err := json.Unmarshal([]byte(jsonKeyVal), &session); err != nil { 174 log.Error("Couldn't unmarshal session object (may be cache miss): ", err) 175 return session, false 176 } 177 178 return session, true 179 } 180 181 func (b *DefaultSessionManager) Stop() {} 182 183 // Sessions returns all sessions in the key store that match a filter key (a prefix) 184 func (b *DefaultSessionManager) Sessions(filter string) []string { 185 return b.store.GetKeys(filter) 186 } 187 188 type DefaultKeyGenerator struct{} 189 190 func generateToken(orgID, keyID string, customHashKeyFunction ...string) string { 191 keyID = strings.TrimPrefix(keyID, orgID) 192 hashKeyFunction := config.Global().HashKeyFunction 193 194 if len(customHashKeyFunction) > 0 { 195 hashKeyFunction = customHashKeyFunction[0] 196 } 197 198 token, err := storage.GenerateToken(orgID, keyID, hashKeyFunction) 199 if err != nil { 200 log.WithFields(logrus.Fields{ 201 "prefix": "auth-mgr", 202 "orgID": orgID, 203 }).WithError(err).Warning("Issue during token generation") 204 } 205 206 return token 207 } 208 209 // GenerateAuthKey is a utility function for generating new auth keys. Returns the storage key name and the actual key 210 func (DefaultKeyGenerator) GenerateAuthKey(orgID string) string { 211 return generateToken(orgID, "") 212 } 213 214 // GenerateHMACSecret is a utility function for generating new auth keys. Returns the storage key name and the actual key 215 func (DefaultKeyGenerator) GenerateHMACSecret() string { 216 u5 := uuid.NewV4() 217 cleanSting := strings.Replace(u5.String(), "-", "", -1) 218 return base64.StdEncoding.EncodeToString([]byte(cleanSting)) 219 }