Skip to content

Commit

Permalink
Migrate to GlobalSessionManager (TykTechnologies#2500)
Browse files Browse the repository at this point in the history
This PR:
- Removes `SessionManager` from `APISpec`
- Change `FallbackKeySesionManager` to `GlobalSessionManager`
  • Loading branch information
furkansenharputlu authored and buger committed Nov 7, 2019
1 parent 861856e commit 37fb753
Show file tree
Hide file tree
Showing 21 changed files with 163 additions and 214 deletions.
163 changes: 65 additions & 98 deletions gateway/api.go

Large diffs are not rendered by default.

6 changes: 0 additions & 6 deletions gateway/api_definition.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,6 @@ type APISpec struct {
WhiteListEnabled map[string]bool
target *url.URL
AuthManager AuthorisationHandler
SessionManager SessionHandler
OAuthManager *OAuthManager
OrgSessionManager SessionHandler
EventPaths map[apidef.TykEvent][]config.TykEventHandler
Expand Down Expand Up @@ -273,9 +272,6 @@ func (a APIDefinitionLoader) MakeSpec(def *apidef.APIDefinition, logger *logrus.
// Add any new session managers or auth handlers here
spec.AuthManager = &DefaultAuthorisationManager{}

spec.SessionManager = &DefaultSessionManager{
orgID: spec.OrgID,
}
spec.OrgSessionManager = &DefaultSessionManager{
orgID: spec.OrgID,
}
Expand Down Expand Up @@ -949,13 +945,11 @@ func (a APIDefinitionLoader) getExtendedPathSpecs(apiVersionDef apidef.VersionIn

func (a *APISpec) Init(authStore, sessionStore, healthStore, orgStore storage.Handler) {
a.AuthManager.Init(authStore)
a.SessionManager.Init(sessionStore)
a.Health.Init(healthStore)
a.OrgSessionManager.Init(orgStore)
}

func (a *APISpec) StopSessionManagerPool() {
a.SessionManager.Stop()
a.OrgSessionManager.Stop()
}

Expand Down
2 changes: 1 addition & 1 deletion gateway/api_loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func prepareStorage() generalStores {
gs.healthStore = &storage.RedisCluster{KeyPrefix: "apihealth."}
gs.rpcAuthStore = &RPCStorageHandler{KeyPrefix: "apikey-", HashKeys: config.Global().HashKeys}
gs.rpcOrgStore = &RPCStorageHandler{KeyPrefix: "orgkey."}
FallbackKeySesionManager.Init(gs.redisStore)
GlobalSessionManager.Init(gs.redisStore)
return gs
}

Expand Down
21 changes: 8 additions & 13 deletions gateway/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import (

"fmt"

"github.com/TykTechnologies/tyk/apidef"
"github.com/TykTechnologies/tyk/config"
"github.com/TykTechnologies/tyk/storage"
"github.com/TykTechnologies/tyk/test"
Expand All @@ -42,14 +41,10 @@ const apiTestDef = `{
}
}`

func loadSampleAPI(t *testing.T, def string) {
spec := CreateSpecTest(t, def)
func loadSampleAPI(def string) (spec *APISpec) {
spec = CreateDefinitionFromString(def)
loadApps([]*APISpec{spec})
}

type testAPIDefinition struct {
apidef.APIDefinition
ID string `json:"id"`
return
}

func TestHealthCheckEndpoint(t *testing.T) {
Expand Down Expand Up @@ -247,7 +242,7 @@ func TestKeyHandler(t *testing.T) {
},
}...)

FallbackKeySesionManager.Store().DeleteAllKeys()
GlobalSessionManager.Store().DeleteAllKeys()
})

_, knownKey := ts.CreateSession(func(s *user.SessionState) {
Expand Down Expand Up @@ -372,7 +367,7 @@ func TestKeyHandler_UpdateKey(t *testing.T) {
{Method: http.MethodPut, Path: path, Data: sessionData, AdminAuth: true, Code: 200},
}...)

sessionState, found := FallbackKeySesionManager.SessionDetail(key, false)
sessionState, found := GlobalSessionManager.SessionDetail("default", key, false)
if !found || sessionState.AccessRights[testAPIID].APIID != testAPIID || len(sessionState.ApplyPolicies) != 2 {
t.Fatal("Adding policy to the list failed")
}
Expand All @@ -387,7 +382,7 @@ func TestKeyHandler_UpdateKey(t *testing.T) {
{Method: http.MethodPut, Path: path, Data: sessionData, AdminAuth: true, Code: 200},
}...)

sessionState, found := FallbackKeySesionManager.SessionDetail(key, false)
sessionState, found := GlobalSessionManager.SessionDetail("default", key, false)
if !found || sessionState.AccessRights[testAPIID].APIID != testAPIID || len(sessionState.ApplyPolicies) != 0 {
t.Fatal("Removing policy from the list failed")
}
Expand All @@ -402,7 +397,7 @@ func TestKeyHandler_UpdateKey(t *testing.T) {
{Method: http.MethodPut, Path: path, Data: sessionData, AdminAuth: true, Code: 200},
}...)

sessionState, found := FallbackKeySesionManager.SessionDetail(key, false)
sessionState, found := GlobalSessionManager.SessionDetail(session.OrgID, key, false)

sort.Strings(sessionState.Tags)
sort.Strings(expected)
Expand Down Expand Up @@ -1174,7 +1169,7 @@ func TestGroupResetHandler(t *testing.T) {
apisByID = make(map[string]*APISpec)
apisMu.Unlock()

loadSampleAPI(t, apiTestDef)
loadSampleAPI(apiTestDef)

recorder := httptest.NewRecorder()

Expand Down
14 changes: 7 additions & 7 deletions gateway/auth_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ type AuthorisationHandler interface {
type SessionHandler interface {
Init(store storage.Handler)
UpdateSession(keyName string, session *user.SessionState, resetTTLTo int64, hashed bool) error
RemoveSession(keyName string, hashed bool) bool
SessionDetail(keyName string, hashed bool) (user.SessionState, bool)
RemoveSession(orgID string, keyName string, hashed bool) bool
SessionDetail(orgID string, keyName string, hashed bool) (user.SessionState, bool)
Sessions(filter string) []string
Store() storage.Handler
ResetQuota(string, *user.SessionState, bool)
Expand Down Expand Up @@ -263,21 +263,21 @@ func (b *DefaultSessionManager) UpdateSession(keyName string, session *user.Sess
}

// RemoveSession removes session from storage
func (b *DefaultSessionManager) RemoveSession(keyName string, hashed bool) bool {
func (b *DefaultSessionManager) RemoveSession(orgID string, keyName string, hashed bool) bool {
defer b.clearCacheForKey(keyName, hashed)

if hashed {
return b.store.DeleteRawKey(b.store.GetKeyPrefix() + keyName)
} else {
// support both old and new key hashing
res1 := b.store.DeleteKey(keyName)
res2 := b.store.DeleteKey(generateToken(b.orgID, keyName))
res2 := b.store.DeleteKey(generateToken(orgID, keyName))
return res1 || res2
}
}

// SessionDetail returns the session detail using the storage engine (either in memory or Redis)
func (b *DefaultSessionManager) SessionDetail(keyName string, hashed bool) (user.SessionState, bool) {
func (b *DefaultSessionManager) SessionDetail(orgID string, keyName string, hashed bool) (user.SessionState, bool) {
var jsonKeyVal string
var err error
var session user.SessionState
Expand All @@ -286,12 +286,12 @@ func (b *DefaultSessionManager) SessionDetail(keyName string, hashed bool) (user
if hashed {
jsonKeyVal, err = b.store.GetRawKey(b.store.GetKeyPrefix() + keyName)
} else {
if storage.TokenOrg(keyName) != b.orgID {
if storage.TokenOrg(keyName) != orgID {
// try to get legacy and new format key at once
var jsonKeyValList []string
jsonKeyValList, err = b.store.GetMultiKey(
[]string{
generateToken(b.orgID, keyName),
generateToken(orgID, keyName),
keyName,
},
)
Expand Down
4 changes: 2 additions & 2 deletions gateway/auth_manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func TestAuthenticationAfterUpdateKey(t *testing.T) {
APIID: api.APIID,
}}

FallbackKeySesionManager.UpdateSession(storage.HashKey(key), session, 0, config.Global().HashKeys)
GlobalSessionManager.UpdateSession(storage.HashKey(key), session, 0, config.Global().HashKeys)

authHeader := map[string]string{
"authorization": key,
Expand All @@ -86,7 +86,7 @@ func TestAuthenticationAfterUpdateKey(t *testing.T) {
APIID: "dummy",
}}

FallbackKeySesionManager.UpdateSession(storage.HashKey(key), session, 0, config.Global().HashKeys)
GlobalSessionManager.UpdateSession(storage.HashKey(key), session, 0, config.Global().HashKeys)

ts.Run(t, []test.TestCase{
{Path: "/get", Headers: authHeader, Code: http.StatusForbidden},
Expand Down
4 changes: 2 additions & 2 deletions gateway/gateway_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1545,13 +1545,13 @@ func TestRateLimitForAPIAndRateLimitAndQuotaCheck(t *testing.T) {
s.Rate = 1
s.Per = 60
})
defer FallbackKeySesionManager.RemoveSession(sess1token, false)
defer GlobalSessionManager.RemoveSession("default", sess1token, false)

sess2token := CreateSession(func(s *user.SessionState) {
s.Rate = 1
s.Per = 60
})
defer FallbackKeySesionManager.RemoveSession(sess2token, false)
defer GlobalSessionManager.RemoveSession("default", sess2token, false)

ts.Run(t, []test.TestCase{
{Headers: map[string]string{"Authorization": sess1token}, Code: http.StatusOK, Path: "/", Delay: 100 * time.Millisecond},
Expand Down
10 changes: 5 additions & 5 deletions gateway/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,17 +214,17 @@ func (t BaseMiddleware) Config() (interface{}, error) {
return nil, nil
}

func (t BaseMiddleware) OrgSession(key string) (user.SessionState, bool) {
func (t BaseMiddleware) OrgSession(orgID string) (user.SessionState, bool) {
// Try and get the session from the session store
session, found := t.Spec.OrgSessionManager.SessionDetail(key, false)
session, found := t.Spec.OrgSessionManager.SessionDetail(orgID, orgID, false)
if found && t.Spec.GlobalConfig.EnforceOrgDataAge {
// If exists, assume it has been authorized and pass on
// We cache org expiry data
t.Logger().Debug("Setting data expiry: ", session.OrgID)
ExpiryCache.Set(session.OrgID, session.DataExpires, cache.DefaultExpiration)
}

session.SetKeyHash(storage.HashKey(key))
session.SetKeyHash(storage.HashKey(orgID))
return session, found
}

Expand Down Expand Up @@ -266,7 +266,7 @@ func (t BaseMiddleware) UpdateRequestSession(r *http.Request) bool {
}

lifetime := session.Lifetime(t.Spec.SessionLifetime)
if err := t.Spec.SessionManager.UpdateSession(token, session, lifetime, false); err != nil {
if err := GlobalSessionManager.UpdateSession(token, session, lifetime, false); err != nil {
t.Logger().WithError(err).Error("Can't update session")
return false
}
Expand Down Expand Up @@ -569,7 +569,7 @@ func (t BaseMiddleware) CheckSessionAndIdentityForValidKey(key string, r *http.R

// Check session store
t.Logger().Debug("Querying keystore")
session, found := t.Spec.SessionManager.SessionDetail(key, false)
session, found := GlobalSessionManager.SessionDetail(t.Spec.OrgID, key, false)
if found {
session.SetKeyHash(cacheKey)
// If exists, assume it has been authorized and pass on
Expand Down
2 changes: 1 addition & 1 deletion gateway/middleware_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ var sess = user.SessionState{
DataExpires: 110,
}

func (mockStore) SessionDetail(keyName string, hashed bool) (user.SessionState, bool) {
func (mockStore) SessionDetail(orgID string, keyName string, hashed bool) (user.SessionState, bool) {
return sess, true
}

Expand Down
24 changes: 12 additions & 12 deletions gateway/multiauth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ func getMultiAuthStandardAndBasicAuthChain(spec *APISpec) http.Handler {
}

func testPrepareMultiSessionBA(t testing.TB, isBench bool) (*APISpec, *http.Request) {
spec := CreateSpecTest(t, multiAuthDev)
spec := loadSampleAPI(multiAuthDev)

// Create BA
baSession := createMultiBasicAuthSession(isBench)
Expand All @@ -101,7 +101,7 @@ func testPrepareMultiSessionBA(t testing.TB, isBench bool) (*APISpec, *http.Requ
password := "TEST"
keyName := generateToken("default", username)
// Basic auth sessions are stored as {org-id}{username}, so we need to append it here when we create the session.
spec.SessionManager.UpdateSession(keyName, baSession, 60, false)
GlobalSessionManager.UpdateSession(keyName, baSession, 60, false)

// Create key
session := createMultiAuthKeyAuthSession(isBench)
Expand All @@ -112,7 +112,7 @@ func testPrepareMultiSessionBA(t testing.TB, isBench bool) (*APISpec, *http.Requ
customToken = "84573485734587384888723487243"
}
// AuthKey sessions are stored by {token}
spec.SessionManager.UpdateSession(customToken, session, 60, false)
GlobalSessionManager.UpdateSession(customToken, session, 60, false)

toEncode := strings.Join([]string{username, password}, ":")
encodedPass := base64.StdEncoding.EncodeToString([]byte(toEncode))
Expand Down Expand Up @@ -153,20 +153,20 @@ func BenchmarkMultiSession_BA_Standard_OK(b *testing.B) {
}

func TestMultiSession_BA_Standard_Identity(t *testing.T) {
spec := CreateSpecTest(t, multiAuthDev)
spec := loadSampleAPI(multiAuthDev)

// Create BA
baSession := createMultiBasicAuthSession(false)
username := "0987876"
password := "TEST"
// Basic auth sessions are stored as {org-id}{username}, so we need to append it here when we create the session.
spec.SessionManager.UpdateSession("default0987876", baSession, 60, false)
GlobalSessionManager.UpdateSession("default0987876", baSession, 60, false)

// Create key
session := createMultiAuthKeyAuthSession(false)
customToken := "84573485734587384888723487243"
// AuthKey sessions are stored by {token}
spec.SessionManager.UpdateSession(customToken, session, 60, false)
GlobalSessionManager.UpdateSession(customToken, session, 60, false)

to_encode := strings.Join([]string{username, password}, ":")
encodedPass := base64.StdEncoding.EncodeToString([]byte(to_encode))
Expand All @@ -190,20 +190,20 @@ func TestMultiSession_BA_Standard_Identity(t *testing.T) {
}

func TestMultiSession_BA_Standard_FAILBA(t *testing.T) {
spec := CreateSpecTest(t, multiAuthDev)
spec := loadSampleAPI(multiAuthDev)

// Create BA
baSession := createMultiBasicAuthSession(false)
username := "0987876"
password := "WRONG"
// Basic auth sessions are stored as {org-id}{username}, so we need to append it here when we create the session.
spec.SessionManager.UpdateSession("default0987876", baSession, 60, false)
GlobalSessionManager.UpdateSession("default0987876", baSession, 60, false)

// Create key
session := createMultiAuthKeyAuthSession(false)
customToken := "84573485734587384888723487243"
// AuthKey sessions are stored by {token}
spec.SessionManager.UpdateSession(customToken, session, 60, false)
GlobalSessionManager.UpdateSession(customToken, session, 60, false)

to_encode := strings.Join([]string{username, password}, ":")
encodedPass := base64.StdEncoding.EncodeToString([]byte(to_encode))
Expand All @@ -222,20 +222,20 @@ func TestMultiSession_BA_Standard_FAILBA(t *testing.T) {
}

func TestMultiSession_BA_Standard_FAILAuth(t *testing.T) {
spec := CreateSpecTest(t, multiAuthDev)
spec := loadSampleAPI(multiAuthDev)

// Create BA
baSession := createMultiBasicAuthSession(false)
username := "0987876"
password := "TEST"
// Basic auth sessions are stored as {org-id}{username}, so we need to append it here when we create the session.
spec.SessionManager.UpdateSession("default0987876", baSession, 60, false)
GlobalSessionManager.UpdateSession("default0987876", baSession, 60, false)

// Create key
session := createMultiAuthKeyAuthSession(false)
customToken := "84573485734587384888723487243"
// AuthKey sessions are stored by {token}
spec.SessionManager.UpdateSession(customToken, session, 60, false)
GlobalSessionManager.UpdateSession(customToken, session, 60, false)

to_encode := strings.Join([]string{username, password}, ":")
encodedPass := base64.StdEncoding.EncodeToString([]byte(to_encode))
Expand Down
2 changes: 1 addition & 1 deletion gateway/mw_api_rate_limit.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func (k *RateLimitForAPI) ProcessRequest(w http.ResponseWriter, r *http.Request,
return nil, http.StatusOK
}

storeRef := k.Spec.SessionManager.Store()
storeRef := GlobalSessionManager.Store()
reason := sessionLimiter.ForwardMessage(r, k.apiSess,
k.keyName,
storeRef,
Expand Down
8 changes: 4 additions & 4 deletions gateway/mw_api_rate_limit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ func getGlobalRLAuthKeyChain(spec *APISpec) http.Handler {
}

func TestRLOpen(t *testing.T) {
spec := CreateSpecTest(t, openRLDefSmall)
spec := loadSampleAPI(openRLDefSmall)

req := TestReq(t, "GET", "/rl_test/", nil)

Expand Down Expand Up @@ -210,14 +210,14 @@ func TestRequestThrottling(t *testing.T) {
}

func TestRLClosed(t *testing.T) {
spec := CreateSpecTest(t, closedRLDefSmall)
spec := loadSampleAPI(closedRLDefSmall)

req := TestReq(t, "GET", "/rl_closed_test/", nil)

session := createRLSession()
customToken := uuid.NewV4().String()
// AuthKey sessions are stored by {token}
spec.SessionManager.UpdateSession(customToken, session, 60, false)
GlobalSessionManager.UpdateSession(customToken, session, 60, false)
req.Header.Set("authorization", "Bearer "+customToken)

DRLManager.SetCurrentTokenValue(1)
Expand Down Expand Up @@ -245,7 +245,7 @@ func TestRLClosed(t *testing.T) {
}

func TestRLOpenWithReload(t *testing.T) {
spec := CreateSpecTest(t, openRLDefSmall)
spec := loadSampleAPI(openRLDefSmall)

req := TestReq(t, "GET", "/rl_test/", nil)

Expand Down
Loading

0 comments on commit 37fb753

Please sign in to comment.