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
|
||||
|
||||
type tokenCacheEntry struct {
|
||||
validUntil time.Time
|
||||
validUntil time.Time
|
||||
graceDeadline time.Time // потолок grace от последней УСПЕШНОЙ проверки (не продлевается)
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -66,18 +67,20 @@ func PingNubesAPICached(ctx context.Context, endpoint, token string) error {
|
||||
return err
|
||||
}
|
||||
if err != nil {
|
||||
// Сетевая ошибка шлюза: если токен ранее был валиден — даём grace.
|
||||
if ok {
|
||||
tokenCacheMu.Lock()
|
||||
tokenCache[key] = tokenCacheEntry{validUntil: time.Now().Add(cacheGraceTTL)}
|
||||
tokenCacheMu.Unlock()
|
||||
// Сетевая ошибка шлюза: если токен ранее был валиден — даём grace, но
|
||||
// НЕ дальше graceDeadline. Раньше validUntil сдвигали вперёд на каждый
|
||||
// сетевой сбой — отозванный токен жил бы вечно при повторных ошибках.
|
||||
if ok && now.Before(entry.graceDeadline) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
tokenCacheMu.Lock()
|
||||
tokenCache[key] = tokenCacheEntry{validUntil: time.Now().Add(cacheTTL)}
|
||||
tokenCache[key] = tokenCacheEntry{
|
||||
validUntil: now.Add(cacheTTL),
|
||||
graceDeadline: now.Add(cacheGraceTTL),
|
||||
}
|
||||
tokenCacheMu.Unlock()
|
||||
return nil
|
||||
}
|
||||
@@ -85,8 +88,12 @@ func PingNubesAPICached(ctx context.Context, endpoint, token string) error {
|
||||
// WarmTokenCache — записывает токен в кэш как валидный без вызова шлюза.
|
||||
// Используется после успешной свежей проверки при логине (jwtAuth).
|
||||
func WarmTokenCache(token string) {
|
||||
now := time.Now()
|
||||
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()
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -71,11 +71,11 @@ var ErrTokenRejected = errors.New("token rejected by nubes API")
|
||||
|
||||
// nubesAPIEndpoints — стенды Nubes API Gateway, по которым валидируется токен.
|
||||
// Токен принимается, если ХОТЯ БЫ ОДИН стенд его принял.
|
||||
// Юзер может вводить токен от любого стенда — главное, что токен действительный.
|
||||
// Безопасность: только prod-шлюз. Тестовый/dev-шлюзы принимают токены своих
|
||||
// стендов, и при их наличии токен тестового стенда считался бы валидным на проде.
|
||||
// Специфичный endpoint можно переопределить через NUBES_ENDPOINT.
|
||||
var nubesAPIEndpoints = []string{
|
||||
"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 — общий клиент для валидации токенов: переиспользует
|
||||
|
||||
Reference in New Issue
Block a user