Merge remote-tracking branch 'origin/master' into feat-settings-ui

# Conflicts:
#	api/openapi.yml
pull/4806/head
James Elliott 2022-12-17 15:47:34 +11:00
commit a186dca3bf
No known key found for this signature in database
GPG Key ID: 0F1C4A096E857E49
177 changed files with 7196 additions and 3914 deletions

View File

@ -3,7 +3,7 @@
set +u set +u
declare -A BUILDS=(["linux"]="amd64 arm arm64 amd64-musl arm-musl arm64-musl" ["freebsd"]="amd64") declare -A BUILDS=(["linux"]="amd64 arm arm64 amd64-musl arm-musl arm64-musl" ["freebsd"]="amd64")
DOCKER_IMAGE=authelia/authelia DOCKER_IMAGE=authelia:dist
if [[ "${BUILDKITE_LABEL}" == ":hammer_and_wrench: Unit Test" ]]; then if [[ "${BUILDKITE_LABEL}" == ":hammer_and_wrench: Unit Test" ]]; then
if [[ ! "${BUILDKITE_BRANCH}" =~ ^renovate/ ]]; then if [[ ! "${BUILDKITE_BRANCH}" =~ ^renovate/ ]]; then

View File

@ -17,7 +17,7 @@ if [[ "${BUILDKITE_LABEL}" == ":service_dog: Linting" ]]; then
fi fi
if [[ "${BUILDKITE_LABEL}" == ":docker: Build Image [coverage]" ]]; then if [[ "${BUILDKITE_LABEL}" == ":docker: Build Image [coverage]" ]]; then
cp -R /buildkite/.pnpm-store . cp -R /buildkite/.local .
fi fi
if [[ "${BUILDKITE_STEP_KEY}" =~ build-deb-package-(arm64|armhf) && "${BUILDKITE_AGENT_NAME}" =~ sauron* ]]; then if [[ "${BUILDKITE_STEP_KEY}" =~ build-deb-package-(arm64|armhf) && "${BUILDKITE_AGENT_NAME}" =~ sauron* ]]; then
@ -30,10 +30,13 @@ fi
if [[ "${BUILDKITE_LABEL}" =~ ":selenium:" ]]; then if [[ "${BUILDKITE_LABEL}" =~ ":selenium:" ]]; then
DEFAULT_ARCH=coverage DEFAULT_ARCH=coverage
echo "--- :docker: Extract, load and tag build container" echo "--- :docker: Extract and load build container"
buildkite-agent artifact download "authelia-image-${DEFAULT_ARCH}*" . buildkite-agent artifact download "authelia-image-${DEFAULT_ARCH}*" .
if [[ "${SUITE}" == "Kubernetes" ]]; then
zstd -d authelia-image-coverage.tar.zst --stdout > ./internal/suites/example/kube/authelia-image-${DEFAULT_ARCH}.tar
else
zstdcat "authelia-image-${DEFAULT_ARCH}.tar.zst" | docker load zstdcat "authelia-image-${DEFAULT_ARCH}.tar.zst" | docker load
docker tag authelia/authelia authelia:dist fi
if [[ "${BUILD_DUO}" == "true" ]] && [[ "${SUITE}" == "DuoPush" ]]; then if [[ "${BUILD_DUO}" == "true" ]] && [[ "${SUITE}" == "DuoPush" ]]; then
CONTAINER="integration-duo" CONTAINER="integration-duo"

View File

