refactor: introduce config key gen (#3206)

This adjusts the validated keys to utilize a generated code section.
pull/3208/head
James Elliott 2022-04-16 19:00:39 +10:00 committed by GitHub
parent 5aa25ec275
commit dc7ca6f03c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 657 additions and 245 deletions

View File

@ -0,0 +1,199 @@
package main
import (
"fmt"
"net/mail"
"net/url"
"os"
"reflect"
"regexp"
"strings"
"text/template"
"time"
"github.com/spf13/cobra"
"github.com/authelia/authelia/v4/internal/configuration/schema"
)
// NewRunGenCmd implements the code generation cobra command.
func NewRunGenCmd() (cmd *cobra.Command) {
cmd = &cobra.Command{
Use: "gen",
RunE: runGenE,
}
return cmd
}
func runGenE(cmd *cobra.Command, args []string) (err error) {
if err = genConfigurationKeys(); err != nil {
return err
}
return nil
}
func genConfigurationKeys() (err error) {
data := loadKeysTemplate()
f, err := os.Create("./internal/configuration/schema/keys.go")
if err != nil {
return err
}
return keysTemplate.Execute(f, data)
}
var keysTemplate = template.Must(template.New("keys").Parse(`// Code generated by go generate. DO NOT EDIT.
//
// Run the following command to generate this file:
// go run ./cmd/authelia-scripts gen
//
package schema
// Keys represents the detected schema keys.
var Keys = []string{
{{- range .Keys }}
{{ printf "%q" . }},
{{- end }}
}
`))
type keysTemplateStruct struct {
Timestamp time.Time
Keys []string
}
func loadKeysTemplate() keysTemplateStruct {
config := schema.Configuration{
Storage: schema.StorageConfiguration{
Local: &schema.LocalStorageConfiguration{},
MySQL: &schema.MySQLStorageConfiguration{},
PostgreSQL: &schema.PostgreSQLStorageConfiguration{},
},
Notifier: schema.NotifierConfiguration{
FileSystem: &schema.FileSystemNotifierConfiguration{},
SMTP: &schema.SMTPNotifierConfiguration{
TLS: &schema.TLSConfig{},
},
},
AuthenticationBackend: schema.AuthenticationBackendConfiguration{
File: &schema.FileAuthenticationBackendConfiguration{
Password: &schema.PasswordConfiguration{},
},
LDAP: &schema.LDAPAuthenticationBackendConfiguration{
TLS: &schema.TLSConfig{},
},
},
Session: schema.SessionConfiguration{
Redis: &schema.RedisSessionConfiguration{
TLS: &schema.TLSConfig{},
HighAvailability: &schema.RedisHighAvailabilityConfiguration{},
},
},
IdentityProviders: schema.IdentityProvidersConfiguration{
OIDC: &schema.OpenIDConnectConfiguration{},
},
}
return keysTemplateStruct{
Timestamp: time.Now(),
Keys: readTags("", reflect.TypeOf(config)),
}
}
var decodedTypes = []reflect.Type{
reflect.TypeOf(mail.Address{}),
reflect.TypeOf(regexp.Regexp{}),
reflect.TypeOf(url.URL{}),
reflect.TypeOf(time.Duration(0)),
}
func containsType(needle reflect.Type, haystack []reflect.Type) (contains bool) {
for _, t := range haystack {
if needle.Kind() == reflect.Ptr {
if needle.Elem() == t {
return true
}
} else if needle == t {
return true
}
}
return false
}
func readTags(prefix string, t reflect.Type) (tags []string) {
tags = make([]string, 0)
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
tag := field.Tag.Get("koanf")
if tag == "" {
tags = append(tags, prefix)
continue
}
switch field.Type.Kind() {
case reflect.Struct:
if !containsType(field.Type, decodedTypes) {
tags = append(tags, readTags(getKeyNameFromTagAndPrefix(prefix, tag, false), field.Type)...)
continue
}
case reflect.Slice:
if field.Type.Elem().Kind() == reflect.Struct {
if !containsType(field.Type.Elem(), decodedTypes) {
tags = append(tags, getKeyNameFromTagAndPrefix(prefix, tag, false))
tags = append(tags, readTags(getKeyNameFromTagAndPrefix(prefix, tag, true), field.Type.Elem())...)
continue
}
}
case reflect.Ptr:
switch field.Type.Elem().Kind() {
case reflect.Struct:
if !containsType(field.Type.Elem(), decodedTypes) {
tags = append(tags, readTags(getKeyNameFromTagAndPrefix(prefix, tag, false), field.Type.Elem())...)
continue
}
case reflect.Slice:
if field.Type.Elem().Elem().Kind() == reflect.Struct {
if !containsType(field.Type.Elem(), decodedTypes) {
tags = append(tags, readTags(getKeyNameFromTagAndPrefix(prefix, tag, true), field.Type.Elem())...)
continue
}
}
}
}
tags = append(tags, getKeyNameFromTagAndPrefix(prefix, tag, false))
}
return tags
}
func getKeyNameFromTagAndPrefix(prefix, name string, slice bool) string {
nameParts := strings.SplitN(name, ",", 2)
if prefix == "" {
return nameParts[0]
}
if len(nameParts) == 2 && nameParts[1] == "squash" {
return prefix
}
if slice {
return fmt.Sprintf("%s.%s[]", prefix, nameParts[0])
}
return fmt.Sprintf("%s.%s", prefix, nameParts[0])
}

