summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Elliott <james-d-elliott@users.noreply.github.com>2025-02-23 19:22:26 +1100
committerGitHub <noreply@github.com>2025-02-23 08:22:26 +0000
commit2934c16dd0895789a75313ad661920c42e1b5169 (patch)
treeda1ac150acc1f3eb91edcf9282b899e687158fbe
parent0af038e0ced689db90da480876a0bb26d78c6fb9 (diff)
feat(storage): allow postgres failover (#7775)
This allows configuring failover PostgreSQL servers. Signed-off-by: James Elliott <james-d-elliott@users.noreply.github.com>
-rw-r--r--cmd/authelia-gen/cmd_code.go2
-rw-r--r--cmd/authelia-gen/cmd_docs_data.go2
-rw-r--r--cmd/authelia-gen/helpers.go51
-rw-r--r--cmd/authelia-gen/helpers_test.go4
-rw-r--r--config.template.yml24
-rw-r--r--docs/content/configuration/storage/postgres.md30
-rw-r--r--docs/data/configkeys.json1076
-rw-r--r--docs/static/schemas/v4.39/json-schema/configuration.json30
-rw-r--r--internal/configuration/config.template.yml24
-rw-r--r--internal/configuration/schema/keys.go731
-rw-r--r--internal/configuration/schema/storage.go35
-rw-r--r--internal/configuration/validator/const.go1
-rw-r--r--internal/configuration/validator/storage.go42
-rw-r--r--internal/configuration/validator/storage_test.go280
-rw-r--r--internal/storage/sql_provider_backend_mysql_test.go60
-rw-r--r--internal/storage/sql_provider_backend_postgres.go42
-rw-r--r--internal/storage/sql_provider_backend_postgres_test.go8
-rw-r--r--internal/storage/sql_provider_backend_sqlite_test.go44
18 files changed, 1475 insertions, 1011 deletions
diff --git a/cmd/authelia-gen/cmd_code.go b/cmd/authelia-gen/cmd_code.go
index a704c2949..0d4624237 100644
--- a/cmd/authelia-gen/cmd_code.go
+++ b/cmd/authelia-gen/cmd_code.go
@@ -173,7 +173,7 @@ func codeKeysRunE(cmd *cobra.Command, args []string) (err error) {
data := tmplConfigurationKeysData{
Timestamp: time.Now(),
- Keys: readTags("", reflect.TypeOf(schema.Configuration{}), false, false),
+ Keys: readTags("", reflect.TypeOf(schema.Configuration{}), false, false, true),
}
if root, err = cmd.Flags().GetString(cmdFlagRoot); err != nil {
diff --git a/cmd/authelia-gen/cmd_docs_data.go b/cmd/authelia-gen/cmd_docs_data.go
index 36dd4423b..91f157a54 100644
--- a/cmd/authelia-gen/cmd_docs_data.go
+++ b/cmd/authelia-gen/cmd_docs_data.go
@@ -123,7 +123,7 @@ func docsKeysRunE(cmd *cobra.Command, args []string) (err error) {
data []ConfigurationKey
)
- keys := readTags("", reflect.TypeOf(schema.Configuration{}), true, true)
+ keys := readTags("", reflect.TypeOf(schema.Configuration{}), true, true, true)
for _, key := range keys {
if strings.HasSuffix(key, ".*") {
diff --git a/cmd/authelia-gen/helpers.go b/cmd/authelia-gen/helpers.go
index 0a9894da4..814a35c7e 100644
--- a/cmd/authelia-gen/helpers.go
+++ b/cmd/authelia-gen/helpers.go
@@ -12,6 +12,7 @@ import (
"path/filepath"
"reflect"
"regexp"
+ "sort"
"strings"
"time"
@@ -116,8 +117,20 @@ func readVersion(cmd *cobra.Command) (version *model.SemanticVersion, err error)
return model.NewSemanticVersion(packageJSON.Version)
}
+func readTags(prefix string, t reflect.Type, envSkip, deprecatedSkip, doSort bool) (tags []string) {
+ tags = iReadTags(prefix, t, envSkip, deprecatedSkip, false)
+
+ tags = removeDuplicate(tags)
+
+ if doSort {
+ sort.Strings(tags)
+ }
+
+ return tags
+}
+
//nolint:gocyclo
-func readTags(prefix string, t reflect.Type, envSkip, deprecatedSkip bool) (tags []string) {
+func iReadTags(prefix string, t reflect.Type, envSkip, deprecatedSkip, parentSlice bool) (tags []string) {
tags = make([]string, 0)
if envSkip && (t.Kind() == reflect.Slice || t.Kind() == reflect.Map) {
@@ -126,7 +139,7 @@ func readTags(prefix string, t reflect.Type, envSkip, deprecatedSkip bool) (tags
if t.Kind() != reflect.Struct {
if t.Kind() == reflect.Slice {
- tags = append(tags, readTags(getKeyNameFromTagAndPrefix(prefix, "", true, false), t.Elem(), envSkip, deprecatedSkip)...)
+ tags = append(tags, iReadTags(getKeyNameFromTagAndPrefix(prefix, "", true, false), t.Elem(), envSkip, deprecatedSkip, true)...)
}
return
@@ -150,7 +163,11 @@ func readTags(prefix string, t reflect.Type, envSkip, deprecatedSkip bool) (tags
switch kind := field.Type.Kind(); kind {
case reflect.Struct:
if !containsType(field.Type, decodedTypes) {
- tags = append(tags, readTags(getKeyNameFromTagAndPrefix(prefix, tag, false, false), field.Type, envSkip, deprecatedSkip)...)
+ if parentSlice {
+ tags = append(tags, getKeyNameFromTagAndPrefix(prefix, tag, false, false))
+ }
+
+ tags = append(tags, iReadTags(getKeyNameFromTagAndPrefix(prefix, tag, false, false), field.Type, envSkip, deprecatedSkip, false)...)
continue
}
@@ -169,7 +186,7 @@ func readTags(prefix string, t reflect.Type, envSkip, deprecatedSkip bool) (tags
case reflect.Struct:
if !containsType(field.Type.Elem(), decodedTypes) {
tags = append(tags, getKeyNameFromTagAndPrefix(prefix, tag, false, false))
- tags = append(tags, readTags(getKeyNameFromTagAndPrefix(prefix, tag, kind == reflect.Slice, kind == reflect.Map), field.Type.Elem(), envSkip, deprecatedSkip)...)
+ tags = append(tags, iReadTags(getKeyNameFromTagAndPrefix(prefix, tag, kind == reflect.Slice, kind == reflect.Map), field.Type.Elem(), envSkip, deprecatedSkip, kind == reflect.Slice)...)
continue
}
@@ -178,13 +195,17 @@ func readTags(prefix string, t reflect.Type, envSkip, deprecatedSkip bool) (tags
tags = append(tags, getKeyNameFromTagAndPrefix(prefix, tag, true, true))
}
- tags = append(tags, readTags(getKeyNameFromTagAndPrefix(prefix, tag, kind == reflect.Slice, kind == reflect.Map), field.Type.Elem(), envSkip, deprecatedSkip)...)
+ tags = append(tags, iReadTags(getKeyNameFromTagAndPrefix(prefix, tag, kind == reflect.Slice, kind == reflect.Map), field.Type.Elem(), envSkip, deprecatedSkip, true)...)
}
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, false), field.Type.Elem(), envSkip, deprecatedSkip)...)
+ if parentSlice {
+ tags = append(tags, getKeyNameFromTagAndPrefix(prefix, tag, false, false))
+ }
+
+ tags = append(tags, iReadTags(getKeyNameFromTagAndPrefix(prefix, tag, false, false), field.Type.Elem(), envSkip, deprecatedSkip, false)...)
continue
}
@@ -197,7 +218,7 @@ func readTags(prefix string, t reflect.Type, envSkip, deprecatedSkip bool) (tags
if k == reflect.Struct {
if !containsType(field.Type.Elem(), decodedTypes) {
- tags = append(tags, readTags(getKeyNameFromTagAndPrefix(prefix, tag, true, false), field.Type.Elem(), envSkip, deprecatedSkip)...)
+ tags = append(tags, iReadTags(getKeyNameFromTagAndPrefix(prefix, tag, true, false), field.Type.Elem(), envSkip, deprecatedSkip, field.Type.Elem().Kind() == reflect.Slice)...)
continue
}
@@ -309,3 +330,19 @@ func readCompose(path string) (compose *Compose, err error) {
return compose, nil
}
+
+func removeDuplicate[T comparable](sliceList []T) []T {
+ var list []T
+
+ allKeys := make(map[T]bool)
+
+ for _, item := range sliceList {
+ if _, value := allKeys[item]; !value {
+ allKeys[item] = true
+
+ list = append(list, item)
+ }
+ }
+
+ return list
+}
diff --git a/cmd/authelia-gen/helpers_test.go b/cmd/authelia-gen/helpers_test.go
index a161e5d8e..a6aac0ccc 100644
--- a/cmd/authelia-gen/helpers_test.go
+++ b/cmd/authelia-gen/helpers_test.go
@@ -136,10 +136,10 @@ func TestContainsType(t *testing.T) {
func TestReadTags(t *testing.T) {
assert.NotPanics(t, func() {
- readTags("", reflect.TypeOf(schema.Configuration{}), false, false)
+ iReadTags("", reflect.TypeOf(schema.Configuration{}), false, false, false)
})
assert.NotPanics(t, func() {
- readTags("", reflect.TypeOf(schema.Configuration{}), true, true)
+ iReadTags("", reflect.TypeOf(schema.Configuration{}), true, true, false)
})
}
diff --git a/config.template.yml b/config.template.yml
index 2e01b7a15..0fd1756e9 100644
--- a/config.template.yml
+++ b/config.template.yml
@@ -1076,6 +1076,30 @@ session:
## The default scheme is 'unix' if the address is an absolute path otherwise it's 'tcp'. The default port is '5432'.
# address: 'tcp://127.0.0.1:5432'
+ ## List of additional server instance configurations to fallback to when the primary instance is not available.
+ # servers:
+ # -
+ ## The Address of this individual instance.
+ # address: 'tcp://127.0.0.1:5432'
+
+ ## The TLS configuration for this individual instance.
+ # tls:
+ # server_name: 'postgres.example.com'
+ # skip_verify: false
+ # minimum_version: 'TLS1.2'
+ # maximum_version: 'TLS1.3'
+ # certificate_chain: |
+ # -----BEGIN CERTIFICATE-----
+ # ...
+ # -----END CERTIFICATE-----
+ # -----BEGIN CERTIFICATE-----
+ # ...
+ # -----END CERTIFICATE-----
+ # private_key: |
+ # -----BEGIN RSA PRIVATE KEY-----
+ # ...
+ # -----END RSA PRIVATE KEY-----
+
## The database name to use.
# database: 'authelia'
diff --git a/docs/content/configuration/storage/postgres.md b/docs/content/configuration/storage/postgres.md
index 2e04f3aeb..78bdeda34 100644
--- a/docs/content/configuration/storage/postgres.md
+++ b/docs/content/configuration/storage/postgres.md
@@ -36,6 +36,7 @@ storage:
encryption_key: 'a_very_important_secret'
postgres:
address: 'tcp://127.0.0.1:5432'
+ servers: []
database: 'authelia'
schema: 'public'
username: 'authelia'
@@ -94,6 +95,35 @@ storage:
address: 'unix:///var/run/postgres.sock'
```
+### servers
+
+{{< confkey type="list(object)" required="no" >}}
+
+This specifies a list of additional fallback [PostgreSQL] instances to use should issues occur with the primary instance
+which is configured with the [address](#address) and [tls](#tls) options.
+
+Each server instance has the [address](#address) and [tls](#tls) option which both have the same requirements and
+effect, and have the same configuration syntax. This means all other settings including but not limited to
+[database](#database), [schema](#schema), [username](#username), and [password](#password); must be the same as the
+primary instance, and they must be fully replicated.
+
+Example configuration:
+
+```yaml
+storage:
+ postgres:
+ address: 'tcp://postgres1:5432'
+ tls:
+ server_name: 'postgres1.local'
+ servers:
+ - address: 'tcp://postgres2:5432'
+ tls:
+ server_name: 'postgres2.local'
+ - address: 'tcp://postgres3:5432'
+ tls:
+ server_name: 'postgres3.local'
+```
+
### database
{{< confkey type="string" required="yes" >}}
diff --git a/docs/data/configkeys.json b/docs/data/configkeys.json
index a93d83920..19ff5d878 100644
--- a/docs/data/configkeys.json
+++ b/docs/data/configkeys.json
@@ -1,308 +1,308 @@
[
{
- "path": "theme",
+ "path": "access_control.default_policy",
"secret": false,
- "env": "AUTHELIA_THEME"
+ "env": "AUTHELIA_ACCESS_CONTROL_DEFAULT_POLICY"
},
{
- "path": "certificates_directory",
+ "path": "authentication_backend.file.password.algorithm",
"secret": false,
- "env": "AUTHELIA_CERTIFICATES_DIRECTORY"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_ALGORITHM"
},
{
- "path": "default_2fa_method",
+ "path": "authentication_backend.file.password.argon2.iterations",
"secret": false,
- "env": "AUTHELIA_DEFAULT_2FA_METHOD"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_ARGON2_ITERATIONS"
},
{
- "path": "log.level",
+ "path": "authentication_backend.file.password.argon2.key_length",
"secret": false,
- "env": "AUTHELIA_LOG_LEVEL"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_ARGON2_KEY_LENGTH"
},
{
- "path": "log.format",
+ "path": "authentication_backend.file.password.argon2.memory",
"secret": false,
- "env": "AUTHELIA_LOG_FORMAT"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_ARGON2_MEMORY"
},
{
- "path": "log.file_path",
+ "path": "authentication_backend.file.password.argon2.parallelism",
"secret": false,
- "env": "AUTHELIA_LOG_FILE_PATH"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_ARGON2_PARALLELISM"
},
{
- "path": "log.keep_stdout",
+ "path": "authentication_backend.file.password.argon2.salt_length",
"secret": false,
- "env": "AUTHELIA_LOG_KEEP_STDOUT"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_ARGON2_SALT_LENGTH"
},
{
- "path": "identity_providers.oidc.hmac_secret",
- "secret": true,
- "env": "AUTHELIA_IDENTITY_PROVIDERS_OIDC_HMAC_SECRET_FILE"
+ "path": "authentication_backend.file.password.argon2.variant",
+ "secret": false,
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_ARGON2_VARIANT"
},
{
- "path": "identity_providers.oidc.enable_client_debug_messages",
+ "path": "authentication_backend.file.password.bcrypt.cost",
"secret": false,
- "env": "AUTHELIA_IDENTITY_PROVIDERS_OIDC_ENABLE_CLIENT_DEBUG_MESSAGES"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_BCRYPT_COST"
},
{
- "path": "identity_providers.oidc.minimum_parameter_entropy",
+ "path": "authentication_backend.file.password.bcrypt.variant",
"secret": false,
- "env": "AUTHELIA_IDENTITY_PROVIDERS_OIDC_MINIMUM_PARAMETER_ENTROPY"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_BCRYPT_VARIANT"
},
{
- "path": "identity_providers.oidc.enforce_pkce",
+ "path": "authentication_backend.file.password.pbkdf2.iterations",
"secret": false,
- "env": "AUTHELIA_IDENTITY_PROVIDERS_OIDC_ENFORCE_PKCE"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_PBKDF2_ITERATIONS"
},
{
- "path": "identity_providers.oidc.enable_pkce_plain_challenge",
+ "path": "authentication_backend.file.password.pbkdf2.salt_length",
"secret": false,
- "env": "AUTHELIA_IDENTITY_PROVIDERS_OIDC_ENABLE_PKCE_PLAIN_CHALLENGE"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_PBKDF2_SALT_LENGTH"
},
{
- "path": "identity_providers.oidc.enable_jwt_access_token_stateless_introspection",
+ "path": "authentication_backend.file.password.pbkdf2.variant",
"secret": false,
- "env": "AUTHELIA_IDENTITY_PROVIDERS_OIDC_ENABLE_JWT_ACCESS_TOKEN_STATELESS_INTROSPECTION"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_PBKDF2_VARIANT"
},
{
- "path": "identity_providers.oidc.discovery_signed_response_alg",
+ "path": "authentication_backend.file.password.scrypt.block_size",
"secret": false,
- "env": "AUTHELIA_IDENTITY_PROVIDERS_OIDC_DISCOVERY_SIGNED_RESPONSE_ALG"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_SCRYPT_BLOCK_SIZE"
},
{
- "path": "identity_providers.oidc.discovery_signed_response_key_id",
+ "path": "authentication_backend.file.password.scrypt.iterations",
"secret": false,
- "env": "AUTHELIA_IDENTITY_PROVIDERS_OIDC_DISCOVERY_SIGNED_RESPONSE_KEY_ID"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_SCRYPT_ITERATIONS"
},
{
- "path": "identity_providers.oidc.require_pushed_authorization_requests",
+ "path": "authentication_backend.file.password.scrypt.key_length",
"secret": false,
- "env": "AUTHELIA_IDENTITY_PROVIDERS_OIDC_REQUIRE_PUSHED_AUTHORIZATION_REQUESTS"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_SCRYPT_KEY_LENGTH"
},
{
- "path": "identity_providers.oidc.cors.endpoints",
+ "path": "authentication_backend.file.password.scrypt.parallelism",
"secret": false,
- "env": "AUTHELIA_IDENTITY_PROVIDERS_OIDC_CORS_ENDPOINTS"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_SCRYPT_PARALLELISM"
},
{
- "path": "identity_providers.oidc.cors.allowed_origins_from_client_redirect_uris",
+ "path": "authentication_backend.file.password.scrypt.salt_length",
"secret": false,
- "env": "AUTHELIA_IDENTITY_PROVIDERS_OIDC_CORS_ALLOWED_ORIGINS_FROM_CLIENT_REDIRECT_URIS"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_SCRYPT_SALT_LENGTH"
},
{
- "path": "identity_providers.oidc.lifespans.access_token",
+ "path": "authentication_backend.file.password.sha2crypt.iterations",
"secret": false,
- "env": "AUTHELIA_IDENTITY_PROVIDERS_OIDC_LIFESPANS_ACCESS_TOKEN"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_SHA2CRYPT_ITERATIONS"
},
{
- "path": "identity_providers.oidc.lifespans.authorize_code",
+ "path": "authentication_backend.file.password.sha2crypt.salt_length",
"secret": false,
- "env": "AUTHELIA_IDENTITY_PROVIDERS_OIDC_LIFESPANS_AUTHORIZE_CODE"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_SHA2CRYPT_SALT_LENGTH"
},
{
- "path": "identity_providers.oidc.lifespans.id_token",
+ "path": "authentication_backend.file.password.sha2crypt.variant",
"secret": false,
- "env": "AUTHELIA_IDENTITY_PROVIDERS_OIDC_LIFESPANS_ID_TOKEN"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_SHA2CRYPT_VARIANT"
},
{
- "path": "identity_providers.oidc.lifespans.refresh_token",
+ "path": "authentication_backend.file.path",
"secret": false,
- "env": "AUTHELIA_IDENTITY_PROVIDERS_OIDC_LIFESPANS_REFRESH_TOKEN"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PATH"
},
{
- "path": "identity_providers.oidc.lifespans.jwt_secured_authorization",
+ "path": "authentication_backend.file.search.case_insensitive",
"secret": false,
- "env": "AUTHELIA_IDENTITY_PROVIDERS_OIDC_LIFESPANS_JWT_SECURED_AUTHORIZATION"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_SEARCH_CASE_INSENSITIVE"
},
{
- "path": "identity_providers.oidc",
+ "path": "authentication_backend.file.search.email",
"secret": false,
- "env": "AUTHELIA_IDENTITY_PROVIDERS_OIDC"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_SEARCH_EMAIL"
},
{
- "path": "authentication_backend.password_reset.disable",
+ "path": "authentication_backend.file.watch",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_PASSWORD_RESET_DISABLE"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_WATCH"
},
{
- "path": "authentication_backend.password_reset.custom_url",
+ "path": "authentication_backend.ldap.additional_groups_dn",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_PASSWORD_RESET_CUSTOM_URL"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ADDITIONAL_GROUPS_DN"
},
{
- "path": "authentication_backend.refresh_interval",
+ "path": "authentication_backend.ldap.additional_users_dn",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_REFRESH_INTERVAL"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ADDITIONAL_USERS_DN"
},
{
- "path": "authentication_backend.file.path",
+ "path": "authentication_backend.ldap.address",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PATH"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ADDRESS"
},
{
- "path": "authentication_backend.file.watch",
+ "path": "authentication_backend.ldap.attributes.birthdate",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_WATCH"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_BIRTHDATE"
},
{
- "path": "authentication_backend.file.password.algorithm",
+ "path": "authentication_backend.ldap.attributes.country",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_ALGORITHM"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_COUNTRY"
},
{
- "path": "authentication_backend.file.password.argon2.variant",
+ "path": "authentication_backend.ldap.attributes.display_name",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_ARGON2_VARIANT"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_DISPLAY_NAME"
},
{
- "path": "authentication_backend.file.password.argon2.iterations",
+ "path": "authentication_backend.ldap.attributes.distinguished_name",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_ARGON2_ITERATIONS"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_DISTINGUISHED_NAME"
},
{
- "path": "authentication_backend.file.password.argon2.memory",
+ "path": "authentication_backend.ldap.attributes.family_name",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_ARGON2_MEMORY"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_FAMILY_NAME"
},
{
- "path": "authentication_backend.file.password.argon2.parallelism",
+ "path": "authentication_backend.ldap.attributes.gender",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_ARGON2_PARALLELISM"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_GENDER"
},
{
- "path": "authentication_backend.file.password.argon2.key_length",
+ "path": "authentication_backend.ldap.attributes.given_name",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_ARGON2_KEY_LENGTH"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_GIVEN_NAME"
},
{
- "path": "authentication_backend.file.password.argon2.salt_length",
+ "path": "authentication_backend.ldap.attributes.group_name",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_ARGON2_SALT_LENGTH"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_GROUP_NAME"
},
{
- "path": "authentication_backend.file.password.sha2crypt.variant",
+ "path": "authentication_backend.ldap.attributes.locale",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_SHA2CRYPT_VARIANT"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_LOCALE"
},
{
- "path": "authentication_backend.file.password.sha2crypt.iterations",
+ "path": "authentication_backend.ldap.attributes.locality",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_SHA2CRYPT_ITERATIONS"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_LOCALITY"
},
{
- "path": "authentication_backend.file.password.sha2crypt.salt_length",
+ "path": "authentication_backend.ldap.attributes.mail",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_SHA2CRYPT_SALT_LENGTH"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_MAIL"
},
{
- "path": "authentication_backend.file.password.pbkdf2.variant",
+ "path": "authentication_backend.ldap.attributes.member_of",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_PBKDF2_VARIANT"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_MEMBER_OF"
},
{
- "path": "authentication_backend.file.password.pbkdf2.iterations",
+ "path": "authentication_backend.ldap.attributes.middle_name",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_PBKDF2_ITERATIONS"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_MIDDLE_NAME"
},
{
- "path": "authentication_backend.file.password.pbkdf2.salt_length",
+ "path": "authentication_backend.ldap.attributes.nickname",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_PBKDF2_SALT_LENGTH"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_NICKNAME"
},
{
- "path": "authentication_backend.file.password.bcrypt.variant",
+ "path": "authentication_backend.ldap.attributes.phone_extension",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_BCRYPT_VARIANT"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_PHONE_EXTENSION"
},
{
- "path": "authentication_backend.file.password.bcrypt.cost",
+ "path": "authentication_backend.ldap.attributes.phone_number",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_BCRYPT_COST"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_PHONE_NUMBER"
},
{
- "path": "authentication_backend.file.password.scrypt.iterations",
+ "path": "authentication_backend.ldap.attributes.picture",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_SCRYPT_ITERATIONS"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_PICTURE"
},
{
- "path": "authentication_backend.file.password.scrypt.block_size",
+ "path": "authentication_backend.ldap.attributes.postal_code",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_SCRYPT_BLOCK_SIZE"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_POSTAL_CODE"
},
{
- "path": "authentication_backend.file.password.scrypt.parallelism",
+ "path": "authentication_backend.ldap.attributes.profile",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_SCRYPT_PARALLELISM"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_PROFILE"
},
{
- "path": "authentication_backend.file.password.scrypt.key_length",
+ "path": "authentication_backend.ldap.attributes.region",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_SCRYPT_KEY_LENGTH"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_REGION"
},
{
- "path": "authentication_backend.file.password.scrypt.salt_length",
+ "path": "authentication_backend.ldap.attributes.street_address",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_SCRYPT_SALT_LENGTH"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_STREET_ADDRESS"
},
{
- "path": "authentication_backend.file.search.email",
+ "path": "authentication_backend.ldap.attributes.username",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_SEARCH_EMAIL"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_USERNAME"
},
{
- "path": "authentication_backend.file.search.case_insensitive",
+ "path": "authentication_backend.ldap.attributes.website",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_FILE_SEARCH_CASE_INSENSITIVE"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_WEBSITE"
},
{
- "path": "authentication_backend.ldap.address",
+ "path": "authentication_backend.ldap.attributes.zoneinfo",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ADDRESS"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_ZONEINFO"
},
{
- "path": "authentication_backend.ldap.implementation",
+ "path": "authentication_backend.ldap.base_dn",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_IMPLEMENTATION"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_BASE_DN"
},
{
- "path": "authentication_backend.ldap.timeout",
+ "path": "authentication_backend.ldap.group_search_mode",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_TIMEOUT"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_GROUP_SEARCH_MODE"
},
{
- "path": "authentication_backend.ldap.start_tls",
+ "path": "authentication_backend.ldap.groups_filter",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_START_TLS"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_GROUPS_FILTER"
},
{
- "path": "authentication_backend.ldap.tls.minimum_version",
+ "path": "authentication_backend.ldap.implementation",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_TLS_MINIMUM_VERSION"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_IMPLEMENTATION"
},
{
- "path": "authentication_backend.ldap.tls.maximum_version",
- "secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_TLS_MAXIMUM_VERSION"
+ "path": "authentication_backend.ldap.password",
+ "secret": true,
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PASSWORD_FILE"
},
{
- "path": "authentication_backend.ldap.tls.skip_verify",
+ "path": "authentication_backend.ldap.permit_feature_detection_failure",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_TLS_SKIP_VERIFY"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PERMIT_FEATURE_DETECTION_FAILURE"
},
{
- "path": "authentication_backend.ldap.tls.server_name",
+ "path": "authentication_backend.ldap.permit_referrals",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_TLS_SERVER_NAME"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PERMIT_REFERRALS"
},
{
- "path": "authentication_backend.ldap.tls.private_key",
- "secret": true,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_TLS_PRIVATE_KEY_FILE"
+ "path": "authentication_backend.ldap.permit_unauthenticated_bind",
+ "secret": false,
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PERMIT_UNAUTHENTICATED_BIND"
},
{
- "path": "authentication_backend.ldap.tls.certificate_chain",
- "secret": true,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_TLS_CERTIFICATE_CHAIN_FILE"
+ "path": "authentication_backend.ldap.pooling.count",
+ "secret": false,
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_POOLING_COUNT"
},
{
"path": "authentication_backend.ldap.pooling.enable",
@@ -310,11 +310,6 @@
"env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_POOLING_ENABLE"
},
{
- "path": "authentication_backend.ldap.pooling.count",
- "secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_POOLING_COUNT"
- },
- {
"path": "authentication_backend.ldap.pooling.retries",
"secret": false,
"env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_POOLING_RETRIES"
@@ -325,434 +320,434 @@
"env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_POOLING_TIMEOUT"
},
{
- "path": "authentication_backend.ldap.base_dn",
+ "path": "authentication_backend.ldap.start_tls",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_BASE_DN"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_START_TLS"
},
{
- "path": "authentication_backend.ldap.additional_users_dn",
+ "path": "authentication_backend.ldap.timeout",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ADDITIONAL_USERS_DN"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_TIMEOUT"
},
{
- "path": "authentication_backend.ldap.users_filter",
- "secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_USERS_FILTER"
+ "path": "authentication_backend.ldap.tls.certificate_chain",
+ "secret": true,
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_TLS_CERTIFICATE_CHAIN_FILE"
},
{
- "path": "authentication_backend.ldap.additional_groups_dn",
+ "path": "authentication_backend.ldap.tls.maximum_version",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ADDITIONAL_GROUPS_DN"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_TLS_MAXIMUM_VERSION"
},
{
- "path": "authentication_backend.ldap.groups_filter",
+ "path": "authentication_backend.ldap.tls.minimum_version",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_GROUPS_FILTER"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_TLS_MINIMUM_VERSION"
},
{
- "path": "authentication_backend.ldap.group_search_mode",
- "secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_GROUP_SEARCH_MODE"
+ "path": "authentication_backend.ldap.tls.private_key",
+ "secret": true,
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_TLS_PRIVATE_KEY_FILE"
},
{
- "path": "authentication_backend.ldap.attributes.distinguished_name",
+ "path": "authentication_backend.ldap.tls.server_name",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_DISTINGUISHED_NAME"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_TLS_SERVER_NAME"
},
{
- "path": "authentication_backend.ldap.attributes.username",
+ "path": "authentication_backend.ldap.tls.skip_verify",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_USERNAME"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_TLS_SKIP_VERIFY"
},
{
- "path": "authentication_backend.ldap.attributes.display_name",
+ "path": "authentication_backend.ldap.user",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_DISPLAY_NAME"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_USER"
},
{
- "path": "authentication_backend.ldap.attributes.family_name",
+ "path": "authentication_backend.ldap.users_filter",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_FAMILY_NAME"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_USERS_FILTER"
},
{
- "path": "authentication_backend.ldap.attributes.given_name",
+ "path": "authentication_backend.password_reset.custom_url",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_GIVEN_NAME"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_PASSWORD_RESET_CUSTOM_URL"
},
{
- "path": "authentication_backend.ldap.attributes.middle_name",
+ "path": "authentication_backend.password_reset.disable",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_MIDDLE_NAME"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_PASSWORD_RESET_DISABLE"
},
{
- "path": "authentication_backend.ldap.attributes.nickname",
+ "path": "authentication_backend.refresh_interval",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_NICKNAME"
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_REFRESH_INTERVAL"
},
{
- "path": "authentication_backend.ldap.attributes.gender",
+ "path": "certificates_directory",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_GENDER"
+ "env": "AUTHELIA_CERTIFICATES_DIRECTORY"
},
{
- "path": "authentication_backend.ldap.attributes.birthdate",
+ "path": "default_2fa_method",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_BIRTHDATE"
+ "env": "AUTHELIA_DEFAULT_2FA_METHOD"
},
{
- "path": "authentication_backend.ldap.attributes.website",
+ "path": "duo_api.disable",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_WEBSITE"
+ "env": "AUTHELIA_DUO_API_DISABLE"
},
{
- "path": "authentication_backend.ldap.attributes.profile",
+ "path": "duo_api.enable_self_enrollment",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_PROFILE"
+ "env": "AUTHELIA_DUO_API_ENABLE_SELF_ENROLLMENT"
},
{
- "path": "authentication_backend.ldap.attributes.picture",
+ "path": "duo_api.hostname",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_PICTURE"
+ "env": "AUTHELIA_DUO_API_HOSTNAME"
},
{
- "path": "authentication_backend.ldap.attributes.zoneinfo",
- "secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_ZONEINFO"
+ "path": "duo_api.integration_key",
+ "secret": true,
+ "env": "AUTHELIA_DUO_API_INTEGRATION_KEY_FILE"
},
{
- "path": "authentication_backend.ldap.attributes.locale",
- "secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_LOCALE"
+ "path": "duo_api.secret_key",
+ "secret": true,
+ "env": "AUTHELIA_DUO_API_SECRET_KEY_FILE"
},
{
- "path": "authentication_backend.ldap.attributes.phone_number",
+ "path": "identity_providers.oidc",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_PHONE_NUMBER"
+ "env": "AUTHELIA_IDENTITY_PROVIDERS_OIDC"
},
{
- "path": "authentication_backend.ldap.attributes.phone_extension",
+ "path": "identity_providers.oidc.cors.allowed_origins_from_client_redirect_uris",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_PHONE_EXTENSION"
+ "env": "AUTHELIA_IDENTITY_PROVIDERS_OIDC_CORS_ALLOWED_ORIGINS_FROM_CLIENT_REDIRECT_URIS"
},
{
- "path": "authentication_backend.ldap.attributes.street_address",
+ "path": "identity_providers.oidc.cors.endpoints",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_STREET_ADDRESS"
+ "env": "AUTHELIA_IDENTITY_PROVIDERS_OIDC_CORS_ENDPOINTS"
},
{
- "path": "authentication_backend.ldap.attributes.locality",
+ "path": "identity_providers.oidc.discovery_signed_response_alg",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_LOCALITY"
+ "env": "AUTHELIA_IDENTITY_PROVIDERS_OIDC_DISCOVERY_SIGNED_RESPONSE_ALG"
},
{
- "path": "authentication_backend.ldap.attributes.region",
+ "path": "identity_providers.oidc.discovery_signed_response_key_id",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_REGION"
+ "env": "AUTHELIA_IDENTITY_PROVIDERS_OIDC_DISCOVERY_SIGNED_RESPONSE_KEY_ID"
},
{
- "path": "authentication_backend.ldap.attributes.postal_code",
+ "path": "identity_providers.oidc.enable_client_debug_messages",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_POSTAL_CODE"
+ "env": "AUTHELIA_IDENTITY_PROVIDERS_OIDC_ENABLE_CLIENT_DEBUG_MESSAGES"
},
{
- "path": "authentication_backend.ldap.attributes.country",
+ "path": "identity_providers.oidc.enable_jwt_access_token_stateless_introspection",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_COUNTRY"
+ "env": "AUTHELIA_IDENTITY_PROVIDERS_OIDC_ENABLE_JWT_ACCESS_TOKEN_STATELESS_INTROSPECTION"
},
{
- "path": "authentication_backend.ldap.attributes.mail",
+ "path": "identity_providers.oidc.enable_pkce_plain_challenge",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_MAIL"
+ "env": "AUTHELIA_IDENTITY_PROVIDERS_OIDC_ENABLE_PKCE_PLAIN_CHALLENGE"
},
{
- "path": "authentication_backend.ldap.attributes.member_of",
+ "path": "identity_providers.oidc.enforce_pkce",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_MEMBER_OF"
+ "env": "AUTHELIA_IDENTITY_PROVIDERS_OIDC_ENFORCE_PKCE"
},
{
- "path": "authentication_backend.ldap.attributes.group_name",
- "secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ATTRIBUTES_GROUP_NAME"
+ "path": "identity_providers.oidc.hmac_secret",
+ "secret": true,
+ "env": "AUTHELIA_IDENTITY_PROVIDERS_OIDC_HMAC_SECRET_FILE"
},
{
- "path": "authentication_backend.ldap.permit_referrals",
+ "path": "identity_providers.oidc.lifespans.access_token",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PERMIT_REFERRALS"
+ "env": "AUTHELIA_IDENTITY_PROVIDERS_OIDC_LIFESPANS_ACCESS_TOKEN"
},
{
- "path": "authentication_backend.ldap.permit_unauthenticated_bind",
+ "path": "identity_providers.oidc.lifespans.authorize_code",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PERMIT_UNAUTHENTICATED_BIND"
+ "env": "AUTHELIA_IDENTITY_PROVIDERS_OIDC_LIFESPANS_AUTHORIZE_CODE"
},
{
- "path": "authentication_backend.ldap.permit_feature_detection_failure",
+ "path": "identity_providers.oidc.lifespans.id_token",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PERMIT_FEATURE_DETECTION_FAILURE"
+ "env": "AUTHELIA_IDENTITY_PROVIDERS_OIDC_LIFESPANS_ID_TOKEN"
},
{
- "path": "authentication_backend.ldap.user",
+ "path": "identity_providers.oidc.lifespans.jwt_secured_authorization",
"secret": false,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_USER"
+ "env": "AUTHELIA_IDENTITY_PROVIDERS_OIDC_LIFESPANS_JWT_SECURED_AUTHORIZATION"
},
{
- "path": "authentication_backend.ldap.password",
- "secret": true,
- "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PASSWORD_FILE"
+ "path": "identity_providers.oidc.lifespans.refresh_token",
+ "secret": false,
+ "env": "AUTHELIA_IDENTITY_PROVIDERS_OIDC_LIFESPANS_REFRESH_TOKEN"
},
{
- "path": "session.name",
+ "path": "identity_providers.oidc.minimum_parameter_entropy",
"secret": false,
- "env": "AUTHELIA_SESSION_NAME"
+ "env": "AUTHELIA_IDENTITY_PROVIDERS_OIDC_MINIMUM_PARAMETER_ENTROPY"
},
{
- "path": "session.same_site",
+ "path": "identity_providers.oidc.require_pushed_authorization_requests",
"secret": false,
- "env": "AUTHELIA_SESSION_SAME_SITE"
+ "env": "AUTHELIA_IDENTITY_PROVIDERS_OIDC_REQUIRE_PUSHED_AUTHORIZATION_REQUESTS"
},
{
- "path": "session.expiration",
+ "path": "identity_validation.elevated_session.characters",
"secret": false,
- "env": "AUTHELIA_SESSION_EXPIRATION"
+ "env": "AUTHELIA_IDENTITY_VALIDATION_ELEVATED_SESSION_CHARACTERS"
},
{
- "path": "session.inactivity",
+ "path": "identity_validation.elevated_session.code_lifespan",
"secret": false,
- "env": "AUTHELIA_SESSION_INACTIVITY"
+ "env": "AUTHELIA_IDENTITY_VALIDATION_ELEVATED_SESSION_CODE_LIFESPAN"
},
{
- "path": "session.remember_me",
+ "path": "identity_validation.elevated_session.elevation_lifespan",
"secret": false,
- "env": "AUTHELIA_SESSION_REMEMBER_ME"
+ "env": "AUTHELIA_IDENTITY_VALIDATION_ELEVATED_SESSION_ELEVATION_LIFESPAN"
},
{
- "path": "session",
+ "path": "identity_validation.elevated_session.require_second_factor",
"secret": false,
- "env": "AUTHELIA_SESSION"
+ "env": "AUTHELIA_IDENTITY_VALIDATION_ELEVATED_SESSION_REQUIRE_SECOND_FACTOR"
},
{
- "path": "session.secret",
- "secret": true,
- "env": "AUTHELIA_SESSION_SECRET_FILE"
+ "path": "identity_validation.elevated_session.skip_second_factor",
+ "secret": false,
+ "env": "AUTHELIA_IDENTITY_VALIDATION_ELEVATED_SESSION_SKIP_SECOND_FACTOR"
},
{
- "path": "session.redis.host",
+ "path": "identity_validation.reset_password.jwt_algorithm",
"secret": false,
- "env": "AUTHELIA_SESSION_REDIS_HOST"
+ "env": "AUTHELIA_IDENTITY_VALIDATION_RESET_PASSWORD_JWT_ALGORITHM"
},
{
- "path": "session.redis.port",
+ "path": "identity_validation.reset_password.jwt_lifespan",
"secret": false,
- "env": "AUTHELIA_SESSION_REDIS_PORT"
+ "env": "AUTHELIA_IDENTITY_VALIDATION_RESET_PASSWORD_JWT_LIFESPAN"
},
{
- "path": "session.redis.timeout",
- "secret": false,
- "env": "AUTHELIA_SESSION_REDIS_TIMEOUT"
+ "path": "identity_validation.reset_password.jwt_secret",
+ "secret": true,
+ "env": "AUTHELIA_IDENTITY_VALIDATION_RESET_PASSWORD_JWT_SECRET_FILE"
},
{
- "path": "session.redis.max_retries",
+ "path": "log.file_path",
"secret": false,
- "env": "AUTHELIA_SESSION_REDIS_MAX_RETRIES"
+ "env": "AUTHELIA_LOG_FILE_PATH"
},
{
- "path": "session.redis.username",
+ "path": "log.format",
"secret": false,
- "env": "AUTHELIA_SESSION_REDIS_USERNAME"
+ "env": "AUTHELIA_LOG_FORMAT"
},
{
- "path": "session.redis.password",
- "secret": true,
- "env": "AUTHELIA_SESSION_REDIS_PASSWORD_FILE"
+ "path": "log.keep_stdout",
+ "secret": false,
+ "env": "AUTHELIA_LOG_KEEP_STDOUT"
},
{
- "path": "session.redis.database_index",
+ "path": "log.level",
"secret": false,
- "env": "AUTHELIA_SESSION_REDIS_DATABASE_INDEX"
+ "env": "AUTHELIA_LOG_LEVEL"
},
{
- "path": "session.redis.maximum_active_connections",
+ "path": "notifier.disable_startup_check",
"secret": false,
- "env": "AUTHELIA_SESSION_REDIS_MAXIMUM_ACTIVE_CONNECTIONS"
+ "env": "AUTHELIA_NOTIFIER_DISABLE_STARTUP_CHECK"
},
{
- "path": "session.redis.minimum_idle_connections",
+ "path": "notifier.filesystem.filename",
"secret": false,
- "env": "AUTHELIA_SESSION_REDIS_MINIMUM_IDLE_CONNECTIONS"
+ "env": "AUTHELIA_NOTIFIER_FILESYSTEM_FILENAME"
},
{
- "path": "session.redis.tls.minimum_version",
+ "path": "notifier.smtp.address",
"secret": false,
- "env": "AUTHELIA_SESSION_REDIS_TLS_MINIMUM_VERSION"
+ "env": "AUTHELIA_NOTIFIER_SMTP_ADDRESS"
},
{
- "path": "session.redis.tls.maximum_version",
+ "path": "notifier.smtp.disable_html_emails",
"secret": false,
- "env": "AUTHELIA_SESSION_REDIS_TLS_MAXIMUM_VERSION"
+ "env": "AUTHELIA_NOTIFIER_SMTP_DISABLE_HTML_EMAILS"
},
{
- "path": "session.redis.tls.skip_verify",
+ "path": "notifier.smtp.disable_require_tls",
"secret": false,
- "env": "AUTHELIA_SESSION_REDIS_TLS_SKIP_VERIFY"
+ "env": "AUTHELIA_NOTIFIER_SMTP_DISABLE_REQUIRE_TLS"
},
{
- "path": "session.redis.tls.server_name",
+ "path": "notifier.smtp.disable_starttls",
"secret": false,
- "env": "AUTHELIA_SESSION_REDIS_TLS_SERVER_NAME"
+ "env": "AUTHELIA_NOTIFIER_SMTP_DISABLE_STARTTLS"
},
{
- "path": "session.redis.tls.private_key",
- "secret": true,
- "env": "AUTHELIA_SESSION_REDIS_TLS_PRIVATE_KEY_FILE"
+ "path": "notifier.smtp.identifier",
+ "secret": false,
+ "env": "AUTHELIA_NOTIFIER_SMTP_IDENTIFIER"
},
{
- "path": "session.redis.tls.certificate_chain",
+ "path": "notifier.smtp.password",
"secret": true,
- "env": "AUTHELIA_SESSION_REDIS_TLS_CERTIFICATE_CHAIN_FILE"
+ "env": "AUTHELIA_NOTIFIER_SMTP_PASSWORD_FILE"
},
{
- "path": "session.redis.high_availability.sentinel_name",
+ "path": "notifier.smtp.sender",
"secret": false,
- "env": "AUTHELIA_SESSION_REDIS_HIGH_AVAILABILITY_SENTINEL_NAME"
+ "env": "AUTHELIA_NOTIFIER_SMTP_SENDER"
},
{
- "path": "session.redis.high_availability.sentinel_username",
+ "path": "notifier.smtp.startup_check_address",
"secret": false,
- "env": "AUTHELIA_SESSION_REDIS_HIGH_AVAILABILITY_SENTINEL_USERNAME"
+ "env": "AUTHELIA_NOTIFIER_SMTP_STARTUP_CHECK_ADDRESS"
},
{
- "path": "session.redis.high_availability.sentinel_password",
- "secret": true,
- "env": "AUTHELIA_SESSION_REDIS_HIGH_AVAILABILITY_SENTINEL_PASSWORD_FILE"
+ "path": "notifier.smtp.subject",
+ "secret": false,
+ "env": "AUTHELIA_NOTIFIER_SMTP_SUBJECT"
},
{
- "path": "session.redis.high_availability.route_by_latency",
+ "path": "notifier.smtp.timeout",
"secret": false,
- "env": "AUTHELIA_SESSION_REDIS_HIGH_AVAILABILITY_ROUTE_BY_LATENCY"
+ "env": "AUTHELIA_NOTIFIER_SMTP_TIMEOUT"
},
{
- "path": "session.redis.high_availability.route_randomly",
- "secret": false,
- "env": "AUTHELIA_SESSION_REDIS_HIGH_AVAILABILITY_ROUTE_RANDOMLY"
+ "path": "notifier.smtp.tls.certificate_chain",
+ "secret": true,
+ "env": "AUTHELIA_NOTIFIER_SMTP_TLS_CERTIFICATE_CHAIN_FILE"
},
{
- "path": "totp.disable",
+ "path": "notifier.smtp.tls.maximum_version",
"secret": false,
- "env": "AUTHELIA_TOTP_DISABLE"
+ "env": "AUTHELIA_NOTIFIER_SMTP_TLS_MAXIMUM_VERSION"
},
{
- "path": "totp.issuer",
+ "path": "notifier.smtp.tls.minimum_version",
"secret": false,
- "env": "AUTHELIA_TOTP_ISSUER"
+ "env": "AUTHELIA_NOTIFIER_SMTP_TLS_MINIMUM_VERSION"
},
{
- "path": "totp.algorithm",
- "secret": false,
- "env": "AUTHELIA_TOTP_ALGORITHM"
+ "path": "notifier.smtp.tls.private_key",
+ "secret": true,
+ "env": "AUTHELIA_NOTIFIER_SMTP_TLS_PRIVATE_KEY_FILE"
},
{
- "path": "totp.digits",
+ "path": "notifier.smtp.tls.server_name",
"secret": false,
- "env": "AUTHELIA_TOTP_DIGITS"
+ "env": "AUTHELIA_NOTIFIER_SMTP_TLS_SERVER_NAME"
},
{
- "path": "totp.period",
+ "path": "notifier.smtp.tls.skip_verify",
"secret": false,
- "env": "AUTHELIA_TOTP_PERIOD"
+ "env": "AUTHELIA_NOTIFIER_SMTP_TLS_SKIP_VERIFY"
},
{
- "path": "totp.skew",
+ "path": "notifier.smtp.username",
"secret": false,
- "env": "AUTHELIA_TOTP_SKEW"
+ "env": "AUTHELIA_NOTIFIER_SMTP_USERNAME"
},
{
- "path": "totp.secret_size",
+ "path": "notifier.template_path",
"secret": false,
- "env": "AUTHELIA_TOTP_SECRET_SIZE"
+ "env": "AUTHELIA_NOTIFIER_TEMPLATE_PATH"
},
{
- "path": "totp.allowed_algorithms",
+ "path": "ntp.address",
"secret": false,
- "env": "AUTHELIA_TOTP_ALLOWED_ALGORITHMS"
+ "env": "AUTHELIA_NTP_ADDRESS"
},
{
- "path": "totp.allowed_digits",
+ "path": "ntp.disable_failure",
"secret": false,
- "env": "AUTHELIA_TOTP_ALLOWED_DIGITS"
+ "env": "AUTHELIA_NTP_DISABLE_FAILURE"
},
{
- "path": "totp.allowed_periods",
+ "path": "ntp.disable_startup_check",
"secret": false,
- "env": "AUTHELIA_TOTP_ALLOWED_PERIODS"
+ "env": "AUTHELIA_NTP_DISABLE_STARTUP_CHECK"
},
{
- "path": "totp.disable_reuse_security_policy",
+ "path": "ntp.max_desync",
"secret": false,
- "env": "AUTHELIA_TOTP_DISABLE_REUSE_SECURITY_POLICY"
+ "env": "AUTHELIA_NTP_MAX_DESYNC"
},
{
- "path": "duo_api.disable",
+ "path": "ntp.version",
"secret": false,
- "env": "AUTHELIA_DUO_API_DISABLE"
+ "env": "AUTHELIA_NTP_VERSION"
},
{
- "path": "duo_api.hostname",
+ "path": "password_policy.standard.enabled",
"secret": false,
- "env": "AUTHELIA_DUO_API_HOSTNAME"
+ "env": "AUTHELIA_PASSWORD_POLICY_STANDARD_ENABLED"
},
{
- "path": "duo_api.integration_key",
- "secret": true,
- "env": "AUTHELIA_DUO_API_INTEGRATION_KEY_FILE"
+ "path": "password_policy.standard.max_length",
+ "secret": false,
+ "env": "AUTHELIA_PASSWORD_POLICY_STANDARD_MAX_LENGTH"
},
{
- "path": "duo_api.secret_key",
- "secret": true,
- "env": "AUTHELIA_DUO_API_SECRET_KEY_FILE"
+ "path": "password_policy.standard.min_length",
+ "secret": false,
+ "env": "AUTHELIA_PASSWORD_POLICY_STANDARD_MIN_LENGTH"
},
{
- "path": "duo_api.enable_self_enrollment",
+ "path": "password_policy.standard.require_lowercase",
"secret": false,
- "env": "AUTHELIA_DUO_API_ENABLE_SELF_ENROLLMENT"
+ "env": "AUTHELIA_PASSWORD_POLICY_STANDARD_REQUIRE_LOWERCASE"
},
{
- "path": "access_control.default_policy",
+ "path": "password_policy.standard.require_number",
"secret": false,
- "env": "AUTHELIA_ACCESS_CONTROL_DEFAULT_POLICY"
+ "env": "AUTHELIA_PASSWORD_POLICY_STANDARD_REQUIRE_NUMBER"
},
{
- "path": "ntp.address",
+ "path": "password_policy.standard.require_special",
"secret": false,
- "env": "AUTHELIA_NTP_ADDRESS"
+ "env": "AUTHELIA_PASSWORD_POLICY_STANDARD_REQUIRE_SPECIAL"
},
{
- "path": "ntp.version",
+ "path": "password_policy.standard.require_uppercase",
"secret": false,
- "env": "AUTHELIA_NTP_VERSION"
+ "env": "AUTHELIA_PASSWORD_POLICY_STANDARD_REQUIRE_UPPERCASE"
},
{
- "path": "ntp.max_desync",
+ "path": "password_policy.zxcvbn.enabled",
"secret": false,
- "env": "AUTHELIA_NTP_MAX_DESYNC"
+ "env": "AUTHELIA_PASSWORD_POLICY_ZXCVBN_ENABLED"
},
{
- "path": "ntp.disable_startup_check",
+ "path": "password_policy.zxcvbn.min_score",
"secret": false,
- "env": "AUTHELIA_NTP_DISABLE_STARTUP_CHECK"
+ "env": "AUTHELIA_PASSWORD_POLICY_ZXCVBN_MIN_SCORE"
},
{
- "path": "ntp.disable_failure",
+ "path": "privacy_policy.enabled",
"secret": false,
- "env": "AUTHELIA_NTP_DISABLE_FAILURE"
+ "env": "AUTHELIA_PRIVACY_POLICY_ENABLED"
},
{
- "path": "regulation.max_retries",
+ "path": "privacy_policy.policy_url",
"secret": false,
- "env": "AUTHELIA_REGULATION_MAX_RETRIES"
+ "env": "AUTHELIA_PRIVACY_POLICY_POLICY_URL"
},
{
- "path": "regulation.find_time",
+ "path": "privacy_policy.require_user_acceptance",
"secret": false,
- "env": "AUTHELIA_REGULATION_FIND_TIME"
+ "env": "AUTHELIA_PRIVACY_POLICY_REQUIRE_USER_ACCEPTANCE"
},
{
"path": "regulation.ban_time",
@@ -760,518 +755,523 @@
"env": "AUTHELIA_REGULATION_BAN_TIME"
},
{
- "path": "storage.local.path",
+ "path": "regulation.find_time",
"secret": false,
- "env": "AUTHELIA_STORAGE_LOCAL_PATH"
+ "env": "AUTHELIA_REGULATION_FIND_TIME"
},
{
- "path": "storage.mysql.address",
+ "path": "regulation.max_retries",
"secret": false,
- "env": "AUTHELIA_STORAGE_MYSQL_ADDRESS"
+ "env": "AUTHELIA_REGULATION_MAX_RETRIES"
},
{
- "path": "storage.mysql.database",
+ "path": "server.address",
"secret": false,
- "env": "AUTHELIA_STORAGE_MYSQL_DATABASE"
+ "env": "AUTHELIA_SERVER_ADDRESS"
},
{
- "path": "storage.mysql.username",
+ "path": "server.asset_path",
"secret": false,
- "env": "AUTHELIA_STORAGE_MYSQL_USERNAME"
+ "env": "AUTHELIA_SERVER_ASSET_PATH"
},
{
- "path": "storage.mysql.password",
- "secret": true,
- "env": "AUTHELIA_STORAGE_MYSQL_PASSWORD_FILE"
+ "path": "server.buffers.read",
+ "secret": false,
+ "env": "AUTHELIA_SERVER_BUFFERS_READ"
},
{
- "path": "storage.mysql.timeout",
+ "path": "server.buffers.write",
"secret": false,
- "env": "AUTHELIA_STORAGE_MYSQL_TIMEOUT"
+ "env": "AUTHELIA_SERVER_BUFFERS_WRITE"
},
{
- "path": "storage.mysql.tls.minimum_version",
+ "path": "server.disable_healthcheck",
"secret": false,
- "env": "AUTHELIA_STORAGE_MYSQL_TLS_MINIMUM_VERSION"
+ "env": "AUTHELIA_SERVER_DISABLE_HEALTHCHECK"
},
{
- "path": "storage.mysql.tls.maximum_version",
+ "path": "server.endpoints.enable_expvars",
"secret": false,
- "env": "AUTHELIA_STORAGE_MYSQL_TLS_MAXIMUM_VERSION"
+ "env": "AUTHELIA_SERVER_ENDPOINTS_ENABLE_EXPVARS"
},
{
- "path": "storage.mysql.tls.skip_verify",
+ "path": "server.endpoints.enable_pprof",
"secret": false,
- "env": "AUTHELIA_STORAGE_MYSQL_TLS_SKIP_VERIFY"
+ "env": "AUTHELIA_SERVER_ENDPOINTS_ENABLE_PPROF"
},
{
- "path": "storage.mysql.tls.server_name",
+ "path": "server.headers.csp_template",
"secret": false,
- "env": "AUTHELIA_STORAGE_MYSQL_TLS_SERVER_NAME"
+ "env": "AUTHELIA_SERVER_HEADERS_CSP_TEMPLATE"
},
{
- "path": "storage.mysql.tls.private_key",
- "secret": true,
- "env": "AUTHELIA_STORAGE_MYSQL_TLS_PRIVATE_KEY_FILE"
+ "path": "server.timeouts.idle",
+ "secret": false,
+ "env": "AUTHELIA_SERVER_TIMEOUTS_IDLE"
},
{
- "path": "storage.mysql.tls.certificate_chain",
- "secret": true,
- "env": "AUTHELIA_STORAGE_MYSQL_TLS_CERTIFICATE_CHAIN_FILE"
+ "path": "server.timeouts.read",
+ "secret": false,
+ "env": "AUTHELIA_SERVER_TIMEOUTS_READ"
},
{
- "path": "storage.postgres.address",
+ "path": "server.timeouts.write",
"secret": false,
- "env": "AUTHELIA_STORAGE_POSTGRES_ADDRESS"
+ "env": "AUTHELIA_SERVER_TIMEOUTS_WRITE"
},
{
- "path": "storage.postgres.database",
+ "path": "server.tls.certificate",
"secret": false,
- "env": "AUTHELIA_STORAGE_POSTGRES_DATABASE"
+ "env": "AUTHELIA_SERVER_TLS_CERTIFICATE"
},
{
- "path": "storage.postgres.username",
+ "path": "server.tls.client_certificates",
"secret": false,
- "env": "AUTHELIA_STORAGE_POSTGRES_USERNAME"
+ "env": "AUTHELIA_SERVER_TLS_CLIENT_CERTIFICATES"
},
{
- "path": "storage.postgres.password",
- "secret": true,
- "env": "AUTHELIA_STORAGE_POSTGRES_PASSWORD_FILE"
+ "path": "server.tls.key",
+ "secret": false,
+ "env": "AUTHELIA_SERVER_TLS_KEY"
},
{
- "path": "storage.postgres.timeout",
+ "path": "session",
"secret": false,
- "env": "AUTHELIA_STORAGE_POSTGRES_TIMEOUT"
+ "env": "AUTHELIA_SESSION"
},
{
- "path": "storage.postgres.schema",
+ "path": "session.expiration",
"secret": false,
- "env": "AUTHELIA_STORAGE_POSTGRES_SCHEMA"
+ "env": "AUTHELIA_SESSION_EXPIRATION"
},
{
- "path": "storage.postgres.tls.minimum_version",
+ "path": "session.inactivity",
"secret": false,
- "env": "AUTHELIA_STORAGE_POSTGRES_TLS_MINIMUM_VERSION"
+ "env": "AUTHELIA_SESSION_INACTIVITY"
},
{
- "path": "storage.postgres.tls.maximum_version",
+ "path": "session.name",
"secret": false,
- "env": "AUTHELIA_STORAGE_POSTGRES_TLS_MAXIMUM_VERSION"
+ "env": "AUTHELIA_SESSION_NAME"
},
{
- "path": "storage.postgres.tls.skip_verify",
+ "path": "session.redis.database_index",
"secret": false,
- "env": "AUTHELIA_STORAGE_POSTGRES_TLS_SKIP_VERIFY"
+ "env": "AUTHELIA_SESSION_REDIS_DATABASE_INDEX"
},
{
- "path": "storage.postgres.tls.server_name",
+ "path": "session.redis.high_availability.route_by_latency",
"secret": false,
- "env": "AUTHELIA_STORAGE_POSTGRES_TLS_SERVER_NAME"
+ "env": "AUTHELIA_SESSION_REDIS_HIGH_AVAILABILITY_ROUTE_BY_LATENCY"
},
{
- "path": "storage.postgres.tls.private_key",
- "secret": true,
- "env": "AUTHELIA_STORAGE_POSTGRES_TLS_PRIVATE_KEY_FILE"
+ "path": "session.redis.high_availability.route_randomly",
+ "secret": false,
+ "env": "AUTHELIA_SESSION_REDIS_HIGH_AVAILABILITY_ROUTE_RANDOMLY"
},
{
- "path": "storage.postgres.tls.certificate_chain",
- "secret": true,
- "env": "AUTHELIA_STORAGE_POSTGRES_TLS_CERTIFICATE_CHAIN_FILE"
+ "path": "session.redis.high_availability.sentinel_name",
+ "secret": false,
+ "env": "AUTHELIA_SESSION_REDIS_HIGH_AVAILABILITY_SENTINEL_NAME"
},
{
- "path": "storage.encryption_key",
+ "path": "session.redis.high_availability.sentinel_password",
"secret": true,
- "env": "AUTHELIA_STORAGE_ENCRYPTION_KEY_FILE"
+ "env": "AUTHELIA_SESSION_REDIS_HIGH_AVAILABILITY_SENTINEL_PASSWORD_FILE"
},
{
- "path": "notifier.disable_startup_check",
+ "path": "session.redis.high_availability.sentinel_username",
"secret": false,
- "env": "AUTHELIA_NOTIFIER_DISABLE_STARTUP_CHECK"
+ "env": "AUTHELIA_SESSION_REDIS_HIGH_AVAILABILITY_SENTINEL_USERNAME"
},
{
- "path": "notifier.filesystem.filename",
+ "path": "session.redis.host",
"secret": false,
- "env": "AUTHELIA_NOTIFIER_FILESYSTEM_FILENAME"
+ "env": "AUTHELIA_SESSION_REDIS_HOST"
},
{
- "path": "notifier.smtp.address",
+ "path": "session.redis.max_retries",
"secret": false,
- "env": "AUTHELIA_NOTIFIER_SMTP_ADDRESS"
+ "env": "AUTHELIA_SESSION_REDIS_MAX_RETRIES"
},
{
- "path": "notifier.smtp.timeout",
+ "path": "session.redis.maximum_active_connections",
"secret": false,
- "env": "AUTHELIA_NOTIFIER_SMTP_TIMEOUT"
+ "env": "AUTHELIA_SESSION_REDIS_MAXIMUM_ACTIVE_CONNECTIONS"
},
{
- "path": "notifier.smtp.username",
+ "path": "session.redis.minimum_idle_connections",
"secret": false,
- "env": "AUTHELIA_NOTIFIER_SMTP_USERNAME"
+ "env": "AUTHELIA_SESSION_REDIS_MINIMUM_IDLE_CONNECTIONS"
},
{
- "path": "notifier.smtp.password",
+ "path": "session.redis.password",
"secret": true,
- "env": "AUTHELIA_NOTIFIER_SMTP_PASSWORD_FILE"
+ "env": "AUTHELIA_SESSION_REDIS_PASSWORD_FILE"
},
{
- "path": "notifier.smtp.identifier",
+ "path": "session.redis.port",
"secret": false,
- "env": "AUTHELIA_NOTIFIER_SMTP_IDENTIFIER"
+ "env": "AUTHELIA_SESSION_REDIS_PORT"
},
{
- "path": "notifier.smtp.sender",
+ "path": "session.redis.timeout",
"secret": false,
- "env": "AUTHELIA_NOTIFIER_SMTP_SENDER"
+ "env": "AUTHELIA_SESSION_REDIS_TIMEOUT"
},
{
- "path": "notifier.smtp.subject",
- "secret": false,
- "env": "AUTHELIA_NOTIFIER_SMTP_SUBJECT"
+ "path": "session.redis.tls.certificate_chain",
+ "secret": true,
+ "env": "AUTHELIA_SESSION_REDIS_TLS_CERTIFICATE_CHAIN_FILE"
},
{
- "path": "notifier.smtp.startup_check_address",
+ "path": "session.redis.tls.maximum_version",
"secret": false,
- "env": "AUTHELIA_NOTIFIER_SMTP_STARTUP_CHECK_ADDRESS"
+ "env": "AUTHELIA_SESSION_REDIS_TLS_MAXIMUM_VERSION"
},
{
- "path": "notifier.smtp.disable_require_tls",
+ "path": "session.redis.tls.minimum_version",
"secret": false,
- "env": "AUTHELIA_NOTIFIER_SMTP_DISABLE_REQUIRE_TLS"
+ "env": "AUTHELIA_SESSION_REDIS_TLS_MINIMUM_VERSION"
},
{
- "path": "notifier.smtp.disable_html_emails",
- "secret": false,
- "env": "AUTHELIA_NOTIFIER_SMTP_DISABLE_HTML_EMAILS"
+ "path": "session.redis.tls.private_key",
+ "secret": true,
+ "env": "AUTHELIA_SESSION_REDIS_TLS_PRIVATE_KEY_FILE"
},
{
- "path": "notifier.smtp.disable_starttls",
+ "path": "session.redis.tls.server_name",
"secret": false,
- "env": "AUTHELIA_NOTIFIER_SMTP_DISABLE_STARTTLS"
+ "env": "AUTHELIA_SESSION_REDIS_TLS_SERVER_NAME"
},
{
- "path": "notifier.smtp.tls.minimum_version",
+ "path": "session.redis.tls.skip_verify",
"secret": false,
- "env": "AUTHELIA_NOTIFIER_SMTP_TLS_MINIMUM_VERSION"
+ "env": "AUTHELIA_SESSION_REDIS_TLS_SKIP_VERIFY"
},
{
- "path": "notifier.smtp.tls.maximum_version",
+ "path": "session.redis.username",
"secret": false,
- "env": "AUTHELIA_NOTIFIER_SMTP_TLS_MAXIMUM_VERSION"
+ "env": "AUTHELIA_SESSION_REDIS_USERNAME"
},
{
- "path": "notifier.smtp.tls.skip_verify",
+ "path": "session.remember_me",
"secret": false,
- "env": "AUTHELIA_NOTIFIER_SMTP_TLS_SKIP_VERIFY"
+ "env": "AUTHELIA_SESSION_REMEMBER_ME"
},
{
- "path": "notifier.smtp.tls.server_name",
+ "path": "session.same_site",
"secret": false,
- "env": "AUTHELIA_NOTIFIER_SMTP_TLS_SERVER_NAME"
+ "env": "AUTHELIA_SESSION_SAME_SITE"
},
{
- "path": "notifier.smtp.tls.private_key",
+ "path": "session.secret",
"secret": true,
- "env": "AUTHELIA_NOTIFIER_SMTP_TLS_PRIVATE_KEY_FILE"
+ "env": "AUTHELIA_SESSION_SECRET_FILE"
},
{
- "path": "notifier.smtp.tls.certificate_chain",
+ "path": "storage.encryption_key",
"secret": true,
- "env": "AUTHELIA_NOTIFIER_SMTP_TLS_CERTIFICATE_CHAIN_FILE"
+ "env": "AUTHELIA_STORAGE_ENCRYPTION_KEY_FILE"
},
{
- "path": "notifier.template_path",
+ "path": "storage.local.path",
"secret": false,
- "env": "AUTHELIA_NOTIFIER_TEMPLATE_PATH"
+ "env": "AUTHELIA_STORAGE_LOCAL_PATH"
},
{
- "path": "server.address",
+ "path": "storage.mysql.address",
"secret": false,
- "env": "AUTHELIA_SERVER_ADDRESS"
+ "env": "AUTHELIA_STORAGE_MYSQL_ADDRESS"
},
{
- "path": "server.asset_path",
+ "path": "storage.mysql.database",
"secret": false,
- "env": "AUTHELIA_SERVER_ASSET_PATH"
+ "env": "AUTHELIA_STORAGE_MYSQL_DATABASE"
},
{
- "path": "server.disable_healthcheck",
- "secret": false,
- "env": "AUTHELIA_SERVER_DISABLE_HEALTHCHECK"
+ "path": "storage.mysql.password",
+ "secret": true,
+ "env": "AUTHELIA_STORAGE_MYSQL_PASSWORD_FILE"
},
{
- "path": "server.tls.certificate",
+ "path": "storage.mysql.timeout",
"secret": false,
- "env": "AUTHELIA_SERVER_TLS_CERTIFICATE"
+ "env": "AUTHELIA_STORAGE_MYSQL_TIMEOUT"
},
{
- "path": "server.tls.key",
- "secret": false,
- "env": "AUTHELIA_SERVER_TLS_KEY"
+ "path": "storage.mysql.tls.certificate_chain",
+ "secret": true,
+ "env": "AUTHELIA_STORAGE_MYSQL_TLS_CERTIFICATE_CHAIN_FILE"
},
{
- "path": "server.tls.client_certificates",
+ "path": "storage.mysql.tls.maximum_version",
"secret": false,
- "env": "AUTHELIA_SERVER_TLS_CLIENT_CERTIFICATES"
+ "env": "AUTHELIA_STORAGE_MYSQL_TLS_MAXIMUM_VERSION"
},
{
- "path": "server.headers.csp_template",
+ "path": "storage.mysql.tls.minimum_version",
"secret": false,
- "env": "AUTHELIA_SERVER_HEADERS_CSP_TEMPLATE"
+ "env": "AUTHELIA_STORAGE_MYSQL_TLS_MINIMUM_VERSION"
},
{
- "path": "server.endpoints.enable_pprof",
- "secret": false,
- "env": "AUTHELIA_SERVER_ENDPOINTS_ENABLE_PPROF"
+ "path": "storage.mysql.tls.private_key",
+ "secret": true,
+ "env": "AUTHELIA_STORAGE_MYSQL_TLS_PRIVATE_KEY_FILE"
},
{
- "path": "server.endpoints.enable_expvars",
+ "path": "storage.mysql.tls.server_name",
"secret": false,
- "env": "AUTHELIA_SERVER_ENDPOINTS_ENABLE_EXPVARS"
+ "env": "AUTHELIA_STORAGE_MYSQL_TLS_SERVER_NAME"
},
{
- "path": "server.buffers.read",
+ "path": "storage.mysql.tls.skip_verify",
"secret": false,
- "env": "AUTHELIA_SERVER_BUFFERS_READ"
+ "env": "AUTHELIA_STORAGE_MYSQL_TLS_SKIP_VERIFY"
},
{
- "path": "server.buffers.write",
+ "path": "storage.mysql.username",
"secret": false,
- "env": "AUTHELIA_SERVER_BUFFERS_WRITE"
+ "env": "AUTHELIA_STORAGE_MYSQL_USERNAME"
},
{
- "path": "server.timeouts.read",
+ "path": "storage.postgres.address",
"secret": false,
- "env": "AUTHELIA_SERVER_TIMEOUTS_READ"
+ "env": "AUTHELIA_STORAGE_POSTGRES_ADDRESS"
},
{
- "path": "server.timeouts.write",
+ "path": "storage.postgres.database",
"secret": false,
- "env": "AUTHELIA_SERVER_TIMEOUTS_WRITE"
+ "env": "AUTHELIA_STORAGE_POSTGRES_DATABASE"
},
{
- "path": "server.timeouts.idle",
- "secret": false,
- "env": "AUTHELIA_SERVER_TIMEOUTS_IDLE"
+ "path": "storage.postgres.password",
+ "secret": true,
+ "env": "AUTHELIA_STORAGE_POSTGRES_PASSWORD_FILE"
},
{
- "path": "telemetry.metrics.enabled",
+ "path": "storage.postgres.schema",
"secret": false,
- "env": "AUTHELIA_TELEMETRY_METRICS_ENABLED"
+ "env": "AUTHELIA_STORAGE_POSTGRES_SCHEMA"
},
{
- "path": "telemetry.metrics.address",
+ "path": "storage.postgres.timeout",
"secret": false,
- "env": "AUTHELIA_TELEMETRY_METRICS_ADDRESS"
+ "env": "AUTHELIA_STORAGE_POSTGRES_TIMEOUT"
},
{
- "path": "telemetry.metrics.buffers.read",
- "secret": false,
- "env": "AUTHELIA_TELEMETRY_METRICS_BUFFERS_READ"
+ "path": "storage.postgres.tls.certificate_chain",
+ "secret": true,
+ "env": "AUTHELIA_STORAGE_POSTGRES_TLS_CERTIFICATE_CHAIN_FILE"
},
{
- "path": "telemetry.metrics.buffers.write",
+ "path": "storage.postgres.tls.maximum_version",
"secret": false,
- "env": "AUTHELIA_TELEMETRY_METRICS_BUFFERS_WRITE"
+ "env": "AUTHELIA_STORAGE_POSTGRES_TLS_MAXIMUM_VERSION"
},
{
- "path": "telemetry.metrics.timeouts.read",
+ "path": "storage.postgres.tls.minimum_version",
"secret": false,
- "env": "AUTHELIA_TELEMETRY_METRICS_TIMEOUTS_READ"
+ "env": "AUTHELIA_STORAGE_POSTGRES_TLS_MINIMUM_VERSION"
},
{
- "path": "telemetry.metrics.timeouts.write",
+ "path": "storage.postgres.tls.private_key",
+ "secret": true,
+ "env": "AUTHELIA_STORAGE_POSTGRES_TLS_PRIVATE_KEY_FILE"
+ },
+ {
+ "path": "storage.postgres.tls.server_name",
"secret": false,
- "env": "AUTHELIA_TELEMETRY_METRICS_TIMEOUTS_WRITE"
+ "env": "AUTHELIA_STORAGE_POSTGRES_TLS_SERVER_NAME"
},
{
- "path": "telemetry.metrics.timeouts.idle",
+ "path": "storage.postgres.tls.skip_verify",
"secret": false,
- "env": "AUTHELIA_TELEMETRY_METRICS_TIMEOUTS_IDLE"
+ "env": "AUTHELIA_STORAGE_POSTGRES_TLS_SKIP_VERIFY"
},
{
- "path": "webauthn.disable",
+ "path": "storage.postgres.username",
"secret": false,
- "env": "AUTHELIA_WEBAUTHN_DISABLE"
+ "env": "AUTHELIA_STORAGE_POSTGRES_USERNAME"
},
{
- "path": "webauthn.enable_passkey_login",
+ "path": "telemetry.metrics.address",
"secret": false,
- "env": "AUTHELIA_WEBAUTHN_ENABLE_PASSKEY_LOGIN"
+ "env": "AUTHELIA_TELEMETRY_METRICS_ADDRESS"
},
{
- "path": "webauthn.experimental_enable_passkey_uv_two_factors",
+ "path": "telemetry.metrics.buffers.read",
"secret": false,
- "env": "AUTHELIA_WEBAUTHN_EXPERIMENTAL_ENABLE_PASSKEY_UV_TWO_FACTORS"
+ "env": "AUTHELIA_TELEMETRY_METRICS_BUFFERS_READ"
},
{
- "path": "webauthn.display_name",
+ "path": "telemetry.metrics.buffers.write",
"secret": false,
- "env": "AUTHELIA_WEBAUTHN_DISPLAY_NAME"
+ "env": "AUTHELIA_TELEMETRY_METRICS_BUFFERS_WRITE"
},
{
- "path": "webauthn.attestation_conveyance_preference",
+ "path": "telemetry.metrics.enabled",
"secret": false,
- "env": "AUTHELIA_WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE"
+ "env": "AUTHELIA_TELEMETRY_METRICS_ENABLED"
},
{
- "path": "webauthn.timeout",
+ "path": "telemetry.metrics.timeouts.idle",
"secret": false,
- "env": "AUTHELIA_WEBAUTHN_TIMEOUT"
+ "env": "AUTHELIA_TELEMETRY_METRICS_TIMEOUTS_IDLE"
},
{
- "path": "webauthn.filtering.prohibit_backup_eligibility",
+ "path": "telemetry.metrics.timeouts.read",
"secret": false,
- "env": "AUTHELIA_WEBAUTHN_FILTERING_PROHIBIT_BACKUP_ELIGIBILITY"
+ "env": "AUTHELIA_TELEMETRY_METRICS_TIMEOUTS_READ"
},
{
- "path": "webauthn.selection_criteria.attachment",
+ "path": "telemetry.metrics.timeouts.write",
"secret": false,
- "env": "AUTHELIA_WEBAUTHN_SELECTION_CRITERIA_ATTACHMENT"
+ "env": "AUTHELIA_TELEMETRY_METRICS_TIMEOUTS_WRITE"
},
{
- "path": "webauthn.selection_criteria.discoverability",
+ "path": "theme",
"secret": false,
- "env": "AUTHELIA_WEBAUTHN_SELECTION_CRITERIA_DISCOVERABILITY"
+ "env": "AUTHELIA_THEME"
},
{
- "path": "webauthn.selection_criteria.user_verification",
+ "path": "totp.algorithm",
"secret": false,
- "env": "AUTHELIA_WEBAUTHN_SELECTION_CRITERIA_USER_VERIFICATION"
+ "env": "AUTHELIA_TOTP_ALGORITHM"
},
{
- "path": "webauthn.metadata.enabled",
+ "path": "totp.allowed_algorithms",
"secret": false,
- "env": "AUTHELIA_WEBAUTHN_METADATA_ENABLED"
+ "env": "AUTHELIA_TOTP_ALLOWED_ALGORITHMS"
},
{
- "path": "webauthn.metadata.validate_trust_anchor",
+ "path": "totp.allowed_digits",
"secret": false,
- "env": "AUTHELIA_WEBAUTHN_METADATA_VALIDATE_TRUST_ANCHOR"
+ "env": "AUTHELIA_TOTP_ALLOWED_DIGITS"
},
{
- "path": "webauthn.metadata.validate_entry",
+ "path": "totp.allowed_periods",
"secret": false,
- "env": "AUTHELIA_WEBAUTHN_METADATA_VALIDATE_ENTRY"
+ "env": "AUTHELIA_TOTP_ALLOWED_PERIODS"
},
{
- "path": "webauthn.metadata.validate_entry_permit_zero_aaguid",
+ "path": "totp.digits",
"secret": false,
- "env": "AUTHELIA_WEBAUTHN_METADATA_VALIDATE_ENTRY_PERMIT_ZERO_AAGUID"
+ "env": "AUTHELIA_TOTP_DIGITS"
},
{
- "path": "webauthn.metadata.validate_status",
+ "path": "totp.disable",
"secret": false,
- "env": "AUTHELIA_WEBAUTHN_METADATA_VALIDATE_STATUS"
+ "env": "AUTHELIA_TOTP_DISABLE"
},
{
- "path": "webauthn.metadata.validate_status_permitted",
+ "path": "totp.disable_reuse_security_policy",
"secret": false,
- "env": "AUTHELIA_WEBAUTHN_METADATA_VALIDATE_STATUS_PERMITTED"
+ "env": "AUTHELIA_TOTP_DISABLE_REUSE_SECURITY_POLICY"
},
{
- "path": "webauthn.metadata.validate_status_prohibited",
+ "path": "totp.issuer",
"secret": false,
- "env": "AUTHELIA_WEBAUTHN_METADATA_VALIDATE_STATUS_PROHIBITED"
+ "env": "AUTHELIA_TOTP_ISSUER"
},
{
- "path": "password_policy.standard.enabled",
+ "path": "totp.period",
"secret": false,
- "env": "AUTHELIA_PASSWORD_POLICY_STANDARD_ENABLED"
+ "env": "AUTHELIA_TOTP_PERIOD"
},
{
- "path": "password_policy.standard.min_length",
+ "path": "totp.secret_size",
"secret": false,
- "env": "AUTHELIA_PASSWORD_POLICY_STANDARD_MIN_LENGTH"
+ "env": "AUTHELIA_TOTP_SECRET_SIZE"
},
{
- "path": "password_policy.standard.max_length",
+ "path": "totp.skew",
"secret": false,
- "env": "AUTHELIA_PASSWORD_POLICY_STANDARD_MAX_LENGTH"
+ "env": "AUTHELIA_TOTP_SKEW"
},
{
- "path": "password_policy.standard.require_uppercase",
+ "path": "webauthn.attestation_conveyance_preference",
"secret": false,
- "env": "AUTHELIA_PASSWORD_POLICY_STANDARD_REQUIRE_UPPERCASE"
+ "env": "AUTHELIA_WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE"
},
{
- "path": "password_policy.standard.require_lowercase",
+ "path": "webauthn.disable",
"secret": false,
- "env": "AUTHELIA_PASSWORD_POLICY_STANDARD_REQUIRE_LOWERCASE"
+ "env": "AUTHELIA_WEBAUTHN_DISABLE"
},
{
- "path": "password_policy.standard.require_number",
+ "path": "webauthn.display_name",
"secret": false,
- "env": "AUTHELIA_PASSWORD_POLICY_STANDARD_REQUIRE_NUMBER"
+ "env": "AUTHELIA_WEBAUTHN_DISPLAY_NAME"
},
{
- "path": "password_policy.standard.require_special",
+ "path": "webauthn.enable_passkey_login",
"secret": false,
- "env": "AUTHELIA_PASSWORD_POLICY_STANDARD_REQUIRE_SPECIAL"
+ "env": "AUTHELIA_WEBAUTHN_ENABLE_PASSKEY_LOGIN"
},
{
- "path": "password_policy.zxcvbn.enabled",
+ "path": "webauthn.experimental_enable_passkey_uv_two_factors",
"secret": false,
- "env": "AUTHELIA_PASSWORD_POLICY_ZXCVBN_ENABLED"
+ "env": "AUTHELIA_WEBAUTHN_EXPERIMENTAL_ENABLE_PASSKEY_UV_TWO_FACTORS"
},
{
- "path": "password_policy.zxcvbn.min_score",
+ "path": "webauthn.filtering.prohibit_backup_eligibility",
"secret": false,
- "env": "AUTHELIA_PASSWORD_POLICY_ZXCVBN_MIN_SCORE"
+ "env": "AUTHELIA_WEBAUTHN_FILTERING_PROHIBIT_BACKUP_ELIGIBILITY"
},
{
- "path": "privacy_policy.enabled",
+ "path": "webauthn.metadata.enabled",
"secret": false,
- "env": "AUTHELIA_PRIVACY_POLICY_ENABLED"
+ "env": "AUTHELIA_WEBAUTHN_METADATA_ENABLED"
},
{
- "path": "privacy_policy.require_user_acceptance",
+ "path": "webauthn.metadata.validate_entry",
"secret": false,
- "env": "AUTHELIA_PRIVACY_POLICY_REQUIRE_USER_ACCEPTANCE"
+ "env": "AUTHELIA_WEBAUTHN_METADATA_VALIDATE_ENTRY"
},
{
- "path": "privacy_policy.policy_url",
+ "path": "webauthn.metadata.validate_entry_permit_zero_aaguid",
"secret": false,
- "env": "AUTHELIA_PRIVACY_POLICY_POLICY_URL"
+ "env": "AUTHELIA_WEBAUTHN_METADATA_VALIDATE_ENTRY_PERMIT_ZERO_AAGUID"
},
{
- "path": "identity_validation.reset_password.jwt_lifespan",
+ "path": "webauthn.metadata.validate_status",
"secret": false,
- "env": "AUTHELIA_IDENTITY_VALIDATION_RESET_PASSWORD_JWT_LIFESPAN"
+ "env": "AUTHELIA_WEBAUTHN_METADATA_VALIDATE_STATUS"
},
{
- "path": "identity_validation.reset_password.jwt_algorithm",
+ "path": "webauthn.metadata.validate_status_permitted",
"secret": false,
- "env": "AUTHELIA_IDENTITY_VALIDATION_RESET_PASSWORD_JWT_ALGORITHM"
+ "env": "AUTHELIA_WEBAUTHN_METADATA_VALIDATE_STATUS_PERMITTED"
},
{
- "path": "identity_validation.reset_password.jwt_secret",
- "secret": true,
- "env": "AUTHELIA_IDENTITY_VALIDATION_RESET_PASSWORD_JWT_SECRET_FILE"
+ "path": "webauthn.metadata.validate_status_prohibited",
+ "secret": false,
+ "env": "AUTHELIA_WEBAUTHN_METADATA_VALIDATE_STATUS_PROHIBITED"
},
{
- "path": "identity_validation.elevated_session.code_lifespan",
+ "path": "webauthn.metadata.validate_trust_anchor",
"secret": false,
- "env": "AUTHELIA_IDENTITY_VALIDATION_ELEVATED_SESSION_CODE_LIFESPAN"
+ "env": "AUTHELIA_WEBAUTHN_METADATA_VALIDATE_TRUST_ANCHOR"
},
{
- "path": "identity_validation.elevated_session.elevation_lifespan",
+ "path": "webauthn.selection_criteria.attachment",
"secret": false,
- "env": "AUTHELIA_IDENTITY_VALIDATION_ELEVATED_SESSION_ELEVATION_LIFESPAN"
+ "env": "AUTHELIA_WEBAUTHN_SELECTION_CRITERIA_ATTACHMENT"
},
{
- "path": "identity_validation.elevated_session.characters",
+ "path": "webauthn.selection_criteria.discoverability",
"secret": false,
- "env": "AUTHELIA_IDENTITY_VALIDATION_ELEVATED_SESSION_CHARACTERS"
+ "env": "AUTHELIA_WEBAUTHN_SELECTION_CRITERIA_DISCOVERABILITY"
},
{
- "path": "identity_validation.elevated_session.require_second_factor",
+ "path": "webauthn.selection_criteria.user_verification",
"secret": false,
- "env": "AUTHELIA_IDENTITY_VALIDATION_ELEVATED_SESSION_REQUIRE_SECOND_FACTOR"
+ "env": "AUTHELIA_WEBAUTHN_SELECTION_CRITERIA_USER_VERIFICATION"
},
{
- "path": "identity_validation.elevated_session.skip_second_factor",
+ "path": "webauthn.timeout",
"secret": false,
- "env": "AUTHELIA_IDENTITY_VALIDATION_ELEVATED_SESSION_SKIP_SECOND_FACTOR"
+ "env": "AUTHELIA_WEBAUTHN_TIMEOUT"
}
]
diff --git a/docs/static/schemas/v4.39/json-schema/configuration.json b/docs/static/schemas/v4.39/json-schema/configuration.json
index 39d9ad7d4..2e72ef96c 100644
--- a/docs/static/schemas/v4.39/json-schema/configuration.json
+++ b/docs/static/schemas/v4.39/json-schema/configuration.json
@@ -3679,7 +3679,7 @@
"address": {
"$ref": "#/$defs/AddressTCP",
"title": "Address",
- "description": "The address of the database."
+ "description": "The address of the SQL Server."
},
"database": {
"type": "string",
@@ -3723,7 +3723,7 @@
"address": {
"$ref": "#/$defs/AddressTCP",
"title": "Address",
- "description": "The address of the database."
+ "description": "The address of the SQL Server."
},
"database": {
"type": "string",
@@ -3754,14 +3754,22 @@
"title": "Timeout",
"description": "The timeout for the database connection."
},
+ "tls": {
+ "$ref": "#/$defs/TLS"
+ },
"schema": {
"type": "string",
"title": "Schema",
"description": "The default schema name to use.",
"default": "public"
},
- "tls": {
- "$ref": "#/$defs/TLS"
+ "servers": {
+ "items": {
+ "$ref": "#/$defs/StoragePostgreSQLServer"
+ },
+ "type": "array",
+ "title": "Servers",
+ "description": "The fallback PostgreSQL severs to connect to in addition to the one defined by the address."
},
"ssl": {
"$ref": "#/$defs/StoragePostgreSQLSSL",
@@ -3811,6 +3819,20 @@
"type": "object",
"description": "StoragePostgreSQLSSL represents the SSL configuration of a PostgreSQL database."
},
+ "StoragePostgreSQLServer": {
+ "properties": {
+ "address": {
+ "$ref": "#/$defs/AddressTCP",
+ "title": "Address",
+ "description": "The address of the PostgreSQL Server."
+ },
+ "tls": {
+ "$ref": "#/$defs/TLS"
+ }
+ },
+ "additionalProperties": false,
+ "type": "object"
+ },
"TLS": {
"properties": {
"minimum_version": {
diff --git a/internal/configuration/config.template.yml b/internal/configuration/config.template.yml
index 2e01b7a15..0fd1756e9 100644
--- a/internal/configuration/config.template.yml
+++ b/internal/configuration/config.template.yml
@@ -1076,6 +1076,30 @@ session:
## The default scheme is 'unix' if the address is an absolute path otherwise it's 'tcp'. The default port is '5432'.
# address: 'tcp://127.0.0.1:5432'
+ ## List of additional server instance configurations to fallback to when the primary instance is not available.
+ # servers:
+ # -
+ ## The Address of this individual instance.
+ # address: 'tcp://127.0.0.1:5432'
+
+ ## The TLS configuration for this individual instance.
+ # tls:
+ # server_name: 'postgres.example.com'
+ # skip_verify: false
+ # minimum_version: 'TLS1.2'
+ # maximum_version: 'TLS1.3'
+ # certificate_chain: |
+ # -----BEGIN CERTIFICATE-----
+ # ...
+ # -----END CERTIFICATE-----
+ # -----BEGIN CERTIFICATE-----
+ # ...
+ # -----END CERTIFICATE-----
+ # private_key: |
+ # -----BEGIN RSA PRIVATE KEY-----
+ # ...
+ # -----END RSA PRIVATE KEY-----
+
## The database name to use.
# database: 'authelia'
diff --git a/internal/configuration/schema/keys.go b/internal/configuration/schema/keys.go
index f2efaca93..fbab487ef 100644
--- a/internal/configuration/schema/keys.go
+++ b/internal/configuration/schema/keys.go
@@ -8,443 +8,450 @@ package schema
// Keys is a list of valid schema keys detected by reflecting over a schema.Configuration struct.
var Keys = []string{
- "theme",
+ "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[].policy",
+ "access_control.rules[].query",
+ "access_control.rules[].query[][].key",
+ "access_control.rules[].query[][].operator",
+ "access_control.rules[].query[][].value",
+ "access_control.rules[].resources",
+ "access_control.rules[].subject",
+ "authentication_backend.file.extra_attributes",
+ "authentication_backend.file.extra_attributes.*",
+ "authentication_backend.file.extra_attributes.*.multi_valued",
+ "authentication_backend.file.extra_attributes.*.value_type",
+ "authentication_backend.file.password.algorithm",
+ "authentication_backend.file.password.argon2.iterations",
+ "authentication_backend.file.password.argon2.key_length",
+ "authentication_backend.file.password.argon2.memory",
+ "authentication_backend.file.password.argon2.parallelism",
+ "authentication_backend.file.password.argon2.salt_length",
+ "authentication_backend.file.password.argon2.variant",
+ "authentication_backend.file.password.bcrypt.cost",
+ "authentication_backend.file.password.bcrypt.variant",
+ "authentication_backend.file.password.iterations",
+ "authentication_backend.file.password.key_length",
+ "authentication_backend.file.password.memory",
+ "authentication_backend.file.password.parallelism",
+ "authentication_backend.file.password.pbkdf2.iterations",
+ "authentication_backend.file.password.pbkdf2.salt_length",
+ "authentication_backend.file.password.pbkdf2.variant",
+ "authentication_backend.file.password.salt_length",
+ "authentication_backend.file.password.scrypt.block_size",
+ "authentication_backend.file.password.scrypt.iterations",
+ "authentication_backend.file.password.scrypt.key_length",
+ "authentication_backend.file.password.scrypt.parallelism",
+ "authentication_backend.file.password.scrypt.salt_length",
+ "authentication_backend.file.password.sha2crypt.iterations",
+ "authentication_backend.file.password.sha2crypt.salt_length",
+ "authentication_backend.file.password.sha2crypt.variant",
+ "authentication_backend.file.path",
+ "authentication_backend.file.search.case_insensitive",
+ "authentication_backend.file.search.email",
+ "authentication_backend.file.watch",
+ "authentication_backend.ldap.additional_groups_dn",
+ "authentication_backend.ldap.additional_users_dn",
+ "authentication_backend.ldap.address",
+ "authentication_backend.ldap.attributes.birthdate",
+ "authentication_backend.ldap.attributes.country",
+ "authentication_backend.ldap.attributes.display_name",
+ "authentication_backend.ldap.attributes.distinguished_name",
+ "authentication_backend.ldap.attributes.extra",
+ "authentication_backend.ldap.attributes.extra.*",
+ "authentication_backend.ldap.attributes.extra.*.multi_valued",
+ "authentication_backend.ldap.attributes.extra.*.name",
+ "authentication_backend.ldap.attributes.extra.*.value_type",
+ "authentication_backend.ldap.attributes.family_name",
+ "authentication_backend.ldap.attributes.gender",
+ "authentication_backend.ldap.attributes.given_name",
+ "authentication_backend.ldap.attributes.group_name",
+ "authentication_backend.ldap.attributes.locale",
+ "authentication_backend.ldap.attributes.locality",
+ "authentication_backend.ldap.attributes.mail",
+ "authentication_backend.ldap.attributes.member_of",
+ "authentication_backend.ldap.attributes.middle_name",
+ "authentication_backend.ldap.attributes.nickname",
+ "authentication_backend.ldap.attributes.phone_extension",
+ "authentication_backend.ldap.attributes.phone_number",
+ "authentication_backend.ldap.attributes.picture",
+ "authentication_backend.ldap.attributes.postal_code",
+ "authentication_backend.ldap.attributes.profile",
+ "authentication_backend.ldap.attributes.region",
+ "authentication_backend.ldap.attributes.street_address",
+ "authentication_backend.ldap.attributes.username",
+ "authentication_backend.ldap.attributes.website",
+ "authentication_backend.ldap.attributes.zoneinfo",
+ "authentication_backend.ldap.base_dn",
+ "authentication_backend.ldap.group_search_mode",
+ "authentication_backend.ldap.groups_filter",
+ "authentication_backend.ldap.implementation",
+ "authentication_backend.ldap.password",
+ "authentication_backend.ldap.permit_feature_detection_failure",
+ "authentication_backend.ldap.permit_referrals",
+ "authentication_backend.ldap.permit_unauthenticated_bind",
+ "authentication_backend.ldap.pooling.count",
+ "authentication_backend.ldap.pooling.enable",
+ "authentication_backend.ldap.pooling.retries",
+ "authentication_backend.ldap.pooling.timeout",
+ "authentication_backend.ldap.start_tls",
+ "authentication_backend.ldap.timeout",
+ "authentication_backend.ldap.tls.certificate_chain",
+ "authentication_backend.ldap.tls.maximum_version",
+ "authentication_backend.ldap.tls.minimum_version",
+ "authentication_backend.ldap.tls.private_key",
+ "authentication_backend.ldap.tls.server_name",
+ "authentication_backend.ldap.tls.skip_verify",
+ "authentication_backend.ldap.user",
+ "authentication_backend.ldap.users_filter",
+ "authentication_backend.password_reset.custom_url",
+ "authentication_backend.password_reset.disable",
+ "authentication_backend.refresh_interval",
"certificates_directory",
"default_2fa_method",
- "log.level",
- "log.format",
- "log.file_path",
- "log.keep_stdout",
- "identity_providers.oidc.hmac_secret",
- "identity_providers.oidc.jwks",
- "identity_providers.oidc.jwks[].key_id",
- "identity_providers.oidc.jwks[].use",
- "identity_providers.oidc.jwks[].algorithm",
- "identity_providers.oidc.jwks[].key",
- "identity_providers.oidc.jwks[].certificate_chain",
- "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.enable_jwt_access_token_stateless_introspection",
- "identity_providers.oidc.discovery_signed_response_alg",
- "identity_providers.oidc.discovery_signed_response_key_id",
- "identity_providers.oidc.require_pushed_authorization_requests",
- "identity_providers.oidc.cors.endpoints",
- "identity_providers.oidc.cors.allowed_origins",
- "identity_providers.oidc.cors.allowed_origins_from_client_redirect_uris",
+ "default_redirection_url",
+ "definitions.network",
+ "definitions.network.*",
+ "definitions.user_attributes",
+ "definitions.user_attributes.*",
+ "definitions.user_attributes.*.expression",
+ "duo_api.disable",
+ "duo_api.enable_self_enrollment",
+ "duo_api.hostname",
+ "duo_api.integration_key",
+ "duo_api.secret_key",
+ "identity_providers.oidc",
+ "identity_providers.oidc.authorization_policies",
+ "identity_providers.oidc.authorization_policies.*",
+ "identity_providers.oidc.authorization_policies.*.default_policy",
+ "identity_providers.oidc.authorization_policies.*.rules",
+ "identity_providers.oidc.authorization_policies.*.rules[].networks",
+ "identity_providers.oidc.authorization_policies.*.rules[].policy",
+ "identity_providers.oidc.authorization_policies.*.rules[].subject",
+ "identity_providers.oidc.claims_policies",
+ "identity_providers.oidc.claims_policies.*",
+ "identity_providers.oidc.claims_policies.*.access_token",
+ "identity_providers.oidc.claims_policies.*.custom_claims",
+ "identity_providers.oidc.claims_policies.*.custom_claims.*",
+ "identity_providers.oidc.claims_policies.*.custom_claims.*.attribute",
+ "identity_providers.oidc.claims_policies.*.id_token",
"identity_providers.oidc.clients",
- "identity_providers.oidc.clients[].client_id",
- "identity_providers.oidc.clients[].client_name",
- "identity_providers.oidc.clients[].client_secret",
- "identity_providers.oidc.clients[].sector_identifier_uri",
- "identity_providers.oidc.clients[].public",
- "identity_providers.oidc.clients[].redirect_uris",
- "identity_providers.oidc.clients[].request_uris",
+ "identity_providers.oidc.clients[]",
+ "identity_providers.oidc.clients[].access_token_encrypted_response_alg",
+ "identity_providers.oidc.clients[].access_token_encrypted_response_enc",
+ "identity_providers.oidc.clients[].access_token_encrypted_response_key_id",
+ "identity_providers.oidc.clients[].access_token_signed_response_alg",
+ "identity_providers.oidc.clients[].access_token_signed_response_key_id",
+ "identity_providers.oidc.clients[].allow_multiple_auth_methods",
"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[].authorization_policy",
- "identity_providers.oidc.clients[].lifespan",
- "identity_providers.oidc.clients[].claims_policy",
- "identity_providers.oidc.clients[].requested_audience_mode",
- "identity_providers.oidc.clients[].consent_mode",
- "identity_providers.oidc.clients[].pre_configured_consent_duration",
- "identity_providers.oidc.clients[].require_pushed_authorization_requests",
- "identity_providers.oidc.clients[].require_pkce",
- "identity_providers.oidc.clients[].pkce_challenge_method",
- "identity_providers.oidc.clients[].authorization_signed_response_alg",
- "identity_providers.oidc.clients[].authorization_signed_response_key_id",
"identity_providers.oidc.clients[].authorization_encrypted_response_alg",
"identity_providers.oidc.clients[].authorization_encrypted_response_enc",
"identity_providers.oidc.clients[].authorization_encrypted_response_key_id",
- "identity_providers.oidc.clients[].id_token_signed_response_alg",
- "identity_providers.oidc.clients[].id_token_signed_response_key_id",
+ "identity_providers.oidc.clients[].authorization_policy",
+ "identity_providers.oidc.clients[].authorization_signed_response_alg",
+ "identity_providers.oidc.clients[].authorization_signed_response_key_id",
+ "identity_providers.oidc.clients[].claims_policy",
+ "identity_providers.oidc.clients[].client_id",
+ "identity_providers.oidc.clients[].client_name",
+ "identity_providers.oidc.clients[].client_secret",
+ "identity_providers.oidc.clients[].consent_mode",
+ "identity_providers.oidc.clients[].grant_types",
"identity_providers.oidc.clients[].id_token_encrypted_response_alg",
"identity_providers.oidc.clients[].id_token_encrypted_response_enc",
"identity_providers.oidc.clients[].id_token_encrypted_response_key_id",
- "identity_providers.oidc.clients[].access_token_signed_response_alg",
- "identity_providers.oidc.clients[].access_token_signed_response_key_id",
- "identity_providers.oidc.clients[].access_token_encrypted_response_alg",
- "identity_providers.oidc.clients[].access_token_encrypted_response_enc",
- "identity_providers.oidc.clients[].access_token_encrypted_response_key_id",
- "identity_providers.oidc.clients[].userinfo_signed_response_alg",
- "identity_providers.oidc.clients[].userinfo_signed_response_key_id",
- "identity_providers.oidc.clients[].userinfo_encrypted_response_alg",
- "identity_providers.oidc.clients[].userinfo_encrypted_response_enc",
- "identity_providers.oidc.clients[].userinfo_encrypted_response_key_id",
- "identity_providers.oidc.clients[].introspection_signed_response_alg",
- "identity_providers.oidc.clients[].introspection_signed_response_key_id",
+ "identity_providers.oidc.clients[].id_token_signed_response_alg",
+ "identity_providers.oidc.clients[].id_token_signed_response_key_id",
"identity_providers.oidc.clients[].introspection_encrypted_response_alg",
"identity_providers.oidc.clients[].introspection_encrypted_response_enc",
"identity_providers.oidc.clients[].introspection_encrypted_response_key_id",
- "identity_providers.oidc.clients[].request_object_signing_alg",
- "identity_providers.oidc.clients[].request_object_encryption_alg",
- "identity_providers.oidc.clients[].request_object_encryption_enc",
- "identity_providers.oidc.clients[].token_endpoint_auth_method",
- "identity_providers.oidc.clients[].token_endpoint_auth_signing_alg",
- "identity_providers.oidc.clients[].revocation_endpoint_auth_method",
- "identity_providers.oidc.clients[].revocation_endpoint_auth_signing_alg",
"identity_providers.oidc.clients[].introspection_endpoint_auth_method",
"identity_providers.oidc.clients[].introspection_endpoint_auth_signing_alg",
- "identity_providers.oidc.clients[].pushed_authorization_request_endpoint_auth_method",
- "identity_providers.oidc.clients[].pushed_authorization_request_endpoint_auth_signing_alg",
- "identity_providers.oidc.clients[].allow_multiple_auth_methods",
- "identity_providers.oidc.clients[].jwks_uri",
+ "identity_providers.oidc.clients[].introspection_signed_response_alg",
+ "identity_providers.oidc.clients[].introspection_signed_response_key_id",
"identity_providers.oidc.clients[].jwks",
- "identity_providers.oidc.clients[].jwks[].key_id",
- "identity_providers.oidc.clients[].jwks[].use",
"identity_providers.oidc.clients[].jwks[].algorithm",
- "identity_providers.oidc.clients[].jwks[].key",
"identity_providers.oidc.clients[].jwks[].certificate_chain",
- "identity_providers.oidc.clients[]",
- "identity_providers.oidc.authorization_policies.*",
- "identity_providers.oidc.authorization_policies",
- "identity_providers.oidc.authorization_policies.*.default_policy",
- "identity_providers.oidc.authorization_policies.*.rules",
- "identity_providers.oidc.authorization_policies.*.rules[].policy",
- "identity_providers.oidc.authorization_policies.*.rules[].subject",
- "identity_providers.oidc.authorization_policies.*.rules[].networks",
+ "identity_providers.oidc.clients[].jwks[].key",
+ "identity_providers.oidc.clients[].jwks[].key_id",
+ "identity_providers.oidc.clients[].jwks[].use",
+ "identity_providers.oidc.clients[].jwks_uri",
+ "identity_providers.oidc.clients[].lifespan",
+ "identity_providers.oidc.clients[].pkce_challenge_method",
+ "identity_providers.oidc.clients[].pre_configured_consent_duration",
+ "identity_providers.oidc.clients[].public",
+ "identity_providers.oidc.clients[].pushed_authorization_request_endpoint_auth_method",
+ "identity_providers.oidc.clients[].pushed_authorization_request_endpoint_auth_signing_alg",
+ "identity_providers.oidc.clients[].redirect_uris",
+ "identity_providers.oidc.clients[].request_object_encryption_alg",
+ "identity_providers.oidc.clients[].request_object_encryption_enc",
+ "identity_providers.oidc.clients[].request_object_signing_alg",
+ "identity_providers.oidc.clients[].request_uris",
+ "identity_providers.oidc.clients[].requested_audience_mode",
+ "identity_providers.oidc.clients[].require_pkce",
+ "identity_providers.oidc.clients[].require_pushed_authorization_requests",
+ "identity_providers.oidc.clients[].response_modes",
+ "identity_providers.oidc.clients[].response_types",
+ "identity_providers.oidc.clients[].revocation_endpoint_auth_method",
+ "identity_providers.oidc.clients[].revocation_endpoint_auth_signing_alg",
+ "identity_providers.oidc.clients[].scopes",
+ "identity_providers.oidc.clients[].sector_identifier_uri",
+ "identity_providers.oidc.clients[].token_endpoint_auth_method",
+ "identity_providers.oidc.clients[].token_endpoint_auth_signing_alg",
+ "identity_providers.oidc.clients[].userinfo_encrypted_response_alg",
+ "identity_providers.oidc.clients[].userinfo_encrypted_response_enc",
+ "identity_providers.oidc.clients[].userinfo_encrypted_response_key_id",
+ "identity_providers.oidc.clients[].userinfo_signed_response_alg",
+ "identity_providers.oidc.clients[].userinfo_signed_response_key_id",
+ "identity_providers.oidc.cors.allowed_origins",
+ "identity_providers.oidc.cors.allowed_origins_from_client_redirect_uris",
+ "identity_providers.oidc.cors.endpoints",
+ "identity_providers.oidc.discovery_signed_response_alg",
+ "identity_providers.oidc.discovery_signed_response_key_id",
+ "identity_providers.oidc.enable_client_debug_messages",
+ "identity_providers.oidc.enable_jwt_access_token_stateless_introspection",
+ "identity_providers.oidc.enable_pkce_plain_challenge",
+ "identity_providers.oidc.enforce_pkce",
+ "identity_providers.oidc.hmac_secret",
+ "identity_providers.oidc.issuer_certificate_chain",
+ "identity_providers.oidc.issuer_private_key",
+ "identity_providers.oidc.jwks",
+ "identity_providers.oidc.jwks[].algorithm",
+ "identity_providers.oidc.jwks[].certificate_chain",
+ "identity_providers.oidc.jwks[].key",
+ "identity_providers.oidc.jwks[].key_id",
+ "identity_providers.oidc.jwks[].use",
"identity_providers.oidc.lifespans.access_token",
"identity_providers.oidc.lifespans.authorize_code",
- "identity_providers.oidc.lifespans.id_token",
- "identity_providers.oidc.lifespans.refresh_token",
- "identity_providers.oidc.lifespans.jwt_secured_authorization",
- "identity_providers.oidc.lifespans.custom.*",
"identity_providers.oidc.lifespans.custom",
+ "identity_providers.oidc.lifespans.custom.*",
"identity_providers.oidc.lifespans.custom.*.access_token",
"identity_providers.oidc.lifespans.custom.*.authorize_code",
- "identity_providers.oidc.lifespans.custom.*.id_token",
- "identity_providers.oidc.lifespans.custom.*.refresh_token",
"identity_providers.oidc.lifespans.custom.*.grants.authorize_code.access_token",
"identity_providers.oidc.lifespans.custom.*.grants.authorize_code.authorize_code",
"identity_providers.oidc.lifespans.custom.*.grants.authorize_code.id_token",
"identity_providers.oidc.lifespans.custom.*.grants.authorize_code.refresh_token",
- "identity_providers.oidc.lifespans.custom.*.grants.implicit.access_token",
- "identity_providers.oidc.lifespans.custom.*.grants.implicit.authorize_code",
- "identity_providers.oidc.lifespans.custom.*.grants.implicit.id_token",
- "identity_providers.oidc.lifespans.custom.*.grants.implicit.refresh_token",
"identity_providers.oidc.lifespans.custom.*.grants.client_credentials.access_token",
"identity_providers.oidc.lifespans.custom.*.grants.client_credentials.authorize_code",
"identity_providers.oidc.lifespans.custom.*.grants.client_credentials.id_token",
"identity_providers.oidc.lifespans.custom.*.grants.client_credentials.refresh_token",
- "identity_providers.oidc.lifespans.custom.*.grants.refresh_token.access_token",
- "identity_providers.oidc.lifespans.custom.*.grants.refresh_token.authorize_code",
- "identity_providers.oidc.lifespans.custom.*.grants.refresh_token.id_token",
- "identity_providers.oidc.lifespans.custom.*.grants.refresh_token.refresh_token",
+ "identity_providers.oidc.lifespans.custom.*.grants.implicit.access_token",
+ "identity_providers.oidc.lifespans.custom.*.grants.implicit.authorize_code",
+ "identity_providers.oidc.lifespans.custom.*.grants.implicit.id_token",
+ "identity_providers.oidc.lifespans.custom.*.grants.implicit.refresh_token",
"identity_providers.oidc.lifespans.custom.*.grants.jwt_bearer.access_token",
"identity_providers.oidc.lifespans.custom.*.grants.jwt_bearer.authorize_code",
"identity_providers.oidc.lifespans.custom.*.grants.jwt_bearer.id_token",
"identity_providers.oidc.lifespans.custom.*.grants.jwt_bearer.refresh_token",
- "identity_providers.oidc.claims_policies.*",
- "identity_providers.oidc.claims_policies",
- "identity_providers.oidc.claims_policies.*.id_token",
- "identity_providers.oidc.claims_policies.*.access_token",
- "identity_providers.oidc.claims_policies.*.custom_claims.*",
- "identity_providers.oidc.claims_policies.*.custom_claims",
- "identity_providers.oidc.claims_policies.*.custom_claims.*.attribute",
- "identity_providers.oidc.scopes.*",
+ "identity_providers.oidc.lifespans.custom.*.grants.refresh_token.access_token",
+ "identity_providers.oidc.lifespans.custom.*.grants.refresh_token.authorize_code",
+ "identity_providers.oidc.lifespans.custom.*.grants.refresh_token.id_token",
+ "identity_providers.oidc.lifespans.custom.*.grants.refresh_token.refresh_token",
+ "identity_providers.oidc.lifespans.custom.*.id_token",
+ "identity_providers.oidc.lifespans.custom.*.refresh_token",
+ "identity_providers.oidc.lifespans.id_token",
+ "identity_providers.oidc.lifespans.jwt_secured_authorization",
+ "identity_providers.oidc.lifespans.refresh_token",
+ "identity_providers.oidc.minimum_parameter_entropy",
+ "identity_providers.oidc.require_pushed_authorization_requests",
"identity_providers.oidc.scopes",
+ "identity_providers.oidc.scopes.*",
"identity_providers.oidc.scopes.*.claims",
- "identity_providers.oidc",
- "identity_providers.oidc.issuer_certificate_chain",
- "identity_providers.oidc.issuer_private_key",
- "authentication_backend.password_reset.disable",
- "authentication_backend.password_reset.custom_url",
- "authentication_backend.refresh_interval",
- "authentication_backend.file.path",
- "authentication_backend.file.watch",
- "authentication_backend.file.password.algorithm",
- "authentication_backend.file.password.argon2.variant",
- "authentication_backend.file.password.argon2.iterations",
- "authentication_backend.file.password.argon2.memory",
- "authentication_backend.file.password.argon2.parallelism",
- "authentication_backend.file.password.argon2.key_length",
- "authentication_backend.file.password.argon2.salt_length",
- "authentication_backend.file.password.sha2crypt.variant",
- "authentication_backend.file.password.sha2crypt.iterations",
- "authentication_backend.file.password.sha2crypt.salt_length",
- "authentication_backend.file.password.pbkdf2.variant",
- "authentication_backend.file.password.pbkdf2.iterations",
- "authentication_backend.file.password.pbkdf2.salt_length",
- "authentication_backend.file.password.bcrypt.variant",
- "authentication_backend.file.password.bcrypt.cost",
- "authentication_backend.file.password.scrypt.iterations",
- "authentication_backend.file.password.scrypt.block_size",
- "authentication_backend.file.password.scrypt.parallelism",
- "authentication_backend.file.password.scrypt.key_length",
- "authentication_backend.file.password.scrypt.salt_length",
- "authentication_backend.file.password.iterations",
- "authentication_backend.file.password.memory",
- "authentication_backend.file.password.parallelism",
- "authentication_backend.file.password.key_length",
- "authentication_backend.file.password.salt_length",
- "authentication_backend.file.search.email",
- "authentication_backend.file.search.case_insensitive",
- "authentication_backend.file.extra_attributes.*",
- "authentication_backend.file.extra_attributes",
- "authentication_backend.file.extra_attributes.*.multi_valued",
- "authentication_backend.file.extra_attributes.*.value_type",
- "authentication_backend.ldap.address",
- "authentication_backend.ldap.implementation",
- "authentication_backend.ldap.timeout",
- "authentication_backend.ldap.start_tls",
- "authentication_backend.ldap.tls.minimum_version",
- "authentication_backend.ldap.tls.maximum_version",
- "authentication_backend.ldap.tls.skip_verify",
- "authentication_backend.ldap.tls.server_name",
- "authentication_backend.ldap.tls.private_key",
- "authentication_backend.ldap.tls.certificate_chain",
- "authentication_backend.ldap.pooling.enable",
- "authentication_backend.ldap.pooling.count",
- "authentication_backend.ldap.pooling.retries",
- "authentication_backend.ldap.pooling.timeout",
- "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_search_mode",
- "authentication_backend.ldap.attributes.distinguished_name",
- "authentication_backend.ldap.attributes.username",
- "authentication_backend.ldap.attributes.display_name",
- "authentication_backend.ldap.attributes.family_name",
- "authentication_backend.ldap.attributes.given_name",
- "authentication_backend.ldap.attributes.middle_name",
- "authentication_backend.ldap.attributes.nickname",
- "authentication_backend.ldap.attributes.gender",
- "authentication_backend.ldap.attributes.birthdate",
- "authentication_backend.ldap.attributes.website",
- "authentication_backend.ldap.attributes.profile",
- "authentication_backend.ldap.attributes.picture",
- "authentication_backend.ldap.attributes.zoneinfo",
- "authentication_backend.ldap.attributes.locale",
- "authentication_backend.ldap.attributes.phone_number",
- "authentication_backend.ldap.attributes.phone_extension",
- "authentication_backend.ldap.attributes.street_address",
- "authentication_backend.ldap.attributes.locality",
- "authentication_backend.ldap.attributes.region",
- "authentication_backend.ldap.attributes.postal_code",
- "authentication_backend.ldap.attributes.country",
- "authentication_backend.ldap.attributes.mail",
- "authentication_backend.ldap.attributes.member_of",
- "authentication_backend.ldap.attributes.group_name",
- "authentication_backend.ldap.attributes.extra.*",
- "authentication_backend.ldap.attributes.extra",
- "authentication_backend.ldap.attributes.extra.*.name",
- "authentication_backend.ldap.attributes.extra.*.multi_valued",
- "authentication_backend.ldap.attributes.extra.*.value_type",
- "authentication_backend.ldap.permit_referrals",
- "authentication_backend.ldap.permit_unauthenticated_bind",
- "authentication_backend.ldap.permit_feature_detection_failure",
- "authentication_backend.ldap.user",
- "authentication_backend.ldap.password",
- "session.name",
- "session.same_site",
- "session.expiration",
- "session.inactivity",
- "session.remember_me",
+ "identity_validation.elevated_session.characters",
+ "identity_validation.elevated_session.code_lifespan",
+ "identity_validation.elevated_session.elevation_lifespan",
+ "identity_validation.elevated_session.require_second_factor",
+ "identity_validation.elevated_session.skip_second_factor",
+ "identity_validation.reset_password.jwt_algorithm",
+ "identity_validation.reset_password.jwt_lifespan",
+ "identity_validation.reset_password.jwt_secret",
+ "log.file_path",
+ "log.format",
+ "log.keep_stdout",
+ "log.level",
+ "notifier.disable_startup_check",
+ "notifier.filesystem.filename",
+ "notifier.smtp.address",
+ "notifier.smtp.disable_html_emails",
+ "notifier.smtp.disable_require_tls",
+ "notifier.smtp.disable_starttls",
+ "notifier.smtp.host",
+ "notifier.smtp.identifier",
+ "notifier.smtp.password",
+ "notifier.smtp.port",
+ "notifier.smtp.sender",
+ "notifier.smtp.startup_check_address",
+ "notifier.smtp.subject",
+ "notifier.smtp.timeout",
+ "notifier.smtp.tls.certificate_chain",
+ "notifier.smtp.tls.maximum_version",
+ "notifier.smtp.tls.minimum_version",
+ "notifier.smtp.tls.private_key",
+ "notifier.smtp.tls.server_name",
+ "notifier.smtp.tls.skip_verify",
+ "notifier.smtp.username",
+ "notifier.template_path",
+ "ntp.address",
+ "ntp.disable_failure",
+ "ntp.disable_startup_check",
+ "ntp.max_desync",
+ "ntp.version",
+ "password_policy.standard.enabled",
+ "password_policy.standard.max_length",
+ "password_policy.standard.min_length",
+ "password_policy.standard.require_lowercase",
+ "password_policy.standard.require_number",
+ "password_policy.standard.require_special",
+ "password_policy.standard.require_uppercase",
+ "password_policy.zxcvbn.enabled",
+ "password_policy.zxcvbn.min_score",
+ "privacy_policy.enabled",
+ "privacy_policy.policy_url",
+ "privacy_policy.require_user_acceptance",
+ "regulation.ban_time",
+ "regulation.find_time",
+ "regulation.max_retries",
+ "server.address",
+ "server.asset_path",
+ "server.buffers.read",
+ "server.buffers.write",
+ "server.disable_healthcheck",
+ "server.endpoints.authz",
+ "server.endpoints.authz.*",
+ "server.endpoints.authz.*.authn_strategies",
+ "server.endpoints.authz.*.authn_strategies[].name",
+ "server.endpoints.authz.*.authn_strategies[].schemes",
+ "server.endpoints.authz.*.implementation",
+ "server.endpoints.enable_expvars",
+ "server.endpoints.enable_pprof",
+ "server.headers.csp_template",
+ "server.timeouts.idle",
+ "server.timeouts.read",
+ "server.timeouts.write",
+ "server.tls.certificate",
+ "server.tls.client_certificates",
+ "server.tls.key",
"session",
- "session.secret",
"session.cookies",
- "session.cookies[].name",
- "session.cookies[].same_site",
- "session.cookies[].expiration",
- "session.cookies[].inactivity",
- "session.cookies[].remember_me",
"session.cookies[]",
- "session.cookies[].domain",
"session.cookies[].authelia_url",
"session.cookies[].default_redirection_url",
- "session.cookies[]",
+ "session.cookies[].domain",
+ "session.cookies[].expiration",
+ "session.cookies[].inactivity",
+ "session.cookies[].name",
+ "session.cookies[].remember_me",
+ "session.cookies[].same_site",
+ "session.domain",
+ "session.expiration",
+ "session.inactivity",
+ "session.name",
+ "session.redis.database_index",
+ "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",
+ "session.redis.high_availability.sentinel_name",
+ "session.redis.high_availability.sentinel_password",
+ "session.redis.high_availability.sentinel_username",
"session.redis.host",
- "session.redis.port",
- "session.redis.timeout",
"session.redis.max_retries",
- "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.password",
+ "session.redis.port",
+ "session.redis.timeout",
+ "session.redis.tls.certificate_chain",
"session.redis.tls.maximum_version",
- "session.redis.tls.skip_verify",
- "session.redis.tls.server_name",
+ "session.redis.tls.minimum_version",
"session.redis.tls.private_key",
- "session.redis.tls.certificate_chain",
- "session.redis.high_availability.sentinel_name",
- "session.redis.high_availability.sentinel_username",
- "session.redis.high_availability.sentinel_password",
- "session.redis.high_availability.route_by_latency",
- "session.redis.high_availability.route_randomly",
- "session.redis.high_availability.nodes",
- "session.redis.high_availability.nodes[].host",
- "session.redis.high_availability.nodes[].port",
- "session.domain",
- "totp.disable",
- "totp.issuer",
- "totp.algorithm",
- "totp.digits",
- "totp.period",
- "totp.skew",
- "totp.secret_size",
- "totp.allowed_algorithms",
- "totp.allowed_digits",
- "totp.allowed_periods",
- "totp.disable_reuse_security_policy",
- "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",
- "access_control.rules[].query[][].operator",
- "access_control.rules[].query[][].key",
- "access_control.rules[].query[][].value",
- "access_control.rules[].query",
- "ntp.address",
- "ntp.version",
- "ntp.max_desync",
- "ntp.disable_startup_check",
- "ntp.disable_failure",
- "regulation.max_retries",
- "regulation.find_time",
- "regulation.ban_time",
+ "session.redis.tls.server_name",
+ "session.redis.tls.skip_verify",
+ "session.redis.username",
+ "session.remember_me",
+ "session.same_site",
+ "session.secret",
+ "storage.encryption_key",
"storage.local.path",
"storage.mysql.address",
"storage.mysql.database",
- "storage.mysql.username",
"storage.mysql.password",
"storage.mysql.timeout",
- "storage.mysql.tls.minimum_version",
+ "storage.mysql.tls.certificate_chain",
"storage.mysql.tls.maximum_version",
- "storage.mysql.tls.skip_verify",
- "storage.mysql.tls.server_name",
+ "storage.mysql.tls.minimum_version",
"storage.mysql.tls.private_key",
- "storage.mysql.tls.certificate_chain",
+ "storage.mysql.tls.server_name",
+ "storage.mysql.tls.skip_verify",
+ "storage.mysql.username",
"storage.postgres.address",
"storage.postgres.database",
- "storage.postgres.username",
"storage.postgres.password",
- "storage.postgres.timeout",
"storage.postgres.schema",
- "storage.postgres.tls.minimum_version",
- "storage.postgres.tls.maximum_version",
- "storage.postgres.tls.skip_verify",
- "storage.postgres.tls.server_name",
- "storage.postgres.tls.private_key",
- "storage.postgres.tls.certificate_chain",
- "storage.postgres.ssl.mode",
- "storage.postgres.ssl.root_certificate",
+ "storage.postgres.servers",
+ "storage.postgres.servers[].address",
+ "storage.postgres.servers[].tls",
+ "storage.postgres.servers[].tls.certificate_chain",
+ "storage.postgres.servers[].tls.maximum_version",
+ "storage.postgres.servers[].tls.minimum_version",
+ "storage.postgres.servers[].tls.private_key",
+ "storage.postgres.servers[].tls.server_name",
+ "storage.postgres.servers[].tls.skip_verify",
"storage.postgres.ssl.certificate",
"storage.postgres.ssl.key",
- "storage.encryption_key",
- "notifier.disable_startup_check",
- "notifier.filesystem.filename",
- "notifier.smtp.address",
- "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.disable_starttls",
- "notifier.smtp.tls.minimum_version",
- "notifier.smtp.tls.maximum_version",
- "notifier.smtp.tls.skip_verify",
- "notifier.smtp.tls.server_name",
- "notifier.smtp.tls.private_key",
- "notifier.smtp.tls.certificate_chain",
- "notifier.smtp.host",
- "notifier.smtp.port",
- "notifier.template_path",
- "server.address",
- "server.asset_path",
- "server.disable_healthcheck",
- "server.tls.certificate",
- "server.tls.key",
- "server.tls.client_certificates",
- "server.headers.csp_template",
- "server.endpoints.enable_pprof",
- "server.endpoints.enable_expvars",
- "server.endpoints.authz.*",
- "server.endpoints.authz",
- "server.endpoints.authz.*.implementation",
- "server.endpoints.authz.*.authn_strategies",
- "server.endpoints.authz.*.authn_strategies[].name",
- "server.endpoints.authz.*.authn_strategies[].schemes",
- "server.buffers.read",
- "server.buffers.write",
- "server.timeouts.read",
- "server.timeouts.write",
- "server.timeouts.idle",
- "telemetry.metrics.enabled",
+ "storage.postgres.ssl.mode",
+ "storage.postgres.ssl.root_certificate",
+ "storage.postgres.timeout",
+ "storage.postgres.tls.certificate_chain",
+ "storage.postgres.tls.maximum_version",
+ "storage.postgres.tls.minimum_version",
+ "storage.postgres.tls.private_key",
+ "storage.postgres.tls.server_name",
+ "storage.postgres.tls.skip_verify",
+ "storage.postgres.username",
"telemetry.metrics.address",
"telemetry.metrics.buffers.read",
"telemetry.metrics.buffers.write",
+ "telemetry.metrics.enabled",
+ "telemetry.metrics.timeouts.idle",
"telemetry.metrics.timeouts.read",
"telemetry.metrics.timeouts.write",
- "telemetry.metrics.timeouts.idle",
+ "theme",
+ "totp.algorithm",
+ "totp.allowed_algorithms",
+ "totp.allowed_digits",
+ "totp.allowed_periods",
+ "totp.digits",
+ "totp.disable",
+ "totp.disable_reuse_security_policy",
+ "totp.issuer",
+ "totp.period",
+ "totp.secret_size",
+ "totp.skew",
+ "webauthn.attestation_conveyance_preference",
"webauthn.disable",
+ "webauthn.display_name",
"webauthn.enable_passkey_login",
"webauthn.experimental_enable_passkey_uv_two_factors",
- "webauthn.display_name",
- "webauthn.attestation_conveyance_preference",
- "webauthn.timeout",
- "webauthn.filtering.prohibit_backup_eligibility",
"webauthn.filtering.permitted_aaguids",
+ "webauthn.filtering.prohibit_backup_eligibility",
"webauthn.filtering.prohibited_aaguids",
- "webauthn.selection_criteria.attachment",
- "webauthn.selection_criteria.discoverability",
- "webauthn.selection_criteria.user_verification",
"webauthn.metadata.enabled",
- "webauthn.metadata.validate_trust_anchor",
"webauthn.metadata.validate_entry",
"webauthn.metadata.validate_entry_permit_zero_aaguid",
"webauthn.metadata.validate_status",
"webauthn.metadata.validate_status_permitted",
"webauthn.metadata.validate_status_prohibited",
- "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",
- "privacy_policy.enabled",
- "privacy_policy.require_user_acceptance",
- "privacy_policy.policy_url",
- "identity_validation.reset_password.jwt_lifespan",
- "identity_validation.reset_password.jwt_algorithm",
- "identity_validation.reset_password.jwt_secret",
- "identity_validation.elevated_session.code_lifespan",
- "identity_validation.elevated_session.elevation_lifespan",
- "identity_validation.elevated_session.characters",
- "identity_validation.elevated_session.require_second_factor",
- "identity_validation.elevated_session.skip_second_factor",
- "definitions.network.*",
- "definitions.network.*",
- "definitions.network",
- "definitions.user_attributes.*",
- "definitions.user_attributes",
- "definitions.user_attributes.*.expression",
- "default_redirection_url",
+ "webauthn.metadata.validate_trust_anchor",
+ "webauthn.selection_criteria.attachment",
+ "webauthn.selection_criteria.discoverability",
+ "webauthn.selection_criteria.user_verification",
+ "webauthn.timeout",
}
diff --git a/internal/configuration/schema/storage.go b/internal/configuration/schema/storage.go
index b51982a59..4bdf397f5 100644
--- a/internal/configuration/schema/storage.go
+++ b/internal/configuration/schema/storage.go
@@ -22,31 +22,36 @@ type StorageLocal struct {
// StorageSQL represents the configuration of the SQL database.
type StorageSQL struct {
- Address *AddressTCP `koanf:"address" json:"address" jsonschema:"title=Address" jsonschema_description:"The address of the database."`
+ Address *AddressTCP `koanf:"address" json:"address" jsonschema:"title=Address" jsonschema_description:"The address of the SQL Server."`
Database string `koanf:"database" json:"database" jsonschema:"title=Database" jsonschema_description:"The database name to use upon a successful connection."`
Username string `koanf:"username" json:"username" jsonschema:"title=Username" jsonschema_description:"The username to use to authenticate."`
Password string `koanf:"password" json:"password" jsonschema:"title=Password" jsonschema_description:"The password to use to authenticate."`
Timeout time.Duration `koanf:"timeout" json:"timeout" jsonschema:"default=5 seconds,title=Timeout" jsonschema_description:"The timeout for the database connection."`
+ TLS *TLS `koanf:"tls" json:"tls"`
}
// StorageMySQL represents the configuration of a MySQL database.
type StorageMySQL struct {
StorageSQL `koanf:",squash"`
-
- TLS *TLS `koanf:"tls" json:"tls"`
}
// StoragePostgreSQL represents the configuration of a PostgreSQL database.
type StoragePostgreSQL struct {
StorageSQL `koanf:",squash"`
- Schema string `koanf:"schema" json:"schema" jsonschema:"default=public,title=Schema" jsonschema_description:"The default schema name to use."`
- TLS *TLS `koanf:"tls" json:"tls"`
+ Schema string `koanf:"schema" json:"schema" jsonschema:"default=public,title=Schema" jsonschema_description:"The default schema name to use."`
+
+ Servers []StoragePostgreSQLServer `koanf:"servers" json:"servers" jsonschema:"title=Servers" jsonschema_description:"The fallback PostgreSQL severs to connect to in addition to the one defined by the address."`
// Deprecated: Use the TLS configuration instead.
SSL *StoragePostgreSQLSSL `koanf:"ssl" json:"ssl" jsonschema:"deprecated,title=SSL"`
}
+type StoragePostgreSQLServer struct {
+ Address *AddressTCP `koanf:"address" json:"address" jsonschema:"title=Address" jsonschema_description:"The address of the PostgreSQL Server."`
+ TLS *TLS `koanf:"tls" json:"tls"`
+}
+
// StoragePostgreSQLSSL represents the SSL configuration of a PostgreSQL database.
type StoragePostgreSQLSSL struct {
Mode string `koanf:"mode" json:"mode" jsonschema:"deprecated,enum=disable,enum=verify-ca,enum=require,enum=verify-full,title=Mode" jsonschema_description:"The SSL mode to use, deprecated and replaced with the TLS options."`
@@ -64,9 +69,9 @@ var DefaultSQLStorageConfiguration = StorageSQL{
var DefaultMySQLStorageConfiguration = StorageMySQL{
StorageSQL: StorageSQL{
Address: &AddressTCP{Address{true, false, -1, 3306, &url.URL{Scheme: AddressSchemeTCP, Host: "localhost:3306"}}},
- },
- TLS: &TLS{
- MinimumVersion: TLSVersion{tls.VersionTLS12},
+ TLS: &TLS{
+ MinimumVersion: TLSVersion{tls.VersionTLS12},
+ },
},
}
@@ -74,11 +79,19 @@ var DefaultMySQLStorageConfiguration = StorageMySQL{
var DefaultPostgreSQLStorageConfiguration = StoragePostgreSQL{
StorageSQL: StorageSQL{
Address: &AddressTCP{Address{true, false, -1, 5432, &url.URL{Scheme: AddressSchemeTCP, Host: "localhost:5432"}}},
+ TLS: &TLS{
+ MinimumVersion: TLSVersion{tls.VersionTLS12},
+ },
},
- Schema: "public",
- TLS: &TLS{
- MinimumVersion: TLSVersion{tls.VersionTLS12},
+ Servers: []StoragePostgreSQLServer{
+ {
+ Address: &AddressTCP{Address{true, false, -1, 5432, &url.URL{Scheme: AddressSchemeTCP, Host: "localhost:5432"}}},
+ TLS: &TLS{
+ MinimumVersion: TLSVersion{tls.VersionTLS12},
+ },
+ },
},
+ Schema: "public",
SSL: &StoragePostgreSQLSSL{
Mode: "disable",
},
diff --git a/internal/configuration/validator/const.go b/internal/configuration/validator/const.go
index 7298f293d..396423982 100644
--- a/internal/configuration/validator/const.go
+++ b/internal/configuration/validator/const.go
@@ -155,6 +155,7 @@ const (
errStrStorageMultiple = "storage: option 'local', 'mysql' and 'postgres' are mutually exclusive but %s have been configured"
errStrStorageEncryptionKeyMustBeProvided = "storage: option 'encryption_key' is required"
errStrStorageEncryptionKeyTooShort = "storage: option 'encryption_key' must be 20 characters or longer"
+ errFmtStorageAddressValidate = "storage: %s: option 'address' with value '%s' is invalid: %w"
errFmtStorageUserPassMustBeProvided = "storage: %s: option 'username' and 'password' are required" //nolint:gosec
errFmtStorageOptionMustBeProvided = "storage: %s: option '%s' is required"
errFmtStorageOptionAddressConflictWithHostPort = "storage: %s: option 'host' and 'port' can't be configured at the same time as 'address'"
diff --git a/internal/configuration/validator/storage.go b/internal/configuration/validator/storage.go
index d0ad1bb7d..647847dc9 100644
--- a/internal/configuration/validator/storage.go
+++ b/internal/configuration/validator/storage.go
@@ -62,7 +62,7 @@ func validateSQLConfiguration(config, defaults *schema.StorageSQL, validator *sc
var err error
if err = config.Address.ValidateSQL(); err != nil {
- validator.Push(fmt.Errorf(errFmtServerAddress, config.Address.String(), err))
+ validator.Push(fmt.Errorf(errFmtStorageAddressValidate, provider, config.Address.String(), err))
}
}
@@ -132,6 +132,46 @@ func validatePostgreSQLConfiguration(config *schema.StoragePostgreSQL, validator
validator.Push(fmt.Errorf(errFmtStoragePostgreSQLInvalidSSLMode, utils.StringJoinOr(validStoragePostgreSQLSSLModes), config.SSL.Mode)) //nolint:staticcheck
}
}
+
+ validatePostgreSQLConfigurationServers(config, validator)
+}
+
+func validatePostgreSQLConfigurationServers(config *schema.StoragePostgreSQL, validator *schema.StructValidator) {
+ for i, server := range config.Servers {
+ description := fmt.Sprintf("postgres: servers: #%d", i+1)
+
+ if server.Address == nil {
+ validator.Push(fmt.Errorf(errFmtStorageOptionMustBeProvided, description, "address"))
+ } else {
+ var err error
+
+ if err = server.Address.ValidateSQL(); err != nil {
+ validator.Push(fmt.Errorf(errFmtStorageAddressValidate, description, server.Address.String(), err))
+ }
+ }
+
+ if server.Address != nil && server.Address.IsTCP() && server.Address.Port() == 0 {
+ server.Address.SetPort(schema.DefaultPostgreSQLStorageConfiguration.Address.Port())
+ }
+
+ if server.TLS != nil {
+ configDefaultTLS := &schema.TLS{
+ ServerName: server.Address.Hostname(),
+ }
+
+ if config.TLS != nil {
+ configDefaultTLS.MinimumVersion = config.TLS.MinimumVersion
+ configDefaultTLS.MaximumVersion = config.TLS.MaximumVersion
+ } else {
+ configDefaultTLS.MinimumVersion = schema.DefaultPostgreSQLStorageConfiguration.TLS.MinimumVersion
+ configDefaultTLS.MaximumVersion = schema.DefaultPostgreSQLStorageConfiguration.TLS.MaximumVersion
+ }
+
+ if err := ValidateTLSConfig(server.TLS, configDefaultTLS); err != nil {
+ validator.Push(fmt.Errorf(errFmtStorageTLSConfigInvalid, description, err))
+ }
+ }
+ }
}
func validateLocalStorageConfiguration(config *schema.StorageLocal, validator *schema.StructValidator) {
diff --git a/internal/configuration/validator/storage_test.go b/internal/configuration/validator/storage_test.go
index fae3ab681..8cf5c83f8 100644
--- a/internal/configuration/validator/storage_test.go
+++ b/internal/configuration/validator/storage_test.go
@@ -32,7 +32,7 @@ func (suite *StorageSuite) TestShouldValidateOneStorageIsConfigured() {
suite.Require().Len(suite.val.Warnings(), 0)
suite.Require().Len(suite.val.Errors(), 1)
- suite.Assert().EqualError(suite.val.Errors()[0], "storage: configuration for a 'local', 'mysql' or 'postgres' database must be provided")
+ suite.EqualError(suite.val.Errors()[0], "storage: configuration for a 'local', 'mysql' or 'postgres' database must be provided")
}
func (suite *StorageSuite) TestShouldValidateMultipleStorageIsConfigured() {
@@ -44,7 +44,7 @@ func (suite *StorageSuite) TestShouldValidateMultipleStorageIsConfigured() {
suite.Require().Len(suite.val.Warnings(), 0)
suite.Require().Len(suite.val.Errors(), 1)
- suite.Assert().EqualError(suite.val.Errors()[0], "storage: option 'local', 'mysql' and 'postgres' are mutually exclusive but 'local', 'mysql', and 'postgres' have been configured")
+ suite.EqualError(suite.val.Errors()[0], "storage: option 'local', 'mysql' and 'postgres' are mutually exclusive but 'local', 'mysql', and 'postgres' have been configured")
}
func (suite *StorageSuite) TestShouldValidateLocalPathIsProvided() {
@@ -57,7 +57,7 @@ func (suite *StorageSuite) TestShouldValidateLocalPathIsProvided() {
suite.Require().Len(suite.val.Warnings(), 0)
suite.Require().Len(suite.val.Errors(), 1)
- suite.Assert().EqualError(suite.val.Errors()[0], "storage: local: option 'path' is required")
+ suite.EqualError(suite.val.Errors()[0], "storage: local: option 'path' is required")
suite.val.Clear()
suite.config.Local.Path = "/myapth"
@@ -73,9 +73,9 @@ func (suite *StorageSuite) TestShouldValidateMySQLHostUsernamePasswordAndDatabas
ValidateStorage(suite.config, suite.val)
suite.Require().Len(suite.val.Errors(), 3)
- suite.Assert().EqualError(suite.val.Errors()[0], "storage: mysql: option 'address' is required")
- suite.Assert().EqualError(suite.val.Errors()[1], "storage: mysql: option 'username' and 'password' are required")
- suite.Assert().EqualError(suite.val.Errors()[2], "storage: mysql: option 'database' is required")
+ suite.EqualError(suite.val.Errors()[0], "storage: mysql: option 'address' is required")
+ suite.EqualError(suite.val.Errors()[1], "storage: mysql: option 'username' and 'password' are required")
+ suite.EqualError(suite.val.Errors()[2], "storage: mysql: option 'database' is required")
suite.val.Clear()
suite.config.MySQL = &schema.StorageMySQL{
@@ -101,19 +101,19 @@ func (suite *StorageSuite) TestShouldSetDefaultMySQLTLSServerName() {
Username: "myuser",
Password: "pass",
Database: "database",
- },
- TLS: &schema.TLS{
- MinimumVersion: schema.TLSVersion{Value: tls.VersionTLS12},
+ TLS: &schema.TLS{
+ MinimumVersion: schema.TLSVersion{Value: tls.VersionTLS12},
+ },
},
}
ValidateStorage(suite.config, suite.val)
- suite.Assert().Len(suite.val.Warnings(), 0)
- suite.Assert().Len(suite.val.Errors(), 0)
+ suite.Len(suite.val.Warnings(), 0)
+ suite.Len(suite.val.Errors(), 0)
- suite.Assert().Equal(suite.config.MySQL.Address.Hostname(), suite.config.MySQL.TLS.ServerName)
- suite.Assert().Equal("mysql", suite.config.MySQL.TLS.ServerName)
+ suite.Equal(suite.config.MySQL.Address.Hostname(), suite.config.MySQL.TLS.ServerName)
+ suite.Equal("mysql", suite.config.MySQL.TLS.ServerName)
}
func (suite *StorageSuite) TestShouldRaiseErrorOnInvalidMySQLAddressScheme() {
@@ -131,7 +131,7 @@ func (suite *StorageSuite) TestShouldRaiseErrorOnInvalidMySQLAddressScheme() {
suite.Len(suite.val.Warnings(), 0)
suite.Require().Len(suite.val.Errors(), 1)
- suite.EqualError(suite.val.Errors()[0], "server: option 'address' with value 'udp://mysql:1234' is invalid: scheme must be one of 'tcp', 'tcp4', 'tcp6', or 'unix' but is configured as 'udp'")
+ suite.EqualError(suite.val.Errors()[0], "storage: mysql: option 'address' with value 'udp://mysql:1234' is invalid: scheme must be one of 'tcp', 'tcp4', 'tcp6', or 'unix' but is configured as 'udp'")
}
func (suite *StorageSuite) TestShouldRaiseErrorOnInvalidMySQLTLSVersion() {
@@ -143,18 +143,18 @@ func (suite *StorageSuite) TestShouldRaiseErrorOnInvalidMySQLTLSVersion() {
Username: "myuser",
Password: "pass",
Database: "database",
- },
- TLS: &schema.TLS{
- MinimumVersion: schema.TLSVersion{Value: tls.VersionSSL30}, //nolint:staticcheck
+ TLS: &schema.TLS{
+ MinimumVersion: schema.TLSVersion{Value: tls.VersionSSL30}, //nolint:staticcheck
+ },
},
}
ValidateStorage(suite.config, suite.val)
- suite.Assert().Len(suite.val.Warnings(), 0)
+ suite.Len(suite.val.Warnings(), 0)
suite.Require().Len(suite.val.Errors(), 1)
- suite.Assert().EqualError(suite.val.Errors()[0], "storage: mysql: tls: option 'minimum_version' is invalid: minimum version is TLS1.0 but SSL3.0 was configured")
+ suite.EqualError(suite.val.Errors()[0], "storage: mysql: tls: option 'minimum_version' is invalid: minimum version is TLS1.0 but SSL3.0 was configured")
}
func (suite *StorageSuite) TestShouldRaiseErrorOnInvalidMySQLTLSMinVersionGreaterThanMaximum() {
@@ -166,19 +166,19 @@ func (suite *StorageSuite) TestShouldRaiseErrorOnInvalidMySQLTLSMinVersionGreate
Username: "myuser",
Password: "pass",
Database: "database",
- },
- TLS: &schema.TLS{
- MinimumVersion: schema.TLSVersion{Value: tls.VersionTLS13},
- MaximumVersion: schema.TLSVersion{Value: tls.VersionTLS11},
+ TLS: &schema.TLS{
+ MinimumVersion: schema.TLSVersion{Value: tls.VersionTLS13},
+ MaximumVersion: schema.TLSVersion{Value: tls.VersionTLS11},
+ },
},
}
ValidateStorage(suite.config, suite.val)
- suite.Assert().Len(suite.val.Warnings(), 0)
+ suite.Len(suite.val.Warnings(), 0)
suite.Require().Len(suite.val.Errors(), 1)
- suite.Assert().EqualError(suite.val.Errors()[0], "storage: mysql: tls: option combination of 'minimum_version' and 'maximum_version' is invalid: minimum version TLS1.3 is greater than the maximum version TLS1.1")
+ suite.EqualError(suite.val.Errors()[0], "storage: mysql: tls: option combination of 'minimum_version' and 'maximum_version' is invalid: minimum version TLS1.3 is greater than the maximum version TLS1.1")
}
func (suite *StorageSuite) TestShouldValidatePostgreSQLHostUsernamePasswordAndDatabaseAreProvided() {
@@ -187,9 +187,9 @@ func (suite *StorageSuite) TestShouldValidatePostgreSQLHostUsernamePasswordAndDa
ValidateStorage(suite.config, suite.val)
suite.Require().Len(suite.val.Errors(), 3)
- suite.Assert().EqualError(suite.val.Errors()[0], "storage: postgres: option 'address' is required")
- suite.Assert().EqualError(suite.val.Errors()[1], "storage: postgres: option 'username' and 'password' are required")
- suite.Assert().EqualError(suite.val.Errors()[2], "storage: postgres: option 'database' is required")
+ suite.EqualError(suite.val.Errors()[0], "storage: postgres: option 'address' is required")
+ suite.EqualError(suite.val.Errors()[1], "storage: postgres: option 'username' and 'password' are required")
+ suite.EqualError(suite.val.Errors()[2], "storage: postgres: option 'database' is required")
suite.val.Clear()
suite.config.PostgreSQL = &schema.StoragePostgreSQL{
@@ -204,8 +204,8 @@ func (suite *StorageSuite) TestShouldValidatePostgreSQLHostUsernamePasswordAndDa
}
ValidateStorage(suite.config, suite.val)
- suite.Assert().Len(suite.val.Warnings(), 0)
- suite.Assert().Len(suite.val.Errors(), 0)
+ suite.Len(suite.val.Warnings(), 0)
+ suite.Len(suite.val.Errors(), 0)
}
func (suite *StorageSuite) TestShouldValidatePostgresSchemaDefault() {
@@ -222,13 +222,13 @@ func (suite *StorageSuite) TestShouldValidatePostgresSchemaDefault() {
ValidateStorage(suite.config, suite.val)
- suite.Assert().Len(suite.val.Warnings(), 0)
- suite.Assert().Len(suite.val.Errors(), 0)
+ suite.Len(suite.val.Warnings(), 0)
+ suite.Len(suite.val.Errors(), 0)
- suite.Assert().Nil(suite.config.PostgreSQL.SSL) //nolint:staticcheck
- suite.Assert().Nil(suite.config.PostgreSQL.TLS)
+ suite.Nil(suite.config.PostgreSQL.SSL) //nolint:staticcheck
+ suite.Nil(suite.config.PostgreSQL.TLS)
- suite.Assert().Equal("public", suite.config.PostgreSQL.Schema)
+ suite.Equal("public", suite.config.PostgreSQL.Schema)
}
func (suite *StorageSuite) TestShouldValidatePostgresPortDefault() {
@@ -261,22 +261,22 @@ func (suite *StorageSuite) TestShouldValidatePostgresTLSDefaults() {
Username: "myuser",
Password: "pass",
Database: "database",
+ TLS: &schema.TLS{},
},
- TLS: &schema.TLS{},
}
ValidateStorage(suite.config, suite.val)
- suite.Assert().Len(suite.val.Warnings(), 0)
- suite.Assert().Len(suite.val.Errors(), 0)
+ suite.Len(suite.val.Warnings(), 0)
+ suite.Len(suite.val.Errors(), 0)
- suite.Assert().Nil(suite.config.PostgreSQL.SSL) //nolint:staticcheck
+ suite.Nil(suite.config.PostgreSQL.SSL) //nolint:staticcheck
suite.Require().NotNil(suite.config.PostgreSQL.TLS)
- suite.Assert().Equal(uint16(tls.VersionTLS12), suite.config.PostgreSQL.TLS.MinimumVersion.Value)
+ suite.Equal(uint16(tls.VersionTLS12), suite.config.PostgreSQL.TLS.MinimumVersion.Value)
}
-func (suite *StorageSuite) TestShouldSetDefaultPostgreSQLTLSServerName() {
+func (suite *StorageSuite) TestShouldValidatePostgresServers() {
suite.config.PostgreSQL = &schema.StoragePostgreSQL{
StorageSQL: schema.StorageSQL{
Address: &schema.AddressTCP{
@@ -286,20 +286,54 @@ func (suite *StorageSuite) TestShouldSetDefaultPostgreSQLTLSServerName() {
Password: "pass",
Database: "database",
},
- TLS: &schema.TLS{
- MinimumVersion: schema.TLSVersion{Value: tls.VersionTLS12},
+ Servers: []schema.StoragePostgreSQLServer{
+ {
+ Address: &schema.AddressTCP{
+ Address: MustParseAddress("udp://server1:4321"),
+ },
+ },
+ {},
+ {
+ Address: &schema.AddressTCP{
+ Address: MustParseAddress("tcp://server1"),
+ },
+ },
+ {
+ Address: &schema.AddressTCP{
+ Address: MustParseAddress("tcp://server1:5432"),
+ },
+ TLS: &schema.TLS{},
+ },
+ {
+ Address: &schema.AddressTCP{
+ Address: MustParseAddress("tcp://server1:5432"),
+ },
+ TLS: &schema.TLS{
+ MinimumVersion: schema.TLSVersion{Value: tls.VersionTLS13},
+ MaximumVersion: schema.TLSVersion{Value: tls.VersionTLS10},
+ },
+ },
},
}
ValidateStorage(suite.config, suite.val)
- suite.Assert().Len(suite.val.Warnings(), 0)
- suite.Assert().Len(suite.val.Errors(), 0)
+ suite.Len(suite.val.Warnings(), 0)
+ suite.Require().Len(suite.config.PostgreSQL.Servers, 5)
- suite.Assert().Equal(suite.config.PostgreSQL.Address.Hostname(), suite.config.PostgreSQL.TLS.ServerName)
+ suite.Equal(uint16(5432), suite.config.PostgreSQL.Servers[2].Address.Port())
+ suite.Equal("server1", suite.config.PostgreSQL.Servers[3].TLS.ServerName)
+ suite.Equal(schema.TLSVersion{Value: tls.VersionTLS12}, suite.config.PostgreSQL.Servers[3].TLS.MinimumVersion)
+
+ errors := suite.val.Errors()
+
+ suite.Require().Len(errors, 3)
+ suite.EqualError(errors[0], "storage: postgres: servers: #1: option 'address' with value 'udp://server1:4321' is invalid: scheme must be one of 'tcp', 'tcp4', 'tcp6', or 'unix' but is configured as 'udp'")
+ suite.EqualError(errors[1], "storage: postgres: servers: #2: option 'address' is required")
+ suite.EqualError(errors[2], "storage: postgres: servers: #5: tls: option combination of 'minimum_version' and 'maximum_version' is invalid: minimum version TLS1.3 is greater than the maximum version TLS1.0")
}
-func (suite *StorageSuite) TestShouldRaiseErrorOnInvalidPostgreSQLTLSVersion() {
+func (suite *StorageSuite) TestShouldValidatePostgresServersTLSMinMaxFromPrimary() {
suite.config.PostgreSQL = &schema.StoragePostgreSQL{
StorageSQL: schema.StorageSQL{
Address: &schema.AddressTCP{
@@ -308,21 +342,77 @@ func (suite *StorageSuite) TestShouldRaiseErrorOnInvalidPostgreSQLTLSVersion() {
Username: "myuser",
Password: "pass",
Database: "database",
+ TLS: &schema.TLS{
+ MinimumVersion: schema.TLSVersion{Value: tls.VersionTLS10},
+ MaximumVersion: schema.TLSVersion{Value: tls.VersionTLS13},
+ },
},
- TLS: &schema.TLS{
- MinimumVersion: schema.TLSVersion{Value: tls.VersionSSL30}, //nolint:staticcheck
+ Servers: []schema.StoragePostgreSQLServer{
+ {
+ Address: &schema.AddressTCP{
+ Address: MustParseAddress("tcp://server1:5432"),
+ },
+ TLS: &schema.TLS{},
+ },
},
}
ValidateStorage(suite.config, suite.val)
- suite.Assert().Len(suite.val.Warnings(), 0)
+ suite.Len(suite.val.Warnings(), 0)
+ suite.Len(suite.val.Errors(), 0)
+ suite.Require().Len(suite.config.PostgreSQL.Servers, 1)
+
+ suite.Equal("server1", suite.config.PostgreSQL.Servers[0].TLS.ServerName)
+ suite.Equal(schema.TLSVersion{Value: tls.VersionTLS10}, suite.config.PostgreSQL.Servers[0].TLS.MinimumVersion)
+ suite.Equal(schema.TLSVersion{Value: tls.VersionTLS13}, suite.config.PostgreSQL.Servers[0].TLS.MaximumVersion)
+}
+
+func (suite *StorageSuite) TestShouldValidatePostgresUDP() {
+ suite.config.PostgreSQL = &schema.StoragePostgreSQL{
+ StorageSQL: schema.StorageSQL{
+ Address: &schema.AddressTCP{
+ Address: MustParseAddress("udp://postgre:4321"),
+ },
+ Username: "myuser",
+ Password: "pass",
+ Database: "database",
+ TLS: &schema.TLS{
+ MinimumVersion: schema.TLSVersion{Value: tls.VersionTLS10},
+ MaximumVersion: schema.TLSVersion{Value: tls.VersionTLS13},
+ },
+ },
+ }
+
+ ValidateStorage(suite.config, suite.val)
+
+ suite.Len(suite.val.Warnings(), 0)
suite.Require().Len(suite.val.Errors(), 1)
- suite.Assert().EqualError(suite.val.Errors()[0], "storage: postgres: tls: option 'minimum_version' is invalid: minimum version is TLS1.0 but SSL3.0 was configured")
+ suite.EqualError(suite.val.Errors()[0], "storage: postgres: option 'address' with value 'udp://postgre:4321' is invalid: scheme must be one of 'tcp', 'tcp4', 'tcp6', or 'unix' but is configured as 'udp'")
}
-func (suite *StorageSuite) TestShouldRaiseErrorOnInvalidPostgreSQLMinVersionGreaterThanMaximum() {
+func (suite *StorageSuite) TestShouldValidatePostgresSetPort() {
+ suite.config.PostgreSQL = &schema.StoragePostgreSQL{
+ StorageSQL: schema.StorageSQL{
+ Address: &schema.AddressTCP{
+ Address: MustParseAddress("tcp://postgre"),
+ },
+ Username: "myuser",
+ Password: "pass",
+ Database: "database",
+ },
+ }
+
+ ValidateStorage(suite.config, suite.val)
+
+ suite.Len(suite.val.Warnings(), 0)
+ suite.Len(suite.val.Errors(), 0)
+
+ suite.Equal(uint16(5432), suite.config.PostgreSQL.Address.Port())
+}
+
+func (suite *StorageSuite) TestShouldSetDefaultPostgreSQLTLSServerName() {
suite.config.PostgreSQL = &schema.StoragePostgreSQL{
StorageSQL: schema.StorageSQL{
Address: &schema.AddressTCP{
@@ -331,19 +421,65 @@ func (suite *StorageSuite) TestShouldRaiseErrorOnInvalidPostgreSQLMinVersionGrea
Username: "myuser",
Password: "pass",
Database: "database",
+ TLS: &schema.TLS{
+ MinimumVersion: schema.TLSVersion{Value: tls.VersionTLS12},
+ },
},
- TLS: &schema.TLS{
- MinimumVersion: schema.TLSVersion{Value: tls.VersionTLS13},
- MaximumVersion: schema.TLSVersion{Value: tls.VersionTLS11},
+ }
+
+ ValidateStorage(suite.config, suite.val)
+
+ suite.Len(suite.val.Warnings(), 0)
+ suite.Len(suite.val.Errors(), 0)
+
+ suite.Equal(suite.config.PostgreSQL.Address.Hostname(), suite.config.PostgreSQL.TLS.ServerName)
+}
+
+func (suite *StorageSuite) TestShouldRaiseErrorOnInvalidPostgreSQLTLSVersion() {
+ suite.config.PostgreSQL = &schema.StoragePostgreSQL{
+ StorageSQL: schema.StorageSQL{
+ Address: &schema.AddressTCP{
+ Address: MustParseAddress("tcp://postgre:4321"),
+ },
+ Username: "myuser",
+ Password: "pass",
+ Database: "database",
+ TLS: &schema.TLS{
+ MinimumVersion: schema.TLSVersion{Value: tls.VersionSSL30}, //nolint:staticcheck
+ },
},
}
ValidateStorage(suite.config, suite.val)
- suite.Assert().Len(suite.val.Warnings(), 0)
+ suite.Len(suite.val.Warnings(), 0)
suite.Require().Len(suite.val.Errors(), 1)
- suite.Assert().EqualError(suite.val.Errors()[0], "storage: postgres: tls: option combination of 'minimum_version' and 'maximum_version' is invalid: minimum version TLS1.3 is greater than the maximum version TLS1.1")
+ suite.EqualError(suite.val.Errors()[0], "storage: postgres: tls: option 'minimum_version' is invalid: minimum version is TLS1.0 but SSL3.0 was configured")
+}
+
+func (suite *StorageSuite) TestShouldRaiseErrorOnInvalidPostgreSQLMinVersionGreaterThanMaximum() {
+ suite.config.PostgreSQL = &schema.StoragePostgreSQL{
+ StorageSQL: schema.StorageSQL{
+ Address: &schema.AddressTCP{
+ Address: MustParseAddress("tcp://postgre:4321"),
+ },
+ Username: "myuser",
+ Password: "pass",
+ Database: "database",
+ TLS: &schema.TLS{
+ MinimumVersion: schema.TLSVersion{Value: tls.VersionTLS13},
+ MaximumVersion: schema.TLSVersion{Value: tls.VersionTLS11},
+ },
+ },
+ }
+
+ ValidateStorage(suite.config, suite.val)
+
+ suite.Len(suite.val.Warnings(), 0)
+ suite.Require().Len(suite.val.Errors(), 1)
+
+ suite.EqualError(suite.val.Errors()[0], "storage: postgres: tls: option combination of 'minimum_version' and 'maximum_version' is invalid: minimum version TLS1.3 is greater than the maximum version TLS1.1")
}
func (suite *StorageSuite) TestShouldValidatePostgresSSLDefaults() {
@@ -361,13 +497,13 @@ func (suite *StorageSuite) TestShouldValidatePostgresSSLDefaults() {
ValidateStorage(suite.config, suite.val)
- suite.Assert().Len(suite.val.Warnings(), 1)
- suite.Assert().Len(suite.val.Errors(), 0)
+ suite.Len(suite.val.Warnings(), 1)
+ suite.Len(suite.val.Errors(), 0)
- suite.Assert().NotNil(suite.config.PostgreSQL.SSL) //nolint:staticcheck
+ suite.NotNil(suite.config.PostgreSQL.SSL) //nolint:staticcheck
suite.Require().Nil(suite.config.PostgreSQL.TLS)
- suite.Assert().Equal(schema.DefaultPostgreSQLStorageConfiguration.SSL.Mode, suite.config.PostgreSQL.SSL.Mode) //nolint:staticcheck
+ suite.Equal(schema.DefaultPostgreSQLStorageConfiguration.SSL.Mode, suite.config.PostgreSQL.SSL.Mode) //nolint:staticcheck
}
func (suite *StorageSuite) TestShouldRaiseErrorOnTLSAndLegacySSL() {
@@ -379,17 +515,17 @@ func (suite *StorageSuite) TestShouldRaiseErrorOnTLSAndLegacySSL() {
Username: "myuser",
Password: "pass",
Database: "database",
+ TLS: &schema.TLS{},
},
SSL: &schema.StoragePostgreSQLSSL{},
- TLS: &schema.TLS{},
}
ValidateStorage(suite.config, suite.val)
- suite.Assert().Len(suite.val.Warnings(), 0)
+ suite.Len(suite.val.Warnings(), 0)
suite.Require().Len(suite.val.Errors(), 1)
- suite.Assert().EqualError(suite.val.Errors()[0], "storage: postgres: can't define both 'tls' and 'ssl' configuration options")
+ suite.EqualError(suite.val.Errors()[0], "storage: postgres: can't define both 'tls' and 'ssl' configuration options")
}
func (suite *StorageSuite) TestShouldValidatePostgresDefaultsDontOverrideConfiguration() {
@@ -411,12 +547,12 @@ func (suite *StorageSuite) TestShouldValidatePostgresDefaultsDontOverrideConfigu
ValidateStorage(suite.config, suite.val)
suite.Require().Len(suite.val.Warnings(), 1)
- suite.Assert().Len(suite.val.Errors(), 0)
+ suite.Len(suite.val.Errors(), 0)
- suite.Assert().Equal("require", suite.config.PostgreSQL.SSL.Mode) //nolint:staticcheck
- suite.Assert().Equal("authelia", suite.config.PostgreSQL.Schema)
+ suite.Equal("require", suite.config.PostgreSQL.SSL.Mode) //nolint:staticcheck
+ suite.Equal("authelia", suite.config.PostgreSQL.Schema)
- suite.Assert().EqualError(suite.val.Warnings()[0], "storage: postgres: ssl: the ssl configuration options are deprecated and we recommend the tls options instead")
+ suite.EqualError(suite.val.Warnings()[0], "storage: postgres: ssl: the ssl configuration options are deprecated and we recommend the tls options instead")
}
func (suite *StorageSuite) TestShouldValidatePostgresSSLModeMustBeValid() {
@@ -436,9 +572,9 @@ func (suite *StorageSuite) TestShouldValidatePostgresSSLModeMustBeValid() {
ValidateStorage(suite.config, suite.val)
- suite.Assert().Len(suite.val.Warnings(), 1)
+ suite.Len(suite.val.Warnings(), 1)
suite.Require().Len(suite.val.Errors(), 1)
- suite.Assert().EqualError(suite.val.Errors()[0], "storage: postgres: ssl: option 'mode' must be one of 'disable', 'require', 'verify-ca', or 'verify-full' but it's configured as 'unknown'")
+ suite.EqualError(suite.val.Errors()[0], "storage: postgres: ssl: option 'mode' must be one of 'disable', 'require', 'verify-ca', or 'verify-full' but it's configured as 'unknown'")
}
func (suite *StorageSuite) TestShouldRaiseErrorOnNoEncryptionKey() {
@@ -451,7 +587,7 @@ func (suite *StorageSuite) TestShouldRaiseErrorOnNoEncryptionKey() {
suite.Require().Len(suite.val.Warnings(), 0)
suite.Require().Len(suite.val.Errors(), 1)
- suite.Assert().EqualError(suite.val.Errors()[0], "storage: option 'encryption_key' is required")
+ suite.EqualError(suite.val.Errors()[0], "storage: option 'encryption_key' is required")
}
func (suite *StorageSuite) TestShouldRaiseErrorOnShortEncryptionKey() {
@@ -464,7 +600,7 @@ func (suite *StorageSuite) TestShouldRaiseErrorOnShortEncryptionKey() {
suite.Require().Len(suite.val.Warnings(), 0)
suite.Require().Len(suite.val.Errors(), 1)
- suite.Assert().EqualError(suite.val.Errors()[0], "storage: option 'encryption_key' must be 20 characters or longer")
+ suite.EqualError(suite.val.Errors()[0], "storage: option 'encryption_key' must be 20 characters or longer")
}
func TestShouldRunStorageSuite(t *testing.T) {
diff --git a/internal/storage/sql_provider_backend_mysql_test.go b/internal/storage/sql_provider_backend_mysql_test.go
new file mode 100644
index 000000000..f5bd2bee7
--- /dev/null
+++ b/internal/storage/sql_provider_backend_mysql_test.go
@@ -0,0 +1,60 @@
+package storage
+
+import (
+ "crypto/tls"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+
+ "github.com/authelia/authelia/v4/internal/configuration/schema"
+)
+
+func TestNewMySQLProvider(t *testing.T) {
+ standardAddress, err := schema.NewAddress("tcp://mysql")
+ require.NoError(t, err)
+
+ testCases := []struct {
+ name string
+ have *schema.Configuration
+ }{
+ {
+ "ShouldHandleBasic",
+ &schema.Configuration{
+ Storage: schema.Storage{
+ MySQL: &schema.StorageMySQL{
+ StorageSQL: schema.StorageSQL{
+ Address: &schema.AddressTCP{Address: *standardAddress},
+ Database: "authelia",
+ },
+ },
+ },
+ },
+ },
+ {
+ "ShouldHandleTLS",
+ &schema.Configuration{
+ Storage: schema.Storage{
+ MySQL: &schema.StorageMySQL{
+ StorageSQL: schema.StorageSQL{
+ Address: &schema.AddressTCP{Address: *standardAddress},
+ Database: "authelia",
+ TLS: &schema.TLS{
+ MinimumVersion: schema.TLSVersion{Value: tls.VersionTLS12},
+ MaximumVersion: schema.TLSVersion{Value: tls.VersionTLS13},
+ SkipVerify: false,
+ ServerName: "mysql",
+ },
+ },
+ },
+ },
+ },
+ },
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ assert.NotNil(t, NewMySQLProvider(tc.have, nil))
+ })
+ }
+}
diff --git a/internal/storage/sql_provider_backend_postgres.go b/internal/storage/sql_provider_backend_postgres.go
index a410e01fd..daa7eef02 100644
--- a/internal/storage/sql_provider_backend_postgres.go
+++ b/internal/storage/sql_provider_backend_postgres.go
@@ -11,6 +11,7 @@ import (
"strconv"
"github.com/jackc/pgx/v5"
+ "github.com/jackc/pgx/v5/pgconn"
"github.com/jackc/pgx/v5/stdlib"
"github.com/authelia/authelia/v4/internal/configuration/schema"
@@ -174,7 +175,12 @@ func dsnPostgreSQL(config *schema.StoragePostgreSQL, globalCACertPool *x509.Cert
dsnConfig.TLSConfig = loadPostgreSQLTLSConfig(config, globalCACertPool)
dsnConfig.ConnectTimeout = config.Timeout
dsnConfig.RuntimeParams = map[string]string{
- "search_path": config.Schema,
+ "application_name": fmt.Sprintf("Authelia %s", utils.Version()),
+ "search_path": config.Schema,
+ }
+
+ if len(config.Servers) != 0 {
+ dsnPostgreSQLFallbacks(config, globalCACertPool, dsnConfig)
}
return stdlib.RegisterConnConfig(dsnConfig)
@@ -207,20 +213,40 @@ func dsnPostgreSQLHostPort(address *schema.AddressTCP) (host string, port uint16
return host, port
}
+func dsnPostgreSQLFallbacks(config *schema.StoragePostgreSQL, globalCACertPool *x509.CertPool, dsnConfig *pgx.ConnConfig) {
+ dsnConfig.Fallbacks = make([]*pgconn.FallbackConfig, len(config.Servers))
+
+ for i, server := range config.Servers {
+ fallback := &pgconn.FallbackConfig{
+ TLSConfig: loadPostgreSQLModernTLSConfig(server.TLS, globalCACertPool),
+ }
+
+ fallback.Host, fallback.Port = dsnPostgreSQLHostPort(server.Address)
+
+ if fallback.Port == 0 && !server.Address.IsUnixDomainSocket() {
+ fallback.Port = 5432
+ }
+
+ dsnConfig.Fallbacks[i] = fallback
+ }
+}
+
func loadPostgreSQLTLSConfig(config *schema.StoragePostgreSQL, globalCACertPool *x509.CertPool) (tlsConfig *tls.Config) {
if config.TLS != nil {
- return utils.NewTLSConfig(config.TLS, globalCACertPool)
+ return loadPostgreSQLModernTLSConfig(config.TLS, globalCACertPool)
+ } else if config.SSL != nil { //nolint:staticcheck
+ return loadPostgreSQLLegacyTLSConfig(config, globalCACertPool)
}
- return loadPostgreSQLLegacyTLSConfig(config, globalCACertPool)
+ return nil
+}
+
+func loadPostgreSQLModernTLSConfig(config *schema.TLS, globalCACertPool *x509.CertPool) (tlsConfig *tls.Config) {
+ return utils.NewTLSConfig(config, globalCACertPool)
}
//nolint:staticcheck // Used for legacy purposes.
func loadPostgreSQLLegacyTLSConfig(config *schema.StoragePostgreSQL, globalCACertPool *x509.CertPool) (tlsConfig *tls.Config) {
- if config.SSL == nil {
- return nil
- }
-
var (
ca *x509.Certificate
certs []tls.Certificate
@@ -238,7 +264,7 @@ func loadPostgreSQLLegacyTLSConfig(config *schema.StoragePostgreSQL, globalCACer
case nil:
caCertPool = globalCACertPool
default:
- caCertPool = globalCACertPool.Clone()
+ caCertPool = globalCACertPool
caCertPool.AddCert(ca)
}
diff --git a/internal/storage/sql_provider_backend_postgres_test.go b/internal/storage/sql_provider_backend_postgres_test.go
index 4a56c25a1..a8ed6d584 100644
--- a/internal/storage/sql_provider_backend_postgres_test.go
+++ b/internal/storage/sql_provider_backend_postgres_test.go
@@ -38,10 +38,10 @@ func TestNewPostgreSQLProvider(t *testing.T) {
PostgreSQL: &schema.StoragePostgreSQL{
StorageSQL: schema.StorageSQL{
Address: &schema.AddressTCP{Address: *address},
- },
- TLS: &schema.TLS{
- MinimumVersion: schema.TLSVersion{Value: tls.VersionTLS12},
- MaximumVersion: schema.TLSVersion{Value: tls.VersionTLS13},
+ TLS: &schema.TLS{
+ MinimumVersion: schema.TLSVersion{Value: tls.VersionTLS12},
+ MaximumVersion: schema.TLSVersion{Value: tls.VersionTLS13},
+ },
},
},
},
diff --git a/internal/storage/sql_provider_backend_sqlite_test.go b/internal/storage/sql_provider_backend_sqlite_test.go
new file mode 100644
index 000000000..a591d0bed
--- /dev/null
+++ b/internal/storage/sql_provider_backend_sqlite_test.go
@@ -0,0 +1,44 @@
+package storage
+
+import (
+ "path/filepath"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+
+ "github.com/authelia/authelia/v4/internal/configuration/schema"
+)
+
+func TestNewSQLiteProvider(t *testing.T) {
+ dir := t.TempDir()
+ testCases := []struct {
+ name string
+ have *schema.Configuration
+ }{
+ {
+ "ShouldHandleBasic",
+ &schema.Configuration{
+ Storage: schema.Storage{
+ Local: &schema.StorageLocal{
+ Path: filepath.Join(dir, "sqlite1.db"),
+ },
+ },
+ },
+ },
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ assert.NotNil(t, NewSQLiteProvider(tc.have))
+ })
+ }
+}
+
+func TestSQLiteRegisteredFuncs(t *testing.T) {
+ output := sqlite3BLOBToTEXTBase64([]byte("example"))
+ assert.Equal(t, "ZXhhbXBsZQ==", output)
+
+ decoded, err := sqlite3TEXTBase64ToBLOB("ZXhhbXBsZQ==")
+ assert.NoError(t, err)
+ assert.Equal(t, []byte("example"), decoded)
+}