From 3f39914c8f4dcaa63d56de579143fc8378afb9b0 Mon Sep 17 00:00:00 2001 From: James Elliott Date: Mon, 3 Oct 2022 11:52:29 +1100 Subject: [PATCH] refactor: private key decoding and generators (#4116) --- cmd/authelia-gen/cmd_code.go | 4 + ...contributing-development-commitmsg.md.tmpl | 6 +- .../contributing/guidelines/documentation.md | 2 +- .../contributing/guidelines/introduction.md | 2 +- .../en/integration/kubernetes/istio.md | 2 +- docs/data/configkeys.json | 2 +- internal/configuration/decode_hooks.go | 48 +++-- internal/configuration/decode_hooks_test.go | 180 +++++++++++++----- internal/configuration/provider.go | 2 +- 9 files changed, 179 insertions(+), 69 deletions(-) diff --git a/cmd/authelia-gen/cmd_code.go b/cmd/authelia-gen/cmd_code.go index f0cac4bba..54db167e0 100644 --- a/cmd/authelia-gen/cmd_code.go +++ b/cmd/authelia-gen/cmd_code.go @@ -1,6 +1,8 @@ package main import ( + "crypto/ecdsa" + "crypto/rsa" "encoding/json" "fmt" "io" @@ -181,6 +183,8 @@ var decodedTypes = []reflect.Type{ reflect.TypeOf(url.URL{}), reflect.TypeOf(time.Duration(0)), reflect.TypeOf(schema.Address{}), + reflect.TypeOf(rsa.PrivateKey{}), + reflect.TypeOf(ecdsa.PrivateKey{}), } func containsType(needle reflect.Type, haystack []reflect.Type) (contains bool) { diff --git a/cmd/authelia-gen/templates/docs-contributing-development-commitmsg.md.tmpl b/cmd/authelia-gen/templates/docs-contributing-development-commitmsg.md.tmpl index 93b960316..7384db785 100644 --- a/cmd/authelia-gen/templates/docs-contributing-development-commitmsg.md.tmpl +++ b/cmd/authelia-gen/templates/docs-contributing-development-commitmsg.md.tmpl @@ -1,5 +1,5 @@ --- -title: "Commit Message Guidelines" +title: "Commit Message" description: "Authelia Development Commit Message Guidelines" lead: "This section covers the git commit message guidelines we use for development." date: 2021-01-30T19:29:07+11:00 @@ -7,8 +7,8 @@ draft: false images: [] menu: contributing: - parent: "development" -weight: 231 + parent: "guidelines" +weight: 320 toc: true aliases: - /docs/contributing/commitmsg-guidelines.html diff --git a/docs/content/en/contributing/guidelines/documentation.md b/docs/content/en/contributing/guidelines/documentation.md index 2a415e874..5d22f567f 100644 --- a/docs/content/en/contributing/guidelines/documentation.md +++ b/docs/content/en/contributing/guidelines/documentation.md @@ -2,7 +2,7 @@ title: "Documentation" description: "Authelia Development Documentation Guidelines" lead: "This section covers the guidelines we use when writing documentation." -date: 2021-01-30T19:29:07+11:00 +date: 2022-10-02T14:32:16+11:00 draft: false images: [] menu: diff --git a/docs/content/en/contributing/guidelines/introduction.md b/docs/content/en/contributing/guidelines/introduction.md index 28d0a249a..293d8a097 100644 --- a/docs/content/en/contributing/guidelines/introduction.md +++ b/docs/content/en/contributing/guidelines/introduction.md @@ -2,7 +2,7 @@ title: "Guidelines" description: "An introduction into guidelines for contributing to the Authelia project." lead: "An introduction into guidelines for contributing to the Authelia project." -date: 2022-06-15T17:51:47+10:00 +date: 2022-10-02T14:32:16+11:00 draft: false images: [] menu: diff --git a/docs/content/en/integration/kubernetes/istio.md b/docs/content/en/integration/kubernetes/istio.md index 29e14a43f..801204406 100644 --- a/docs/content/en/integration/kubernetes/istio.md +++ b/docs/content/en/integration/kubernetes/istio.md @@ -2,7 +2,7 @@ title: "Istio" description: "A guide to integrating Authelia with the Istio Kubernetes Ingress." lead: "A guide to integrating Authelia with the Istio Kubernetes Ingress." -date: 2022-06-15T17:51:47+10:00 +date: 2022-10-02T13:59:09+11:00 draft: false images: [] menu: diff --git a/docs/data/configkeys.json b/docs/data/configkeys.json index c351cb250..c3bb2436f 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_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.endpoints","secret":false,"env":"AUTHELIA_IDENTITY_PROVIDERS_OIDC_CORS_ENDPOINTS"},{"path":"identity_providers.oidc.cors.allowed_origins","secret":false,"env":"AUTHELIA_IDENTITY_PROVIDERS_OIDC_CORS_ALLOWED_ORIGINS"},{"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.clients","secret":false,"env":"AUTHELIA_IDENTITY_PROVIDERS_OIDC_CLIENTS"},{"path":"authentication_backend.ldap.implementation","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_IMPLEMENTATION"},{"path":"authentication_backend.ldap.url","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_URL"},{"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.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.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":"authentication_backend.file.path","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PATH"},{"path":"authentication_backend.file.password.iterations","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_ITERATIONS"},{"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.password.algorithm","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_ALGORITHM"},{"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.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":"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.secret","secret":true,"env":"AUTHELIA_SESSION_SECRET_FILE"},{"path":"session.expiration","secret":false,"env":"AUTHELIA_SESSION_EXPIRATION"},{"path":"session.inactivity","secret":false,"env":"AUTHELIA_SESSION_INACTIVITY"},{"path":"session.remember_me_duration","secret":false,"env":"AUTHELIA_SESSION_REMEMBER_ME_DURATION"},{"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.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.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.nodes","secret":false,"env":"AUTHELIA_SESSION_REDIS_HIGH_AVAILABILITY_NODES"},{"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":"access_control.networks","secret":false,"env":"AUTHELIA_ACCESS_CONTROL_NETWORKS"},{"path":"access_control.rules","secret":false,"env":"AUTHELIA_ACCESS_CONTROL_RULES"},{"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.host","secret":false,"env":"AUTHELIA_STORAGE_MYSQL_HOST"},{"path":"storage.mysql.port","secret":false,"env":"AUTHELIA_STORAGE_MYSQL_PORT"},{"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.postgres.host","secret":false,"env":"AUTHELIA_STORAGE_POSTGRES_HOST"},{"path":"storage.postgres.port","secret":false,"env":"AUTHELIA_STORAGE_POSTGRES_PORT"},{"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.schema","secret":false,"env":"AUTHELIA_STORAGE_POSTGRES_SCHEMA"},{"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.host","secret":false,"env":"AUTHELIA_NOTIFIER_SMTP_HOST"},{"path":"notifier.smtp.port","secret":false,"env":"AUTHELIA_NOTIFIER_SMTP_PORT"},{"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.tls.minimum_version","secret":false,"env":"AUTHELIA_NOTIFIER_SMTP_TLS_MINIMUM_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.template_path","secret":false,"env":"AUTHELIA_NOTIFIER_TEMPLATE_PATH"},{"path":"server.host","secret":false,"env":"AUTHELIA_SERVER_HOST"},{"path":"server.port","secret":false,"env":"AUTHELIA_SERVER_PORT"},{"path":"server.path","secret":false,"env":"AUTHELIA_SERVER_PATH"},{"path":"server.asset_path","secret":false,"env":"AUTHELIA_SERVER_ASSET_PATH"},{"path":"server.enable_pprof","secret":false,"env":"AUTHELIA_SERVER_ENABLE_PPROF"},{"path":"server.enable_expvars","secret":false,"env":"AUTHELIA_SERVER_ENABLE_EXPVARS"},{"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.tls.client_certificates","secret":false,"env":"AUTHELIA_SERVER_TLS_CLIENT_CERTIFICATES"},{"path":"server.headers.csp_template","secret":false,"env":"AUTHELIA_SERVER_HEADERS_CSP_TEMPLATE"},{"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":"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"}] \ 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":false,"env":"AUTHELIA_IDENTITY_PROVIDERS_OIDC_ISSUER_CERTIFICATE_CHAIN"},{"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.endpoints","secret":false,"env":"AUTHELIA_IDENTITY_PROVIDERS_OIDC_CORS_ENDPOINTS"},{"path":"identity_providers.oidc.cors.allowed_origins","secret":false,"env":"AUTHELIA_IDENTITY_PROVIDERS_OIDC_CORS_ALLOWED_ORIGINS"},{"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.clients","secret":false,"env":"AUTHELIA_IDENTITY_PROVIDERS_OIDC_CLIENTS"},{"path":"authentication_backend.ldap.implementation","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_IMPLEMENTATION"},{"path":"authentication_backend.ldap.url","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_LDAP_URL"},{"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.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.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":"authentication_backend.file.path","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PATH"},{"path":"authentication_backend.file.password.iterations","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_ITERATIONS"},{"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.password.algorithm","secret":false,"env":"AUTHELIA_AUTHENTICATION_BACKEND_FILE_PASSWORD_ALGORITHM"},{"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.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":"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.secret","secret":true,"env":"AUTHELIA_SESSION_SECRET_FILE"},{"path":"session.expiration","secret":false,"env":"AUTHELIA_SESSION_EXPIRATION"},{"path":"session.inactivity","secret":false,"env":"AUTHELIA_SESSION_INACTIVITY"},{"path":"session.remember_me_duration","secret":false,"env":"AUTHELIA_SESSION_REMEMBER_ME_DURATION"},{"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.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.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.nodes","secret":false,"env":"AUTHELIA_SESSION_REDIS_HIGH_AVAILABILITY_NODES"},{"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":"access_control.networks","secret":false,"env":"AUTHELIA_ACCESS_CONTROL_NETWORKS"},{"path":"access_control.rules","secret":false,"env":"AUTHELIA_ACCESS_CONTROL_RULES"},{"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.host","secret":false,"env":"AUTHELIA_STORAGE_MYSQL_HOST"},{"path":"storage.mysql.port","secret":false,"env":"AUTHELIA_STORAGE_MYSQL_PORT"},{"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.postgres.host","secret":false,"env":"AUTHELIA_STORAGE_POSTGRES_HOST"},{"path":"storage.postgres.port","secret":false,"env":"AUTHELIA_STORAGE_POSTGRES_PORT"},{"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.schema","secret":false,"env":"AUTHELIA_STORAGE_POSTGRES_SCHEMA"},{"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.host","secret":false,"env":"AUTHELIA_NOTIFIER_SMTP_HOST"},{"path":"notifier.smtp.port","secret":false,"env":"AUTHELIA_NOTIFIER_SMTP_PORT"},{"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.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.template_path","secret":false,"env":"AUTHELIA_NOTIFIER_TEMPLATE_PATH"},{"path":"server.host","secret":false,"env":"AUTHELIA_SERVER_HOST"},{"path":"server.port","secret":false,"env":"AUTHELIA_SERVER_PORT"},{"path":"server.path","secret":false,"env":"AUTHELIA_SERVER_PATH"},{"path":"server.asset_path","secret":false,"env":"AUTHELIA_SERVER_ASSET_PATH"},{"path":"server.enable_pprof","secret":false,"env":"AUTHELIA_SERVER_ENABLE_PPROF"},{"path":"server.enable_expvars","secret":false,"env":"AUTHELIA_SERVER_ENABLE_EXPVARS"},{"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.tls.client_certificates","secret":false,"env":"AUTHELIA_SERVER_TLS_CLIENT_CERTIFICATES"},{"path":"server.headers.csp_template","secret":false,"env":"AUTHELIA_SERVER_HEADERS_CSP_TEMPLATE"},{"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":"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"}] \ No newline at end of file diff --git a/internal/configuration/decode_hooks.go b/internal/configuration/decode_hooks.go index 31f657f37..9dd236690 100644 --- a/internal/configuration/decode_hooks.go +++ b/internal/configuration/decode_hooks.go @@ -1,6 +1,7 @@ package configuration import ( + "crypto/ecdsa" "crypto/rsa" "crypto/x509" "fmt" @@ -343,8 +344,8 @@ func StringToX509CertificateChainHookFunc() mapstructure.DecodeHookFuncType { } } -// StringToRSAPrivateKeyHookFunc decodes strings to rsa.PrivateKey's. -func StringToRSAPrivateKeyHookFunc() mapstructure.DecodeHookFuncType { +// StringToPrivateKeyHookFunc decodes strings to rsa.PrivateKey's. +func StringToPrivateKeyHookFunc() mapstructure.DecodeHookFuncType { return func(f reflect.Type, t reflect.Type, data interface{}) (value interface{}, err error) { if f.Kind() != reflect.String { return data, nil @@ -354,28 +355,53 @@ func StringToRSAPrivateKeyHookFunc() mapstructure.DecodeHookFuncType { return data, nil } - expectedType := reflect.TypeOf(rsa.PrivateKey{}) + expectedTypeRSA := reflect.TypeOf(rsa.PrivateKey{}) + expectedTypeECDSA := reflect.TypeOf(ecdsa.PrivateKey{}) - if t.Elem() != expectedType { - return data, nil - } + var ( + i any + expectedType reflect.Type + ) dataStr := data.(string) - var result *rsa.PrivateKey + switch t.Elem() { + case expectedTypeRSA: + var result *rsa.PrivateKey - if dataStr == "" { - return result, nil + if dataStr == "" { + return result, nil + } + + expectedType = expectedTypeRSA + case expectedTypeECDSA: + var result *ecdsa.PrivateKey + + if dataStr == "" { + return result, nil + } + + expectedType = expectedTypeECDSA + default: + return data, nil } - var i interface{} - if i, err = utils.ParseX509FromPEM([]byte(dataStr)); err != nil { return nil, fmt.Errorf(errFmtDecodeHookCouldNotParseBasic, "*", expectedType, err) } switch r := i.(type) { case *rsa.PrivateKey: + if expectedType != expectedTypeRSA { + return nil, fmt.Errorf(errFmtDecodeHookCouldNotParseBasic, "*", expectedType, fmt.Errorf("the data is for a %T not a *%s", r, expectedType)) + } + + return r, nil + case *ecdsa.PrivateKey: + if expectedType != expectedTypeECDSA { + return nil, fmt.Errorf(errFmtDecodeHookCouldNotParseBasic, "*", expectedType, fmt.Errorf("the data is for a %T not a *%s", r, expectedType)) + } + return r, nil default: return nil, fmt.Errorf(errFmtDecodeHookCouldNotParseBasic, "*", expectedType, fmt.Errorf("the data is for a %T not a *%s", r, expectedType)) diff --git a/internal/configuration/decode_hooks_test.go b/internal/configuration/decode_hooks_test.go index 69e947de0..6a752e5f9 100644 --- a/internal/configuration/decode_hooks_test.go +++ b/internal/configuration/decode_hooks_test.go @@ -23,8 +23,8 @@ import ( func TestStringToMailAddressHookFunc(t *testing.T) { testCases := []struct { desc string - have interface{} - want interface{} + have any + want any err string decode bool }{ @@ -78,8 +78,8 @@ func TestStringToMailAddressHookFunc(t *testing.T) { func TestStringToMailAddressHookFuncPointer(t *testing.T) { testCases := []struct { desc string - have interface{} - want interface{} + have any + want any err string decode bool }{ @@ -139,8 +139,8 @@ func TestStringToMailAddressHookFuncPointer(t *testing.T) { func TestStringToURLHookFunc(t *testing.T) { testCases := []struct { desc string - have interface{} - want interface{} + have any + want any err string decode bool }{ @@ -212,8 +212,8 @@ func TestStringToURLHookFunc(t *testing.T) { func TestStringToURLHookFuncPointer(t *testing.T) { testCases := []struct { desc string - have interface{} - want interface{} + have any + want any err string decode bool }{ @@ -285,8 +285,8 @@ func TestStringToURLHookFuncPointer(t *testing.T) { func TestToTimeDurationHookFunc(t *testing.T) { testCases := []struct { desc string - have interface{} - want interface{} + have any + want any err string decode bool }{ @@ -405,8 +405,8 @@ func TestToTimeDurationHookFunc(t *testing.T) { func TestToTimeDurationHookFuncPointer(t *testing.T) { testCases := []struct { desc string - have interface{} - want interface{} + have any + want any err string decode bool }{ @@ -526,8 +526,8 @@ func TestToTimeDurationHookFuncPointer(t *testing.T) { func TestStringToRegexpFunc(t *testing.T) { testCases := []struct { desc string - have interface{} - want interface{} + have any + want any err string decode bool wantGrps []string @@ -640,8 +640,8 @@ func TestStringToRegexpFunc(t *testing.T) { func TestStringToRegexpFuncPointers(t *testing.T) { testCases := []struct { desc string - have interface{} - want interface{} + have any + want any err string decode bool wantGrps []string @@ -775,8 +775,8 @@ func TestStringToAddressHookFunc(t *testing.T) { testCases := []struct { name string - have interface{} - expected interface{} + have any + expected any err string decode bool }{ @@ -867,51 +867,108 @@ func TestStringToAddressHookFunc(t *testing.T) { } } -func TestStringToRSAPrivateKeyHookFunc(t *testing.T) { - var nilkey *rsa.PrivateKey +func TestStringToPrivateKeyHookFunc(t *testing.T) { + var ( + nilRSA *rsa.PrivateKey + nilECDSA *ecdsa.PrivateKey + nilCert *x509.Certificate + ) testCases := []struct { desc string - have interface{} - want interface{} + have any + want any err string decode bool }{ { desc: "ShouldDecodeRSAPrivateKey", have: x509PrivateKeyRSA1, - want: mustParseRSAPrivateKey(x509PrivateKeyRSA1), + want: MustParseRSAPrivateKey(x509PrivateKeyRSA1), + decode: true, + }, + { + desc: "ShouldDecodeECDSAPrivateKey", + have: x509PrivateKeyEC1, + want: MustParseECDSAPrivateKey(x509PrivateKeyEC1), decode: true, }, { desc: "ShouldNotDecodeToECDSAPrivateKey", have: x509PrivateKeyRSA1, want: &ecdsa.PrivateKey{}, - decode: false, + decode: true, + err: "could not decode to a *ecdsa.PrivateKey: the data is for a *rsa.PrivateKey not a *ecdsa.PrivateKey", }, { - desc: "ShouldNotDecodeEmptyKey", + desc: "ShouldNotDecodeEmptyRSAKey", have: "", - want: nilkey, + want: nilRSA, + decode: true, + }, + { + desc: "ShouldNotDecodeEmptyECDSAKey", + have: "", + want: nilECDSA, decode: true, }, { desc: "ShouldNotDecodeECDSAKeyToRSAKey", have: x509PrivateKeyEC1, - want: nilkey, + want: nilRSA, decode: true, err: "could not decode to a *rsa.PrivateKey: the data is for a *ecdsa.PrivateKey not a *rsa.PrivateKey", }, + { + desc: "ShouldNotDecodeRSAKeyToECDSAKey", + have: x509PrivateKeyRSA1, + want: nilECDSA, + decode: true, + err: "could not decode to a *ecdsa.PrivateKey: the data is for a *rsa.PrivateKey not a *ecdsa.PrivateKey", + }, { desc: "ShouldNotDecodeBadRSAPrivateKey", have: x509PrivateKeyRSA2, - want: nilkey, + want: nilRSA, decode: true, err: "could not decode to a *rsa.PrivateKey: failed to parse PEM block containing the key", }, + { + desc: "ShouldNotDecodeBadECDSAPrivateKey", + have: x509PrivateKeyEC2, + want: nilECDSA, + decode: true, + err: "could not decode to a *ecdsa.PrivateKey: failed to parse PEM block containing the key", + }, + { + desc: "ShouldNotDecodeCertificateToRSAPrivateKey", + have: x509CertificateRSA1, + want: nilRSA, + decode: true, + err: "could not decode to a *rsa.PrivateKey: the data is for a *x509.Certificate not a *rsa.PrivateKey", + }, + { + desc: "ShouldNotDecodeCertificateToECDSAPrivateKey", + have: x509CertificateRSA1, + want: nilECDSA, + decode: true, + err: "could not decode to a *ecdsa.PrivateKey: the data is for a *x509.Certificate not a *ecdsa.PrivateKey", + }, + { + desc: "ShouldNotDecodeRSAKeyToCertificate", + have: x509PrivateKeyRSA1, + want: nilCert, + decode: false, + }, + { + desc: "ShouldNotDecodeECDSAKeyToCertificate", + have: x509PrivateKeyEC1, + want: nilCert, + decode: false, + }, } - hook := configuration.StringToRSAPrivateKeyHookFunc() + hook := configuration.StringToPrivateKeyHookFunc() for _, tc := range testCases { t.Run(tc.desc, func(t *testing.T) { @@ -944,25 +1001,25 @@ func TestStringToX509CertificateHookFunc(t *testing.T) { { desc: "ShouldDecodeRSACertificate", have: x509CertificateRSA1, - want: mustParseX509Certificate(x509CertificateRSA1), + want: MustParseX509Certificate(x509CertificateRSA1), decode: true, }, { desc: "ShouldDecodeECDSACertificate", have: x509CACertificateECDSA, - want: mustParseX509Certificate(x509CACertificateECDSA), + want: MustParseX509Certificate(x509CACertificateECDSA), decode: true, }, { desc: "ShouldDecodeRSACACertificate", have: x509CACertificateRSA, - want: mustParseX509Certificate(x509CACertificateRSA), + want: MustParseX509Certificate(x509CACertificateRSA), decode: true, }, { desc: "ShouldDecodeECDSACACertificate", have: x509CACertificateECDSA, - want: mustParseX509Certificate(x509CACertificateECDSA), + want: MustParseX509Certificate(x509CACertificateECDSA), decode: true, }, { @@ -1020,50 +1077,50 @@ func TestStringToX509CertificateChainHookFunc(t *testing.T) { { desc: "ShouldDecodeRSACertificate", have: x509CertificateRSA1, - expected: mustParseX509CertificateChain(x509CertificateRSA1), + expected: MustParseX509CertificateChain(x509CertificateRSA1), decode: true, }, { desc: "ShouldDecodeRSACertificateNoPtr", have: x509CertificateRSA1, - expected: *mustParseX509CertificateChain(x509CertificateRSA1), + expected: *MustParseX509CertificateChain(x509CertificateRSA1), decode: true, }, { desc: "ShouldDecodeRSACertificateChain", - have: buildChain(x509CertificateRSA1, x509CACertificateRSA), - expected: mustParseX509CertificateChain(x509CertificateRSA1, x509CACertificateRSA), + have: BuildChain(x509CertificateRSA1, x509CACertificateRSA), + expected: MustParseX509CertificateChain(x509CertificateRSA1, x509CACertificateRSA), decode: true, }, { desc: "ShouldDecodeRSACertificateChainNoPtr", - have: buildChain(x509CertificateRSA1, x509CACertificateRSA), - expected: *mustParseX509CertificateChain(x509CertificateRSA1, x509CACertificateRSA), + have: BuildChain(x509CertificateRSA1, x509CACertificateRSA), + expected: *MustParseX509CertificateChain(x509CertificateRSA1, x509CACertificateRSA), decode: true, }, { desc: "ShouldNotDecodeBadRSACertificateChain", - have: buildChain(x509CertificateRSA1, x509CACertificateECDSA), - expected: mustParseX509CertificateChain(x509CertificateRSA1, x509CACertificateECDSA), + have: BuildChain(x509CertificateRSA1, x509CACertificateECDSA), + expected: MustParseX509CertificateChain(x509CertificateRSA1, x509CACertificateECDSA), verr: "certificate #1 in chain is not signed properly by certificate #2 in chain: x509: signature algorithm specifies an RSA public key, but have public key of type *ecdsa.PublicKey", decode: true, }, { desc: "ShouldDecodeECDSACertificate", have: x509CACertificateECDSA, - expected: mustParseX509CertificateChain(x509CACertificateECDSA), + expected: MustParseX509CertificateChain(x509CACertificateECDSA), decode: true, }, { desc: "ShouldDecodeRSACACertificate", have: x509CACertificateRSA, - expected: mustParseX509CertificateChain(x509CACertificateRSA), + expected: MustParseX509CertificateChain(x509CACertificateRSA), decode: true, }, { desc: "ShouldDecodeECDSACACertificate", have: x509CACertificateECDSA, - expected: mustParseX509CertificateChain(x509CACertificateECDSA), + expected: MustParseX509CertificateChain(x509CACertificateECDSA), decode: true, }, { @@ -1175,6 +1232,11 @@ bad key MHcCAQEEIMn970LSn8aKVhBM4vyUmpZyEdCT4riN+Lp4QU04zUhYoAoGCCqGSM49 AwEHoUQDQgAEMD69n22nd78GmaRDzy/s7muqhbc/OEnFS2mNtiRAA5FaX+kbkCB5 8pu/k2jkaSVNZtBYKPVAibHkhvakjVb66A== +-----END EC PRIVATE KEY-----` + + x509PrivateKeyEC2 = ` +-----BEGIN EC PRIVATE KEY----- +bad key -----END EC PRIVATE KEY-----` x509CertificateRSA1 = ` @@ -1232,14 +1294,14 @@ uDv6M2spMi0CIQC8uOSMcv11vp1ylsGg38N6XYA+GQa1BHRd79+91hC+7w== -----END CERTIFICATE-----` ) -func mustParseRSAPrivateKey(data string) *rsa.PrivateKey { +func MustParseRSAPrivateKey(data string) *rsa.PrivateKey { block, _ := pem.Decode([]byte(data)) if block == nil || block.Bytes == nil || len(block.Bytes) == 0 { panic("not pem encoded") } if block.Type != "RSA PRIVATE KEY" { - panic("not private key") + panic("not rsa private key") } key, err := x509.ParsePKCS1PrivateKey(block.Bytes) @@ -1250,7 +1312,25 @@ func mustParseRSAPrivateKey(data string) *rsa.PrivateKey { return key } -func mustParseX509Certificate(data string) *x509.Certificate { +func MustParseECDSAPrivateKey(data string) *ecdsa.PrivateKey { + block, _ := pem.Decode([]byte(data)) + if block == nil || block.Bytes == nil || len(block.Bytes) == 0 { + panic("not pem encoded") + } + + if block.Type != "EC PRIVATE KEY" { + panic("not ecdsa private key") + } + + key, err := x509.ParseECPrivateKey(block.Bytes) + if err != nil { + panic(err) + } + + return key +} + +func MustParseX509Certificate(data string) *x509.Certificate { block, _ := pem.Decode([]byte(data)) if block == nil || len(block.Bytes) == 0 { panic("not a PEM") @@ -1264,7 +1344,7 @@ func mustParseX509Certificate(data string) *x509.Certificate { return cert } -func buildChain(pems ...string) string { +func BuildChain(pems ...string) string { buf := bytes.Buffer{} for i, data := range pems { @@ -1278,8 +1358,8 @@ func buildChain(pems ...string) string { return buf.String() } -func mustParseX509CertificateChain(datas ...string) *schema.X509CertificateChain { - chain, err := schema.NewX509CertificateChain(buildChain(datas...)) +func MustParseX509CertificateChain(datas ...string) *schema.X509CertificateChain { + chain, err := schema.NewX509CertificateChain(BuildChain(datas...)) if err != nil { panic(err) } diff --git a/internal/configuration/provider.go b/internal/configuration/provider.go index 96db9c86b..22b179331 100644 --- a/internal/configuration/provider.go +++ b/internal/configuration/provider.go @@ -63,7 +63,7 @@ func unmarshal(ko *koanf.Koanf, val *schema.StructValidator, path string, o inte StringToAddressHookFunc(), StringToX509CertificateHookFunc(), StringToX509CertificateChainHookFunc(), - StringToRSAPrivateKeyHookFunc(), + StringToPrivateKeyHookFunc(), ToTimeDurationHookFunc(), ), Metadata: nil,