View File

@ -136,7 +136,7 @@ func main() {
cobraCommands = append(cobraCommands, command) cobraCommands = append(cobraCommands, command)
} }
cobraCommands = append(cobraCommands, commands.NewHashPasswordCmd(), commands.NewCertificatesCmd(), commands.NewRSACmd(), xflagsCmd) cobraCommands = append(cobraCommands, commands.NewHashPasswordCmd(), commands.NewCertificatesCmd(), commands.NewRSACmd(), NewRunGenCmd(), xflagsCmd)
rootCmd.PersistentFlags().BoolVar(&buildkite, "buildkite", false, "Set CI flag for Buildkite") rootCmd.PersistentFlags().BoolVar(&buildkite, "buildkite", false, "Set CI flag for Buildkite")
rootCmd.PersistentFlags().StringVar(&logLevel, "log-level", "info", "Set the log level for the command") rootCmd.PersistentFlags().StringVar(&logLevel, "log-level", "info", "Set the log level for the command")

View File

@ -7,7 +7,6 @@ import (
"github.com/spf13/pflag" "github.com/spf13/pflag"
"github.com/authelia/authelia/v4/internal/configuration/schema" "github.com/authelia/authelia/v4/internal/configuration/schema"
"github.com/authelia/authelia/v4/internal/configuration/validator"
"github.com/authelia/authelia/v4/internal/utils" "github.com/authelia/authelia/v4/internal/utils"
) )
@ -25,7 +24,7 @@ func koanfEnvironmentCallback(keyMap map[string]string, ignoredKeys []string, pr
formattedKey := strings.TrimPrefix(key, prefix) formattedKey := strings.TrimPrefix(key, prefix)
formattedKey = strings.ReplaceAll(strings.ToLower(formattedKey), delimiter, constDelimiter) formattedKey = strings.ReplaceAll(strings.ToLower(formattedKey), delimiter, constDelimiter)
if utils.IsStringInSlice(formattedKey, validator.ValidKeys) { if utils.IsStringInSlice(formattedKey, schema.Keys) {
return formattedKey, value return formattedKey, value
} }
@ -64,7 +63,7 @@ func koanfCommandLineWithMappingCallback(mapping map[string]string, includeValid
if includeValidKeys { if includeValidKeys {
formattedKey := strings.ReplaceAll(flag.Name, "-", "_") formattedKey := strings.ReplaceAll(flag.Name, "-", "_")
if utils.IsStringInSlice(formattedKey, validator.ValidKeys) { if utils.IsStringInSlice(formattedKey, schema.Keys) {
return formattedKey, flag.Value.String() return formattedKey, flag.Value.String()
} }
} }

View File

@ -0,0 +1,196 @@
// Code generated by go generate. DO NOT EDIT.
//
// Run the following command to generate this file:
// go run ./cmd/authelia-scripts gen
//
package schema
// Keys represents the detected schema keys.
var Keys = []string{
"theme",
"certificates_directory",
"jwt_secret",
"default_redirection_url",
"log.level",
"log.format",
"log.file_path",
"log.keep_stdout",
"identity_providers.oidc.hmac_secret",
"identity_providers.oidc.issuer_private_key",
"identity_providers.oidc.access_token_lifespan",
"identity_providers.oidc.authorize_code_lifespan",
"identity_providers.oidc.id_token_lifespan",
"identity_providers.oidc.refresh_token_lifespan",
"identity_providers.oidc.enable_client_debug_messages",
"identity_providers.oidc.minimum_parameter_entropy",
"identity_providers.oidc.enforce_pkce",
"identity_providers.oidc.enable_pkce_plain_challenge",
"identity_providers.oidc.cors.endpoints",
"identity_providers.oidc.cors.allowed_origins",
"identity_providers.oidc.cors.allowed_origins_from_client_redirect_uris",
"identity_providers.oidc.clients",
"identity_providers.oidc.clients[].id",
"identity_providers.oidc.clients[].description",
"identity_providers.oidc.clients[].secret",
"identity_providers.oidc.clients[].sector_identifier",
"identity_providers.oidc.clients[].public",
"identity_providers.oidc.clients[].redirect_uris",
"identity_providers.oidc.clients[].audience",
"identity_providers.oidc.clients[].scopes",
"identity_providers.oidc.clients[].grant_types",
"identity_providers.oidc.clients[].response_types",
"identity_providers.oidc.clients[].response_modes",
"identity_providers.oidc.clients[].userinfo_signing_algorithm",
"identity_providers.oidc.clients[].authorization_policy",
"identity_providers.oidc.clients[].pre_configured_consent_duration",
"authentication_backend.ldap.implementation",
"authentication_backend.ldap.url",
"authentication_backend.ldap.timeout",
"authentication_backend.ldap.start_tls",
"authentication_backend.ldap.tls.minimum_version",
"authentication_backend.ldap.tls.skip_verify",
"authentication_backend.ldap.tls.server_name",
"authentication_backend.ldap.base_dn",
"authentication_backend.ldap.additional_users_dn",
"authentication_backend.ldap.users_filter",
"authentication_backend.ldap.additional_groups_dn",
"authentication_backend.ldap.groups_filter",
"authentication_backend.ldap.group_name_attribute",
"authentication_backend.ldap.username_attribute",
"authentication_backend.ldap.mail_attribute",
"authentication_backend.ldap.display_name_attribute",
"authentication_backend.ldap.user",
"authentication_backend.ldap.password",
"authentication_backend.file.path",
"authentication_backend.file.password.iterations",
"authentication_backend.file.password.key_length",
"authentication_backend.file.password.salt_length",
"authentication_backend.file.password.algorithm",
"authentication_backend.file.password.memory",
"authentication_backend.file.password.parallelism",
"authentication_backend.password_reset.custom_url",
"authentication_backend.disable_reset_password",
"authentication_backend.refresh_interval",
"session.name",
"session.domain",
"session.same_site",
"session.secret",
"session.expiration",
"session.inactivity",
"session.remember_me_duration",
"session.redis.host",
"session.redis.port",
"session.redis.username",
"session.redis.password",
"session.redis.database_index",
"session.redis.maximum_active_connections",
"session.redis.minimum_idle_connections",
"session.redis.tls.minimum_version",
"session.redis.tls.skip_verify",
"session.redis.tls.server_name",
"session.redis.high_availability.sentinel_name",
"session.redis.high_availability.sentinel_username",
"session.redis.high_availability.sentinel_password",
"session.redis.high_availability.nodes",
"session.redis.high_availability.nodes[].host",
"session.redis.high_availability.nodes[].port",
"session.redis.high_availability.route_by_latency",
"session.redis.high_availability.route_randomly",
"totp.disable",
"totp.issuer",
"totp.algorithm",
"totp.digits",
"totp.period",
"totp.skew",
"totp.secret_size",
"duo_api.disable",
"duo_api.hostname",
"duo_api.integration_key",
"duo_api.secret_key",
"duo_api.enable_self_enrollment",
"access_control.default_policy",
"access_control.networks",
"access_control.networks[].name",
"access_control.networks[].networks",
"access_control.rules",
"access_control.rules[].domain",
"access_control.rules[].domain_regex",
"access_control.rules[].policy",
"access_control.rules[].subject",
"access_control.rules[].networks",
"access_control.rules[].resources",
"access_control.rules[].methods",
"ntp.address",
"ntp.version",
"ntp.max_desync",
"ntp.disable_startup_check",
"ntp.disable_failure",
"regulation.max_retries",
"regulation.find_time",
"regulation.ban_time",
"storage.local.path",
"storage.mysql.host",
"storage.mysql.port",
"storage.mysql.database",
"storage.mysql.username",
"storage.mysql.password",
"storage.mysql.timeout",
"storage.postgres.host",
"storage.postgres.port",
"storage.postgres.database",
"storage.postgres.username",
"storage.postgres.password",
"storage.postgres.timeout",
"storage.postgres.schema",
"storage.postgres.ssl.mode",
"storage.postgres.ssl.root_certificate",
"storage.postgres.ssl.certificate",
"storage.postgres.ssl.key",
"storage.postgres.sslmode",
"storage.encryption_key",
"notifier.disable_startup_check",
"notifier.filesystem.filename",
"notifier.smtp.host",
"notifier.smtp.port",
"notifier.smtp.timeout",
"notifier.smtp.username",
"notifier.smtp.password",
"notifier.smtp.identifier",
"notifier.smtp.sender",
"notifier.smtp.subject",
"notifier.smtp.startup_check_address",
"notifier.smtp.disable_require_tls",
"notifier.smtp.disable_html_emails",
"notifier.smtp.tls.minimum_version",
"notifier.smtp.tls.skip_verify",
"notifier.smtp.tls.server_name",
"notifier.template_path",
"server.host",
"server.port",
"server.path",
"server.asset_path",
"server.read_buffer_size",
"server.write_buffer_size",
"server.enable_pprof",
"server.enable_expvars",
"server.disable_healthcheck",
"server.tls.certificate",
"server.tls.key",
"server.tls.client_certificates",
"server.headers.csp_template",
"webauthn.disable",
"webauthn.display_name",
"webauthn.attestation_conveyance_preference",
"webauthn.user_verification",
"webauthn.timeout",
"password_policy.standard.enabled",
"password_policy.standard.min_length",
"password_policy.standard.max_length",
"password_policy.standard.require_uppercase",
"password_policy.standard.require_lowercase",
"password_policy.standard.require_number",
"password_policy.standard.require_special",
"password_policy.zxcvbn.enabled",
"password_policy.zxcvbn.min_score",
}

View File

@ -0,0 +1,253 @@
package schema
import (
"testing"
"github.com/stretchr/testify/assert"
)
var ValidKeys = []string{
// Root Keys.
"certificates_directory",
"theme",
"default_redirection_url",
"jwt_secret",
// Log keys.
"log.level",
"log.format",
"log.file_path",
"log.keep_stdout",
// Server Keys.
"server.host",
"server.port",
"server.read_buffer_size",
"server.write_buffer_size",
"server.path",
"server.asset_path",
"server.enable_pprof",
"server.enable_expvars",
"server.disable_healthcheck",
"server.tls.key",
"server.tls.certificate",
"server.tls.client_certificates",
"server.headers.csp_template",
// TOTP Keys.
"totp.disable",
"totp.issuer",
"totp.algorithm",
"totp.digits",
"totp.period",
"totp.skew",
"totp.secret_size",
// Webauthn Keys.
"webauthn.disable",
"webauthn.display_name",
"webauthn.attestation_conveyance_preference",
"webauthn.user_verification",
"webauthn.timeout",
// DUO API Keys.
"duo_api.disable",
"duo_api.hostname",
"duo_api.enable_self_enrollment",
"duo_api.secret_key",
"duo_api.integration_key",
// Access Control Keys.
"access_control.default_policy",
"access_control.networks",
"access_control.networks[].name",
"access_control.networks[].networks",
"access_control.rules",
"access_control.rules[].domain",
"access_control.rules[].domain_regex",
"access_control.rules[].methods",
"access_control.rules[].networks",
"access_control.rules[].subject",
"access_control.rules[].policy",
"access_control.rules[].resources",
// Session Keys.
"session.name",
"session.domain",
"session.secret",
"session.same_site",
"session.expiration",
"session.inactivity",
"session.remember_me_duration",
// Redis Session Keys.
"session.redis.host",
"session.redis.port",
"session.redis.username",
"session.redis.password",
"session.redis.database_index",
"session.redis.maximum_active_connections",
"session.redis.minimum_idle_connections",
"session.redis.tls.minimum_version",
"session.redis.tls.skip_verify",
"session.redis.tls.server_name",
"session.redis.high_availability.sentinel_name",
"session.redis.high_availability.sentinel_username",
"session.redis.high_availability.sentinel_password",
"session.redis.high_availability.nodes",
"session.redis.high_availability.nodes[].host",
"session.redis.high_availability.nodes[].port",
"session.redis.high_availability.route_by_latency",
"session.redis.high_availability.route_randomly",
// Storage Keys.
"storage.encryption_key",
// Local Storage Keys.
"storage.local.path",
// MySQL Storage Keys.
"storage.mysql.host",
"storage.mysql.port",
"storage.mysql.database",
"storage.mysql.username",
"storage.mysql.password",
"storage.mysql.timeout",
// PostgreSQL Storage Keys.
"storage.postgres.host",
"storage.postgres.port",
"storage.postgres.database",
"storage.postgres.username",
"storage.postgres.password",
"storage.postgres.timeout",
"storage.postgres.schema",
"storage.postgres.ssl.mode",
"storage.postgres.ssl.root_certificate",
"storage.postgres.ssl.certificate",
"storage.postgres.ssl.key",
"storage.postgres.sslmode", // Deprecated. TODO: Remove in v4.36.0.
// FileSystem Notifier Keys.
"notifier.filesystem.filename",
"notifier.disable_startup_check",
// SMTP Notifier Keys.
"notifier.smtp.host",
"notifier.smtp.port",
"notifier.smtp.timeout",
"notifier.smtp.username",
"notifier.smtp.password",
"notifier.smtp.identifier",
"notifier.smtp.sender",
"notifier.smtp.subject",
"notifier.smtp.startup_check_address",
"notifier.smtp.disable_require_tls",
"notifier.smtp.disable_html_emails",
"notifier.smtp.tls.minimum_version",
"notifier.smtp.tls.skip_verify",
"notifier.smtp.tls.server_name",
"notifier.template_path",
// Regulation Keys.
"regulation.max_retries",
"regulation.find_time",
"regulation.ban_time",
// Authentication Backend Keys.
"authentication_backend.disable_reset_password",
"authentication_backend.password_reset.custom_url",
"authentication_backend.refresh_interval",
// LDAP Authentication Backend Keys.
"authentication_backend.ldap.implementation",
"authentication_backend.ldap.url",
"authentication_backend.ldap.timeout",
"authentication_backend.ldap.base_dn",
"authentication_backend.ldap.username_attribute",
"authentication_backend.ldap.additional_users_dn",
"authentication_backend.ldap.users_filter",
"authentication_backend.ldap.additional_groups_dn",
"authentication_backend.ldap.groups_filter",
"authentication_backend.ldap.group_name_attribute",
"authentication_backend.ldap.mail_attribute",
"authentication_backend.ldap.display_name_attribute",
"authentication_backend.ldap.user",
"authentication_backend.ldap.password",
"authentication_backend.ldap.start_tls",
"authentication_backend.ldap.tls.minimum_version",
"authentication_backend.ldap.tls.skip_verify",
"authentication_backend.ldap.tls.server_name",
// File Authentication Backend Keys.
"authentication_backend.file.path",
"authentication_backend.file.password.algorithm",
"authentication_backend.file.password.iterations",
"authentication_backend.file.password.key_length",
"authentication_backend.file.password.salt_length",
"authentication_backend.file.password.memory",
"authentication_backend.file.password.parallelism",
// Identity Provider Keys.
"identity_providers.oidc.hmac_secret",
"identity_providers.oidc.issuer_private_key",
"identity_providers.oidc.id_token_lifespan",
"identity_providers.oidc.access_token_lifespan",
"identity_providers.oidc.refresh_token_lifespan",
"identity_providers.oidc.authorize_code_lifespan",
"identity_providers.oidc.enforce_pkce",
"identity_providers.oidc.enable_pkce_plain_challenge",
"identity_providers.oidc.enable_client_debug_messages",
"identity_providers.oidc.minimum_parameter_entropy",
"identity_providers.oidc.cors.endpoints",
"identity_providers.oidc.cors.allowed_origins",
"identity_providers.oidc.cors.allowed_origins_from_client_redirect_uris",
"identity_providers.oidc.clients",
"identity_providers.oidc.clients[].id",
"identity_providers.oidc.clients[].description",
"identity_providers.oidc.clients[].secret",
"identity_providers.oidc.clients[].sector_identifier",
"identity_providers.oidc.clients[].public",
"identity_providers.oidc.clients[].redirect_uris",
"identity_providers.oidc.clients[].authorization_policy",
"identity_providers.oidc.clients[].pre_configured_consent_duration",
"identity_providers.oidc.clients[].scopes",
"identity_providers.oidc.clients[].audience",
"identity_providers.oidc.clients[].grant_types",
"identity_providers.oidc.clients[].response_types",
"identity_providers.oidc.clients[].response_modes",
"identity_providers.oidc.clients[].userinfo_signing_algorithm",
// NTP keys.
"ntp.address",
"ntp.version",
"ntp.max_desync",
"ntp.disable_startup_check",
"ntp.disable_failure",
// Password Policy keys.
"password_policy.standard.enabled",
"password_policy.standard.min_length",
"password_policy.standard.max_length",
"password_policy.standard.require_uppercase",
"password_policy.standard.require_lowercase",
"password_policy.standard.require_number",
"password_policy.standard.require_special",
"password_policy.zxcvbn.enabled",
"password_policy.zxcvbn.min_score",
}
func TestOldKeys(t *testing.T) {
for _, key := range ValidKeys {
assert.Contains(t, Keys, key)
}
for _, key := range Keys {
assert.Contains(t, ValidKeys, key)
}
}
func TestDuplicates(t *testing.T) {
assert.Equal(t, len(Keys), len(ValidKeys))
}

View File

@ -12,7 +12,6 @@ import (
"github.com/spf13/pflag" "github.com/spf13/pflag"
"github.com/authelia/authelia/v4/internal/configuration/schema" "github.com/authelia/authelia/v4/internal/configuration/schema"
"github.com/authelia/authelia/v4/internal/configuration/validator"
) )
// NewYAMLFileSource returns a Source configured to load from a specified YAML path. If there is an issue accessing this // NewYAMLFileSource returns a Source configured to load from a specified YAML path. If there is an issue accessing this
@ -75,7 +74,7 @@ func (s *EnvironmentSource) Merge(ko *koanf.Koanf, _ *schema.StructValidator) (e
// Load the Source into the EnvironmentSource koanf.Koanf. // Load the Source into the EnvironmentSource koanf.Koanf.
func (s *EnvironmentSource) Load(_ *schema.StructValidator) (err error) { func (s *EnvironmentSource) Load(_ *schema.StructValidator) (err error) {
keyMap, ignoredKeys := getEnvConfigMap(validator.ValidKeys, s.prefix, s.delimiter) keyMap, ignoredKeys := getEnvConfigMap(schema.Keys, s.prefix, s.delimiter)
return s.koanf.Load(env.ProviderWithValue(s.prefix, constDelimiter, koanfEnvironmentCallback(keyMap, ignoredKeys, s.prefix, s.delimiter)), nil) return s.koanf.Load(env.ProviderWithValue(s.prefix, constDelimiter, koanfEnvironmentCallback(keyMap, ignoredKeys, s.prefix, s.delimiter)), nil)
} }
@ -109,7 +108,7 @@ func (s *SecretsSource) Merge(ko *koanf.Koanf, val *schema.StructValidator) (err
// Load the Source into the SecretsSource koanf.Koanf. // Load the Source into the SecretsSource koanf.Koanf.
func (s *SecretsSource) Load(val *schema.StructValidator) (err error) { func (s *SecretsSource) Load(val *schema.StructValidator) (err error) {
keyMap := getSecretConfigMap(validator.ValidKeys, s.prefix, s.delimiter) keyMap := getSecretConfigMap(schema.Keys, s.prefix, s.delimiter)
return s.koanf.Load(env.ProviderWithValue(s.prefix, constDelimiter, koanfEnvironmentSecretsCallback(keyMap, val)), nil) return s.koanf.Load(env.ProviderWithValue(s.prefix, constDelimiter, koanfEnvironmentSecretsCallback(keyMap, val)), nil)
} }

View File

@ -300,240 +300,6 @@ var validOIDCCORSEndpoints = []string{oidc.AuthorizationEndpoint, oidc.TokenEndp
var reKeyReplacer = regexp.MustCompile(`\[\d+]`) var reKeyReplacer = regexp.MustCompile(`\[\d+]`)
// ValidKeys is a list of valid keys that are not secret names. For the sake of consistency please place any secret in
// the secret names map and reuse it in relevant sections.
var ValidKeys = []string{
// Root Keys.
"certificates_directory",
"theme",
"default_redirection_url",
"jwt_secret",
// Log keys.
"log.level",
"log.format",
"log.file_path",
"log.keep_stdout",
// Server Keys.
"server.host",
"server.port",
"server.read_buffer_size",
"server.write_buffer_size",
"server.path",
"server.asset_path",
"server.enable_pprof",
"server.enable_expvars",
"server.disable_healthcheck",
"server.tls.key",
"server.tls.certificate",
"server.tls.client_certificates",
"server.headers.csp_template",
// TOTP Keys.
"totp.disable",
"totp.issuer",
"totp.algorithm",
"totp.digits",
"totp.period",
"totp.skew",
"totp.secret_size",
// Webauthn Keys.
"webauthn.disable",
"webauthn.display_name",
"webauthn.attestation_conveyance_preference",
"webauthn.user_verification",
"webauthn.timeout",
// DUO API Keys.
"duo_api.disable",
"duo_api.hostname",
"duo_api.enable_self_enrollment",
"duo_api.secret_key",
"duo_api.integration_key",
// Access Control Keys.
"access_control.default_policy",
"access_control.networks",
"access_control.networks[].name",
"access_control.networks[].networks",
"access_control.rules",
"access_control.rules[].domain",
"access_control.rules[].domain_regex",
"access_control.rules[].methods",
"access_control.rules[].networks",
"access_control.rules[].subject",
"access_control.rules[].policy",
"access_control.rules[].resources",
// Session Keys.
"session.name",
"session.domain",
"session.secret",
"session.same_site",
"session.expiration",
"session.inactivity",
"session.remember_me_duration",
// Redis Session Keys.
"session.redis.host",
"session.redis.port",
"session.redis.username",
"session.redis.password",
"session.redis.database_index",
"session.redis.maximum_active_connections",
"session.redis.minimum_idle_connections",
"session.redis.tls.minimum_version",
"session.redis.tls.skip_verify",
"session.redis.tls.server_name",
"session.redis.high_availability.sentinel_name",
"session.redis.high_availability.sentinel_username",
"session.redis.high_availability.sentinel_password",
"session.redis.high_availability.nodes",
"session.redis.high_availability.nodes[].host",
"session.redis.high_availability.nodes[].port",
"session.redis.high_availability.route_by_latency",
"session.redis.high_availability.route_randomly",
// Storage Keys.
"storage.encryption_key",
// Local Storage Keys.
"storage.local.path",
// MySQL Storage Keys.
"storage.mysql.host",
"storage.mysql.port",
"storage.mysql.database",
"storage.mysql.username",
"storage.mysql.password",
"storage.mysql.timeout",
// PostgreSQL Storage Keys.
"storage.postgres.host",
"storage.postgres.port",
"storage.postgres.database",
"storage.postgres.username",
"storage.postgres.password",
"storage.postgres.timeout",
"storage.postgres.schema",
"storage.postgres.ssl.mode",
"storage.postgres.ssl.root_certificate",
"storage.postgres.ssl.certificate",
"storage.postgres.ssl.key",
"storage.postgres.sslmode", // Deprecated. TODO: Remove in v4.36.0.
// FileSystem Notifier Keys.
"notifier.filesystem.filename",
"notifier.disable_startup_check",
// SMTP Notifier Keys.
"notifier.smtp.host",
"notifier.smtp.port",
"notifier.smtp.timeout",
"notifier.smtp.username",
"notifier.smtp.password",
"notifier.smtp.identifier",
"notifier.smtp.sender",
"notifier.smtp.subject",
"notifier.smtp.startup_check_address",
"notifier.smtp.disable_require_tls",
"notifier.smtp.disable_html_emails",
"notifier.smtp.tls.minimum_version",
"notifier.smtp.tls.skip_verify",
"notifier.smtp.tls.server_name",
"notifier.template_path",
// Regulation Keys.
"regulation.max_retries",
"regulation.find_time",
"regulation.ban_time",
// Authentication Backend Keys.
"authentication_backend.disable_reset_password",
"authentication_backend.password_reset.custom_url",
"authentication_backend.refresh_interval",
// LDAP Authentication Backend Keys.
"authentication_backend.ldap.implementation",
"authentication_backend.ldap.url",
"authentication_backend.ldap.timeout",
"authentication_backend.ldap.base_dn",
"authentication_backend.ldap.username_attribute",
"authentication_backend.ldap.additional_users_dn",
"authentication_backend.ldap.users_filter",
"authentication_backend.ldap.additional_groups_dn",
"authentication_backend.ldap.groups_filter",
"authentication_backend.ldap.group_name_attribute",
"authentication_backend.ldap.mail_attribute",
"authentication_backend.ldap.display_name_attribute",
"authentication_backend.ldap.user",
"authentication_backend.ldap.password",
"authentication_backend.ldap.start_tls",
"authentication_backend.ldap.tls.minimum_version",
"authentication_backend.ldap.tls.skip_verify",
"authentication_backend.ldap.tls.server_name",
// File Authentication Backend Keys.
"authentication_backend.file.path",
"authentication_backend.file.password.algorithm",
"authentication_backend.file.password.iterations",
"authentication_backend.file.password.key_length",
"authentication_backend.file.password.salt_length",
"authentication_backend.file.password.memory",
"authentication_backend.file.password.parallelism",
// Identity Provider Keys.
"identity_providers.oidc.hmac_secret",
"identity_providers.oidc.issuer_private_key",
"identity_providers.oidc.id_token_lifespan",
"identity_providers.oidc.access_token_lifespan",
"identity_providers.oidc.refresh_token_lifespan",
"identity_providers.oidc.authorize_code_lifespan",
"identity_providers.oidc.enforce_pkce",
"identity_providers.oidc.enable_pkce_plain_challenge",
"identity_providers.oidc.enable_client_debug_messages",
"identity_providers.oidc.minimum_parameter_entropy",
"identity_providers.oidc.cors.endpoints",
"identity_providers.oidc.cors.allowed_origins",
"identity_providers.oidc.cors.allowed_origins_from_client_redirect_uris",
"identity_providers.oidc.clients",
"identity_providers.oidc.clients[].id",
"identity_providers.oidc.clients[].description",
"identity_providers.oidc.clients[].secret",
"identity_providers.oidc.clients[].sector_identifier",
"identity_providers.oidc.clients[].public",
"identity_providers.oidc.clients[].redirect_uris",
"identity_providers.oidc.clients[].authorization_policy",
"identity_providers.oidc.clients[].pre_configured_consent_duration",
"identity_providers.oidc.clients[].scopes",
"identity_providers.oidc.clients[].audience",
"identity_providers.oidc.clients[].grant_types",
"identity_providers.oidc.clients[].response_types",
"identity_providers.oidc.clients[].response_modes",
"identity_providers.oidc.clients[].userinfo_signing_algorithm",
// NTP keys.
"ntp.address",
"ntp.version",
"ntp.max_desync",
"ntp.disable_startup_check",
"ntp.disable_failure",
// Password Policy keys.
"password_policy.standard.enabled",
"password_policy.standard.min_length",
"password_policy.standard.max_length",
"password_policy.standard.require_uppercase",
"password_policy.standard.require_lowercase",
"password_policy.standard.require_number",
"password_policy.standard.require_special",
"password_policy.zxcvbn.enabled",
"password_policy.zxcvbn.min_score",
}
var replacedKeys = map[string]string{ var replacedKeys = map[string]string{
"authentication_backend.ldap.skip_verify": "authentication_backend.ldap.tls.skip_verify", "authentication_backend.ldap.skip_verify": "authentication_backend.ldap.tls.skip_verify",
"authentication_backend.ldap.minimum_tls_version": "authentication_backend.ldap.tls.minimum_version", "authentication_backend.ldap.minimum_tls_version": "authentication_backend.ldap.tls.minimum_version",

View File

@ -16,7 +16,7 @@ func ValidateKeys(keys []string, prefix string, validator *schema.StructValidato
for _, key := range keys { for _, key := range keys {
expectedKey := reKeyReplacer.ReplaceAllString(key, "[]") expectedKey := reKeyReplacer.ReplaceAllString(key, "[]")
if utils.IsStringInSlice(expectedKey, ValidKeys) { if utils.IsStringInSlice(expectedKey, schema.Keys) {
continue continue
} }

View File

@ -12,7 +12,7 @@ import (
) )
func TestShouldValidateGoodKeys(t *testing.T) { func TestShouldValidateGoodKeys(t *testing.T) {
configKeys := ValidKeys configKeys := schema.Keys
val := schema.NewStructValidator() val := schema.NewStructValidator()
ValidateKeys(configKeys, "AUTHELIA_", val) ValidateKeys(configKeys, "AUTHELIA_", val)
@ -20,7 +20,7 @@ func TestShouldValidateGoodKeys(t *testing.T) {
} }
func TestShouldNotValidateBadKeys(t *testing.T) { func TestShouldNotValidateBadKeys(t *testing.T) {
configKeys := ValidKeys configKeys := schema.Keys
configKeys = append(configKeys, "bad_key") configKeys = append(configKeys, "bad_key")
configKeys = append(configKeys, "totp.skewy") configKeys = append(configKeys, "totp.skewy")
val := schema.NewStructValidator() val := schema.NewStructValidator()
@ -34,7 +34,7 @@ func TestShouldNotValidateBadKeys(t *testing.T) {
} }
func TestShouldNotValidateBadEnvKeys(t *testing.T) { func TestShouldNotValidateBadEnvKeys(t *testing.T) {
configKeys := ValidKeys configKeys := schema.Keys
configKeys = append(configKeys, "AUTHELIA__BAD_ENV_KEY") configKeys = append(configKeys, "AUTHELIA__BAD_ENV_KEY")
configKeys = append(configKeys, "AUTHELIA_BAD_ENV_KEY") configKeys = append(configKeys, "AUTHELIA_BAD_ENV_KEY")