authelia/internal/configuration/validator/configuration.go

152 lines
3.6 KiB
Go

package validator
import (
"context"
"crypto/tls"
"fmt"
"net"
"net/http"
"os"
"time"
"github.com/authelia/authelia/v4/internal/configuration/schema"
"github.com/authelia/authelia/v4/internal/utils"
)
// ValidateConfiguration and adapt the configuration read from file.
func ValidateConfiguration(config *schema.Configuration, validator *schema.StructValidator, opts ...func(ctx *ValidateCtx)) {
var err error
ctx := NewValidateCtx()
for _, opt := range opts {
opt(ctx)
}
if config.CertificatesDirectory != "" {
var info os.FileInfo
if info, err = os.Stat(config.CertificatesDirectory); err != nil {
validator.Push(fmt.Errorf("the location 'certificates_directory' could not be inspected: %w", err))
} else if !info.IsDir() {
validator.Push(fmt.Errorf("the location 'certificates_directory' refers to '%s' is not a directory", config.CertificatesDirectory))
}
}
validateDefault2FAMethod(config, validator)
ValidateTheme(config, validator)
ValidateLog(config, validator)
ValidateDuo(config, validator)
ValidateTOTP(config, validator)
ValidateWebAuthn(config, validator)
ValidateAuthenticationBackend(&config.AuthenticationBackend, validator)
ValidateAccessControl(config, validator)
ValidateRules(config, validator)
ValidateSession(config, validator)
ValidateRegulation(config, validator)
ValidateServer(config, validator)
ValidateTelemetry(config, validator)
ValidateStorage(config.Storage, validator)
ValidateNotifier(&config.Notifier, validator)
ValidateIdentityProviders(ctx, &config.IdentityProviders, validator)
ValidateIdentityValidation(config, validator)
ValidateNTP(config, validator)
ValidatePasswordPolicy(&config.PasswordPolicy, validator)
ValidatePrivacyPolicy(&config.PrivacyPolicy, validator)
}
func validateDefault2FAMethod(config *schema.Configuration, validator *schema.StructValidator) {
if config.Default2FAMethod == "" {
return
}
if !utils.IsStringInSlice(config.Default2FAMethod, validDefault2FAMethods) {
validator.Push(fmt.Errorf(errFmtInvalidDefault2FAMethod, utils.StringJoinOr(validDefault2FAMethods), config.Default2FAMethod))
return
}
var enabledMethods []string
if !config.TOTP.Disable {
enabledMethods = append(enabledMethods, "totp")
}
if !config.WebAuthn.Disable {
enabledMethods = append(enabledMethods, "webauthn")
}
if !config.DuoAPI.Disable {
enabledMethods = append(enabledMethods, "mobile_push")
}
if !utils.IsStringInSlice(config.Default2FAMethod, enabledMethods) {
validator.Push(fmt.Errorf(errFmtInvalidDefault2FAMethodDisabled, utils.StringJoinOr(enabledMethods), config.Default2FAMethod))
}
}
func NewValidateCtx() *ValidateCtx {
return &ValidateCtx{
Context: context.Background(),
}
}
type ValidateCtx struct {
client *http.Client
tlsconfig *tls.Config
cacheSectorIdentifierURIs map[string][]string
context.Context
}
func (ctx *ValidateCtx) GetHTTPClient() (client *http.Client) {
if ctx.client == nil {
dialer := &net.Dialer{
Timeout: 5 * time.Second,
KeepAlive: 30 * time.Second,
}
transport := &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: dialer.DialContext,
ForceAttemptHTTP2: true,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
TLSClientConfig: ctx.tlsconfig,
}
ctx.client = &http.Client{Transport: transport}
}
return ctx.client
}
func WithTLSConfig(config *tls.Config) func(ctx *ValidateCtx) {
return func(ctx *ValidateCtx) {
ctx.tlsconfig, ctx.client = config, nil
}
}