From 6c472d86279cc375110b5fc32cfc7bfdafd6b4b0 Mon Sep 17 00:00:00 2001 From: James Elliott Date: Tue, 9 May 2023 21:25:56 +1000 Subject: [PATCH] refactor(configuration): umask from query (#5416) Signed-off-by: James Elliott --- .../en/configuration/miscellaneous/server.md | 15 - .../en/configuration/prologue/common.md | 12 + .../en/configuration/telemetry/metrics.md | 15 - docs/data/configkeys.json | 2 +- internal/configuration/schema/const.go | 14 +- internal/configuration/schema/keys.go | 2 - internal/configuration/schema/notifier.go | 2 +- internal/configuration/schema/server.go | 12 +- internal/configuration/schema/storage.go | 2 +- internal/configuration/schema/telemetry.go | 8 +- .../configuration/schema/types_address.go | 155 ++++++---- .../schema/types_address_test.go | 280 +++++++++++++----- internal/server/server.go | 18 +- 13 files changed, 340 insertions(+), 197 deletions(-) diff --git a/docs/content/en/configuration/miscellaneous/server.md b/docs/content/en/configuration/miscellaneous/server.md index 683590747..865329991 100644 --- a/docs/content/en/configuration/miscellaneous/server.md +++ b/docs/content/en/configuration/miscellaneous/server.md @@ -22,7 +22,6 @@ aliases: ```yaml server: address: 'tcp://:9091' - umask: 0022 path: '' disable_healthcheck: false tls: @@ -80,20 +79,6 @@ server: address: unix:///var/run/authelia.sock ``` -### umask - -{{< confkey type="int" required="no" >}} - -If set temporarily changes the umask during the creation of the unix domain socket if configured as such in the -[address](#address). Typically this should be set before the process is actually running and users should not use this -option, however it's recognized in various specific scenarios this may not be completely adequate. - -One such example is when you want the proxy to have permission to the socket but not the files, in which case running a -umask of `0077` by default is good, and running a umask of `0027` so that the group Authelia is running as has -permission to the socket. - -This value should typically be prefixed with a `0` to ensure the relevant parsers handle it correctly. - ### path {{< confkey type="string " required="no" >}} diff --git a/docs/content/en/configuration/prologue/common.md b/docs/content/en/configuration/prologue/common.md index b4c10dbc5..f6762411d 100644 --- a/docs/content/en/configuration/prologue/common.md +++ b/docs/content/en/configuration/prologue/common.md @@ -108,10 +108,22 @@ The following format represents the unix domain socket format. It's valid for bo instances. Refer to the individual documentation for an option for clarity. In this format as per the notation there are no optional portions. +The Unix Domain Socket format also accepts a query string. The following query parameters control certain behaviour of +this address type. + +| Parameter | Listeners | Connectors | Purpose | +|:---------:|:---------:|:----------:|:------------------------------------------------------------------------------------------------------------------------------------:| +| `umask` | Yes | No | Sets the umask prior to creating the socket and restores it after creating it. The value must be an octal number with 3 or 4 digits. | + + ```text unix:// ``` +```text +unix://?umask=0022 +``` + ##### Examples Various examples for these formats. diff --git a/docs/content/en/configuration/telemetry/metrics.md b/docs/content/en/configuration/telemetry/metrics.md index 4c9b3acbf..deb30d329 100644 --- a/docs/content/en/configuration/telemetry/metrics.md +++ b/docs/content/en/configuration/telemetry/metrics.md @@ -23,7 +23,6 @@ telemetry: metrics: enabled: false address: 'tcp://:9959' - umask: 0022 buffers: read: 4096 write: 4096 @@ -53,20 +52,6 @@ see the [documentation](../prologue/common.md#address) on this format for more i Configures the listener address for the [Prometheus] Metrics Exporter HTTP Server. The address itself is a listener and the scheme must either be the `unix` scheme or one of the `tcp` schemes. -### umask - -{{< confkey type="int" required="no" >}} - -If set temporarily changes the umask during the creation of the unix domain socket if configured as such in the -[address](#address). Typically this should be set before the process is actually running and users should not use this -option, however it's recognized in various specific scenarios this may not be completely adequate. - -One such example is when you want the proxy to have permission to the socket but not the files, in which case running a -umask of `0077` by default is good, and running a umask of `0027` so that the group Authelia is running as has -permission to the socket. - -This value should typically be prefixed with a `0` to ensure the relevant parsers handle it correctly. - ### buffers *__Reference Note:__ This configuration option uses the diff --git a/docs/data/configkeys.json b/docs/data/configkeys.json index ecc9213cf..cdbb3a02c 100644 --- a/docs/data/configkeys.json +++ b/docs/data/configkeys.json @@ -1 +1 @@ -[{"path":"theme","secret":false,"env":"AUTHELIA_THEME"},{"path":"certificates_directory","secret":false,"env":"AUTHELIA_CERTIFICATES_DIRECTORY"},{"path":"jwt_secret","secret":true,"env":"AUTHELIA_JWT_SECRET_FILE"},{"path":"default_redirection_url","secret":false,"env":"AUTHELIA_DEFAULT_REDIRECTION_URL"},{"path":"default_2fa_method","secret":false,"env":"AUTHELIA_DEFAULT_2FA_METHOD"},{"path":"log.level","secret":false,"env":"AUTHELIA_LOG_LEVEL"},{"path":"log.format","secret":false,"env":"AUTHELIA_LOG_FORMAT"},{"path":"log.file_path","secret":false,"env":"AUTHELIA_LOG_FILE_PATH"},{"path":"log.keep_stdout","secret":false,"env":"AUTHELIA_LOG_KEEP_STDOUT"},{"path":"identity_providers.oidc.hmac_secret","secret":true,"env":"AUTHELIA_IDENTITY_PROVIDERS_OIDC_HMAC_SECRET_FILE"},{"path":"identity_providers.oidc.issuer_certificate_chain","secret":true,"env":"AUTHELIA_IDENTITY_PROVIDERS_OIDC_ISSUER_CERTIFICATE_CHAIN_FILE"},{"path":"identity_providers.oidc.issuer_private_key","secret":true,"env":"AUTHELIA_IDENTITY_PROVIDERS_OIDC_ISSUER_PRIVATE_KEY_FILE"},{"path":"identity_providers.oidc.access_token_lifespan","secret":false,"env":"AUTHELIA_IDENTITY_PROVIDERS_OIDC_ACCESS_TOKEN_LIFESPAN"},{"path":"identity_providers.oidc.authorize_code_lifespan","secret":false,"env":"AUTHELIA_IDENTITY_PROVIDERS_OIDC_AUTHORIZE_CODE_LIFESPAN"},{"path":"identity_providers.oidc.id_token_lifespan","secret":false,"env":"AUTHELIA_IDENTITY_PROVIDERS_OIDC_ID_TOKEN_LIFESPAN"},{"path":"identity_providers.oidc.refresh_token_lifespan","secret":false,"env":"AUTHELIA_IDENTITY_PROVIDERS_OIDC_REFRESH_TOKEN_LIFESPAN"},{"path":"identity_providers.oidc.enable_client_debug_messages","secret":false,"env":"AUTHELIA_IDENTITY_PROVIDERS_OIDC_ENABLE_CLIENT_DEBUG_MESSAGES"},{"path":"identity_providers.oidc.minimum_parameter_entropy","secret":false,"env":"AUTHELIA_IDENTITY_PROVIDERS_OIDC_MINIMUM_PARAMETER_ENTROPY"},{"path":"identity_providers.oidc.enforce_pkce","secret":false,"env":"AUTHELIA_IDENTITY_PROVIDERS_OIDC_ENFORCE_PKCE"},{"path":"identity_providers.oidc.enable_pkce_plain_challenge","secret":false,"env":"AUTHELIA_IDENTITY_PROVIDERS_OIDC_ENABLE_PKCE_PLAIN_CHALLENGE"},{"path":"identity_providers.oidc.cors.allowed_origins_from_client_redirect_uris","secret":false,"env":"AUTHELIA_IDENTITY_PROVIDERS_OIDC_CORS_ALLOWED_ORIGINS_FROM_CLIENT_REDIRECT_URIS"},{"path":"identity_providers.oidc.pushed_authorizations.enforce","secret":false,"env":"AUTHELIA_IDENTITY_PROVIDERS_OIDC_PUSHED_AUTHORIZATIONS_ENFORCE"},{"path":"identity_providers.oidc.pushed_authorizations.context_lifespan","secret":false,"env":"AUTHELIA_IDENTITY_PROVIDERS_OIDC_PUSHED_AUTHORIZATIONS_CONTEXT_LIFESPAN"},{"path":"authentication_backend.password_reset.disable","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_PASSWORD_RESET_DISABLE"},{"path":"authentication_backend.password_reset.custom_url","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_PASSWORD_RESET_CUSTOM_URL"},{"path":"authentication_backend.refresh_interval","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_REFRESH_INTERVAL"},{"path":"authentication_backend.file.path","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PATH"},{"path":"authentication_backend.file.watch","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_WATCH"},{"path":"authentication_backend.file.password.algorithm","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_ALGORITHM"},{"path":"authentication_backend.file.password.argon2.variant","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_ARGON2_VARIANT"},{"path":"authentication_backend.file.password.argon2.iterations","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_ARGON2_ITERATIONS"},{"path":"authentication_backend.file.password.argon2.memory","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_ARGON2_MEMORY"},{"path":"authentication_backend.file.password.argon2.parallelism","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_ARGON2_PARALLELISM"},{"path":"authentication_backend.file.password.argon2.key_length","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_ARGON2_KEY_LENGTH"},{"path":"authentication_backend.file.password.argon2.salt_length","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_ARGON2_SALT_LENGTH"},{"path":"authentication_backend.file.password.sha2crypt.variant","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_SHA2CRYPT_VARIANT"},{"path":"authentication_backend.file.password.sha2crypt.iterations","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_SHA2CRYPT_ITERATIONS"},{"path":"authentication_backend.file.password.sha2crypt.salt_length","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_SHA2CRYPT_SALT_LENGTH"},{"path":"authentication_backend.file.password.pbkdf2.variant","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_PBKDF2_VARIANT"},{"path":"authentication_backend.file.password.pbkdf2.iterations","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_PBKDF2_ITERATIONS"},{"path":"authentication_backend.file.password.pbkdf2.salt_length","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_PBKDF2_SALT_LENGTH"},{"path":"authentication_backend.file.password.bcrypt.variant","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_BCRYPT_VARIANT"},{"path":"authentication_backend.file.password.bcrypt.cost","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_BCRYPT_COST"},{"path":"authentication_backend.file.password.scrypt.iterations","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_SCRYPT_ITERATIONS"},{"path":"authentication_backend.file.password.scrypt.block_size","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_SCRYPT_BLOCK_SIZE"},{"path":"authentication_backend.file.password.scrypt.parallelism","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_SCRYPT_PARALLELISM"},{"path":"authentication_backend.file.password.scrypt.key_length","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_SCRYPT_KEY_LENGTH"},{"path":"authentication_backend.file.password.scrypt.salt_length","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_SCRYPT_SALT_LENGTH"},{"path":"authentication_backend.file.password.iterations","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_ITERATIONS"},{"path":"authentication_backend.file.password.memory","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_MEMORY"},{"path":"authentication_backend.file.password.parallelism","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_PARALLELISM"},{"path":"authentication_backend.file.password.key_length","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_KEY_LENGTH"},{"path":"authentication_backend.file.password.salt_length","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_SALT_LENGTH"},{"path":"authentication_backend.file.search.email","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_SEARCH_EMAIL"},{"path":"authentication_backend.file.search.case_insensitive","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_SEARCH_CASE_INSENSITIVE"},{"path":"authentication_backend.ldap.address","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ADDRESS"},{"path":"authentication_backend.ldap.implementation","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_IMPLEMENTATION"},{"path":"authentication_backend.ldap.timeout","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_TIMEOUT"},{"path":"authentication_backend.ldap.start_tls","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_START_TLS"},{"path":"authentication_backend.ldap.tls.minimum_version","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_TLS_MINIMUM_VERSION"},{"path":"authentication_backend.ldap.tls.maximum_version","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_TLS_MAXIMUM_VERSION"},{"path":"authentication_backend.ldap.tls.skip_verify","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_TLS_SKIP_VERIFY"},{"path":"authentication_backend.ldap.tls.server_name","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_TLS_SERVER_NAME"},{"path":"authentication_backend.ldap.tls.private_key","secret":true,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_TLS_PRIVATE_KEY_FILE"},{"path":"authentication_backend.ldap.tls.certificate_chain","secret":true,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_TLS_CERTIFICATE_CHAIN_FILE"},{"path":"authentication_backend.ldap.base_dn","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_BASE_DN"},{"path":"authentication_backend.ldap.additional_users_dn","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ADDITIONAL_USERS_DN"},{"path":"authentication_backend.ldap.users_filter","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_USERS_FILTER"},{"path":"authentication_backend.ldap.additional_groups_dn","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ADDITIONAL_GROUPS_DN"},{"path":"authentication_backend.ldap.groups_filter","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_GROUPS_FILTER"},{"path":"authentication_backend.ldap.group_name_attribute","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_GROUP_NAME_ATTRIBUTE"},{"path":"authentication_backend.ldap.username_attribute","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_USERNAME_ATTRIBUTE"},{"path":"authentication_backend.ldap.mail_attribute","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_MAIL_ATTRIBUTE"},{"path":"authentication_backend.ldap.display_name_attribute","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_DISPLAY_NAME_ATTRIBUTE"},{"path":"authentication_backend.ldap.permit_referrals","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PERMIT_REFERRALS"},{"path":"authentication_backend.ldap.permit_unauthenticated_bind","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PERMIT_UNAUTHENTICATED_BIND"},{"path":"authentication_backend.ldap.permit_feature_detection_failure","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PERMIT_FEATURE_DETECTION_FAILURE"},{"path":"authentication_backend.ldap.user","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_USER"},{"path":"authentication_backend.ldap.password","secret":true,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PASSWORD_FILE"},{"path":"session.secret","secret":true,"env":"AUTHELIA_SESSION_SECRET_FILE"},{"path":"session.name","secret":false,"env":"AUTHELIA_SESSION_NAME"},{"path":"session.domain","secret":false,"env":"AUTHELIA_SESSION_DOMAIN"},{"path":"session.same_site","secret":false,"env":"AUTHELIA_SESSION_SAME_SITE"},{"path":"session.expiration","secret":false,"env":"AUTHELIA_SESSION_EXPIRATION"},{"path":"session.inactivity","secret":false,"env":"AUTHELIA_SESSION_INACTIVITY"},{"path":"session.remember_me","secret":false,"env":"AUTHELIA_SESSION_REMEMBER_ME"},{"path":"session","secret":false,"env":"AUTHELIA_SESSION"},{"path":"session.redis.host","secret":false,"env":"AUTHELIA_SESSION_REDIS_HOST"},{"path":"session.redis.port","secret":false,"env":"AUTHELIA_SESSION_REDIS_PORT"},{"path":"session.redis.username","secret":false,"env":"AUTHELIA_SESSION_REDIS_USERNAME"},{"path":"session.redis.password","secret":true,"env":"AUTHELIA_SESSION_REDIS_PASSWORD_FILE"},{"path":"session.redis.database_index","secret":false,"env":"AUTHELIA_SESSION_REDIS_DATABASE_INDEX"},{"path":"session.redis.maximum_active_connections","secret":false,"env":"AUTHELIA_SESSION_REDIS_MAXIMUM_ACTIVE_CONNECTIONS"},{"path":"session.redis.minimum_idle_connections","secret":false,"env":"AUTHELIA_SESSION_REDIS_MINIMUM_IDLE_CONNECTIONS"},{"path":"session.redis.tls.minimum_version","secret":false,"env":"AUTHELIA_SESSION_REDIS_TLS_MINIMUM_VERSION"},{"path":"session.redis.tls.maximum_version","secret":false,"env":"AUTHELIA_SESSION_REDIS_TLS_MAXIMUM_VERSION"},{"path":"session.redis.tls.skip_verify","secret":false,"env":"AUTHELIA_SESSION_REDIS_TLS_SKIP_VERIFY"},{"path":"session.redis.tls.server_name","secret":false,"env":"AUTHELIA_SESSION_REDIS_TLS_SERVER_NAME"},{"path":"session.redis.tls.private_key","secret":true,"env":"AUTHELIA_SESSION_REDIS_TLS_PRIVATE_KEY_FILE"},{"path":"session.redis.tls.certificate_chain","secret":true,"env":"AUTHELIA_SESSION_REDIS_TLS_CERTIFICATE_CHAIN_FILE"},{"path":"session.redis.high_availability.sentinel_name","secret":false,"env":"AUTHELIA_SESSION_REDIS_HIGH_AVAILABILITY_SENTINEL_NAME"},{"path":"session.redis.high_availability.sentinel_username","secret":false,"env":"AUTHELIA_SESSION_REDIS_HIGH_AVAILABILITY_SENTINEL_USERNAME"},{"path":"session.redis.high_availability.sentinel_password","secret":true,"env":"AUTHELIA_SESSION_REDIS_HIGH_AVAILABILITY_SENTINEL_PASSWORD_FILE"},{"path":"session.redis.high_availability.route_by_latency","secret":false,"env":"AUTHELIA_SESSION_REDIS_HIGH_AVAILABILITY_ROUTE_BY_LATENCY"},{"path":"session.redis.high_availability.route_randomly","secret":false,"env":"AUTHELIA_SESSION_REDIS_HIGH_AVAILABILITY_ROUTE_RANDOMLY"},{"path":"totp.disable","secret":false,"env":"AUTHELIA_TOTP_DISABLE"},{"path":"totp.issuer","secret":false,"env":"AUTHELIA_TOTP_ISSUER"},{"path":"totp.algorithm","secret":false,"env":"AUTHELIA_TOTP_ALGORITHM"},{"path":"totp.digits","secret":false,"env":"AUTHELIA_TOTP_DIGITS"},{"path":"totp.period","secret":false,"env":"AUTHELIA_TOTP_PERIOD"},{"path":"totp.skew","secret":false,"env":"AUTHELIA_TOTP_SKEW"},{"path":"totp.secret_size","secret":false,"env":"AUTHELIA_TOTP_SECRET_SIZE"},{"path":"duo_api.disable","secret":false,"env":"AUTHELIA_DUO_API_DISABLE"},{"path":"duo_api.hostname","secret":false,"env":"AUTHELIA_DUO_API_HOSTNAME"},{"path":"duo_api.integration_key","secret":true,"env":"AUTHELIA_DUO_API_INTEGRATION_KEY_FILE"},{"path":"duo_api.secret_key","secret":true,"env":"AUTHELIA_DUO_API_SECRET_KEY_FILE"},{"path":"duo_api.enable_self_enrollment","secret":false,"env":"AUTHELIA_DUO_API_ENABLE_SELF_ENROLLMENT"},{"path":"access_control.default_policy","secret":false,"env":"AUTHELIA_ACCESS_CONTROL_DEFAULT_POLICY"},{"path":"ntp.address","secret":false,"env":"AUTHELIA_NTP_ADDRESS"},{"path":"ntp.version","secret":false,"env":"AUTHELIA_NTP_VERSION"},{"path":"ntp.max_desync","secret":false,"env":"AUTHELIA_NTP_MAX_DESYNC"},{"path":"ntp.disable_startup_check","secret":false,"env":"AUTHELIA_NTP_DISABLE_STARTUP_CHECK"},{"path":"ntp.disable_failure","secret":false,"env":"AUTHELIA_NTP_DISABLE_FAILURE"},{"path":"regulation.max_retries","secret":false,"env":"AUTHELIA_REGULATION_MAX_RETRIES"},{"path":"regulation.find_time","secret":false,"env":"AUTHELIA_REGULATION_FIND_TIME"},{"path":"regulation.ban_time","secret":false,"env":"AUTHELIA_REGULATION_BAN_TIME"},{"path":"storage.local.path","secret":false,"env":"AUTHELIA_STORAGE_LOCAL_PATH"},{"path":"storage.mysql.address","secret":false,"env":"AUTHELIA_STORAGE_MYSQL_ADDRESS"},{"path":"storage.mysql.database","secret":false,"env":"AUTHELIA_STORAGE_MYSQL_DATABASE"},{"path":"storage.mysql.username","secret":false,"env":"AUTHELIA_STORAGE_MYSQL_USERNAME"},{"path":"storage.mysql.password","secret":true,"env":"AUTHELIA_STORAGE_MYSQL_PASSWORD_FILE"},{"path":"storage.mysql.timeout","secret":false,"env":"AUTHELIA_STORAGE_MYSQL_TIMEOUT"},{"path":"storage.mysql.host","secret":false,"env":"AUTHELIA_STORAGE_MYSQL_HOST"},{"path":"storage.mysql.port","secret":false,"env":"AUTHELIA_STORAGE_MYSQL_PORT"},{"path":"storage.mysql.tls.minimum_version","secret":false,"env":"AUTHELIA_STORAGE_MYSQL_TLS_MINIMUM_VERSION"},{"path":"storage.mysql.tls.maximum_version","secret":false,"env":"AUTHELIA_STORAGE_MYSQL_TLS_MAXIMUM_VERSION"},{"path":"storage.mysql.tls.skip_verify","secret":false,"env":"AUTHELIA_STORAGE_MYSQL_TLS_SKIP_VERIFY"},{"path":"storage.mysql.tls.server_name","secret":false,"env":"AUTHELIA_STORAGE_MYSQL_TLS_SERVER_NAME"},{"path":"storage.mysql.tls.private_key","secret":true,"env":"AUTHELIA_STORAGE_MYSQL_TLS_PRIVATE_KEY_FILE"},{"path":"storage.mysql.tls.certificate_chain","secret":true,"env":"AUTHELIA_STORAGE_MYSQL_TLS_CERTIFICATE_CHAIN_FILE"},{"path":"storage.postgres.address","secret":false,"env":"AUTHELIA_STORAGE_POSTGRES_ADDRESS"},{"path":"storage.postgres.database","secret":false,"env":"AUTHELIA_STORAGE_POSTGRES_DATABASE"},{"path":"storage.postgres.username","secret":false,"env":"AUTHELIA_STORAGE_POSTGRES_USERNAME"},{"path":"storage.postgres.password","secret":true,"env":"AUTHELIA_STORAGE_POSTGRES_PASSWORD_FILE"},{"path":"storage.postgres.timeout","secret":false,"env":"AUTHELIA_STORAGE_POSTGRES_TIMEOUT"},{"path":"storage.postgres.host","secret":false,"env":"AUTHELIA_STORAGE_POSTGRES_HOST"},{"path":"storage.postgres.port","secret":false,"env":"AUTHELIA_STORAGE_POSTGRES_PORT"},{"path":"storage.postgres.schema","secret":false,"env":"AUTHELIA_STORAGE_POSTGRES_SCHEMA"},{"path":"storage.postgres.tls.minimum_version","secret":false,"env":"AUTHELIA_STORAGE_POSTGRES_TLS_MINIMUM_VERSION"},{"path":"storage.postgres.tls.maximum_version","secret":false,"env":"AUTHELIA_STORAGE_POSTGRES_TLS_MAXIMUM_VERSION"},{"path":"storage.postgres.tls.skip_verify","secret":false,"env":"AUTHELIA_STORAGE_POSTGRES_TLS_SKIP_VERIFY"},{"path":"storage.postgres.tls.server_name","secret":false,"env":"AUTHELIA_STORAGE_POSTGRES_TLS_SERVER_NAME"},{"path":"storage.postgres.tls.private_key","secret":true,"env":"AUTHELIA_STORAGE_POSTGRES_TLS_PRIVATE_KEY_FILE"},{"path":"storage.postgres.tls.certificate_chain","secret":true,"env":"AUTHELIA_STORAGE_POSTGRES_TLS_CERTIFICATE_CHAIN_FILE"},{"path":"storage.postgres.ssl.mode","secret":false,"env":"AUTHELIA_STORAGE_POSTGRES_SSL_MODE"},{"path":"storage.postgres.ssl.root_certificate","secret":false,"env":"AUTHELIA_STORAGE_POSTGRES_SSL_ROOT_CERTIFICATE"},{"path":"storage.postgres.ssl.certificate","secret":false,"env":"AUTHELIA_STORAGE_POSTGRES_SSL_CERTIFICATE"},{"path":"storage.postgres.ssl.key","secret":true,"env":"AUTHELIA_STORAGE_POSTGRES_SSL_KEY_FILE"},{"path":"storage.encryption_key","secret":true,"env":"AUTHELIA_STORAGE_ENCRYPTION_KEY_FILE"},{"path":"notifier.disable_startup_check","secret":false,"env":"AUTHELIA_NOTIFIER_DISABLE_STARTUP_CHECK"},{"path":"notifier.filesystem.filename","secret":false,"env":"AUTHELIA_NOTIFIER_FILESYSTEM_FILENAME"},{"path":"notifier.smtp.address","secret":false,"env":"AUTHELIA_NOTIFIER_SMTP_ADDRESS"},{"path":"notifier.smtp.timeout","secret":false,"env":"AUTHELIA_NOTIFIER_SMTP_TIMEOUT"},{"path":"notifier.smtp.username","secret":false,"env":"AUTHELIA_NOTIFIER_SMTP_USERNAME"},{"path":"notifier.smtp.password","secret":true,"env":"AUTHELIA_NOTIFIER_SMTP_PASSWORD_FILE"},{"path":"notifier.smtp.identifier","secret":false,"env":"AUTHELIA_NOTIFIER_SMTP_IDENTIFIER"},{"path":"notifier.smtp.sender","secret":false,"env":"AUTHELIA_NOTIFIER_SMTP_SENDER"},{"path":"notifier.smtp.subject","secret":false,"env":"AUTHELIA_NOTIFIER_SMTP_SUBJECT"},{"path":"notifier.smtp.startup_check_address","secret":false,"env":"AUTHELIA_NOTIFIER_SMTP_STARTUP_CHECK_ADDRESS"},{"path":"notifier.smtp.disable_require_tls","secret":false,"env":"AUTHELIA_NOTIFIER_SMTP_DISABLE_REQUIRE_TLS"},{"path":"notifier.smtp.disable_html_emails","secret":false,"env":"AUTHELIA_NOTIFIER_SMTP_DISABLE_HTML_EMAILS"},{"path":"notifier.smtp.disable_starttls","secret":false,"env":"AUTHELIA_NOTIFIER_SMTP_DISABLE_STARTTLS"},{"path":"notifier.smtp.tls.minimum_version","secret":false,"env":"AUTHELIA_NOTIFIER_SMTP_TLS_MINIMUM_VERSION"},{"path":"notifier.smtp.tls.maximum_version","secret":false,"env":"AUTHELIA_NOTIFIER_SMTP_TLS_MAXIMUM_VERSION"},{"path":"notifier.smtp.tls.skip_verify","secret":false,"env":"AUTHELIA_NOTIFIER_SMTP_TLS_SKIP_VERIFY"},{"path":"notifier.smtp.tls.server_name","secret":false,"env":"AUTHELIA_NOTIFIER_SMTP_TLS_SERVER_NAME"},{"path":"notifier.smtp.tls.private_key","secret":true,"env":"AUTHELIA_NOTIFIER_SMTP_TLS_PRIVATE_KEY_FILE"},{"path":"notifier.smtp.tls.certificate_chain","secret":true,"env":"AUTHELIA_NOTIFIER_SMTP_TLS_CERTIFICATE_CHAIN_FILE"},{"path":"notifier.smtp.host","secret":false,"env":"AUTHELIA_NOTIFIER_SMTP_HOST"},{"path":"notifier.smtp.port","secret":false,"env":"AUTHELIA_NOTIFIER_SMTP_PORT"},{"path":"notifier.template_path","secret":false,"env":"AUTHELIA_NOTIFIER_TEMPLATE_PATH"},{"path":"server.address","secret":false,"env":"AUTHELIA_SERVER_ADDRESS"},{"path":"server.umask","secret":false,"env":"AUTHELIA_SERVER_UMASK"},{"path":"server.path","secret":false,"env":"AUTHELIA_SERVER_PATH"},{"path":"server.asset_path","secret":false,"env":"AUTHELIA_SERVER_ASSET_PATH"},{"path":"server.disable_healthcheck","secret":false,"env":"AUTHELIA_SERVER_DISABLE_HEALTHCHECK"},{"path":"server.tls.certificate","secret":false,"env":"AUTHELIA_SERVER_TLS_CERTIFICATE"},{"path":"server.tls.key","secret":true,"env":"AUTHELIA_SERVER_TLS_KEY_FILE"},{"path":"server.headers.csp_template","secret":false,"env":"AUTHELIA_SERVER_HEADERS_CSP_TEMPLATE"},{"path":"server.endpoints.enable_pprof","secret":false,"env":"AUTHELIA_SERVER_ENDPOINTS_ENABLE_PPROF"},{"path":"server.endpoints.enable_expvars","secret":false,"env":"AUTHELIA_SERVER_ENDPOINTS_ENABLE_EXPVARS"},{"path":"server.buffers.read","secret":false,"env":"AUTHELIA_SERVER_BUFFERS_READ"},{"path":"server.buffers.write","secret":false,"env":"AUTHELIA_SERVER_BUFFERS_WRITE"},{"path":"server.timeouts.read","secret":false,"env":"AUTHELIA_SERVER_TIMEOUTS_READ"},{"path":"server.timeouts.write","secret":false,"env":"AUTHELIA_SERVER_TIMEOUTS_WRITE"},{"path":"server.timeouts.idle","secret":false,"env":"AUTHELIA_SERVER_TIMEOUTS_IDLE"},{"path":"server.host","secret":false,"env":"AUTHELIA_SERVER_HOST"},{"path":"server.port","secret":false,"env":"AUTHELIA_SERVER_PORT"},{"path":"telemetry.metrics.enabled","secret":false,"env":"AUTHELIA_TELEMETRY_METRICS_ENABLED"},{"path":"telemetry.metrics.address","secret":false,"env":"AUTHELIA_TELEMETRY_METRICS_ADDRESS"},{"path":"telemetry.metrics.umask","secret":false,"env":"AUTHELIA_TELEMETRY_METRICS_UMASK"},{"path":"telemetry.metrics.buffers.read","secret":false,"env":"AUTHELIA_TELEMETRY_METRICS_BUFFERS_READ"},{"path":"telemetry.metrics.buffers.write","secret":false,"env":"AUTHELIA_TELEMETRY_METRICS_BUFFERS_WRITE"},{"path":"telemetry.metrics.timeouts.read","secret":false,"env":"AUTHELIA_TELEMETRY_METRICS_TIMEOUTS_READ"},{"path":"telemetry.metrics.timeouts.write","secret":false,"env":"AUTHELIA_TELEMETRY_METRICS_TIMEOUTS_WRITE"},{"path":"telemetry.metrics.timeouts.idle","secret":false,"env":"AUTHELIA_TELEMETRY_METRICS_TIMEOUTS_IDLE"},{"path":"webauthn.disable","secret":false,"env":"AUTHELIA_WEBAUTHN_DISABLE"},{"path":"webauthn.display_name","secret":false,"env":"AUTHELIA_WEBAUTHN_DISPLAY_NAME"},{"path":"webauthn.attestation_conveyance_preference","secret":false,"env":"AUTHELIA_WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE"},{"path":"webauthn.user_verification","secret":false,"env":"AUTHELIA_WEBAUTHN_USER_VERIFICATION"},{"path":"webauthn.timeout","secret":false,"env":"AUTHELIA_WEBAUTHN_TIMEOUT"},{"path":"password_policy.standard.enabled","secret":false,"env":"AUTHELIA_PASSWORD_POLICY_STANDARD_ENABLED"},{"path":"password_policy.standard.min_length","secret":false,"env":"AUTHELIA_PASSWORD_POLICY_STANDARD_MIN_LENGTH"},{"path":"password_policy.standard.max_length","secret":false,"env":"AUTHELIA_PASSWORD_POLICY_STANDARD_MAX_LENGTH"},{"path":"password_policy.standard.require_uppercase","secret":false,"env":"AUTHELIA_PASSWORD_POLICY_STANDARD_REQUIRE_UPPERCASE"},{"path":"password_policy.standard.require_lowercase","secret":false,"env":"AUTHELIA_PASSWORD_POLICY_STANDARD_REQUIRE_LOWERCASE"},{"path":"password_policy.standard.require_number","secret":false,"env":"AUTHELIA_PASSWORD_POLICY_STANDARD_REQUIRE_NUMBER"},{"path":"password_policy.standard.require_special","secret":false,"env":"AUTHELIA_PASSWORD_POLICY_STANDARD_REQUIRE_SPECIAL"},{"path":"password_policy.zxcvbn.enabled","secret":false,"env":"AUTHELIA_PASSWORD_POLICY_ZXCVBN_ENABLED"},{"path":"password_policy.zxcvbn.min_score","secret":false,"env":"AUTHELIA_PASSWORD_POLICY_ZXCVBN_MIN_SCORE"},{"path":"privacy_policy.enabled","secret":false,"env":"AUTHELIA_PRIVACY_POLICY_ENABLED"},{"path":"privacy_policy.require_user_acceptance","secret":false,"env":"AUTHELIA_PRIVACY_POLICY_REQUIRE_USER_ACCEPTANCE"},{"path":"privacy_policy.policy_url","secret":false,"env":"AUTHELIA_PRIVACY_POLICY_POLICY_URL"}] \ No newline at end of file +[{"path":"theme","secret":false,"env":"AUTHELIA_THEME"},{"path":"certificates_directory","secret":false,"env":"AUTHELIA_CERTIFICATES_DIRECTORY"},{"path":"jwt_secret","secret":true,"env":"AUTHELIA_JWT_SECRET_FILE"},{"path":"default_redirection_url","secret":false,"env":"AUTHELIA_DEFAULT_REDIRECTION_URL"},{"path":"default_2fa_method","secret":false,"env":"AUTHELIA_DEFAULT_2FA_METHOD"},{"path":"log.level","secret":false,"env":"AUTHELIA_LOG_LEVEL"},{"path":"log.format","secret":false,"env":"AUTHELIA_LOG_FORMAT"},{"path":"log.file_path","secret":false,"env":"AUTHELIA_LOG_FILE_PATH"},{"path":"log.keep_stdout","secret":false,"env":"AUTHELIA_LOG_KEEP_STDOUT"},{"path":"identity_providers.oidc.hmac_secret","secret":true,"env":"AUTHELIA_IDENTITY_PROVIDERS_OIDC_HMAC_SECRET_FILE"},{"path":"identity_providers.oidc.issuer_certificate_chain","secret":true,"env":"AUTHELIA_IDENTITY_PROVIDERS_OIDC_ISSUER_CERTIFICATE_CHAIN_FILE"},{"path":"identity_providers.oidc.issuer_private_key","secret":true,"env":"AUTHELIA_IDENTITY_PROVIDERS_OIDC_ISSUER_PRIVATE_KEY_FILE"},{"path":"identity_providers.oidc.access_token_lifespan","secret":false,"env":"AUTHELIA_IDENTITY_PROVIDERS_OIDC_ACCESS_TOKEN_LIFESPAN"},{"path":"identity_providers.oidc.authorize_code_lifespan","secret":false,"env":"AUTHELIA_IDENTITY_PROVIDERS_OIDC_AUTHORIZE_CODE_LIFESPAN"},{"path":"identity_providers.oidc.id_token_lifespan","secret":false,"env":"AUTHELIA_IDENTITY_PROVIDERS_OIDC_ID_TOKEN_LIFESPAN"},{"path":"identity_providers.oidc.refresh_token_lifespan","secret":false,"env":"AUTHELIA_IDENTITY_PROVIDERS_OIDC_REFRESH_TOKEN_LIFESPAN"},{"path":"identity_providers.oidc.enable_client_debug_messages","secret":false,"env":"AUTHELIA_IDENTITY_PROVIDERS_OIDC_ENABLE_CLIENT_DEBUG_MESSAGES"},{"path":"identity_providers.oidc.minimum_parameter_entropy","secret":false,"env":"AUTHELIA_IDENTITY_PROVIDERS_OIDC_MINIMUM_PARAMETER_ENTROPY"},{"path":"identity_providers.oidc.enforce_pkce","secret":false,"env":"AUTHELIA_IDENTITY_PROVIDERS_OIDC_ENFORCE_PKCE"},{"path":"identity_providers.oidc.enable_pkce_plain_challenge","secret":false,"env":"AUTHELIA_IDENTITY_PROVIDERS_OIDC_ENABLE_PKCE_PLAIN_CHALLENGE"},{"path":"identity_providers.oidc.cors.allowed_origins_from_client_redirect_uris","secret":false,"env":"AUTHELIA_IDENTITY_PROVIDERS_OIDC_CORS_ALLOWED_ORIGINS_FROM_CLIENT_REDIRECT_URIS"},{"path":"identity_providers.oidc.pushed_authorizations.enforce","secret":false,"env":"AUTHELIA_IDENTITY_PROVIDERS_OIDC_PUSHED_AUTHORIZATIONS_ENFORCE"},{"path":"identity_providers.oidc.pushed_authorizations.context_lifespan","secret":false,"env":"AUTHELIA_IDENTITY_PROVIDERS_OIDC_PUSHED_AUTHORIZATIONS_CONTEXT_LIFESPAN"},{"path":"authentication_backend.password_reset.disable","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_PASSWORD_RESET_DISABLE"},{"path":"authentication_backend.password_reset.custom_url","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_PASSWORD_RESET_CUSTOM_URL"},{"path":"authentication_backend.refresh_interval","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_REFRESH_INTERVAL"},{"path":"authentication_backend.file.path","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PATH"},{"path":"authentication_backend.file.watch","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_WATCH"},{"path":"authentication_backend.file.password.algorithm","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_ALGORITHM"},{"path":"authentication_backend.file.password.argon2.variant","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_ARGON2_VARIANT"},{"path":"authentication_backend.file.password.argon2.iterations","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_ARGON2_ITERATIONS"},{"path":"authentication_backend.file.password.argon2.memory","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_ARGON2_MEMORY"},{"path":"authentication_backend.file.password.argon2.parallelism","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_ARGON2_PARALLELISM"},{"path":"authentication_backend.file.password.argon2.key_length","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_ARGON2_KEY_LENGTH"},{"path":"authentication_backend.file.password.argon2.salt_length","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_ARGON2_SALT_LENGTH"},{"path":"authentication_backend.file.password.sha2crypt.variant","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_SHA2CRYPT_VARIANT"},{"path":"authentication_backend.file.password.sha2crypt.iterations","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_SHA2CRYPT_ITERATIONS"},{"path":"authentication_backend.file.password.sha2crypt.salt_length","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_SHA2CRYPT_SALT_LENGTH"},{"path":"authentication_backend.file.password.pbkdf2.variant","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_PBKDF2_VARIANT"},{"path":"authentication_backend.file.password.pbkdf2.iterations","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_PBKDF2_ITERATIONS"},{"path":"authentication_backend.file.password.pbkdf2.salt_length","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_PBKDF2_SALT_LENGTH"},{"path":"authentication_backend.file.password.bcrypt.variant","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_BCRYPT_VARIANT"},{"path":"authentication_backend.file.password.bcrypt.cost","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_BCRYPT_COST"},{"path":"authentication_backend.file.password.scrypt.iterations","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_SCRYPT_ITERATIONS"},{"path":"authentication_backend.file.password.scrypt.block_size","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_SCRYPT_BLOCK_SIZE"},{"path":"authentication_backend.file.password.scrypt.parallelism","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_SCRYPT_PARALLELISM"},{"path":"authentication_backend.file.password.scrypt.key_length","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_SCRYPT_KEY_LENGTH"},{"path":"authentication_backend.file.password.scrypt.salt_length","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_SCRYPT_SALT_LENGTH"},{"path":"authentication_backend.file.password.iterations","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_ITERATIONS"},{"path":"authentication_backend.file.password.memory","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_MEMORY"},{"path":"authentication_backend.file.password.parallelism","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_PARALLELISM"},{"path":"authentication_backend.file.password.key_length","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_KEY_LENGTH"},{"path":"authentication_backend.file.password.salt_length","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_SALT_LENGTH"},{"path":"authentication_backend.file.search.email","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_SEARCH_EMAIL"},{"path":"authentication_backend.file.search.case_insensitive","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_SEARCH_CASE_INSENSITIVE"},{"path":"authentication_backend.ldap.address","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ADDRESS"},{"path":"authentication_backend.ldap.implementation","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_IMPLEMENTATION"},{"path":"authentication_backend.ldap.timeout","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_TIMEOUT"},{"path":"authentication_backend.ldap.start_tls","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_START_TLS"},{"path":"authentication_backend.ldap.tls.minimum_version","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_TLS_MINIMUM_VERSION"},{"path":"authentication_backend.ldap.tls.maximum_version","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_TLS_MAXIMUM_VERSION"},{"path":"authentication_backend.ldap.tls.skip_verify","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_TLS_SKIP_VERIFY"},{"path":"authentication_backend.ldap.tls.server_name","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_TLS_SERVER_NAME"},{"path":"authentication_backend.ldap.tls.private_key","secret":true,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_TLS_PRIVATE_KEY_FILE"},{"path":"authentication_backend.ldap.tls.certificate_chain","secret":true,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_TLS_CERTIFICATE_CHAIN_FILE"},{"path":"authentication_backend.ldap.base_dn","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_BASE_DN"},{"path":"authentication_backend.ldap.additional_users_dn","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ADDITIONAL_USERS_DN"},{"path":"authentication_backend.ldap.users_filter","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_USERS_FILTER"},{"path":"authentication_backend.ldap.additional_groups_dn","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_ADDITIONAL_GROUPS_DN"},{"path":"authentication_backend.ldap.groups_filter","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_GROUPS_FILTER"},{"path":"authentication_backend.ldap.group_name_attribute","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_GROUP_NAME_ATTRIBUTE"},{"path":"authentication_backend.ldap.username_attribute","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_USERNAME_ATTRIBUTE"},{"path":"authentication_backend.ldap.mail_attribute","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_MAIL_ATTRIBUTE"},{"path":"authentication_backend.ldap.display_name_attribute","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_DISPLAY_NAME_ATTRIBUTE"},{"path":"authentication_backend.ldap.permit_referrals","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PERMIT_REFERRALS"},{"path":"authentication_backend.ldap.permit_unauthenticated_bind","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PERMIT_UNAUTHENTICATED_BIND"},{"path":"authentication_backend.ldap.permit_feature_detection_failure","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PERMIT_FEATURE_DETECTION_FAILURE"},{"path":"authentication_backend.ldap.user","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_USER"},{"path":"authentication_backend.ldap.password","secret":true,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PASSWORD_FILE"},{"path":"session.secret","secret":true,"env":"AUTHELIA_SESSION_SECRET_FILE"},{"path":"session.name","secret":false,"env":"AUTHELIA_SESSION_NAME"},{"path":"session.domain","secret":false,"env":"AUTHELIA_SESSION_DOMAIN"},{"path":"session.same_site","secret":false,"env":"AUTHELIA_SESSION_SAME_SITE"},{"path":"session.expiration","secret":false,"env":"AUTHELIA_SESSION_EXPIRATION"},{"path":"session.inactivity","secret":false,"env":"AUTHELIA_SESSION_INACTIVITY"},{"path":"session.remember_me","secret":false,"env":"AUTHELIA_SESSION_REMEMBER_ME"},{"path":"session","secret":false,"env":"AUTHELIA_SESSION"},{"path":"session.redis.host","secret":false,"env":"AUTHELIA_SESSION_REDIS_HOST"},{"path":"session.redis.port","secret":false,"env":"AUTHELIA_SESSION_REDIS_PORT"},{"path":"session.redis.username","secret":false,"env":"AUTHELIA_SESSION_REDIS_USERNAME"},{"path":"session.redis.password","secret":true,"env":"AUTHELIA_SESSION_REDIS_PASSWORD_FILE"},{"path":"session.redis.database_index","secret":false,"env":"AUTHELIA_SESSION_REDIS_DATABASE_INDEX"},{"path":"session.redis.maximum_active_connections","secret":false,"env":"AUTHELIA_SESSION_REDIS_MAXIMUM_ACTIVE_CONNECTIONS"},{"path":"session.redis.minimum_idle_connections","secret":false,"env":"AUTHELIA_SESSION_REDIS_MINIMUM_IDLE_CONNECTIONS"},{"path":"session.redis.tls.minimum_version","secret":false,"env":"AUTHELIA_SESSION_REDIS_TLS_MINIMUM_VERSION"},{"path":"session.redis.tls.maximum_version","secret":false,"env":"AUTHELIA_SESSION_REDIS_TLS_MAXIMUM_VERSION"},{"path":"session.redis.tls.skip_verify","secret":false,"env":"AUTHELIA_SESSION_REDIS_TLS_SKIP_VERIFY"},{"path":"session.redis.tls.server_name","secret":false,"env":"AUTHELIA_SESSION_REDIS_TLS_SERVER_NAME"},{"path":"session.redis.tls.private_key","secret":true,"env":"AUTHELIA_SESSION_REDIS_TLS_PRIVATE_KEY_FILE"},{"path":"session.redis.tls.certificate_chain","secret":true,"env":"AUTHELIA_SESSION_REDIS_TLS_CERTIFICATE_CHAIN_FILE"},{"path":"session.redis.high_availability.sentinel_name","secret":false,"env":"AUTHELIA_SESSION_REDIS_HIGH_AVAILABILITY_SENTINEL_NAME"},{"path":"session.redis.high_availability.sentinel_username","secret":false,"env":"AUTHELIA_SESSION_REDIS_HIGH_AVAILABILITY_SENTINEL_USERNAME"},{"path":"session.redis.high_availability.sentinel_password","secret":true,"env":"AUTHELIA_SESSION_REDIS_HIGH_AVAILABILITY_SENTINEL_PASSWORD_FILE"},{"path":"session.redis.high_availability.route_by_latency","secret":false,"env":"AUTHELIA_SESSION_REDIS_HIGH_AVAILABILITY_ROUTE_BY_LATENCY"},{"path":"session.redis.high_availability.route_randomly","secret":false,"env":"AUTHELIA_SESSION_REDIS_HIGH_AVAILABILITY_ROUTE_RANDOMLY"},{"path":"totp.disable","secret":false,"env":"AUTHELIA_TOTP_DISABLE"},{"path":"totp.issuer","secret":false,"env":"AUTHELIA_TOTP_ISSUER"},{"path":"totp.algorithm","secret":false,"env":"AUTHELIA_TOTP_ALGORITHM"},{"path":"totp.digits","secret":false,"env":"AUTHELIA_TOTP_DIGITS"},{"path":"totp.period","secret":false,"env":"AUTHELIA_TOTP_PERIOD"},{"path":"totp.skew","secret":false,"env":"AUTHELIA_TOTP_SKEW"},{"path":"totp.secret_size","secret":false,"env":"AUTHELIA_TOTP_SECRET_SIZE"},{"path":"duo_api.disable","secret":false,"env":"AUTHELIA_DUO_API_DISABLE"},{"path":"duo_api.hostname","secret":false,"env":"AUTHELIA_DUO_API_HOSTNAME"},{"path":"duo_api.integration_key","secret":true,"env":"AUTHELIA_DUO_API_INTEGRATION_KEY_FILE"},{"path":"duo_api.secret_key","secret":true,"env":"AUTHELIA_DUO_API_SECRET_KEY_FILE"},{"path":"duo_api.enable_self_enrollment","secret":false,"env":"AUTHELIA_DUO_API_ENABLE_SELF_ENROLLMENT"},{"path":"access_control.default_policy","secret":false,"env":"AUTHELIA_ACCESS_CONTROL_DEFAULT_POLICY"},{"path":"ntp.address","secret":false,"env":"AUTHELIA_NTP_ADDRESS"},{"path":"ntp.version","secret":false,"env":"AUTHELIA_NTP_VERSION"},{"path":"ntp.max_desync","secret":false,"env":"AUTHELIA_NTP_MAX_DESYNC"},{"path":"ntp.disable_startup_check","secret":false,"env":"AUTHELIA_NTP_DISABLE_STARTUP_CHECK"},{"path":"ntp.disable_failure","secret":false,"env":"AUTHELIA_NTP_DISABLE_FAILURE"},{"path":"regulation.max_retries","secret":false,"env":"AUTHELIA_REGULATION_MAX_RETRIES"},{"path":"regulation.find_time","secret":false,"env":"AUTHELIA_REGULATION_FIND_TIME"},{"path":"regulation.ban_time","secret":false,"env":"AUTHELIA_REGULATION_BAN_TIME"},{"path":"storage.local.path","secret":false,"env":"AUTHELIA_STORAGE_LOCAL_PATH"},{"path":"storage.mysql.address","secret":false,"env":"AUTHELIA_STORAGE_MYSQL_ADDRESS"},{"path":"storage.mysql.database","secret":false,"env":"AUTHELIA_STORAGE_MYSQL_DATABASE"},{"path":"storage.mysql.username","secret":false,"env":"AUTHELIA_STORAGE_MYSQL_USERNAME"},{"path":"storage.mysql.password","secret":true,"env":"AUTHELIA_STORAGE_MYSQL_PASSWORD_FILE"},{"path":"storage.mysql.timeout","secret":false,"env":"AUTHELIA_STORAGE_MYSQL_TIMEOUT"},{"path":"storage.mysql.host","secret":false,"env":"AUTHELIA_STORAGE_MYSQL_HOST"},{"path":"storage.mysql.port","secret":false,"env":"AUTHELIA_STORAGE_MYSQL_PORT"},{"path":"storage.mysql.tls.minimum_version","secret":false,"env":"AUTHELIA_STORAGE_MYSQL_TLS_MINIMUM_VERSION"},{"path":"storage.mysql.tls.maximum_version","secret":false,"env":"AUTHELIA_STORAGE_MYSQL_TLS_MAXIMUM_VERSION"},{"path":"storage.mysql.tls.skip_verify","secret":false,"env":"AUTHELIA_STORAGE_MYSQL_TLS_SKIP_VERIFY"},{"path":"storage.mysql.tls.server_name","secret":false,"env":"AUTHELIA_STORAGE_MYSQL_TLS_SERVER_NAME"},{"path":"storage.mysql.tls.private_key","secret":true,"env":"AUTHELIA_STORAGE_MYSQL_TLS_PRIVATE_KEY_FILE"},{"path":"storage.mysql.tls.certificate_chain","secret":true,"env":"AUTHELIA_STORAGE_MYSQL_TLS_CERTIFICATE_CHAIN_FILE"},{"path":"storage.postgres.address","secret":false,"env":"AUTHELIA_STORAGE_POSTGRES_ADDRESS"},{"path":"storage.postgres.database","secret":false,"env":"AUTHELIA_STORAGE_POSTGRES_DATABASE"},{"path":"storage.postgres.username","secret":false,"env":"AUTHELIA_STORAGE_POSTGRES_USERNAME"},{"path":"storage.postgres.password","secret":true,"env":"AUTHELIA_STORAGE_POSTGRES_PASSWORD_FILE"},{"path":"storage.postgres.timeout","secret":false,"env":"AUTHELIA_STORAGE_POSTGRES_TIMEOUT"},{"path":"storage.postgres.host","secret":false,"env":"AUTHELIA_STORAGE_POSTGRES_HOST"},{"path":"storage.postgres.port","secret":false,"env":"AUTHELIA_STORAGE_POSTGRES_PORT"},{"path":"storage.postgres.schema","secret":false,"env":"AUTHELIA_STORAGE_POSTGRES_SCHEMA"},{"path":"storage.postgres.tls.minimum_version","secret":false,"env":"AUTHELIA_STORAGE_POSTGRES_TLS_MINIMUM_VERSION"},{"path":"storage.postgres.tls.maximum_version","secret":false,"env":"AUTHELIA_STORAGE_POSTGRES_TLS_MAXIMUM_VERSION"},{"path":"storage.postgres.tls.skip_verify","secret":false,"env":"AUTHELIA_STORAGE_POSTGRES_TLS_SKIP_VERIFY"},{"path":"storage.postgres.tls.server_name","secret":false,"env":"AUTHELIA_STORAGE_POSTGRES_TLS_SERVER_NAME"},{"path":"storage.postgres.tls.private_key","secret":true,"env":"AUTHELIA_STORAGE_POSTGRES_TLS_PRIVATE_KEY_FILE"},{"path":"storage.postgres.tls.certificate_chain","secret":true,"env":"AUTHELIA_STORAGE_POSTGRES_TLS_CERTIFICATE_CHAIN_FILE"},{"path":"storage.postgres.ssl.mode","secret":false,"env":"AUTHELIA_STORAGE_POSTGRES_SSL_MODE"},{"path":"storage.postgres.ssl.root_certificate","secret":false,"env":"AUTHELIA_STORAGE_POSTGRES_SSL_ROOT_CERTIFICATE"},{"path":"storage.postgres.ssl.certificate","secret":false,"env":"AUTHELIA_STORAGE_POSTGRES_SSL_CERTIFICATE"},{"path":"storage.postgres.ssl.key","secret":true,"env":"AUTHELIA_STORAGE_POSTGRES_SSL_KEY_FILE"},{"path":"storage.encryption_key","secret":true,"env":"AUTHELIA_STORAGE_ENCRYPTION_KEY_FILE"},{"path":"notifier.disable_startup_check","secret":false,"env":"AUTHELIA_NOTIFIER_DISABLE_STARTUP_CHECK"},{"path":"notifier.filesystem.filename","secret":false,"env":"AUTHELIA_NOTIFIER_FILESYSTEM_FILENAME"},{"path":"notifier.smtp.address","secret":false,"env":"AUTHELIA_NOTIFIER_SMTP_ADDRESS"},{"path":"notifier.smtp.timeout","secret":false,"env":"AUTHELIA_NOTIFIER_SMTP_TIMEOUT"},{"path":"notifier.smtp.username","secret":false,"env":"AUTHELIA_NOTIFIER_SMTP_USERNAME"},{"path":"notifier.smtp.password","secret":true,"env":"AUTHELIA_NOTIFIER_SMTP_PASSWORD_FILE"},{"path":"notifier.smtp.identifier","secret":false,"env":"AUTHELIA_NOTIFIER_SMTP_IDENTIFIER"},{"path":"notifier.smtp.sender","secret":false,"env":"AUTHELIA_NOTIFIER_SMTP_SENDER"},{"path":"notifier.smtp.subject","secret":false,"env":"AUTHELIA_NOTIFIER_SMTP_SUBJECT"},{"path":"notifier.smtp.startup_check_address","secret":false,"env":"AUTHELIA_NOTIFIER_SMTP_STARTUP_CHECK_ADDRESS"},{"path":"notifier.smtp.disable_require_tls","secret":false,"env":"AUTHELIA_NOTIFIER_SMTP_DISABLE_REQUIRE_TLS"},{"path":"notifier.smtp.disable_html_emails","secret":false,"env":"AUTHELIA_NOTIFIER_SMTP_DISABLE_HTML_EMAILS"},{"path":"notifier.smtp.disable_starttls","secret":false,"env":"AUTHELIA_NOTIFIER_SMTP_DISABLE_STARTTLS"},{"path":"notifier.smtp.tls.minimum_version","secret":false,"env":"AUTHELIA_NOTIFIER_SMTP_TLS_MINIMUM_VERSION"},{"path":"notifier.smtp.tls.maximum_version","secret":false,"env":"AUTHELIA_NOTIFIER_SMTP_TLS_MAXIMUM_VERSION"},{"path":"notifier.smtp.tls.skip_verify","secret":false,"env":"AUTHELIA_NOTIFIER_SMTP_TLS_SKIP_VERIFY"},{"path":"notifier.smtp.tls.server_name","secret":false,"env":"AUTHELIA_NOTIFIER_SMTP_TLS_SERVER_NAME"},{"path":"notifier.smtp.tls.private_key","secret":true,"env":"AUTHELIA_NOTIFIER_SMTP_TLS_PRIVATE_KEY_FILE"},{"path":"notifier.smtp.tls.certificate_chain","secret":true,"env":"AUTHELIA_NOTIFIER_SMTP_TLS_CERTIFICATE_CHAIN_FILE"},{"path":"notifier.smtp.host","secret":false,"env":"AUTHELIA_NOTIFIER_SMTP_HOST"},{"path":"notifier.smtp.port","secret":false,"env":"AUTHELIA_NOTIFIER_SMTP_PORT"},{"path":"notifier.template_path","secret":false,"env":"AUTHELIA_NOTIFIER_TEMPLATE_PATH"},{"path":"server.address","secret":false,"env":"AUTHELIA_SERVER_ADDRESS"},{"path":"server.path","secret":false,"env":"AUTHELIA_SERVER_PATH"},{"path":"server.asset_path","secret":false,"env":"AUTHELIA_SERVER_ASSET_PATH"},{"path":"server.disable_healthcheck","secret":false,"env":"AUTHELIA_SERVER_DISABLE_HEALTHCHECK"},{"path":"server.tls.certificate","secret":false,"env":"AUTHELIA_SERVER_TLS_CERTIFICATE"},{"path":"server.tls.key","secret":true,"env":"AUTHELIA_SERVER_TLS_KEY_FILE"},{"path":"server.headers.csp_template","secret":false,"env":"AUTHELIA_SERVER_HEADERS_CSP_TEMPLATE"},{"path":"server.endpoints.enable_pprof","secret":false,"env":"AUTHELIA_SERVER_ENDPOINTS_ENABLE_PPROF"},{"path":"server.endpoints.enable_expvars","secret":false,"env":"AUTHELIA_SERVER_ENDPOINTS_ENABLE_EXPVARS"},{"path":"server.buffers.read","secret":false,"env":"AUTHELIA_SERVER_BUFFERS_READ"},{"path":"server.buffers.write","secret":false,"env":"AUTHELIA_SERVER_BUFFERS_WRITE"},{"path":"server.timeouts.read","secret":false,"env":"AUTHELIA_SERVER_TIMEOUTS_READ"},{"path":"server.timeouts.write","secret":false,"env":"AUTHELIA_SERVER_TIMEOUTS_WRITE"},{"path":"server.timeouts.idle","secret":false,"env":"AUTHELIA_SERVER_TIMEOUTS_IDLE"},{"path":"server.host","secret":false,"env":"AUTHELIA_SERVER_HOST"},{"path":"server.port","secret":false,"env":"AUTHELIA_SERVER_PORT"},{"path":"telemetry.metrics.enabled","secret":false,"env":"AUTHELIA_TELEMETRY_METRICS_ENABLED"},{"path":"telemetry.metrics.address","secret":false,"env":"AUTHELIA_TELEMETRY_METRICS_ADDRESS"},{"path":"telemetry.metrics.buffers.read","secret":false,"env":"AUTHELIA_TELEMETRY_METRICS_BUFFERS_READ"},{"path":"telemetry.metrics.buffers.write","secret":false,"env":"AUTHELIA_TELEMETRY_METRICS_BUFFERS_WRITE"},{"path":"telemetry.metrics.timeouts.read","secret":false,"env":"AUTHELIA_TELEMETRY_METRICS_TIMEOUTS_READ"},{"path":"telemetry.metrics.timeouts.write","secret":false,"env":"AUTHELIA_TELEMETRY_METRICS_TIMEOUTS_WRITE"},{"path":"telemetry.metrics.timeouts.idle","secret":false,"env":"AUTHELIA_TELEMETRY_METRICS_TIMEOUTS_IDLE"},{"path":"webauthn.disable","secret":false,"env":"AUTHELIA_WEBAUTHN_DISABLE"},{"path":"webauthn.display_name","secret":false,"env":"AUTHELIA_WEBAUTHN_DISPLAY_NAME"},{"path":"webauthn.attestation_conveyance_preference","secret":false,"env":"AUTHELIA_WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE"},{"path":"webauthn.user_verification","secret":false,"env":"AUTHELIA_WEBAUTHN_USER_VERIFICATION"},{"path":"webauthn.timeout","secret":false,"env":"AUTHELIA_WEBAUTHN_TIMEOUT"},{"path":"password_policy.standard.enabled","secret":false,"env":"AUTHELIA_PASSWORD_POLICY_STANDARD_ENABLED"},{"path":"password_policy.standard.min_length","secret":false,"env":"AUTHELIA_PASSWORD_POLICY_STANDARD_MIN_LENGTH"},{"path":"password_policy.standard.max_length","secret":false,"env":"AUTHELIA_PASSWORD_POLICY_STANDARD_MAX_LENGTH"},{"path":"password_policy.standard.require_uppercase","secret":false,"env":"AUTHELIA_PASSWORD_POLICY_STANDARD_REQUIRE_UPPERCASE"},{"path":"password_policy.standard.require_lowercase","secret":false,"env":"AUTHELIA_PASSWORD_POLICY_STANDARD_REQUIRE_LOWERCASE"},{"path":"password_policy.standard.require_number","secret":false,"env":"AUTHELIA_PASSWORD_POLICY_STANDARD_REQUIRE_NUMBER"},{"path":"password_policy.standard.require_special","secret":false,"env":"AUTHELIA_PASSWORD_POLICY_STANDARD_REQUIRE_SPECIAL"},{"path":"password_policy.zxcvbn.enabled","secret":false,"env":"AUTHELIA_PASSWORD_POLICY_ZXCVBN_ENABLED"},{"path":"password_policy.zxcvbn.min_score","secret":false,"env":"AUTHELIA_PASSWORD_POLICY_ZXCVBN_MIN_SCORE"},{"path":"privacy_policy.enabled","secret":false,"env":"AUTHELIA_PRIVACY_POLICY_ENABLED"},{"path":"privacy_policy.require_user_acceptance","secret":false,"env":"AUTHELIA_PRIVACY_POLICY_REQUIRE_USER_ACCEPTANCE"},{"path":"privacy_policy.policy_url","secret":false,"env":"AUTHELIA_PRIVACY_POLICY_POLICY_URL"}] \ No newline at end of file diff --git a/internal/configuration/schema/const.go b/internal/configuration/schema/const.go index 0e59410c5..9c5621c2d 100644 --- a/internal/configuration/schema/const.go +++ b/internal/configuration/schema/const.go @@ -103,9 +103,17 @@ const ( TOTPSecretSizeMinimum = 20 ) -// regexpHasScheme checks if a string has a scheme. Valid characters for schemes include alphanumeric, hyphen, -// period, and plus characters. -var regexpHasScheme = regexp.MustCompile(`^[-+.a-zA-Z\d]*(://|:$)`) +var ( + // regexpHasScheme checks if a string has a scheme. Valid characters for schemes include alphanumeric, hyphen, + // period, and plus characters. + regexpHasScheme = regexp.MustCompile(`^[-+.a-zA-Z\d]*(://|:$)`) + + regexpIsUmask = regexp.MustCompile(`^[0-7]{3,4}$`) +) + +const ( + addressQueryParamUmask = "umask" +) const ( blockCERTIFICATE = "CERTIFICATE" diff --git a/internal/configuration/schema/keys.go b/internal/configuration/schema/keys.go index ac5dbca3e..6bbddf150 100644 --- a/internal/configuration/schema/keys.go +++ b/internal/configuration/schema/keys.go @@ -239,7 +239,6 @@ var Keys = []string{ "notifier.smtp.port", "notifier.template_path", "server.address", - "server.umask", "server.path", "server.asset_path", "server.disable_healthcheck", @@ -262,7 +261,6 @@ var Keys = []string{ "server.port", "telemetry.metrics.enabled", "telemetry.metrics.address", - "telemetry.metrics.umask", "telemetry.metrics.buffers.read", "telemetry.metrics.buffers.write", "telemetry.metrics.timeouts.read", diff --git a/internal/configuration/schema/notifier.go b/internal/configuration/schema/notifier.go index d554e6d64..9a3d862d0 100644 --- a/internal/configuration/schema/notifier.go +++ b/internal/configuration/schema/notifier.go @@ -44,7 +44,7 @@ type NotifierConfiguration struct { // DefaultSMTPNotifierConfiguration represents default configuration parameters for the SMTP notifier. var DefaultSMTPNotifierConfiguration = SMTPNotifierConfiguration{ - Address: &AddressSMTP{Address{true, false, 25, &url.URL{Scheme: AddressSchemeSMTP, Host: "localhost:25"}}}, + Address: &AddressSMTP{Address{true, false, -1, 25, &url.URL{Scheme: AddressSchemeSMTP, Host: "localhost:25"}}}, Timeout: time.Second * 5, Subject: "[Authelia] {title}", Identifier: "localhost", diff --git a/internal/configuration/schema/server.go b/internal/configuration/schema/server.go index 46264f3c8..65ac03099 100644 --- a/internal/configuration/schema/server.go +++ b/internal/configuration/schema/server.go @@ -7,12 +7,10 @@ import ( // ServerConfiguration represents the configuration of the http server. type ServerConfiguration struct { - Address *AddressTCP `koanf:"address"` - UMask *int `koanf:"umask"` - - Path string `koanf:"path"` - AssetPath string `koanf:"asset_path"` - DisableHealthcheck bool `koanf:"disable_healthcheck"` + Address *AddressTCP `koanf:"address"` + Path string `koanf:"path"` + AssetPath string `koanf:"asset_path"` + DisableHealthcheck bool `koanf:"disable_healthcheck"` TLS ServerTLS `koanf:"tls"` Headers ServerHeaders `koanf:"headers"` @@ -62,7 +60,7 @@ type ServerHeaders struct { // DefaultServerConfiguration represents the default values of the ServerConfiguration. var DefaultServerConfiguration = ServerConfiguration{ - Address: &AddressTCP{Address{true, false, 9091, &url.URL{Scheme: AddressSchemeTCP, Host: ":9091"}}}, + Address: &AddressTCP{Address{true, false, -1, 9091, &url.URL{Scheme: AddressSchemeTCP, Host: ":9091"}}}, Buffers: ServerBuffers{ Read: 4096, Write: 4096, diff --git a/internal/configuration/schema/storage.go b/internal/configuration/schema/storage.go index 3dc2836f0..0d7b318ed 100644 --- a/internal/configuration/schema/storage.go +++ b/internal/configuration/schema/storage.go @@ -75,7 +75,7 @@ var DefaultMySQLStorageConfiguration = MySQLStorageConfiguration{ // DefaultPostgreSQLStorageConfiguration represents the default PostgreSQL configuration. var DefaultPostgreSQLStorageConfiguration = PostgreSQLStorageConfiguration{ SQLStorageConfiguration: SQLStorageConfiguration{ - Address: &AddressTCP{Address{true, false, 5432, &url.URL{Scheme: AddressSchemeTCP, Host: "localhost:5432"}}}, + Address: &AddressTCP{Address{true, false, -1, 5432, &url.URL{Scheme: AddressSchemeTCP, Host: "localhost:5432"}}}, }, Schema: "public", TLS: &TLSConfig{ diff --git a/internal/configuration/schema/telemetry.go b/internal/configuration/schema/telemetry.go index f3231144e..10f804f4d 100644 --- a/internal/configuration/schema/telemetry.go +++ b/internal/configuration/schema/telemetry.go @@ -12,10 +12,8 @@ type TelemetryConfig struct { // TelemetryMetricsConfig represents the telemetry metrics config. type TelemetryMetricsConfig struct { - Enabled bool `koanf:"enabled"` - Address *AddressTCP `koanf:"address"` - UMask *int `koanf:"umask"` - + Enabled bool `koanf:"enabled"` + Address *AddressTCP `koanf:"address"` Buffers ServerBuffers `koanf:"buffers"` Timeouts ServerTimeouts `koanf:"timeouts"` } @@ -23,7 +21,7 @@ type TelemetryMetricsConfig struct { // DefaultTelemetryConfig is the default telemetry configuration. var DefaultTelemetryConfig = TelemetryConfig{ Metrics: TelemetryMetricsConfig{ - Address: &AddressTCP{Address{true, false, 9959, &url.URL{Scheme: AddressSchemeTCP, Host: ":9959"}}}, + Address: &AddressTCP{Address{true, false, -1, 9959, &url.URL{Scheme: AddressSchemeTCP, Host: ":9959"}}}, Buffers: ServerBuffers{ Read: 4096, Write: 4096, diff --git a/internal/configuration/schema/types_address.go b/internal/configuration/schema/types_address.go index c33dcf6c0..a68bad701 100644 --- a/internal/configuration/schema/types_address.go +++ b/internal/configuration/schema/types_address.go @@ -21,7 +21,7 @@ func NewAddress(value string) (address *Address, err error) { // else without a scheme is the schemeDefault scheme. func NewAddressDefault(value, schemeDefault, schemeDefaultPath string) (address *Address, err error) { if len(value) == 0 { - return &Address{true, false, 0, &url.URL{Scheme: AddressSchemeTCP, Host: ":0"}}, nil + return &Address{true, false, -1, 0, &url.URL{Scheme: AddressSchemeTCP, Host: ":0"}}, nil } var u *url.URL @@ -71,12 +71,17 @@ func NewAddressFromNetworkValuesDefault(value string, port int, schemeDefault, s // NewAddressUnix returns an *Address from a path value. func NewAddressUnix(path string) Address { - return Address{true, true, 0, &url.URL{Scheme: AddressSchemeUnix, Path: path}} + return Address{true, true, -1, 0, &url.URL{Scheme: AddressSchemeUnix, Path: path}} } // NewAddressFromNetworkValues returns an *Address from network values. func NewAddressFromNetworkValues(network, host string, port int) Address { - return Address{true, false, port, &url.URL{Scheme: network, Host: fmt.Sprintf("%s:%d", host, port)}} + return NewAddressFromNetworkPathValues(network, host, port, "") +} + +// NewAddressFromNetworkPathValues returns an *Address from network values and a path. +func NewAddressFromNetworkPathValues(network, host string, port int, path string) Address { + return Address{true, false, -1, port, &url.URL{Scheme: network, Host: fmt.Sprintf("%s:%d", host, port), Path: path}} } // NewSMTPAddress returns an *AddressSMTP from SMTP values. @@ -103,13 +108,14 @@ func NewSMTPAddress(scheme, host string, port int) *AddressSMTP { } } - return &AddressSMTP{Address: Address{true, false, port, &url.URL{Scheme: scheme, Host: fmt.Sprintf("%s:%d", host, port)}}} + return &AddressSMTP{Address: Address{true, false, -1, port, &url.URL{Scheme: scheme, Host: fmt.Sprintf("%s:%d", host, port)}}} } // NewAddressFromURL returns an *Address and error depending on the ability to parse the *url.URL as an Address. func NewAddressFromURL(u *url.URL) (addr *Address, err error) { addr = &Address{ - url: u, + url: u, + umask: -1, } if err = addr.validate(); err != nil { @@ -143,6 +149,7 @@ type AddressSMTP struct { type Address struct { valid bool socket bool + umask int port int url *url.URL @@ -153,6 +160,15 @@ func (a *Address) Valid() bool { return a.valid } +// Umask returns the formatted umask or an empty string. +func (a *Address) Umask() string { + if a.umask == -1 { + return "" + } + + return fmt.Sprintf("%04s", strconv.FormatInt(int64(a.umask), 8)) +} + // IsUnixDomainSocket returns true if the address has been determined to be a Unix Domain Socket. func (a *Address) IsUnixDomainSocket() bool { return a.socket @@ -257,16 +273,6 @@ func (a *Address) String() string { return a.url.String() } -// Network returns the Scheme() if it's appropriate for the net packages network arguments otherwise it returns tcp. -func (a *Address) Network() string { - switch scheme := a.Scheme(); scheme { - case AddressSchemeTCP, AddressSchemeTCP4, AddressSchemeTCP6, AddressSchemeUDP, AddressSchemeUDP4, AddressSchemeUDP6, AddressSchemeUnix: - return scheme - default: - return AddressSchemeTCP - } -} - // Scheme returns the *url.URL Scheme field. func (a *Address) Scheme() string { if !a.valid || a.url == nil { @@ -276,6 +282,15 @@ func (a *Address) Scheme() string { return a.url.Scheme } +// Host returns the *url.URL Host field. +func (a *Address) Host() string { + if !a.valid || a.url == nil { + return "" + } + + return a.url.Host +} + // Hostname returns the output of the *url.URL Hostname func. func (a *Address) Hostname() string { if !a.valid || a.url == nil { @@ -285,19 +300,6 @@ func (a *Address) Hostname() string { return a.url.Hostname() } -// SocketHostname returns the correct hostname for a socket connection. -func (a *Address) SocketHostname() string { - if !a.valid || a.url == nil { - return "" - } - - if a.socket { - return a.url.Path - } - - return a.url.Hostname() -} - // SetHostname sets the hostname preserving the port. func (a *Address) SetHostname(hostname string) { if !a.valid || a.url == nil { @@ -325,13 +327,36 @@ func (a *Address) SetPort(port int) { a.setport(port) } -// Host returns the *url.URL Host field. -func (a *Address) Host() string { +// Path returns the path. +func (a *Address) Path() string { if !a.valid || a.url == nil { return "" } - return a.url.Host + return a.url.Path +} + +// SocketHostname returns the correct hostname for a socket connection. +func (a *Address) SocketHostname() string { + if !a.valid || a.url == nil { + return "" + } + + if a.socket { + return a.url.Path + } + + return a.url.Hostname() +} + +// Network returns the Scheme() if it's appropriate for the net packages network arguments otherwise it returns tcp. +func (a *Address) Network() string { + switch scheme := a.Scheme(); scheme { + case AddressSchemeTCP, AddressSchemeTCP4, AddressSchemeTCP6, AddressSchemeUDP, AddressSchemeUDP4, AddressSchemeUDP6, AddressSchemeUnix: + return scheme + default: + return AddressSchemeTCP + } } // NetworkAddress returns a string representation of the Address with just the host and port. @@ -348,46 +373,33 @@ func (a *Address) NetworkAddress() string { } // Listener creates and returns a net.Listener. -func (a *Address) Listener() (net.Listener, error) { - return a.listener() +func (a *Address) Listener() (ln net.Listener, err error) { + if a.url == nil { + return nil, fmt.Errorf("address url is nil") + } + + if a.socket && a.umask != -1 { + umask := syscall.Umask(a.umask) + + ln, err = net.Listen(a.Network(), a.NetworkAddress()) + + _ = syscall.Umask(umask) + + return ln, err + } + + return net.Listen(a.Network(), a.NetworkAddress()) } // Dial creates and returns a dialed net.Conn. func (a *Address) Dial() (net.Conn, error) { - if a.url == nil { + if !a.valid || a.url == nil { return nil, fmt.Errorf("address url is nil") } return net.Dial(a.Network(), a.NetworkAddress()) } -// ListenerWithUMask creates and returns a net.Listener with a temporary UMask if the scheme is `unix`. -func (a *Address) ListenerWithUMask(umask int) (ln net.Listener, err error) { - if !a.socket { - return a.listener() - } - - if a.url == nil { - return nil, fmt.Errorf("address url is nil") - } - - umask = syscall.Umask(umask) - - ln, err = net.Listen(a.Network(), a.NetworkAddress()) - - _ = syscall.Umask(umask) - - return ln, err -} - -func (a *Address) listener() (net.Listener, error) { - if a.url == nil { - return nil, fmt.Errorf("address url is nil") - } - - return net.Listen(a.Network(), a.NetworkAddress()) -} - func (a *Address) setport(port int) { a.port = port a.url.Host = net.JoinHostPort(a.url.Hostname(), strconv.Itoa(port)) @@ -399,8 +411,8 @@ func (a *Address) validate() (err error) { } switch { - case a.url.RawQuery != "": - return fmt.Errorf("error validating the address: the url '%s' appears to have a query but this is not valid for addresses", a.url.String()) + case a.url.RawQuery != "" && a.url.Scheme != AddressSchemeUnix: + return fmt.Errorf("error validating the address: the url '%s' appears to have a query but this is not valid for addresses with the '%s' scheme", a.url.String(), a.url.Scheme) case a.url.RawFragment != "", a.url.Fragment != "": return fmt.Errorf("error validating the address: the url '%s' appears to have a fragment but this is not valid for addresses", a.url.String()) case a.url.User != nil: @@ -469,6 +481,8 @@ func (a *Address) validateTCPUDP() (err error) { } func (a *Address) validateUnixSocket() (err error) { + umask := -1 + switch { case a.url.Path == "" && a.url.Scheme != AddressSchemeLDAPI: return fmt.Errorf("error validating the unix socket address: could not determine path from '%s'", a.url.String()) @@ -476,7 +490,22 @@ func (a *Address) validateUnixSocket() (err error) { return fmt.Errorf("error validating the unix socket address: the url '%s' appears to have a host but this is not valid for unix sockets: this may occur if you omit the leading forward slash from the socket path", a.url.String()) } + if a.url.Query().Has(addressQueryParamUmask) { + v := a.url.Query().Get(addressQueryParamUmask) + + if !regexpIsUmask.MatchString(v) { + return fmt.Errorf("error validating the unix socket address: could not parse address '%s': the address has a umask value of '%s' which does not appear to be a valid octal string", a.url.String(), v) + } + + var p int64 + + p, _ = strconv.ParseInt(v, 8, 0) + + umask = int(p) + } + a.socket = true + a.umask = umask return nil } diff --git a/internal/configuration/schema/types_address_test.go b/internal/configuration/schema/types_address_test.go index f40393d60..c30a2e09b 100644 --- a/internal/configuration/schema/types_address_test.go +++ b/internal/configuration/schema/types_address_test.go @@ -1,6 +1,7 @@ package schema import ( + "fmt" "net" "net/url" "path/filepath" @@ -20,7 +21,7 @@ func TestNewAddressFromString(t *testing.T) { { "ShouldParseBasicAddress", "tcp://0.0.0.0:9091", - &Address{true, false, 9091, &url.URL{Scheme: AddressSchemeTCP, Host: "0.0.0.0:9091"}}, + &Address{true, false, -1, 9091, &url.URL{Scheme: AddressSchemeTCP, Host: "0.0.0.0:9091"}}, "0.0.0.0:9091", "tcp://0.0.0.0:9091", "", @@ -28,7 +29,7 @@ func TestNewAddressFromString(t *testing.T) { { "ShouldParseEmptyAddress", "", - &Address{true, false, 0, &url.URL{Scheme: AddressSchemeTCP, Host: ":0"}}, + &Address{true, false, -1, 0, &url.URL{Scheme: AddressSchemeTCP, Host: ":0"}}, ":0", "tcp://:0", "", @@ -36,7 +37,7 @@ func TestNewAddressFromString(t *testing.T) { { "ShouldParseAddressMissingScheme", "0.0.0.0:9091", - &Address{true, false, 9091, &url.URL{Scheme: AddressSchemeTCP, Host: "0.0.0.0:9091"}}, + &Address{true, false, -1, 9091, &url.URL{Scheme: AddressSchemeTCP, Host: "0.0.0.0:9091"}}, "0.0.0.0:9091", "tcp://0.0.0.0:9091", "", @@ -44,7 +45,7 @@ func TestNewAddressFromString(t *testing.T) { { "ShouldParseUnixAddressMissingScheme", "/var/run/example.sock", - &Address{true, true, 0, &url.URL{Scheme: AddressSchemeUnix, Path: "/var/run/example.sock"}}, + &Address{true, true, -1, 0, &url.URL{Scheme: AddressSchemeUnix, Path: "/var/run/example.sock"}}, "/var/run/example.sock", "unix:///var/run/example.sock", "", @@ -52,15 +53,23 @@ func TestNewAddressFromString(t *testing.T) { { "ShouldParseAddressMissingPort", "tcp://0.0.0.0", - &Address{true, false, 0, &url.URL{Scheme: AddressSchemeTCP, Host: "0.0.0.0:0"}}, + &Address{true, false, -1, 0, &url.URL{Scheme: AddressSchemeTCP, Host: "0.0.0.0:0"}}, "0.0.0.0:0", "tcp://0.0.0.0:0", "", }, + { + "ShouldNotParseAddressWithQuery", + "tcp://0.0.0.0?umask=0022", + nil, + "0.0.0.0:0", + "tcp://0.0.0.0:0", + "error validating the address: the url 'tcp://0.0.0.0?umask=0022' appears to have a query but this is not valid for addresses with the 'tcp' scheme", + }, { "ShouldParseUnixSocket", "unix:///path/to/a/socket.sock", - &Address{true, true, 0, &url.URL{Scheme: AddressSchemeUnix, Path: "/path/to/a/socket.sock"}}, + &Address{true, true, -1, 0, &url.URL{Scheme: AddressSchemeUnix, Path: "/path/to/a/socket.sock"}}, "/path/to/a/socket.sock", "unix:///path/to/a/socket.sock", "", @@ -82,12 +91,12 @@ func TestNewAddressFromString(t *testing.T) { "error validating the unix socket address: could not determine path from 'unix://nopath.com'", }, { - "ShouldNotParseUnixSocketWithQuery", - "unix:///path/to/a/socket.sock?q=yes", - nil, + "ShouldParseUnixSocketWithQuery", + "unix:///path/to/a/socket.sock?umask=0022", + &Address{true, true, 18, 0, &url.URL{Scheme: AddressSchemeUnix, Path: "/path/to/a/socket.sock", RawQuery: "umask=0022"}}, + "/path/to/a/socket.sock", + "unix:///path/to/a/socket.sock?umask=0022", "", - "", - "error validating the address: the url 'unix:///path/to/a/socket.sock?q=yes' appears to have a query but this is not valid for addresses", }, { "ShouldNotParseUnixSocketWithFragment", @@ -108,7 +117,7 @@ func TestNewAddressFromString(t *testing.T) { { "ShouldParseUnknownScheme", "a://0.0.0.0", - &Address{true, false, 0, &url.URL{Scheme: "a", Host: "0.0.0.0"}}, + &Address{true, false, -1, 0, &url.URL{Scheme: "a", Host: "0.0.0.0"}}, "0.0.0.0", "a://0.0.0.0", "", @@ -140,7 +149,7 @@ func TestNewAddressFromString(t *testing.T) { { "ShouldSetDefaultPortLDAP", "ldap://127.0.0.1", - &Address{true, false, 389, &url.URL{Scheme: AddressSchemeLDAP, Host: "127.0.0.1:389"}}, + &Address{true, false, -1, 389, &url.URL{Scheme: AddressSchemeLDAP, Host: "127.0.0.1:389"}}, "127.0.0.1:389", "ldap://127.0.0.1:389", "", @@ -148,7 +157,7 @@ func TestNewAddressFromString(t *testing.T) { { "ShouldSetDefaultPortLDAPS", "ldaps://127.0.0.1", - &Address{true, false, 636, &url.URL{Scheme: AddressSchemeLDAPS, Host: "127.0.0.1:636"}}, + &Address{true, false, -1, 636, &url.URL{Scheme: AddressSchemeLDAPS, Host: "127.0.0.1:636"}}, "127.0.0.1:636", "ldaps://127.0.0.1:636", "", @@ -156,7 +165,7 @@ func TestNewAddressFromString(t *testing.T) { { "ShouldAllowLDAPI", "ldapi:///abc", - &Address{true, true, 0, &url.URL{Scheme: AddressSchemeLDAPI, Path: "/abc"}}, + &Address{true, true, -1, 0, &url.URL{Scheme: AddressSchemeLDAPI, Path: "/abc"}}, "/abc", "ldapi:///abc", "", @@ -164,7 +173,7 @@ func TestNewAddressFromString(t *testing.T) { { "ShouldAllowImplicitLDAPI", "ldapi://", - &Address{true, true, 0, &url.URL{Scheme: AddressSchemeLDAPI, Path: ""}}, + &Address{true, true, -1, 0, &url.URL{Scheme: AddressSchemeLDAPI, Path: ""}}, "", "ldapi:", "", @@ -172,7 +181,7 @@ func TestNewAddressFromString(t *testing.T) { { "ShouldAllowImplicitLDAPINoSlash", "ldapi:", - &Address{true, true, 0, &url.URL{Scheme: AddressSchemeLDAPI, Path: ""}}, + &Address{true, true, -1, 0, &url.URL{Scheme: AddressSchemeLDAPI, Path: ""}}, "", "ldapi:", "", @@ -180,7 +189,7 @@ func TestNewAddressFromString(t *testing.T) { { "ShouldSetDefaultPortSMTP", "smtp://127.0.0.1", - &Address{true, false, 25, &url.URL{Scheme: AddressSchemeSMTP, Host: "127.0.0.1:25"}}, + &Address{true, false, -1, 25, &url.URL{Scheme: AddressSchemeSMTP, Host: "127.0.0.1:25"}}, "127.0.0.1:25", "smtp://127.0.0.1:25", "", @@ -188,7 +197,7 @@ func TestNewAddressFromString(t *testing.T) { { "ShouldSetDefaultPortSUBMISSION", "submission://127.0.0.1", - &Address{true, false, 587, &url.URL{Scheme: AddressSchemeSUBMISSION, Host: "127.0.0.1:587"}}, + &Address{true, false, -1, 587, &url.URL{Scheme: AddressSchemeSUBMISSION, Host: "127.0.0.1:587"}}, "127.0.0.1:587", "submission://127.0.0.1:587", "", @@ -196,7 +205,7 @@ func TestNewAddressFromString(t *testing.T) { { "ShouldSetDefaultPortSUBMISSIONS", "submissions://127.0.0.1", - &Address{true, false, 465, &url.URL{Scheme: AddressSchemeSUBMISSIONS, Host: "127.0.0.1:465"}}, + &Address{true, false, -1, 465, &url.URL{Scheme: AddressSchemeSUBMISSIONS, Host: "127.0.0.1:465"}}, "127.0.0.1:465", "submissions://127.0.0.1:465", "", @@ -204,7 +213,7 @@ func TestNewAddressFromString(t *testing.T) { { "ShouldNotOverridePort", "ldap://127.0.0.1:123", - &Address{true, false, 123, &url.URL{Scheme: AddressSchemeLDAP, Host: "127.0.0.1:123"}}, + &Address{true, false, -1, 123, &url.URL{Scheme: AddressSchemeLDAP, Host: "127.0.0.1:123"}}, "127.0.0.1:123", "ldap://127.0.0.1:123", "", @@ -239,7 +248,7 @@ func TestAddress_ValidateErrors(t *testing.T) { }{ { "ShouldValidateLDAPAddress", - &Address{true, false, 0, &url.URL{Scheme: AddressSchemeLDAP, Host: "127.0.0.1"}}, + &Address{true, false, -1, 0, &url.URL{Scheme: AddressSchemeLDAP, Host: "127.0.0.1"}}, "", "scheme must be one of 'smtp', 'submission', or 'submissions' but is configured as 'ldap'", "scheme must be one of 'tcp', 'tcp4', 'tcp6', or 'unix' but is configured as 'ldap'", @@ -248,7 +257,7 @@ func TestAddress_ValidateErrors(t *testing.T) { }, { "ShouldValidateSMTPAddress", - &Address{true, false, 0, &url.URL{Scheme: AddressSchemeSMTP, Host: "127.0.0.1"}}, + &Address{true, false, -1, 0, &url.URL{Scheme: AddressSchemeSMTP, Host: "127.0.0.1"}}, "scheme must be one of 'ldap', 'ldaps', or 'ldapi' but is configured as 'smtp'", "", "scheme must be one of 'tcp', 'tcp4', 'tcp6', or 'unix' but is configured as 'smtp'", @@ -257,7 +266,7 @@ func TestAddress_ValidateErrors(t *testing.T) { }, { "ShouldValidateTCPAddress", - &Address{true, false, 0, &url.URL{Scheme: AddressSchemeTCP, Host: "127.0.0.1"}}, + &Address{true, false, -1, 0, &url.URL{Scheme: AddressSchemeTCP, Host: "127.0.0.1"}}, "scheme must be one of 'ldap', 'ldaps', or 'ldapi' but is configured as 'tcp'", "scheme must be one of 'smtp', 'submission', or 'submissions' but is configured as 'tcp'", "", @@ -266,7 +275,7 @@ func TestAddress_ValidateErrors(t *testing.T) { }, { "ShouldValidateUnixSocket", - &Address{true, true, 0, &url.URL{Scheme: AddressSchemeUnix, Path: "/path/to/socket"}}, + &Address{true, true, -1, 0, &url.URL{Scheme: AddressSchemeUnix, Path: "/path/to/socket"}}, "scheme must be one of 'ldap', 'ldaps', or 'ldapi' but is configured as 'unix'", "scheme must be one of 'smtp', 'submission', or 'submissions' but is configured as 'unix'", "", @@ -311,7 +320,7 @@ func TestAddress_ValidateErrors(t *testing.T) { } func TestAddress_SetHostname(t *testing.T) { - address := &Address{true, false, 0, &url.URL{Scheme: AddressSchemeTCP, Host: "0.0.0.0"}} + address := &Address{true, false, -1, 0, &url.URL{Scheme: AddressSchemeTCP, Host: "0.0.0.0"}} assert.Equal(t, "tcp://0.0.0.0", address.String()) @@ -320,32 +329,6 @@ func TestAddress_SetHostname(t *testing.T) { assert.Equal(t, "tcp://127.0.0.1", address.String()) } -func TestAddress_ListenerWithUMask(t *testing.T) { - dir := t.TempDir() - - address := &Address{true, true, 0, &url.URL{Scheme: AddressSchemeUnix, Path: filepath.Join(dir, "example.sock")}} - - ln, err := address.ListenerWithUMask(600) - - assert.NotNil(t, ln) - assert.NoError(t, err) - assert.NoError(t, ln.Close()) - - address = &Address{true, true, 0, nil} - - ln, err = address.ListenerWithUMask(600) - - assert.Nil(t, ln) - assert.EqualError(t, err, "address url is nil") - - address = &Address{true, false, 0, nil} - - ln, err = address.ListenerWithUMask(600) - - assert.Nil(t, ln) - assert.EqualError(t, err, "address url is nil") -} - func TestAddressOutputValues(t *testing.T) { var ( address *Address @@ -356,7 +339,7 @@ func TestAddressOutputValues(t *testing.T) { address = &Address{} assert.EqualError(t, address.validate(), "error validating the address: address url was nil") - address = &Address{false, false, 0, nil} + address = &Address{false, false, -1, 0, nil} assert.Equal(t, "", address.String()) assert.Equal(t, "", address.Scheme()) @@ -370,7 +353,7 @@ func TestAddressOutputValues(t *testing.T) { assert.Nil(t, listener) assert.EqualError(t, err, "address url is nil") - address = &Address{true, false, 8080, &url.URL{Scheme: AddressSchemeTCP, Host: "0.0.0.0:8080"}} + address = &Address{true, false, -1, 8080, &url.URL{Scheme: AddressSchemeTCP, Host: "0.0.0.0:8080"}} assert.Equal(t, "tcp://0.0.0.0:8080", address.String()) assert.Equal(t, "tcp", address.Scheme()) @@ -384,7 +367,7 @@ func TestAddressOutputValues(t *testing.T) { assert.NotNil(t, listener) assert.NoError(t, err) - address = &Address{true, false, 0, nil} + address = &Address{true, false, -1, 0, nil} assert.Equal(t, "", address.String()) assert.Equal(t, "", address.Scheme()) @@ -413,7 +396,7 @@ func TestAddressOutputValues(t *testing.T) { assert.Nil(t, listener) assert.EqualError(t, err, "address url is nil") - address = &Address{true, false, 9091, &url.URL{Scheme: AddressSchemeTCP, Host: "0.0.0.0:9091"}} + address = &Address{true, false, -1, 9091, &url.URL{Scheme: AddressSchemeTCP, Host: "0.0.0.0:9091"}} assert.Equal(t, "tcp://0.0.0.0:9091", address.String()) assert.Equal(t, "tcp", address.Scheme()) @@ -570,6 +553,132 @@ func TestNewSMTPAddress(t *testing.T) { } } +func TestAddress_Dial(t *testing.T) { + testCases := []struct { + name string + have Address + success bool + err string + }{ + { + "ShouldNotDialNil", + Address{true, false, -1, 0, nil}, + false, + "address url is nil", + }, + { + "ShouldNotDialInvalid", + Address{false, false, -1, 0, &url.URL{}}, + false, + "address url is nil", + }, + { + "ShouldNotDialInvalidAddress", + Address{true, false, -1, 0, &url.URL{Scheme: "abc", Host: "127.0.0.1:0"}}, + false, + "dial tcp 127.0.0.1:0: connect: connection refused", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + conn, err := tc.have.Dial() + + defer func(c net.Conn) { + if c == nil { + return + } + + conn.Close() + }(conn) + + if tc.success { + + } else { + assert.Nil(t, conn) + if tc.err != "" { + assert.EqualError(t, err, tc.err) + } else { + assert.NotNil(t, err) + } + } + }) + } +} + +func TestAddress_UnixDomainSocket(t *testing.T) { + dir := t.TempDir() + + testCases := []struct { + name string + have string + socket bool + path string + strUmask string + umask int + err string + }{ + { + "ShouldNotBeSocket", + "tcp://:9091", + false, + "", + "", + -1, + "", + }, + { + "ShouldParseSocket", + fmt.Sprintf("unix://%s", filepath.Join(dir, "example.sock")), + true, + filepath.Join(dir, "example.sock"), + "", + -1, + "", + }, + { + "ShouldParseSocketWithUmask", + fmt.Sprintf("unix://%s?umask=0022", filepath.Join(dir, "example.sock")), + true, + filepath.Join(dir, "example.sock"), + "0022", + 18, + "", + }, + { + "ShouldParseSocketWithBadUmask", + fmt.Sprintf("unix://%s?umask=abc", filepath.Join(dir, "example.sock")), + true, + "", + "", + -1, + fmt.Sprintf("error validating the unix socket address: could not parse address 'unix://%s?umask=abc': the address has a umask value of 'abc' which does not appear to be a valid octal string", filepath.Join(dir, "example.sock")), + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + actual, err := NewAddress(tc.have) + + if tc.err == "" { + assert.Equal(t, tc.socket, actual.IsUnixDomainSocket()) + assert.Equal(t, tc.path, actual.Path()) + assert.Equal(t, tc.strUmask, actual.Umask()) + assert.Equal(t, tc.umask, actual.umask) + + ln, err := actual.Listener() + + assert.NoError(t, err) + assert.NotNil(t, ln) + + assert.NoError(t, ln.Close()) + } else { + assert.EqualError(t, err, tc.err) + } + }) + } +} + func TestAddress_SocketHostname(t *testing.T) { testCases := []struct { name string @@ -578,22 +687,22 @@ func TestAddress_SocketHostname(t *testing.T) { }{ { "ShouldReturnHostname", - Address{true, false, 80, &url.URL{Scheme: AddressSchemeTCP, Host: "examplea:80"}}, + Address{true, false, -1, 80, &url.URL{Scheme: AddressSchemeTCP, Host: "examplea:80"}}, "examplea", }, { "ShouldReturnPath", - Address{true, true, 80, &url.URL{Scheme: AddressSchemeUnix, Path: "/abc/123"}}, + Address{true, true, -1, 80, &url.URL{Scheme: AddressSchemeUnix, Path: "/abc/123"}}, "/abc/123", }, { "ShouldReturnNothing", - Address{false, true, 80, &url.URL{Scheme: AddressSchemeUnix, Path: "/abc/123"}}, + Address{false, true, -1, 80, &url.URL{Scheme: AddressSchemeUnix, Path: "/abc/123"}}, "", }, { "ShouldReturnNothingNil", - Address{true, true, 80, nil}, + Address{true, true, -1, 80, nil}, "", }, } @@ -605,6 +714,41 @@ func TestAddress_SocketHostname(t *testing.T) { } } +func TestAddress_Path(t *testing.T) { + testCases := []struct { + name string + have Address + expected string + }{ + { + "ShouldReturnEmptyPath", + Address{true, false, -1, 80, &url.URL{Scheme: AddressSchemeTCP, Host: "tcphosta"}}, + "", + }, + { + "ShouldReturnPath", + Address{true, false, -1, 80, &url.URL{Scheme: AddressSchemeTCP, Host: "tcphosta", Path: "/apath"}}, + "/apath", + }, + { + "ShouldNotReturnPathInvalid", + Address{false, false, -1, 80, &url.URL{Scheme: AddressSchemeTCP, Host: "tcphosta", Path: "/apath"}}, + "", + }, + { + "ShouldNotReturnPathNil", + Address{true, false, -1, 80, nil}, + "", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + assert.Equal(t, tc.expected, tc.have.Path()) + }) + } +} + func TestAddress_IsTCP_IsUDP(t *testing.T) { testCases := []struct { name string @@ -614,49 +758,49 @@ func TestAddress_IsTCP_IsUDP(t *testing.T) { }{ { "ShouldReturnTrueTCP", - Address{true, false, 80, &url.URL{Scheme: AddressSchemeTCP, Host: "tcphosta"}}, + Address{true, false, -1, 80, &url.URL{Scheme: AddressSchemeTCP, Host: "tcphosta"}}, true, false, }, { "ShouldReturnTrueTCP4", - Address{true, false, 80, &url.URL{Scheme: AddressSchemeTCP4, Host: "tcphostb"}}, + Address{true, false, -1, 80, &url.URL{Scheme: AddressSchemeTCP4, Host: "tcphostb"}}, true, false, }, { "ShouldReturnTrueTCP6", - Address{true, false, 80, &url.URL{Scheme: AddressSchemeTCP6, Host: "tcphostc"}}, + Address{true, false, -1, 80, &url.URL{Scheme: AddressSchemeTCP6, Host: "tcphostc"}}, true, false, }, { "ShouldReturnFalseUDP", - Address{true, false, 80, &url.URL{Scheme: AddressSchemeUDP, Host: "tcphostd"}}, + Address{true, false, -1, 80, &url.URL{Scheme: AddressSchemeUDP, Host: "tcphostd"}}, false, true, }, { "ShouldReturnFalseUDP4", - Address{true, false, 80, &url.URL{Scheme: AddressSchemeUDP4, Host: "tcphoste"}}, + Address{true, false, -1, 80, &url.URL{Scheme: AddressSchemeUDP4, Host: "tcphoste"}}, false, true, }, { "ShouldReturnFalseUDP6", - Address{true, false, 80, &url.URL{Scheme: AddressSchemeUDP6, Host: "tcphostf"}}, + Address{true, false, -1, 80, &url.URL{Scheme: AddressSchemeUDP6, Host: "tcphostf"}}, false, true, }, { "ShouldReturnFalseSMTP", - Address{true, false, 80, &url.URL{Scheme: AddressSchemeSMTP, Host: "tcphostg"}}, + Address{true, false, -1, 80, &url.URL{Scheme: AddressSchemeSMTP, Host: "tcphostg"}}, false, false, }, { "ShouldReturnFalseUnix", - Address{true, true, 80, &url.URL{Scheme: AddressSchemeUnix, Host: "tcphosth"}}, + Address{true, true, -1, 80, &url.URL{Scheme: AddressSchemeUnix, Host: "tcphosth"}}, false, false, }, diff --git a/internal/server/server.go b/internal/server/server.go index d1f83c9f7..59d2d5d92 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -37,14 +37,7 @@ func CreateDefaultServer(config *schema.Configuration, providers middlewares.Pro connectionScheme = schemeHTTP ) - switch config.Server.UMask { - case nil: - listener, err = config.Server.Address.Listener() - default: - listener, err = config.Server.Address.ListenerWithUMask(*config.Server.UMask) - } - - if err != nil { + if listener, err = config.Server.Address.Listener(); err != nil { return nil, nil, nil, false, fmt.Errorf("error occurred while attempting to initialize main server listener for address '%s': %w", config.Server.Address.String(), err) } @@ -109,14 +102,7 @@ func CreateMetricsServer(config *schema.Configuration, providers middlewares.Pro Logger: logging.LoggerPrintf(logrus.DebugLevel), } - switch config.Telemetry.Metrics.UMask { - case nil: - listener, err = config.Telemetry.Metrics.Address.Listener() - default: - listener, err = config.Telemetry.Metrics.Address.ListenerWithUMask(*config.Telemetry.Metrics.UMask) - } - - if err != nil { + if listener, err = config.Telemetry.Metrics.Address.Listener(); err != nil { return nil, nil, nil, false, fmt.Errorf("error occurred while attempting to initialize metrics telemetry server listener for address '%s': %w", config.Telemetry.Metrics.Address.String(), err) }