package validator import ( "fmt" "path" "strings" "github.com/authelia/authelia/v4/internal/configuration/schema" "github.com/authelia/authelia/v4/internal/utils" ) // ValidateSession validates and update session configuration. func ValidateSession(config *schema.SessionConfiguration, validator *schema.StructValidator) { if config.Name == "" { config.Name = schema.DefaultSessionConfiguration.Name } if config.Redis != nil { if config.Redis.HighAvailability != nil { validateRedisSentinel(config, validator) } else { validateRedis(config, validator) } } validateSession(config, validator) } func validateSession(config *schema.SessionConfiguration, validator *schema.StructValidator) { if config.Expiration <= 0 { config.Expiration = schema.DefaultSessionConfiguration.Expiration // 1 hour. } if config.Inactivity <= 0 { config.Inactivity = schema.DefaultSessionConfiguration.Inactivity // 5 min. } if config.RememberMeDuration <= 0 && config.RememberMeDuration != schema.RememberMeDisabled { config.RememberMeDuration = schema.DefaultSessionConfiguration.RememberMeDuration // 1 month. } if config.Domain == "" { validator.Push(fmt.Errorf(errFmtSessionOptionRequired, "domain")) } else if strings.HasPrefix(config.Domain, ".") { validator.PushWarning(fmt.Errorf("session: option 'domain' has a prefix of '.' which is not supported or intended behaviour: you can use this at your own risk but we recommend removing it")) } if strings.HasPrefix(config.Domain, "*.") { validator.Push(fmt.Errorf(errFmtSessionDomainMustBeRoot, config.Domain)) } if config.SameSite == "" { config.SameSite = schema.DefaultSessionConfiguration.SameSite } else if !utils.IsStringInSlice(config.SameSite, validSessionSameSiteValues) { validator.Push(fmt.Errorf(errFmtSessionSameSite, strings.Join(validSessionSameSiteValues, "', '"), config.SameSite)) } } func validateRedisCommon(config *schema.SessionConfiguration, validator *schema.StructValidator) { if config.Secret == "" { validator.Push(fmt.Errorf(errFmtSessionSecretRequired, "redis")) } if config.Redis.TLS != nil { configDefaultTLS := &schema.TLSConfig{ ServerName: config.Redis.Host, MinimumVersion: schema.DefaultRedisConfiguration.TLS.MinimumVersion, MaximumVersion: schema.DefaultRedisConfiguration.TLS.MaximumVersion, } if err := ValidateTLSConfig(config.Redis.TLS, configDefaultTLS); err != nil { validator.Push(fmt.Errorf(errFmtSessionRedisTLSConfigInvalid, err)) } } } func validateRedis(config *schema.SessionConfiguration, validator *schema.StructValidator) { if config.Redis.Host == "" { validator.Push(fmt.Errorf(errFmtSessionRedisHostRequired)) } validateRedisCommon(config, validator) if !path.IsAbs(config.Redis.Host) && (config.Redis.Port < 1 || config.Redis.Port > 65535) { validator.Push(fmt.Errorf(errFmtSessionRedisPortRange, config.Redis.Port)) } if config.Redis.MaximumActiveConnections <= 0 { config.Redis.MaximumActiveConnections = 8 } } func validateRedisSentinel(config *schema.SessionConfiguration, validator *schema.StructValidator) { if config.Redis.HighAvailability.SentinelName == "" { validator.Push(fmt.Errorf(errFmtSessionRedisSentinelMissingName)) } if config.Redis.Port == 0 { config.Redis.Port = 26379 } else if config.Redis.Port < 0 || config.Redis.Port > 65535 { validator.Push(fmt.Errorf(errFmtSessionRedisPortRange, config.Redis.Port)) } if config.Redis.Host == "" && len(config.Redis.HighAvailability.Nodes) == 0 { validator.Push(fmt.Errorf(errFmtSessionRedisHostOrNodesRequired)) } validateRedisCommon(config, validator) hostMissing := false for i, node := range config.Redis.HighAvailability.Nodes { if node.Host == "" { hostMissing = true } if node.Port == 0 { config.Redis.HighAvailability.Nodes[i].Port = 26379 } } if hostMissing { validator.Push(fmt.Errorf(errFmtSessionRedisSentinelNodeHostMissing)) } }