tests: integration suite

This commit is contained in:
IliaDenisov
2026-04-09 15:27:14 +02:00
parent e04fc663f0
commit 1c8e0ca48e
20 changed files with 2748 additions and 10 deletions
+42
View File
@@ -4,6 +4,7 @@ package config
import (
"fmt"
"net/url"
"os"
"strconv"
"strings"
@@ -39,6 +40,11 @@ const (
// configures the timeout budget used for public auth upstream calls.
publicAuthUpstreamTimeoutEnvVar = "GATEWAY_PUBLIC_AUTH_UPSTREAM_TIMEOUT"
// authServiceBaseURLEnvVar names the environment variable that configures
// the optional Auth / Session Service public HTTP base URL used by gateway
// public-auth delegation.
authServiceBaseURLEnvVar = "GATEWAY_AUTH_SERVICE_BASE_URL"
// adminHTTPAddrEnvVar names the environment variable that configures the
// private admin HTTP listener address. When it is empty, the admin listener
// remains disabled.
@@ -464,6 +470,15 @@ type PublicHTTPConfig struct {
AntiAbuse PublicHTTPAntiAbuseConfig
}
// AuthServiceConfig describes the optional public-auth upstream used by the
// gateway runtime.
type AuthServiceConfig struct {
// BaseURL is the absolute base URL of the Auth / Session Service public
// HTTP API. When BaseURL is empty, the gateway keeps using its built-in
// unavailable public-auth adapter.
BaseURL string
}
// AdminHTTPConfig describes the private operational HTTP listener used for
// metrics exposure. The listener remains disabled when Addr is empty.
type AdminHTTPConfig struct {
@@ -591,6 +606,10 @@ type Config struct {
// PublicHTTP configures the public unauthenticated REST listener.
PublicHTTP PublicHTTPConfig
// AuthService configures the optional public-auth delegation to the Auth /
// Session Service.
AuthService AuthServiceConfig
// AdminHTTP configures the optional private admin listener used for metrics
// exposure.
AdminHTTP AdminHTTPConfig
@@ -766,6 +785,12 @@ func DefaultResponseSignerConfig() ResponseSignerConfig {
return ResponseSignerConfig{}
}
// DefaultAuthServiceConfig returns the default public-auth upstream settings.
// The zero value keeps the built-in unavailable adapter active.
func DefaultAuthServiceConfig() AuthServiceConfig {
return AuthServiceConfig{}
}
// LoadFromEnv loads Config from the process environment, applies defaults for
// omitted settings, and validates the resulting values.
func LoadFromEnv() (Config, error) {
@@ -773,6 +798,7 @@ func LoadFromEnv() (Config, error) {
ShutdownTimeout: defaultShutdownTimeout,
Logging: DefaultLoggingConfig(),
PublicHTTP: DefaultPublicHTTPConfig(),
AuthService: DefaultAuthServiceConfig(),
AdminHTTP: DefaultAdminHTTPConfig(),
AuthenticatedGRPC: DefaultAuthenticatedGRPCConfig(),
SessionCacheRedis: DefaultSessionCacheRedisConfig(),
@@ -825,6 +851,11 @@ func LoadFromEnv() (Config, error) {
}
cfg.PublicHTTP.AuthUpstreamTimeout = publicAuthUpstreamTimeout
rawAuthServiceBaseURL, ok := os.LookupEnv(authServiceBaseURLEnvVar)
if ok {
cfg.AuthService.BaseURL = rawAuthServiceBaseURL
}
rawAdminHTTPAddr, ok := os.LookupEnv(adminHTTPAddrEnvVar)
if ok {
cfg.AdminHTTP.Addr = rawAdminHTTPAddr
@@ -1082,6 +1113,17 @@ func LoadFromEnv() (Config, error) {
if cfg.PublicHTTP.AuthUpstreamTimeout <= 0 {
return Config{}, fmt.Errorf("load gateway config: %s must be positive", publicAuthUpstreamTimeoutEnvVar)
}
cfg.AuthService.BaseURL = strings.TrimSpace(cfg.AuthService.BaseURL)
if cfg.AuthService.BaseURL != "" {
parsedAuthServiceBaseURL, err := url.Parse(cfg.AuthService.BaseURL)
if err != nil {
return Config{}, fmt.Errorf("load gateway config: parse %s: %w", authServiceBaseURLEnvVar, err)
}
if parsedAuthServiceBaseURL.Scheme == "" || parsedAuthServiceBaseURL.Host == "" {
return Config{}, fmt.Errorf("load gateway config: %s must be an absolute URL", authServiceBaseURLEnvVar)
}
cfg.AuthService.BaseURL = strings.TrimRight(parsedAuthServiceBaseURL.String(), "/")
}
if addr := strings.TrimSpace(cfg.AdminHTTP.Addr); addr != "" {
cfg.AdminHTTP.Addr = addr
}
+105
View File
@@ -24,6 +24,9 @@ func TestLoadFromEnv(t *testing.T) {
customPublicHTTPAddr := new(string)
*customPublicHTTPAddr = "127.0.0.1:9090"
customAuthServiceBaseURL := new(string)
*customAuthServiceBaseURL = " http://127.0.0.1:8082/ "
customAuthenticatedGRPCAddr := new(string)
*customAuthenticatedGRPCAddr = "127.0.0.1:9191"
@@ -76,6 +79,7 @@ func TestLoadFromEnv(t *testing.T) {
name string
shutdownTimeout *string
publicHTTPAddr *string
authServiceBaseURL *string
authenticatedGRPCAddr *string
authenticatedGRPCFreshnessWindow *string
sessionCacheRedisAddr *string
@@ -179,6 +183,40 @@ func TestLoadFromEnv(t *testing.T) {
},
},
},
{
name: "custom auth service base url",
authServiceBaseURL: customAuthServiceBaseURL,
sessionCacheRedisAddr: customSessionCacheRedisAddr,
responseSignerPrivateKeyPEMPath: customResponseSignerPrivateKeyPEMPath,
want: Config{
ShutdownTimeout: 5 * time.Second,
Logging: DefaultLoggingConfig(),
PublicHTTP: DefaultPublicHTTPConfig(),
AuthService: AuthServiceConfig{
BaseURL: "http://127.0.0.1:8082",
},
AdminHTTP: DefaultAdminHTTPConfig(),
AuthenticatedGRPC: DefaultAuthenticatedGRPCConfig(),
SessionCacheRedis: SessionCacheRedisConfig{
Addr: "127.0.0.1:6379",
DB: defaultSessionCacheRedisDB,
KeyPrefix: defaultSessionCacheRedisKeyPrefix,
LookupTimeout: defaultSessionCacheRedisLookupTimeout,
},
ReplayRedis: DefaultReplayRedisConfig(),
SessionEventsRedis: SessionEventsRedisConfig{
Stream: "gateway:session_events",
ReadBlockTimeout: defaultSessionEventsRedisReadBlockTimeout,
},
ClientEventsRedis: ClientEventsRedisConfig{
Stream: "gateway:client_events",
ReadBlockTimeout: defaultClientEventsRedisReadBlockTimeout,
},
ResponseSigner: ResponseSignerConfig{
PrivateKeyPEMPath: *customResponseSignerPrivateKeyPEMPath,
},
},
},
{
name: "custom authenticated grpc address",
authenticatedGRPCAddr: customAuthenticatedGRPCAddr,
@@ -329,6 +367,7 @@ func TestLoadFromEnv(t *testing.T) {
restoreEnvs(t,
shutdownTimeoutEnvVar,
publicHTTPAddrEnvVar,
authServiceBaseURLEnvVar,
authenticatedGRPCAddrEnvVar,
authenticatedGRPCFreshnessWindowEnvVar,
sessionCacheRedisAddrEnvVar,
@@ -339,6 +378,7 @@ func TestLoadFromEnv(t *testing.T) {
setEnvValue(t, shutdownTimeoutEnvVar, tt.shutdownTimeout)
setEnvValue(t, publicHTTPAddrEnvVar, tt.publicHTTPAddr)
setEnvValue(t, authServiceBaseURLEnvVar, tt.authServiceBaseURL)
setEnvValue(t, authenticatedGRPCAddrEnvVar, tt.authenticatedGRPCAddr)
setEnvValue(t, authenticatedGRPCFreshnessWindowEnvVar, tt.authenticatedGRPCFreshnessWindow)
setEnvValue(t, sessionCacheRedisAddrEnvVar, tt.sessionCacheRedisAddr)
@@ -477,6 +517,70 @@ func TestLoadFromEnvOperationalSettings(t *testing.T) {
}
}
func TestLoadFromEnvAuthService(t *testing.T) {
t.Parallel()
customSessionCacheRedisAddr := new(string)
*customSessionCacheRedisAddr = "127.0.0.1:6379"
customSessionEventsRedisStream := new(string)
*customSessionEventsRedisStream = "gateway:session_events"
customClientEventsRedisStream := new(string)
*customClientEventsRedisStream = "gateway:client_events"
customResponseSignerPrivateKeyPEMPath := new(string)
*customResponseSignerPrivateKeyPEMPath = writeTestResponseSignerPEMFile(t)
invalidRelativeURL := new(string)
*invalidRelativeURL = "/authsession"
invalidURL := new(string)
*invalidURL = "://bad"
tests := []struct {
name string
value *string
wantErr string
}{
{
name: "relative url rejected",
value: invalidRelativeURL,
wantErr: authServiceBaseURLEnvVar + " must be an absolute URL",
},
{
name: "malformed url rejected",
value: invalidURL,
wantErr: "parse " + authServiceBaseURLEnvVar,
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
restoreEnvs(t,
authServiceBaseURLEnvVar,
sessionCacheRedisAddrEnvVar,
sessionEventsRedisStreamEnvVar,
clientEventsRedisStreamEnvVar,
responseSignerPrivateKeyPEMPathEnvVar,
)
setEnvValue(t, authServiceBaseURLEnvVar, tt.value)
setEnvValue(t, sessionCacheRedisAddrEnvVar, customSessionCacheRedisAddr)
setEnvValue(t, sessionEventsRedisStreamEnvVar, customSessionEventsRedisStream)
setEnvValue(t, clientEventsRedisStreamEnvVar, customClientEventsRedisStream)
setEnvValue(t, responseSignerPrivateKeyPEMPathEnvVar, customResponseSignerPrivateKeyPEMPath)
_, err := LoadFromEnv()
require.Error(t, err)
require.ErrorContains(t, err, tt.wantErr)
})
}
}
func TestLoadFromEnvAuthenticatedGRPCAntiAbuse(t *testing.T) {
customSessionCacheRedisAddr := new(string)
*customSessionCacheRedisAddr = "127.0.0.1:6379"
@@ -1212,6 +1316,7 @@ func operationalEnvVars() []string {
publicHTTPReadTimeoutEnvVar,
publicHTTPIdleTimeoutEnvVar,
publicAuthUpstreamTimeoutEnvVar,
authServiceBaseURLEnvVar,
adminHTTPAddrEnvVar,
adminHTTPReadHeaderTimeoutEnvVar,
adminHTTPReadTimeoutEnvVar,