fix(security): JWT validate against prod gateway only + cap grace renewal
- jwt: drop test/dev gateway from nubesAPIEndpoints (test-stand token was accepted as prod) - cache: grace bounded by graceDeadline from last successful validation (no more indefinite renewal)
This commit is contained in:
+15
-8
@@ -27,7 +27,8 @@ const cacheGraceTTL = 2 * time.Minute
|
|||||||
const cacheCleanupInterval = 5 * time.Minute
|
const cacheCleanupInterval = 5 * time.Minute
|
||||||
|
|
||||||
type tokenCacheEntry struct {
|
type tokenCacheEntry struct {
|
||||||
validUntil time.Time
|
validUntil time.Time
|
||||||
|
graceDeadline time.Time // потолок grace от последней УСПЕШНОЙ проверки (не продлевается)
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -66,18 +67,20 @@ func PingNubesAPICached(ctx context.Context, endpoint, token string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Сетевая ошибка шлюза: если токен ранее был валиден — даём grace.
|
// Сетевая ошибка шлюза: если токен ранее был валиден — даём grace, но
|
||||||
if ok {
|
// НЕ дальше graceDeadline. Раньше validUntil сдвигали вперёд на каждый
|
||||||
tokenCacheMu.Lock()
|
// сетевой сбой — отозванный токен жил бы вечно при повторных ошибках.
|
||||||
tokenCache[key] = tokenCacheEntry{validUntil: time.Now().Add(cacheGraceTTL)}
|
if ok && now.Before(entry.graceDeadline) {
|
||||||
tokenCacheMu.Unlock()
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
tokenCacheMu.Lock()
|
tokenCacheMu.Lock()
|
||||||
tokenCache[key] = tokenCacheEntry{validUntil: time.Now().Add(cacheTTL)}
|
tokenCache[key] = tokenCacheEntry{
|
||||||
|
validUntil: now.Add(cacheTTL),
|
||||||
|
graceDeadline: now.Add(cacheGraceTTL),
|
||||||
|
}
|
||||||
tokenCacheMu.Unlock()
|
tokenCacheMu.Unlock()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -85,8 +88,12 @@ func PingNubesAPICached(ctx context.Context, endpoint, token string) error {
|
|||||||
// WarmTokenCache — записывает токен в кэш как валидный без вызова шлюза.
|
// WarmTokenCache — записывает токен в кэш как валидный без вызова шлюза.
|
||||||
// Используется после успешной свежей проверки при логине (jwtAuth).
|
// Используется после успешной свежей проверки при логине (jwtAuth).
|
||||||
func WarmTokenCache(token string) {
|
func WarmTokenCache(token string) {
|
||||||
|
now := time.Now()
|
||||||
tokenCacheMu.Lock()
|
tokenCacheMu.Lock()
|
||||||
tokenCache[tokenCacheKey(token)] = tokenCacheEntry{validUntil: time.Now().Add(cacheTTL)}
|
tokenCache[tokenCacheKey(token)] = tokenCacheEntry{
|
||||||
|
validUntil: now.Add(cacheTTL),
|
||||||
|
graceDeadline: now.Add(cacheGraceTTL),
|
||||||
|
}
|
||||||
tokenCacheMu.Unlock()
|
tokenCacheMu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -71,11 +71,11 @@ var ErrTokenRejected = errors.New("token rejected by nubes API")
|
|||||||
|
|
||||||
// nubesAPIEndpoints — стенды Nubes API Gateway, по которым валидируется токен.
|
// nubesAPIEndpoints — стенды Nubes API Gateway, по которым валидируется токен.
|
||||||
// Токен принимается, если ХОТЯ БЫ ОДИН стенд его принял.
|
// Токен принимается, если ХОТЯ БЫ ОДИН стенд его принял.
|
||||||
// Юзер может вводить токен от любого стенда — главное, что токен действительный.
|
// Безопасность: только prod-шлюз. Тестовый/dev-шлюзы принимают токены своих
|
||||||
|
// стендов, и при их наличии токен тестового стенда считался бы валидным на проде.
|
||||||
|
// Специфичный endpoint можно переопределить через NUBES_ENDPOINT.
|
||||||
var nubesAPIEndpoints = []string{
|
var nubesAPIEndpoints = []string{
|
||||||
"https://lk-api-gateway.ngcloud.ru/api/v1/svc",
|
"https://lk-api-gateway.ngcloud.ru/api/v1/svc",
|
||||||
"https://lk-api-gateway-test.ngcloud.ru/api/v1/svc",
|
|
||||||
"https://lk-api-gateway-dev.ngcloud.ru/api/v1/svc",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// nubesHTTPClient — общий клиент для валидации токенов: переиспользует
|
// nubesHTTPClient — общий клиент для валидации токенов: переиспользует
|
||||||
|
|||||||
Reference in New Issue
Block a user