mirror of
https://github.com/pocket-id/pocket-id.git
synced 2026-07-15 21:48:13 +03:00
feat: add support for CIDR and IP address lists in TRUST_PROXY
This commit is contained in:
@@ -68,7 +68,10 @@ func initEngine() (*gin.Engine, error) {
|
|||||||
|
|
||||||
r := gin.New()
|
r := gin.New()
|
||||||
initLogger(r)
|
initLogger(r)
|
||||||
configureEngine(r)
|
err := configureEngine(r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
registerGlobalMiddleware(r)
|
registerGlobalMiddleware(r)
|
||||||
|
|
||||||
return r, nil
|
return r, nil
|
||||||
@@ -86,9 +89,10 @@ func setGinMode() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func configureEngine(r *gin.Engine) {
|
func configureEngine(r *gin.Engine) error {
|
||||||
if !common.EnvConfig.TrustProxy {
|
err := r.SetTrustedProxies(common.EnvConfig.TrustProxy)
|
||||||
_ = r.SetTrustedProxies(nil)
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to configure trusted proxies: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if common.EnvConfig.TrustedPlatform != "" {
|
if common.EnvConfig.TrustedPlatform != "" {
|
||||||
@@ -99,6 +103,8 @@ func configureEngine(r *gin.Engine) {
|
|||||||
common.Name,
|
common.Name,
|
||||||
otelgin.WithFilter(shouldTraceRequest)),
|
otelgin.WithFilter(shouldTraceRequest)),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// shouldTraceRequest reports whether an incoming request should be traced.
|
// shouldTraceRequest reports whether an incoming request should be traced.
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/caarlos0/env/v11"
|
"github.com/caarlos0/env/v11"
|
||||||
@@ -17,6 +18,7 @@ import (
|
|||||||
|
|
||||||
type AppEnv string
|
type AppEnv string
|
||||||
type DbProvider string
|
type DbProvider string
|
||||||
|
type TrustProxyConfig []string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// TracerName should be passed to otel.Tracer, trace.SpanFromContext when creating custom spans.
|
// TracerName should be passed to otel.Tracer, trace.SpanFromContext when creating custom spans.
|
||||||
@@ -42,18 +44,18 @@ type EnvConfigSchema struct {
|
|||||||
EncryptionKey []byte `env:"ENCRYPTION_KEY" options:"file"`
|
EncryptionKey []byte `env:"ENCRYPTION_KEY" options:"file"`
|
||||||
AppURL string `env:"APP_URL" options:"toLower,trimTrailingSlash"`
|
AppURL string `env:"APP_URL" options:"toLower,trimTrailingSlash"`
|
||||||
DbProvider DbProvider
|
DbProvider DbProvider
|
||||||
DbConnectionString string `env:"DB_CONNECTION_STRING" options:"file"`
|
DbConnectionString string `env:"DB_CONNECTION_STRING" options:"file"`
|
||||||
TrustProxy bool `env:"TRUST_PROXY"`
|
TrustProxy TrustProxyConfig `env:"TRUST_PROXY"`
|
||||||
TrustedPlatform string `env:"TRUSTED_PLATFORM"`
|
TrustedPlatform string `env:"TRUSTED_PLATFORM"`
|
||||||
AuditLogRetentionDays int `env:"AUDIT_LOG_RETENTION_DAYS"`
|
AuditLogRetentionDays int `env:"AUDIT_LOG_RETENTION_DAYS"`
|
||||||
AnalyticsDisabled bool `env:"ANALYTICS_DISABLED"`
|
AnalyticsDisabled bool `env:"ANALYTICS_DISABLED"`
|
||||||
AllowDowngrade bool `env:"ALLOW_DOWNGRADE"`
|
AllowDowngrade bool `env:"ALLOW_DOWNGRADE"`
|
||||||
AllowInsecureCallbackURLs bool `env:"ALLOW_INSECURE_CALLBACK_URLS"`
|
AllowInsecureCallbackURLs bool `env:"ALLOW_INSECURE_CALLBACK_URLS"`
|
||||||
InternalAppURL string `env:"INTERNAL_APP_URL"`
|
InternalAppURL string `env:"INTERNAL_APP_URL"`
|
||||||
UiConfigDisabled bool `env:"UI_CONFIG_DISABLED"`
|
UiConfigDisabled bool `env:"UI_CONFIG_DISABLED"`
|
||||||
DisableRateLimiting bool `env:"DISABLE_RATE_LIMITING"`
|
DisableRateLimiting bool `env:"DISABLE_RATE_LIMITING"`
|
||||||
VersionCheckDisabled bool `env:"VERSION_CHECK_DISABLED"`
|
VersionCheckDisabled bool `env:"VERSION_CHECK_DISABLED"`
|
||||||
StaticApiKey string `env:"STATIC_API_KEY" options:"file"`
|
StaticApiKey string `env:"STATIC_API_KEY" options:"file"`
|
||||||
|
|
||||||
FileBackend string `env:"FILE_BACKEND" options:"toLower"`
|
FileBackend string `env:"FILE_BACKEND" options:"toLower"`
|
||||||
UploadPath string `env:"UPLOAD_PATH"`
|
UploadPath string `env:"UPLOAD_PATH"`
|
||||||
@@ -392,3 +394,29 @@ func (a AppEnv) IsProduction() bool {
|
|||||||
func (a AppEnv) IsTest() bool {
|
func (a AppEnv) IsTest() bool {
|
||||||
return a == AppEnvTest
|
return a == AppEnvTest
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (config *TrustProxyConfig) UnmarshalText(text []byte) error {
|
||||||
|
value := strings.TrimSpace(string(text))
|
||||||
|
|
||||||
|
// Support boolean values for completely enabling or disabling trust proxy
|
||||||
|
enabled, err := strconv.ParseBool(value)
|
||||||
|
if err == nil {
|
||||||
|
if enabled {
|
||||||
|
*config = TrustProxyConfig{"0.0.0.0/0", "::/0"}
|
||||||
|
} else {
|
||||||
|
*config = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normalize and validate each explicit proxy before the server starts
|
||||||
|
proxies := strings.Split(value, ",")
|
||||||
|
for i, proxy := range proxies {
|
||||||
|
proxy = strings.TrimSpace(proxy)
|
||||||
|
proxies[i] = proxy
|
||||||
|
}
|
||||||
|
|
||||||
|
*config = proxies
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -124,11 +124,33 @@ func TestParseEnvConfig(t *testing.T) {
|
|||||||
err := parseAndValidateEnvConfig(t)
|
err := parseAndValidateEnvConfig(t)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.True(t, EnvConfig.UiConfigDisabled)
|
assert.True(t, EnvConfig.UiConfigDisabled)
|
||||||
assert.True(t, EnvConfig.TrustProxy)
|
assert.Equal(t, TrustProxyConfig{"0.0.0.0/0", "::/0"}, EnvConfig.TrustProxy)
|
||||||
assert.False(t, EnvConfig.AnalyticsDisabled)
|
assert.False(t, EnvConfig.AnalyticsDisabled)
|
||||||
assert.False(t, EnvConfig.AllowInsecureCallbackURLs)
|
assert.False(t, EnvConfig.AllowInsecureCallbackURLs)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("should parse trusted proxy IP addresses and CIDR ranges", func(t *testing.T) {
|
||||||
|
EnvConfig = defaultConfig()
|
||||||
|
t.Setenv("TRUST_PROXY", "10.0.0.0/8, 192.168.1.10, ::1/128")
|
||||||
|
|
||||||
|
err := parseAndValidateEnvConfig(t)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, TrustProxyConfig{"10.0.0.0/8", "192.168.1.10", "::1/128"}, EnvConfig.TrustProxy)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should disable trusted proxies when set to false", func(t *testing.T) {
|
||||||
|
EnvConfig = defaultConfig()
|
||||||
|
t.Setenv("TRUST_PROXY", "false")
|
||||||
|
|
||||||
|
err := parseAndValidateEnvConfig(t)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Nil(t, EnvConfig.TrustProxy)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should allow insecure callback URLs by default", func(t *testing.T) {
|
||||||
|
assert.True(t, defaultConfig().AllowInsecureCallbackURLs)
|
||||||
|
})
|
||||||
|
|
||||||
t.Run("should default audit log retention days to 90", func(t *testing.T) {
|
t.Run("should default audit log retention days to 90", func(t *testing.T) {
|
||||||
EnvConfig = defaultConfig()
|
EnvConfig = defaultConfig()
|
||||||
t.Setenv("DB_PROVIDER", "sqlite")
|
t.Setenv("DB_PROVIDER", "sqlite")
|
||||||
|
|||||||
Reference in New Issue
Block a user