@ -7,7 +7,11 @@ trim_trailing_whitespace = true
end_of_line = lf end_of_line = lf
insert_final_newline = true insert_final_newline = true
[{.buildkite/hooks/**,*.sh,*.yml,*.yaml}] [*.{sh,yml,yaml}]
indent_style = space
indent_size = 2
[.buildkite/hooks/**]
indent_style = space indent_style = space
indent_size = 2 indent_size = 2

View File

@ -26,6 +26,7 @@ body:
description: What version(s) of Authelia can you reproduce this bug on? description: What version(s) of Authelia can you reproduce this bug on?
multiple: true multiple: true
options: options:
- v4.37.3
- v4.37.2 - v4.37.2
- v4.37.1 - v4.37.1
- v4.37.0 - v4.37.0

39
.gitignore vendored
View File

@ -1,50 +1,27 @@
# IDE user configuration
.idea/
.vscode/
# NodeJs modules # Nodejs modules
.pnpm-store/
node_modules/ node_modules/
# npm debug logs
npm-debug.log*
# Coverage reports # Coverage reports
coverage/ coverage/
.nyc_output/
coverage.txt coverage.txt
.vscode/
*.swp
*~
# Directory used by example
/notifications/
# VSCode user configuration
.vscode/
# Generated by TypeScript compiler # Generated by TypeScript compiler
dist/ dist/
.nyc_output/
*.tgz
# Specific files # Specific files
/configuration.yml /configuration.yml
/config.yml /config.yml
/config.test.yml /config.test.yml
internal/suites/example/ldap/private.ldif
Configuration.schema.json
.suite .suite
.kube .kube
.idea authelia-image-dev.tar
.authelia-interrupt /authelia
qemu-*-static
public_html.gen.go
authelia
__debug_bin __debug_bin

View File

@ -1,4 +1,5 @@
{ {
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [ "extends": [
"config:base", "config:base",
":semanticCommitTypeAll(build)", ":semanticCommitTypeAll(build)",
@ -14,12 +15,15 @@
"workarounds:all" "workarounds:all"
], ],
"enabledManagers": [ "enabledManagers": [
"bundler",
"docker-compose", "docker-compose",
"dockerfile", "dockerfile",
"gomod", "gomod",
"kubernetes",
"npm" "npm"
], ],
"kubernetes": {
"fileMatch": ["kube/.+\\.yml$"],
},
"labels": [ "labels": [
"dependencies" "dependencies"
], ],
@ -47,6 +51,14 @@
"go" "go"
] ]
}, },
{
"datasources": [
"kubernetes"
],
"addLabels": [
"kubernetes"
]
},
{ {
"datasources": [ "datasources": [
"npm" "npm"

View File

@ -1,6 +1,13 @@
--- ---
extends: default extends: default
locale: en_US.UTF-8
yaml-files:
- '*.yaml'
- '*.yml'
- '.yamllint'
ignore: | ignore: |
docs/pnpm-lock.yaml docs/pnpm-lock.yaml
internal/configuration/test_resources/config_bad_quoting.yml internal/configuration/test_resources/config_bad_quoting.yml

View File

@ -2,7 +2,7 @@
Anybody willing to contribute to the project either with code, documentation, security reviews or whatever, are very Anybody willing to contribute to the project either with code, documentation, security reviews or whatever, are very
welcome to create or review pull requests and take part in discussions in any of our public welcome to create or review pull requests and take part in discussions in any of our public
[chat rooms](./README.md#contact-options). [chat rooms](README.md#contact-options).
It's also possible to contribute financially in order to support the community. It's also possible to contribute financially in order to support the community.
@ -42,4 +42,4 @@ Read more about this in the [GitHub docs, Re-requesting a review](https://docs.g
Sometimes the codebase can be a challenge to navigate, especially for a first-time contributor. We don't want you Sometimes the codebase can be a challenge to navigate, especially for a first-time contributor. We don't want you
spending an hour trying to work out something that would take us only a minute to explain. spending an hour trying to work out something that would take us only a minute to explain.
If you'd like some help getting started we have several [contact options](./README.md#contact-options) available. If you'd like some help getting started we have several [contact options](README.md#contact-options) available.

View File

@ -5,7 +5,7 @@ FROM node:19-alpine AS builder-frontend
WORKDIR /node/src/app WORKDIR /node/src/app
COPY .pnpm-store /root/.pnpm-store COPY .local /root/.local
COPY web ./ COPY web ./
# Install the dependencies and build # Install the dependencies and build
@ -15,7 +15,7 @@ RUN yarn global add pnpm && \
# ======================================= # =======================================
# ===== Build image for the backend ===== # ===== Build image for the backend =====
# ======================================= # =======================================
FROM golang:1.19.3-alpine AS builder-backend FROM golang:1.19.4-alpine AS builder-backend
WORKDIR /go/src/app WORKDIR /go/src/app

View File

@ -20,4 +20,4 @@ bootstrap.sh
# Overrides # Overrides
!.healthcheck.env !.healthcheck.env
!.pnpm-store !.local

View File

@ -13,7 +13,7 @@ RUN yarn install --frozen-lockfile && yarn build
# ======================================= # =======================================
# ===== Build image for the backend ===== # ===== Build image for the backend =====
# ======================================= # =======================================
FROM golang:1.19.3-alpine AS builder-backend FROM golang:1.19.4-alpine AS builder-backend
WORKDIR /go/src/app WORKDIR /go/src/app

View File

@ -184,7 +184,7 @@ Internet (your reverse proxies are) however, it's still the control plane for yo
## Contribute ## Contribute
If you want to contribute to Authelia, please read our [contribution guidelines](./CONTRIBUTING.md). If you want to contribute to Authelia, please read our [contribution guidelines](CONTRIBUTING.md).
Authelia exists thanks to all the people who contribute so don't be shy, come chat with us on either [Matrix](#matrix) Authelia exists thanks to all the people who contribute so don't be shy, come chat with us on either [Matrix](#matrix)
or [Discord](#discord) and start contributing too. or [Discord](#discord) and start contributing too.
@ -379,7 +379,7 @@ Companies contributing to Authelia via Open Collective will have a special menti
## License ## License
**Authelia** is **licensed** under the **[Apache 2.0]** license. The terms of the license are detailed in **Authelia** is **licensed** under the **[Apache 2.0]** license. The terms of the license are detailed in
[LICENSE](./LICENSE). [LICENSE](LICENSE).
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fauthelia%2Fauthelia.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fauthelia%2Fauthelia?ref=badge_large) [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fauthelia%2Fauthelia.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fauthelia%2Fauthelia?ref=badge_large)

View File

@ -19,14 +19,14 @@ For more information about [security](https://www.authelia.com/information/secur
## Contact Options ## Contact Options
Several [contact options](./README.md#contact-options) exist, it's important to make sure you contact the maintainers Several [contact options](README.md#contact-options) exist, it's important to make sure you contact the maintainers
privately which is described in each available contact method. The methods include our [security email](./README.md#security), privately which is described in each available contact method. The methods include our [security email](README.md#security),
[Matrix](./README.md#matrix), and [Discord](./README.md#discord). [Matrix](README.md#matrix), and [Discord](README.md#discord).
## Credit ## Credit
Users who report bugs will optionally be credited for the discovery. Both in the [security advisory] and in our Users who report bugs will optionally be credited for the discovery. Both in the [security advisory] and in our
[all contributors](./README.md#contribute) configuration/documentation. [all contributors](README.md#contribute) configuration/documentation.
## Process ## Process

File diff suppressed because it is too large Load Diff

View File

@ -87,12 +87,19 @@ var hostEntries = []HostEntry{
{Domain: "mail.example.com", IP: "192.168.240.100"}, {Domain: "mail.example.com", IP: "192.168.240.100"},
{Domain: "duo.example.com", IP: "192.168.240.100"}, {Domain: "duo.example.com", IP: "192.168.240.100"},
// For Traefik suite.
{Domain: "traefik.example.com", IP: "192.168.240.100"},
// For HAProxy suite. // For HAProxy suite.
{Domain: "haproxy.example.com", IP: "192.168.240.100"}, {Domain: "haproxy.example.com", IP: "192.168.240.100"},
// Kubernetes dashboard.
{Domain: "kubernetes.example.com", IP: "192.168.240.100"},
// OIDC tester app.
{Domain: "oidc.example.com", IP: "192.168.240.100"},
{Domain: "oidc-public.example.com", IP: "192.168.240.100"},
// For Traefik suite.
{Domain: "traefik.example.com", IP: "192.168.240.100"},
// For testing network ACLs. // For testing network ACLs.
{Domain: "proxy-client1.example.com", IP: "192.168.240.201"}, {Domain: "proxy-client1.example.com", IP: "192.168.240.201"},
{Domain: "proxy-client2.example.com", IP: "192.168.240.202"}, {Domain: "proxy-client2.example.com", IP: "192.168.240.202"},
@ -107,12 +114,6 @@ var hostEntries = []HostEntry{
{Domain: "redis-sentinel-0.example.com", IP: "192.168.240.120"}, {Domain: "redis-sentinel-0.example.com", IP: "192.168.240.120"},
{Domain: "redis-sentinel-1.example.com", IP: "192.168.240.121"}, {Domain: "redis-sentinel-1.example.com", IP: "192.168.240.121"},
{Domain: "redis-sentinel-2.example.com", IP: "192.168.240.122"}, {Domain: "redis-sentinel-2.example.com", IP: "192.168.240.122"},
// Kubernetes dashboard.
{Domain: "kubernetes.example.com", IP: "192.168.240.110"},
// OIDC tester app.
{Domain: "oidc.example.com", IP: "192.168.240.100"},
{Domain: "oidc-public.example.com", IP: "192.168.240.100"},
} }
func runCommand(cmd string, args ...string) { func runCommand(cmd string, args ...string) {
@ -151,8 +152,8 @@ func createTemporaryDirectory() {
func createPNPMDirectory() { func createPNPMDirectory() {
home := os.Getenv("HOME") home := os.Getenv("HOME")
if home != "" { if home != "" {
bootstrapPrintln("Creating ", home+"/.pnpm-store") bootstrapPrintln("Creating ", home+"/.local/share/pnpm/store")
err := os.MkdirAll(home+"/.pnpm-store", 0755) err := os.MkdirAll(home+"/.local/share/pnpm/store", 0755)
if err != nil { if err != nil {
panic(err) panic(err)
@ -161,7 +162,7 @@ func createPNPMDirectory() {
} }
func pnpmInstall() { func pnpmInstall() {
bootstrapPrintln("Installing web dependences ") bootstrapPrintln("Installing web dependencies ")
cwd, err := os.Getwd() cwd, err := os.Getwd()
if err != nil { if err != nil {

View File

@ -167,14 +167,14 @@ section [here](../prologue/common.md#tls-configuration).
Sets the base distinguished name container for all LDAP queries. If your LDAP domain is example.com this is usually Sets the base distinguished name container for all LDAP queries. If your LDAP domain is example.com this is usually
`DC=example,DC=com`, however you can fine tune this to be more specific for example to only include objects inside the `DC=example,DC=com`, however you can fine tune this to be more specific for example to only include objects inside the
authelia OU: `OU=authelia,DC=example,DC=com`. This is prefixed with the [additional_users_dn](#additional_users_dn) for authelia OU: `OU=authelia,DC=example,DC=com`. This is prefixed with the [additional_users_dn](#additionalusersdn) for
user searches and [additional_groups_dn](#additional_groups_dn) for groups searches. user searches and [additional_groups_dn](#additionalgroupsdn) for groups searches.
### additional_users_dn ### additional_users_dn
{{< confkey type="string" required="no" >}} {{< confkey type="string" required="no" >}}
Additional LDAP path to append to the [base_dn](#base_dn) when searching for users. Useful if you want to restrict Additional LDAP path to append to the [base_dn](#basedn) when searching for users. Useful if you want to restrict
exactly which OU to get users from for either security or performance reasons. For example setting it to exactly which OU to get users from for either security or performance reasons. For example setting it to
`OU=users,OU=people` with a base_dn set to `DC=example,DC=com` will mean user searches will occur in `OU=users,OU=people` with a base_dn set to `DC=example,DC=com` will mean user searches will occur in
`OU=users,OU=people,DC=example,DC=com`. `OU=users,OU=people,DC=example,DC=com`.
@ -184,28 +184,31 @@ exactly which OU to get users from for either security or performance reasons. F
{{< confkey type="string" required="situational" >}} {{< confkey type="string" required="situational" >}}
*__Note:__ This option is technically required however the [implementation](#implementation) option can implicitly set a *__Note:__ This option is technically required however the [implementation](#implementation) option can implicitly set a
default negating this requirement. Refer to the [filter defaults](#filter-defaults) for more information.* default negating this requirement. Refer to the [filter defaults](../../reference/guides/ldap.md#filter-defaults) for
more information.*
The LDAP filter to narrow down which users are valid. This is important to set correctly as to exclude disabled users. The LDAP filter to narrow down which users are valid. This is important to set correctly as to exclude disabled users.
The default value is dependent on the [implementation](#implementation), refer to the The default value is dependent on the [implementation](#implementation), refer to the
[attribute defaults](#attribute-defaults) for more information. [attribute defaults](../../reference/guides/ldap.md#attribute-defaults) for more information.
### username_attribute ### username_attribute
{{< confkey type="string" required="situational" >}} {{< confkey type="string" required="situational" >}}
*__Note:__ This option is technically required however the [implementation](#implementation) option can implicitly set a *__Note:__ This option is technically required however the [implementation](#implementation) option can implicitly set a
default negating this requirement. Refer to the [attribute defaults](#attribute-defaults) for more information.* default negating this requirement. Refer to the [attribute defaults](../../reference/guides/ldap.md#attribute-defaults)
for more information.*
The LDAP attribute that maps to the username in *Authelia*. This must contain the `{username_attribute}` The LDAP attribute that maps to the username in *Authelia*. This must contain the `{username_attribute}`
[placeholder](#users-filter-replacements). [placeholder](../../reference/guides/ldap.md#users-filter-replacements).
### mail_attribute ### mail_attribute
{{< confkey type="string" required="situational" >}} {{< confkey type="string" required="situational" >}}
*__Note:__ This option is technically required however the [implementation](#implementation) option can implicitly set a *__Note:__ This option is technically required however the [implementation](#implementation) option can implicitly set a
default negating this requirement. Refer to the [attribute defaults](#attribute-defaults) for more information.* default negating this requirement. Refer to the [attribute defaults](../../reference/guides/ldap.md#attribute-defaults)
for more information.*
The attribute to retrieve which contains the users email addresses. This is important for the device registration and The attribute to retrieve which contains the users email addresses. This is important for the device registration and
password reset processes. The user must have an email address in order for Authelia to perform identity verification password reset processes. The user must have an email address in order for Authelia to perform identity verification
@ -294,7 +297,7 @@ characters and the user password is changed to this value.
## Refresh Interval ## Refresh Interval
It's recommended you either use the default [refresh interval](./introduction.md#refresh_interval) or configure this to It's recommended you either use the default [refresh interval](introduction.md#refreshinterval) or configure this to
a value low enough to refresh the user groups and status (deleted, disabled, etc) to adequately secure your environment. a value low enough to refresh the user groups and status (deleted, disabled, etc) to adequately secure your environment.
## Important notes ## Important notes
@ -311,6 +314,6 @@ for your users.
- [LDAP Reference Guide](../../reference/guides/ldap.md) - [LDAP Reference Guide](../../reference/guides/ldap.md)
[username attribute]: #username_attribute [username attribute]: #usernameattribute
[TechNet wiki]: https://social.technet.microsoft.com/wiki/contents/articles/5392.active-directory-ldap-syntax-filters.aspx [TechNet wiki]: https://social.technet.microsoft.com/wiki/contents/articles/5392.active-directory-ldap-syntax-filters.aspx
[RFC2307]: https://www.rfc-editor.org/rfc/rfc2307.html [RFC2307]: https://www.rfc-editor.org/rfc/rfc2307.html

View File

@ -157,8 +157,8 @@ The HMAC secret used to sign the [JWT]'s. The provided string is hashed to a SHA
purpose of meeting the required format. purpose of meeting the required format.
It's __strongly recommended__ this is a It's __strongly recommended__ this is a
[Random Alphanumeric String](../../reference/guides/generating-secure-values.md#generating-a-random-alphanumeric-string) with 64 or more [Random Alphanumeric String](../../reference/guides/generating-secure-values.md#generating-a-random-alphanumeric-string)
characters. with 64 or more characters.
### issuer_certificate_chain ### issuer_certificate_chain
@ -173,7 +173,7 @@ as per [RFC7517].
[x5c]: https://www.rfc-editor.org/rfc/rfc7517#section-4.7 [x5c]: https://www.rfc-editor.org/rfc/rfc7517#section-4.7
[x5t]: https://www.rfc-editor.org/rfc/rfc7517#section-4.8 [x5t]: https://www.rfc-editor.org/rfc/rfc7517#section-4.8
The first certificate in the chain must have the public key for the [issuer_private_key](#issuer_private_key), each The first certificate in the chain must have the public key for the [issuer_private_key](#issuerprivatekey), each
certificate in the chain must be valid for the current date, and each certificate in the chain should be signed by the certificate in the chain must be valid for the current date, and each certificate in the chain should be signed by the
certificate immediately following it if present. certificate immediately following it if present.
@ -185,14 +185,15 @@ certificate immediately following it if present.
especially for containerized deployments.* especially for containerized deployments.*
The private key used to sign/encrypt the [OpenID Connect] issued [JWT]'s. The key must be generated by the administrator The private key used to sign/encrypt the [OpenID Connect] issued [JWT]'s. The key must be generated by the administrator
and can be done by following the [Generating an RSA Keypair](../../reference/guides/generating-secure-values.md#generating-an-rsa-keypair) guide. and can be done by following the
[Generating an RSA Keypair](../../reference/guides/generating-secure-values.md#generating-an-rsa-keypair) guide.
The private key *__MUST__*: The private key *__MUST__*:
* Be a PEM block encoded in the DER base64 format ([RFC4648]). * Be a PEM block encoded in the DER base64 format ([RFC4648]).
* Be an RSA Key. * Be an RSA Key.
* Have a key size of at least 2048 bits. * Have a key size of at least 2048 bits.
If the [issuer_certificate_chain](#issuer_certificate_chain) is provided the private key must include matching public If the [issuer_certificate_chain](#issuercertificatechain) is provided the private key must include matching public
key data for the first certificate in the chain. key data for the first certificate in the chain.
### access_token_lifespan ### access_token_lifespan
@ -302,7 +303,7 @@ you must configure this option manually if you want http endpoints to be permitt
Origins must only have the scheme, hostname and port, they may not have a trailing slash or path. Origins must only have the scheme, hostname and port, they may not have a trailing slash or path.
In addition to an Origin URI, you may specify the wildcard origin in the allowed_origins. It MUST be specified by itself In addition to an Origin URI, you may specify the wildcard origin in the allowed_origins. It MUST be specified by itself
and the [allowed_origins_from_client_redirect_uris](#allowed_origins_from_client_redirect_uris) MUST NOT be enabled. The and the [allowed_origins_from_client_redirect_uris](#allowedoriginsfromclientredirecturis) MUST NOT be enabled. The
wildcard origin is denoted as `*`. Examples: wildcard origin is denoted as `*`. Examples:
```yaml ```yaml
@ -422,7 +423,7 @@ Configures the consent mode. The following table describes the different modes:
| implicit | Automatically assumes consent for every authorization, never asking the user if they wish to give consent. *__Note:__* this option is not technically part of the specification. | | implicit | Automatically assumes consent for every authorization, never asking the user if they wish to give consent. *__Note:__* this option is not technically part of the specification. |
| pre-configured | Allows the end-user to remember their consent for the [pre_configured_consent_duration]. | | pre-configured | Allows the end-user to remember their consent for the [pre_configured_consent_duration]. |
[pre_configured_consent_duration]: #pre_configured_consent_duration [pre_configured_consent_duration]: #preconfiguredconsentduration
#### pre_configured_consent_duration #### pre_configured_consent_duration
@ -439,7 +440,7 @@ The period of time dictates how long a users choice to remember the pre-configur
Pre-configured consents are only valid if the subject, client id are exactly the same and the requested scopes/audience Pre-configured consents are only valid if the subject, client id are exactly the same and the requested scopes/audience
match exactly with the granted scopes/audience. match exactly with the granted scopes/audience.
[consent_mode]: #consent_mode [consent_mode]: #consentmode
#### audience #### audience

View File

@ -27,7 +27,7 @@ likely result in an error or even worse misconfiguration.
### Kubernetes ### Kubernetes
Please see the Please see the
[Kubernetes Integration: Enable Service Links](../../integration/kubernetes/introduction/index.md#enable-service-links) [Kubernetes Integration: Enable Service Links](../../integration/kubernetes/introduction.md#enable-service-links)
documentation for specific requirements for using *Authelia* with Kubernetes. documentation for specific requirements for using *Authelia* with Kubernetes.
## Mapping ## Mapping

View File

@ -55,15 +55,15 @@ other configuration using the environment but instead of loading a file the valu
{{% table-config-keys secrets="true" %}} {{% table-config-keys secrets="true" %}}
[server.tls.key]: ../miscellaneous/server.md#key [server.tls.key]: ../miscellaneous/server.md#key
[jwt_secret]: ../miscellaneous/introduction.md#jwt_secret [jwt_secret]: ../miscellaneous/introduction.md#jwtsecret
[duo_api.integration_key]: ../second-factor/duo.md#integration_key [duo_api.integration_key]: ../second-factor/duo.md#integrationkey
[duo_api.secret_key]: ../second-factor/duo.md#secret_key [duo_api.secret_key]: ../second-factor/duo.md#secretkey
[session.secret]: ../session/introduction.md#secret [session.secret]: ../session/introduction.md#secret
[session.redis.password]: ../session/redis.md#password [session.redis.password]: ../session/redis.md#password
[session.redis.tls.certificate_chain]: ../session/redis.md#tls [session.redis.tls.certificate_chain]: ../session/redis.md#tls
[session.redis.tls.private_key]: ../session/redis.md#tls [session.redis.tls.private_key]: ../session/redis.md#tls
[session.redis.high_availability.sentinel_password]: ../session/redis.md#sentinel_password [session.redis.high_availability.sentinel_password]: ../session/redis.md#sentinelpassword
[storage.encryption_key]: ../storage/introduction.md#encryption_key [storage.encryption_key]: ../storage/introduction.md#encryptionkey
[storage.mysql.password]: ../storage/mysql.md#password [storage.mysql.password]: ../storage/mysql.md#password
[storage.mysql.tls.certificate_chain]: ../storage/mysql.md#tls [storage.mysql.tls.certificate_chain]: ../storage/mysql.md#tls
[storage.mysql.tls.private_key]: ../storage/mysql.md#tls [storage.mysql.tls.private_key]: ../storage/mysql.md#tls
@ -77,9 +77,9 @@ other configuration using the environment but instead of loading a file the valu
[authentication_backend.ldap.password]: ../first-factor/ldap.md#password [authentication_backend.ldap.password]: ../first-factor/ldap.md#password
[authentication_backend.ldap.tls.certificate_chain]: ../first-factor/ldap.md#tls [authentication_backend.ldap.tls.certificate_chain]: ../first-factor/ldap.md#tls
[authentication_backend.ldap.tls.private_key]: ../first-factor/ldap.md#tls [authentication_backend.ldap.tls.private_key]: ../first-factor/ldap.md#tls
[identity_providers.oidc.issuer_certificate_chain]: ../identity-providers/open-id-connect.md#issuer_certificate_chain [identity_providers.oidc.issuer_certificate_chain]: ../identity-providers/open-id-connect.md#issuercertificatechain
[identity_providers.oidc.issuer_private_key]: ../identity-providers/open-id-connect.md#issuer_private_key [identity_providers.oidc.issuer_private_key]: ../identity-providers/open-id-connect.md#issuerprivatekey
[identity_providers.oidc.hmac_secret]: ../identity-providers/open-id-connect.md#hmac_secret [identity_providers.oidc.hmac_secret]: ../identity-providers/open-id-connect.md#hmacsecret
## Secrets in configuration file ## Secrets in configuration file

View File

@ -73,7 +73,7 @@ default_2fa_method: totp
especially for containerized deployments.* especially for containerized deployments.*
Defines the secret used to craft JWT tokens leveraged by the identity verification process. This can a random string. Defines the secret used to craft JWT tokens leveraged by the identity verification process. This can a random string.
It's strongly recommended this is a [Random Alphanumeric String](../../reference/guides/generating-secure-values.md/#generating-a-random-alphanumeric-string) with It's strongly recommended this is a [Random Alphanumeric String](../../reference/guides/generating-secure-values.md#generating-a-random-alphanumeric-string) with
64 or more characters. 64 or more characters.
### theme ### theme

View File

@ -68,4 +68,4 @@ Setting this to true will disable the startup check entirely.
Setting this to true will allow Authelia to start and just log an error instead of exiting. The default is that if Setting this to true will allow Authelia to start and just log an error instead of exiting. The default is that if
Authelia can contact the NTP server successfully, and the time reported by the server is greater than what is configured Authelia can contact the NTP server successfully, and the time reported by the server is greater than what is configured
in [max_desync](#max_desync) that Authelia fails to start and logs a fatal error. in [max_desync](#maxdesync) that Authelia fails to start and logs a fatal error.

View File

@ -123,7 +123,7 @@ require an IP address for the host of the backend service but want to verify a s
The key `skip_verify` completely negates validating the certificate of the backend service. This is not recommended, The key `skip_verify` completely negates validating the certificate of the backend service. This is not recommended,
instead you should tweak the `server_name` option, and the global option instead you should tweak the `server_name` option, and the global option
[certificates directory](../miscellaneous/introduction.md#certificates_directory). [certificates directory](../miscellaneous/introduction.md#certificatesdirectory).
### minimum_version ### minimum_version
@ -147,7 +147,7 @@ this value. At the time of this writing `SSL3.0` will always produce errors.
{{< confkey type="string" required="no" >}} {{< confkey type="string" required="no" >}}
The certificate chain/bundle to be used with the [private_key](#private_key) to perform mutual TLS authentication with The certificate chain/bundle to be used with the [private_key](#privatekey) to perform mutual TLS authentication with
the server. the server.
The value must be one or more certificates encoded in the DER base64 ([RFC4648]) encoded PEM format. The value must be one or more certificates encoded in the DER base64 ([RFC4648]) encoded PEM format.
@ -159,7 +159,7 @@ The value must be one or more certificates encoded in the DER base64 ([RFC4648])
*__Important Note:__ This can also be defined using a [secret](../methods/secrets.md) which is __strongly recommended__ *__Important Note:__ This can also be defined using a [secret](../methods/secrets.md) which is __strongly recommended__
especially for containerized deployments.* especially for containerized deployments.*
The private key to be used with the [certificate_chain](#certificate_chain) for mutual TLS authentication. The private key to be used with the [certificate_chain](#certificatechain) for mutual TLS authentication.
The value must be one private key encoded in the DER base64 ([RFC4648]) encoded PEM format. The value must be one private key encoded in the DER base64 ([RFC4648]) encoded PEM format.

View File

@ -73,7 +73,7 @@ environment variable or other environment variables set. This also applies to ot
*__Please Note:__ if you're using Authelia with Kubernetes and are not using the provided *__Please Note:__ if you're using Authelia with Kubernetes and are not using the provided
[helm chart](https://charts.authelia.com) you will be required to [helm chart](https://charts.authelia.com) you will be required to
[configure the enableServiceLinks](../../integration/kubernetes/introduction/index.md#enable-service-links) option.* [configure the enableServiceLinks](../../integration/kubernetes/introduction.md#enable-service-links) option.*
### 4.25.0 ### 4.25.0
@ -99,7 +99,7 @@ The following changes occurred in 4.7.0:
| logs_level | log_level | | logs_level | log_level |
| logs_file | log_file | | logs_file | log_file |
*__Please Note:__ The new keys also changed in [4.30.0](#4.30.0) so you will need to update them to the new values if you *__Please Note:__ The new keys also changed in [4.30.0](#4300) so you will need to update them to the new values if you
are using [4.30.0](#4.30.0) or newer instead of the new keys listed here.* are using [4.30.0](#4300) or newer instead of the new keys listed here.*
[YAML]: https://yaml.org/ [YAML]: https://yaml.org/

View File

@ -61,10 +61,12 @@ by Authelia from others.
*__Important Note:__ Many TOTP applications do not support this option. It is strongly advised you find out which *__Important Note:__ Many TOTP applications do not support this option. It is strongly advised you find out which
applications your users use and test them before changing this option. It is insufficient to test that the application applications your users use and test them before changing this option. It is insufficient to test that the application
can add the key, it must also authenticate with Authelia as some applications silently ignore these options. Bitwarden can add the key, it must also authenticate with Authelia as some applications silently ignore these options. [Bitwarden]
is the only one that has been tested at this time. If you'd like to contribute to documenting support for this option is the only one that has been tested at this time. If you'd like to contribute to documenting support for this option
please see [Issue 2650](https://github.com/authelia/authelia/issues/2650).* please see [Issue 2650](https://github.com/authelia/authelia/issues/2650).*
[Bitwarden]: https://bitwarden.com/
The algorithm used for the TOTP key. The algorithm used for the TOTP key.
Possible Values (case-insensitive): Possible Values (case-insensitive):
@ -82,7 +84,7 @@ information.
*__Important Note:__ Some TOTP applications do not support this option. It is strongly advised you find out which *__Important Note:__ Some TOTP applications do not support this option. It is strongly advised you find out which
applications your users use and test them before changing this option. It is insufficient to test that the application applications your users use and test them before changing this option. It is insufficient to test that the application
can add the key, it must also authenticate with Authelia as some applications silently ignore these options. Bitwarden can add the key, it must also authenticate with Authelia as some applications silently ignore these options. [Bitwarden]
is the only one that has been tested at this time. If you'd like to contribute to documenting support for this option is the only one that has been tested at this time. If you'd like to contribute to documenting support for this option
please see [Issue 2650](https://github.com/authelia/authelia/issues/2650).* please see [Issue 2650](https://github.com/authelia/authelia/issues/2650).*
@ -137,7 +139,7 @@ validations.
This means if the configuration options are changed, users will not need to regenerate their keys. This functionality This means if the configuration options are changed, users will not need to regenerate their keys. This functionality
takes effect from 4.33.0 onwards, previously the effect was the keys would just fail to validate. If you'd like to force takes effect from 4.33.0 onwards, previously the effect was the keys would just fail to validate. If you'd like to force
users to register a new device, you can delete the old device for a particular user by using the users to register a new device, you can delete the old device for a particular user by using the
`authelia storage totp delete <username>` command regardless of if you change the settings or not. `authelia storage user totp delete <username>` command regardless of if you change the settings or not.
## Input Validation ## Input Validation
@ -160,7 +162,7 @@ check the clients.
## Encryption ## Encryption
The TOTP secret is [encrypted](../storage/introduction.md#encryption_key) in the database in version 4.33.0 and above. The TOTP secret is [encrypted](../storage/introduction.md#encryptionkey) in the database in version 4.33.0 and above.
This is so a user having access to only the database cannot easily compromise your two-factor authentication method. This is so a user having access to only the database cannot easily compromise your two-factor authentication method.
This may be inconvenient for some users who wish to export TOTP keys from Authelia to other services. As such there is This may be inconvenient for some users who wish to export TOTP keys from Authelia to other services. As such there is
@ -170,19 +172,19 @@ at least a minimal configuration that has the storage backend connection details
Export in [Key URI Format](https://github.com/google/google-authenticator/wiki/Key-Uri-Format): Export in [Key URI Format](https://github.com/google/google-authenticator/wiki/Key-Uri-Format):
```bash ```bash
authelia storage totp export --format uri authelia storage user totp export --format uri
``` ```
Export as CSV: Export as CSV:
```bash ```bash
authelia storage totp export --format csv authelia storage user totp export --format csv
``` ```
Help: Help:
```bash ```bash
authelia storage totp export --help authelia storage user totp export --help
``` ```
[RFC4226]: https://www.rfc-editor.org/rfc/rfc4226.html [RFC4226]: https://www.rfc-editor.org/rfc/rfc4226.html

View File

@ -198,7 +198,7 @@ When used in conjunction with [domain] the rule will match when either the [doma
In addition to standard regex patterns this criteria can match some [Named Regex Groups]. In addition to standard regex patterns this criteria can match some [Named Regex Groups].
[domain_regex]: #domain_regex [domain_regex]: #domainregex
##### Examples ##### Examples
@ -339,7 +339,7 @@ access_control:
{{< confkey type="list(string)" required="no" >}} {{< confkey type="list(string)" required="no" >}}
This criteria is a list of values which can be an IP Address, network address range in CIDR notation, or an alias from This criteria is a list of values which can be an IP Address, network address range in CIDR notation, or an alias from
the [global](#networks-global) section. It matches against the first address in the `X-Forwarded-For` header, or if there the [global](#networks--global-) section. It matches against the first address in the `X-Forwarded-For` header, or if there
are none it will fall back to the IP address of the packet TCP source IP address. For this reason it's important for you are none it will fall back to the IP address of the packet TCP source IP address. For this reason it's important for you
to configure the proxy server correctly in order to accurately match requests with this criteria. *__Note:__ you may to configure the proxy server correctly in order to accurately match requests with this criteria. *__Note:__ you may
combine CIDR networks with the alias rules as you please.* combine CIDR networks with the alias rules as you please.*
@ -360,7 +360,7 @@ for administrators to tune the security to their specific needs if desired.
##### Examples ##### Examples
*Require [two_factor](#two_factor) for all clients other than internal clients and `112.134.145.167`. The first two *Require [two_factor](#twofactor) for all clients other than internal clients and `112.134.145.167`. The first two
rules in this list are effectively the same rule just expressed in different ways.* rules in this list are effectively the same rule just expressed in different ways.*
```yaml ```yaml
@ -485,7 +485,7 @@ access_control:
## Policies ## Policies
The policy of the first matching rule in the configured list decides the policy applied to the request, if no rule The policy of the first matching rule in the configured list decides the policy applied to the request, if no rule
matches the request the [default_policy](#default_policy) is applied. matches the request the [default_policy](#defaultpolicy) is applied.
[policies]: #policies [policies]: #policies
@ -510,14 +510,14 @@ about the subject is [one_factor]. See [Rule Matching Concept 2] for more inform
This policy requires the user at minimum complete 1FA successfully (username and password). This means if they have This policy requires the user at minimum complete 1FA successfully (username and password). This means if they have
performed 2FA then they will be allowed to access the resource. performed 2FA then they will be allowed to access the resource.
[one_factor]: #one_factor [one_factor]: #onefactor
### two_factor ### two_factor
This policy requires the user to complete 2FA successfully. This is currently the highest level of authentication This policy requires the user to complete 2FA successfully. This is currently the highest level of authentication
policy available. policy available.
[two_factor]: #two_factor [two_factor]: #twofactor
## Rule Matching ## Rule Matching
@ -554,7 +554,7 @@ a match for that request.
policy: two_factor policy: two_factor
``` ```
[Rule Matching Concept 1]: #rule-matching-concept-1-sequential-order [Rule Matching Concept 1]: #rule-matching-concept-1--sequential-order
### Rule Matching Concept 2: Subject Criteria Requires Authentication ### Rule Matching Concept 2: Subject Criteria Requires Authentication
@ -569,7 +569,7 @@ for authentication if no prior rules match the request per [Rule Matching Concep
identical rules, and one of them has a subject based reliant criteria, and the other one is a [bypass] rule then the identical rules, and one of them has a subject based reliant criteria, and the other one is a [bypass] rule then the
[bypass] rule should generally come first. [bypass] rule should generally come first.
[Rule Matching Concept 2]: #rule-matching-concept-2-subject-criteria-requires-authentication [Rule Matching Concept 2]: #rule-matching-concept-2--subject-criteria-requires-authentication
## Named Regex Groups ## Named Regex Groups

View File

@ -40,7 +40,7 @@ There are currently two providers for session storage (three if you count Redis
* Memory (default, stateful, no additional configuration) * Memory (default, stateful, no additional configuration)
* [Redis](redis.md) (stateless). * [Redis](redis.md) (stateless).
* [Redis Sentinel](redis.md#high_availability) (stateless, highly available). * [Redis Sentinel](redis.md#highavailability) (stateless, highly available).
### Kubernetes or High Availability ### Kubernetes or High Availability
@ -99,7 +99,7 @@ characters.
the [common options](../prologue/common.md#duration-notation-format) documentation for information on this format.* the [common options](../prologue/common.md#duration-notation-format) documentation for information on this format.*
The period of time before the cookie expires and the session is destroyed. This is overriden by The period of time before the cookie expires and the session is destroyed. This is overriden by
[remember_me_duration](#remember_me_duration) when the remember me box is checked. [remember_me_duration](#remembermeduration) when the remember me box is checked.
### inactivity ### inactivity

View File

@ -32,7 +32,7 @@ storage:
username: authelia username: authelia
password: mypassword password: mypassword
tls: tls:
server_name: psotgres.example.com server_name: postgres.example.com
skip_verify: false skip_verify: false
minimum_version: TLS1.2 minimum_version: TLS1.2
maximum_version: TLS1.3 maximum_version: TLS1.3

View File

@ -35,7 +35,7 @@ storage:
### encryption_key ### encryption_key
See the [encryption_key docs](introduction.md#encryption_key). See the [encryption_key docs](introduction.md#encryptionkey).
### path ### path

View File

@ -13,7 +13,7 @@ toc: true
--- ---
*Authelia* allows collecting telemetry for the purpose of monitoring it. At the present time we only allow collecting *Authelia* allows collecting telemetry for the purpose of monitoring it. At the present time we only allow collecting
[metrics](./metrics.md). These [metrics](./metrics.md) are stored in memory and must be scraped manually by the [metrics](metrics.md). These [metrics](metrics.md) are stored in memory and must be scraped manually by the
administrator. administrator.
No metrics or telemetry are reported from an *Authelia* binary to any location the administrator doesn't explicitly No metrics or telemetry are reported from an *Authelia* binary to any location the administrator doesn't explicitly

View File

@ -24,7 +24,7 @@ was not prompted by any bug bounty program as we do not have one, but we hope to
Potential usage for the money, ranked in order of priority: Potential usage for the money, ranked in order of priority:
1. Put Authelia through a comprehensive [Security Audit](../../../information/security.md#help-wanted). 1. Put Authelia through a comprehensive [Security Audit](../../policies/security.md#help-wanted).
1. Audit of Code Security via Analysis. 1. Audit of Code Security via Analysis.
2. Audit via Penetration Testing. 2. Audit via Penetration Testing.
2. Bug Bounty Program. 2. Bug Bounty Program.
@ -38,11 +38,11 @@ Please visit [Open Collective] in order to financially contribute to Authelia.
Authelia is sponsored by several companies via indirect means. These companies deserve a special mention since their Authelia is sponsored by several companies via indirect means. These companies deserve a special mention since their
contributions are very important to us but not easily visible. contributions are very important to us but not easily visible.
If you feel you have a product or service that Authelia could benefit from please feel free to [contact](../../../information/contact.md) us. If you feel you have a product or service that Authelia could benefit from please feel free to [contact](../../information/contact.md) us.
We are currently directly looking for someone to sponsor: We are currently directly looking for someone to sponsor:
* [Security Audit](../../../information/security.md#help-wanted) * [Security Audit](../../policies/security.md#help-wanted)
### Balto ### Balto

View File

@ -29,7 +29,7 @@ If the language you wish to translate is not on [Crowdin] then you have a few op
## Overrides ## Overrides
Users can override translations easily locally using the Users can override translations easily locally using the
[assets](../../configuration/miscellaneous/server.md#asset_path) directory. This is useful if you wish to perform a [assets](../../configuration/miscellaneous/server.md#assetpath) directory. This is useful if you wish to perform a
translation and see if it looks correct in the browser. translation and see if it looks correct in the browser.
[Crowdin]: https://translate.authelia.com [Crowdin]: https://translate.authelia.com

View File

@ -11,8 +11,8 @@ aliases:
## Security ## Security
If you believe you have identified a security related bug with Authelia please visit the [security policy](security.md) If you believe you have identified a security related bug with Authelia please visit the
documentation. [security policy](../policies/security.md) documentation.
## GitHub ## GitHub

View File

@ -42,10 +42,10 @@ It expects the following:
* The file `data/authelia/config/configuration.yml` is present and the configuration file. * The file `data/authelia/config/configuration.yml` is present and the configuration file.
* The directory `data/authelia/secrets/` exists and contain the relevant [secret](../../configuration/methods/secrets.md) files: * The directory `data/authelia/secrets/` exists and contain the relevant [secret](../../configuration/methods/secrets.md) files:
* A file named `JWT_SECRET` for the [jwt_secret](../../configuration/miscellaneous/introduction.md#jwt_secret) * A file named `JWT_SECRET` for the [jwt_secret](../../configuration/miscellaneous/introduction.md#jwtsecret)
* A file named `SESSION_SECRET` for the [session secret](../../configuration/session/introduction.md#secret) * A file named `SESSION_SECRET` for the [session secret](../../configuration/session/introduction.md#secret)
* A file named `STORAGE_PASSWORD` for the [PostgreSQL password secret](../../configuration/storage/postgres.md#password) * A file named `STORAGE_PASSWORD` for the [PostgreSQL password secret](../../configuration/storage/postgres.md#password)
* A file named `STORAGE_ENCRYPTION_KEY` for the [storage encryption_key secret](../../configuration/storage/introduction.md#encryption_key) * A file named `STORAGE_ENCRYPTION_KEY` for the [storage encryption_key secret](../../configuration/storage/introduction.md#encryptionkey)
* You're using PostgreSQL. * You're using PostgreSQL.
* You have an external network named `net` which is in bridge mode. * You have an external network named `net` which is in bridge mode.

View File

@ -15,7 +15,7 @@ toc: true
There are three main methods to deploy *Authelia*. There are three main methods to deploy *Authelia*.
1. [Docker](docker.md) 1. [Docker](docker.md)
2. [Kubernetes](../kubernetes/introduction/index.md) 2. [Kubernetes](../kubernetes/introduction.md)
3. [Bare-Metal](bare-metal.md) 3. [Bare-Metal](bare-metal.md)
## Get Started ## Get Started

View File

@ -15,4 +15,4 @@ search:
index: false index: false
--- ---
Please see the dedicated [Kubernetes Documentation](../kubernetes/introduction/index.md). Please see the dedicated [Kubernetes Documentation](../kubernetes/introduction.md).

View File

@ -30,7 +30,7 @@ Users are welcome to reach out directly by using any of our various [contact opt
## Get Started ## Get Started
It's __*strongly recommended*__ that users setting up *Authelia* for the first time take a look at our It's __*strongly recommended*__ that users setting up *Authelia* for the first time take a look at our
[Get Started](../../prologue/get-started) guide. This takes you through various steps which are essential to [Get Started](../prologue/get-started.md) guide. This takes you through various steps which are essential to
bootstrapping *Authelia*. bootstrapping *Authelia*.
## Important Notes ## Important Notes
@ -70,7 +70,7 @@ spec:
If using file-based authentication, the argon2id provider will by default use 1GB of RAM for password generation. This If using file-based authentication, the argon2id provider will by default use 1GB of RAM for password generation. This
means you should allow for at least this amount in your deployment/daemonset spec and have this much available on your means you should allow for at least this amount in your deployment/daemonset spec and have this much available on your
node, alternatively you can node, alternatively you can
[tweak the providers settings](../../../configuration/first-factor/file.md#memory). Otherwise, [tweak the providers settings](../../configuration/first-factor/file.md#memory). Otherwise,
your Authelia may OOM during login. See [here](https://github.com/authelia/authelia/issues/1234#issuecomment-663910799) your Authelia may OOM during login. See [here](https://github.com/authelia/authelia/issues/1234#issuecomment-663910799)
for more info. for more info.

View File

@ -86,7 +86,7 @@ metadata:
name: app name: app
namespace: default namespace: default
annotations: annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure traefik.ingress.kubernetes.io/router.entryPoints: websecure
traefik.ingress.kubernetes.io/router.middlewares: default-forwardauth-authelia@kubernetescrd traefik.ingress.kubernetes.io/router.middlewares: default-forwardauth-authelia@kubernetescrd
traefik.ingress.kubernetes.io/router.tls: "true" traefik.ingress.kubernetes.io/router.tls: "true"
spec: spec:

View File

@ -111,7 +111,7 @@ Below is a list of the potential values we place in the [Claim] and their meanin
## User Information Signing Algorithm ## User Information Signing Algorithm
The following table describes the response from the [UserInfo] endpoint depending on the The following table describes the response from the [UserInfo] endpoint depending on the
[userinfo_signing_algorithm](../../configuration/identity-providers/open-id-connect.md#userinfo_signing_algorithm). [userinfo_signing_algorithm](../../configuration/identity-providers/open-id-connect.md#userinfosigningalgorithm).
| Signing Algorithm | Encoding | Content Type | | Signing Algorithm | Encoding | Content Type |
|:-----------------:|:------------:|:-----------------------------------:| |:-----------------:|:------------:|:-----------------------------------:|

View File

@ -38,9 +38,9 @@ used as a basis for configuration.
The important sections to consider in initial configuration are as follows: The important sections to consider in initial configuration are as follows:
1. [jwt_secret](../../configuration/miscellaneous/introduction.md#jwt_secret) which is used to sign identity 1. [jwt_secret](../../configuration/miscellaneous/introduction.md#jwtsecret) which is used to sign identity
verification emails verification emails
2. [default_redirection_url](../../configuration/miscellaneous/introduction.md#default_redirection_url) which is the 2. [default_redirection_url](../../configuration/miscellaneous/introduction.md#defaultredirectionurl) which is the
default URL users will be redirected to when visiting *Authelia* directly default URL users will be redirected to when visiting *Authelia* directly
3. [authentication_backend](../../configuration/first-factor/introduction.md) which you must pick between 3. [authentication_backend](../../configuration/first-factor/introduction.md) which you must pick between
[LDAP](../../configuration/first-factor/ldap.md) and a [YAML File](../../configuration/first-factor/file.md) and is [LDAP](../../configuration/first-factor/ldap.md) and a [YAML File](../../configuration/first-factor/file.md) and is
@ -76,8 +76,8 @@ There are several methods of deploying *Authelia* and we recommend reading the
The default method of utilizing *Authelia* is via the [Proxy Integrations](../proxies/introduction.md). It's The default method of utilizing *Authelia* is via the [Proxy Integrations](../proxies/introduction.md). It's
recommended that you read the relevant [Proxy Integration Documentation](../proxies/introduction.md). recommended that you read the relevant [Proxy Integration Documentation](../proxies/introduction.md).
*__Important Note:__ When your [Deployment](#deployment) is on [Kubernetes](../kubernetes/introduction/index.md) we *__Important Note:__ When your [Deployment](#deployment) is on [Kubernetes](../kubernetes/introduction.md) we
recommend viewing the dedicated [Kubernetes Documentation](../kubernetes/introduction/index.md) prior to viewing the recommend viewing the dedicated [Kubernetes Documentation](../kubernetes/introduction.md) prior to viewing the
[Proxy Integration Documentation](../proxies/introduction.md).* [Proxy Integration Documentation](../proxies/introduction.md).*
## Moving to Production ## Moving to Production

View File

@ -24,12 +24,12 @@ throughout this documentation and in the [See Also](#see-also) section.*
## Get Started ## Get Started
It's __*strongly recommended*__ that users setting up *Authelia* for the first time take a look at our It's __*strongly recommended*__ that users setting up *Authelia* for the first time take a look at our
[Get Started](../prologue/get-started.md) guide. This takes you through various steps which are essential to [Get Started](../../prologue/get-started.md) guide. This takes you through various steps which are essential to
bootstrapping *Authelia*. bootstrapping *Authelia*.
## Requirements ## Requirements
[NGINX Proxy Manager] supports the required [NGINX](nginx.md#requirements) requirements for __Authelia__ out-of-the-box. [NGINX Proxy Manager] supports the required [NGINX](../nginx.md#requirements) requirements for __Authelia__ out-of-the-box.
## Trusted Proxies ## Trusted Proxies
@ -37,7 +37,7 @@ bootstrapping *Authelia*.
Especially if you have never read it before.* Especially if you have never read it before.*
To configure trusted proxies for [NGINX Proxy Manager] see the [NGINX] section on To configure trusted proxies for [NGINX Proxy Manager] see the [NGINX] section on
[Trusted Proxies](nginx.md#trusted-proxies). Adapting this to [NGINX Proxy Manager] is beyond the scope of [Trusted Proxies](../nginx.md#trusted-proxies). Adapting this to [NGINX Proxy Manager] is beyond the scope of
this documentation. this documentation.
## Docker Compose ## Docker Compose
@ -137,9 +137,9 @@ either most likely require an adjustment, or may require an adjustment if you're
### Snippets ### Snippets
The examples assume you've mounted a volume containing the relevant The examples assume you've mounted a volume containing the relevant
[NGINX Snippets](nginx.md#supporting-configuration-snippets) from the [NGINX Integration Guide](nginx.md). The suggested [NGINX Snippets](../nginx.md#supporting-configuration-snippets) from the [NGINX Integration Guide](../nginx.md). The
snippets are the `proxy.conf`, `authelia-location.conf`, and `authelia-authrequest.conf`. It may be fine to substitute suggested snippets are the `proxy.conf`, `authelia-location.conf`, and `authelia-authrequest.conf`. It may be fine to
the standard variant of the `proxy.conf` for the headers only variant but this is untested. substitute the standard variant of the `proxy.conf` for the headers only variant but this is untested.
These snippets make the addition of a protected proxy host substantially easier. These snippets make the addition of a protected proxy host substantially easier.

View File

@ -62,7 +62,7 @@ required modules including the `http_set_misc` module.
It also includes the [nginx-proxy-confs](https://github.com/linuxserver/docker-mods/tree/nginx-proxy-confs) mod where It also includes the [nginx-proxy-confs](https://github.com/linuxserver/docker-mods/tree/nginx-proxy-confs) mod where
they have several configuration examples in the `/config/nginx/proxy-confs` directory. This can be omitted if desired. they have several configuration examples in the `/config/nginx/proxy-confs` directory. This can be omitted if desired.
If you're looking for a more complete solution [linuxserver.io] also have an nginx container called [SWAG](./swag.md) If you're looking for a more complete solution [linuxserver.io] also have an nginx container called [SWAG](swag.md)
which includes ACME and various other useful utilities. which includes ACME and various other useful utilities.
{{< details "docker-compose.yaml" >}} {{< details "docker-compose.yaml" >}}

View File

@ -76,7 +76,7 @@ For example the nginx ngx_http_auth_request_module does not seem to support this
Authelia detects the upstream request method using the X-Forwarded-Method header. Some proxies set this out of the box, Authelia detects the upstream request method using the X-Forwarded-Method header. Some proxies set this out of the box,
some require you to configure this manually. At the present time all proxies that have some require you to configure this manually. At the present time all proxies that have
[Standard Support](#standard-support) do support this. [Standard Support](#standard) do support this.
## Specific proxy notes ## Specific proxy notes

View File

@ -77,7 +77,7 @@ required modules including the `http_set_misc` module.
It also includes the [nginx-proxy-confs](https://github.com/linuxserver/docker-mods/tree/nginx-proxy-confs) mod where It also includes the [nginx-proxy-confs](https://github.com/linuxserver/docker-mods/tree/nginx-proxy-confs) mod where
they have several configuration examples in the `/config/nginx/proxy-confs` directory. This can be omitted if desired. they have several configuration examples in the `/config/nginx/proxy-confs` directory. This can be omitted if desired.
If you're looking for a more complete solution [linuxserver.io] also have an nginx container called [SWAG](./swag.md) If you're looking for a more complete solution [linuxserver.io] also have an nginx container called [SWAG](swag.md)
which includes ACME and various other useful utilities. which includes ACME and various other useful utilities.
{{< details "docker-compose.yaml" >}} {{< details "docker-compose.yaml" >}}

View File

@ -25,8 +25,8 @@ unreliable and simple usernames and passwords are not sufficient for security.
__Authelia__ enables primarily two-factor authentication. These methods offered come in two forms: __Authelia__ enables primarily two-factor authentication. These methods offered come in two forms:
* 1FA or first-factor authentication which is handled by a username and password. This falls into the *something you know* * 1FA or first-factor authentication which is handled by a username and password. This falls into the
categorization. *something you know* categorization.
* 2FA or second-factor authentication which is handled by several methods including one-time passwords, authentication * 2FA or second-factor authentication which is handled by several methods including one-time passwords, authentication
keys, etc. This falls into the *something you have* categorization. keys, etc. This falls into the *something you have* categorization.

View File

@ -28,14 +28,7 @@ the user must match the name of the user in Authelia, or must have an alias that
Then, in Duo interface, click on *Applications* and *Protect an Application*. Select the option *Partner Auth API*. This Then, in Duo interface, click on *Applications* and *Protect an Application*. Select the option *Partner Auth API*. This
will generate an integration key, a secret key and a hostname. You can set the name of the application to __Authelia__ will generate an integration key, a secret key and a hostname. You can set the name of the application to __Authelia__
and then you must add the generated information to Authelia [configuration](../../deployment/index.md) as shown below: and then you must add the generated information to Authelia [configuration](../../../configuration/second-factor/duo.md).
```yaml
duo_api:
hostname: api-123456789.example.com
integration_key: ABCDEF
secret_key: 1234567890abcdefghifjkl
```
See the [configuration documentation](../../../configuration/second-factor/duo.md) for more details. See the [configuration documentation](../../../configuration/second-factor/duo.md) for more details.

View File

@ -1,7 +1,7 @@
--- ---
title: "OpenID Connect 1.0" title: "OpenID Connect 1.0"
description: "OpenID Connect 1.0 is a authorization identity framework supported by Authelia." description: "OpenID Connect 1.0 is a authorization identity framework supported by Authelia."
date: 2022-06-15T17:51:47+10:00 date: 2022-11-27T16:07:08+11:00
draft: false draft: false
images: [] images: []
menu: menu:

View File

@ -2,7 +2,7 @@
title: "Trusted Headers SSO" title: "Trusted Headers SSO"
description: "Trusted Headers SSO is a simple header authorization framework supported by Authelia." description: "Trusted Headers SSO is a simple header authorization framework supported by Authelia."
lead: "Trusted Headers is a simple header authorization framework supported by Authelia." lead: "Trusted Headers is a simple header authorization framework supported by Authelia."
date: 2022-06-15T17:51:47+10:00 date: 2022-11-27T16:07:08+11:00
draft: false draft: false
images: [] images: []
menu: menu:

View File

@ -53,6 +53,6 @@ Authelia only works for websites served over HTTPS because the session cookie ca
connections. Please note that it has been decided that we won't support websites served over HTTP in order to avoid any connections. Please note that it has been decided that we won't support websites served over HTTP in order to avoid any
risk due to misconfiguration (see [#590](https://github.com/authelia/authelia/issues/590)). risk due to misconfiguration (see [#590](https://github.com/authelia/authelia/issues/590)).
If a self-signed certificate is required, the If a self-signed certificate is required, the [Generating an RSA Self-Signed Certificate] guide should be followed.
[Generating an RSA Self-Signed Certificate](../../../reference/guides/generating-secure-values.md#generating-an-rsa-self-signed-certificate)
guide should be followed. [Generating an RSA Self-Signed Certificate]: ../../../reference/guides/generating-secure-values.md#generating-an-rsa-self-signed-certificate

View File

@ -73,7 +73,7 @@ attacker obtains the file, each password has to be brute forced individually.
Lastly Authelia's implementation of Argon2id is highly tunable. You can tune the key length, salt used, iterations Lastly Authelia's implementation of Argon2id is highly tunable. You can tune the key length, salt used, iterations
(time), parallelism, and memory usage. To read more about this please read how to (time), parallelism, and memory usage. To read more about this please read how to
[configure](../configuration/authentication/file.md) file authentication. [configure](../../configuration/first-factor/file.md) file authentication.
## User profile and group membership always kept up-to-date (LDAP authentication provider) ## User profile and group membership always kept up-to-date (LDAP authentication provider)
@ -163,33 +163,34 @@ preferable:
### Configuration Option: certificates_directory ### Configuration Option: certificates_directory
You can [configure a directory](../../configuration/miscellaneous/introduction.md#certificates_directory) of You can configure a [certificates_directory] option which contains certificates for Authelia to trust. These certificates
certificates for Authelia can either be CA's or individual public certificates that should be trusted. These are added in addition to the
to trust. These certificates can either be CA's or individual public certificates that should be trusted. These environments PKI trusted certificates if available. This is useful for trusting a certificate that is self-signed without
are added in addition to the environments PKI trusted certificates if available. This is useful for trusting a drastically reducing security. This is the most recommended workaround to not having a valid PKI trusted certificate as
certificate that is self-signed without drastically reducing security. This is the most recommended workaround to not it gives you complete control over which ones are trusted without disabling critically needed validation of the identity
having a valid PKI trusted certificate as it gives you complete control over which ones are trusted without disabling of the target service.
critically needed validation of the identity of the target service.
Read more in the [documentation](../../configuration/miscellaneous/introduction.md#certificates_directory) for this Read more in the [certificates_directory] documentation for this option.
option.
[certificates_directory]: ../../configuration/miscellaneous/introduction.md#certificatesdirectory
[certificates directory]: #configuration-option--certificatesdirectory
### Configuration Option: tls.skip_verify ### Configuration Option: tls.skip_verify
The [tls.skip_verify](../../configuration/notifications/smtp.md#tls) option allows you to skip verifying the certificate The [tls.skip_verify](../../configuration/notifications/smtp.md#tls) option allows you to skip verifying the certificate
entirely which is why [certificates_directory](#configuration-option-certificates_directory) is preferred over this. entirely which is why [certificates directory] is preferred over this. This will effectively mean you cannot be sure the
This will effectively mean you cannot be sure the certificate is valid which means an attacker via DNS poisoning or MITM certificate is valid which means an attacker via DNS poisoning or MITM attacks could intercept emails from Authelia
attacks could intercept emails from Authelia compromising a user's security without their knowledge. compromising a user's security without their knowledge.
### Configuration Option: disable_require_tls ### Configuration Option: disable_require_tls
Authelia by default ensures that the SMTP server connection is secured via TLS prior to sending sensitive information. Authelia by default ensures that the SMTP server connection is secured via TLS prior to sending sensitive information.
The [disable_require_tls](../../configuration/notifications/smtp.md#disable_require_tls) option disables this The [disable_require_tls](../../configuration/notifications/smtp.md#disablerequiretls) option disables this
requirement which means the emails may be sent in cleartext. This is the least secure option as it effectively removes requirement which means the emails may be sent in cleartext. This is the least secure option as it effectively removes
the validation of SMTP certificates and makes using an encrypted connection with TLS optional. the validation of SMTP certificates and makes using an encrypted connection with TLS optional.
This means not only can the vulnerabilities of the [skip_verify](#configuration-option-tlsskip_verify) option be This means not only can the vulnerabilities of the [skip_verify](#configuration-option--tlsskipverify) option be
exploited, but any router or switch along the route of the email which receives the packets could be used to silently exploited, but any router or switch along the route of the email which receives the packets could be used to silently
exploit the cleartext nature of the connection to manipulate the email in transit. exploit the cleartext nature of the connection to manipulate the email in transit.
@ -237,7 +238,7 @@ would not even be able to create a TCP connection. This measure is recommended i
configured some kind of ACLs specifically allowing the communication between proxies and Authelia instances like in a configured some kind of ACLs specifically allowing the communication between proxies and Authelia instances like in a
service mesh or some kind of network overlay. service mesh or some kind of network overlay.
To configure mutual TLS, please refer to [this document](../../configuration/miscellaneous/server.md#client_certificates) To configure mutual TLS, please refer to [this document](../../configuration/miscellaneous/server.md#clientcertificates)
## Additional security ## Additional security
@ -255,7 +256,7 @@ database. The value of this option should be long and as random as possible. See
[documentation](../../configuration/session/introduction.md#secret) for this option. [documentation](../../configuration/session/introduction.md#secret) for this option.
The validity period of session is highly configurable. For example in a highly security conscious domain you could The validity period of session is highly configurable. For example in a highly security conscious domain you could
set the session [remember_me_duration](../../configuration/session/introduction.md#remember_me_duration) to 0 to disable this set the session [remember_me_duration](../../configuration/session/introduction.md#remembermeduration) to 0 to disable this
feature, and set the [expiration](../../configuration/session/introduction.md#expiration) to 2 hours and the feature, and set the [expiration](../../configuration/session/introduction.md#expiration) to 2 hours and the
[inactivity](../../configuration/session/introduction.md#inactivity) of 10 minutes. Configuring the session security in this [inactivity](../../configuration/session/introduction.md#inactivity) of 10 minutes. Configuring the session security in this
manner would mean if the cookie age was more than 2 hours or if the user was inactive for more than 10 minutes the manner would mean if the cookie age was more than 2 hours or if the user was inactive for more than 10 minutes the

View File

@ -37,11 +37,11 @@ This is the preferred method of reporting.
### Chat ### Chat
If you wish to chat directly instead of sending an email please use one of the [chat options](../information/contact.md#chat) but it If you wish to chat directly instead of sending an email please use one of the
is vital that when you do that you only do so privately with one of the maintainers. In order to start a private [chat options](../information/contact.md#chat) but it is vital that when you do that you only do so privately with one
discussion you should ask to have a private discussion with a team member without mentioning the reason why you wish to of the maintainers. In order to start a private discussion you should ask to have a private discussion with a team
have a private discussion so that provided the bug is confirmed we can coordinate the release of fixes and information member without mentioning the reason why you wish to have a private discussion so that provided the bug is confirmed we
responsibly. can coordinate the release of fixes and information responsibly.
## Credit ## Credit

View File

@ -48,7 +48,7 @@ The logo is just the Authelia circle logo without any text.
#### Logo Files #### Logo Files
[PSD](https://www.authelia.com/images/branding/logo.psd) | [SVG](https://www.authelia.com/images/branding/logo.svg) | [PNG](https://www.authelia.com/images/branding/logo.png) [PSD](https://www.authelia.com/images/branding/logo.psd) | [AI](https://www.authelia.com/images/branding/logo.ai) | [SVG](https://www.authelia.com/images/branding/logo.svg) | [PNG](https://www.authelia.com/images/branding/logo.png)
#### Logo Example #### Logo Example
@ -60,7 +60,7 @@ The logo is the same as the standard logo without padding.
#### Logo (Cropped) Files #### Logo (Cropped) Files
[PSD](https://www.authelia.com/images/branding/logo-cropped.psd) | [SVG](https://www.authelia.com/images/branding/logo-cropped.svg) | [PNG](https://www.authelia.com/images/branding/logo-cropped.png) [PSD](https://www.authelia.com/images/branding/logo-cropped.psd) | [AI](https://www.authelia.com/images/branding/logo-cropped.ai) | [SVG](https://www.authelia.com/images/branding/logo-cropped.svg) | [PNG](https://www.authelia.com/images/branding/logo-cropped.png)
#### Logo (Cropped) Example #### Logo (Cropped) Example
@ -72,7 +72,7 @@ The title is the Authelia circle logo with the `authelia` branded text.
#### Title Files #### Title Files
[PSD](https://www.authelia.com/images/branding/title.psd) | [SVG](https://www.authelia.com/images/branding/title.svg) | [PNG](https://www.authelia.com/images/branding/title.png) [PSD](https://www.authelia.com/images/branding/title.psd) | [AI](https://www.authelia.com/images/branding/title.ai) | [SVG](https://www.authelia.com/images/branding/title.svg) | [PNG](https://www.authelia.com/images/branding/title.png)
#### Title Example #### Title Example

View File

@ -22,7 +22,7 @@ The most insecure method is unauthenticated binds. They are generally considered
at all ensures anyone with any level of network access can easily obtain objects and their attributes. at all ensures anyone with any level of network access can easily obtain objects and their attributes.
Authelia does support unauthenticated binds but it is not by default, you must configure the Authelia does support unauthenticated binds but it is not by default, you must configure the
[permit_unauthenticated_bind](../../configuration/first-factor/ldap.md#permit_unauthenticated_bind) configuration [permit_unauthenticated_bind](../../configuration/first-factor/ldap.md#permitunauthenticatedbind) configuration
option. option.
### End-User Binding ### End-User Binding
@ -95,15 +95,16 @@ be appreciated). The userAccountControl filter checks that the account is not di
value is not 0 which means the password requires changing at the next login. value is not 0 which means the password requires changing at the next login.
| Implementation | Users Filter | Groups Filter | | Implementation | Users Filter | Groups Filter |
|:---------------:|:---------------------------------------------------------------------------------------------------------------------------------------------------------------:|:------------------------------------------:| |:---------------:|:---------------------------------------------------------------------------------------------------------------------------------------------------------------:|:----------------------------------------------------------------------------:|
| custom | N/A | N/A | | custom | N/A | N/A |
| activedirectory | (&(&#124;({username_attribute}={input})({mail_attribute}={input}))(sAMAccountType=805306368)(!(userAccountControl:1.2.840.113556.1.4.803:=2))(!(pwdLastSet=0))) | (&(member={dn})(sAMAccountType=268435456)) | | activedirectory | (&(&#124;({username_attribute}={input})({mail_attribute}={input}))(sAMAccountType=805306368)(!(userAccountControl:1.2.840.113556.1.4.803:=2))(!(pwdLastSet=0))) | (&(member={dn})(&#124;(sAMAccountType=268435456)(sAMAccountType=536870912))) |
##### Microsoft Active Directory sAMAccountType ##### Microsoft Active Directory sAMAccountType
| Account Type Value | Description | Equivalent Filter | | Account Type Value | Description | Equivalent Filter |
|:------------------:|:--------------------------:|:----------------------------------------------:| |:------------------:|:---------------------------------------:|:----------------------------------------------:|
| 268435456 | Normal Group Objects | N/A | | 268435456 | Global/Universal Security Group Objects | N/A |
| 536870912 | Domain Local Security Group Objects | N/A |
| 805306368 | Normal User Accounts | `(&(objectCategory=person)(objectClass=user))` | | 805306368 | Normal User Accounts | `(&(objectCategory=person)(objectClass=user))` |
*__References:__* *__References:__*

View File

@ -16,7 +16,7 @@ Authelia uses templates to generate the HTML and plaintext emails sent via the n
two extensions; `.html` for HTML templates, and `.txt` for plaintext templates. two extensions; `.html` for HTML templates, and `.txt` for plaintext templates.
This guide effectively documents the usage of the This guide effectively documents the usage of the
[template_path](../../configuration/notifications/introduction.md#template_path) notification configuration option. [template_path](../../configuration/notifications/introduction.md#templatepath) notification configuration option.
## Important Notes ## Important Notes
@ -37,7 +37,7 @@ This guide effectively documents the usage of the
| PasswordReset | Used to render notifications sent when password has successfully been reset | | PasswordReset | Used to render notifications sent when password has successfully been reset |
For example, to modify the `IdentityVerification` HTML template, if your For example, to modify the `IdentityVerification` HTML template, if your
[template_path](../../configuration/notifications/introduction.md#template_path) was configured as [template_path](../../configuration/notifications/introduction.md#templatepath) was configured as
`/config/email_templates`, you would create the `/config/email_templates/IdentityVerification.html` file to override the `/config/email_templates`, you would create the `/config/email_templates/IdentityVerification.html` file to override the
HTML `IdentityVerification` template. HTML `IdentityVerification` template.

View File

@ -156,7 +156,7 @@ See the [Crypt (C) Wiki page](https://en.wikipedia.org/wiki/Crypt_(C)) for more
#### Tuning #### Tuning
The configuration variables are unique to the file authentication provider, thus they all exist in a key under the file The configuration variables are unique to the file authentication provider, thus they all exist in a key under the file
authentication configuration key called [password](../../configuration/first-factor/file.md#password). The defaults are authentication configuration key called [password](../../configuration/first-factor/file.md#password-options). The defaults are
considered as sane for a reasonable system however we still recommend taking time to figure out the best values to considered as sane for a reasonable system however we still recommend taking time to figure out the best values to
adequately determine the [cost](#cost). adequately determine the [cost](#cost).

View File

@ -27,7 +27,7 @@ This guide effectively documents the usage of the
## Assets ## Assets
| Asset | File Name | Directory | Notes | | Asset | File Name | Directory | Notes |
|:-------------------:|:-----------:|:---------:|:-------------:| |:-------------------:|:-----------:|:---------:|:-----------------------:|
| Favicon | favicon.ico | No | N/A | | Favicon | favicon.ico | No | N/A |
| Logo | logo.png | No | N/A | | Logo | logo.png | No | N/A |
| Translation Locales | locales | Yes | see [locales](#locales) | | Translation Locales | locales | Yes | see [locales](#locales) |

View File

@ -12,7 +12,6 @@ weight: 220
toc: true toc: true
aliases: aliases:
- /r/sanitize - /r/sanitize
- /reference/guides/domain-sanitizaiton
--- ---
Some users may wish to hide their domain in files provided during troubleshooting. While this is discouraged, if a user Some users may wish to hide their domain in files provided during troubleshooting. While this is discouraged, if a user

View File

@ -0,0 +1,40 @@
---
title: "Cache Integrations"
description: "A cache integration reference guide"
lead: "This section contains a cache integration reference guide for Authelia."
date: 2022-11-19T16:47:09+11:00
draft: false
images: []
menu:
reference:
parent: "integrations"
weight: 320
toc: true
---
We currently only support [Redis Standalone] and [Redis Sentinel] for cached information like sessions
(other than in-memory).
## Redis
The following is guidance on versions of [Redis] supported.
### Standalone
When it comes to [Redis Standalone] we support the versions supported by [Redis] themselves which can be found in the
[Redis release cycle](https://redis.io/docs/about/releases/) documentation. This is typically the latest available
version.
### Sentinel
When it comes to [Redis Sentinel] we support the versions supported by [Redis] themselves which can be found in the
[Redis release cycle](https://redis.io/docs/about/releases/) documentation. This is typically the latest available
version.
_**Note:** Currently we only support [Redis Sentinel] version 6.x due to a breaking change to [Redis Sentinel] in
version 7.x. This will be resolved in the near future._
[Redis]: https://redis.io/
[Redis Standalone]: https://redis.io/docs/getting-started/
[Redis Sentinel]: https://redis.io/docs/management/sentinel/

View File

@ -15,16 +15,29 @@ toc: true
We generally recommend using [PostgreSQL] for a database. If high availability is not a consideration we also support We generally recommend using [PostgreSQL] for a database. If high availability is not a consideration we also support
[SQLite3]. [SQLite3].
It is also a general recommendation that if you're using [PostgreSQL], [MySQL], or [MariaDB]; that you do not
automatically upgrade the major/minor version of these databases, and pin the image tag so at most the patch version
is updated. For example for database version `x.y.z` only the `z` should change, `x` and `y` should remain the same.
It is also generally recommended that you do not rely on automatic update tools to perform this action
unless you are sure they shut down the container properly (i.e. with a graceful stop).
While this guide exists and it contains some guidance on managing the database being used, it is by no means exhaustive
or intended as such and users should refer to the database vendors documentation.
## PostgreSQL ## PostgreSQL
The only current support criteria for [PostgreSQL] at present is that the version you're using is supported by the The only current support criteria for [PostgreSQL] at present is that the version you're using is supported by the
[PostgreSQL] developers. See their [Versioning Policy](https://www.postgresql.org/support/versioning/) for more [PostgreSQL] developers. See [Vendor Supported Versions](#vendor-supported-versions) more information.
information.
We generally perform integration testing against the latest supported version of [PostgreSQL] and that is generally the We generally perform integration testing against the latest supported version of [PostgreSQL] and that is generally the
recommended version for new installations. recommended version for new installations.
### Vendor Supported Versions
See the [PostgreSQL Versioning Policy](https://www.postgresql.org/support/versioning/) for information on the versions
and platforms that are currently supported by this vendor.
## MySQL ## MySQL
[MySQL] and [MariaDB] are both supported as part of the [MySQL] implementation. This is generally discouraged as [MySQL] and [MariaDB] are both supported as part of the [MySQL] implementation. This is generally discouraged as
@ -40,8 +53,8 @@ party.
4. Must support maximum index size of no less than 2048 bytes. The default maximum index size for the InnoDB engine is 4. Must support maximum index size of no less than 2048 bytes. The default maximum index size for the InnoDB engine is
3072 bytes on: 3072 bytes on:
1. [MySQL] [8.0](https://dev.mysql.com/doc/refman/8.0/en/innodb-limits.html) or later. 1. [MySQL] [8.0](https://dev.mysql.com/doc/refman/8.0/en/innodb-limits.html) or later.
2. [MySQL] [5.7](https://dev.mysql.com/doc/refman/5.7/en/innodb-limits.html) provided 2. [MySQL] [5.7](https://dev.mysql.com/doc/refman/5.7/en/innodb-limits.html) or later provided:
[innodb_large_prefix](#innodb-large-prefixes) or later. 1. The [innodb_large_prefix](#innodb-large-prefixes) option is **_ON_**.
3. [MariaDB] [10.3](https://mariadb.com/kb/en/innodb-system-variables/#innodb_large_prefix) or later. 3. [MariaDB] [10.3](https://mariadb.com/kb/en/innodb-system-variables/#innodb_large_prefix) or later.
5. Must support ANSI standard time behaviours. See [ANSI standard time behaviours](#ansi-standard-time-behaviours). 5. Must support ANSI standard time behaviours. See [ANSI standard time behaviours](#ansi-standard-time-behaviours).
@ -52,8 +65,8 @@ supported version of [MariaDB] is generally the recommended version for new inst
#### InnoDB Large Prefixes #### InnoDB Large Prefixes
This can be configured in the [MySQL] configuration file by setting the `innodb_large_prefix` value to on. This can be configured in the [MySQL] configuration file by setting the `innodb_large_prefix` option to on.
According to the Oracle documentation this is the default behaviour in According to the [Oracle] documentation this is the default behaviour in
[MySQL] [5.7](https://dev.mysql.com/doc/refman/5.7/en/innodb-parameters.html#sysvar_innodb_large_prefix) and it can't be [MySQL] [5.7](https://dev.mysql.com/doc/refman/5.7/en/innodb-parameters.html#sysvar_innodb_large_prefix) and it can't be
turned off in [MySQL] [8.0](https://dev.mysql.com/doc/refman/8.0/en/innodb-limits.html) or in [MariaDB] 10.3 and later. turned off in [MySQL] [8.0](https://dev.mysql.com/doc/refman/8.0/en/innodb-limits.html) or in [MariaDB] 10.3 and later.
@ -65,7 +78,7 @@ innodb_large_prefix = ON
#### ANSI standard time behaviours #### ANSI standard time behaviours
This can be configured in the [MySQL] configuration file by setting the `explicit_defaults_for_timestamp` value to on. This can be configured in the [MySQL] configuration file by setting the `explicit_defaults_for_timestamp` value to on.
According to the Oracle documentation this is the default behaviour in According to the [Oracle] documentation this is the default behaviour in
[MySQL] [5.7](https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_explicit_defaults_for_timestamp) [MySQL] [5.7](https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_explicit_defaults_for_timestamp)
and [MySQL] [8.0](https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_explicit_defaults_for_timestamp). and [MySQL] [8.0](https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_explicit_defaults_for_timestamp).
This is however not the default behaviour in This is however not the default behaviour in
@ -76,19 +89,43 @@ This is however not the default behaviour in
explicit_defaults_for_timestamp = ON explicit_defaults_for_timestamp = ON
``` ```
#### Upgrades
[MySQL] and [MariaDB] have several standard but important system databases named `mysql`, `sys`, and
`performance_schema`. These databases are outside the scope and not intended for individual applications to manage as
they are system databases used by [MySQL] and [MariaDB] internally.
These servers/engines may successfully start when these databases are incompatible with your particular [MySQL] or
[MariaDB] version, but may raise errors when you attempt to use particular features of the database. This may lead a
user to believe the server/engine is functioning correctly when it is in fact running with a potentially badly corrupted
schema.
The risk here is that the database may run for an extended period of time unnoticed and may be getting more and more
corrupt with no visible signs until it's no longer recoverable. This makes it critically important users do not neglect
this operation or ensure it's happening.
While some [MySQL] or [MariaDB] containers will do this automatically or give users an option to perform this
automatically, it is strongly recommended that this process is manually done and only done **_after_** doing a backup of
all databases on the server as is the recommendation from both [MySQL] and [MariaDB].
It is your responsibility to ensure these tables are upgraded as per the
[mysql_upgrade](https://dev.mysql.com/doc/refman/8.0/en/mysql-upgrade.html) and
[mariadb_upgrade](https://mariadb.com/kb/en/mysql_upgrade/) documentation.
### Vendor Supported Versions ### Vendor Supported Versions
#### MariaDB Vendor Supported Versions #### MariaDB Vendor Supported Versions
See the [MariaDB Server Releases](https://mariadb.com/kb/en/mariadb-server-release-dates/) for more information. See the [MariaDB Server Releases](https://mariadb.com/kb/en/mariadb-server-release-dates/) for information on the
versions and platforms that are currently supported by this vendor.
#### MySQL Vendor Supported Versions #### MySQL Vendor Supported Versions
See the [MySQL Supported Platforms](https://www.mysql.com/support/supportedplatforms/database.html) for information on See the [MySQL Supported Platforms](https://www.mysql.com/support/supportedplatforms/database.html) for information on
which versions and platforms they support. the versions and platforms that are currently supported by this vendor.
[PostgreSQL]: https://www.postgresql.org/ [PostgreSQL]: https://www.postgresql.org/
[MySQL]: https://www.mysql.com/ [MySQL]: https://www.mysql.com/
[MariaDB]: https://mariadb.org/ [MariaDB]: https://mariadb.org/
[SQLite3]: https://www.sqlite.org/index.html [SQLite3]: https://www.sqlite.org/index.html
[Oracle]: https://www.oracle.com/

View File

@ -3,20 +3,21 @@
functions = "functions" functions = "functions"
[build.environment] [build.environment]
NODE_VERSION = "16.16.0" NODE_VERSION = "16.18.1"
NPM_VERSION = "8.11.0" NPM_VERSION = "8.19.2"
GO_VERSION = "1.19.4"
[context.production] [context.production]
command = "npm run build" command = "pnpm run build"
[context.deploy-preview] [context.deploy-preview]
command = "npm run build -- -b $DEPLOY_PRIME_URL" command = "pnpm run build --baseURL $DEPLOY_URL"
[context.branch-deploy] [context.branch-deploy]
command = "npm run build -- -b $DEPLOY_PRIME_URL" command = "pnpm run build --baseURL $DEPLOY_URL"
[context.next] [context.next]
command = "npm run build" command = "pnpm run build"
[context.next.environment] [context.next.environment]
HUGO_ENV = "next" HUGO_ENV = "next"

View File

@ -3,7 +3,7 @@
"description": "Doks theme", "description": "Doks theme",
"version": "0.5.0", "version": "0.5.0",
"engines": { "engines": {
"node": ">=16.16.0" "node": ">=16.18.1"
}, },
"browserslist": [ "browserslist": [
"defaults" "defaults"
@ -39,7 +39,7 @@
}, },
"devDependencies": { "devDependencies": {
"@babel/cli": "7.19.3", "@babel/cli": "7.19.3",
"@babel/core": "7.20.2", "@babel/core": "7.20.5",
"@babel/preset-env": "7.20.2", "@babel/preset-env": "7.20.2",
"@fullhuman/postcss-purgecss": "5.0.0", "@fullhuman/postcss-purgecss": "5.0.0",
"@hyas/images": "0.3.2", "@hyas/images": "0.3.2",
@ -49,25 +49,25 @@
"bootstrap": "5.2.3", "bootstrap": "5.2.3",
"bootstrap-icons": "1.10.2", "bootstrap-icons": "1.10.2",
"clipboard": "2.0.11", "clipboard": "2.0.11",
"eslint": "8.28.0", "eslint": "8.29.0",
"exec-bin": "1.0.0", "exec-bin": "1.0.0",
"flexsearch": "0.7.31", "flexsearch": "0.7.31",
"highlight.js": "11.7.0", "highlight.js": "11.7.0",
"hugo-installer": "4.0.1", "hugo-installer": "4.0.1",
"instant.page": "5.1.1", "instant.page": "5.1.1",
"katex": "0.16.3", "katex": "0.16.4",
"lazysizes": "5.3.2", "lazysizes": "5.3.2",
"markdownlint-cli2": "0.5.1", "markdownlint-cli2": "0.5.1",
"netlify-plugin-submit-sitemap": "0.4.0", "netlify-plugin-submit-sitemap": "0.4.0",
"node-fetch": "3.3.0", "node-fetch": "3.3.0",
"postcss": "8.4.19", "postcss": "8.4.19",
"postcss-cli": "10.0.0", "postcss-cli": "10.1.0",
"purgecss-whitelister": "2.4.0", "purgecss-whitelister": "2.4.0",
"shx": "0.3.4", "shx": "0.3.4",
"stylelint": "14.15.0", "stylelint": "14.16.0",
"stylelint-config-standard-scss": "6.1.0" "stylelint-config-standard-scss": "6.1.0"
}, },
"otherDependencies": { "otherDependencies": {
"hugo": "0.107.0" "hugo": "0.108.0"
} }
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -45,7 +45,7 @@ services:
- TZ=Australia/Melbourne - TZ=Australia/Melbourne
traefik: traefik:
image: traefik:v2.9.5 image: traefik:v2.9.6
container_name: traefik container_name: traefik
volumes: volumes:
- ./traefik:/etc/traefik - ./traefik:/etc/traefik

View File

@ -32,7 +32,7 @@ services:
- TZ=Australia/Melbourne - TZ=Australia/Melbourne
traefik: traefik:
image: traefik:v2.9.5 image: traefik:v2.9.6
container_name: traefik container_name: traefik
volumes: volumes:
- ./traefik:/etc/traefik - ./traefik:/etc/traefik

20
go.mod
View File

@ -11,27 +11,27 @@ require (
github.com/fasthttp/session/v2 v2.4.13 github.com/fasthttp/session/v2 v2.4.13
github.com/fsnotify/fsnotify v1.6.0 github.com/fsnotify/fsnotify v1.6.0
github.com/go-asn1-ber/asn1-ber v1.5.4 github.com/go-asn1-ber/asn1-ber v1.5.4
github.com/go-crypt/crypt v0.1.14 github.com/go-crypt/crypt v0.2.3
github.com/go-ldap/ldap/v3 v3.4.4 github.com/go-ldap/ldap/v3 v3.4.4
github.com/go-rod/rod v0.112.2 github.com/go-rod/rod v0.112.2
github.com/go-sql-driver/mysql v1.6.0 github.com/go-sql-driver/mysql v1.7.0
github.com/go-webauthn/webauthn v0.5.0 github.com/go-webauthn/webauthn v0.5.0
github.com/golang-jwt/jwt/v4 v4.4.3 github.com/golang-jwt/jwt/v4 v4.4.3
github.com/golang/mock v1.6.0 github.com/golang/mock v1.6.0
github.com/google/uuid v1.3.0 github.com/google/uuid v1.3.0
github.com/hashicorp/go-retryablehttp v0.7.1 github.com/hashicorp/go-retryablehttp v0.7.1
github.com/jackc/pgx/v5 v5.1.1 github.com/jackc/pgx/v5 v5.2.0
github.com/jmoiron/sqlx v1.3.5 github.com/jmoiron/sqlx v1.3.5
github.com/knadh/koanf v1.4.4 github.com/knadh/koanf v1.4.4
github.com/mattn/go-sqlite3 v1.14.16 github.com/mattn/go-sqlite3 v1.14.16
github.com/mitchellh/mapstructure v1.5.0 github.com/mitchellh/mapstructure v1.5.0
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826
github.com/ory/fosite v0.43.0 github.com/ory/fosite v0.44.0
github.com/ory/herodot v0.9.13 github.com/ory/herodot v0.9.13
github.com/ory/x v0.0.517 github.com/ory/x v0.0.520
github.com/otiai10/copy v1.9.0 github.com/otiai10/copy v1.9.0
github.com/pkg/errors v0.9.1 github.com/pkg/errors v0.9.1
github.com/pquerna/otp v1.3.0 github.com/pquerna/otp v1.4.0
github.com/prometheus/client_golang v1.14.0 github.com/prometheus/client_golang v1.14.0
github.com/sirupsen/logrus v1.9.0 github.com/sirupsen/logrus v1.9.0
github.com/spf13/cobra v1.6.1 github.com/spf13/cobra v1.6.1
@ -40,8 +40,8 @@ require (
github.com/trustelem/zxcvbn v1.0.1 github.com/trustelem/zxcvbn v1.0.1
github.com/valyala/fasthttp v1.43.0 github.com/valyala/fasthttp v1.43.0
golang.org/x/sync v0.1.0 golang.org/x/sync v0.1.0
golang.org/x/term v0.2.0 golang.org/x/term v0.3.0
golang.org/x/text v0.4.0 golang.org/x/text v0.5.0
gopkg.in/square/go-jose.v2 v2.6.0 gopkg.in/square/go-jose.v2 v2.6.0
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
) )
@ -63,7 +63,7 @@ require (
github.com/ecordell/optgen v0.0.6 // indirect github.com/ecordell/optgen v0.0.6 // indirect
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 // indirect github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 // indirect
github.com/fxamacker/cbor/v2 v2.4.0 // indirect github.com/fxamacker/cbor/v2 v2.4.0 // indirect
github.com/go-crypt/x v0.1.3 // indirect github.com/go-crypt/x v0.1.10 // indirect
github.com/go-redis/redis/v8 v8.11.5 // indirect github.com/go-redis/redis/v8 v8.11.5 // indirect
github.com/go-webauthn/revoke v0.1.6 // indirect github.com/go-webauthn/revoke v0.1.6 // indirect
github.com/golang/glog v1.0.0 // indirect github.com/golang/glog v1.0.0 // indirect
@ -110,7 +110,7 @@ require (
golang.org/x/mod v0.6.0 // indirect golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.1.0 // indirect golang.org/x/net v0.1.0 // indirect
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b // indirect golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b // indirect
golang.org/x/sys v0.2.0 // indirect golang.org/x/sys v0.3.0 // indirect
golang.org/x/tools v0.2.0 // indirect golang.org/x/tools v0.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71 // indirect google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71 // indirect

39
go.sum
View File

@ -162,10 +162,10 @@ github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrt
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-asn1-ber/asn1-ber v1.5.4 h1:vXT6d/FNDiELJnLb6hGNa309LMsrCoYFvpwHDF0+Y1A= github.com/go-asn1-ber/asn1-ber v1.5.4 h1:vXT6d/FNDiELJnLb6hGNa309LMsrCoYFvpwHDF0+Y1A=
github.com/go-asn1-ber/asn1-ber v1.5.4/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= github.com/go-asn1-ber/asn1-ber v1.5.4/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
github.com/go-crypt/crypt v0.1.14 h1:Pd8iBYlbwDXJNi0lz8CS/qYvpvxCfP0XO/f5PYvVQ4o= github.com/go-crypt/crypt v0.2.3 h1:g9OPe39VmqonsTXP/zo4byEoxrxAAUG+DzBvjzGWvuw=
github.com/go-crypt/crypt v0.1.14/go.mod h1:VNLdWMD0go46arq5WVZB2MV/9Vw02FOWhKDORXl7K2c= github.com/go-crypt/crypt v0.2.3/go.mod h1:mbhOIjybuVuh0Vxveb//7UbGV8OCugJC7UPzqs1awYw=
github.com/go-crypt/x v0.1.3 h1:3YSlHqOZsw4gcPzfqrcc5kg4GIhTKmkjl/ZVqJ3CbbU= github.com/go-crypt/x v0.1.10 h1:HN8oQGrWcg5xPtIIGwPDWs9MvdYEUJrP7JeNkC46dvM=
github.com/go-crypt/x v0.1.3/go.mod h1:/6X1DjQki055ajXV/7pCHZM0OmMR1+csiXFkxK73Kc8= github.com/go-crypt/x v0.1.10/go.mod h1:OI04rm/Ojti3mrUFZAJnx66nFbnZ0CVPF7qG49mBZgI=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
@ -184,8 +184,9 @@ github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
github.com/go-rod/rod v0.112.2 h1:dwauKYC/H2em8/BcGk3gC0LTzZHf5MIDKf2DVM4z9gU= github.com/go-rod/rod v0.112.2 h1:dwauKYC/H2em8/BcGk3gC0LTzZHf5MIDKf2DVM4z9gU=
github.com/go-rod/rod v0.112.2/go.mod h1:ElViL9ABbcshNQw93+11FrYRH92RRhMKleuILo6+5V0= github.com/go-rod/rod v0.112.2/go.mod h1:ElViL9ABbcshNQw93+11FrYRH92RRhMKleuILo6+5V0=
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
@ -338,8 +339,8 @@ github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsI
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg=
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
github.com/jackc/pgx/v5 v5.1.1 h1:pZD79K1SYv8wc2HmCQA6VdmRQi7/OtCfv9bM3WAXUYA= github.com/jackc/pgx/v5 v5.2.0 h1:NdPpngX0Y6z6XDFKqmFQaE+bCtkqzvQIOt1wvBlAqs8=
github.com/jackc/pgx/v5 v5.1.1/go.mod h1:Ptn7zmohNsWEsdxRawMzk3gaKma2obW+NWTnKa0S4nk= github.com/jackc/pgx/v5 v5.2.0/go.mod h1:Ptn7zmohNsWEsdxRawMzk3gaKma2obW+NWTnKa0S4nk=
github.com/jandelgado/gcov2lcov v1.0.5 h1:rkBt40h0CVK4oCb8Dps950gvfd1rYvQ8+cWa346lVU0= github.com/jandelgado/gcov2lcov v1.0.5 h1:rkBt40h0CVK4oCb8Dps950gvfd1rYvQ8+cWa346lVU0=
github.com/jandelgado/gcov2lcov v1.0.5/go.mod h1:NnSxK6TMlg1oGDBfGelGbjgorT5/L3cchlbtgFYZSss= github.com/jandelgado/gcov2lcov v1.0.5/go.mod h1:NnSxK6TMlg1oGDBfGelGbjgorT5/L3cchlbtgFYZSss=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
@ -449,8 +450,8 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
github.com/ory/fosite v0.43.0 h1:9H1O3I7CFxS2Y6j9FDAx2W3I5uAyEubc9hECS0UTOgI= github.com/ory/fosite v0.44.0 h1:Z3UjyO11/wlIoa3BotOqcTkfm7kUNA8F7dd8mOMfx0o=
github.com/ory/fosite v0.43.0/go.mod h1:BTd8+oG1mRtezZbQq0S4D2HBc815bedZHjjs2KRs39Y= github.com/ory/fosite v0.44.0/go.mod h1:o/G4kAeNn65l6MCod2+KmFfU6JQBSojS7eXys6lKGzM=
github.com/ory/go-acc v0.2.6/go.mod h1:4Kb/UnPcT8qRAk3IAxta+hvVapdxTLWtrr7bFLlEgpw= github.com/ory/go-acc v0.2.6/go.mod h1:4Kb/UnPcT8qRAk3IAxta+hvVapdxTLWtrr7bFLlEgpw=
github.com/ory/go-acc v0.2.8 h1:rOHHAPQjf0u7eHFGWpiXK+gIu/e0GRSJNr9pDukdNC4= github.com/ory/go-acc v0.2.8 h1:rOHHAPQjf0u7eHFGWpiXK+gIu/e0GRSJNr9pDukdNC4=
github.com/ory/go-acc v0.2.8/go.mod h1:iCRZUdGb/7nqvSn8xWZkhfVrtXRZ9Wru2E5rabCjFPI= github.com/ory/go-acc v0.2.8/go.mod h1:iCRZUdGb/7nqvSn8xWZkhfVrtXRZ9Wru2E5rabCjFPI=
@ -460,8 +461,8 @@ github.com/ory/herodot v0.9.13 h1:cN/Z4eOkErl/9W7hDIDLb79IO/bfsH+8yscBjRpB4IU=
github.com/ory/herodot v0.9.13/go.mod h1:IWDs9kSvFQqw/cQ8zi5ksyYvITiUU4dI7glUrhZcJYo= github.com/ory/herodot v0.9.13/go.mod h1:IWDs9kSvFQqw/cQ8zi5ksyYvITiUU4dI7glUrhZcJYo=
github.com/ory/viper v1.7.5 h1:+xVdq7SU3e1vNaCsk/ixsfxE4zylk1TJUiJrY647jUE= github.com/ory/viper v1.7.5 h1:+xVdq7SU3e1vNaCsk/ixsfxE4zylk1TJUiJrY647jUE=
github.com/ory/viper v1.7.5/go.mod h1:ypOuyJmEUb3oENywQZRgeAMwqgOyDqwboO1tj3DjTaM= github.com/ory/viper v1.7.5/go.mod h1:ypOuyJmEUb3oENywQZRgeAMwqgOyDqwboO1tj3DjTaM=
github.com/ory/x v0.0.517 h1:20FrwHie18q78WGaHcaH0+XoPNdE88zqSXCQNPNlYUs= github.com/ory/x v0.0.520 h1:ryfKHQEViUBv/UdlZhePOG52RpPAooZtK/I7+x58lBI=
github.com/ory/x v0.0.517/go.mod h1:xUtRpoiRARyJNPVk/fcCNKzyp25Foxt9GPlj8pd7egY= github.com/ory/x v0.0.520/go.mod h1:7f32P5XMBLCy6aVT+fUYq3WPcMVpzsjC0C+FovlMNqY=
github.com/otiai10/copy v1.9.0 h1:7KFNiCgZ91Ru4qW4CWPf/7jqtxLagGRmIxWldPP9VY4= github.com/otiai10/copy v1.9.0 h1:7KFNiCgZ91Ru4qW4CWPf/7jqtxLagGRmIxWldPP9VY4=
github.com/otiai10/copy v1.9.0/go.mod h1:hsfX19wcn0UWIHUQ3/4fHuehhk2UyArQ9dVFAn3FczI= github.com/otiai10/copy v1.9.0/go.mod h1:hsfX19wcn0UWIHUQ3/4fHuehhk2UyArQ9dVFAn3FczI=
github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=
@ -493,8 +494,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
github.com/pquerna/otp v1.3.0 h1:oJV/SkzR33anKXwQU3Of42rL4wbrffP4uvUf1SvS5Xs= github.com/pquerna/otp v1.4.0 h1:wZvl1TIVxKRThZIBiwOOHOGP/1+nZyWBil9Y2XNEDzg=
github.com/pquerna/otp v1.3.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg= github.com/pquerna/otp v1.4.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
@ -846,12 +847,12 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A= golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.2.0 h1:z85xZCsEl7bi/KwbNADeBYoOP0++7W1ipu+aGnpwzRM= golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI=
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -862,8 +863,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=

View File

@ -8,7 +8,12 @@ import (
"sync" "sync"
"time" "time"
"github.com/go-crypt/crypt" "github.com/go-crypt/crypt/algorithm"
"github.com/go-crypt/crypt/algorithm/argon2"
"github.com/go-crypt/crypt/algorithm/bcrypt"
"github.com/go-crypt/crypt/algorithm/pbkdf2"
"github.com/go-crypt/crypt/algorithm/scrypt"
"github.com/go-crypt/crypt/algorithm/shacrypt"
"github.com/authelia/authelia/v4/internal/configuration/schema" "github.com/authelia/authelia/v4/internal/configuration/schema"
"github.com/authelia/authelia/v4/internal/logging" "github.com/authelia/authelia/v4/internal/logging"
@ -17,7 +22,7 @@ import (
// FileUserProvider is a provider reading details from a file. // FileUserProvider is a provider reading details from a file.
type FileUserProvider struct { type FileUserProvider struct {
config *schema.FileAuthenticationBackend config *schema.FileAuthenticationBackend
hash crypt.Hash hash algorithm.Hash
database *FileUserDatabase database *FileUserDatabase
mutex *sync.Mutex mutex *sync.Mutex
timeoutReload time.Time timeoutReload time.Time
@ -145,39 +150,50 @@ func (p *FileUserProvider) setTimeoutReload(now time.Time) {
} }
// NewFileCryptoHashFromConfig returns a crypt.Hash given a valid configuration. // NewFileCryptoHashFromConfig returns a crypt.Hash given a valid configuration.
func NewFileCryptoHashFromConfig(config schema.Password) (hash crypt.Hash, err error) { func NewFileCryptoHashFromConfig(config schema.Password) (hash algorithm.Hash, err error) {
switch config.Algorithm { switch config.Algorithm {
case hashArgon2, "": case hashArgon2, "":
hash = crypt.NewArgon2Hash(). hash, err = argon2.New(
WithVariant(crypt.NewArgon2Variant(config.Argon2.Variant)). argon2.WithVariantName(config.Argon2.Variant),
WithT(config.Argon2.Iterations). argon2.WithT(config.Argon2.Iterations),
WithM(config.Argon2.Memory). argon2.WithM(uint32(config.Argon2.Memory)),
WithP(config.Argon2.Parallelism). argon2.WithP(config.Argon2.Parallelism),
WithK(config.Argon2.KeyLength). argon2.WithK(config.Argon2.KeyLength),
WithS(config.Argon2.SaltLength) argon2.WithS(config.Argon2.SaltLength),
)
case hashSHA2Crypt: case hashSHA2Crypt:
hash = crypt.NewSHA2CryptHash(). hash, err = shacrypt.New(
WithVariant(crypt.NewSHA2CryptVariant(config.SHA2Crypt.Variant)). shacrypt.WithVariantName(config.SHA2Crypt.Variant),
WithRounds(config.SHA2Crypt.Iterations). shacrypt.WithIterations(config.SHA2Crypt.Iterations),
WithSaltLength(config.SHA2Crypt.SaltLength) shacrypt.WithSaltLength(config.SHA2Crypt.SaltLength),
)
case hashPBKDF2: case hashPBKDF2:
hash = crypt.NewPBKDF2Hash(). hash, err = pbkdf2.New(
WithVariant(crypt.NewPBKDF2Variant(config.PBKDF2.Variant)). pbkdf2.WithVariantName(config.PBKDF2.Variant),
WithIterations(config.PBKDF2.Iterations). pbkdf2.WithIterations(config.PBKDF2.Iterations),
WithSaltLength(config.PBKDF2.SaltLength) pbkdf2.WithSaltLength(config.PBKDF2.SaltLength),
)
case hashSCrypt: case hashSCrypt:
hash = crypt.NewScryptHash(). hash, err = scrypt.New(
WithLN(config.SCrypt.Iterations). scrypt.WithLN(config.SCrypt.Iterations),
WithP(config.SCrypt.Parallelism). scrypt.WithP(config.SCrypt.Parallelism),
WithR(config.SCrypt.BlockSize) scrypt.WithR(config.SCrypt.BlockSize),
scrypt.WithKeyLength(config.SCrypt.KeyLength),
scrypt.WithSaltLength(config.SCrypt.SaltLength),
)
case hashBCrypt: case hashBCrypt:
hash = crypt.NewBcryptHash(). hash, err = bcrypt.New(
WithVariant(crypt.NewBcryptVariant(config.BCrypt.Variant)). bcrypt.WithVariantName(config.BCrypt.Variant),
WithCost(config.BCrypt.Cost) bcrypt.WithIterations(config.BCrypt.Cost),
)
default: default:
return nil, fmt.Errorf("algorithm '%s' is unknown", config.Algorithm) return nil, fmt.Errorf("algorithm '%s' is unknown", config.Algorithm)
} }
if err != nil {
return nil, fmt.Errorf("failed to initialize hash settings: %w", err)
}
if err = hash.Validate(); err != nil { if err = hash.Validate(); err != nil {
return nil, fmt.Errorf("failed to validate hash settings: %w", err) return nil, fmt.Errorf("failed to validate hash settings: %w", err)
} }

View File

@ -8,6 +8,7 @@ import (
"github.com/asaskevich/govalidator" "github.com/asaskevich/govalidator"
"github.com/go-crypt/crypt" "github.com/go-crypt/crypt"
"github.com/go-crypt/crypt/algorithm"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
) )
@ -203,7 +204,7 @@ func (m *FileUserDatabase) ToDatabaseModel() (model *DatabaseModel) {
// DatabaseUserDetails is the model of user details in the file database. // DatabaseUserDetails is the model of user details in the file database.
type DatabaseUserDetails struct { type DatabaseUserDetails struct {
Username string Username string
Digest crypt.Digest Digest algorithm.Digest
Disabled bool Disabled bool
DisplayName string DisplayName string
Email string Email string
@ -308,7 +309,7 @@ type UserDetailsModel struct {
// ToDatabaseUserDetailsModel converts a UserDetailsModel into a *DatabaseUserDetails. // ToDatabaseUserDetailsModel converts a UserDetailsModel into a *DatabaseUserDetails.
func (m UserDetailsModel) ToDatabaseUserDetailsModel(username string) (model *DatabaseUserDetails, err error) { func (m UserDetailsModel) ToDatabaseUserDetailsModel(username string) (model *DatabaseUserDetails, err error) {
var d crypt.Digest var d algorithm.Digest
if d, err = crypt.Decode(m.HashedPassword); err != nil { if d, err = crypt.Decode(m.HashedPassword); err != nil {
return nil, err return nil, err

View File

@ -252,7 +252,7 @@ func TestShouldRaiseWhenLoadingDatabaseWithBadSHA512HashesForTheFirstTime(t *tes
provider := NewFileUserProvider(&config) provider := NewFileUserProvider(&config)
assert.EqualError(t, provider.StartupCheck(), "error decoding the authentication database: failed to parse hash for user 'john': sha2crypt decode error: provided encoded hash has an invalid option: option 'rounds00000' is invalid") assert.EqualError(t, provider.StartupCheck(), "error decoding the authentication database: failed to parse hash for user 'john': shacrypt decode error: parameter pair 'rounds00000' is not properly encoded: does not contain kv separator '='")
}) })
} }
@ -263,7 +263,7 @@ func TestShouldRaiseWhenLoadingDatabaseWithBadArgon2idHashSettingsForTheFirstTim
provider := NewFileUserProvider(&config) provider := NewFileUserProvider(&config)
assert.EqualError(t, provider.StartupCheck(), "error decoding the authentication database: failed to parse hash for user 'john': argon2 decode error: provided encoded hash has an invalid option: option 'm65536' is invalid") assert.EqualError(t, provider.StartupCheck(), "error decoding the authentication database: failed to parse hash for user 'john': argon2 decode error: parameter pair 'm65536' is not properly encoded: does not contain kv separator '='")
}) })
} }

View File

@ -5,6 +5,7 @@ import (
"strings" "strings"
"github.com/go-crypt/crypt" "github.com/go-crypt/crypt"
"github.com/go-crypt/crypt/algorithm"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/pflag" "github.com/spf13/pflag"
@ -272,7 +273,7 @@ func newCryptoHashValidateCmd() (cmd *cobra.Command) {
func cmdCryptoHashGenerateFinish(cmd *cobra.Command, args []string, flagsMap map[string]string) (err error) { func cmdCryptoHashGenerateFinish(cmd *cobra.Command, args []string, flagsMap map[string]string) (err error) {
var ( var (
algorithm string algName string
configs []string configs []string
c schema.Password c schema.Password
@ -294,25 +295,25 @@ func cmdCryptoHashGenerateFinish(cmd *cobra.Command, args []string, flagsMap map
break break
case legacy: case legacy:
if sha512, _ := cmd.Flags().GetBool(cmdFlagNameSHA512); sha512 { if sha512, _ := cmd.Flags().GetBool(cmdFlagNameSHA512); sha512 {
algorithm = cmdUseHashSHA2Crypt algName = cmdUseHashSHA2Crypt
} else { } else {
algorithm = cmdUseHashArgon2 algName = cmdUseHashArgon2
} }
default: default:
algorithm = cmd.Use algName = cmd.Use
} }
if c, err = cmdCryptoHashGetConfig(algorithm, configs, cmd.Flags(), flagsMap); err != nil { if c, err = cmdCryptoHashGetConfig(algName, configs, cmd.Flags(), flagsMap); err != nil {
return err return err
} }
if legacy && algorithm == cmdUseHashArgon2 && cmd.Flags().Changed(cmdFlagNameMemory) { if legacy && algName == cmdUseHashArgon2 && cmd.Flags().Changed(cmdFlagNameMemory) {
c.Argon2.Memory *= 1024 c.Argon2.Memory *= 1024
} }
var ( var (
hash crypt.Hash hash algorithm.Hash
digest crypt.Digest digest algorithm.Digest
password string password string
random bool random bool
) )

View File

@ -12,7 +12,7 @@ import (
"strings" "strings"
"time" "time"
"github.com/go-crypt/crypt" "github.com/go-crypt/crypt/algorithm/plaintext"
"github.com/mitchellh/mapstructure" "github.com/mitchellh/mapstructure"
"github.com/authelia/authelia/v4/internal/configuration/schema" "github.com/authelia/authelia/v4/internal/configuration/schema"
@ -486,7 +486,7 @@ func StringToPrivateKeyHookFunc() mapstructure.DecodeHookFuncType {
} }
// StringToPasswordDigestHookFunc decodes a string into a crypt.Digest. // StringToPasswordDigestHookFunc decodes a string into a crypt.Digest.
func StringToPasswordDigestHookFunc(plaintext bool) mapstructure.DecodeHookFuncType { func StringToPasswordDigestHookFunc() mapstructure.DecodeHookFuncType {
return func(f reflect.Type, t reflect.Type, data interface{}) (value interface{}, err error) { return func(f reflect.Type, t reflect.Type, data interface{}) (value interface{}, err error) {
var ptr bool var ptr bool
@ -514,11 +514,11 @@ func StringToPasswordDigestHookFunc(plaintext bool) mapstructure.DecodeHookFuncT
var result *schema.PasswordDigest var result *schema.PasswordDigest
if !strings.HasPrefix(dataStr, "$") { if !strings.HasPrefix(dataStr, "$") {
dataStr = fmt.Sprintf(crypt.StorageFormatSimple, crypt.AlgorithmPrefixPlainText, dataStr) dataStr = fmt.Sprintf(plaintext.EncodingFmt, plaintext.AlgIdentifierPlainText, dataStr)
} }
if dataStr != "" { if dataStr != "" {
if result, err = schema.NewPasswordDigest(dataStr, plaintext); err != nil { if result, err = schema.DecodePasswordDigest(dataStr); err != nil {
return nil, fmt.Errorf(errFmtDecodeHookCouldNotParse, dataStr, prefixType, expectedType.String(), err) return nil, fmt.Errorf(errFmtDecodeHookCouldNotParse, dataStr, prefixType, expectedType.String(), err)
} }
} }

View File

@ -2,7 +2,6 @@ package configuration
import ( import (
"fmt" "fmt"
"os"
"path/filepath" "path/filepath"
"runtime" "runtime"
"testing" "testing"
@ -58,8 +57,7 @@ func TestKoanfSecretCallbackWithValidSecrets(t *testing.T) {
"AUTHELIA__STORAGE_MYSQL_FAKE_PASSWORD": "storage.mysql.fake_password", "AUTHELIA__STORAGE_MYSQL_FAKE_PASSWORD": "storage.mysql.fake_password",
} }
dir, err := os.MkdirTemp("", "authelia-test-callbacks") dir := t.TempDir()
assert.NoError(t, err)
secretOne := filepath.Join(dir, "secert_one") secretOne := filepath.Join(dir, "secert_one")
secretTwo := filepath.Join(dir, "secret_two") secretTwo := filepath.Join(dir, "secret_two")
@ -108,8 +106,7 @@ func TestKoanfSecretCallbackShouldErrorOnFSError(t *testing.T) {
"AUTHELIA_THEME": "theme", "AUTHELIA_THEME": "theme",
} }
dir, err := os.MkdirTemp("", "authelia-test-callbacks") dir := t.TempDir()
assert.NoError(t, err)
secret := filepath.Join(dir, "inaccessible") secret := filepath.Join(dir, "inaccessible")

View File

@ -66,7 +66,7 @@ func unmarshal(ko *koanf.Koanf, val *schema.StructValidator, path string, o any)
StringToPrivateKeyHookFunc(), StringToPrivateKeyHookFunc(),
StringToCryptoPrivateKeyHookFunc(), StringToCryptoPrivateKeyHookFunc(),
StringToTLSVersionHookFunc(), StringToTLSVersionHookFunc(),
StringToPasswordDigestHookFunc(true), StringToPasswordDigestHookFunc(),
ToTimeDurationHookFunc(), ToTimeDurationHookFunc(),
), ),
Metadata: nil, Metadata: nil,

View File

@ -19,8 +19,7 @@ import (
func TestShouldErrorSecretNotExist(t *testing.T) { func TestShouldErrorSecretNotExist(t *testing.T) {
testReset() testReset()
dir, err := os.MkdirTemp("", "authelia-test-secret-not-exist") dir := t.TempDir()
assert.NoError(t, err)
testSetEnv(t, "JWT_SECRET_FILE", filepath.Join(dir, "jwt")) testSetEnv(t, "JWT_SECRET_FILE", filepath.Join(dir, "jwt"))
testSetEnv(t, "DUO_API_SECRET_KEY_FILE", filepath.Join(dir, "duo")) testSetEnv(t, "DUO_API_SECRET_KEY_FILE", filepath.Join(dir, "duo"))
@ -36,7 +35,7 @@ func TestShouldErrorSecretNotExist(t *testing.T) {
testSetEnv(t, "IDENTITY_PROVIDERS_OIDC_HMAC_SECRET_FILE", filepath.Join(dir, "oidc-hmac")) testSetEnv(t, "IDENTITY_PROVIDERS_OIDC_HMAC_SECRET_FILE", filepath.Join(dir, "oidc-hmac"))
val := schema.NewStructValidator() val := schema.NewStructValidator()
_, _, err = Load(val, NewEnvironmentSource(DefaultEnvPrefix, DefaultEnvDelimiter), NewSecretsSource(DefaultEnvPrefix, DefaultEnvDelimiter)) _, _, err := Load(val, NewEnvironmentSource(DefaultEnvPrefix, DefaultEnvDelimiter), NewSecretsSource(DefaultEnvPrefix, DefaultEnvDelimiter))
assert.NoError(t, err) assert.NoError(t, err)
assert.Len(t, val.Warnings(), 0) assert.Len(t, val.Warnings(), 0)
@ -162,15 +161,14 @@ func TestShouldRaiseIOErrOnUnreadableFile(t *testing.T) {
testReset() testReset()
dir, err := os.MkdirTemp("", "authelia-conf") dir := t.TempDir()
assert.NoError(t, err)
assert.NoError(t, os.WriteFile(filepath.Join(dir, "myconf.yml"), []byte("server:\n port: 9091\n"), 0000)) assert.NoError(t, os.WriteFile(filepath.Join(dir, "myconf.yml"), []byte("server:\n port: 9091\n"), 0000))
cfg := filepath.Join(dir, "myconf.yml") cfg := filepath.Join(dir, "myconf.yml")
val := schema.NewStructValidator() val := schema.NewStructValidator()
_, _, err = Load(val, NewYAMLFileSource(cfg)) _, _, err := Load(val, NewYAMLFileSource(cfg))
assert.NoError(t, err) assert.NoError(t, err)
require.Len(t, val.Errors(), 1) require.Len(t, val.Errors(), 1)
@ -390,14 +388,13 @@ func TestShouldNotReadConfigurationOnFSAccessDenied(t *testing.T) {
testReset() testReset()
dir, err := os.MkdirTemp("", "authelia-config") dir := t.TempDir()
assert.NoError(t, err)
cfg := filepath.Join(dir, "config.yml") cfg := filepath.Join(dir, "config.yml")
assert.NoError(t, testCreateFile(filepath.Join(dir, "config.yml"), "port: 9091\n", 0000)) assert.NoError(t, testCreateFile(filepath.Join(dir, "config.yml"), "port: 9091\n", 0000))
val := schema.NewStructValidator() val := schema.NewStructValidator()
_, _, err = Load(val, NewYAMLFileSource(cfg)) _, _, err := Load(val, NewYAMLFileSource(cfg))
assert.NoError(t, err) assert.NoError(t, err)
require.Len(t, val.Errors(), 1) require.Len(t, val.Errors(), 1)
@ -408,11 +405,10 @@ func TestShouldNotReadConfigurationOnFSAccessDenied(t *testing.T) {
func TestShouldNotLoadDirectoryConfiguration(t *testing.T) { func TestShouldNotLoadDirectoryConfiguration(t *testing.T) {
testReset() testReset()
dir, err := os.MkdirTemp("", "authelia-config") dir := t.TempDir()
assert.NoError(t, err)
val := schema.NewStructValidator() val := schema.NewStructValidator()
_, _, err = Load(val, NewYAMLFileSource(dir)) _, _, err := Load(val, NewYAMLFileSource(dir))
assert.NoError(t, err) assert.NoError(t, err)
require.Len(t, val.Errors(), 1) require.Len(t, val.Errors(), 1)

View File

@ -191,7 +191,7 @@ var DefaultLDAPAuthenticationBackendConfigurationImplementationActiveDirectory =
UsernameAttribute: "sAMAccountName", UsernameAttribute: "sAMAccountName",
MailAttribute: "mail", MailAttribute: "mail",
DisplayNameAttribute: "displayName", DisplayNameAttribute: "displayName",
GroupsFilter: "(&(member={dn})(sAMAccountType=268435456))", GroupsFilter: "(&(member={dn})(|(sAMAccountType=268435456)(sAMAccountType=536870912)))",
GroupNameAttribute: "cn", GroupNameAttribute: "cn",
Timeout: time.Second * 5, Timeout: time.Second * 5,
TLS: &TLSConfig{ TLS: &TLSConfig{

View File

@ -16,6 +16,8 @@ import (
"time" "time"
"github.com/go-crypt/crypt" "github.com/go-crypt/crypt"
"github.com/go-crypt/crypt/algorithm"
"github.com/go-crypt/crypt/algorithm/plaintext"
) )
// NewAddressFromString returns an *Address and error depending on the ability to parse the string as an Address. // NewAddressFromString returns an *Address and error depending on the ability to parse the string as an Address.
@ -110,27 +112,32 @@ func (a Address) Listener() (net.Listener, error) {
return net.Listen(a.Scheme, a.HostPort()) return net.Listen(a.Scheme, a.HostPort())
} }
// NewPasswordDigest returns a new PasswordDigest. var cdecoder algorithm.DecoderRegister
func NewPasswordDigest(value string, plaintext bool) (digest *PasswordDigest, err error) {
var d crypt.Digest
switch { // DecodePasswordDigest returns a new PasswordDigest if it can be decoded.
case plaintext: func DecodePasswordDigest(encodedDigest string) (digest *PasswordDigest, err error) {
d, err = crypt.DecodeWithPlainText(value) if cdecoder == nil {
default: if cdecoder, err = crypt.NewDefaultDecoder(); err != nil {
d, err = crypt.Decode(value) return nil, fmt.Errorf("failed to initialize decoder: %w", err)
} }
if err != nil { if err = plaintext.RegisterDecoderPlainText(cdecoder); err != nil {
return nil, fmt.Errorf("failed to initialize decoder: could not register the plaintext decoder: %w", err)
}
}
var d algorithm.Digest
if d, err = cdecoder.Decode(encodedDigest); err != nil {
return nil, err return nil, err
} }
return &PasswordDigest{d}, err return &PasswordDigest{Digest: d}, nil
} }
// PasswordDigest is a configuration type for the crypt.Digest. // PasswordDigest is a configuration type for the crypt.Digest.
type PasswordDigest struct { type PasswordDigest struct {
crypt.Digest algorithm.Digest
} }
// NewX509CertificateChain creates a new *X509CertificateChain from a given string, parsing each PEM block one by one. // NewX509CertificateChain creates a new *X509CertificateChain from a given string, parsing each PEM block one by one.

View File

@ -13,8 +13,7 @@ import (
) )
func TestShouldGenerateConfiguration(t *testing.T) { func TestShouldGenerateConfiguration(t *testing.T) {
dir, err := os.MkdirTemp("", "authelia-config") dir := t.TempDir()
assert.NoError(t, err)
cfg := filepath.Join(dir, "config.yml") cfg := filepath.Join(dir, "config.yml")
@ -31,8 +30,7 @@ func TestShouldNotGenerateConfigurationOnFSAccessDenied(t *testing.T) {
t.Skip("skipping test due to being on windows") t.Skip("skipping test due to being on windows")
} }
dir, err := os.MkdirTemp("", "authelia-config") dir := t.TempDir()
assert.NoError(t, err)
assert.NoError(t, os.Mkdir(filepath.Join(dir, "zero"), 0000)) assert.NoError(t, os.Mkdir(filepath.Join(dir, "zero"), 0000))
@ -44,8 +42,7 @@ func TestShouldNotGenerateConfigurationOnFSAccessDenied(t *testing.T) {
} }
func TestShouldNotGenerateConfiguration(t *testing.T) { func TestShouldNotGenerateConfiguration(t *testing.T) {
dir, err := os.MkdirTemp("", "authelia-config") dir := t.TempDir()
assert.NoError(t, err)
cfg := filepath.Join(dir, "..", "not-a-dir", "config.yml") cfg := filepath.Join(dir, "..", "not-a-dir", "config.yml")

View File

@ -5,7 +5,11 @@ import (
"net/url" "net/url"
"strings" "strings"
"github.com/go-crypt/crypt" "github.com/go-crypt/crypt/algorithm/argon2"
"github.com/go-crypt/crypt/algorithm/bcrypt"
"github.com/go-crypt/crypt/algorithm/pbkdf2"
"github.com/go-crypt/crypt/algorithm/scrypt"
"github.com/go-crypt/crypt/algorithm/shacrypt"
"github.com/authelia/authelia/v4/internal/configuration/schema" "github.com/authelia/authelia/v4/internal/configuration/schema"
"github.com/authelia/authelia/v4/internal/utils" "github.com/authelia/authelia/v4/internal/utils"
@ -91,46 +95,48 @@ func validateFileAuthenticationBackendPasswordConfigArgon2(config *schema.Passwo
switch { switch {
case config.Argon2.Iterations == 0: case config.Argon2.Iterations == 0:
config.Argon2.Iterations = schema.DefaultPasswordConfig.Argon2.Iterations config.Argon2.Iterations = schema.DefaultPasswordConfig.Argon2.Iterations
case config.Argon2.Iterations < crypt.Argon2IterationsMin: case config.Argon2.Iterations < argon2.IterationsMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashArgon2, "iterations", config.Argon2.Iterations, crypt.Argon2IterationsMin)) validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashArgon2, "iterations", config.Argon2.Iterations, argon2.IterationsMin))
case config.Argon2.Iterations > crypt.Argon2IterationsMax: case config.Argon2.Iterations > argon2.IterationsMax:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashArgon2, "iterations", config.Argon2.Iterations, crypt.Argon2IterationsMax)) validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashArgon2, "iterations", config.Argon2.Iterations, argon2.IterationsMax))
} }
switch { switch {
case config.Argon2.Parallelism == 0: case config.Argon2.Parallelism == 0:
config.Argon2.Parallelism = schema.DefaultPasswordConfig.Argon2.Parallelism config.Argon2.Parallelism = schema.DefaultPasswordConfig.Argon2.Parallelism
case config.Argon2.Parallelism < crypt.Argon2ParallelismMin: case config.Argon2.Parallelism < argon2.ParallelismMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashArgon2, "parallelism", config.Argon2.Parallelism, crypt.Argon2ParallelismMin)) validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashArgon2, "parallelism", config.Argon2.Parallelism, argon2.ParallelismMin))
case config.Argon2.Parallelism > crypt.Argon2ParallelismMax: case config.Argon2.Parallelism > argon2.ParallelismMax:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashArgon2, "parallelism", config.Argon2.Parallelism, crypt.Argon2ParallelismMax)) validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashArgon2, "parallelism", config.Argon2.Parallelism, argon2.ParallelismMax))
} }
switch { switch {
case config.Argon2.Memory == 0: case config.Argon2.Memory == 0:
config.Argon2.Memory = schema.DefaultPasswordConfig.Argon2.Memory config.Argon2.Memory = schema.DefaultPasswordConfig.Argon2.Memory
case config.Argon2.Memory < 0: case config.Argon2.Memory < argon2.MemoryMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashArgon2, "memory", config.Argon2.Parallelism, 1)) validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashArgon2, "memory", config.Argon2.Memory, argon2.MemoryMin))
case config.Argon2.Memory < (crypt.Argon2MemoryMinParallelismMultiplier * config.Argon2.Parallelism): case uint64(config.Argon2.Memory) > uint64(argon2.MemoryMax):
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordArgon2MemoryTooLow, config.Argon2.Memory, config.Argon2.Parallelism*crypt.Argon2MemoryMinParallelismMultiplier, config.Argon2.Parallelism, crypt.Argon2MemoryMinParallelismMultiplier)) validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashArgon2, "memory", config.Argon2.Memory, argon2.MemoryMax))
case config.Argon2.Memory < (config.Argon2.Parallelism * argon2.MemoryMinParallelismMultiplier):
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordArgon2MemoryTooLow, config.Argon2.Memory, config.Argon2.Parallelism*argon2.MemoryMinParallelismMultiplier, config.Argon2.Parallelism, argon2.MemoryMinParallelismMultiplier))
} }
switch { switch {
case config.Argon2.KeyLength == 0: case config.Argon2.KeyLength == 0:
config.Argon2.KeyLength = schema.DefaultPasswordConfig.Argon2.KeyLength config.Argon2.KeyLength = schema.DefaultPasswordConfig.Argon2.KeyLength
case config.Argon2.KeyLength < crypt.Argon2KeySizeMin: case config.Argon2.KeyLength < argon2.KeyLengthMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashArgon2, "key_length", config.Argon2.KeyLength, crypt.Argon2KeySizeMin)) validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashArgon2, "key_length", config.Argon2.KeyLength, argon2.KeyLengthMin))
case config.Argon2.KeyLength > crypt.Argon2KeySizeMax: case config.Argon2.KeyLength > argon2.KeyLengthMax:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashArgon2, "key_length", config.Argon2.KeyLength, crypt.Argon2KeySizeMax)) validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashArgon2, "key_length", config.Argon2.KeyLength, argon2.KeyLengthMax))
} }
switch { switch {
case config.Argon2.SaltLength == 0: case config.Argon2.SaltLength == 0:
config.Argon2.SaltLength = schema.DefaultPasswordConfig.Argon2.SaltLength config.Argon2.SaltLength = schema.DefaultPasswordConfig.Argon2.SaltLength
case config.Argon2.SaltLength < crypt.Argon2SaltSizeMin: case config.Argon2.SaltLength < argon2.SaltLengthMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashArgon2, "salt_length", config.Argon2.SaltLength, crypt.Argon2SaltSizeMin)) validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashArgon2, "salt_length", config.Argon2.SaltLength, argon2.SaltLengthMin))
case config.Argon2.SaltLength > crypt.Argon2SaltSizeMax: case config.Argon2.SaltLength > argon2.SaltLengthMax:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashArgon2, "salt_length", config.Argon2.SaltLength, crypt.Argon2SaltSizeMax)) validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashArgon2, "salt_length", config.Argon2.SaltLength, argon2.SaltLengthMax))
} }
} }
@ -147,19 +153,19 @@ func validateFileAuthenticationBackendPasswordConfigSHA2Crypt(config *schema.Pas
switch { switch {
case config.SHA2Crypt.Iterations == 0: case config.SHA2Crypt.Iterations == 0:
config.SHA2Crypt.Iterations = schema.DefaultPasswordConfig.SHA2Crypt.Iterations config.SHA2Crypt.Iterations = schema.DefaultPasswordConfig.SHA2Crypt.Iterations
case config.SHA2Crypt.Iterations < crypt.SHA2CryptIterationsMin: case config.SHA2Crypt.Iterations < shacrypt.IterationsMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashSHA2Crypt, "iterations", config.SHA2Crypt.Iterations, crypt.SHA2CryptIterationsMin)) validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashSHA2Crypt, "iterations", config.SHA2Crypt.Iterations, shacrypt.IterationsMin))
case config.SHA2Crypt.Iterations > crypt.SHA2CryptIterationsMax: case config.SHA2Crypt.Iterations > shacrypt.IterationsMax:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashSHA2Crypt, "iterations", config.SHA2Crypt.Iterations, crypt.SHA2CryptIterationsMax)) validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashSHA2Crypt, "iterations", config.SHA2Crypt.Iterations, shacrypt.IterationsMax))
} }
switch { switch {
case config.SHA2Crypt.SaltLength == 0: case config.SHA2Crypt.SaltLength == 0:
config.SHA2Crypt.SaltLength = schema.DefaultPasswordConfig.SHA2Crypt.SaltLength config.SHA2Crypt.SaltLength = schema.DefaultPasswordConfig.SHA2Crypt.SaltLength
case config.SHA2Crypt.SaltLength < crypt.SHA2CryptSaltSizeMin: case config.SHA2Crypt.SaltLength < shacrypt.SaltLengthMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashSHA2Crypt, "salt_length", config.SHA2Crypt.SaltLength, crypt.SHA2CryptSaltSizeMin)) validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashSHA2Crypt, "salt_length", config.SHA2Crypt.SaltLength, shacrypt.SaltLengthMin))
case config.SHA2Crypt.SaltLength > crypt.SHA2CryptSaltSizeMax: case config.SHA2Crypt.SaltLength > shacrypt.SaltLengthMax:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashSHA2Crypt, "salt_length", config.SHA2Crypt.SaltLength, crypt.SHA2CryptSaltSizeMax)) validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashSHA2Crypt, "salt_length", config.SHA2Crypt.SaltLength, shacrypt.SaltLengthMax))
} }
} }
@ -176,19 +182,19 @@ func validateFileAuthenticationBackendPasswordConfigPBKDF2(config *schema.Passwo
switch { switch {
case config.PBKDF2.Iterations == 0: case config.PBKDF2.Iterations == 0:
config.PBKDF2.Iterations = schema.DefaultPasswordConfig.PBKDF2.Iterations config.PBKDF2.Iterations = schema.DefaultPasswordConfig.PBKDF2.Iterations
case config.PBKDF2.Iterations < crypt.PBKDF2IterationsMin: case config.PBKDF2.Iterations < pbkdf2.IterationsMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashPBKDF2, "iterations", config.PBKDF2.Iterations, crypt.PBKDF2IterationsMin)) validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashPBKDF2, "iterations", config.PBKDF2.Iterations, pbkdf2.IterationsMin))
case config.PBKDF2.Iterations > crypt.PBKDF2IterationsMax: case config.PBKDF2.Iterations > pbkdf2.IterationsMax:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashPBKDF2, "iterations", config.PBKDF2.Iterations, crypt.PBKDF2IterationsMax)) validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashPBKDF2, "iterations", config.PBKDF2.Iterations, pbkdf2.IterationsMax))
} }
switch { switch {
case config.PBKDF2.SaltLength == 0: case config.PBKDF2.SaltLength == 0:
config.PBKDF2.SaltLength = schema.DefaultPasswordConfig.PBKDF2.SaltLength config.PBKDF2.SaltLength = schema.DefaultPasswordConfig.PBKDF2.SaltLength
case config.PBKDF2.SaltLength < crypt.PBKDF2SaltSizeMin: case config.PBKDF2.SaltLength < pbkdf2.SaltLengthMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashPBKDF2, "salt_length", config.PBKDF2.SaltLength, crypt.PBKDF2SaltSizeMin)) validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashPBKDF2, "salt_length", config.PBKDF2.SaltLength, pbkdf2.SaltLengthMin))
case config.PBKDF2.SaltLength > crypt.PBKDF2SaltSizeMax: case config.PBKDF2.SaltLength > pbkdf2.SaltLengthMax:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashPBKDF2, "salt_length", config.PBKDF2.SaltLength, crypt.PBKDF2SaltSizeMax)) validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashPBKDF2, "salt_length", config.PBKDF2.SaltLength, pbkdf2.SaltLengthMax))
} }
} }
@ -205,53 +211,58 @@ func validateFileAuthenticationBackendPasswordConfigBCrypt(config *schema.Passwo
switch { switch {
case config.BCrypt.Cost == 0: case config.BCrypt.Cost == 0:
config.BCrypt.Cost = schema.DefaultPasswordConfig.BCrypt.Cost config.BCrypt.Cost = schema.DefaultPasswordConfig.BCrypt.Cost
case config.BCrypt.Cost < crypt.BcryptCostMin: case config.BCrypt.Cost < bcrypt.IterationsMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashBCrypt, "cost", config.BCrypt.Cost, crypt.BcryptCostMin)) validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashBCrypt, "cost", config.BCrypt.Cost, bcrypt.IterationsMin))
case config.BCrypt.Cost > crypt.BcryptCostMax: case config.BCrypt.Cost > bcrypt.IterationsMax:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashBCrypt, "cost", config.BCrypt.Cost, crypt.BcryptCostMax)) validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashBCrypt, "cost", config.BCrypt.Cost, bcrypt.IterationsMax))
} }
} }
//nolint:gocyclo
func validateFileAuthenticationBackendPasswordConfigSCrypt(config *schema.Password, validator *schema.StructValidator) { func validateFileAuthenticationBackendPasswordConfigSCrypt(config *schema.Password, validator *schema.StructValidator) {
switch { switch {
case config.SCrypt.Iterations == 0: case config.SCrypt.Iterations == 0:
config.SCrypt.Iterations = schema.DefaultPasswordConfig.SCrypt.Iterations config.SCrypt.Iterations = schema.DefaultPasswordConfig.SCrypt.Iterations
case config.SCrypt.Iterations < crypt.ScryptIterationsMin: case config.SCrypt.Iterations < scrypt.IterationsMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashSCrypt, "iterations", config.SCrypt.Iterations, crypt.ScryptIterationsMin)) validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashSCrypt, "iterations", config.SCrypt.Iterations, scrypt.IterationsMin))
case config.SCrypt.Iterations > scrypt.IterationsMax:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashSCrypt, "iterations", config.SCrypt.Iterations, scrypt.IterationsMax))
} }
switch { switch {
case config.SCrypt.BlockSize == 0: case config.SCrypt.BlockSize == 0:
config.SCrypt.BlockSize = schema.DefaultPasswordConfig.SCrypt.BlockSize config.SCrypt.BlockSize = schema.DefaultPasswordConfig.SCrypt.BlockSize
case config.SCrypt.BlockSize < crypt.ScryptBlockSizeMin: case config.SCrypt.BlockSize < scrypt.BlockSizeMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashSCrypt, "block_size", config.SCrypt.BlockSize, crypt.ScryptBlockSizeMin)) validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashSCrypt, "block_size", config.SCrypt.BlockSize, scrypt.BlockSizeMin))
case config.SCrypt.BlockSize > crypt.ScryptBlockSizeMax: case config.SCrypt.BlockSize > scrypt.BlockSizeMax:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashSCrypt, "block_size", config.SCrypt.BlockSize, crypt.ScryptBlockSizeMax)) validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashSCrypt, "block_size", config.SCrypt.BlockSize, scrypt.BlockSizeMax))
} }
switch { switch {
case config.SCrypt.Parallelism == 0: case config.SCrypt.Parallelism == 0:
config.SCrypt.Parallelism = schema.DefaultPasswordConfig.SCrypt.Parallelism config.SCrypt.Parallelism = schema.DefaultPasswordConfig.SCrypt.Parallelism
case config.SCrypt.Parallelism < crypt.ScryptParallelismMin: case config.SCrypt.Parallelism < scrypt.ParallelismMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashSCrypt, "parallelism", config.SCrypt.Parallelism, crypt.ScryptParallelismMin)) validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashSCrypt, "parallelism", config.SCrypt.Parallelism, scrypt.ParallelismMin))
case config.SCrypt.Parallelism > scrypt.ParallelismMax:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashSCrypt, "parallelism", config.SCrypt.Parallelism, scrypt.ParallelismMax))
} }
switch { switch {
case config.SCrypt.KeyLength == 0: case config.SCrypt.KeyLength == 0:
config.SCrypt.KeyLength = schema.DefaultPasswordConfig.SCrypt.KeyLength config.SCrypt.KeyLength = schema.DefaultPasswordConfig.SCrypt.KeyLength
case config.SCrypt.KeyLength < crypt.ScryptKeySizeMin: case config.SCrypt.KeyLength < scrypt.KeyLengthMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashSCrypt, "key_length", config.SCrypt.KeyLength, crypt.ScryptKeySizeMin)) validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashSCrypt, "key_length", config.SCrypt.KeyLength, scrypt.KeyLengthMin))
case config.SCrypt.KeyLength > crypt.ScryptKeySizeMax: case config.SCrypt.KeyLength > scrypt.KeyLengthMax:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashSCrypt, "key_length", config.SCrypt.KeyLength, crypt.ScryptKeySizeMax)) validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashSCrypt, "key_length", config.SCrypt.KeyLength, scrypt.KeyLengthMax))
} }
switch { switch {
case config.SCrypt.SaltLength == 0: case config.SCrypt.SaltLength == 0:
config.SCrypt.SaltLength = schema.DefaultPasswordConfig.SCrypt.SaltLength config.SCrypt.SaltLength = schema.DefaultPasswordConfig.SCrypt.SaltLength
case config.SCrypt.SaltLength < crypt.ScryptSaltSizeMin: case config.SCrypt.SaltLength < scrypt.SaltLengthMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashSCrypt, "salt_length", config.SCrypt.SaltLength, crypt.ScryptSaltSizeMin)) validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashSCrypt, "salt_length", config.SCrypt.SaltLength, scrypt.SaltLengthMin))
case config.SCrypt.SaltLength > crypt.ScryptSaltSizeMax: case config.SCrypt.SaltLength > scrypt.SaltLengthMax:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashSCrypt, "salt_length", config.SCrypt.SaltLength, crypt.ScryptSaltSizeMax)) validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashSCrypt, "salt_length", config.SCrypt.SaltLength, scrypt.SaltLengthMax))
} }
} }

View File

@ -409,18 +409,22 @@ func (suite *FileBasedAuthenticationBackend) TestShouldRaiseErrorWhenSCryptOptio
} }
func (suite *FileBasedAuthenticationBackend) TestShouldRaiseErrorWhenSCryptOptionsTooHigh() { func (suite *FileBasedAuthenticationBackend) TestShouldRaiseErrorWhenSCryptOptionsTooHigh() {
suite.config.File.Password.SCrypt.Iterations = 59
suite.config.File.Password.SCrypt.BlockSize = 360287970189639672 suite.config.File.Password.SCrypt.BlockSize = 360287970189639672
suite.config.File.Password.SCrypt.Parallelism = 1073741825
suite.config.File.Password.SCrypt.KeyLength = 1374389534409 suite.config.File.Password.SCrypt.KeyLength = 1374389534409
suite.config.File.Password.SCrypt.SaltLength = 2147483647 suite.config.File.Password.SCrypt.SaltLength = 2147483647
ValidateAuthenticationBackend(&suite.config, suite.validator) ValidateAuthenticationBackend(&suite.config, suite.validator)
suite.Assert().Len(suite.validator.Warnings(), 0) suite.Assert().Len(suite.validator.Warnings(), 0)
suite.Require().Len(suite.validator.Errors(), 3) suite.Require().Len(suite.validator.Errors(), 5)
suite.Assert().EqualError(suite.validator.Errors()[0], "authentication_backend: file: password: scrypt: option 'block_size' is configured as '360287970189639672' but must be less than or equal to '36028797018963967'") suite.Assert().EqualError(suite.validator.Errors()[0], "authentication_backend: file: password: scrypt: option 'iterations' is configured as '59' but must be less than or equal to '58'")
suite.Assert().EqualError(suite.validator.Errors()[1], "authentication_backend: file: password: scrypt: option 'key_length' is configured as '1374389534409' but must be less than or equal to '137438953440'") suite.Assert().EqualError(suite.validator.Errors()[1], "authentication_backend: file: password: scrypt: option 'block_size' is configured as '360287970189639672' but must be less than or equal to '36028797018963967'")
suite.Assert().EqualError(suite.validator.Errors()[2], "authentication_backend: file: password: scrypt: option 'salt_length' is configured as '2147483647' but must be less than or equal to '1024'") suite.Assert().EqualError(suite.validator.Errors()[2], "authentication_backend: file: password: scrypt: option 'parallelism' is configured as '1073741825' but must be less than or equal to '1073741823'")
suite.Assert().EqualError(suite.validator.Errors()[3], "authentication_backend: file: password: scrypt: option 'key_length' is configured as '1374389534409' but must be less than or equal to '137438953440'")
suite.Assert().EqualError(suite.validator.Errors()[4], "authentication_backend: file: password: scrypt: option 'salt_length' is configured as '2147483647' but must be less than or equal to '1024'")
} }
func (suite *FileBasedAuthenticationBackend) TestShouldRaiseErrorWhenArgon2OptionsTooLow() { func (suite *FileBasedAuthenticationBackend) TestShouldRaiseErrorWhenArgon2OptionsTooLow() {
@ -437,13 +441,14 @@ func (suite *FileBasedAuthenticationBackend) TestShouldRaiseErrorWhenArgon2Optio
suite.Assert().EqualError(suite.validator.Errors()[0], "authentication_backend: file: password: argon2: option 'iterations' is configured as '-1' but must be greater than or equal to '1'") suite.Assert().EqualError(suite.validator.Errors()[0], "authentication_backend: file: password: argon2: option 'iterations' is configured as '-1' but must be greater than or equal to '1'")
suite.Assert().EqualError(suite.validator.Errors()[1], "authentication_backend: file: password: argon2: option 'parallelism' is configured as '-1' but must be greater than or equal to '1'") suite.Assert().EqualError(suite.validator.Errors()[1], "authentication_backend: file: password: argon2: option 'parallelism' is configured as '-1' but must be greater than or equal to '1'")
suite.Assert().EqualError(suite.validator.Errors()[2], "authentication_backend: file: password: argon2: option 'memory' is configured as '-1' but must be greater than or equal to '1'") suite.Assert().EqualError(suite.validator.Errors()[2], "authentication_backend: file: password: argon2: option 'memory' is configured as '-1' but must be greater than or equal to '8'")
suite.Assert().EqualError(suite.validator.Errors()[3], "authentication_backend: file: password: argon2: option 'key_length' is configured as '1' but must be greater than or equal to '4'") suite.Assert().EqualError(suite.validator.Errors()[3], "authentication_backend: file: password: argon2: option 'key_length' is configured as '1' but must be greater than or equal to '4'")
suite.Assert().EqualError(suite.validator.Errors()[4], "authentication_backend: file: password: argon2: option 'salt_length' is configured as '-1' but must be greater than or equal to '1'") suite.Assert().EqualError(suite.validator.Errors()[4], "authentication_backend: file: password: argon2: option 'salt_length' is configured as '-1' but must be greater than or equal to '1'")
} }
func (suite *FileBasedAuthenticationBackend) TestShouldRaiseErrorWhenArgon2OptionsTooHigh() { func (suite *FileBasedAuthenticationBackend) TestShouldRaiseErrorWhenArgon2OptionsTooHigh() {
suite.config.File.Password.Argon2.Iterations = 9999999999 suite.config.File.Password.Argon2.Iterations = 9999999999
suite.config.File.Password.Argon2.Memory = 4294967296
suite.config.File.Password.Argon2.Parallelism = 16777216 suite.config.File.Password.Argon2.Parallelism = 16777216
suite.config.File.Password.Argon2.KeyLength = 9999999998 suite.config.File.Password.Argon2.KeyLength = 9999999998
suite.config.File.Password.Argon2.SaltLength = 9999999997 suite.config.File.Password.Argon2.SaltLength = 9999999997
@ -455,6 +460,7 @@ func (suite *FileBasedAuthenticationBackend) TestShouldRaiseErrorWhenArgon2Optio
suite.Assert().EqualError(suite.validator.Errors()[0], "authentication_backend: file: password: argon2: option 'iterations' is configured as '9999999999' but must be less than or equal to '2147483647'") suite.Assert().EqualError(suite.validator.Errors()[0], "authentication_backend: file: password: argon2: option 'iterations' is configured as '9999999999' but must be less than or equal to '2147483647'")
suite.Assert().EqualError(suite.validator.Errors()[1], "authentication_backend: file: password: argon2: option 'parallelism' is configured as '16777216' but must be less than or equal to '16777215'") suite.Assert().EqualError(suite.validator.Errors()[1], "authentication_backend: file: password: argon2: option 'parallelism' is configured as '16777216' but must be less than or equal to '16777215'")
suite.Assert().EqualError(suite.validator.Errors()[2], "authentication_backend: file: password: argon2: option 'memory' is configured as '4294967296' but must be less than or equal to '4294967295'")
suite.Assert().EqualError(suite.validator.Errors()[3], "authentication_backend: file: password: argon2: option 'key_length' is configured as '9999999998' but must be less than or equal to '2147483647'") suite.Assert().EqualError(suite.validator.Errors()[3], "authentication_backend: file: password: argon2: option 'key_length' is configured as '9999999998' but must be less than or equal to '2147483647'")
suite.Assert().EqualError(suite.validator.Errors()[4], "authentication_backend: file: password: argon2: option 'salt_length' is configured as '9999999997' but must be less than or equal to '2147483647'") suite.Assert().EqualError(suite.validator.Errors()[4], "authentication_backend: file: password: argon2: option 'salt_length' is configured as '9999999997' but must be less than or equal to '2147483647'")
} }
@ -468,7 +474,19 @@ func (suite *FileBasedAuthenticationBackend) TestShouldRaiseErrorWhenArgon2Memor
suite.Assert().Len(suite.validator.Warnings(), 0) suite.Assert().Len(suite.validator.Warnings(), 0)
suite.Require().Len(suite.validator.Errors(), 1) suite.Require().Len(suite.validator.Errors(), 1)
suite.Assert().EqualError(suite.validator.Errors()[0], "authentication_backend: file: password: argon2: option 'memory' is configured as '4' but must be greater than or equal to '32' or '4' (the value of 'parallelism) multiplied by '8'") suite.Assert().EqualError(suite.validator.Errors()[0], "authentication_backend: file: password: argon2: option 'memory' is configured as '4' but must be greater than or equal to '8'")
}
func (suite *FileBasedAuthenticationBackend) TestShouldRaiseErrorWhenArgon2MemoryTooLowMultiplier() {
suite.config.File.Password.Argon2.Memory = 8
suite.config.File.Password.Argon2.Parallelism = 4
ValidateAuthenticationBackend(&suite.config, suite.validator)
suite.Assert().Len(suite.validator.Warnings(), 0)
suite.Require().Len(suite.validator.Errors(), 1)
suite.Assert().EqualError(suite.validator.Errors()[0], "authentication_backend: file: password: argon2: option 'memory' is configured as '8' but must be greater than or equal to '32' or '4' (the value of 'parallelism) multiplied by '8'")
} }
func (suite *FileBasedAuthenticationBackend) TestShouldRaiseErrorWhenBadAlgorithmDefined() { func (suite *FileBasedAuthenticationBackend) TestShouldRaiseErrorWhenBadAlgorithmDefined() {

View File

@ -838,7 +838,7 @@ func TestValidateOIDCClientRedirectURIsSupportingPrivateUseURISchemes(t *testing
} }
func MustDecodeSecret(value string) *schema.PasswordDigest { func MustDecodeSecret(value string) *schema.PasswordDigest {
if secret, err := schema.NewPasswordDigest(value, true); err != nil { if secret, err := schema.DecodePasswordDigest(value); err != nil {
panic(err) panic(err)
} else { } else {
return secret return secret

View File

@ -52,13 +52,7 @@ func OpenIDConnectAuthorization(ctx *middlewares.AutheliaCtx, rw http.ResponseWr
return return
} }
if issuer, err = ctx.IssuerURL(); err != nil { issuer = ctx.RootURL()
ctx.Logger.Errorf("Authorization Request with id '%s' on client with id '%s' could not be processed: error occurred determining issuer: %+v", requester.GetID(), clientID, err)
ctx.Providers.OpenIDConnect.WriteAuthorizeError(ctx, rw, requester, oidc.ErrIssuerCouldNotDerive)
return
}
userSession := ctx.GetSession() userSession := ctx.GetSession()

View File

@ -130,12 +130,7 @@ func OpenIDConnectConsentPOST(ctx *middlewares.AutheliaCtx) {
query url.Values query url.Values
) )
if redirectURI, err = ctx.IssuerURL(); err != nil { redirectURI = ctx.RootURL()
ctx.Logger.Errorf("Failed to parse the consent redirect URL: %+v", err)
ctx.SetJSONError(messageOperationFailed)
return
}
if query, err = url.ParseQuery(consent.Form); err != nil { if query, err = url.ParseQuery(consent.Form); err != nil {
ctx.Logger.Errorf("Failed to parse the consent form values: %+v", err) ctx.Logger.Errorf("Failed to parse the consent form values: %+v", err)

View File

@ -20,13 +20,7 @@ func OpenIDConnectConfigurationWellKnownGET(ctx *middlewares.AutheliaCtx) {
err error err error
) )
if issuer, err = ctx.IssuerURL(); err != nil { issuer = ctx.RootURL()
ctx.Logger.Errorf("Error occurred determining OpenID Connect issuer details: %+v", err)
ctx.ReplyStatusCode(fasthttp.StatusBadRequest)
return
}
wellKnown := ctx.Providers.OpenIDConnect.GetOpenIDConnectWellKnownConfiguration(issuer.String()) wellKnown := ctx.Providers.OpenIDConnect.GetOpenIDConnectWellKnownConfiguration(issuer.String())
@ -52,13 +46,7 @@ func OAuthAuthorizationServerWellKnownGET(ctx *middlewares.AutheliaCtx) {
err error err error
) )
if issuer, err = ctx.IssuerURL(); err != nil { issuer = ctx.RootURL()
ctx.Logger.Errorf("Error occurred determining OpenID Connect issuer details: %+v", err)
ctx.ReplyStatusCode(fasthttp.StatusBadRequest)
return
}
wellKnown := ctx.Providers.OpenIDConnect.GetOAuth2WellKnownConfiguration(issuer.String()) wellKnown := ctx.Providers.OpenIDConnect.GetOAuth2WellKnownConfiguration(issuer.String())

View File

@ -144,11 +144,7 @@ func handleOIDCWorkflowResponseWithTargetURL(ctx *middlewares.AutheliaCtx, targe
return return
} }
if issuerURL, err = ctx.IssuerURL(); err != nil { issuerURL = ctx.RootURL()
ctx.Error(fmt.Errorf("unable to get issuer for redirection: %w", err), messageAuthenticationFailed)
return
}
if targetURL.Host != issuerURL.Host { if targetURL.Host != issuerURL.Host {
ctx.Error(fmt.Errorf("unable to redirect to '%s': target host '%s' does not match expected issuer host '%s'", targetURL, targetURL.Host, issuerURL.Host), messageAuthenticationFailed) ctx.Error(fmt.Errorf("unable to redirect to '%s': target host '%s' does not match expected issuer host '%s'", targetURL, targetURL.Host, issuerURL.Host), messageAuthenticationFailed)
@ -221,11 +217,7 @@ func handleOIDCWorkflowResponseWithID(ctx *middlewares.AutheliaCtx, id string) {
form url.Values form url.Values
) )
if targetURL, err = ctx.IssuerURL(); err != nil { targetURL = ctx.RootURL()
ctx.Error(fmt.Errorf("unable to get issuer for redirection: %w", err), messageAuthenticationFailed)
return
}
if form, err = consent.GetForm(); err != nil { if form, err = consent.GetForm(); err != nil {
ctx.Error(fmt.Errorf("unable to get authorization form values from consent session with challenge id '%s': %w", consent.ChallengeID, err), messageAuthenticationFailed) ctx.Error(fmt.Errorf("unable to get authorization form values from consent session with challenge id '%s': %w", consent.ChallengeID, err), messageAuthenticationFailed)

View File

@ -3,7 +3,6 @@ package logging
import ( import (
"fmt" "fmt"
"io" "io"
"log"
"os" "os"
"runtime" "runtime"
"testing" "testing"
@ -16,15 +15,10 @@ import (
) )
func TestShouldWriteLogsToFile(t *testing.T) { func TestShouldWriteLogsToFile(t *testing.T) {
dir, err := os.MkdirTemp("/tmp", "logs-dir") dir := t.TempDir()
if err != nil {
log.Fatal(err)
}
defer os.RemoveAll(dir)
path := fmt.Sprintf("%s/authelia.log", dir) path := fmt.Sprintf("%s/authelia.log", dir)
err = InitializeLogger(schema.LogConfiguration{Format: "text", FilePath: path, KeepStdout: false}, false) err := InitializeLogger(schema.LogConfiguration{Format: "text", FilePath: path, KeepStdout: false}, false)
require.NoError(t, err) require.NoError(t, err)
Logger().Info("This is a test") Logger().Info("This is a test")
@ -39,15 +33,10 @@ func TestShouldWriteLogsToFile(t *testing.T) {
} }
func TestShouldWriteLogsToFileAndStdout(t *testing.T) { func TestShouldWriteLogsToFileAndStdout(t *testing.T) {
dir, err := os.MkdirTemp("/tmp", "logs-dir") dir := t.TempDir()
if err != nil {
log.Fatal(err)
}
defer os.RemoveAll(dir)
path := fmt.Sprintf("%s/authelia.log", dir) path := fmt.Sprintf("%s/authelia.log", dir)
err = InitializeLogger(schema.LogConfiguration{Format: "text", FilePath: path, KeepStdout: true}, false) err := InitializeLogger(schema.LogConfiguration{Format: "text", FilePath: path, KeepStdout: true}, false)
require.NoError(t, err) require.NoError(t, err)
Logger().Info("This is a test") Logger().Info("This is a test")
@ -62,15 +51,10 @@ func TestShouldWriteLogsToFileAndStdout(t *testing.T) {
} }
func TestShouldFormatLogsAsJSON(t *testing.T) { func TestShouldFormatLogsAsJSON(t *testing.T) {
dir, err := os.MkdirTemp("/tmp", "logs-dir") dir := t.TempDir()
if err != nil {
log.Fatal(err)
}
defer os.RemoveAll(dir)
path := fmt.Sprintf("%s/authelia.log", dir) path := fmt.Sprintf("%s/authelia.log", dir)
err = InitializeLogger(schema.LogConfiguration{Format: "json", FilePath: path, KeepStdout: false}, false) err := InitializeLogger(schema.LogConfiguration{Format: "json", FilePath: path, KeepStdout: false}, false)
require.NoError(t, err) require.NoError(t, err)
Logger().Info("This is a test") Logger().Info("This is a test")

View File

@ -5,7 +5,6 @@ import (
"fmt" "fmt"
"net" "net"
"net/url" "net/url"
"path"
"strings" "strings"
"github.com/asaskevich/govalidator" "github.com/asaskevich/govalidator"
@ -81,7 +80,7 @@ func (ctx *AutheliaCtx) ReplyError(err error, message string) {
ctx.Logger.Error(marshalErr) ctx.Logger.Error(marshalErr)
} }
ctx.SetContentTypeBytes(contentTypeApplicationJSON) ctx.SetContentTypeApplicationJSON()
ctx.SetBody(b) ctx.SetBody(b)
ctx.Logger.Debug(err) ctx.Logger.Debug(err)
} }
@ -90,7 +89,7 @@ func (ctx *AutheliaCtx) ReplyError(err error, message string) {
func (ctx *AutheliaCtx) ReplyStatusCode(statusCode int) { func (ctx *AutheliaCtx) ReplyStatusCode(statusCode int) {
ctx.Response.Reset() ctx.Response.Reset()
ctx.SetStatusCode(statusCode) ctx.SetStatusCode(statusCode)
ctx.SetContentTypeBytes(contentTypeTextPlain) ctx.SetContentTypeTextPlain()
ctx.SetBodyString(fmt.Sprintf("%d %s", statusCode, fasthttp.StatusMessage(statusCode))) ctx.SetBodyString(fmt.Sprintf("%d %s", statusCode, fasthttp.StatusMessage(statusCode)))
} }
@ -108,7 +107,7 @@ func (ctx *AutheliaCtx) ReplyJSON(data any, statusCode int) (err error) {
ctx.SetStatusCode(statusCode) ctx.SetStatusCode(statusCode)
} }
ctx.SetContentTypeBytes(contentTypeApplicationJSON) ctx.SetContentTypeApplicationJSON()
ctx.SetBody(body) ctx.SetBody(body)
return nil return nil
@ -145,7 +144,7 @@ func (ctx *AutheliaCtx) XForwardedProto() (proto []byte) {
} }
// XForwardedMethod return the content of the X-Forwarded-Method header. // XForwardedMethod return the content of the X-Forwarded-Method header.
func (ctx *AutheliaCtx) XForwardedMethod() (method []byte) { func (ctx *AutheliaCtx) XForwardedMethod() []byte {
return ctx.RequestCtx.Request.Header.PeekBytes(headerXForwardedMethod) return ctx.RequestCtx.Request.Header.PeekBytes(headerXForwardedMethod)
} }
@ -171,79 +170,61 @@ func (ctx *AutheliaCtx) XForwardedURI() (uri []byte) {
return uri return uri
} }
// XAutheliaURL return the content of the X-Authelia-URL header. // XOriginalURL returns the content of the X-Original-URL header.
func (ctx *AutheliaCtx) XAutheliaURL() (autheliaURL []byte) { func (ctx *AutheliaCtx) XOriginalURL() []byte {
return ctx.RequestCtx.Request.Header.PeekBytes(headerXOriginalURL)
}
// XOriginalMethod return the content of the X-Original-Method header.
func (ctx *AutheliaCtx) XOriginalMethod() []byte {
return ctx.RequestCtx.Request.Header.PeekBytes(headerXOriginalMethod)
}
// XAutheliaURL return the content of the X-Authelia-URL header which is used to communicate the location of the
// portal when using proxies like Envoy.
func (ctx *AutheliaCtx) XAutheliaURL() []byte {
return ctx.RequestCtx.Request.Header.PeekBytes(headerXAutheliaURL) return ctx.RequestCtx.Request.Header.PeekBytes(headerXAutheliaURL)
} }
// QueryArgRedirect return the content of the rd query argument. // QueryArgRedirect return the content of the rd query argument.
func (ctx *AutheliaCtx) QueryArgRedirect() (val []byte) { func (ctx *AutheliaCtx) QueryArgRedirect() []byte {
return ctx.RequestCtx.QueryArgs().PeekBytes(queryArgRedirect) return ctx.RequestCtx.QueryArgs().PeekBytes(qryArgRedirect)
} }
// BasePath returns the base_url as per the path visited by the client. // BasePath returns the base_url as per the path visited by the client.
func (ctx *AutheliaCtx) BasePath() (base string) { func (ctx *AutheliaCtx) BasePath() string {
if baseURL := ctx.UserValueBytes(UserValueKeyBaseURL); baseURL != nil { if baseURL := ctx.UserValueBytes(UserValueKeyBaseURL); baseURL != nil {
return baseURL.(string) return baseURL.(string)
} }
return base return ""
} }
// ExternalRootURL gets the X-Forwarded-Proto, X-Forwarded-Host headers and the BasePath and forms them into a URL. // BasePathSlash is the same as BasePath but returns a final slash as well.
func (ctx *AutheliaCtx) ExternalRootURL() (string, error) { func (ctx *AutheliaCtx) BasePathSlash() string {
protocol := ctx.XForwardedProto() if baseURL := ctx.UserValueBytes(UserValueKeyBaseURL); baseURL != nil {
if protocol == nil { return baseURL.(string) + strSlash
return "", errMissingXForwardedProto
} }
host := ctx.XForwardedHost() return strSlash
if host == nil {
return "", errMissingXForwardedHost
}
externalRootURL := fmt.Sprintf("%s://%s", protocol, host)
if base := ctx.BasePath(); base != "" {
externalBaseURL, err := url.ParseRequestURI(externalRootURL)
if err != nil {
return "", err
}
externalBaseURL.Path = path.Join(externalBaseURL.Path, base)
return externalBaseURL.String(), nil
}
return externalRootURL, nil
} }
// IssuerURL returns the expected Issuer. // RootURL returns the Root URL.
func (ctx *AutheliaCtx) IssuerURL() (issuerURL *url.URL, err error) { func (ctx *AutheliaCtx) RootURL() (issuerURL *url.URL) {
issuerURL = &url.URL{ return &url.URL{
Scheme: "https", Scheme: string(ctx.XForwardedProto()),
Host: string(ctx.XForwardedHost()),
Path: ctx.BasePath(),
} }
if scheme := ctx.XForwardedProto(); scheme != nil {
issuerURL.Scheme = string(scheme)
}
if host := ctx.XForwardedHost(); len(host) != 0 {
issuerURL.Host = string(host)
} else {
return nil, errMissingXForwardedHost
}
if base := ctx.BasePath(); base != "" {
issuerURL.Path = path.Join(issuerURL.Path, base)
}
return issuerURL, nil
} }
// XOriginalURL return the content of the X-Original-URL header. // RootURLSlash is the same as RootURL but includes a final slash as well.
func (ctx *AutheliaCtx) XOriginalURL() []byte { func (ctx *AutheliaCtx) RootURLSlash() (issuerURL *url.URL) {
return ctx.RequestCtx.Request.Header.PeekBytes(headerXOriginalURL) return &url.URL{
Scheme: string(ctx.XForwardedProto()),
Host: string(ctx.XForwardedHost()),
Path: ctx.BasePathSlash(),
}
} }
// GetSession return the user session. Any update will be saved in cache. // GetSession return the user session. Any update will be saved in cache.
@ -264,7 +245,7 @@ func (ctx *AutheliaCtx) SaveSession(userSession session.UserSession) error {
// ReplyOK is a helper method to reply ok. // ReplyOK is a helper method to reply ok.
func (ctx *AutheliaCtx) ReplyOK() { func (ctx *AutheliaCtx) ReplyOK() {
ctx.SetContentTypeBytes(contentTypeApplicationJSON) ctx.SetContentTypeApplicationJSON()
ctx.SetBody(okMessageBytes) ctx.SetBody(okMessageBytes)
} }
@ -377,7 +358,7 @@ func (ctx *AutheliaCtx) SpecialRedirect(uri string, statusCode int) {
statusCode = fasthttp.StatusFound statusCode = fasthttp.StatusFound
} }
ctx.SetContentTypeBytes(contentTypeTextHTML) ctx.SetContentTypeTextHTML()
ctx.SetStatusCode(statusCode) ctx.SetStatusCode(statusCode)
u := fasthttp.AcquireURI() u := fasthttp.AcquireURI()
@ -400,3 +381,18 @@ func (ctx *AutheliaCtx) RecordAuthentication(success, regulated bool, method str
ctx.Providers.Metrics.RecordAuthentication(success, regulated, method) ctx.Providers.Metrics.RecordAuthentication(success, regulated, method)
} }
// SetContentTypeTextPlain efficiently sets the Content-Type header to 'text/plain; charset=utf-8'.
func (ctx *AutheliaCtx) SetContentTypeTextPlain() {
ctx.SetContentTypeBytes(contentTypeTextPlain)
}
// SetContentTypeTextHTML efficiently sets the Content-Type header to 'text/html; charset=utf-8'.
func (ctx *AutheliaCtx) SetContentTypeTextHTML() {
ctx.SetContentTypeBytes(contentTypeTextHTML)
}
// SetContentTypeApplicationJSON efficiently sets the Content-Type header to 'application/json; charset=utf-8'.
func (ctx *AutheliaCtx) SetContentTypeApplicationJSON() {
ctx.SetContentTypeBytes(contentTypeApplicationJSON)
}

View File

@ -21,7 +21,6 @@ func TestIssuerURL(t *testing.T) {
name string name string
proto, host, base string proto, host, base string
expected string expected string
err string
}{ }{
{ {
name: "Standard", name: "Standard",
@ -36,7 +35,7 @@ func TestIssuerURL(t *testing.T) {
{ {
name: "NoHost", name: "NoHost",
proto: "https", host: "", base: "", proto: "https", host: "", base: "",
err: "Missing header X-Forwarded-Host", expected: "https:",
}, },
} }
@ -52,21 +51,14 @@ func TestIssuerURL(t *testing.T) {
mock.Ctx.SetUserValue("base_url", tc.base) mock.Ctx.SetUserValue("base_url", tc.base)
} }
actual, err := mock.Ctx.IssuerURL() actual := mock.Ctx.RootURL()
switch tc.err {
case "":
assert.NoError(t, err)
require.NotNil(t, actual) require.NotNil(t, actual)
assert.Equal(t, tc.expected, actual.String()) assert.Equal(t, tc.expected, actual.String())
assert.Equal(t, tc.proto, actual.Scheme) assert.Equal(t, tc.proto, actual.Scheme)
assert.Equal(t, tc.host, actual.Host) assert.Equal(t, tc.host, actual.Host)
assert.Equal(t, tc.base, actual.Path) assert.Equal(t, tc.base, actual.Path)
default:
assert.EqualError(t, err, tc.err)
assert.Nil(t, actual)
}
}) })
} }
} }

View File

@ -20,6 +20,7 @@ var (
headerXForwardedURI = []byte("X-Forwarded-URI") headerXForwardedURI = []byte("X-Forwarded-URI")
headerXOriginalURL = []byte("X-Original-URL") headerXOriginalURL = []byte("X-Original-URL")
headerXOriginalMethod = []byte("X-Original-Method")
headerXForwardedMethod = []byte("X-Forwarded-Method") headerXForwardedMethod = []byte("X-Forwarded-Method")
headerVary = []byte(fasthttp.HeaderVary) headerVary = []byte(fasthttp.HeaderVary)
@ -67,13 +68,17 @@ var (
const ( const (
strProtoHTTPS = "https" strProtoHTTPS = "https"
strProtoHTTP = "http" strProtoHTTP = "http"
strSlash = "/"
queryArgRedirect = "rd"
queryArgToken = "token"
) )
var ( var (
protoHTTPS = []byte(strProtoHTTPS) protoHTTPS = []byte(strProtoHTTPS)
protoHTTP = []byte(strProtoHTTP) protoHTTP = []byte(strProtoHTTP)
queryArgRedirect = []byte("rd") qryArgRedirect = []byte(queryArgRedirect)
// UserValueKeyBaseURL is the User Value key where we store the Base URL. // UserValueKeyBaseURL is the User Value key where we store the Base URL.
UserValueKeyBaseURL = []byte("base_url") UserValueKeyBaseURL = []byte("base_url")

View File

@ -5,6 +5,7 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/mail" "net/mail"
"path"
"time" "time"
"github.com/golang-jwt/jwt/v4" "github.com/golang-jwt/jwt/v4"
@ -62,7 +63,7 @@ func IdentityVerificationStart(args IdentityVerificationStartArgs, delayFunc Tim
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
ss, err := token.SignedString([]byte(ctx.Configuration.JWTSecret)) signedToken, err := token.SignedString([]byte(ctx.Configuration.JWTSecret))
if err != nil { if err != nil {
ctx.Error(err, messageOperationFailed) ctx.Error(err, messageOperationFailed)
return return
@ -73,23 +74,23 @@ func IdentityVerificationStart(args IdentityVerificationStartArgs, delayFunc Tim
return return
} }
var (
uri string
)
if uri, err = ctx.ExternalRootURL(); err != nil {
ctx.Error(err, messageOperationFailed)
return
}
disableHTML := false disableHTML := false
if ctx.Configuration.Notifier.SMTP != nil { if ctx.Configuration.Notifier.SMTP != nil {
disableHTML = ctx.Configuration.Notifier.SMTP.DisableHTMLEmails disableHTML = ctx.Configuration.Notifier.SMTP.DisableHTMLEmails
} }
linkURL := ctx.RootURL()
query := linkURL.Query()
query.Set(queryArgToken, signedToken)
linkURL.Path = path.Join(linkURL.Path, args.TargetEndpoint)
linkURL.RawQuery = query.Encode()
values := templates.EmailIdentityVerificationValues{ values := templates.EmailIdentityVerificationValues{
Title: args.MailTitle, Title: args.MailTitle,
LinkURL: fmt.Sprintf("%s%s?token=%s", uri, args.TargetEndpoint, ss), LinkURL: linkURL.String(),
LinkText: args.MailButtonContent, LinkText: args.MailButtonContent,
DisplayName: identity.DisplayName, DisplayName: identity.DisplayName,
RemoteIP: ctx.RemoteIP().String(), RemoteIP: ctx.RemoteIP().String(),

Some files were not shown because too many files have changed in this diff Show More