tests: integration suite
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user