diff options
580 files changed, 23733 insertions, 7885 deletions
diff --git a/.buildkite/deployment.sh b/.buildkite/deployment.sh index 53bc2b1c0..d96221ae9 100755 --- a/.buildkite/deployment.sh +++ b/.buildkite/deployment.sh @@ -61,11 +61,4 @@ steps:      agents:        upload: "fast"      if: build.tag != null - -  - label: ":book: Deploy Documentation" -    command: "syncdoc.sh" -    depends_on: ~ -    agents: -      upload: "fast" -    if: build.branch == "master" -EOF
\ No newline at end of file +EOF diff --git a/.buildkite/steps/syncdoc.sh b/.buildkite/steps/syncdoc.sh deleted file mode 100755 index 67d4d17cb..000000000 --- a/.buildkite/steps/syncdoc.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env bash - -set -e - -rm -rf authelia -git clone git@github.com:authelia/authelia.git --single-branch --branch gh-pages - -pushd docs -bundle install -bundle exec jekyll build -d ../authelia -popd - -COMMIT=$(git show -s --format=%h) - -pushd authelia -git config user.name "Authelia[bot]" -git config user.email "autheliabot@gmail.com" - -git status | grep "nothing to commit" && exit -git add -A -git commit -m "Synchronize docs of commit: ${COMMIT}" -git push -popd - -rm -rf authelia diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 87dd83e77..899f94db9 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -2,7 +2,7 @@  blank_issues_enabled: false  contact_links:    - name: Documentation -    url: https://www.authelia.com/docs/ +    url: https://www.authelia.com/      about: Read the Documentation    - name: Matrix      url: https://matrix.to/#/#community:authelia.com diff --git a/.renovaterc b/.renovaterc index fa26dd983..09fe00a98 100644 --- a/.renovaterc +++ b/.renovaterc @@ -4,6 +4,9 @@      ":semanticCommitTypeAll(build)",      ":separatePatchReleases"    ], +  "ignorePaths": [ +  	"docs/**" +  ],    "ignorePresets": [      ":combinePatchMinorReleases",      "helpers:disableTypesNodeMajor", @@ -58,4 +61,4 @@        "gomodTidy",        "gomodNoMassage"    ] -}
\ No newline at end of file +} diff --git a/.yamllint.yml b/.yamllint.yml index 89675cfa5..3d31542b4 100644 --- a/.yamllint.yml +++ b/.yamllint.yml @@ -2,6 +2,7 @@  extends: default  ignore: | +  docs/pnpm-lock.yaml    internal/configuration/test_resources/config_bad_quoting.yml    web/pnpm-lock.yaml    web/node_modules/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 886ac4104..1b23c8aaf 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,7 +1,7 @@  # Contributing -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  +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  [chat rooms](./README.md#contact-options).  It's also possible to contribute financially in order to support the community. @@ -15,11 +15,13 @@ If you've found a **bug** or have a **feature request** then please create an is  ## Code  If you would like to fix a bug or implement a feature, please fork the repository and create a Pull Request. -More information on getting set up locally can be found [here](https://www.authelia.com/docs/contributing/). +More information on getting set up locally can be found in the +[Development Contribution](https://www.authelia.com/contributing/development/introduction/) documentation. -Before you start any Pull Request, it's recommended that you create an issue to discuss first if you have any doubts about requirement or implementation. -That way you can be sure that the maintainer(s) agree on what to change and how, and you can hopefully get a quick merge afterwards. -Also, let the maintainers know that you plan to work on a particular issue so that no one else starts any duplicate work. +Before you start any Pull Request, it's recommended that you create an issue to discuss first if you have any doubts +about requirement or implementation. That way you can be sure that the maintainer(s) agree on what to change and how, +and you can hopefully get a quick merge afterwards. Also, let the maintainers know that you plan to work on a particular +issue so that no one else starts any duplicate work.  Pull Requests can only be merged once all status checks are green, which means `authelia-scripts --log-level debug ci` passes, and coverage does not regress. @@ -37,7 +39,7 @@ Read more about this in the [GitHub docs, Re-requesting a review](https://docs.g  ## Collaboration with maintainers -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.  If you'd like some help getting started we have several [contact options](./README.md#contact-options) available. @@ -1,5 +1,5 @@  <p align="center"> -  <img src="./docs/images/authelia-title.png" width="350" title="Authelia"> +  <img src="./docs/static/images/authelia-title.png" width="350" title="Authelia">  </p>    [](https://buildkite.com/authelia/authelia) @@ -20,12 +20,12 @@ sign-on (SSO) for your applications via a web portal. It acts as a companion for  [Traefik], [caddy] or [HAProxy] to let them know whether requests should either be allowed or redirected to Authelia's  portal for authentication. -Documentation is available at https://www.authelia.com/docs. +Documentation is available at [https://www.authelia.com/](https://www.authelia.com/).  The following is a simple diagram of the architecture:  <p align="center" style="margin:50px"> -  <img src="./docs/images/archi.png"/> +  <img src="./docs/static/images/archi.png"/>  </p>  **Authelia** can be installed as a standalone service from the [AUR](https://aur.archlinux.org/packages/authelia/), @@ -36,15 +36,15 @@ The following is a simple diagram of the architecture:  the Helm [Chart](https://charts.authelia.com) (beta) leveraging ingress controllers and ingress configurations.  <p align="center"> -  <img src="./docs/images/logos/kubernetes.png" height="100"/> -  <img src="./docs/images/logos/docker.logo.png" width="100"> +  <img src="./docs/static/images/logos/kubernetes.png" height="100"/> +  <img src="./docs/static/images/logos/docker.logo.png" width="100">  </p>  Here is what Authelia's portal looks like:  <p align="center"> -  <img src="./docs/images/1FA.png" width="400" /> -  <img src="./docs/images/2FA-METHODS.png" width="400" /> +  <img src="./docs/static/images/1FA.png" width="400" /> +  <img src="./docs/static/images/2FA-METHODS.png" width="400" />  </p>  ## Features summary @@ -52,11 +52,11 @@ Here is what Authelia's portal looks like:  This is a list of the key features of Authelia:  * Several second factor methods: -  * **[Security Keys](https://www.authelia.com/docs/features/2fa/security-key)** that support [FIDO2] [Webauthn] -    with devices like a [YubiKey]. -  * **[Time-based One-Time password](https://www.authelia.com/docs/features/2fa/one-time-password)** +  * **[Security Keys](https://www.authelia.com/overview/authentication/webauthn-security-key/)** that support +    [FIDO2] [Webauthn] with devices like a [YubiKey]. +  * **[Time-based One-Time password](https://www.authelia.com/overview/authentication/one-time-password/)**      with compatible authenticator applications. -  * **[Mobile Push Notifications](https://www.authelia.com/docs/features/2fa/push-notifications)** +  * **[Mobile Push Notifications](https://www.authelia.com/overview/authentication/push-notification/)**      with [Duo](https://duo.com/).  * Password reset with identity verification using email confirmation.  * Access restriction after too many invalid authentication attempts. @@ -78,11 +78,11 @@ This is a list of the key features of Authelia:      [Traefik Kubernetes Ingress](https://doc.traefik.io/traefik/providers/kubernetes-crd/) Kubernetes ingress      controllers out of the box.    * Beta support for installing via Helm using our [Charts](https://charts.authelia.com). -* Beta support for [OpenID Connect](https://www.authelia.com/docs/configuration/identity-providers/oidc.html). +* Beta support for [OpenID Connect](https://www.authelia.com/roadmap/active/openid-connect/). -For more details about the features, follow [Features](https://www.authelia.com/docs/features/). +For more details take a look at the [Overview](https://www.authelia.com/overview/prologue/introduction/). -If you want to know more about the roadmap, follow [Roadmap](https://www.authelia.com/docs/roadmap). +If you want to know more about the roadmap, follow [Roadmap](https://www.authelia.com/roadmap).  ## Proxy support @@ -90,33 +90,36 @@ Authelia works in combination with [nginx], [Traefik], [caddy] or [HAProxy]. It  Docker or on top of [Kubernetes].  <p align="center"> -  <img src="./docs/images/logos/nginx.png" height="50"/> -  <img src="./docs/images/logos/traefik.png" height="50"/> -  <img src="./docs/images/logos/caddy.png" height="50"/> -  <img src="./docs/images/logos/haproxy.png" height="50"/> -  <img src="./docs/images/logos/kubernetes.png" height="50"/> +  <img src="./docs/static/images/logos/nginx.png" height="50"/> +  <img src="./docs/static/images/logos/traefik.png" height="50"/> +  <img src="./docs/static/images/logos/caddy.png" height="50"/> +  <img src="./docs/static/images/logos/haproxy.png" height="50"/> +  <img src="./docs/static/images/logos/kubernetes.png" height="50"/>  </p>  ***Help Wanted:*** Assistance would be appreciated in getting Authelia working with  [Envoy](https://www.envoyproxy.io/).  <p align="center"> -  <img src="./docs/images/logos/envoy.png" height="50"/> +  <img src="./docs/static/images/logos/envoy.png" height="50"/>  </p>  ## Getting Started +See the [Get Started Guide](https://www.authelia.com/integration/prologue/get-started/) or one of the curated examples +below. +  ### docker-compose  The `docker-compose` bundles act as a starting point for anyone wanting to see Authelia in action. You will have to  customize them to your needs as they come with self-signed certificates. -#### [Local](https://www.authelia.com/docs/getting-started) +#### [Local](https://www.authelia.com/integration/deployment/docker/#local)  The Local compose bundle is intended to test Authelia without worrying about configuration.  It's meant to be used for scenarios where the server is not be exposed to the internet.  Domains will be defined in the local hosts file and self-signed certificates will be utilised. -#### [Lite](https://www.authelia.com/docs/deployment/deployment-lite) +#### [Lite](https://www.authelia.com/integration/deployment/docker/#lite)  The Lite compose bundle is intended for scenarios where the server will be exposed to the internet, domains and DNS will  need to be setup accordingly and certificates will be generated through LetsEncrypt. The Lite element refers to minimal  external dependencies; File based user storage, SQLite based configuration storage. In this configuration, the service @@ -140,8 +143,8 @@ This guide will show you how to deploy it on bare metal as well as on  Authelia takes security very seriously. If you discover a vulnerability in Authelia, please see our  [Security Policy](https://github.com/authelia/authelia/security/policy). -For more information about [security](https://www.authelia.com/docs/security/) related matters, please read -[the documentation](https://www.authelia.com/docs/security/). +For more information about [security](https://www.authelia.com/information/security/) related matters, please read +[the documentation](https://www.authelia.com/information/security/).  ## Contact Options @@ -345,22 +348,17 @@ Companies contributing to Authelia will have a specical mention below. [[Become  #### Balto -Thank you to [<img src="./docs/images/logos/balto.svg" alt="Balto" width="32"> Balto](https://www.getbalto.com/) for -hosting our apt repository. - -#### Digital Ocean - -Thank you to [<img src="./docs/images/logos/digitalocean.svg" alt="Digital Ocean" width="32"> DigitalOcean](https://www.digitalocean.com/?from=Authelia) for -contributing on OpenCollective. +Thank you to [<img src="./docs/static/images/logos/balto.svg" alt="Balto" width="32"> Balto](https://www.getbalto.com/) +for hosting our apt repository.  #### JetBrains -Thank you to [<img src="./docs/images/logos/jetbrains.svg" alt="JetBrains" width="32"> JetBrains](https://www.jetbrains.com/?from=Authelia) +Thank you to [<img src="./docs/static/images/logos/jetbrains.svg" alt="JetBrains" width="32"> JetBrains](https://www.jetbrains.com/?from=Authelia)  for providing us with free licenses to their great tools. -* [<img src="./docs/images/logos/intellij-idea.svg" alt="IDEA" width="32"> IDEA](http://www.jetbrains.com/idea/) -* [<img src="./docs/images/logos/goland.svg" alt="GoLand" width="32"> GoLand](http://www.jetbrains.com/go/) -* [<img src="./docs/images/logos/webstorm.svg" alt="WebStorm" width="32"> WebStorm](http://www.jetbrains.com/webstorm/) +* [<img src="./docs/static/images/logos/intellij-idea.svg" alt="IDEA" width="32"> IDEA](http://www.jetbrains.com/idea/) +* [<img src="./docs/static/images/logos/goland.svg" alt="GoLand" width="32"> GoLand](http://www.jetbrains.com/go/) +* [<img src="./docs/static/images/logos/webstorm.svg" alt="WebStorm" width="32"> WebStorm](http://www.jetbrains.com/webstorm/)  ## License diff --git a/SECURITY.md b/SECURITY.md index 783a2d701..6324e796c 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -2,20 +2,20 @@  ## Prologue -Authelia takes security very seriously. We follow the rule of  +Authelia takes security very seriously. We follow the rule of  [responsible disclosure](https://en.wikipedia.org/wiki/Responsible_disclosure), and we urge our community to do so as  well instead of making the vulnerability public. This allows time for the security issue to be patched quickly. -If you discover a vulnerability in Authelia, please first contact one of the maintainers privately  as described in the  -[contact options](#contact-options) below.  +If you discover a vulnerability in Authelia, please first contact one of the maintainers privately  as described in the +[contact options](#contact-options) below.  We urge you not to disclose the bug publicly at least until we've had a -reasonable chance to fix it, and to clearly communicate any public disclosure timeline in your initial contact with us.  +reasonable chance to fix it, and to clearly communicate any public disclosure timeline in your initial contact with us.  If you do not have a particular public disclosure timeline, we will clearly communicate ours as we publish security -advisories.  +advisories. -For more information about [security](https://www.authelia.com/docs/security/) related matters, please read  -[the documentation](https://www.authelia.com/docs/security/). +For more information about [security](https://www.authelia.com/information/security/) related matters, please read +[the documentation](https://www.authelia.com/information/security/).  ## Contact Options @@ -25,7 +25,7 @@ privately which is described in each available contact method. The methods inclu  ## Credit -Users who report bugs will optionally be creditted 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.  ## Process @@ -40,8 +40,8 @@ Users who report bugs will optionally be creditted for the discovery. Both in th  ## Help Wanted -We are actively looking for sponsorship to obtain either a code security audit, penetration testing, or other audits  +We are actively looking for sponsorship to obtain either a code security audit, penetration testing, or other audits  related to improving the security of Authelia. If your company or you personally are willing to offer discounts, pro  bono, or funding towards services like these please feel free to contact us on *any* of the methods above. -[security advisory]: https://github.com/authelia/authelia/security/advisories
\ No newline at end of file +[security advisory]: https://github.com/authelia/authelia/security/advisories diff --git a/config.template.yml b/config.template.yml index e38dbda84..cb5e13b2f 100644 --- a/config.template.yml +++ b/config.template.yml @@ -15,7 +15,7 @@  theme: light  ## The secret used to generate JWT tokens when validating user identity by email confirmation. JWT Secret can also be -## set using a secret: https://www.authelia.com/docs/configuration/secrets.html +## set using a secret: https://www.authelia.com/c/secrets  jwt_secret: a_very_important_secret  ## Default redirection URL @@ -52,7 +52,7 @@ server:    # asset_path: /config/assets/    ## Buffers usually should be configured to be the same value. -  ## Explanation at https://www.authelia.com/docs/configuration/server.html +  ## Explanation at https://www.authelia.com/c/server#buffer-sizes    ## Read buffer size adjusts the server's max incoming request size in bytes.    ## Write buffer size does the same for outgoing responses.    read_buffer_size: 4096 @@ -129,13 +129,13 @@ totp:    ## The TOTP algorithm to use.    ## It is CRITICAL you read the documentation before changing this option: -  ## https://www.authelia.com/docs/configuration/one-time-password.html#algorithm +  ## https://www.authelia.com/c/totp#algorithm    algorithm: sha1    ## The number of digits a user has to input. Must either be 6 or 8.    ## Changing this option only affects newly generated TOTP configurations.    ## It is CRITICAL you read the documentation before changing this option: -  ## https://www.authelia.com/docs/configuration/one-time-password.html#digits +  ## https://www.authelia.com/c/totp#digits    digits: 6    ## The period in seconds a one-time password is valid for. @@ -145,7 +145,8 @@ totp:    ## The skew controls number of one-time passwords either side of the current one that are valid.    ## Warning: before changing skew read the docs link below.    skew: 1 -  ## See: https://www.authelia.com/docs/configuration/one-time-password.html#input-validation to read the documentation. +  ## See: https://www.authelia.com/c/totp#input-validation to read +  ## the documentation.    ## The size of the generated shared secrets. Default is 32 and is sufficient in most use cases, minimum is 20.    secret_size: 32 @@ -181,7 +182,7 @@ duo_api:    disable: false    hostname: api-123456789.example.com    integration_key: ABCDEF -  ## Secret can also be set using a secret: https://www.authelia.com/docs/configuration/secrets.html +  ## Secret can also be set using a secret: https://www.authelia.com/c/secrets    secret_key: 1234567890abcdefghifjkl    enable_self_enrollment: false @@ -230,8 +231,8 @@ authentication_backend:    ## always belong to groups they belonged to at the time of login even if they have been removed from them in LDAP.    ## To force update on every request you can set this to '0' or 'always', this will increase processor demand.    ## See the below documentation for more information. -  ## Duration Notation docs:  https://www.authelia.com/docs/configuration/index.html#duration-notation-format -  ## Refresh Interval docs: https://www.authelia.com/docs/configuration/authentication/ldap.html#refresh-interval +  ## Duration Notation docs:  https://www.authelia.com/c/common#duration-notation-format +  ## Refresh Interval docs: https://www.authelia.com/c/1fa#refresh-interval    refresh_interval: 5m    ## @@ -249,7 +250,7 @@ authentication_backend:      ##      ## Depending on the option here certain other values in this section have a default value, notably all of the      ## attribute mappings have a default value that this config overrides, you can read more about these default values -    ## at https://www.authelia.com/docs/configuration/authentication/ldap.html#defaults +    ## at https://www.authelia.com/c/ldap#defaults      implementation: custom      ## The url to the ldap server. Format: <scheme>://<address>[:<port>]. @@ -294,7 +295,7 @@ authentication_backend:      ## The users filter used in search queries to find the user profile based on input filled in login form.      ## Various placeholders are available in the user filter which you can read about in the documentation which can -    ## be found at: https://www.authelia.com/docs/configuration/authentication/ldap.html#users-filter-replacements +    ## be found at: https://www.authelia.com/c/ldap#users-filter-replacements      ##      ## Recommended settings are as follows:      ## - Microsoft Active Directory: (&({username_attribute}={input})(objectCategory=person)(objectClass=user)) @@ -312,7 +313,7 @@ authentication_backend:      ## The groups filter used in search queries to find the groups based on relevant authenticated user.      ## Various placeholders are available in the groups filter which you can read about in the documentation which can -    ## be found at: https://www.authelia.com/docs/configuration/authentication/ldap.html#groups-filter-replacements +    ## be found at: https://www.authelia.com/c/ldap#groups-filter-replacements      ##      ## If your groups use the `groupOfUniqueNames` structure use this instead:      ##    (&(uniqueMember={dn})(objectClass=groupOfUniqueNames)) @@ -334,7 +335,7 @@ authentication_backend:      ## The username and password of the admin user.      user: cn=admin,dc=example,dc=com -    ## Password can also be set using a secret: https://www.authelia.com/docs/configuration/secrets.html +    ## Password can also be set using a secret: https://www.authelia.com/c/secrets      password: password    ## @@ -345,9 +346,9 @@ authentication_backend:    ## to be scaled to more than one instance. The options under 'password' have sane defaults, and as it has security    ## implications it is highly recommended you leave the default values. Before considering changing these settings    ## please read the docs page below: -  ## https://www.authelia.com/docs/configuration/authentication/file.html#password-hash-algorithm-tuning +  ## https://www.authelia.com/r/passwords#tuning    ## -  ## Important: Kubernetes (or HA) users must read https://www.authelia.com/docs/features/statelessness.html +  ## Important: Kubernetes (or HA) users must read https://www.authelia.com/t/statelessness    ##    # file:    #   path: /config/users_database.yml @@ -524,15 +525,15 @@ session:    domain: example.com    ## Sets the Cookie SameSite value. Possible options are none, lax, or strict. -  ## Please read https://www.authelia.com/docs/configuration/session/#same_site +  ## Please read https://www.authelia.com/c/session#same_site    same_site: lax    ## The secret to encrypt the session data. This is only used with Redis / Redis Sentinel. -  ## Secret can also be set using a secret: https://www.authelia.com/docs/configuration/secrets.html +  ## Secret can also be set using a secret: https://www.authelia.com/c/secrets    secret: insecure_session_secret    ## The value for expiration, inactivity, and remember_me_duration are in seconds or the duration notation format. -  ## See: https://www.authelia.com/docs/configuration/index.html#duration-notation-format +  ## See: https://www.authelia.com/c/common#duration-notation-format    ## All three of these values affect the cookie/session validity period. Longer periods are considered less secure    ## because a stolen cookie will last longer giving attackers more time to spy or attack. @@ -551,7 +552,7 @@ session:    ##    ## Redis Provider    ## -  ## Important: Kubernetes (or HA) users must read https://www.authelia.com/docs/features/statelessness.html +  ## Important: Kubernetes (or HA) users must read https://www.authelia.com/t/statelessness    ##    redis:      host: 127.0.0.1 @@ -562,7 +563,7 @@ session:      ## Username used for redis authentication. This is optional and a new feature in redis 6.0.      # username: authelia -    ## Password can also be set using a secret: https://www.authelia.com/docs/configuration/secrets.html +    ## Password can also be set using a secret: https://www.authelia.com/c/secrets      password: authelia      ## This is the Redis DB Index https://redis.io/commands/select (sometimes referred to as database number, DB, etc). @@ -625,11 +626,11 @@ regulation:    ## The time range during which the user can attempt login before being banned. The user is banned if the    ## authentication failed 'max_retries' times in a 'find_time' seconds window. Find Time accepts duration notation. -  ## See: https://www.authelia.com/docs/configuration/index.html#duration-notation-format +  ## See: https://www.authelia.com/c/common#duration-notation-format    find_time: 2m    ## The length of time before a banned user can login again. Ban Time accepts duration notation. -  ## See: https://www.authelia.com/docs/configuration/index.html#duration-notation-format +  ## See: https://www.authelia.com/c/common#duration-notation-format    ban_time: 5m  ## @@ -647,7 +648,7 @@ storage:    ## This stores the data in a SQLite3 Database.    ## This is only recommended for lightweight non-stateful installations.    ## -  ## Important: Kubernetes (or HA) users must read https://www.authelia.com/docs/features/statelessness.html +  ## Important: Kubernetes (or HA) users must read https://www.authelia.com/t/statelessness    ##    # local:    #   path: /config/db.sqlite3 @@ -660,7 +661,7 @@ storage:      port: 3306      database: authelia      username: authelia -    ## Password can also be set using a secret: https://www.authelia.com/docs/configuration/secrets.html +    ## Password can also be set using a secret: https://www.authelia.com/c/secrets      password: mypassword      timeout: 5s @@ -673,7 +674,7 @@ storage:    #   database: authelia    #   schema: public    #   username: authelia -  #   ## Password can also be set using a secret: https://www.authelia.com/docs/configuration/secrets.html +  #   ## Password can also be set using a secret: https://www.authelia.com/c/secrets    #   password: mypassword    #   timeout: 5s    #   ssl: @@ -694,7 +695,7 @@ notifier:    ##    ## File System (Notification Provider)    ## -  ## Important: Kubernetes (or HA) users must read https://www.authelia.com/docs/features/statelessness.html +  ## Important: Kubernetes (or HA) users must read https://www.authelia.com/t/statelessness    ##    # filesystem:    #   filename: /config/notification.txt @@ -723,7 +724,7 @@ notifier:      username: test      ## The password used for SMTP authentication. -    ## Can also be set using a secret: https://www.authelia.com/docs/configuration/secrets.html +    ## Can also be set using a secret: https://www.authelia.com/c/secrets      password: password      ## The sender is used to is used for the MAIL FROM command and the FROM header. @@ -768,14 +769,14 @@ notifier:    ## OpenID Connect (Identity Provider)    ##    ## It's recommended you read the documentation before configuration of this section: -  ## https://www.authelia.com/docs/configuration/identity-providers/oidc.html +  ## https://www.authelia.com/c/oidc    # oidc:      ## The hmac_secret is used to sign OAuth2 tokens (authorization code, access tokens and refresh tokens). -    ## HMAC Secret can also be set using a secret: https://www.authelia.com/docs/configuration/secrets.html +    ## HMAC Secret can also be set using a secret: https://www.authelia.com/c/secrets      # hmac_secret: this_is_a_secret_abc123abc123abc      ## The issuer_private_key is used to sign the JWT forged by OpenID Connect. -    ## Issuer Private Key can also be set using a secret: https://docs.authelia.com/configuration/secrets.html +    ## Issuer Private Key can also be set using a secret: https://www.authelia.com/c/secrets      # issuer_private_key: |      #   --- KEY START      #   --- KEY END diff --git a/docs/.editorconfig b/docs/.editorconfig new file mode 100644 index 000000000..dad6b5822 --- /dev/null +++ b/docs/.editorconfig @@ -0,0 +1,11 @@ +# editorconfig.org + +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true
\ No newline at end of file diff --git a/docs/.eslintignore b/docs/.eslintignore new file mode 100644 index 000000000..57d005799 --- /dev/null +++ b/docs/.eslintignore @@ -0,0 +1,4 @@ +assets/js/index.js +assets/js/katex.js +assets/js/vendor +node_modules
\ No newline at end of file diff --git a/docs/.eslintrc.json b/docs/.eslintrc.json new file mode 100644 index 000000000..c926994dc --- /dev/null +++ b/docs/.eslintrc.json @@ -0,0 +1,31 @@ +{ +  "env": { +    "browser": true, +    "commonjs": true, +    "es6": true, +    "node": true +  }, +  "extends": "eslint:recommended", +  "globals": { +    "Atomics": "readonly", +    "SharedArrayBuffer": "readonly" +  }, +  "parserOptions": { +    "ecmaVersion": 2018, +    "sourceType": "module" +  }, +  "rules": { +    "no-console": 0, +    "quotes": ["error", "single"], +    "comma-dangle": [ +      "error", +      { +        "arrays": "always-multiline", +        "objects": "always-multiline", +        "imports": "always-multiline", +        "exports": "always-multiline", +        "functions": "ignore" +      } +    ] +  } +}
\ No newline at end of file diff --git a/docs/.gitignore b/docs/.gitignore index fcb2476de..6c3c7ae90 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -1,4 +1,6 @@ -_site -.sass-cache -.jekyll-metadata -.jekyll-cache +node_modules +public +resources +.netlify +.hugo_build.lock +!content/*/reference/cli/authelia diff --git a/docs/.markdownlint-cli2.jsonc b/docs/.markdownlint-cli2.jsonc new file mode 100644 index 000000000..f3168449f --- /dev/null +++ b/docs/.markdownlint-cli2.jsonc @@ -0,0 +1,20 @@ +{ +  "config": { +    "default": true, +    "MD013": false, +    "MD024": false, +    "MD026": false, +    "MD033": false, +    "MD034": false, +    "emphasis-style": { +      "style": "asterisk" +    }, +    "strong-style": { +      "style": "underscore" +    }, +    "ul-style": { +      "style": "asterisk" +    } +  }, +  "ignores": ["node_modules", "CHANGELOG.md", "README.md", "content/*/reference/cli"] +} diff --git a/docs/.stylelintignore b/docs/.stylelintignore new file mode 100644 index 000000000..3972095a3 --- /dev/null +++ b/docs/.stylelintignore @@ -0,0 +1,3 @@ +assets/scss/components/_syntax.scss +assets/scss/vendor +node_modules
\ No newline at end of file diff --git a/docs/.stylelintrc.json b/docs/.stylelintrc.json new file mode 100644 index 000000000..191d09381 --- /dev/null +++ b/docs/.stylelintrc.json @@ -0,0 +1,48 @@ +{ +  "extends": "stylelint-config-standard-scss", +  "rules": { +    "no-empty-source": null, +    "string-quotes": "double", +    "scss/comment-no-empty": null, +    "max-line-length": null, +    "scss/at-extend-no-missing-placeholder": null, +    "scss/dollar-variable-colon-space-after": null, +    "scss/dollar-variable-empty-line-before": null, +    "color-function-notation": null, +    "alpha-value-notation": null, +    "selector-id-pattern": null, +    "selector-class-pattern": null, +    "scss/no-global-function-names": null, +    "number-max-precision": null, +    "hue-degree-notation": null, +    "value-no-vendor-prefix": null, +    "property-no-vendor-prefix": null, +    "at-rule-no-unknown": [ +      true, +      { +        "ignoreAtRules": [ +          "extend", +          "at-root", +          "debug", +          "warn", +          "error", +          "if", +          "else", +          "for", +          "each", +          "while", +          "mixin", +          "include", +          "content", +          "return", +          "function", +          "tailwind", +          "apply", +          "responsive", +          "variants", +          "screen" +        ] +      } +    ] +  } +}
\ No newline at end of file diff --git a/docs/Gemfile b/docs/Gemfile deleted file mode 100644 index d63015943..000000000 --- a/docs/Gemfile +++ /dev/null @@ -1,30 +0,0 @@ -source "https://rubygems.org" - -# Hello! This is where you manage which Jekyll version is used to run. -# When you want to use a different version, change it below, save the -# file and run `bundle install`. Run Jekyll with `bundle exec`, like so: -# -#     bundle exec jekyll serve -# -# This will help ensure the proper Jekyll version is running. -# Happy Jekylling! -gem "jekyll", "~> 3.9.0" - -# This is the default theme for new Jekyll sites. You may change this to anything you like. -#gem "minima", "~> 2.0" -gem "just-the-docs" - -# If you want to use GitHub Pages, remove the "gem "jekyll"" above and -# uncomment the line below. To upgrade, run `bundle update github-pages`. -gem "github-pages", group: :jekyll_plugins - -# If you have any plugins, put them here! -group :jekyll_plugins do -  # gem "jekyll-feed", "~> 0.6" -end - -# Windows does not include zoneinfo files, so bundle the tzinfo-data gem -gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw, :jruby] - -# Performance-booster for watching directories on Windows -gem "wdm", "~> 0.1.0" if Gem.win_platform? diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock deleted file mode 100644 index 5f3ff5d60..000000000 --- a/docs/Gemfile.lock +++ /dev/null @@ -1,273 +0,0 @@ -GEM -  remote: https://rubygems.org/ -  specs: -    activesupport (6.0.3.6) -      concurrent-ruby (~> 1.0, >= 1.0.2) -      i18n (>= 0.7, < 2) -      minitest (~> 5.1) -      tzinfo (~> 1.1) -      zeitwerk (~> 2.2, >= 2.2.2) -    addressable (2.8.0) -      public_suffix (>= 2.0.2, < 5.0) -    coffee-script (2.4.1) -      coffee-script-source -      execjs -    coffee-script-source (1.11.1) -    colorator (1.1.0) -    commonmarker (0.17.13) -      ruby-enum (~> 0.5) -    concurrent-ruby (1.1.8) -    dnsruby (1.61.5) -      simpleidn (~> 0.1) -    em-websocket (0.5.2) -      eventmachine (>= 0.12.9) -      http_parser.rb (~> 0.6.0) -    ethon (0.12.0) -      ffi (>= 1.3.0) -    eventmachine (1.2.7) -    execjs (2.7.0) -    faraday (1.3.0) -      faraday-net_http (~> 1.0) -      multipart-post (>= 1.2, < 3) -      ruby2_keywords -    faraday-net_http (1.0.1) -    ffi (1.15.0) -    forwardable-extended (2.6.0) -    gemoji (3.0.1) -    github-pages (214) -      github-pages-health-check (= 1.17.0) -      jekyll (= 3.9.0) -      jekyll-avatar (= 0.7.0) -      jekyll-coffeescript (= 1.1.1) -      jekyll-commonmark-ghpages (= 0.1.6) -      jekyll-default-layout (= 0.1.4) -      jekyll-feed (= 0.15.1) -      jekyll-gist (= 1.5.0) -      jekyll-github-metadata (= 2.13.0) -      jekyll-mentions (= 1.6.0) -      jekyll-optional-front-matter (= 0.3.2) -      jekyll-paginate (= 1.1.0) -      jekyll-readme-index (= 0.3.0) -      jekyll-redirect-from (= 0.16.0) -      jekyll-relative-links (= 0.6.1) -      jekyll-remote-theme (= 0.4.3) -      jekyll-sass-converter (= 1.5.2) -      jekyll-seo-tag (= 2.7.1) -      jekyll-sitemap (= 1.4.0) -      jekyll-swiss (= 1.0.0) -      jekyll-theme-architect (= 0.1.1) -      jekyll-theme-cayman (= 0.1.1) -      jekyll-theme-dinky (= 0.1.1) -      jekyll-theme-hacker (= 0.1.2) -      jekyll-theme-leap-day (= 0.1.1) -      jekyll-theme-merlot (= 0.1.1) -      jekyll-theme-midnight (= 0.1.1) -      jekyll-theme-minimal (= 0.1.1) -      jekyll-theme-modernist (= 0.1.1) -      jekyll-theme-primer (= 0.5.4) -      jekyll-theme-slate (= 0.1.1) -      jekyll-theme-tactile (= 0.1.1) -      jekyll-theme-time-machine (= 0.1.1) -      jekyll-titles-from-headings (= 0.5.3) -      jemoji (= 0.12.0) -      kramdown (= 2.3.1) -      kramdown-parser-gfm (= 1.1.0) -      liquid (= 4.0.3) -      mercenary (~> 0.3) -      minima (= 2.5.1) -      nokogiri (>= 1.10.4, < 2.0) -      rouge (= 3.26.0) -      terminal-table (~> 1.4) -    github-pages-health-check (1.17.0) -      addressable (~> 2.3) -      dnsruby (~> 1.60) -      octokit (~> 4.0) -      public_suffix (>= 2.0.2, < 5.0) -      typhoeus (~> 1.3) -    html-pipeline (2.14.0) -      activesupport (>= 2) -      nokogiri (>= 1.4) -    http_parser.rb (0.6.0) -    i18n (0.9.5) -      concurrent-ruby (~> 1.0) -    jekyll (3.9.0) -      addressable (~> 2.4) -      colorator (~> 1.0) -      em-websocket (~> 0.5) -      i18n (~> 0.7) -      jekyll-sass-converter (~> 1.0) -      jekyll-watch (~> 2.0) -      kramdown (>= 1.17, < 3) -      liquid (~> 4.0) -      mercenary (~> 0.3.3) -      pathutil (~> 0.9) -      rouge (>= 1.7, < 4) -      safe_yaml (~> 1.0) -    jekyll-avatar (0.7.0) -      jekyll (>= 3.0, < 5.0) -    jekyll-coffeescript (1.1.1) -      coffee-script (~> 2.2) -      coffee-script-source (~> 1.11.1) -    jekyll-commonmark (1.3.1) -      commonmarker (~> 0.14) -      jekyll (>= 3.7, < 5.0) -    jekyll-commonmark-ghpages (0.1.6) -      commonmarker (~> 0.17.6) -      jekyll-commonmark (~> 1.2) -      rouge (>= 2.0, < 4.0) -    jekyll-default-layout (0.1.4) -      jekyll (~> 3.0) -    jekyll-feed (0.15.1) -      jekyll (>= 3.7, < 5.0) -    jekyll-gist (1.5.0) -      octokit (~> 4.2) -    jekyll-github-metadata (2.13.0) -      jekyll (>= 3.4, < 5.0) -      octokit (~> 4.0, != 4.4.0) -    jekyll-mentions (1.6.0) -      html-pipeline (~> 2.3) -      jekyll (>= 3.7, < 5.0) -    jekyll-optional-front-matter (0.3.2) -      jekyll (>= 3.0, < 5.0) -    jekyll-paginate (1.1.0) -    jekyll-readme-index (0.3.0) -      jekyll (>= 3.0, < 5.0) -    jekyll-redirect-from (0.16.0) -      jekyll (>= 3.3, < 5.0) -    jekyll-relative-links (0.6.1) -      jekyll (>= 3.3, < 5.0) -    jekyll-remote-theme (0.4.3) -      addressable (~> 2.0) -      jekyll (>= 3.5, < 5.0) -      jekyll-sass-converter (>= 1.0, <= 3.0.0, != 2.0.0) -      rubyzip (>= 1.3.0, < 3.0) -    jekyll-sass-converter (1.5.2) -      sass (~> 3.4) -    jekyll-seo-tag (2.7.1) -      jekyll (>= 3.8, < 5.0) -    jekyll-sitemap (1.4.0) -      jekyll (>= 3.7, < 5.0) -    jekyll-swiss (1.0.0) -    jekyll-theme-architect (0.1.1) -      jekyll (~> 3.5) -      jekyll-seo-tag (~> 2.0) -    jekyll-theme-cayman (0.1.1) -      jekyll (~> 3.5) -      jekyll-seo-tag (~> 2.0) -    jekyll-theme-dinky (0.1.1) -      jekyll (~> 3.5) -      jekyll-seo-tag (~> 2.0) -    jekyll-theme-hacker (0.1.2) -      jekyll (> 3.5, < 5.0) -      jekyll-seo-tag (~> 2.0) -    jekyll-theme-leap-day (0.1.1) -      jekyll (~> 3.5) -      jekyll-seo-tag (~> 2.0) -    jekyll-theme-merlot (0.1.1) -      jekyll (~> 3.5) -      jekyll-seo-tag (~> 2.0) -    jekyll-theme-midnight (0.1.1) -      jekyll (~> 3.5) -      jekyll-seo-tag (~> 2.0) -    jekyll-theme-minimal (0.1.1) -      jekyll (~> 3.5) -      jekyll-seo-tag (~> 2.0) -    jekyll-theme-modernist (0.1.1) -      jekyll (~> 3.5) -      jekyll-seo-tag (~> 2.0) -    jekyll-theme-primer (0.5.4) -      jekyll (> 3.5, < 5.0) -      jekyll-github-metadata (~> 2.9) -      jekyll-seo-tag (~> 2.0) -    jekyll-theme-slate (0.1.1) -      jekyll (~> 3.5) -      jekyll-seo-tag (~> 2.0) -    jekyll-theme-tactile (0.1.1) -      jekyll (~> 3.5) -      jekyll-seo-tag (~> 2.0) -    jekyll-theme-time-machine (0.1.1) -      jekyll (~> 3.5) -      jekyll-seo-tag (~> 2.0) -    jekyll-titles-from-headings (0.5.3) -      jekyll (>= 3.3, < 5.0) -    jekyll-watch (2.2.1) -      listen (~> 3.0) -    jemoji (0.12.0) -      gemoji (~> 3.0) -      html-pipeline (~> 2.2) -      jekyll (>= 3.0, < 5.0) -    just-the-docs (0.3.3) -      jekyll (>= 3.8.5) -      jekyll-seo-tag (~> 2.0) -      rake (>= 12.3.1, < 13.1.0) -    kramdown (2.3.1) -      rexml -    kramdown-parser-gfm (1.1.0) -      kramdown (~> 2.0) -    liquid (4.0.3) -    listen (3.5.1) -      rb-fsevent (~> 0.10, >= 0.10.3) -      rb-inotify (~> 0.9, >= 0.9.10) -    mercenary (0.3.6) -    mini_portile2 (2.8.0) -    minima (2.5.1) -      jekyll (>= 3.5, < 5.0) -      jekyll-feed (~> 0.9) -      jekyll-seo-tag (~> 2.1) -    minitest (5.14.4) -    multipart-post (2.1.1) -    nokogiri (1.13.6) -      mini_portile2 (~> 2.8.0) -      racc (~> 1.4) -    octokit (4.20.0) -      faraday (>= 0.9) -      sawyer (~> 0.8.0, >= 0.5.3) -    pathutil (0.16.2) -      forwardable-extended (~> 2.6) -    public_suffix (4.0.6) -    racc (1.6.0) -    rake (13.0.3) -    rb-fsevent (0.10.4) -    rb-inotify (0.10.1) -      ffi (~> 1.0) -    rexml (3.2.5) -    rouge (3.26.0) -    ruby-enum (0.9.0) -      i18n -    ruby2_keywords (0.0.4) -    rubyzip (2.3.0) -    safe_yaml (1.0.5) -    sass (3.7.4) -      sass-listen (~> 4.0.0) -    sass-listen (4.0.0) -      rb-fsevent (~> 0.9, >= 0.9.4) -      rb-inotify (~> 0.9, >= 0.9.7) -    sawyer (0.8.2) -      addressable (>= 2.3.5) -      faraday (> 0.8, < 2.0) -    simpleidn (0.2.1) -      unf (~> 0.1.4) -    terminal-table (1.8.0) -      unicode-display_width (~> 1.1, >= 1.1.1) -    thread_safe (0.3.6) -    typhoeus (1.4.0) -      ethon (>= 0.9.0) -    tzinfo (1.2.9) -      thread_safe (~> 0.1) -    unf (0.1.4) -      unf_ext -    unf_ext (0.0.7.7) -    unicode-display_width (1.7.0) -    zeitwerk (2.4.2) - -PLATFORMS -  ruby - -DEPENDENCIES -  github-pages -  jekyll (~> 3.9.0) -  just-the-docs -  tzinfo-data - -BUNDLED WITH -   2.2.3 diff --git a/docs/LICENSE b/docs/LICENSE new file mode 100644 index 000000000..a9431aad1 --- /dev/null +++ b/docs/LICENSE @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2018-present, Gridsome +Copyright (c) 2020-present, Henk Verlinde + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 000000000..c16c540b2 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,9 @@ +The **Authelia** website / documentation source. + +Please: + +- Only edit the `/content` folder via the main Authelia [monorepo](https://github.com/authelia/authelia/tree/master/docs) +- Edit everything else via the Authelia [website repo](https://github.com/authelia/website) + +See the [Documentation Contributing Guide](https://www.authelia.com/contributing/prologue/documentation/) for more +information. diff --git a/docs/_config.yml b/docs/_config.yml deleted file mode 100644 index 54b87556d..000000000 --- a/docs/_config.yml +++ /dev/null @@ -1,19 +0,0 @@ ---- -title: Authelia -email: team@authelia.com -description: Authelia is an open source multi-factor single sign-on portal for web applications -# We need this base URL to serve the docs under https://www.authelia.com/docs/ -baseurl: "/docs/" -# url: "https://www.authelia.com" -repository: https://github.com/authelia/authelia -logo: ./images/authelia-title.png -footer_content: > -  Copyright © 2022 Authelia. Distributed by an -  <a href="https://github.com/authelia/authelia/blob/master/LICENSE">Apache 2.0 license.</a> -markdown: kramdown -theme: just-the-docs -keep_files: -  - .git -  - CNAME -ga_tracking: UA-124926127-1 -... diff --git a/docs/_includes/head_custom.html b/docs/_includes/head_custom.html deleted file mode 100644 index 4dad5dc58..000000000 --- a/docs/_includes/head_custom.html +++ /dev/null @@ -1,4 +0,0 @@ -<link rel="stylesheet" -      href="https://cdnjs.cloudflare.com/ajax/libs/github-fork-ribbon-css/0.2.3/gh-fork-ribbon.min.css" /> -<link rel="stylesheet" -      href="https://fonts.googleapis.com/icon?family=Material+Icons" /> diff --git a/docs/_layouts/default.html b/docs/_layouts/default.html deleted file mode 100644 index fa6300c6a..000000000 --- a/docs/_layouts/default.html +++ /dev/null @@ -1,262 +0,0 @@ ---- -layout: table_wrappers ---- - -<!DOCTYPE html> - -<html lang="{{ site.lang | default: 'en-US' }}"> -{% include head.html %} -<body> -<a class="github-fork-ribbon" href="https://github.com/authelia/authelia" data-ribbon="Fork me on GitHub" -   title="Fork me on GitHub">Fork me on GitHub</a> -<svg xmlns="http://www.w3.org/2000/svg" style="display: none;"> -    <symbol id="svg-link" viewBox="0 0 24 24"> -        <title>Link</title> -        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"> -            <path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path> -        </svg> -    </symbol> -    <symbol id="svg-search" viewBox="0 0 24 24"> -        <title>Search</title> -        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-search"> -            <circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line> -        </svg> -    </symbol> -    <symbol id="svg-menu" viewBox="0 0 24 24"> -        <title>Menu</title> -        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-menu"> -            <line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="18" x2="21" y2="18"></line> -        </svg> -    </symbol> -    <symbol id="svg-arrow-right" viewBox="0 0 24 24"> -        <title>Expand</title> -        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-right"> -            <polyline points="9 18 15 12 9 6"></polyline> -        </svg> -    </symbol> -    <symbol id="svg-doc" viewBox="0 0 24 24"> -        <title>Document</title> -        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file"> -            <path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path><polyline points="13 2 13 9 20 9"></polyline> -        </svg> -    </symbol> -    <symbol id="svg-contrib" viewBox="0 0 24 24"> -        <title>Survey contribution</title> -    <?xml version="1.0" encoding="iso-8859-1"?> -    <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  --> -    <svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" -         viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve"> -<path style="fill:#FEC9A3;" d="M507.661,503.322V399.907c0-11.325-5.528-21.938-14.805-28.438l-65.25-45.681 -        c-4.374-3.063-9.589-4.703-14.935-4.703h-52.536l0.868,148.48c0.321,15.473,10.431,29.028,25.166,33.757H507.661z"/> -        <path style="fill:#FABD91;" d="M455.593,503.322h-60.746c-19.17,0-34.712-15.542-34.712-34.712v-34.712h60.746L455.593,503.322z"/> -        <path style="fill:#88B337;" d="M229.966,60.746c-5.979,0.009-11.889,1.258-17.356,3.662V0H56.407 -        C27.648,0,4.339,23.309,4.339,52.068v156.203h64.408c-9.633-21.938,0.338-47.538,22.285-57.17 -        c21.938-9.633,47.538,0.338,57.17,22.285c4.886,11.116,4.886,23.778,0,34.894h64.408v-64.408 -        c21.938,9.633,47.538-0.338,57.17-22.285s-0.338-47.538-22.285-57.17C241.976,61.978,236.006,60.737,229.966,60.746z"/> -        <path style="fill:#E8594A;" d="M420.881,52.068C420.881,23.309,397.572,0,368.814,0H212.61v64.408 -        c21.938-9.633,47.538,0.338,57.17,22.285c9.633,21.938-0.338,47.538-22.285,57.17c-11.116,4.886-23.778,4.886-34.894,0v64.408 -        h64.408c-9.633,21.938,0.338,47.538,22.285,57.17c21.938,9.633,47.538-0.338,57.17-22.285c4.886-11.116,4.886-23.778,0-34.894 -        h64.417V52.068z"/> -        <path style="fill:#D65245;" d="M420.881,57.023C371.278,126.03,281.73,165.228,212.61,186.325v21.947h64.408 -        c-9.633,21.938,0.338,47.538,22.285,57.17c21.938,9.633,47.538-0.338,57.17-22.285c4.886-11.116,4.886-23.778,0-34.894h64.408 -        V57.023z"/> -        <path style="fill:#FDB62F;" d="M195.254,277.695c5.979,0.009,11.889,1.258,17.356,3.662v-73.086h-64.408 -        c9.633-21.938-0.338-47.538-22.285-57.17c-21.947-9.633-47.538,0.338-57.17,22.285c-4.886,11.116-4.886,23.778,0,34.894H4.339 -        v156.203c0,28.759,23.309,52.068,52.068,52.068H212.61v-55.73c-21.938,9.633-47.538-0.338-57.17-22.285 -        c-9.633-21.938,0.338-47.538,22.285-57.17C183.244,278.927,189.214,277.686,195.254,277.695z"/> -        <path style="fill:#FFA719;" d="M4.339,364.475c0,28.759,23.309,52.068,52.068,52.068H212.61v-55.73 -        c-21.834,9.615-47.33-0.286-56.945-22.12c-2.23-5.068-3.471-10.526-3.645-16.063c-46.523,20.749-96.751,31.918-147.682,32.846 -        V364.475z"/> -        <path style="fill:#4398D1;" d="M443.574,389.641l-54.906-146.658l-60.303,22.71c16.809,17.122,16.549,44.631-0.573,61.431 -        c-17.122,16.801-44.631,16.549-61.431-0.573c-8.556-8.721-13.052-20.636-12.375-32.837l-60.295,22.71l25.687,68.634 -        c-5.962-0.338-11.932,0.573-17.529,2.673c-22.407,8.695-33.514,33.905-24.819,56.311c8.548,22.016,33.098,33.202,55.322,25.183 -        c5.597-2.109,10.7-5.372,14.969-9.563L266.9,512l146.241-55.079C440.094,446.716,453.71,416.62,443.574,389.641z"/> -        <path style="fill:#3E8FC9;" d="M415.258,314.012c-59.878,89.557-172.127,120.832-237.872,131.601 -        c9.225,21.947,34.495,32.256,56.441,23.031c5.025-2.109,9.607-5.163,13.494-8.982L266.9,512l146.241-55.079 -        c26.945-10.205,40.552-40.283,30.434-67.254L415.258,314.012z"/> -        <path style="fill:#80A834;" d="M229.966,60.746c-5.979,0.009-11.889,1.258-17.356,3.662V51.816 -        C147.63,111.633,59.592,144.67,4.339,160.768v47.503h64.408c-9.633-21.938,0.338-47.538,22.285-57.17 -        c21.938-9.633,47.538,0.338,57.17,22.285c4.886,11.116,4.886,23.778,0,34.894h64.408v-64.408 -        c21.938,9.633,47.538-0.338,57.17-22.285s-0.338-47.538-22.285-57.17C241.976,61.978,236.006,60.737,229.966,60.746z"/> -        <path style="fill:#FEC9A3;" d="M403.682,390.665c-8.305-8.47-21.903-8.609-30.373-0.304c-8.47,8.305-8.609,21.903-0.304,30.373 -        c0.104,0.104,0.2,0.208,0.304,0.304l30.217,30.217c0,28.759,23.309,52.068,52.068,52.068l0,0h52.068v-8.678L403.682,390.665z"/> -        <g> -</g> -        <g> -</g> -        <g> -</g> -        <g> -</g> -        <g> -</g> -        <g> -</g> -        <g> -</g> -        <g> -</g> -        <g> -</g> -        <g> -</g> -        <g> -</g> -        <g> -</g> -        <g> -</g> -        <g> -</g> -        <g> -</g> -</svg> -    </symbol> -</svg> - -<div class="side-bar"> -    <div class="site-header"> -        <a href="{{ '/' | absolute_url }}" class="site-title lh-tight">{% include title.html %}</a> -        <a href="#" id="menu-button" class="site-button"> -            <svg viewBox="0 0 24 24" class="icon"><use xlink:href="#svg-menu"></use></svg> -        </a> -    </div> -    <nav role="navigation" aria-label="Main" id="site-nav" class="site-nav"> -        {% if site.just_the_docs.collections %} -        {% assign collections_size = site.just_the_docs.collections | size %} -        {% for collection_entry in site.just_the_docs.collections %} -        {% assign collection_key = collection_entry[0] %} -        {% assign collection_value = collection_entry[1] %} -        {% assign collection = site[collection_key] %} -        {% if collection_value.nav_exclude != true %} -        {% if collections_size > 1 %} -        <div class="nav-category">{{ collection_value.name }}</div> -        {% endif %} -        {% include nav.html pages=collection %} -        {% endif %} -        {% endfor %} -        {% else %} -        {% include nav.html pages=site.html_pages %} -        {% endif %} -    </nav> -    <footer class="site-footer"> -        This site uses <a href="https://github.com/pmarsceill/just-the-docs">Just the Docs</a>, a documentation theme for Jekyll. -    </footer> -</div> -<div class="main" id="top"> -    <div id="main-header" class="main-header"> -        {% if site.search_enabled != false %} -        <div class="search"> -            <div class="search-input-wrap"> -                <input type="text" id="search-input" class="search-input" tabindex="0" placeholder="Search {{ site.title }}" aria-label="Search {{ site.title }}" autocomplete="off"> -                <label for="search-input" class="search-label"><svg viewBox="0 0 24 24" class="search-icon"><use xlink:href="#svg-search"></use></svg></label> -            </div> -            <div id="search-results" class="search-results"></div> -        </div> -        {% endif %} -        {% if site.aux_links %} -        <nav aria-label="Auxiliary" class="aux-nav"> -            <ul class="aux-nav-list"> -                {% for link in site.aux_links %} -                <li class="aux-nav-list-item"> -                    <a href="{{ link.last }}" class="site-button" -                       {% if site.aux_links_new_tab %} -                       target="_blank" rel="noopener noreferrer" -                       {% endif %} -                    > -                        {{ link.first }} -                    </a> -                </li> -                {% endfor %} -            </ul> -        </nav> -        {% endif %} -    </div> -    <div id="main-content-wrap" class="main-content-wrap"> -        {% unless page.url == "/" %} -        {% if page.parent %} -        <nav aria-label="Breadcrumb" class="breadcrumb-nav"> -            <ol class="breadcrumb-nav-list"> -                {% if page.grand_parent %} -                <li class="breadcrumb-nav-list-item"><a href="{{ first_level_url }}">{{ page.grand_parent }}</a></li> -                <li class="breadcrumb-nav-list-item"><a href="{{ second_level_url }}">{{ page.parent }}</a></li> -                {% else %} -                <li class="breadcrumb-nav-list-item"><a href="{{ first_level_url }}">{{ page.parent }}</a></li> -                {% endif %} -                <li class="breadcrumb-nav-list-item"><span>{{ page.title }}</span></li> -            </ol> -        </nav> -        {% endif %} -        {% endunless %} -        <div id="survey-wrapper" style="border: 1px solid #d6d6d6; border-radius: 5px; background-color: #f1f1f1; padding: 20px; display: flex; flex-direction: row; align-items: center;"> -            <svg viewBox="0 0 24 24" width="32px" height="32px" class="contrib-icon" style="display: inline-block"><use xlink:href="#svg-contrib"></use></svg> -            <span style="margin-left: 10px">Help the team improve <b>Authelia</b> by taking this <a href="https://forms.gle/aVw6J9jcez97EAhD6" target="_blank">10-second survey</a>.</span> -        </div> -        <div id="main-content" class="main-content" role="main"> -            {% if site.heading_anchors != false %} -            {% include vendor/anchor_headings.html html=content beforeHeading="true" anchorBody="<svg viewBox=\"0 0 16 16\" aria-hidden=\"true\"><use xlink:href=\"#svg-link\"></use></svg>" anchorClass="anchor-heading" anchorAttrs="aria-labelledby=\"%html_id%\"" %} -            {% else %} -            {{ content }} -            {% endif %} - -            {% if page.has_children == true and page.has_toc != false %} -            <hr> -            <h2 class="text-delta">Table of contents</h2> -            <ul> -                {%- assign children_list = pages_list | where: "parent", page.title | where: "grand_parent", page.parent -%} -                {% for child in children_list %} -                <li> -                    <a href="{{ child.url | absolute_url }}">{{ child.title }}</a>{% if child.summary %} - {{ child.summary }}{% endif %} -                </li> -                {% endfor %} -            </ul> -            {% endif %} - -            {% if site.footer_content != nil or site.last_edit_timestamp or site.gh_edit_link %} -            <hr> -            <footer> -                {% if site.back_to_top %} -                <p><a href="#top" id="back-to-top">{{ site.back_to_top_text }}</a></p> -                {% endif %} -                {% if site.footer_content != nil %} -                <p class="text-small text-grey-dk-000 mb-0">{{ site.footer_content }}</p> -                {% endif %} - -                {% if site.last_edit_timestamp or site.gh_edit_link %} -                <div class="d-flex mt-2"> -                    {% if site.last_edit_timestamp and site.last_edit_time_format and page.last_modified_date %} -                    <p class="text-small text-grey-dk-000 mb-0 mr-2"> -                        Page last modified: <span class="d-inline-block">{{ page.last_modified_date | date: site.last_edit_time_format }}</span>. -                    </p> -                    {% endif %} -                    {% if -                    site.gh_edit_link and -                    site.gh_edit_link_text and -                    site.gh_edit_repository and -                    site.gh_edit_branch and -                    site.gh_edit_view_mode -                    %} -                    <p class="text-small text-grey-dk-000 mb-0"> -                        <a href="{{ site.gh_edit_repository }}/{{ site.gh_edit_view_mode }}/{{ site.gh_edit_branch }}{% if site.gh_edit_source %}/{{ site.gh_edit_source }}{% endif %}/{{ page.path }}" id="edit-this-page">{{ site.gh_edit_link_text }}</a> -                    </p> -                    {% endif %} -                </div> -                {% endif %} -            </footer> -            {% endif %} - -        </div> -    </div> - -    {% if site.search_enabled != false %} -    {% if site.search.button %} -    <a href="#" id="search-button" class="search-button"> -        <svg viewBox="0 0 24 24" class="icon"><use xlink:href="#svg-search"></use></svg> -    </a> -    {% endif %} - -    <div class="search-overlay"></div> -    {% endif %} -</div> -</body> -</html>
\ No newline at end of file diff --git a/docs/_sass/custom/custom.scss b/docs/_sass/custom/custom.scss deleted file mode 100644 index 2edf9f74e..000000000 --- a/docs/_sass/custom/custom.scss +++ /dev/null @@ -1,19 +0,0 @@ -.label.label-config { -    text-transform: none; -} -.tbl-header { -    font-weight: bold; -    text-align: center; -} -.tbl-beta-stage { -    border-bottom-width: 3px !important; -} -.material-icons.green { -    color: #56D364; -} -.material-icons.red { -    color: #F85149; -} -.material-icons.orange { -    color: #E3B341; -}
\ No newline at end of file diff --git a/docs/_sass/overrides.scss b/docs/_sass/overrides.scss deleted file mode 100644 index cba6cefdc..000000000 --- a/docs/_sass/overrides.scss +++ /dev/null @@ -1,10 +0,0 @@ - -img { -    border: 1px solid #e6e6e6; -    border-radius: 5px; -    padding: 10px; -} - -.no-border { -    border: 0px; -}
\ No newline at end of file diff --git a/docs/about-us.md b/docs/about-us.md deleted file mode 100644 index 1b70839a5..000000000 --- a/docs/about-us.md +++ /dev/null @@ -1,69 +0,0 @@ ---- -layout: default -title: About Us -nav_order: 10 ---- - -## Core Team - -<table> -    <td align="center"> -        <a href="https://github.com/clems4ever"> -            <img src="https://avatars.githubusercontent.com/u/3193257?v=4?s=100" width="100px;" alt=""/> -            <br /> -            <sub> -                <b>Clément Michaud</b> -            </sub> -        </a> -    </td> -    <td align="center"> -        <a href="https://github.com/nightah"> -            <img src="https://avatars.githubusercontent.com/u/3339418?v=4?s=100" width="100px;" alt=""/> -            <br /> -            <sub> -                <b>Amir Zarrinkafsh</b> -            </sub> -        </a> -    </td> -    <td align="center"> -        <a href="https://github.com/james-d-elliott"> -            <img src="https://avatars.githubusercontent.com/u/3903683?v=4?s=100" width="100px;" alt=""/> -            <br /> -            <sub> -                <b>James Elliott</b> -            </sub> -        </a> -    </td> -</table> - - -## Contact Options - -Several contact options exist for our community, the primary one being [Matrix](#matrix). These are in addition to -[GitHub issues](https://github.com/authelia/authelia/issues) for creating a [new issue](https://github.com/authelia/authelia/issues/new/choose). - -### Matrix - -Community members are invited to join the [Matrix Space](https://matrix.to/#/#community:authelia.com) which includes both -the [Support Room](https://matrix.to/#/#support:authelia.com) and the [Contributing Room](https://matrix.to/#/#contributing:authelia.com).  - -- The core team members are identified as administrators in the Space and individual Rooms. -- All channels are linked to [Discord](#discord). - -### Discord - -Community members are invited to join the [Discord Server](https://discord.authelia.com). - -- The core team members are identified by the <span style="color:#BA55D3;">**CORE TEAM**</span> role in Discord. -- The [#support] and [#contributing] channels are linked to [Matrix](#matrix). - -### Email - -You can contact the core team by email via [team@authelia.com](mailto:team@authelia.com). Please note the   -[security@authelia.com](mailto:security@authelia.com) is also available but is strictly reserved for [security] related -matters. - - -[security]: https://github.com/authelia/authelia/security/policy -[#support]: https://discord.com/channels/707844280412012608/707844280412012612 -[#contributing]: https://discord.com/channels/707844280412012608/804943261265297408
\ No newline at end of file diff --git a/docs/archetypes/blog.md b/docs/archetypes/blog.md new file mode 100644 index 000000000..b4ad21a4c --- /dev/null +++ b/docs/archetypes/blog.md @@ -0,0 +1,11 @@ +--- +title: "{{ replace .Name "-" " " | title }}" +description: "" +lead: "" +date: {{ .Date }} +lastmod: {{ .Date }} +draft: true +weight: 50 +images: ["{{ .Name | urlize }}.jpg"] +contributors: [] +--- diff --git a/docs/archetypes/configuration.md b/docs/archetypes/configuration.md new file mode 100644 index 000000000..7118ea64f --- /dev/null +++ b/docs/archetypes/configuration.md @@ -0,0 +1,14 @@ +--- +title: "{{ replace .Name "-" " " | title }}" +description: "" +lead: "" +date: {{ .Date }} +lastmod: {{ .Date }} +draft: true +images: [] +menu: +  configuration: +    parent: "" +weight: 999 +toc: true +--- diff --git a/docs/archetypes/default.md b/docs/archetypes/default.md new file mode 100644 index 000000000..d8210df1b --- /dev/null +++ b/docs/archetypes/default.md @@ -0,0 +1,8 @@ +--- +title: "{{ replace .Name "-" " " | title }}" +description: "" +date: {{ .Date }} +lastmod: {{ .Date }} +draft: true +images: [] +--- diff --git a/docs/archetypes/docs.md b/docs/archetypes/docs.md new file mode 100644 index 000000000..436bd0863 --- /dev/null +++ b/docs/archetypes/docs.md @@ -0,0 +1,14 @@ +--- +title: "{{ replace .Name "-" " " | title }}" +description: "" +lead: "" +date: {{ .Date }} +lastmod: {{ .Date }} +draft: true +images: [] +menu: +  docs: +    parent: "" +weight: 999 +toc: true +--- diff --git a/docs/assets/fonts/.gitkeep b/docs/assets/fonts/.gitkeep new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/docs/assets/fonts/.gitkeep diff --git a/docs/assets/images/.gitkeep b/docs/assets/images/.gitkeep new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/docs/assets/images/.gitkeep diff --git a/docs/assets/js/alert-init.js b/docs/assets/js/alert-init.js new file mode 100644 index 000000000..af3ac3254 --- /dev/null +++ b/docs/assets/js/alert-init.js @@ -0,0 +1,5 @@ +Object.keys(localStorage).forEach(function(key) { +  if (/^global-alert-/.test(key)) { +    document.documentElement.setAttribute('data-global-alert', 'closed'); +  } +});
\ No newline at end of file diff --git a/docs/assets/js/alert.js b/docs/assets/js/alert.js new file mode 100644 index 000000000..1956103d8 --- /dev/null +++ b/docs/assets/js/alert.js @@ -0,0 +1,20 @@ +var announcement = document.getElementById('announcement'); + +if (announcement !== null) { + +  var id = announcement.dataset.id; + +  Object.keys(localStorage).forEach(function(key) { +    if (/^global-alert-/.test(key)) { +      if (key !== id ) { +        localStorage.removeItem(key); +        document.documentElement.removeAttribute('data-global-alert'); +      } +    } +  }); + +  announcement.addEventListener('closed.bs.alert', () => { +    localStorage.setItem(id, 'closed'); +  }); + +}
\ No newline at end of file diff --git a/docs/assets/js/app.js b/docs/assets/js/app.js new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/docs/assets/js/app.js diff --git a/docs/assets/js/bootstrap.js b/docs/assets/js/bootstrap.js new file mode 100644 index 000000000..17f9621f9 --- /dev/null +++ b/docs/assets/js/bootstrap.js @@ -0,0 +1 @@ +import 'bootstrap/dist/js/bootstrap.bundle.min.js' diff --git a/docs/assets/js/clipboard.js b/docs/assets/js/clipboard.js new file mode 100644 index 000000000..55eec7b36 --- /dev/null +++ b/docs/assets/js/clipboard.js @@ -0,0 +1,37 @@ +import Clipboard from 'clipboard'; + +var pre = document.getElementsByTagName('pre'); + +for (var i = 0; i < pre.length; ++ i) +{ +  var element = pre[i]; +  var mermaid = element.getElementsByClassName('language-mermaid')[0]; + +  if (mermaid == null) { +    element.insertAdjacentHTML('afterbegin', '<button class="btn btn-copy"></button>'); +  } +} + +var clipboard = new Clipboard('.btn-copy', { + +  target: function(trigger) { +    return trigger.nextElementSibling; +  }, + +}); + +clipboard.on('success', function(e) { + +    /* +    console.info('Action:', e.action); +    console.info('Text:', e.text); +    console.info('Trigger:', e.trigger); +    */ + +    e.clearSelection(); +}); + +clipboard.on('error', function(e) { +    console.error('Action:', e.action); +    console.error('Trigger:', e.trigger); +}); diff --git a/docs/assets/js/darkmode-init.js b/docs/assets/js/darkmode-init.js new file mode 100644 index 000000000..0f3508deb --- /dev/null +++ b/docs/assets/js/darkmode-init.js @@ -0,0 +1,21 @@ +const globalDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches; +const localMode = localStorage.getItem('theme'); + +if (globalDark && (localMode === null)) { + +  localStorage.setItem('theme', 'dark'); +  document.documentElement.setAttribute('data-dark-mode', ''); + +} + +if (globalDark && (localMode === 'dark')) { + +  document.documentElement.setAttribute('data-dark-mode', ''); + +} + +if (localMode === 'dark') { + +  document.documentElement.setAttribute('data-dark-mode', ''); + +} diff --git a/docs/assets/js/darkmode.js b/docs/assets/js/darkmode.js new file mode 100644 index 000000000..e81db47d7 --- /dev/null +++ b/docs/assets/js/darkmode.js @@ -0,0 +1,38 @@ +const mode = document.getElementById('mode'); + +if (mode !== null) { + +  window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => { + +    if (event.matches) { + +      localStorage.setItem('theme', 'dark'); +      document.documentElement.setAttribute('data-dark-mode', ''); + +    } else { + +      localStorage.setItem('theme', 'light'); +      document.documentElement.removeAttribute('data-dark-mode'); + +    } + +  }) + +  mode.addEventListener('click', () => { + +    document.documentElement.toggleAttribute('data-dark-mode'); +    localStorage.setItem('theme', document.documentElement.hasAttribute('data-dark-mode') ? 'dark' : 'light'); + +  }); + +  if (localStorage.getItem('theme') === 'dark') { + +    document.documentElement.setAttribute('data-dark-mode', ''); + +  } else { + +    document.documentElement.removeAttribute('data-dark-mode'); + +  } + +} diff --git a/docs/assets/js/highlight.js b/docs/assets/js/highlight.js new file mode 100644 index 000000000..381952488 --- /dev/null +++ b/docs/assets/js/highlight.js @@ -0,0 +1,44 @@ +import hljs from 'highlight.js/lib/core'; + +import go from 'highlight.js/lib/languages/go'; +import json from 'highlight.js/lib/languages/json'; +import bash from 'highlight.js/lib/languages/bash'; +import xml from 'highlight.js/lib/languages/xml'; +import yaml from 'highlight.js/lib/languages/yaml'; +import dockerfile from 'highlight.js/lib/languages/dockerfile'; +import nginx from 'highlight.js/lib/languages/nginx'; +import ruby from 'highlight.js/lib/languages/ruby'; +import plaintext from 'highlight.js/lib/languages/plaintext'; +import php from 'highlight.js/lib/languages/php'; +import python from 'highlight.js/lib/languages/python'; +import ldif from 'highlight.js/lib/languages/ldif'; +import ini from 'highlight.js/lib/languages/ini'; + +hljs.registerLanguage('go', go); +hljs.registerLanguage('json', json); +hljs.registerLanguage('bash', bash); +hljs.registerLanguage('console', bash); +hljs.registerLanguage('sh', bash); +hljs.registerLanguage('shell', bash); +hljs.registerLanguage('html', xml); +hljs.registerLanguage('yaml', yaml); +hljs.registerLanguage('yml', yaml); +hljs.registerLanguage('dockerfile', dockerfile); +hljs.registerLanguage('nginx', nginx); +hljs.registerLanguage('ruby', ruby); +hljs.registerLanguage('rb', ruby); +hljs.registerLanguage('plaintext', plaintext); +hljs.registerLanguage('php', php); +hljs.registerLanguage('text', plaintext); +hljs.registerLanguage('txt', plaintext); +hljs.registerLanguage('python', python); +hljs.registerLanguage('py', python); +hljs.registerLanguage('ldif', ldif); +hljs.registerLanguage('ini', ini); +hljs.registerLanguage('cnf', ini); + +document.addEventListener('DOMContentLoaded', () => { +  document.querySelectorAll('pre code:not(.language-mermaid)').forEach((block) => { +    hljs.highlightElement(block); +  }); +}); diff --git a/docs/assets/js/index.js b/docs/assets/js/index.js new file mode 100644 index 000000000..672d6c7a6 --- /dev/null +++ b/docs/assets/js/index.js @@ -0,0 +1,169 @@ +var suggestions = document.getElementById('suggestions'); +var search = document.getElementById('search'); + +if (search !== null) { +  document.addEventListener('keydown', inputFocus); +} + +function inputFocus(e) { +  if (e.ctrlKey && e.key === '/' ) { +    e.preventDefault(); +    search.focus(); +  } +  if (e.key === 'Escape' ) { +    search.blur(); +    suggestions.classList.add('d-none'); +  } +} + +document.addEventListener('click', function(event) { + +  var isClickInsideElement = suggestions.contains(event.target); + +  if (!isClickInsideElement) { +    suggestions.classList.add('d-none'); +  } + +}); + +/* +Source: +  - https://dev.to/shubhamprakash/trap-focus-using-javascript-6a3 +*/ + +document.addEventListener('keydown',suggestionFocus); + +function suggestionFocus(e) { +  const suggestionsHidden = suggestions.classList.contains('d-none'); +  if (suggestionsHidden) return; + +  const focusableSuggestions= [...suggestions.querySelectorAll('a')]; +  if (focusableSuggestions.length === 0) return; + +  const index = focusableSuggestions.indexOf(document.activeElement); + +  if (e.key === "ArrowUp") { +    e.preventDefault(); +    const nextIndex = index > 0 ? index - 1 : 0; +    focusableSuggestions[nextIndex].focus(); +  } +  else if (e.key === "ArrowDown") { +    e.preventDefault(); +    const nextIndex= index + 1 < focusableSuggestions.length ? index + 1 : index; +    focusableSuggestions[nextIndex].focus(); +  } + +} + +/* +Source: +  - https://github.com/nextapps-de/flexsearch#index-documents-field-search +  - https://raw.githack.com/nextapps-de/flexsearch/master/demo/autocomplete.html +*/ + +(function(){ + +  var index = new FlexSearch.Document({ +    tokenize: "forward", +    cache: 100, +    document: { +      id: 'id', +      store: [ +        "href", "title", "description" +      ], +      index: ["title", "description", "content"] +    } +  }); + + +  // Not yet supported: https://github.com/nextapps-de/flexsearch#complex-documents + +  /* +  var docs = [ +    {{ range $index, $page := (where .Site.Pages "Section" "docs") -}} +      { +        id: {{ $index }}, +        href: "{{ .Permalink }}", +        title: {{ .Title | jsonify }}, +        description: {{ .Params.description | jsonify }}, +        content: {{ .Content | jsonify }} +      }, +    {{ end -}} +  ]; +  */ + +  // https://discourse.gohugo.io/t/range-length-or-last-element/3803/2 + +  {{ $list := (where .Site.RegularPages "Type" "in" (union .Site.Params.Sections.Search .Site.Params.Sections.Searchable)) -}} +  {{ $len := (len $list) -}} + +  index.add( +    {{ range $index, $element := $list -}} +      { +        id: {{ $index }}, +        href: "{{ .RelPermalink }}", +        title: {{ .Title | jsonify }}, +        {{ with .Description -}} +          description: {{ . | jsonify }}, +        {{ else -}} +          description: {{ .Summary | plainify | jsonify }}, +        {{ end -}} +        content: {{ .Plain | jsonify }} +      }) +      {{ if ne (add $index 1) $len -}} +        .add( +      {{ end -}} +    {{ end -}} +  ; + +  search.addEventListener('input', show_results, true); + +  function show_results(){ +    const maxResult = 5; +    var searchQuery = this.value; +    var results = index.search(searchQuery, {limit: maxResult, enrich: true}); + +    // flatten results since index.search() returns results for each indexed field +    const flatResults = new Map(); // keyed by href to dedupe results +    for (const result of results.flatMap(r => r.result)) { +      if (flatResults.has(result.doc.href)) continue; +      flatResults.set(result.doc.href, result.doc); +    } + +    suggestions.innerHTML = ""; +    suggestions.classList.remove('d-none'); + +    // inform user that no results were found +    if (flatResults.size === 0 && searchQuery) { +      const noResultsMessage = document.createElement('div') +      noResultsMessage.innerHTML = `No results for "<strong>${searchQuery}</strong>"` +      noResultsMessage.classList.add("suggestion__no-results"); +      suggestions.appendChild(noResultsMessage); +      return; +    } + +    // construct a list of suggestions +    for(const [href, doc] of flatResults) { +        const entry = document.createElement('div'); +        suggestions.appendChild(entry); + +        const a = document.createElement('a'); +        a.href = href; +        entry.appendChild(a); + +        const title = document.createElement('span'); +        title.textContent = doc.title; +        title.classList.add("suggestion__title"); +        a.appendChild(title); + +        const description = document.createElement('span'); +        description.textContent = doc.description; +        description.classList.add("suggestion__description"); +        a.appendChild(description); + +        suggestions.appendChild(entry); + +        if(suggestions.childElementCount == maxResult) break; +    } +  } +}()); diff --git a/docs/assets/js/instant.page.js b/docs/assets/js/instant.page.js new file mode 100644 index 000000000..b394bcc4c --- /dev/null +++ b/docs/assets/js/instant.page.js @@ -0,0 +1 @@ +import 'instant.page'; diff --git a/docs/assets/js/katex.js b/docs/assets/js/katex.js new file mode 100644 index 000000000..e0543eafe --- /dev/null +++ b/docs/assets/js/katex.js @@ -0,0 +1,10 @@ +document.addEventListener('DOMContentLoaded', function() { +  renderMathInElement(document.body, { +    delimiters: [ +      {left: '$$', right: '$$', display: true}, +      {left: '$', right: '$', display: false}, +      {left: '\\(', right: '\\)', display: false}, +      {left: '\\[', right: '\\]', display: true}, +    ], +  }); +}); diff --git a/docs/assets/js/lazysizes.js b/docs/assets/js/lazysizes.js new file mode 100644 index 000000000..c12ed585d --- /dev/null +++ b/docs/assets/js/lazysizes.js @@ -0,0 +1 @@ +import 'lazysizes'; diff --git a/docs/assets/js/mermaid.js b/docs/assets/js/mermaid.js new file mode 100644 index 000000000..b214d5f7f --- /dev/null +++ b/docs/assets/js/mermaid.js @@ -0,0 +1,11 @@ +import mermaid from 'mermaid'; + +var config = { +  theme: 'default', +  fontFamily: '"Jost", -apple-system, blinkmacsystemfont, "Segoe UI", roboto, "Helvetica Neue", arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";', +}; + +document.addEventListener('DOMContentLoaded', () => { +  mermaid.initialize(config); +  mermaid.init(undefined, '.language-mermaid'); +}); diff --git a/docs/assets/js/scroll-lock.js b/docs/assets/js/scroll-lock.js new file mode 100644 index 000000000..069b8c2e3 --- /dev/null +++ b/docs/assets/js/scroll-lock.js @@ -0,0 +1,14 @@ +// Adds scroll position lock for default docs sidebar + +if (document.querySelector('#sidebar-default') !== null) { +  let sidebar = document.getElementById('sidebar-default'); + +  let pos = sessionStorage.getItem('sidebar-scroll'); +  if (pos !== null) { +      sidebar.scrollTop = parseInt(pos, 10); +  } + +  window.addEventListener('beforeunload', () => { +      sessionStorage.setItem('sidebar-scroll', sidebar.scrollTop); +  }); +} diff --git a/docs/assets/js/vendor/.gitkeep b/docs/assets/js/vendor/.gitkeep new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/docs/assets/js/vendor/.gitkeep diff --git a/docs/assets/scss/app.scss b/docs/assets/scss/app.scss new file mode 100644 index 000000000..6d489fb2f --- /dev/null +++ b/docs/assets/scss/app.scss @@ -0,0 +1,37 @@ +/** Import Bootstrap functions */ +@import "bootstrap/scss/functions"; + +/** Import theme variables */ +@import "common/variables"; + +/** Import Bootstrap */ +@import "bootstrap/scss/bootstrap"; +@import "bootstrap-icons/font/bootstrap-icons.scss"; + +/** Import highlight.js */ +@import "highlight.js/scss/github-dark-dimmed"; + +/** Import KaTeX */ +@import "katex/dist/katex"; + +/** Import theme styles */ +@import "common/fonts"; +@import "common/global"; +@import "common/dark"; +@import "components/alerts"; +@import "components/buttons"; +@import "components/code"; +@import "components/details"; +@import "components/syntax"; +@import "components/comments"; +@import "components/forms"; +@import "components/images"; +@import "components/mermaid"; +@import "components/search"; +@import "components/tables"; +@import "layouts/footer"; +@import "layouts/header"; +@import "layouts/pages"; +@import "layouts/posts"; +@import "layouts/sidebar"; +@import "custom"; diff --git a/docs/assets/scss/common/_dark.scss b/docs/assets/scss/common/_dark.scss new file mode 100644 index 000000000..4694fd540 --- /dev/null +++ b/docs/assets/scss/common/_dark.scss @@ -0,0 +1,572 @@ +/** Theme variables */ + +// Source: https://material.io/design/color/dark-theme.html + +$body-bg-dark: $gray-900; +$body-overlay-dark: darken($body-bg-dark, 2.5%); + +/* +$border-dark: darken($body-bg-dark, 2.5%); +*/ +$border-dark: $gray-800; +$body-color-dark: $gray-300; +$dots-dark: darken($body-color-dark, 50%); + +$link-color-dark: $blue-300; +$button-color-dark: $link-color-dark; +$focus-color-dark: lighten($link-color-dark, 2.5%); + +$navbar-dark-color:                 $body-color-dark; +$navbar-dark-hover-color:           $link-color-dark; +$navbar-dark-active-color:          $link-color-dark; + +/** Theme styles */ + +[data-dark-mode] body { +  background: $body-bg-dark; +  color: $body-color-dark; +} + +[data-dark-mode] body a { +  color: $link-color-dark; +} + +[data-dark-mode] body a.text-body { +  color: $body-color-dark !important; +} + +[data-dark-mode] body .btn-primary { +  @include button-variant($button-color-dark, $button-color-dark); + +  color: $body-bg-dark !important; +} + +[data-dark-mode] body .btn-outline-primary { +  @include button-outline-variant($button-color-dark, $button-color-dark); + +  color: $link-color-dark; +} + +[data-dark-mode] body .btn-outline-primary:hover { +  color: $body-bg-dark; +} + +[data-dark-mode] body .btn-doks-light { +  color: $navbar-dark-color; +} + +[data-dark-mode] body .show > .btn-doks-light, +[data-dark-mode] body .btn-doks-light:hover, +[data-dark-mode] body .btn-doks-light:active { +  color: $link-color-dark; +} + +[data-dark-mode] body .btn-menu svg { +  color: $body-color-dark; +} + +[data-dark-mode] body .doks-sidebar-toggle { +  color: $navbar-dark-color; +} + +[data-dark-mode] body .btn-menu:hover, +[data-dark-mode] body .btn-doks-light:hover, +[data-dark-mode] body .doks-sidebar-toggle:hover { +  background: $body-overlay-dark; +} + +/* +[data-dark-mode] body .dropdown-menu { +  @extend .dropdown-menu-dark; +} +*/ + +[data-dark-mode] body .navbar, +[data-dark-mode] body .doks-subnavbar { +  background-color: rgba(33, 37, 41, 0.95); +  border-bottom: 1px solid $border-dark; +} + +[data-dark-mode] body.home .navbar { +  border-bottom: 0; +} + +[data-dark-mode] body .offcanvas-header { +  border-bottom: 1px solid $gray-800; +} + +[data-dark-mode] body .offcanvas .nav-link { +  color: $body-color-dark; +} + +[data-dark-mode] body .offcanvas .nav-link:hover, +[data-dark-mode] body .offcanvas .nav-link:focus { +  color: $link-color-dark; +} + +[data-dark-mode] body .offcanvas .nav-link.active { +  color: $link-color-dark; +} + +[data-dark-mode] body .navbar-light .navbar-brand { +  color: $navbar-dark-color !important; +} + +[data-dark-mode] body .navbar-light .navbar-nav .nav-link { +  color: $navbar-dark-color; +} + +[data-dark-mode] body .navbar-light .navbar-nav .nav-link:hover, +[data-dark-mode] body .navbar-light .navbar-nav .nav-link:focus { +  color: $navbar-dark-hover-color; +} + +[data-dark-mode] body .navbar-light .navbar-nav .nav-link.disabled { +  color: $navbar-dark-disabled-color; +} + +[data-dark-mode] body .navbar-light .navbar-nav .show > .nav-link, +[data-dark-mode] body .navbar-light .navbar-nav .active > .nav-link, +[data-dark-mode] body .navbar-light .navbar-nav .nav-link.show, +[data-dark-mode] body .navbar-light .navbar-nav .nav-link.active { +  color: $navbar-dark-active-color; +} + +[data-dark-mode] body .navbar-light .navbar-text { +  color: $navbar-dark-color; +} + +[data-dark-mode] body .alert-primary a { +  color: $body-bg-dark; +} + +[data-dark-mode] body .alert-doks { +  background: $body-overlay-dark; +  color: $body-color-dark; +} + +[data-dark-mode] body .alert-doks a { +  color: $link-color-dark; +} + +[data-dark-mode] body .page-links a { +  color: $body-color-dark; +} + +[data-dark-mode] body .btn-toggle-nav a { +  color: $body-color-dark; +} + +[data-dark-mode] body .showcase-meta a { +  color: $body-color-dark; +} + +[data-dark-mode] body .showcase-meta a:hover, +[data-dark-mode] body .showcase-meta a:focus { +  color: $link-color-dark; +} + +[data-dark-mode] body .docs-link:hover, +[data-dark-mode] body .docs-link.active, +[data-dark-mode] body .page-links a:hover { +  text-decoration: none; +  color: $link-color-dark; +} + +[data-dark-mode] body .btn-toggle { +  color: $body-color-dark; +  background-color: transparent; +  border: 0; +} + +[data-dark-mode] body .btn-toggle:hover, +[data-dark-mode] body .btn-toggle:focus { +  color: $body-color-dark; +} + +[data-dark-mode] body .btn-toggle::before { +  width: 1.25em; +  line-height: 0; +  content: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='rgba%28222, 226, 230, 0.75%29' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M5 14l6-6-6-6'/%3e%3c/svg%3e"); +  transition: transform 0.35s ease; +  transform-origin: 0.5em 50%; +  margin-bottom: 0.125rem; +} + +[data-dark-mode] body .btn-toggle[aria-expanded="true"] { +  color: $body-color-dark; +} + +[data-dark-mode] body .btn-toggle[aria-expanded="true"]::before { +  transform: rotate(90deg); +} + +[data-dark-mode] body .btn-toggle-nav a:hover, +[data-dark-mode] body .btn-toggle-nav a:focus { +  color: $link-color-dark; +} + +[data-dark-mode] body .btn-toggle-nav a.active { +  color: $link-color-dark; +} + +[data-dark-mode] body .navbar-light .navbar-text a { +  color: $navbar-dark-active-color; +} + +[data-dark-mode] body .docs-links h3.sidebar-link a, +[data-dark-mode] body .page-links h3.sidebar-link a { +  color: $body-color-dark; +} + +[data-dark-mode] body .navbar-light .navbar-text a:hover, +[data-dark-mode] body .navbar-light .navbar-text a:focus { +  color: $navbar-dark-active-color; +} + +[data-dark-mode] body .navbar .btn-link { +  color: $navbar-dark-color; +} + +[data-dark-mode] body .content .btn-link { +  color: $link-color-dark; +} + +[data-dark-mode] body .content .btn-link:hover { +  color: $link-color-dark; +} + +[data-dark-mode] body .content img[src^="https://latex.codecogs.com/svg.latex"] { +  filter: invert(1); +} + +[data-dark-mode] body .navbar .btn-link:hover { +  color: $navbar-dark-hover-color; +} + +[data-dark-mode] body .navbar .btn-link:active { +  color: $navbar-dark-active-color; +} + +[data-dark-mode] body .form-control.is-search { +  background: $body-overlay-dark; +  border: 1px solid transparent; +  color: $gray-300; + +  /* +  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='%236c757d' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-search'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E"); +  background-repeat: no-repeat; +  background-position: right calc(0.375em + 0.1875rem) center; +  background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); +  */ +} + +[data-dark-mode] body .form-control.is-search:focus { +  border: 1px solid $link-color-dark; +} + +[data-dark-mode] body .doks-search::after { +  color: $gray-300; +  border: 1px solid $gray-700; +} + +[data-dark-mode] body .text-dark { +  color: $body-color-dark !important; +} + +/* +[data-dark-mode] body .navbar-form::after { +  color: $gray-600; +  border: 1px solid $gray-800; +} +*/ + +[data-dark-mode] body .form-control { +  color: $gray-300; +} + +[data-dark-mode] body .form-control::placeholder { +  color: $gray-400; +  opacity: 1; +} + +[data-dark-mode] body .border-top { +  border-top: 1px solid $border-dark !important; +} + +@include media-breakpoint-up(lg) { +  [data-dark-mode] body .docs-sidebar { +    order: 0; +    border-right: 1px solid $border-dark; +  } +} + +[data-dark-mode] body .docs-navigation { +  border-top: 1px solid $border-dark; +} + +[data-dark-mode] body pre code::-webkit-scrollbar-thumb { +  background: $gray-400; +} + +[data-dark-mode] body code:not(.hljs) { +  background: $body-overlay-dark; +  color: $body-color-dark; +} + +[data-dark-mode] body pre code:hover { +  scrollbar-width: thin; +  scrollbar-color: $border-dark transparent; +} + +[data-dark-mode] body pre code::-webkit-scrollbar-thumb:hover { +  background: $gray-500; +} + +[data-dark-mode] body blockquote { +  border-left: 3px solid $border-dark; +} + +[data-dark-mode] body .footer { +  border-top: 1px solid $border-dark; +} + +[data-dark-mode] body .docs-links, +[data-dark-mode] body .docs-toc { +  scrollbar-width: thin; +  scrollbar-color: $body-bg-dark $body-bg-dark; +} + +[data-dark-mode] body .docs-links::-webkit-scrollbar, +[data-dark-mode] body .docs-toc::-webkit-scrollbar { +  width: 5px; +} + +[data-dark-mode] body .docs-links::-webkit-scrollbar-track, +[data-dark-mode] body .docs-toc::-webkit-scrollbar-track { +  background: $body-bg-dark; +} + +[data-dark-mode] body .docs-links::-webkit-scrollbar-thumb, +[data-dark-mode] body .docs-toc::-webkit-scrollbar-thumb { +  background: $body-bg-dark; +} + +[data-dark-mode] body .docs-links:hover, +[data-dark-mode] body .docs-toc:hover { +  scrollbar-width: thin; +  scrollbar-color: $border-dark $body-bg-dark; +} + +[data-dark-mode] body .docs-links:hover::-webkit-scrollbar-thumb, +[data-dark-mode] body .docs-toc:hover::-webkit-scrollbar-thumb { +  background: $border-dark; +} + +[data-dark-mode] body .docs-links::-webkit-scrollbar-thumb:hover, +[data-dark-mode] body .docs-toc::-webkit-scrollbar-thumb:hover { +  background: $border-dark; +} + +[data-dark-mode] body .docs-links h3:not(:first-child) { +  border-top: 1px solid $border-dark; +} + +[data-dark-mode] body a.docs-link { +  color: $body-color-dark; +} + +[data-dark-mode] body .page-links li:not(:first-child) { +  border-top: 1px dashed $border-dark; +} + +[data-dark-mode] body .card { +  background: $body-bg-dark; +  border: 1px solid $border-dark; +} + +[data-dark-mode] body .card.bg-light { +  background: $body-overlay-dark !important; +} + +[data-dark-mode] body .navbar .menu-icon .navicon { +  background: $navbar-dark-color; +} + +[data-dark-mode] body .navbar .menu-icon .navicon::before, +[data-dark-mode] body .navbar .menu-icon .navicon::after { +  background: $navbar-dark-color; +} + +[data-dark-mode] body .logo-light { +  display: none !important; +} + +[data-dark-mode] body .logo-dark { +  display: inline-block !important; +} + +[data-dark-mode] body .bg-light { +  background: darken($body-bg-dark, 1.5%) !important; +} + +[data-dark-mode] body .bg-dots { +  background-image: radial-gradient($dots-dark 15%, transparent 15%); +} + +[data-dark-mode] body .text-muted { +  color: darken($body-color-dark, 7.5%) !important; +} + +[data-dark-mode] body .alert-primary { +  background: $link-color-dark; +  color: $body-bg-dark; +} + +[data-dark-mode] body .figure-caption { +  color: $body-color-dark; +} + +[data-dark-mode] body table { +  @extend .table-dark; +} + +[data-dark-mode] body .copy-status::after { +  content: "Copy"; +  display: block; +  color: $body-color-dark; +} + +[data-dark-mode] body .copy-status:hover::after { +  content: "Copy"; +  display: block; +  color: $link-color-dark; +} + +[data-dark-mode] body .copy-status:focus::after, +[data-dark-mode] body .copy-status:active::after { +  content: "Copied"; +  display: block; +  color: $link-color-dark; +} + +/* +[data-dark-mode] body .dropdown-toggle:focus, +[data-dark-mode] body .doks-sidebar-toggle:focus { +  box-shadow: 0 0 0 0.2rem $focus-color-dark; +} +*/ + +[data-dark-mode] body .offcanvas { +  background-color: $body-bg-dark; +} + +[data-dark-mode] body .btn-close { +  background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiNkZWUyZTYiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0iZmVhdGhlciBmZWF0aGVyLXgiPjxsaW5lIHgxPSIxOCIgeTE9IjYiIHgyPSI2IiB5Mj0iMTgiPjwvbGluZT48bGluZSB4MT0iNiIgeTE9IjYiIHgyPSIxOCIgeTI9IjE4Ij48L2xpbmU+PC9zdmc+"); +  background-size: 1.5rem; +} + +@include media-breakpoint-up(md) { +  [data-dark-mode] body .alert-dismissible .btn-close { +    background-size: 1.25rem; +  } +} + +/* +[data-dark-mode] body .btn-close:focus { +  box-shadow: 0 0 0 0.2rem $focus-color-dark; +} +*/ + +[data-dark-mode] .dropdown-item { +  color: $body-bg-dark; +} + +[data-dark-mode] body hr.text-black-50 { +  color: $gray-600 !important; +} + +[data-dark-mode] body .email-form .form-control { +  background: $body-overlay-dark; +  border: 1px solid transparent; +} + +[data-dark-mode] body .email-form .form-control:focus { +  border: 1px solid $link-color-dark; +} + +[data-dark-mode] .page-link { +  color: $link-color-dark; +  background-color: transparent; +  border: $pagination-border-width solid $border-dark; + +  &:hover { +    color: $body-bg-dark; +    background-color: $body-color-dark; +    border-color: $body-color-dark; +  } + +  &:focus { +    color: $body-bg-dark; +    background-color: $body-color-dark; +  } +} + +[data-dark-mode] .page-item { +  &.active .page-link { +    color: $body-bg-dark; + +    @include gradient-bg($link-color-dark); + +    border-color: $link-color-dark; +  } + +  &.disabled .page-link { +    color: $pagination-disabled-color; +    background-color: $body-overlay-dark; +    border-color: $border-dark; +  } +} + +[data-dark-mode] .dropdown-menu { +  background: $body-overlay-dark; +} + +[data-dark-mode] .dropdown-menu .dropdown-item { +  color: $body-color-dark; +} + +[data-dark-mode] .dropdown-menu .dropdown-item:hover { +  color: $link-color-dark; +  background: $body-bg-dark; +} + +[data-dark-mode] .dropdown-menu .dropdown-item.active, +[data-dark-mode] .dropdown-menu .dropdown-item:focus { +  color: $link-color-dark; +  background: $body-bg-dark; +} + +[data-dark-mode] .doks-navbar .dropdown-item.current, +[data-dark-mode] .doks-subnavbar .dropdown-item.current { +  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23dee2e6' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e"); +  background-repeat: no-repeat; +  background-position: right 1rem top 0.6rem; +  background-size: 0.75rem 0.75rem; +} + +[data-dark-mode] details { +  border: 1px solid $border-dark; +} + +[data-dark-mode] summary:hover { +  background: $body-overlay-dark; +} + +[data-dark-mode] details[open] > summary { +  border-bottom: 1px solid $border-dark; +} + +[data-dark-mode] details summary::before { +  content: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='rgba%28222, 226, 230, 0.75%29' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M5 14l6-6-6-6'/%3e%3c/svg%3e"); +} diff --git a/docs/assets/scss/common/_fonts.scss b/docs/assets/scss/common/_fonts.scss new file mode 100644 index 000000000..9bbc6eee5 --- /dev/null +++ b/docs/assets/scss/common/_fonts.scss @@ -0,0 +1,101 @@ +/* jost-regular - latin */ +@font-face { +  font-family: Jost; +  font-style: normal; +  font-weight: 400; +  font-display: swap; +  src: +    // Google Fonts Jost +    local("Jost Regular Regular"),   // Full Name +    local("Jost-Regular"),           // PostScript name +    // indestructible Jost* +    local("Jost* Book"), +    local("Jost-Book"), +    url("fonts/vendor/jost/jost-v4-latin-regular.woff2") format("woff2"), +    url("fonts/vendor/jost/jost-v4-latin-regular.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} + +/* jost-500 - latin */ +@font-face { +  font-family: Jost; +  font-style: normal; +  font-weight: 500; +  font-display: swap; +  src: +    // Google Fonts Jost +    local("Jost Regular Medium"), +    local("JostRoman-Medium"), +    // indestructible Jost* +    local("Jost* Medium"), +    local("Jost-Medium"), +    url("fonts/vendor/jost/jost-v4-latin-500.woff2") format("woff2"), +    url("fonts/vendor/jost/jost-v4-latin-500.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} + +/* jost-700 - latin */ +@font-face { +  font-family: Jost; +  font-style: normal; +  font-weight: 700; +  font-display: swap; +  src: +    // Google Fonts Jost +    local("Jost Regular Bold"), +    local("JostRoman-Bold"), +    // indestructible Jost* +    local("Jost* Bold"), +    local("Jost-Bold"), +    url("fonts/vendor/jost/jost-v4-latin-700.woff2") format("woff2"), +    url("fonts/vendor/jost/jost-v4-latin-700.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} + +/* jost-italic - latin */ +@font-face { +  font-family: Jost; +  font-style: italic; +  font-weight: 400; +  font-display: swap; +  src: +    // Google Fonts Jost +    local("Jost Italic Italic"), +    local("Jost-Italic"), +    // indestructible Jost* +    local("Jost* BookItalic"), +    local("Jost-BookItalic"), +    url("fonts/vendor/jost/jost-v4-latin-italic.woff2") format("woff2"), +    url("fonts/vendor/jost/jost-v4-latin-italic.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} + +/* jost-500italic - latin */ +@font-face { +  font-family: Jost; +  font-style: italic; +  font-weight: 500; +  font-display: swap; +  src: +    // Google Fonts Jost +    local("Jost Italic Medium Italic"), +    local("JostItalic-Medium"), +    // indestructible Jost* +    local("Jost* Medium Italic"), +    local("Jost-MediumItalic"), +    url("fonts/vendor/jost/jost-v4-latin-500italic.woff2") format("woff2"), +    url("fonts/vendor/jost/jost-v4-latin-500italic.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} + +/* jost-700italic - latin */ +@font-face { +  font-family: Jost; +  font-style: italic; +  font-weight: 700; +  font-display: swap; +  src: +    // Google Fonts Jost +    local("Jost Italic Bold Italic"), +    local("JostItalic-Bold"), +    // indestructible Jost* +    local("Jost* Bold Italic"), +    local("Jost-BoldItalic"), +    url("fonts/vendor/jost/jost-v4-latin-700italic.woff2") format("woff2"), +    url("fonts/vendor/jost/jost-v4-latin-700italic.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} diff --git a/docs/assets/scss/common/_global.scss b/docs/assets/scss/common/_global.scss new file mode 100644 index 000000000..8fa8b2f93 --- /dev/null +++ b/docs/assets/scss/common/_global.scss @@ -0,0 +1,312 @@ +.contributors .content, +.blog .content, +.page .content, +.error404 .content, +.docs.list .content, +.tutorial.list .content, +.showcase.list .content { +  padding-top: 1rem; +  padding-bottom: 3rem; +} + +.content img { +  max-width: 100%; +} + +h1, +h2, +h3, +h4, +h5, +h6, +.h1, +.h2, +.h3, +.h4, +.h5, +.h6 { +  margin: 2rem 0 1rem; +} + +.offcanvas-header { +  border-bottom: 1px solid $gray-300; +  padding-top: 1.0625rem; +  padding-bottom: 0.8125rem; +} + +h5.offcanvas-title { +  margin: 0; +} + +body.docs { +  padding-top: 0 !important; +} + +@include media-breakpoint-up(md) { +  body { +    font-size: $font-size-md; + +    /* +    padding-top: 4rem !important; +    */ +  } + +  h1, +  h2, +  h3, +  h4, +  h5, +  h6, +  .h1, +  .h2, +  .h3, +  .h4, +  .h5, +  .h6 { +    margin-bottom: 1.125rem; +  } +} + +.home h1 { +  /* font-size: calc(1.375rem + 1.5vw); */ +  font-size: calc(1.875rem + 1.5vw); +} + +a:hover, +a:focus { +  text-decoration: underline; +} + +a.btn:hover, +a.btn:focus { +  text-decoration: none; +} + +.section { +  padding-top: 5rem; +  padding-bottom: 5rem; +} + +.section-md { +  padding-top: 3rem; +  padding-bottom: 3rem; +} + +.section-sm { +  padding-top: 1rem; +  padding-bottom: 1rem; +} + +/* +.section svg { +  display: inline-block; +  width: 2rem; +  height: 2rem; +  vertical-align: text-top; +} +*/ + +/* +body { +  padding-top: 3.5625rem; +} +*/ + +.docs-sidebar { +  order: 2; +} + +@include media-breakpoint-up(lg) { +  .docs-sidebar { +    order: 0; +    border-right: 1px solid $gray-200; +  } + +  @supports ((position:-webkit-sticky) or (position:sticky)) { +    .docs-sidebar { +      position: -webkit-sticky; +      position: sticky; +      top: 4rem; +      z-index: 1000; +      height: calc(100vh - 4rem); +    } +  } +} + +@include media-breakpoint-up(xl) { +  .docs-sidebar { +    flex: 0 1 320px; +  } +} + +.docs-links { +  padding-bottom: 5rem; +} + +@include media-breakpoint-up(lg) { +  @supports ((position: -webkit-sticky) or (position: sticky)) { +    .docs-links { +      max-height: calc(100vh - 4rem); +      overflow-y: scroll; +    } +  } +} + +@include media-breakpoint-up(lg) { +  .docs-links { +    display: block; +    width: auto; +    margin-right: -1.5rem; +    padding-bottom: 4rem; +  } +} + +.docs-toc { +  order: 2; +} + +@supports ((position:-webkit-sticky) or (position:sticky)) { +  .docs-toc { +    position: -webkit-sticky; +    position: sticky; +    top: 4rem; +    height: calc(100vh - 4rem); +    overflow-y: auto; +  } +} + +.docs-content { +  padding-bottom: 3rem; +  order: 1; +} + +.docs-navigation { +  border-top: 1px solid $gray-200; +  margin-top: 2rem; +  margin-bottom: 0; +  padding-top: 2rem; +} + +.docs-navigation a { +  font-size: $font-size-base * 0.9; +} + +@include media-breakpoint-up(lg) { +  .docs-navigation { +    margin-bottom: -1rem; +  } + +  .docs-navigation a { +    font-size: $font-size-base; +  } +} + +.navbar a:hover, +.navbar a:focus { +  text-decoration: none; +} + +#TableOfContents ul { +  padding-left: 0; +  list-style: none; +} + +::selection { +  background: rgba(212, 53, 159, 0.2); +} + +.bg-dots { +  background-image: radial-gradient($gray-300 15%, transparent 15%); +  background-position: 0 0; +  background-size: 1rem 1rem; +  -webkit-mask: linear-gradient(to top, #fff, transparent); +  mask: linear-gradient(to top, #fff, transparent); +  width: 100%; +  height: 9rem; +  margin-top: -10rem; +  z-index: -1; +} + +.bg-dots-md { +  margin-top: -11rem; +} + +.bg-dots-lg { +  margin-top: -12rem; +} + +.confkey-type { +  background-color: $purple; +} + +.confkey-default { +  background-color: $blue; +} + +.confkey-required { +  background-color: $red; +} + +.confkey-notrequired { +  background-color: $green; +} + +.confkey-situational { +  background-color: $orange; +} + +.rs-not-started { +  background-color: $red; +} + +.rs-complete { +  background-color: $green; +} + +.rs-started { +  background-color: $blue; +} + +.rs-waiting { +  background-color: $yellow; +} + +.rs-version { +  background-color: $purple; +} + +// https://fossheim.io/writing/posts/css-text-gradient/ +.gradient-text { +  background-color: $primary; +  background-image: linear-gradient(90deg, $primary, $blue-300 50%, $pink-500); +  background-size: 100%; +  background-repeat: repeat; +  -webkit-background-clip: text; +  -moz-background-clip: text; +  -webkit-text-fill-color: transparent; +  -moz-text-fill-color: transparent; +} + +.katex { +  font-size: $font-size-md; +} + +.card-bar { +  border-top: 4px solid; +  border-image-source: linear-gradient(90deg, $primary, #8ed6fb 50%, #d32e9d); +  border-image-slice: 1; +} + +.modal-backdrop { +  background-color: #fff; +} + +.modal-backdrop.show { +  opacity: 0.7; +} + +@include media-breakpoint-up(md) { +  .modal-backdrop.show { +    opacity: 0; +  } +} diff --git a/docs/assets/scss/common/_variables.scss b/docs/assets/scss/common/_variables.scss new file mode 100644 index 000000000..77f538454 --- /dev/null +++ b/docs/assets/scss/common/_variables.scss @@ -0,0 +1,200 @@ +// Color system + +$white:    #fff; +$gray-100: #f8f9fa; +$gray-200: #e9ecef; +$gray-300: #dee2e6; +$gray-400: #ced4da; +$gray-500: #adb5bd; +$gray-600: #6c757d; +$gray-700: #495057; +$gray-800: #343a40; +$gray-900: #212529; +$black:    #000; + +$yellow:   #ffe000; +$black:    #1d2d35; +$beige:    #fbf7f0; + +// $red:      #e55235; +$purple:   #5d2f86; +$brown:    #aa9c84; + +$blue-300: #8ed6fb; +$pink-100: #fcfaff; +$pink-500: #d32e9d; + +$primary: $purple; + +$color-btn-bg: $pink-500; +$color-btn-border: darken($pink-500, 5%); +$color-btn-text: $white; + +// Options +// +// Quickly modify global styling by enabling or disabling optional features. + +$enable-caret:                true; +$enable-rounded:              true; +$enable-shadows:              false; +$enable-gradients:            false; +$enable-transitions:          true; +$enable-reduced-motion:       true; +$enable-smooth-scroll:        true; +$enable-grid-classes:         true; +$enable-button-pointers:      true; +$enable-rfs:                  true; +$enable-validation-icons:     true; +$enable-negative-margins:     true; +$enable-deprecation-messages: true; +$enable-important-utilities:  true; + +/** Bootstrap navbar fix (https://git.io/fADqW) */ +$navbar-dark-toggler-icon-bg: none; +$navbar-light-toggler-icon-bg: none; + +// Options +// +// Quickly modify global styling by enabling or disabling optional features. + +// $enable-responsive-font-sizes: true; + +// Body +// +// Settings for the `<body>` element. + +$body-bg:                   $white; +$body-color:                $black; + +// Links +// +// Style anchor elements. + +$link-color:                              $primary; +$link-decoration:                         none; + +// Grid containers +// +// Define the breakpoints for different screen sizes. +$grid-breakpoints: ( +  xs: 0, +  sm: 576px, +  md: 768px, +  lg: 992px, +  xl: 1200px, +  xxl: 2380px +); + +// Define the maximum width of `.container` for different screen sizes. + +$container-max-widths: ( +  sm: 540px, +  md: 720px, +  lg: 960px, +  xl: 1240px, +  xxl: 2240px +); + +@include _assert-ascending($container-max-widths, "$container-max-widths"); + +// Grid columns +// +// Set the number of columns and specify the width of the gutters. + +$grid-columns:                16; +$grid-gutter-width:           48px; +$grid-row-columns:            6; + +// Components +// +// Define common padding and border radius sizes and more. + +$border-color:                $gray-200; + +// Typography +// +// Font, line-height, and color for body text, headings, and more. + +// stylelint-disable value-keyword-case +$font-family-sans-serif:      "Jost", -apple-system, blinkmacsystemfont, "Segoe UI", roboto, "Helvetica Neue", arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; +$font-family-monospace:       sfmono-regular, menlo, monaco, consolas, "Liberation Mono", "Courier New", monospace; +$font-family-base:            $font-family-sans-serif; +// stylelint-enable value-keyword-case + +$font-size-base:              1rem; // Assumes the browser default, typically `16px` +$font-size-xl:                $font-size-base * 1.375; +$font-size-lg:                $font-size-base * 1.25; +$font-size-md:                $font-size-base * 1.125; +$font-size-sm:                $font-size-base * 0.875; + +// $line-height-base:            1.5; + +$headings-font-family:        null; +$headings-font-weight:        700; + +$lead-font-weight:            400; + +// Spacing +// +// Control the default styling of most Bootstrap elements by modifying these +// variables. Mostly focused on spacing. +// You can add more entries to the $spacers map, should you need more variation. + +$spacer: 1rem; + +// Navbar + +$navbar-padding-y:                  $spacer / 2; +$navbar-padding-x:                  null; + +$navbar-nav-link-padding-x:         0.5rem; + +$navbar-light-color:                $black; +$navbar-light-hover-color:          $primary; +$navbar-light-active-color:         $primary; + +// Cards + +$card-border-color:                 $gray-200; + +// Alerts +// +// Define alert colors, border radius, and padding. + +$alert-padding-y:                   $spacer; +$alert-padding-x:                   $spacer * 1.5; +$alert-margin-bottom:               0; +$alert-border-radius:               0; +$alert-link-font-weight:            $headings-font-weight; +$alert-border-width:                0; + +$alert-bg-scale:                    0; +$alert-border-scale:                0; +$alert-color-scale:                 0; + +// docsearch +$dropdown-config: ( +  main-color: $purple, +  layout-type: normal, +  layout-width: normal, +  layout-alignment: align, +  background-color: $white, +  border-radius: 4, +  border-width: 1, +  border-color: $gray-200, +  box-shadow: none, +  branding-position: bottom, +  spacing: normal, +  include-desc: yes, +  background-category-header: $white, +  font-size: normal, +  header-color: $black, +  title-color: $black, +  subtitle-color: $black, +  text-color: $black, +  highlight-color: $purple, +  highlight-opacity: 0.1, +  highlight-type: underline +); + +$input-btn-focus-width:       0; diff --git a/docs/assets/scss/components/_alerts.scss b/docs/assets/scss/components/_alerts.scss new file mode 100644 index 000000000..0e4ed8344 --- /dev/null +++ b/docs/assets/scss/components/_alerts.scss @@ -0,0 +1,164 @@ +.alert { +  font-family: $font-family-monospace; +  font-size: $font-size-sm; +} + +.alert-icon { +  margin-right: 0.75rem; +} + +.docs main .alert { +  margin: 2rem -1.5rem; +} + +.alert .alert-link { +  text-decoration: underline; +} + +.alert-doks { +  background: $beige; +  color: $black; +} + +/* +.alert-light { +  color: #215888; +  background: linear-gradient(-45deg, rgb(212, 245, 255), rgb(234, 250, 255), rgb(234, 250, 255), #d3f6ef); +} + +.alert-light .alert-link { +  color: #215888; +} +*/ + +.alert-white { +  background-color: rgba(255, 255, 255, 0.95); +} + +.alert-primary { +  color: $white; +  background-color: $primary; +} + +.alert a { +  text-decoration: underline; +} + +.alert-primary .alert-link { +  color: $white; +} + +/* +.alert-primary { +  color: #084298; +  background-color: #cfe2ff; +  border-color: #b6d4fe; +} + +.alert-primary .alert-link { +  color: #06357a; +} +*/ + +.alert-secondary { +  color: #41464b; +  background-color: #e2e3e5; +  border-color: #d3d6d8; +} + +.alert-secondary .alert-link { +  color: #34383c; +} + +.alert-success { +  color: #0f5132; +  background-color: #d1e7dd; +  border-color: #badbcc; +} + +.alert-success .alert-link { +  color: #0c4128; +} + +.alert-info { +  color: #055160; +  background-color: #cff4fc; +  border-color: #b6effb; +} + +.alert-info .alert-link { +  color: #04414d; +} + +.alert-warning { +  color: #664d03; +  background-color: #fff3cd; +  border-color: #ffecb5; +} + +.alert-warning .alert-link { +  color: #523e02; +} + +.alert-danger { +  color: #842029; +  background-color: #f8d7da; +  border-color: #f5c2c7; +} + +.alert-danger .alert-link { +  color: #6a1a21; +} + +.alert-light { +  color: #636464; +  background-color: #fefefe; +  border-color: #fdfdfe; +} + +.alert-light .alert-link { +  color: #4f5050; +} + +.alert-dark { +  color: #141619; +  background-color: #d3d3d4; +  border-color: #bcbebf; +} + +.alert-dark .alert-link { +  color: #101214; +} + +.alert .alert-link:hover, +.alert .alert-link:focus { +  text-decoration: none; +} + +.alert-dismissible .btn-close { +  position: absolute; +  top: 50%; +  transform: translateY(-50%); +  right: 1rem; +  z-index: 2; +  padding: 0.5rem; +  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-x'%3E%3Cline x1='18' y1='6' x2='6' y2='18'%3E%3C/line%3E%3Cline x1='6' y1='6' x2='18' y2='18'%3E%3C/line%3E%3C/svg%3E"); +  background-size: 1.5rem; +  filter: invert(1) grayscale(100%) brightness(200%); +} + +@include media-breakpoint-up(md) { +  .alert-dismissible .btn-close { +    background-size: 1.25rem; +  } +} + +[data-global-alert="closed"] #announcement { +  display: none; +} + +.alert code { +  background: darken($beige, 5%); +  color: $black; +  padding: 0.25rem 0.5rem; +} diff --git a/docs/assets/scss/components/_buttons.scss b/docs/assets/scss/components/_buttons.scss new file mode 100644 index 000000000..235d6ea19 --- /dev/null +++ b/docs/assets/scss/components/_buttons.scss @@ -0,0 +1,253 @@ +.navbar .btn-link { +  color: $navbar-light-color; +  padding: 0.4375rem 0; +} + +#mode { +  padding-right: 0.25rem; +  padding-left: 0.25rem; +  margin-right: -0.25rem; +} + +.btn-link:focus { +  outline: 0; +  box-shadow: none; +} + +#navigation { +  margin-left: 1.25rem; +} + +@include media-breakpoint-up(md) { +  #mode { +    margin-left: 1.125rem; +    margin-right: -0.375rem; +  } + +  .navbar .btn-link { +    padding: 0.5625em 0.25rem 0.5rem 0.125rem; +  } +} + +.navbar .btn-link:hover { +  color: $navbar-light-hover-color; +} + +.navbar .btn-link:active { +  color: $navbar-light-active-color; +} + +body .toggle-dark { +  display: block; +} + +body .toggle-light { +  display: none; +} + +[data-dark-mode] body .toggle-light { +  display: block; +} + +[data-dark-mode] body .toggle-dark { +  display: none; +} + +pre { +  position: relative; +} + +@include media-breakpoint-down(md) { +  .btn-copy { +    display: none; +  } +} + +.btn-copy { +  transition: opacity 0.3s ease-in-out; +  visibility: hidden !important; +  position: absolute; +  right: 0.25rem; +  top: 0.25rem; +  z-index: 10; +  font-family: $font-family-sans-serif; +  font-size: $font-size-sm; +  padding: 0.25rem 0.5rem; +  color: $color-btn-text; +  background-color: $color-btn-bg; +  border-color: $color-btn-border; +} + +.btn-copy:hover { +  color: $color-btn-text; +  background-color: lighten($color-btn-bg, 5%); +  border-color: lighten($color-btn-border, 15%); +} + +.btn-copy:focus { +  color: $color-btn-text; +  background-color: $color-btn-bg; +  border-color: lighten($color-btn-border, 15%); +  box-shadow: none; +} + +.btn-copy:active, +.btn-copy.active { +  color: $color-btn-text; +  background-color: $color-btn-bg; +  border-color: lighten($color-btn-border, 15%); +} + +.btn-copy:active:focus, +.btn-copy.active:focus { +  box-shadow: none; +} + +@include media-breakpoint-up(md) { +  pre:hover .btn-copy { +    visibility: visible !important; +  } +} + +.btn-copy::after { +  content: "Copy"; +  display: block; +  color: $color-btn-text; +} + +.btn-copy:hover::after { +  content: "Copy"; +  display: block; +  color: $color-btn-text; +} + +.btn-copy:focus::after, +.btn-copy:active::after { +  content: "Copied"; +  display: block; +  color: $color-btn-text; +} + +.collapsible-sidebar { +  margin: 2.125rem 0; +} + +.btn-toggle { +  display: inline-flex; +  align-items: center; +  padding: 0.25rem 0.5rem 0.25rem 0; +  font-weight: $headings-font-weight; +  font-size: $font-size-base; +  text-transform: uppercase; +  color: $body-color; +  background-color: transparent; +  border: 0; +} + +.btn-toggle:hover, +.btn-toggle:focus { +  color: $body-color; +  background-color: transparent; +  outline: 0; +  box-shadow: none; +} + +.btn-toggle::before { +  width: 1.25em; +  line-height: 0; +  content: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='rgba%2829, 45, 53, 0.75%29' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M5 14l6-6-6-6'/%3e%3c/svg%3e"); +  transition: transform 0.35s ease; +  transform-origin: 0.5em 50%; +  margin-bottom: 0.125rem; +} + +.btn-toggle[aria-expanded="true"] { +  color: $body-color; +} + +.btn-toggle[aria-expanded="true"]::before { +  transform: rotate(90deg); +} + +.btn-toggle-nav a { +  display: inline-flex; +  padding: 0.1875rem 0.5rem; +  margin-top: 0.125rem; +  margin-left: 1.25rem; +  text-decoration: none; +} + +.btn-toggle-nav a:hover, +.btn-toggle-nav a:focus { +  background-color: transparent; +  color: $link-color; +} + +.btn-toggle-nav a.active { +  color: $link-color; +} + +.doks-navbar .dropdown-menu, +.doks-subnavbar .dropdown-menu { +  font-size: 0.875rem; +} + +.doks-navbar .dropdown-item.current, +.doks-subnavbar .dropdown-item.current { +  font-weight: 600; +  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23292b2c' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e"); +  background-repeat: no-repeat; +  background-position: right 1rem top 0.6rem; +  background-size: 0.75rem 0.75rem; +} + +.btn-close { +  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-x'%3E%3Cline x1='18' y1='6' x2='6' y2='18'%3E%3C/line%3E%3Cline x1='6' y1='6' x2='18' y2='18'%3E%3C/line%3E%3C/svg%3E"); +  background-size: 1.5rem; +} + +.offcanvas-header .btn-close { +  margin-right: 0 !important; +} + +.dropdown-toggle::after { +  display: none; +} + +.dropdown-caret { +  margin-left: -0.1875rem; +  margin-right: -0.3125rem; +} + +.dropdown-menu.dropdown-menu-main { +  width: 100%; +} + +@include media-breakpoint-up(md) { +  .dropdown-menu.dropdown-menu-main { +    width: auto; +  } +} + +.dropdown-menu-main .dropdown-item { +  color: inherit; +  font-size: $font-size-base; +  font-weight: 400; +  text-decoration: none; +} + +.dropdown-menu-main .dropdown-item:hover { +  background-color: transparent; +  color: $primary; +} + +.dropdown-menu-main .dropdown-item.active { +  color: $primary; +  font-weight: 400; +  text-decoration: none; +  background-color: inherit; +} + +.dropdown-menu-main .dropdown-item.active:hover { +  background-color: transparent; +} diff --git a/docs/assets/scss/components/_code.scss b/docs/assets/scss/components/_code.scss new file mode 100644 index 000000000..84ad2bca5 --- /dev/null +++ b/docs/assets/scss/components/_code.scss @@ -0,0 +1,66 @@ +pre, +code, +kbd, +samp { +  font-family: $font-family-monospace; +  font-size: $font-size-sm; +  border-radius: $border-radius; +} + +code { +  background: $beige; +  color: $black; +  padding: 0.25rem 0.5rem; +} + +pre { +  margin: 2rem 0; +} + +pre code { +  display: block; +  overflow-x: auto; +  line-height: $line-height-base; +  padding: 1.25rem 1.5rem; +  tab-size: 4; +  scrollbar-width: thin; +  scrollbar-color: transparent transparent; +} + +.hljs { +  padding: 1.5rem !important; +} + +@include media-breakpoint-down(sm) { +  pre, +  code, +  kbd, +  samp { +    border-radius: 0; +  } + +  pre { +    margin: 2rem -1.5rem; +  } +} + +pre code::-webkit-scrollbar { +  height: 5px; +} + +pre code::-webkit-scrollbar-thumb { +  background: $gray-400; +} + +pre code:hover { +  scrollbar-width: thin; +  scrollbar-color: $gray-500 transparent; +} + +pre code::-webkit-scrollbar-thumb:hover { +  background: $gray-500; +} + +code.language-mermaid { +  background: none; +} diff --git a/docs/assets/scss/components/_comments.scss b/docs/assets/scss/components/_comments.scss new file mode 100644 index 000000000..18f610c94 --- /dev/null +++ b/docs/assets/scss/components/_comments.scss @@ -0,0 +1,30 @@ +.comment-list { +  @extend .list-unstyled; +} + +.comment-list ol { +  list-style: none; +} + +.comment-form p { +  @extend .form-group !optional; +} + +.comment-form input[type="text"], +.comment-form input[type="email"], +.comment-form input[type="url"], +.comment-form textarea { +  @extend .form-control; +} + +.comment-form input[type="submit"] { +  @extend .btn; +  @extend .btn-secondary; +} + +blockquote { +  margin-bottom: 1rem; +  font-size: 1.25rem; +  border-left: 3px solid $gray-300; +  padding-left: 1rem; +} diff --git a/docs/assets/scss/components/_details.scss b/docs/assets/scss/components/_details.scss new file mode 100644 index 000000000..fb719d366 --- /dev/null +++ b/docs/assets/scss/components/_details.scss @@ -0,0 +1,77 @@ +details { +  display: block; +  border: 1px solid $gray-200; +  border-radius: 0.25rem; +  padding: 0.5rem 1rem 0; +  margin: 0.5rem 0; +} + +/* +details summary { +  &::marker { +    content: ""; +  } +} +*/ + +summary { +  list-style: none; +  display: inline-block; +  width: calc(100% + 2rem); +  margin: -0.5rem -1rem 0; +  padding: 0.5rem 0.75rem; +} + +summary::-webkit-details-marker { +  display: none; +} + +summary:hover { +  background: $gray-100; +} + +details summary::before { +  display: inline-block; +  content: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='rgba%2829, 45, 53, 0.75%29' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M5 14l6-6-6-6'/%3e%3c/svg%3e"); +  transition: transform 0.35s ease; +  transform-origin: center center; +  margin-right: 0.375rem; +} + +details[open] > summary::before { +  transform: rotate(90deg); +} + +/* +details summary > * { +  display: inline-block; +} +*/ + +details[open] { +  padding: 0.5rem 1rem; +} + +details[open] > summary { +  border-bottom: 1px solid $gray-300; +  margin-bottom: 0.5rem; +} + +details h2, +details h3, +details h4 { +  margin: 1rem 0 0.5rem; +} + +details p:last-child { +  margin-bottom: 0; +} + +details ul, +details ol { +  margin-bottom: 0; +} + +details pre { +  margin: 0 0 1rem; +} diff --git a/docs/assets/scss/components/_forms.scss b/docs/assets/scss/components/_forms.scss new file mode 100644 index 000000000..9732838df --- /dev/null +++ b/docs/assets/scss/components/_forms.scss @@ -0,0 +1,19 @@ +/** Search form */ +.search-form { +  @extend .form-inline !optional; +} + +.search-form label { +  @extend .form-group; + +  font-weight: normal; +} + +.search-form .search-field { +  @extend .form-control; +} + +.search-form .search-submit { +  @extend .btn; +  @extend .btn-secondary; +} diff --git a/docs/assets/scss/components/_images.scss b/docs/assets/scss/components/_images.scss new file mode 100644 index 000000000..254eefa09 --- /dev/null +++ b/docs/assets/scss/components/_images.scss @@ -0,0 +1,48 @@ +figure { +  margin: 2rem 0; +} + +.figure-caption { +  margin: 0.25rem 0 0.75rem; +} + +figure.wide { +  margin: 2rem -1.5rem; +} + +figure.wide .figure-caption { +  margin: 0.25rem 1.5rem 0.75rem; +} + +@include media-breakpoint-up(md) { +  figure.wide { +    margin: 2rem -2.5rem; +  } + +  figure.wide .figure-caption { +    margin: 0.25rem 2.5rem 0.75rem; +  } +} + +@include media-breakpoint-up(lg) { +  figure.wide { +    margin: 2rem -5rem; +  } + +  figure.wide .figure-caption { +    margin: 0.25rem 5rem 0.75rem; +  } +} + +.blur-up { +  filter: blur(5px); +} + +.blur-up.lazyloaded { +  filter: unset; +} + +.img-simple { +  margin-top: 0.375rem; +  margin-bottom: 1.25rem; +} diff --git a/docs/assets/scss/components/_mermaid.scss b/docs/assets/scss/components/_mermaid.scss new file mode 100644 index 000000000..3ff24888a --- /dev/null +++ b/docs/assets/scss/components/_mermaid.scss @@ -0,0 +1,8 @@ +.mermaid { +  margin: 1.5rem 0; +  padding: 1.5rem; +} + +.mermaid svg { +  height: auto; +} diff --git a/docs/assets/scss/components/_search.scss b/docs/assets/scss/components/_search.scss new file mode 100644 index 000000000..45ec2afff --- /dev/null +++ b/docs/assets/scss/components/_search.scss @@ -0,0 +1,81 @@ +.navbar-form { +  position: relative; +} + +#suggestions { +  position: absolute; +  left: 0; +  margin-top: 0.5rem; +  width: calc(100vw - 3rem); +  z-index: $zindex-dropdown; +} + +#suggestions a, +.suggestion__no-results { +  padding: 0.75rem; +  margin: 0 0.5rem; +} + +#suggestions a { +  display: block; +  text-decoration: none; +} + +#suggestions a:focus { +  background: $gray-100; +  outline: 0; +} + +#suggestions div:not(:first-child) { +  border-top: 1px dashed $gray-200; +} + +#suggestions div:first-child { +  margin-top: 0.5rem; +} + +#suggestions div:last-child { +  margin-bottom: 0.5rem; +} + +#suggestions a:hover { +  background: $gray-100; +} + +#suggestions span { +  display: flex; +  font-size: $font-size-base; +} + +.suggestion__title { +  font-weight: $headings-font-weight; +  color: $black; +} + +.suggestion__description, +.suggestion__no-results { +  color: $gray-700; +} + +@include media-breakpoint-up(sm) { +  #suggestions { +    width: 31.125rem; +  } + +  #suggestions a { +    display: flex; +  } + +  .suggestion__title { +    width: 9rem; +    padding-right: 1rem; +    border-right: 1px solid $gray-200; +    display: inline-block; +    text-align: right; +  } + +  .suggestion__description { +    width: 19rem; +    padding-left: 1rem; +  } +} diff --git a/docs/assets/scss/components/_syntax.scss b/docs/assets/scss/components/_syntax.scss new file mode 100644 index 000000000..2be315d95 --- /dev/null +++ b/docs/assets/scss/components/_syntax.scss @@ -0,0 +1,62 @@ +/* + +Based on Ascetic by (c) Ivan Sagalaev <Maniac@SoftwareManiacs.Org> + +*/ + +.hljs { +  display: block; +  overflow-x: auto; +  padding: 1.25rem 1.5rem; +  background: $beige; +  color: $body-color; +} + +.hljs-string, +.hljs-variable, +.hljs-template-variable, +.hljs-symbol, +.hljs-bullet, +.hljs-section, +.hljs-addition, +.hljs-attribute, +.hljs-link { +  color: $pink-500; +} + +.hljs-comment, +.hljs-quote, +.hljs-meta, +.hljs-deletion { +  color: #888; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-section, +.hljs-name, +.hljs-type, +.hljs-strong { +  font-weight: bold; +} + +.hljs-emphasis { +  font-style: italic; +} + +[data-dark-mode] body .hljs { +  background: $body-overlay-dark; +  color: $body-color-dark; +} + +[data-dark-mode] body .hljs-string, +[data-dark-mode] body .hljs-variable, +[data-dark-mode] body .hljs-template-variable, +[data-dark-mode] body .hljs-symbol, +[data-dark-mode] body .hljs-bullet, +[data-dark-mode] body .hljs-section, +[data-dark-mode] body .hljs-addition, +[data-dark-mode] body .hljs-attribute, +[data-dark-mode] body .hljs-link { +  color: $blue-300; +} diff --git a/docs/assets/scss/components/_tables.scss b/docs/assets/scss/components/_tables.scss new file mode 100644 index 000000000..b1f8c2e79 --- /dev/null +++ b/docs/assets/scss/components/_tables.scss @@ -0,0 +1,5 @@ +table { +  @extend .table; + +  margin: 3rem 0; +} diff --git a/docs/assets/scss/custom.scss b/docs/assets/scss/custom.scss new file mode 100644 index 000000000..dda718c20 --- /dev/null +++ b/docs/assets/scss/custom.scss @@ -0,0 +1,65 @@ +.text-orange { +  --bs-text-opacity: 1; + +  color: $orange; +} + +.icon-support-full { +  @extend .bi; +  @extend .bi-check-circle-fill; +  @extend .text-success; +} + +[data-dark-mode] .icon-support-full { +  @extend .bi; +  @extend .bi-check-circle; +  @extend .text-success; +} + +.icon-support-unknown { +  @extend .bi; +  @extend .bi-dash-circle-fill; +  @extend .text-warning; +} + +[data-dark-mode] .icon-support-unknown { +  @extend .bi; +  @extend .bi-dash-circle; +  @extend .text-warning; +} + +.icon-support-partial { +  @extend .bi; +  @extend .bi-exclamation-circle-fill; +  @extend .text-orange; +} + +[data-dark-mode] .icon-support-partial { +  @extend .bi; +  @extend .bi-exclamation-circle; +  @extend .text-orange; +} + +.icon-support-none { +  @extend .bi; +  @extend .bi-x-circle-fill; +  @extend .text-danger; +} + +[data-dark-mode] .icon-support-none { +  @extend .bi; +  @extend .bi-x-circle; +  @extend .text-danger; +} + +body code span.line.hl { +  background: $orange; +  display: block; +  width: 100%; +} + +[data-dark-mode] body code span.line.hl { +  background: $orange; +  display: block; +  width: 100%; +} diff --git a/docs/assets/scss/layouts/_footer.scss b/docs/assets/scss/layouts/_footer.scss new file mode 100644 index 000000000..7d2181144 --- /dev/null +++ b/docs/assets/scss/layouts/_footer.scss @@ -0,0 +1,20 @@ +.footer { +  border-top: 1px solid $gray-200; +  padding-top: 1.125rem; +  padding-bottom: 1.125rem; +} + +.footer ul { +  margin-bottom: 0; +} + +.footer li { +  font-size: $font-size-sm; +  margin-bottom: 0; +} + +@include media-breakpoint-up(md) { +  .footer li { +    font-size: $font-size-base; +  } +} diff --git a/docs/assets/scss/layouts/_header.scss b/docs/assets/scss/layouts/_header.scss new file mode 100644 index 000000000..cb85c32c1 --- /dev/null +++ b/docs/assets/scss/layouts/_header.scss @@ -0,0 +1,445 @@ +.banner .nav li { +  @extend .nav-item; +} + +.banner .nav a { +  @extend .nav-link; +} + +.navbar-text { +  margin-left: 1rem; +} + +.navbar-brand { +  font-weight: $headings-font-weight; +} + +/* +.navbar-light .navbar-brand, +.navbar-light .navbar-brand:hover, +.navbar-light .navbar-brand:active { +  color: $body-color; +} + +.navbar-light .navbar-nav .active .nav-link { +  color: $primary; +} +*/ + +.navbar { +  z-index: 1000; +  background-color: rgba(255, 255, 255, 0.95); +  border-bottom: 1px solid $gray-200; + +  /* +  margin-top: 4px; +  */ +} + +@include media-breakpoint-up(lg) { +  .navbar { +    z-index: 1025; +  } +} + +@include media-breakpoint-up(md) { +  .navbar-brand { +    font-size: $font-size-xl; +  } + +  .navbar-text { +    margin-left: 1.25rem; +  } +} + +.navbar-nav { +  flex-direction: row; +} + +.nav-item { +  margin-left: 0; +} + +@include media-breakpoint-up(md) { +  .nav-item { +    margin-left: 0.5rem; +  } +} + +/* +@include media-breakpoint-down(sm) { +  .nav-item:first-child { +    margin-left: 0; +  } +} +*/ + +@include media-breakpoint-down(md) { +  .navbar .container { +    padding-left: 1.5rem; +    padding-right: 1.5rem; +  } +} + +.break { +  flex-basis: 100%; +  height: 0; +} + +button#doks-languages { +  margin-right: -0.5625rem; +  margin-left: 0.75rem; +} + +button#doks-versions { +  margin-right: -0.5625rem; +  margin-left: 0; +} + +.offcanvas .nav-link { +  color: $body-color; +} + +.doks-subnavbar { +  background-color: rgba(255, 255, 255, 0.95); +  border-bottom: 1px solid $gray-200; +} + +.doks-subnavbar .nav-link { +  padding: 0.5rem 1.5rem 0.5rem 0; +} + +.doks-subnavbar .nav-link:first-child { +  padding: 0.5rem 1.5rem 0.5rem 0; +} + +.offcanvas .nav-link:hover, +.offcanvas .nav-link:focus { +  color: $link-color; +} + +.offcanvas .nav-link.active { +  color: $link-color; +} + +/* +.navbar { +  background-color: rgba(255, 255, 255, 0.95); +  border-bottom: 1px solid $gray-200; +  margin-top: 4px; +} +*/ + +.header-bar { +  border-top: 4px solid; +  border-image-source: linear-gradient(90deg, $primary, #8ed6fb 50%, #d32e9d); +  border-image-slice: 1; +} + +.offcanvas .header-bar { +  margin-bottom: -4px; +} + +.home .navbar { +  border-bottom: 0; +} + +/* +.navbar-form { +  position: relative; +  margin-top: 0.25rem; +} +*/ + +@include media-breakpoint-up(md) { +  .navbar-brand { +    margin-right: 0.75rem !important; +  } + +  .main-nav .nav-item:first-child .nav-link, +  .social-nav .nav-item:first-child .nav-link { +    padding-left: 0; +  } + +  .main-nav .nav-item:last-child .nav-link, +  .social-nav .nav-item:last-child .nav-link { +    padding-right: 0; +  } + +  .doks-search { +    max-width: 20rem; +    margin-top: 0.125rem; +    margin-bottom: 0.125rem; +  } + +  /* +  .navbar-form { +    margin-top: 0; +    margin-left: 6rem; +    margin-right: 1.5rem; +  } +  */ +} + +.form-control.is-search { +  padding-right: 4rem; +  border: 1px solid transparent; +  background: $gray-100; +} + +.form-control.is-search:focus { +  border: 1px solid $primary; +} + +.doks-search::after { +  position: absolute; +  top: 0.4625rem; +  right: 0.5375rem; +  display: flex; +  align-items: center; +  justify-content: center; +  height: 1.5rem; +  padding-right: 0.3125rem; +  padding-left: 0.3125rem; +  font-size: $font-size-base * 0.75; +  color: $gray-700; +  content: "Ctrl + /"; +  border: 1px solid $gray-300; +  border-radius: 0.25rem; +} + +/* +@include media-breakpoint-up(lg) { +  .navbar-form { +    margin-left: 15rem; +  } +} + +@include media-breakpoint-up(xl) { +  .navbar-form { +    margin-left: 30rem; +  } +} +*/ + +/* +.form-control.is-search { +*/ + +/* +  padding-right: calc(1.5em + 0.75rem); +  */ + +/* +  padding-right: 2.5rem; +  background: $gray-100; +  border: 0; +  */ + +/* +  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='%236c757d' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-search'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E"); +  background-repeat: no-repeat; +  background-position: right calc(0.375em + 0.1875rem) center; +  background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); +  */ + +/* +} +*/ + +/* +.navbar-form::after { +  position: absolute; +  top: 0.4625rem; +  right: 0.5375rem; +  display: flex; +  align-items: center; +  justify-content: center; +  height: 1.5rem; +  padding-right: 0.4375rem; +  padding-left: 0.4375rem; +  font-size: $font-size-base * 0.75; +  color: $gray-700; +  content: "/"; +  border: 1px solid $gray-300; +  border-radius: 0.25rem; +} +*/ + +/*! purgecss start ignore */ +.algolia-autocomplete { +  display: flex !important; +} + +.algolia-autocomplete .ds-dropdown-menu { +  box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important; +} + +@include media-breakpoint-down(sm) { +  .algolia-autocomplete .ds-dropdown-menu { +    max-width: 512px !important; +    min-width: 312px !important; +    width: auto !important; +  } + +  .algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--subcategory-column { +    font-weight: normal; +  } + +  .algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--subcategory-column::after { +    content: "/"; +    margin-right: 0.25rem; +  } +} + +.algolia-autocomplete .algolia-docsearch-suggestion--category-header { +  color: $black; +} + +.algolia-autocomplete .algolia-docsearch-suggestion--title { +  margin-bottom: 0; +} + +.algolia-autocomplete .algolia-docsearch-suggestion--highlight { +  padding: 0 0.05em; +} + +.algolia-autocomplete .algolia-docsearch-footer { +  margin-top: 1rem; +  margin-right: 0.5rem; +  margin-bottom: 0.5rem; +} + +/*! purgecss end ignore */ + +/* + * Source: https://medium.com/creative-technology-concepts-code/responsive-mobile-dropdown-navigation-using-css-only-7218e4498a99 +*/ + +/* Style the menu icon for the dropdown */ + +.navbar .menu-icon { +  cursor: pointer; + +  /* display: inline-block; */ + +  /* float: right; */ +  padding: 1.125rem 0.625rem; +  margin: 0 0 0 -0.625rem; + +  /* position: relative; */ +  user-select: none; +} + +.navbar .menu-icon .navicon { +  background: $navbar-light-color; +  display: block; +  height: 2px; +  position: relative; +  transition: background 0.2s ease-out; +  width: 18px; +} + +.navbar .menu-icon .navicon::before, +.navbar .menu-icon .navicon::after { +  background: $navbar-light-color; +  content: ""; +  display: block; +  height: 100%; +  position: absolute; +  transition: all 0.2s ease-out; +  width: 100%; +} + +.navbar .menu-icon .navicon::before { +  top: 5px; +} + +.navbar .menu-icon .navicon::after { +  top: -5px; +} + +/* Add the icon and menu animations when the checkbox is clicked */ + +.navbar .menu-btn { +  display: none; +} + +.navbar .menu-btn:checked ~ .navbar-collapse { +  display: block; +  max-height: 100vh; +} + +.navbar .menu-btn:checked ~ .menu-icon .navicon { +  background: transparent; +} + +.navbar .menu-btn:checked ~ .menu-icon .navicon::before { +  transform: rotate(-45deg); +} + +.navbar .menu-btn:checked ~ .menu-icon .navicon::after { +  transform: rotate(45deg); +} + +.navbar .menu-btn:checked ~ .menu-icon:not(.steps) .navicon::before, +.navbar .menu-btn:checked ~ .menu-icon:not(.steps) .navicon::after { +  top: 0; +} + +.btn-menu { +  margin-left: 1rem; +} + +.btn-menu, +.doks-sidebar-toggle { +  padding-right: 0.25rem; +  padding-left: 0.25rem; +  margin-right: -0.5rem; +} + +.btn-menu:hover, +.btn-doks-light:hover, +.doks-sidebar-toggle:hover { +  background: $pink-100; +} + +.btn-menu:focus, +.doks-sidebar-toggle:focus, +.doks-mode-toggle:focus { +  outline: 0; +} + +.doks-sidebar-toggle .doks-collapse { +  display: none; +} + +.doks-sidebar-toggle:not(.collapsed) .doks-expand { +  display: none; +} + +.doks-sidebar-toggle:not(.collapsed) .doks-collapse { +  display: inline-block; +} + +.navbar-light .navbar-brand, +.navbar-light .navbar-brand:hover, +.navbar-light .navbar-brand:active { +  color: $body-color; +} + +.navbar-light .navbar-nav .active .nav-link { +  color: $primary; +} + +.dropdown-divider { +  border-top: 1px dashed $gray-200; +} + +.dropdown-item:hover { +  background: $gray-100; +} + +.dropdown-item:active { +  color: inherit; +} diff --git a/docs/assets/scss/layouts/_pages.scss b/docs/assets/scss/layouts/_pages.scss new file mode 100644 index 000000000..405ede950 --- /dev/null +++ b/docs/assets/scss/layouts/_pages.scss @@ -0,0 +1,64 @@ +.docs-content > h2[id]::before, +.docs-content > h3[id]::before, +.docs-content > h4[id]::before { +  display: block; +  height: 6rem; +  margin-top: -6rem; +  content: ""; +} + +.anchor { +  visibility: hidden; +} + +h1:hover a, +h2:hover a, +h3:hover a, +h4:hover a { +  visibility: visible; +  text-decoration: none; +} + +.card-list { +  margin-top: 2.25rem; +} + +.page-footer-meta { +  margin-top: 3rem; +} + +.edit-page, +.last-modified { +  font-size: $font-size-sm; +  margin-top: 0.25rem; +  margin-bottom: 0.25rem; +} + +@include media-breakpoint-up(md) { +  .edit-page, +  .last-modified { +    font-size: $font-size-base; +    margin-top: 0.75rem; +    margin-bottom: 0.25rem; +  } +} + +.edit-page svg, +.last-modified svg { +  margin-right: 0.25rem; +  margin-bottom: 0.25rem; +} + +p.meta { +  margin-top: 0.5rem; +  font-size: $font-size-base; +} + +.breadcrumb { +  margin-top: 2.25rem; +  font-size: $font-size-base; +} + +.page-link:hover { +  text-decoration: none; +} diff --git a/docs/assets/scss/layouts/_posts.scss b/docs/assets/scss/layouts/_posts.scss new file mode 100644 index 000000000..da2766052 --- /dev/null +++ b/docs/assets/scss/layouts/_posts.scss @@ -0,0 +1,28 @@ +.home .card, +.contributors.list .card, +.blog.list .card { +  margin-top: 2rem; +  margin-bottom: 2rem; +  transition: transform 0.3s; +} + +.home .card:hover, +.contributors.list .card:hover, +.blog.list .card:hover { +  transform: scale(1.025); +} + +.home .card-body, +.contributors.list .card-body, +.blog.list .card-body { +  padding: 0 2rem 1rem; +} + +.blog-header { +  text-align: center; +  margin-bottom: 2rem; +} + +.blog-footer { +  text-align: center; +} diff --git a/docs/assets/scss/layouts/_sidebar.scss b/docs/assets/scss/layouts/_sidebar.scss new file mode 100644 index 000000000..88959bfe9 --- /dev/null +++ b/docs/assets/scss/layouts/_sidebar.scss @@ -0,0 +1,116 @@ +.docs-links, +.docs-toc { +  scrollbar-width: thin; +  scrollbar-color: $white $white; +} + +.docs-links::-webkit-scrollbar, +.docs-toc::-webkit-scrollbar { +  width: 5px; +} + +.docs-links::-webkit-scrollbar-track, +.docs-toc::-webkit-scrollbar-track { +  background: $white; +} + +.docs-links::-webkit-scrollbar-thumb, +.docs-toc::-webkit-scrollbar-thumb { +  background: $white; +} + +.docs-links:hover, +.docs-toc:hover { +  scrollbar-width: thin; +  scrollbar-color: $gray-200 $white; +} + +.docs-links:hover::-webkit-scrollbar-thumb, +.docs-toc:hover::-webkit-scrollbar-thumb { +  background: $gray-200; +} + +.docs-links::-webkit-scrollbar-thumb:hover, +.docs-toc::-webkit-scrollbar-thumb:hover { +  background: $gray-200; +} + +.docs-links h3, +.page-links h3 { +  text-transform: uppercase; +  font-size: $font-size-base; +  margin: 1.25rem 0 0.5rem; +  padding: 1.5rem 0 0; +} + +@include media-breakpoint-up(lg) { +  .docs-links h3, +  .page-links h3 { +    margin: 1.125rem 1.5rem 0.75rem 0; +    padding: 1.375rem 0 0; +  } +} + +.docs-links h3:not(:first-child) { +  border-top: 1px solid $gray-200; +} + +a.docs-link { +  color: $body-color; +  display: block; +  padding: 0.125rem 0; +  font-size: $font-size-base; +} + +.page-links li { +  margin-top: 0.375rem; +  padding-top: 0.375rem; +} + +.page-links li ul li { +  border-top: none; +  padding-left: 1rem; +  margin-top: 0.125rem; +  padding-top: 0.125rem; +} + +.page-links li:not(:first-child) { +  border-top: 1px dashed $gray-200; +} + +.page-links a { +  color: $body-color; +  display: block; +  padding: 0.125rem 0; +  font-size: $font-size-base * 0.9375; +} + +.docs-link:hover, +.docs-link.active, +.page-links a:hover { +  text-decoration: none; +  color: $link-color; +} + +.nav-link.active, +.dropdown-menu-main .dropdown-item.active, +.docs-link.active { +  font-weight: 500; +} + +.docs-links h3.sidebar-link, +.page-links h3.sidebar-link { +  text-transform: none; +  font-size: $font-size-md; +  font-weight: normal; +} + +.docs-links h3.sidebar-link a, +.page-links h3.sidebar-link a { +  color: $body-color; +} + +.docs-links h3.sidebar-link a:hover, +.page-links h3.sidebar-link a:hover { +  text-decoration: underline; +} diff --git a/docs/assets/scss/vendor/.gitkeep b/docs/assets/scss/vendor/.gitkeep new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/docs/assets/scss/vendor/.gitkeep diff --git a/docs/babel.config.js b/docs/babel.config.js new file mode 100644 index 000000000..ce9c9de02 --- /dev/null +++ b/docs/babel.config.js @@ -0,0 +1,17 @@ +module.exports = { +  presets: [ +    [ +      '@babel/preset-env', +      { +        targets: { +          browsers: [ +            // Best practice: https://github.com/babel/babel/issues/7789 +            '>=1%', +            'not ie 11', +            'not op_mini all' +          ] +        } +      } +    ] +  ] +};
\ No newline at end of file diff --git a/docs/community/additional-resources.md b/docs/community/additional-resources.md deleted file mode 100644 index 6cccc3eef..000000000 --- a/docs/community/additional-resources.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -layout: default -title: Miscellaneous Additional Resources -parent: Community -nav_order: 3 ---- - -In this document you will find miscellaneous resources that could give you more -information on Authelia or help you set it up. - -# Articles - -[Setting Up Authelia With SWAG](https://blog.linuxserver.io/2020/08/26/setting-up-authelia/) -[Authelia Tutorial – Protect your Docker Traefik stack with Private MFA](https://www.smarthomebeginner.com/docker-authelia-tutorial/) - -# Youtube Videos - -[Authelia: Install Guide on Unraid + NGINX (Deep Dive)](https://www.youtube.com/watch?v=kw_pohbKE3Y)
\ No newline at end of file diff --git a/docs/community/django-integration.md b/docs/community/django-integration.md deleted file mode 100644 index 0297c0746..000000000 --- a/docs/community/django-integration.md +++ /dev/null @@ -1,212 +0,0 @@ ---- -layout: default -title: Integrate Authelia with Django -parent: Community -nav_order: 6 ---- - -# Integrate Authelia with Django - -Django, the Python web framework, can be configured to delegate authentication to external services  -using HTTP request headers. This is well documented on [Django documentation](https://docs.djangoproject.com/en/3.2/howto/auth-remote-user/) - -Therefore, it is possible to integrate Django with Authelia following the documentation about  -[Proxy integration](https://www.authelia.com/docs/deployment/supported-proxies/#how-can-the-backend-be-aware-of-the-authenticated-users)  -and adding a few lines of code on your Django application. - - -## Basic integration - -Django uses `REMOTE_USER` header by default. But WSGI servers transform the headers received from  -proxy servers adding `HTTP_` as prefix. So we need to add a custom middleware in order to use `HTTP_REMOTE_USER`. - -This basic configuration enables authentication using Authelia. If the user does not exists on Django database, -it will be automatically created. - - -### Configuration - -```python -# file: settings.py - -MIDDLEWARE = [ -    '...', -    'django.contrib.auth.middleware.AuthenticationMiddleware', -    'your_app.auth.middleware.RemoteUserMiddleware', -    # or 'your_app.auth.middleware.PersistentRemoteUserMiddleware', -    '...', -] - -AUTHENTICATION_BACKENDS = [ -    'django.contrib.auth.backends.RemoteUserBackend', -] - -# Logout from authelia after logout on the Django application -LOGOUT_REDIRECT_URL = 'https://auth.your_domain.com/logout' - -``` - -### New authentication middleware - -```python -# new file: your_app/auth/middleware.py -from django.contrib.auth.middleware import RemoteUserMiddleware, PersistentRemoteUserMiddleware - - -class HttpRemoteUserMiddleware(RemoteUserMiddleware): -    header = 'HTTP_REMOTE_USER' - -    # uncomment the line below to disable authentication to users that not exists on Django database -    # create_unknown_user = False  - - -class PersistentHttpRemoteUserMiddleware(PersistentRemoteUserMiddleware): -    """ -    The RemoteUserMiddleware authentication middleware assumes that the HTTP request header  -    REMOTE_USER is present with all authenticated requests. - -    With PersistentRemoteUserMiddleware, it is possible to receive this header only on a few  -    pages (as login page) and maintain the authenticated session until explicit  -    logout by the user. -    """ -    header = 'HTTP_REMOTE_USER'  - -``` - -**Security Warning:** -The proxy server **must** set `Remote-User` header **every time** it hits the Django application. If you only -protect the login URL with Authelia and use the Persistent class, you have to set this header to `''`  -on the other locations. - - -## Advanced integration - -While the basic integration only uses the HTTP header `Remote-User` set by Authelia, this advanced integration -uses also the HTTP headers `Remote-Name`, `Remote-Email` and `Remote-Groups`. - -In this example, we create a new authentication backend on Django that will synchronize user data with Authelia  -backend, storing the name, the email and the groups of the user on the Django database. - -### Configuration - -```python -# file: settings.py - -MIDDLEWARE = [ -    '...', -    'django.contrib.auth.middleware.AuthenticationMiddleware', -    'your_app.auth.middleware.RemoteUserMiddleware', -    # or 'your_app.auth.middleware.PersistentRemoteUserMiddleware', -    '...', -] - -AUTHENTICATION_BACKENDS = [ -    'your_app.auth.backends.RemoteExtendedUserBackend', -] - -# Logout from authelia after logout on the Django application -LOGOUT_REDIRECT_URL = 'https://auth.your_domain.com/logout' - -``` - -### New authentication backend -```python -# new file: your_app/auth/backends.py -from django.conf import settings -from django.contrib.auth.models import Group -from django.contrib.auth.backends import RemoteUserBackend - - -class RemoteExtendedUserBackend(RemoteUserBackend): -    """ -    This backend can be used in conjunction with the ``RemoteUserMiddleware`` -    to handle authentication outside Django and update local user with external information -    (name, email and groups). - -    Extends RemoteUserBackend (it creates the Django user if it does not exist, -    as explained here: https://github.com/django/django/blob/main/django/contrib/auth/backends.py#L167), -    updating the user with the information received from the remote headers. - -    Django user is only added to groups that already exist on the database (no groups are created). -    A settings variable can be used to exclude some groups when updating the user. -    """ - -    excluded_groups = set() -    if hasattr(settings, 'REMOTE_AUTH_BACKEND_EXCLUDED_GROUPS'): -        excluded_groups = set(settings.REMOTE_AUTH_BACKEND_EXCLUDED_GROUPS) - -    # Warning: possible security breach if reverse proxy does not set -    # these variables EVERY TIME it hits this Django application (and REMOTE_USER variable). -    # See https://docs.djangoproject.com/en/4.0/howto/auth-remote-user/#configuration -    header_name = 'HTTP_REMOTE_NAME' -    header_groups = 'HTTP_REMOTE_GROUPS' -    header_email = 'HTTP_REMOTE_EMAIL' - -    def authenticate(self, request, remote_user): -        user = super().authenticate(request, remote_user) - -        # original authenticate calls configure_user only -        # when user is created. We need to call this method every time -        # the user is authenticated in order to update its data. -        if user: -            self.configure_user(request, user) -        return user - -    def configure_user(self, request, user): -        """ -        Complete the user from extra request.META information. -        """ -        if self.header_name in request.META: -            user.last_name = request.META[self.header_name] - -        if self.header_email in request.META: -            user.email = request.META[self.header_email] - -        if self.header_groups in request.META: -            self.update_groups(user, request.META[self.header_groups]) - -        if self.user_has_to_be_staff(user): -            user.is_staff = True - -        user.save() -        return user - -    def user_has_to_be_staff(self, user): -        return True - -    def update_groups(self, user, remote_groups): -        """ -        Synchronizes groups the user belongs to with remote information. - -        Groups (existing django groups or remote groups) on excluded_groups are completely ignored. -        No group will be created on the django database. - -        Disclaimer: this method is strongly inspired by the LDAPBackend from django-auth-ldap. -        """ -        current_group_names = frozenset( -            user.groups.values_list("name", flat=True).iterator() -        ) -        preserved_group_names = current_group_names.intersection(self.excluded_groups) -        current_group_names = current_group_names - self.excluded_groups - -        target_group_names = frozenset( -            [x for x in map(self.clean_groupname, remote_groups.split(',')) if x is not None] -        ) -        target_group_names = target_group_names - self.excluded_groups - -        if target_group_names != current_group_names: -            target_group_names = target_group_names.union(preserved_group_names) -            existing_groups = list( -                Group.objects.filter(name__in=target_group_names).iterator() -            ) -            user.groups.set(existing_groups) -        return - -    def clean_groupname(self, groupname): -        """ -        Perform any cleaning on the "groupname" prior to using it. -        Return the cleaned groupname. -        """ -        return groupname - -``` diff --git a/docs/community/example-of-authelia-lite-on-docker-swarm.md b/docs/community/example-of-authelia-lite-on-docker-swarm.md deleted file mode 100644 index 52cf543c2..000000000 --- a/docs/community/example-of-authelia-lite-on-docker-swarm.md +++ /dev/null @@ -1,181 +0,0 @@ ---- -layout: default -title: Example of authelia lite on docker swarm -parent: Community -nav_order: 4 ---- - -The overlay network for docker swarm can be initialized with: - -``` -$ docker swarm init -$ docker swarm init && docker network create --driver=overlay traefik-public -$ mkdir ./redis ./letsencrypt -``` - -The structure of the folder should be like this: - -``` -├── authelia/ -│   ├── configuration.yml -│   └── users_database.yml -├── redis/ -├── letsencrypt/ -│   └── acme.json -└── traefik-compose.yml -``` - -The following configuration allows you to deploy authelia to docker swarm with traefik 2.x. Please replace the **example.com** and **your@email.com** with your domain and email respectively.  Then save it as **traefik-compose.yml**. - -``` -version: '3.3' - -services: -  authelia: -    image: authelia/authelia:4 -    volumes: -      - ./authelia:/config -    networks: -      - traefik-public -    deploy: -      labels: -        - 'traefik.enable=true' -        - 'traefik.http.routers.authelia.rule=Host(`auth.example.com`)' -        - 'traefik.http.routers.authelia.entrypoints=web' -        - "traefik.http.services.authelia.loadbalancer.server.port=9091" -        # TLS -        - "traefik.http.routers.authelias.rule=Host(`auth.example.com`)" -        - "traefik.http.routers.authelias.entrypoints=websecure" -        - "traefik.http.routers.authelias.tls.certresolver=letsencrypt" -        # Redirect -        - "traefik.http.routers.authelia.middlewares=https_redirect" -        - "traefik.http.middlewares.https_redirect.redirectscheme.scheme=https" -        # Authelia -        - 'traefik.http.middlewares.authelia.forwardauth.address=http://authelia:9091/api/verify?rd=https://auth.example.com' -        - 'traefik.http.middlewares.authelia.forwardauth.trustForwardHeader=true' -        - 'traefik.http.middlewares.authelia.forwardauth.authResponseHeaders=Remote-User, Remote-Groups' -        - "traefik.http.routers.authelia.service=authelia" - -  redis: -    image: redis:6-alpine -    volumes: -      - ./redis:/data -    networks: -      - traefik-public - -  traefik: -    # The official v2.0 Traefik docker image -    image: traefik:v2.2 -    deploy: -      labels: -        - 'traefik.enable=true' -        - 'traefik.http.routers.api.rule=Host(`traefik.example.com`)' -        - 'traefik.http.routers.api.entrypoints=web' -        - 'traefik.http.routers.api.service=api@internal' -        - 'traefik.http.services.traefik.loadbalancer.server.port=80' -        # TLS -        - "traefik.http.routers.apis.rule=Host(`traefik.example.com`)" -        - "traefik.http.routers.apis.entrypoints=websecure" -        - "traefik.http.routers.apis.tls.certresolver=letsencrypt" -        # Redirect -        - "traefik.http.routers.api.middlewares=https_redirect" -        - "traefik.http.middlewares.https_redirect.redirectscheme.scheme=https" -        # Authelia -        - 'traefik.http.routers.apis.service=api@internal' -        - 'traefik.http.routers.apis.middlewares=authelia@docker' -      placement: -        constraints: -          - node.role == manager -    command:  -      - "--api" -      - "--providers.docker=true" -      - "--providers.docker.swarmMode=true" -      - "--providers.docker.exposedbydefault=false" -      - "--entrypoints.web.address=:80" -      - "--entryPoints.websecure.address=:443" -      - "--certificatesresolvers.letsencrypt.acme.httpchallenge=true" -      - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web" -      - "--certificatesresolvers.letsencrypt.acme.email=your@email.com" -      - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json" -    ports: -      # Listen on port 80, default for HTTP, necessary to redirect to HTTPS -      - target: 80 -        published: 80 -        mode: host -      # Listen on port 443, default for HTTPS -      - target: 443 -        published: 443 -        mode: host -    volumes: -      # So that Traefik can listen to the Docker events -      - /var/run/docker.sock:/var/run/docker.sock -      - ./letsencrypt:/letsencrypt -    networks: -      - traefik-public - -  secure: -    image: containous/whoami -    networks: -      - traefik-public -    deploy: -      labels: -        - 'traefik.enable=true' -        - 'traefik.http.routers.secure.rule=Host(`secure.example.com`)' -        - 'traefik.http.routers.secure.entrypoints=web' -        - 'traefik.http.services.secure.loadbalancer.server.port=80' -        # TLS -        - "traefik.http.routers.secures.rule=Host(`secure.example.com`)" -        - "traefik.http.routers.secures.entrypoints=websecure" -        - "traefik.http.routers.secures.tls.certresolver=letsencrypt" -        # Redirect -        - "traefik.http.routers.secure.middlewares=https_redirect" -        - "traefik.http.middlewares.https_redirect.redirectscheme.scheme=https" -        # Authelia -        - 'traefik.http.routers.secures.middlewares=authelia@docker' - -  public: -    image: containous/whoami -    networks: -      - traefik-public -    deploy: -      labels: -        - 'traefik.enable=true' -        - 'traefik.http.routers.public.rule=Host(`public.example.com`)' -        - 'traefik.http.routers.public.entrypoints=web' -        - 'traefik.http.services.public.loadbalancer.server.port=80' -        # TLS -        - "traefik.http.routers.publics.rule=Host(`public.example.com`)" -        - "traefik.http.routers.publics.entrypoints=websecure" -        - "traefik.http.routers.publics.tls.certresolver=letsencrypt" -        # Redirect -        - "traefik.http.routers.public.middlewares=https_redirect" -        - "traefik.http.middlewares.https_redirect.redirectscheme.scheme=https" -        # Authelia -        - 'traefik.http.routers.publics.middlewares=authelia@docker' - -networks: -  traefik-public: -    external: true -``` - -Finally, the stack is ready to be deployed. - -``` -$ docker stack deploy -c traefik-compose.yml traefik -``` - -Full configuration files can be found here https://github.com/wuhanstudio/authelia-docker-swarm - -``` -$ docker swarm init && docker network create --driver=overlay traefik-public - -$ git clone https://github.com/wuhanstudio/authelia-docker-swarm && cd authelia-docker-swarm - -# Replace wuhanstudio.cc with your domain -$ find . -type f -name "*.yml" -exec sed -i'' -e 's/example.com/wuhanstudio.cc/g' {} + - -# Replace wuhanstudio@qq.com with your email -$ find . -type f -name "*.yml" -exec sed -i'' -e 's/your@email.com/wuhanstudio@qq.com/g' {} + - -$ docker stack deploy -c traefik-compose.yml traefik -``` diff --git a/docs/community/index.md b/docs/community/index.md deleted file mode 100644 index 923ec4597..000000000 --- a/docs/community/index.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -layout: default -title: Community -nav_order: 11 -has_children: true ---- - -# Community documentation - -This section is meant to advertise and organize documentation produced -by the community. This documentation is considered non-official and we -will not guarantee that this documentation is up-to-date. If you think -some of it should be considered official, please file an issue on GitHub. diff --git a/docs/community/oidc-integrations.md b/docs/community/oidc-integrations.md deleted file mode 100644 index d1cc2410a..000000000 --- a/docs/community/oidc-integrations.md +++ /dev/null @@ -1,51 +0,0 @@ ---- -layout: default -title: Community-Tested OIDC Integrations -parent: Community -nav_order: 5 -has_children: true -has_toc: false ---- - -# OIDC Integrations - -**Note** This is community-based content for which the core-maintainers cannot guarantee correctness. The parameters may change over time. If a parameter does not work as documented, please submit a PR to update the list. - -## Currently Tested Applications - -|   Application    |        Minimal Version         |                                                    Notes                                                      | -|:----------------:|:------------------------------:|:-------------------------------------------------------------------------------------------------------------:| -| Bookstack        | `21.10`                        |                                                                                                               | -| Gitea            | `1.14.6`                       |                                                                                                               | -| GitLab           | `13.0.0`                       |                                                                                                               | -| Grafana          | `8.0.5`                        |                                                                                                               | -| Harbor           | `1.10`                         | It works on >v2.1 also, but not sure if there is OIDC support on v2.0                                         | -| Hashicorp Vault  | `1.8.1`                        |                                                                                                               | -| Miniflux         | `2.0.21`                       |                                                                                                               | -| MinIO            | `RELEASE.2021-11-09T03-21-45Z` | must set `MINIO_IDENTITY_OPENID_CLAIM_NAME: groups` in MinIO and set [MinIO policies](https://docs.min.io/minio/baremetal/security/minio-identity-management/policy-based-access-control.html#minio-policy) as groups in Authelia | -| Nextcloud        | `22.1.0`                       | Tested using the `nextcloud-oidc-login` app - [Link](https://github.com/pulsejet/nextcloud-oidc-login)        | -| Portainer CE     | `2.6.1`                        | Settings to use username as ID: set `Scopes` to `openid` and `User Identifier` to `preferred_username`        | -| Seafile          | `9.0.4`                        | Requires `OAUTH_ATTRIBUTE_MAP` to contain the mapping of the `id` field even if not present in Authelia, e.g. `'id': (False, "unused")` (see [seahub#5162](https://github.com/haiwen/seahub/issues/5162)) | -| Verdaccio        | `5`                            | Depends on this fork of verdaccio-github-oauth-ui: [Link](https://github.com/OnekO/verdaccio-github-oauth-ui) | -| Wekan            | `5.41`                         |                                                                                                               | - -## Known Callback URLs - -If you do not find the application in the list below, you will need to search for yourself - and maybe come back to open a PR to add your application to this list so others won't have to search for them. - -`<DOMAIN>` needs to be substituted with the full URL on which the application runs on. If GitLab, as an example, was reachable under `https://gitlab.example.com`, `<DOMAIN>` would be exactly the same. - -|   Application   |                Version                |                               Callback URL                               |                                                                                                                                              Notes                                                                                                                                               | -|:---------------:|:-------------------------------------:|:------------------------------------------------------------------------:|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:| -| Bookstack       | `21.10`                               | `<DOMAIN>/oidc/callback`                                                 |                                                                                                                                                                                                                                                                                                  | -| Gitea           | `1.14.6`                              | `<DOMAIN>/user/oauth2/authelia/callback`                                 | `ROOT_URL` in `[server]` section of `app.ini` must be configured correctly. Typically it is `<DOMAIN>/`. The string `authelia` in the callback url is the `Authentication Name` of the configured Authentication Source in Gitea (Authentication Type: OAuth2, OAuth2 Provider: OpenID Connect). | -| GitLab          | `14.0.1`                              | `<DOMAIN>/users/auth/openid_connect/callback`                            |                                                                                                                                                                                                                                                                                                  | -| Harbor          | `1.10`                                | `<DOMAIN>/-/oauth/callback`                                              |                                                                                                                                                                                                                                                                                                  | -| Hashicorp Vault  | `14.0.1`                              | `<DOMAIN>/oidc/callback` and `<DOMAIN>/ui/vault/auth/oidc/oidc/callback` |                                                                                                                                                                                                                                                                                                  | -| Miniflux        | `2.0.21`                              | `<DOMAIN>/oauth2/oidc/callback`                                          | Set via Miniflux `OAUTH2_REDIRECT_URL` [configuration parameter](https://miniflux.app/docs/configuration.html#oauth2-redirect-url). Example value follows this format                                                                                                                                            | -| MinIO           | `RELEASE.2021-07-12T02-44-53Z`        | `<DOMAIN>/oauth_callback`                                                |                                                                                                                                                                                                                                                                                                  | -| Nextcloud       | `22.1.0` + `nextcloud-oidc-login` app | `<DOMAIN>/apps/oidc_login/oidc`                                          |                                                                                                                                                                                                                                                                                                  | -| Portainer CE    | `2.6.1`                               | `<DOMAIN>`                                                               |                                                                                                                                                                                                                                                                                                  | -| Seafile         | `9.0.4`                               | `<DOMAIN>/oauth/callback/`                                               | Must exactly match `OAUTH_REDIRECT_URL` value as set in `seahub_settings.py`                                                                                                                                                                                                                                          | -| Verdaccio       | `5`                                   | `<DOMAIN>/oidc/callback`                                                 |                                                                                                                                                                                                                                                                                                  | -| Wekan           | `5.41`                                | `<DOMAIN>/_oauth_oidc`                                                   |                                                                                                                                                                                                                                                                                                  | diff --git a/docs/community/oidc-integrations/portainer.md b/docs/community/oidc-integrations/portainer.md deleted file mode 100644 index a54415c70..000000000 --- a/docs/community/oidc-integrations/portainer.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -layout: default -title: Portainer -parent: Community-Tested OIDC Integrations -grand_parent: Community -nav_order: 1 ---- - -# OIDC Integrations: Portainer - -{{ page.path }} - -**Note** these setting have been tested with authelia `v4.34.6` and Portainer (CE and EE) `2.12.2` - -## Authelia config - -The specific client config for portainer. - -```yaml -identity_providers: -  oidc: -    clients: -      - id: portainer_client_id -        description: Some description you want to shown on the Authelia consent page -        secret: some secret string which should also be entered in the portainer config -        public: false -        authorization_policy: two_factor -        audience: [] -        scopes: -          - openid -          - profile -          - groups -          - email -        redirect_uris: -          - https://portainer.example.com -        userinfo_signing_algorithm: none -``` - -## Portainer config - -To setup Authelia as SSO provider in portainer go to **Settings > Authentication** and select **Authentication method** OAuth and **Provider** Custom and make sure automatic user provision is turned so users get automatically created. - -**Note** make sure that Redirect URL matches exacty the redirect_uris in authelia config. Use `preferred_username` as the User identifier which makes sure the portianer user and authelia user have the same username. Scopes should be `openid profile groups email` **do not use commas** - -<p align="center"> -  <a href="../../images/portainer.gif" target="_blank"><img src="../../images/portainer.gif" width="736"></a> -</p> diff --git a/docs/community/oidc-integrations/proxmox.md b/docs/community/oidc-integrations/proxmox.md deleted file mode 100644 index 86183f34f..000000000 --- a/docs/community/oidc-integrations/proxmox.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -layout: default -title: Proxmox -parent: Community-Tested OIDC Integrations -grand_parent: Community -nav_order: 2 ---- - -# OIDC Integrations: Proxmox - -{{ page.path }} - -## Authelia config - -**Note** these setting have been tested with authelia `v4.33.2` and Proxmox `7.1-10` - -The specific client config for proxmox. - -```yaml -identity_providers: -  oidc: -    clients: -      - id: some id you want to use on the client -        description: Some description you want to shown on the Authelia consent page -        secret: some secret string which should also be entered in the proxmox config -        public: false -        authorization_policy: two_factor -        audience: [] -        scopes: -          - openid -        redirect_uris: -          - https://proxmox.example.com -        userinfo_signing_algorithm: none -``` - -## Proxmox config - -Under Datacenter go to **Persmission > Realms** and add the an OpenID Connect Server - -<p align="center"> -  <a href="../../images/portainer.gif" target="_blank"><img src="../../images/proxmox.gif" width="736"></a> -</p>
\ No newline at end of file diff --git a/docs/community/two-factor-basic-auth.md b/docs/community/two-factor-basic-auth.md deleted file mode 100644 index 84dfb7acd..000000000 --- a/docs/community/two-factor-basic-auth.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -layout: default -title: 2FA through basic auth -parent: Community -nav_order: 1 ---- - -The following project allows you to use Authelia's one-time password (OTP) 2-factor authentication (2FA) through only -[basic auth](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication) -and a custom credentials format described below. -This allows you to use 2FA on clients and scenarios -that demand basic auth, e.g. [webdav](https://en.wikipedia.org/wiki/WebDAV) network streaming. -More information: - -## [authelia-basic-2fa](https://github.com/ViRb3/authelia-basic-2fa) diff --git a/docs/community/using-remote-user-header-for-sso-with-jira.md b/docs/community/using-remote-user-header-for-sso-with-jira.md deleted file mode 100644 index fc42f4d36..000000000 --- a/docs/community/using-remote-user-header-for-sso-with-jira.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -layout: default -title: Using Remote-User header for SSO with Jira -parent: Community -nav_order: 2 ---- - -# Using Remote-User header for SSO with Jira - -You can make Jira auto-login to the user that is currently logged in to authelia. -I say "auto-login" as I couldn't find any plugin to actually be authentication -provider through HTTP headers only - LDAP though seems to have support. - -So this guide is targeted to authelia users that don't use any other authentication -backend. - -I'm using traefik with docker as an example, but any proxy that can forward -authelia `Remote-User` header is fine. - -First of all, users should exist on both Authelia and Jira, and have the same -username for this to work. Also you will have to -[pay for a plugin](https://marketplace.atlassian.com/apps/1212581/easy-sso-jira-kerberos-ntlm-saml?hosting=server&tab=overview). - -After both steps are done: -  - Add `traefik.http.middlewares.authelia.forwardauth.authResponseHeaders=Remote-User` in the labels of authelia -  - Add `traefik.http.routers.jira.middlewares=authelia@docker` in the labels of Jira (to actually enable Authelia for  -    the Jira instance) -  - Install EasySSO in Jira -  - Go to EasySSO preferences and add the "Remote-User" header under HTTP and tick the "Username" checkbox. -  - Save - -## Other Systems - -While this guide is tailored for Jira, you can use a similar method with many other services like Jenkins and Grafana. diff --git a/docs/config/_default/config.toml b/docs/config/_default/config.toml new file mode 100644 index 000000000..5174a6a08 --- /dev/null +++ b/docs/config/_default/config.toml @@ -0,0 +1,89 @@ +baseurl = "https://www.authelia.com/" +canonifyURLs = false +disableAliases = true +disableHugoGeneratorInject = true +enableEmoji = true +enableGitInfo = true +enableRobotsTXT = true +languageCode = "en-US" +paginate = 7 +rssLimit = 10 +title = "Authelia" + +# Multilingual +defaultContentLanguage = "en" +disableLanguages = [] +# defaultContentLanguageInSubdir = true + +# add redirects/headers +[outputs] +home = ["HTML", "RSS", "REDIRECTS", "HEADERS"] +section = ["HTML", "RSS", "SITEMAP"] + +# remove .{ext} from text/netlify +[mediaTypes."text/netlify"] +suffixes = [""] +delimiter = "" + +# add output format for netlify _redirects +[outputFormats.REDIRECTS] +mediaType = "text/netlify" +baseName = "_redirects" +isPlainText = true +notAlternative = true + +# add output format for netlify _headers +[outputFormats.HEADERS] +mediaType = "text/netlify" +baseName = "_headers" +isPlainText = true +notAlternative = true + +# add output format for section sitemap.xml +[outputFormats.SITEMAP] +mediaType = "application/xml" +baseName = "sitemap" +isHTML = false +isPlainText = true +noUgly = true +rel  = "sitemap" + +[caches] +  [caches.getjson] +    dir = ":cacheDir/:project" +    maxAge = "10s" + +[sitemap] +  changefreq = "weekly" +  filename = "sitemap.xml" +  priority = 0.5 + +[taxonomies] +  contributor = "contributors" + +[permalinks] +  blog = "/blog/:title/" + +[minify.tdewolff.html] +  keepWhitespace = false + +[module] +  [module.hugoVersion] +    extended = true +    min = "0.80.0" +    max = "" +  [[module.mounts]] +    source = "assets" +    target = "assets" +  [[module.mounts]] +    source = "static" +    target = "static" +  [[module.mounts]] +    source = "node_modules/flexsearch" +    target = "assets/js/vendor/flexsearch" +  [[module.mounts]] +    source = "node_modules/katex" +    target = "assets/js/vendor/katex" +  [[module.mounts]] +    source = "node_modules/mermaid" +    target = "assets/js/vendor/mermaid" diff --git a/docs/config/_default/languages.toml b/docs/config/_default/languages.toml new file mode 100644 index 000000000..6ee6333fa --- /dev/null +++ b/docs/config/_default/languages.toml @@ -0,0 +1,6 @@ +[en] +  languageName = "English" +  contentDir = "content/en" +  weight = 10 +  [en.params] +    languageISO = "EN" diff --git a/docs/config/_default/markup.toml b/docs/config/_default/markup.toml new file mode 100644 index 000000000..7960409d5 --- /dev/null +++ b/docs/config/_default/markup.toml @@ -0,0 +1,29 @@ +defaultMarkdownHandler = "goldmark" + +[goldmark] +  [goldmark.extensions] +    linkify = true +  [goldmark.parser] +    autoHeadingID = true +    autoHeadingIDType = "github" +    [goldmark.parser.attribute] +      block = true +      title = true +  [goldmark.renderer] +    unsafe = true + +[highlight] +  codeFences = false +  guessSyntax = false +  hl_Lines = "" +  lineNoStart = 1 +  lineNos = false +  lineNumbersInTable = true +  noClasses = false +  style = "dracula" +  tabWidth = 4 + +[tableOfContents] +  endLevel = 4 +  ordered = false +  startLevel = 2 diff --git a/docs/config/_default/menus/menus.en.toml b/docs/config/_default/menus/menus.en.toml new file mode 100644 index 000000000..2cb6e6245 --- /dev/null +++ b/docs/config/_default/menus/menus.en.toml @@ -0,0 +1,68 @@ +[[main]] +  name = "Overview" +  identifier = "overview" +  url = "/overview/prologue/introduction/" +  weight = 10 + +[[main]] +  name = "Configuration" +  identifier = "configuration" +  url = "/configuration/prologue/introduction/" +  weight = 20 + +[[main]] +  name = "Integration" +  identifier = "integration" +  url = "/integration/prologue/introduction/" +  weight = 30 + +[[main]] +  name = "Contributing" +  identifier = "contributing" +  url = "/contributing/prologue/introduction" +  weight = 40 + +[[main]] +  name = "Blog" +  identifier = "blog" +  url = "/blog/" +  weight = 50 + +[[main]] +  name = "Roadmap" +  identifier = "roadmap" +  url = "/roadmap/prologue/introduction/" +  weight = 80 + +[[main]] +  name = "Reference" +  identifier = "reference" +  url = "/reference/prologue/introduction/" +  weight = 90 + +[[social]] +  name = "GitHub" +  pre = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"feather feather-github\"><path d=\"M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22\"></path></svg>" +  url = "https://github.com/authelia/authelia" +  post = "v0.1.0" +  weight = 10 + +[[footer]] +  name = "Privacy" +  url = "/information/privacy-policy" +  weight = 10 + +[[footer]] +  name = "Code of Conduct" +  url = "/information/code-of-conduct" +  weight = 20 + +[[footer]] +  name = "Security" +  url = "/information/security" +  weight = 30 + +[[footer]] +  name = "Contact" +  url = "/information/contact" +  weight = 40 diff --git a/docs/config/_default/params.toml b/docs/config/_default/params.toml new file mode 100644 index 000000000..10cd7ed9c --- /dev/null +++ b/docs/config/_default/params.toml @@ -0,0 +1,95 @@ +# Meta Data for SEO + +## Homepage +title = "Authelia" +titleSeparator = "-" +titleAddition = "The Single Sign-On Multi-Factor portal for web apps" +description = "Authelia is an open-source authentication and authorization server and portal fulfilling the identity and access management (IAM) role of information security in providing multi-factor authentication and single sign-on (SSO) for your applications via a web portal. It acts as a companion for common reverse proxies." + +## Documentation +# docsVersion = "0.3" + +## Open Graph +images = ["authelia.png"] +ogLocale = "en_US" +domainTLD = "authelia.com" +titleHome = "Authelia" + +## Twitter Cards +# twitterSite = "" +# twitterCreator = "" + +## JSON-LD +schemaType = "Organization" +schemaName = "Authelia" +schemaAuthor = "Authelia" +# schemaAuthorTwitter = "" +# schemaAuthorLinkedIn = "" +schemaAuthorGitHub = "https://github.com/authelia" +schemaLocale = "en-US" +schemaLogo = "logo-doks.png" +schemaLogoWidth = 512 +schemaLogoHeight = 512 +schemaImage = "doks.png" +schemaImageWidth = 1280 +schemaImageHeight = 640 +# schemaTwitter = "" +# schemaLinkedIn = "" +schemaGitHub = "https://github.com/authelia/authelia" +schemaSection = "blog" + +## Sitelinks Search Box +siteLinksSearchBox = false + +## Chrome Browser +themeColor = "#fff" + +# Images +quality = 85 +bgColor = "#fff" +landscapePhotoWidths = [900, 800, 700, 600, 500] +portraitPhotoWidths = [800, 700, 600, 500] +lqipWidth = "20x" +smallLimit = "300" + +# Footer +footer = "Powered by <a class=\"text-muted\" href=\"https://www.netlify.com/\">Netlify</a>, <a class=\"text-muted\" href=\"https://gohugo.io/\">Hugo</a>, and <a class=\"text-muted\" href=\"https://getdoks.org/\">Doks</a>" + +# Feed +copyRight = "Copyright © 2016-%s Authelia" + +# Alert +alert = true +alertDismissable = true +alertText = "Help us improve Authelia by taking this <a class=\"alert-link stretched-link\" href=\"https://forms.gle/aVw6J9jcez97EAhD6\">10 second survey.</a>" + +# Edit Page +repoHost = "GitHub" +docsRepo = "https://github.com/authelia/authelia" +docsRepoBranch = "master" +docsRepoSubPath = "docs" +editPage = true +lastMod = true + +[options] +  lazySizes = true +  clipBoard = true +  instantPage = true +  flexSearch = true +  darkMode = true +  bootStrapJs = true +  breadCrumb = true +  highLight = true +  kaTex = false +  multilingualMode = false +  docsVersioning = false +  fullWidth = false + +[menu] +  [menu.section] +    auto = true +    collapsibleSidebar = true + +[Sections] +  Search = ["overview", "configuration", "integration", "contributing", "reference"] +  Searchable = ["blog"] diff --git a/docs/config/next/config.toml b/docs/config/next/config.toml new file mode 100644 index 000000000..9c5e90da5 --- /dev/null +++ b/docs/config/next/config.toml @@ -0,0 +1 @@ +canonifyURLs = false diff --git a/docs/config/postcss.config.js b/docs/config/postcss.config.js new file mode 100644 index 000000000..f9d1a18ab --- /dev/null +++ b/docs/config/postcss.config.js @@ -0,0 +1,39 @@ +const autoprefixer = require('autoprefixer'); +const purgecss = require('@fullhuman/postcss-purgecss'); +const whitelister = require('purgecss-whitelister'); + +module.exports = { +  plugins: [ +    autoprefixer(), +    purgecss({ +      content: [ +        './layouts/**/*.html', +        './content/**/*.md', +      ], +      safelist: [ +        'lazyloaded', +        'table', +        'thead', +        'tbody', +        'tr', +        'th', +        'td', +        'h5', +        'alert-link', +        'container-xxl', +        'container-fluid', +        ...whitelister([ +          './assets/scss/components/_alerts.scss', +          './assets/scss/components/_buttons.scss', +          './assets/scss/components/_code.scss', +          './assets/scss/components/_diagrams.scss', +          './assets/scss/components/_syntax.scss', +          './assets/scss/components/_search.scss', +          './assets/scss/common/_dark.scss', +          './node_modules/bootstrap/scss/_dropdown.scss', +          './node_modules/katex/dist/katex.css', +        ]), +      ], +    }), +  ], +} diff --git a/docs/config/production/config.toml b/docs/config/production/config.toml new file mode 100644 index 000000000..9c5e90da5 --- /dev/null +++ b/docs/config/production/config.toml @@ -0,0 +1 @@ +canonifyURLs = false diff --git a/docs/config/staging/config.toml b/docs/config/staging/config.toml new file mode 100644 index 000000000..31a41916f --- /dev/null +++ b/docs/config/staging/config.toml @@ -0,0 +1,2 @@ +canonifyURLs = false +baseurl = "https://authelia-staging.netlify.app/" diff --git a/docs/configuration/authentication/file.md b/docs/configuration/authentication/file.md deleted file mode 100644 index 3a8565422..000000000 --- a/docs/configuration/authentication/file.md +++ /dev/null @@ -1,247 +0,0 @@ ---- -layout: default -title: File -parent: Authentication Backends -grand_parent: Configuration -nav_order: 1 ---- - -# File - -**Authelia** supports a file as a users database. - - -## Configuration - -Configuring Authelia to use a file is done by specifying the path to the -file in the configuration file. - -```yaml -authentication_backend: -  disable_reset_password: false -  file: -    path: /config/users.yml -    password: -      algorithm: argon2id -      iterations: 3 -      salt_length: 16 -      key_length: 32 -      parallelism: 4 -      memory: 64 -``` - -## Format - -The format of the users file is as follows. - -```yaml -users: -  john: -    displayname: "John Doe" -    password: "$argon2id$v=19$m=65536,t=3,p=2$BpLnfgDsc2WD8F2q$o/vzA4myCqZZ36bUGsDY//8mKUYNZZaR0t4MFFSs+iM" -    email: john.doe@authelia.com -    groups: -      - admins -      - dev -  harry: -    displayname: "Harry Potter" -    password: "$argon2id$v=19$m=65536,t=3,p=2$BpLnfgDsc2WD8F2q$o/vzA4myCqZZ36bUGsDY//8mKUYNZZaR0t4MFFSs+iM" -    email: harry.potter@authelia.com -    groups: [] -  bob: -    displayname: "Bob Dylan" -    password: "$argon2id$v=19$m=65536,t=3,p=2$BpLnfgDsc2WD8F2q$o/vzA4myCqZZ36bUGsDY//8mKUYNZZaR0t4MFFSs+iM" -    email: bob.dylan@authelia.com -    groups: -      - dev -  james: -    displayname: "James Dean" -    password: "$argon2id$v=19$m=65536,t=3,p=2$BpLnfgDsc2WD8F2q$o/vzA4myCqZZ36bUGsDY//8mKUYNZZaR0t4MFFSs+iM" -    email: james.dean@authelia.com -``` - -This file should be set with read/write permissions as it could be updated by users -resetting their passwords. - - -## Options - -### path -<div markdown="1"> -type: string (path) -{: .label .label-config .label-purple } -required: yes -{: .label .label-config .label-red } -</div> - - -### password - -#### algorithm -<div markdown="1"> -type: string -{: .label .label-config .label-purple } -default: argon2id -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -Controls the hashing algorithm used for hashing new passwords. Value must be one of `argon2id` or `sha512`. - - -#### iterations -<div markdown="1"> -type: integer -{: .label .label-config .label-purple } -required: no -{: .label .label-config .label-green } -</div> - -Controls the number of hashing iterations done by the other hashing settings. - -When using `argon2id` the minimum is 3, which is also the recommended and default value. - -When using `sha512` the minimum is 1000, and 50000 is the recommended and default value. - - -#### salt_length -<div markdown="1"> -type: integer -{: .label .label-config .label-purple } -default: 16 -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -Controls the length of the random salt added to each password before hashing. It's recommended this value is set to 16, -and there is no documented reason why you'd set it to anything other than this, however the minimum is 8. - - -#### parallelism -<div markdown="1"> -type: integer -{: .label .label-config .label-purple } -default: 4 -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -This setting is specific to `argon2id` and unused with `sha512`. Sets the number of threads used when hashing passwords, -which affects the effective cost of hashing. - - -#### memory -<div markdown="1"> -type: integer -{: .label .label-config .label-purple } -default: 64 -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -This setting is specific to `argon2id` and unused with `sha512`. Sets the amount of memory allocated to a single -password hashing action. This memory is released by go after the hashing process completes, however the operating system -may not reclaim it until it needs the memory which may make Authelia appear to be using more memory than it technically -is. - -## Passwords - -The file contains hashed passwords instead of plain text passwords for security reasons. - -You can use Authelia binary or docker image to generate the hash of any password. The -hash-password command has many tunable options, you can view them with the -`authelia hash-password --help` command. For example if you wanted to improve the entropy -you could generate a 16 byte salt and provide it with the `--salt` flag. -Example: `authelia hash-password --salt abcdefghijklhijl -- 'yourpassword'`. For argon2id the salt must -always be valid for base64 decoding (characters a through z, A through Z, 0 through 9, and +/). - -Passwords passed to `hash-password` should be single quoted if using special characters to prevent parameter substitution. -For instance to generate a hash with the docker image just run: - -    $ docker run authelia/authelia:latest authelia hash-password -- 'yourpassword' -    Password hash: $argon2id$v=19$m=65536$3oc26byQuSkQqksq$zM1QiTvVPrMfV6BVLs2t4gM+af5IN7euO0VB6+Q8ZFs - -You may also use the `--config` flag to point to your existing configuration. When used, the values defined in the config will be used instead. - -Full CLI Help Documentation: - -``` -Hash a password to be used in file-based users database. Default algorithm is argon2id. - -Usage: -  authelia hash-password [flags] -- <password> - -Flags: -  -c, --config strings    Configuration files -  -h, --help              help for hash-password -  -i, --iterations int    set the number of hashing iterations (default 3) -  -k, --key-length int    [argon2id] set the key length param (default 32) -  -m, --memory int        [argon2id] set the amount of memory param (in MB) (default 64) -  -p, --parallelism int   [argon2id] set the parallelism param (default 4) -  -s, --salt string       set the salt string -  -l, --salt-length int   set the auto-generated salt length (default 16) -  -z, --sha512            use sha512 as the algorithm (changes iterations to 50000, change with -i) -``` - -### Password hash algorithm - -The default hash algorithm is Argon2id version 19 with a salt. Argon2id is currently considered -the best hashing algorithm, and in 2015 won the -[Password Hashing Competition](https://en.wikipedia.org/wiki/Password_Hashing_Competition). -It benefits from customizable parameters allowing the cost of computing a hash to scale -into the future which makes it harder to brute-force. Argon2id was implemented due to community -feedback as you can see in this closed [issue](https://github.com/authelia/authelia/issues/577). - -For backwards compatibility and user choice support for the SHA512 algorithm is still available. -While it's a reasonable hashing function given high enough iterations, as hardware improves it -has a higher chance of being brute-forced. - -Hashes are identifiable as argon2id or SHA512 by their prefix of either `$argon2id$` and `$6$` -respectively,  as described in this [wiki page](https://en.wikipedia.org/wiki/Crypt_(C)). - -**Important Note:** When using argon2id Authelia will appear to remain using the memory allocated -to creating the hash. This is due to how [Go](https://golang.org/) allocates memory to the heap when -generating an argon2id hash. Go periodically garbage collects the heap, however this doesn't remove -the memory allocation, it keeps it allocated even though it's technically unused. Under memory -pressure the unused allocated memory will be reclaimed by the operating system, you can test -this on linux with: - -    $ stress-ng --vm-bytes $(awk '/MemFree/{printf "%d\n", $2 * 0.9;}' < /proc/meminfo)k --vm-keep -m 1 - -If this is not desirable we recommend investigating the following options in order of most to least secure: -1. using the [LDAP authentication provider](./ldap.md) -2. adjusting the [memory](#memory) parameter -3. changing the [algorithm](#algorithm) - -### Password hash algorithm tuning - -All algorithm tuning for Argon2id is supported. The only configuration variables that affect -SHA512 are iterations and salt length. 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`. We have set what are considered as sane and recommended defaults -to cater for a reasonable system, if you're unsure about which settings to tune, please see the -parameters below, or for a more in depth understanding see the referenced documentation in -[Argon2 links](./file.md#argon2-links). - -#### Recommended Parameters: Argon2id - -This table is adapted from [RFC9106 Parameter Choice]: - -|  Situation  | Iterations (t) | Parallelism (p) | Memory (m) | Salt Size | Key Size | -|:-----------:|:--------------:|:---------------:|:----------:|:---------:|:--------:| -| Low Memory  |       3        |        4        |     64     |    16     |    32    | -| Recommended |       1        |        4        |    2048    |    16     |    32    | - -## Argon2 Links - -- [Go Documentation](https://godoc.org/golang.org/x/crypto/argon2) -- Argon2 Specification [RFC9106] -- [OWASP Password Storage Cheatsheet] - -[RFC9106]: https://www.rfc-editor.org/rfc/rfc9106.html -[RFC9106 Parameter Choice]: https://www.rfc-editor.org/rfc/rfc9106.html#section-4 -[OWASP Password Storage Cheatsheet]: https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html diff --git a/docs/configuration/authentication/index.md b/docs/configuration/authentication/index.md deleted file mode 100644 index be1204443..000000000 --- a/docs/configuration/authentication/index.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -layout: default -title: Authentication Backends -parent: Configuration -nav_order: 2 -has_children: true ---- - -# Authentication Backends - -There are two ways to store the users along with their password: - -* LDAP: users are stored in remote servers like OpenLDAP, OpenAM or Microsoft Active Directory. -* File: users are stored in YAML file with a hashed version of their password. - -## Configuration - -```yaml -authentication_backend: -  disable_reset_password: false -  password_reset: -    custom_url: "" -  file: {} -  ldap: {} -``` - -## Options - -### disable_reset_password -<div markdown="1"> -type: boolean -{: .label .label-config .label-purple }  -default: false -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -This setting controls if users can reset their password from the web frontend or not. - -### password_reset - -#### custom_url -<div markdown="1"> -type: string -{: .label .label-config .label-purple }  -default: "" -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -The custom password reset URL. This replaces the inbuilt password reset functionality and disables the endpoints if -this is configured to anything other than nothing or an empty string. - -### file - -The [file](file.md) authentication provider. - -### ldap - -The [LDAP](ldap.md) authentication provider. diff --git a/docs/configuration/authentication/ldap.md b/docs/configuration/authentication/ldap.md deleted file mode 100644 index 70e2ef522..000000000 --- a/docs/configuration/authentication/ldap.md +++ /dev/null @@ -1,336 +0,0 @@ ---- -layout: default -title: LDAP -parent: Authentication Backends -grand_parent: Configuration -nav_order: 2 ---- - -# LDAP -**Authelia** supports using a LDAP server as the users database. - -## Configuration -```yaml -authentication_backend: -  disable_reset_password: false -  refresh_interval: 5m -  ldap: -    implementation: custom -    url: ldap://127.0.0.1 -    timeout: 5s -    start_tls: false -    tls: -      server_name: ldap.example.com -      skip_verify: false -      minimum_version: TLS1.2 -    base_dn: DC=example,DC=com -    username_attribute: uid -    additional_users_dn: ou=users -    users_filter: (&({username_attribute}={input})(objectClass=person)) -    additional_groups_dn: ou=groups -    groups_filter: (&(member={dn})(objectClass=groupOfNames)) -    group_name_attribute: cn -    mail_attribute: mail -    display_name_attribute: displayName -    permit_referrals: false -    user: CN=admin,DC=example,DC=com -    password: password -``` - -## Options - -### implementation -<div markdown="1"> -type: string -{: .label .label-config .label-purple }  -default: custom -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -Configures the LDAP implementation used by Authelia. - -See the [Implementation Guide](#implementation-guide) for information. - -### url -<div markdown="1"> -type: string -{: .label .label-config .label-purple } -required: yes -{: .label .label-config .label-red } -</div> - -The LDAP URL which consists of a scheme, address, and port. Format is `<scheme>://<address>:<port>` or -`<scheme>://<address>` where scheme is either `ldap` or `ldaps`. - -If utilising an IPv6 literal address it must be enclosed by square brackets: - -```yaml -url: ldap://[fd00:1111:2222:3333::1] -``` - -### timeout -<div markdown="1"> -type: duration -{: .label .label-config .label-purple } -default: 5s -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -The timeout for dialing an LDAP connection. - -### start_tls -<div markdown="1"> -type: boolean -{: .label .label-config .label-purple }  -default: false -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -Enables use of the LDAP StartTLS process which is not commonly used. You should only configure this if you know you need -it. The initial connection will be over plain text, and Authelia will try to upgrade it with the LDAP server. LDAPS -URL's are slightly more secure. - -### tls -Controls the TLS connection validation process. You can see how to configure the tls -section [here](../index.md#tls-configuration). - -### base_dn -<div markdown="1"> -type: string -{: .label .label-config .label-purple }  -required: yes -{: .label .label-config .label-red } -</div> - -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 -authelia OU: `ou=authelia,dc=example,dc=com`. This is prefixed with the [additional_users_dn](#additional_users_dn) for -user searches and [additional_groups_dn](#additional_groups_dn) for groups searches. - -### username_attribute -<div markdown="1"> -type: string -{: .label .label-config .label-purple } -required: yes -{: .label .label-config .label-red } -</div> - -_**Note:** While this option is required, an [implementation](#implementation) may set a default value implicitly -negating this requirement. Refer to the [attribute defaults](#attribute-defaults) for more information._ - -The LDAP attribute that maps to the username in Authelia. - -### additional_users_dn -<div markdown="1"> -type: string -{: .label .label-config .label-purple } -required: no -{: .label .label-config .label-green } -</div> - -Additional LDAP path to append to the [base_dn](#base_dn) 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 -`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`. The default value is dependent on the [implementation](#implementation), refer -to the [attribute defaults](#attribute-defaults) for more information. - -### users_filter -<div markdown="1"> -type: string -{: .label .label-config .label-purple } -required: yes -{: .label .label-config .label-red } -</div> - -_**Note:** While this option is required, an [implementation](#implementation) may set a default value implicitly -negating this requirement. Refer to the [attribute defaults](#attribute-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. - -### group_name_attribute -<div markdown="1"> -type: string -{: .label .label-config .label-purple } -required: yes -{: .label .label-config .label-red } -</div> - -_**Note:** While this option is required, an [implementation](#implementation) may set a default value implicitly -negating this requirement. Refer to the [attribute defaults](#attribute-defaults) for more information._ - -The LDAP attribute that is used by Authelia to determine the group name. - -### additional_groups_dn -<div markdown="1"> -type: string -{: .label .label-config .label-purple } -required: no -{: .label .label-config .label-green } -</div> - -Similar to [additional_users_dn](#additional_users_dn) but it applies to group searches. - -### groups_filter -<div markdown="1"> -type: string -{: .label .label-config .label-purple } -required: yes -{: .label .label-config .label-red } -</div> - -_**Note:** While this option is required, an [implementation](#implementation) may set a default value implicitly -negating this requirement. Refer to the [attribute defaults](#attribute-defaults) for more information._ - -Similar to [users_filter](#users_filter) but it applies to group searches. In order to include groups the member is not -a direct member of, but is a member of another group that is a member of those (i.e. recursive groups), you may try -using the following filter which is currently only tested against Microsoft Active Directory: - -`(&(member:1.2.840.113556.1.4.1941:={dn})(objectClass=group)(objectCategory=group))` - -### mail_attribute -<div markdown="1"> -type: string -{: .label .label-config .label-purple } -required: yes -{: .label .label-config .label-red } -</div> - -_**Note:** While this option is required, an [implementation](#implementation) may set a default value implicitly -negating this requirement. Refer to the [attribute defaults](#attribute-defaults) for more information._ - -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 when a user attempts to reset -their password or register a second factor device. - -### display_name_attribute -<div markdown="1"> -type: string -{: .label .label-config .label-purple } -required: yes -{: .label .label-config .label-red } -</div> - -_**Note:** While this option is required, an [implementation](#implementation) may set a default value implicitly -negating this requirement. Refer to the [attribute defaults](#attribute-defaults) for more information._ - -The attribute to retrieve which is shown on the Web UI to the user when they log in. - -### permit_referrals -<div markdown="1"> -type: boolean -{: .label .label-config .label-purple } -default: false -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-red } -</div> - -Permits following referrals. This is useful if you have read-only servers in your architecture and thus require  -referrals to be followed when performing write operations. This is only implemented for password modifications, if you -need this for searches please open a GitHub issue or contact us. - -### user -The distinguished name of the user paired with the password to bind with for lookup and password change operations. - -### password -The password of the user paired with the user to bind with for lookup and password change operations. -Can also be defined using a [secret](../secrets.md) which is the recommended for containerized deployments. - -## Implementation Guide -There are currently two implementations, `custom` and `activedirectory`. The `activedirectory` implementation -must be used if you wish to allow users to change or reset their password as Active Directory -uses a custom attribute for this, and an input format other implementations do not use. The long term -intention of this is to have logical defaults for various RFC implementations of LDAP. - -### Filter replacements -Various replacements occur in the user and groups filter. The replacements either occur at startup or upon an LDAP -search. - -#### Users filter replacements - -|       Placeholder        |  Phase  |              Replacement              | -|:------------------------:|:-------:|:-------------------------------------:| -|   {username_attribute}   | startup |   The configured username attribute   | -|     {mail_attribute}     | startup |     The configured mail attribute     | -| {display_name_attribute} | startup | The configured display name attribute | -|         {input}          | search  |   The input into the username field   | - -#### Groups filter replacements - -| Placeholder | Phase  |                                Replacement                                | -|:-----------:|:------:|:-------------------------------------------------------------------------:| -|   {input}   | search |                     The input into the username field                     | -| {username}  | search | The username from the profile lookup obtained from the username attribute | -|    {dn}     | search |              The distinguished name from the profile lookup               | - -### Defaults -The below tables describes the current attribute defaults for each implementation. - -#### Attribute defaults -This table describes the attribute defaults for each implementation. i.e. the username_attribute is -described by the Username column. - -| Implementation  |    Username    | Display Name | Mail | Group Name | -|:---------------:|:--------------:|:------------:|:----:|:----------:| -|     custom      |      n/a       | displayName  | mail |     cn     | -| activedirectory | sAMAccountName | displayName  | mail |     cn     | - -#### Filter defaults -The filters are probably the most important part to get correct when setting up LDAP. -You want to exclude disabled accounts. The active directory example has two attribute -filters that accomplish this as an example (more examples would be appreciated). The -userAccountControl filter checks that the account is not disabled and the pwdLastSet -makes sure that value is not 0 which means the password requires changing at the next login. - -| Implementation  |                                                                          Users Filter                                                                           |                       Groups Filter                       | -|:---------------:|:---------------------------------------------------------------------------------------------------------------------------------------------------------------:|:---------------------------------------------------------:| -|     custom      |                                                                               n/a                                                                               |                            n/a                            | -| activedirectory | (&(|({username_attribute}={input})({mail_attribute}={input}))(sAMAccountType=805306368)(!(userAccountControl:1.2.840.113556.1.4.803:=2))(!(pwdLastSet=0))) | (&(member={dn})(objectClass=group)(objectCategory=group)) | - -_**Note:**_ The Active Directory filter `(sAMAccountType=805306368)` is exactly the same as -`(&(objectCategory=person)(objectClass=user))` except that the former is more performant, you can read more about this -and other Active Directory filters on the  -[TechNet wiki](https://social.technet.microsoft.com/wiki/contents/articles/5392.active-directory-ldap-syntax-filters.aspx). - -## Refresh Interval -This setting takes a [duration notation](../index.md#duration-notation-format) that sets the max frequency -for how often Authelia contacts the backend to verify the user still exists and that the groups stored -in the session are up to date. This allows us to destroy sessions when the user no longer matches the -user_filter, or deny access to resources as they are removed from groups. - -In addition to the duration notation, you may provide the value `always` or `disable`. Setting to `always` -is the same as setting it to 0 which will refresh on every request, `disable` turns the feature off, which is -not recommended. This completely prevents Authelia from refreshing this information, and it would only be -refreshed when the user session gets destroyed by other means like inactivity, session expiration or logging -out and in. - -This value can be any value including 0, setting it to 0 would automatically refresh the session on -every single request. This means Authelia will have to contact the LDAP backend every time an element -on a page loads which could be substantially costly. It's a trade-off between load and security that -you should adapt according to your own security policy. - -## Important notes -Users must be uniquely identified by an attribute, this attribute must obviously contain a single value and -be guaranteed by the administrator to be unique. If multiple users have the same value, Authelia will simply -fail authenticating the user and display an error message in the logs. - -In order to avoid such problems, we highly recommended you follow https://www.ietf.org/rfc/rfc2307.txt by using -`sAMAccountName` for Active Directory and `uid` for other implementations as the attribute holding the -unique identifier for your users. - -As of versions > `4.24.0` the `users_filter` must include the `username_attribute` placeholder, not including this will -result in Authelia throwing an error. -In versions <= `4.24.0` not including the `username_attribute` placeholder will cause issues with the session refresh -and will result in session resets when the refresh interval has expired, default of 5 minutes. - -[LDAP GeneralizedTime]: https://ldapwiki.com/wiki/GeneralizedTime -[username attribute]: #username_attribute -[TechNet wiki]: https://social.technet.microsoft.com/wiki/contents/articles/5392.active-directory-ldap-syntax-filters.aspx diff --git a/docs/configuration/duo-push-notifications.md b/docs/configuration/duo-push-notifications.md deleted file mode 100644 index 26af6e27c..000000000 --- a/docs/configuration/duo-push-notifications.md +++ /dev/null @@ -1,97 +0,0 @@ ---- -layout: default -title: Duo Push Notifications -parent: Configuration -nav_order: 3 ---- - -# Duo Push Notifications - -Authelia supports mobile push notifications relying on [Duo]. - -Follow the instructions in the dedicated [documentation](../features/2fa/push-notifications.md) -to know how to set up push notifications in Authelia. - -**Note:** The configuration options in the following sections are noted as required. They are however only required when -you have this section defined. i.e. if you don't wish to use the [Duo] push notifications you can just not define this -section of the configuration. - -## Configuration - -The configuration is as follows: -```yaml -duo_api: -  disable: false -  hostname: api-123456789.example.com -  integration_key: ABCDEF -  secret_key: 1234567890abcdefghifjkl -  enable_self_enrollment: false -``` - -The secret key is shown as an example, you also have the option to set it using an environment -variable as described [here](./secrets.md). - -## Options - -### disable: -<div markdown="1"> -type: boolean -{: .label .label-config .label-purple }  -default: false -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -Disables Duo. If the hostname, integration_key, and secret_key are all empty strings or undefined this is automatically  -true. - -### hostname -<div markdown="1"> -type: string -{: .label .label-config .label-purple }  -default: "" -{: .label .label-config .label-blue } -required: yes -{: .label .label-config .label-red } -</div> - -The [Duo] API hostname supplied by [Duo]. - -### integration_key -<div markdown="1"> -type: string -{: .label .label-config .label-purple }  -default: "" -{: .label .label-config .label-blue } -required: yes -{: .label .label-config .label-red } -</div> - -The non-secret [Duo] integration key. Similar to a client identifier. - -### secret_key -<div markdown="1"> -type: string -{: .label .label-config .label-purple }  -default: "" -{: .label .label-config .label-blue } -required: yes -{: .label .label-config .label-red } -</div> - -The secret [Duo] key used to verify your application is valid. - -### enable_self_enrollment -<div markdown="1"> -type: boolean -{: .label .label-config .label-purple }  -default: false -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -Enables [Duo] device self-enrollment from within the Authelia portal. - -[Duo]: https://duo.com/ diff --git a/docs/configuration/identity-providers/index.md b/docs/configuration/identity-providers/index.md deleted file mode 100644 index d3b93e5d0..000000000 --- a/docs/configuration/identity-providers/index.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -layout: default -title: Identity Providers -parent: Configuration -nav_order: 4 -has_children: true ---- - -# Identity Providers - -This section covers configuration of the identity server characteristics of Authelia. Currently the only identity server -supported is OpenID Connect. diff --git a/docs/configuration/identity-providers/oidc.md b/docs/configuration/identity-providers/oidc.md deleted file mode 100644 index eda2af788..000000000 --- a/docs/configuration/identity-providers/oidc.md +++ /dev/null @@ -1,656 +0,0 @@ ---- -layout: default -title: OpenID Connect -parent: Identity Providers -grand_parent: Configuration -nav_order: 2 ---- - -# OpenID Connect - -**Authelia** currently supports the [OpenID Connect] OP role as a [**beta**](../../roadmap/oidc.md) feature. The OP role -is the [OpenID Connect] Provider role, not the Relying Party or RP role. This means other applications that implement the -[OpenID Connect] RP role can use Authelia as an authentication and authorization backend similar to how you may use -social media or development platforms for login. - -The Relying Party role is the role which allows an application to use GitHub, Google, or other [OpenID Connect] -providers for authentication and authorization. We do not intend to support this functionality at this moment in time. - -More information about the beta can be found in the [roadmap](../../roadmap/oidc.md). - -## Configuration - -The following snippet provides a sample-configuration for the OIDC identity provider explaining each field in detail. - -```yaml -identity_providers: -  oidc: -    hmac_secret: this_is_a_secret_abc123abc123abc -    issuer_private_key: | -      --- KEY START -      --- KEY END -    access_token_lifespan: 1h -    authorize_code_lifespan: 1m -    id_token_lifespan: 1h -    refresh_token_lifespan: 90m -    enable_client_debug_messages: false -    enforce_pkce: public_clients_only -    cors: -      endpoints: -        - authorization -        - token -        - revocation -        - introspection -      allowed_origins: -        - https://example.com -      allowed_origins_from_client_redirect_uris: false -    clients: -      - id: myapp -        description: My Application -        secret: this_is_a_secret -        sector_identifier: '' -        public: false -        authorization_policy: two_factor -        pre_configured_consent_duration: '' -        audience: [] -        scopes: -          - openid -          - groups -          - email -          - profile -        redirect_uris: -          - https://oidc.example.com:8080/oauth2/callback -        grant_types: -          - refresh_token -          - authorization_code -        response_types: -          - code -        response_modes: -          - form_post -          - query -          - fragment -        userinfo_signing_algorithm: none -``` - -## Options - -### hmac_secret -<div markdown="1"> -type: string -{: .label .label-config .label-purple }  -required: yes -{: .label .label-config .label-red } -</div> - -The HMAC secret used to sign the [OpenID Connect] JWT's. The provided string is hashed to a SHA256 -byte string for the purpose of meeting the required format. You must [generate this option yourself](#generating-a-random-secret). - -Should be defined using a [secret](../secrets.md) which is the recommended for containerized deployments. - -### issuer_private_key -<div markdown="1"> -type: string -{: .label .label-config .label-purple } -required: yes -{: .label .label-config .label-red } -</div> - -The private key in DER base64 encoded PEM format used to encrypt the [OpenID Connect] JWT's.[¹](../../faq.md#why-only-use-a-private-issuer-key-and-no-public-key-with-oidc) -You must [generate this option yourself](#generating-a-random-secret). To create this option, use -`docker run -u "$(id -u):$(id -g)" -v "$(pwd)":/keys authelia/authelia:latest authelia rsa generate --dir /keys` -to generate both the private and public key in the current directory. You can then paste the -private key into your configuration. - -Should be defined using a [secret](../secrets.md) which is the recommended for containerized deployments. - -### access_token_lifespan -<div markdown="1"> -type: duration -{: .label .label-config .label-purple } -default: 1h -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -The maximum lifetime of an access token. It's generally recommended keeping this short similar to the default. -For more information read these docs about [token lifespan]. - -### authorize_code_lifespan -<div markdown="1"> -type: duration -{: .label .label-config .label-purple } -default: 1m -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -The maximum lifetime of an authorize code. This can be rather short, as the authorize code should only be needed to -obtain the other token types. For more information read these docs about [token lifespan]. - -### id_token_lifespan -<div markdown="1"> -type: duration -{: .label .label-config .label-purple } -default: 1h -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -The maximum lifetime of an ID token. For more information read these docs about [token lifespan]. - -### refresh_token_lifespan -<div markdown="1"> -type: string -{: .label .label-config .label-purple } -default: 90m -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -The maximum lifetime of a refresh token. The -refresh token can be used to obtain new refresh tokens as well as access tokens or id tokens with an -up-to-date expiration. For more information read these docs about [token lifespan]. - -A good starting point is 50% more or 30 minutes more (which ever is less) time than the highest lifespan out of the -[access token lifespan](#access_token_lifespan), the [authorize code lifespan](#authorize_code_lifespan), and the -[id token lifespan](#id_token_lifespan). For instance the default for all of these is 60 minutes, so the default refresh -token lifespan is 90 minutes. - -### enable_client_debug_messages -<div markdown="1"> -type: boolean -{: .label .label-config .label-purple } -default: false -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -Allows additional debug messages to be sent to the clients. - -### minimum_parameter_entropy -<div markdown="1"> -type: integer -{: .label .label-config .label-purple } -default: 8 -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -This controls the minimum length of the `nonce` and `state` parameters. - -***Security Notice:*** Changing this value is generally discouraged, reducing it from the default can theoretically -make certain scenarios less secure. It is highly encouraged that if your OpenID Connect RP does not send these parameters -or sends parameters with a lower length than the default that they implement a change rather than changing this value. - -### enforce_pkce -<div markdown="1"> -type: string -{: .label .label-config .label-purple }  -default: public_clients_only -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -[Proof Key for Code Exchange](https://datatracker.ietf.org/doc/html/rfc7636) enforcement policy: if specified, must be either `never`, `public_clients_only` or `always`. - -If set to `public_clients_only` (default), PKCE will be required for public clients using the Authorization Code flow. - -When set to `always`, PKCE will be required for all clients using the Authorization Code flow. - -***Security Notice:*** Changing this value to `never` is generally discouraged, reducing it from the default can theoretically -make certain client-side applications (mobile applications, SPA) vulnerable to CSRF and authorization code interception attacks. - -### enable_pkce_plain_challenge -<div markdown="1"> -type: boolean -{: .label .label-config .label-purple } -default: false -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -Allows PKCE `plain` challenges when set to `true`. - -***Security Notice:*** Changing this value is generally discouraged. Applications should use the `S256` PKCE challenge method instead. - -### cors - -Some OpenID Connect Endpoints need to allow cross-origin resource sharing, however some are optional. This section allows -you to configure the optional parts. We reply with CORS headers when the request includes the Origin header. - -#### endpoints -<div markdown="1"> -type: list(string) -{: .label .label-config .label-purple } -default: empty -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -A list of endpoints to configure with cross-origin resource sharing headers. It is recommended that the `userinfo` -option is at least in this list. The potential endpoints which this can be enabled on are as follows: - -* authorization -* token -* revocation -* introspection -* userinfo - -#### allowed_origins -<div markdown="1"> -type: list(string) -{: .label .label-config .label-purple } -default: empty -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -A list of permitted origins. - -Any origin with https is permitted unless this option is configured or the allowed_origins_from_client_redirect_uris -option is enabled. This means you must configure this option manually if you want http endpoints to be permitted to -make cross-origin requests to the OpenID Connect endpoints, however this is not recommended. - -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 -and the allowed_origins_from_client_redirect_uris MUST NOT be enabled. The wildcard origin is denoted as `*`. Examples: - -```yaml -identity_providers: -  oidc: -    cors: -      allowed_origins: "*" -``` - -```yaml -identity_providers: -  oidc: -    cors: -      allowed_origins:  -        - "*" -``` - -#### allowed_origins_from_client_redirect_uris -<div markdown="1"> -type: boolean -{: .label .label-config .label-purple } -default: false -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -Automatically adds the origin portion of all redirect URI's on all clients to the list of allowed_origins, provided they -have the scheme http or https and do not have the hostname of localhost. - -### clients - -A list of clients to configure. The options for each client are described below. - -#### id -<div markdown="1"> -type: string -{: .label .label-config .label-purple }  -required: yes -{: .label .label-config .label-red } -</div> - -The Client ID for this client. It must exactly match the Client ID configured in the application -consuming this client. - -#### description -<div markdown="1"> -type: string -{: .label .label-config .label-purple }  -default: *same as id* -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -A friendly description for this client shown in the UI. This defaults to the same as the ID. - -#### secret -<div markdown="1"> -type: string -{: .label .label-config .label-purple } -required: situational -{: .label .label-config .label-yellow } -</div> - -The shared secret between Authelia and the application consuming this client. This secret must -match the secret configured in the application. Currently this is stored in plain text. -You must [generate this option yourself](#generating-a-random-secret). - -This must be provided when the client is a confidential client type, and must be blank when using the public client -type. To set the client type to public see the [public](#public) configuration option. - -#### sector_identifier -<div markdown="1"> -type: string -{: .label .label-config .label-purple } -default: '' -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-red } -</div> - -_**Important Note:** because adjusting this option will inevitably change the `sub` claim of all tokens generated for -the specified client, changing this should cause the relying party to detect all future authorizations as completely new -users._ - -Must be an empty string or the host component of a URL. This is commonly just the domain name, but may also include a -port. - -Authelia utilizes UUID version 4 subject identifiers. By default the public subject identifier type is utilized for all -clients. This means the subject identifiers will be the same for all clients. This configuration option enables pairwise -for this client, and configures the sector identifier utilized for both the storage and the lookup of the subject -identifier. - -1. All clients who do not have this configured will generate the same subject identifier for a particular user regardless -   of which client obtains the ID token. -2. All clients which have the same sector identifier will: -   1. have the same subject identifier for a particular user when compared to clients with the same sector identifier. -   2. have a completely different subject identifier for a particular user whe compared to: -      1. any client with the public subject identifier type. -      2. any client with a differing sector identifier. - -In specific but limited scenarios this option is beneficial for privacy reasons. In particular this is useful when the -party utilizing the _Authelia_ [OpenID Connect] Authorization Server is foreign and not controlled by the user. It would -prevent the third party utilizing the subject identifier with another third party in order to track the user. - -Keep in mind depending on the other claims they may still be able to perform this tracking and it is not a silver bullet. -There are very few benefits when utilizing this in a homelab or business where no third party is utilizing -the server. - -#### public -<div markdown="1"> -type: bool -{: .label .label-config .label-purple } -default: false -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -This enables the public client type for this client. This is for clients that are not capable of maintaining -confidentiality of credentials, you can read more about client types in [RFC6749](https://datatracker.ietf.org/doc/html/rfc6749#section-2.1). -This is particularly useful for SPA's and CLI tools. This option requires setting the [client secret](#secret) to a -blank string. - -In addition to the standard rules for redirect URIs, public clients can use the `urn:ietf:wg:oauth:2.0:oob` redirect URI. - -#### authorization_policy -<div markdown="1"> -type: string -{: .label .label-config .label-purple }  -default: two_factor -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -The authorization policy for this client: either `one_factor` or `two_factor`. - -#### pre_configured_consent_duration -<div markdown="1"> -type: string (duration)  -{: .label .label-config .label-purple }  -required: no -{: .label .label-config .label-green } -</div> - -Configuring this enables users of this client to remember their consent as a pre-configured consent. The value is period -of time is in [duration notation format](../index.md#duration-notation-format). The period of time dictates how long a -users choice to remember the pre-configured consent lasts. - -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. - -#### audience -<div markdown="1"> -type: list(string) -{: .label .label-config .label-purple }  -required: no -{: .label .label-config .label-green } -</div> - -A list of audiences this client is allowed to request. - -#### scopes -<div markdown="1"> -type: list(string) -{: .label .label-config .label-purple } -default: openid, groups, profile, email -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -A list of scopes to allow this client to consume. See [scope definitions](#scope-definitions) for more -information. The documentation for the application you want to use with Authelia will most-likely provide -you with the scopes to allow. - -#### redirect_uris -<div markdown="1"> -type: list(string) -{: .label .label-config .label-purple } -required: yes -{: .label .label-config .label-red } -</div> - -A list of valid callback URIs this client will redirect to. All other callbacks will be considered -unsafe. The URIs are case-sensitive and they differ from application to application - the community has -provided [a list of URL´s for common applications](../../community/oidc-integrations.md). - -Some restrictions that have been placed on clients and -their redirect URIs are as follows: - -1. If a client attempts to authorize with Authelia and its redirect URI is not listed in the client configuration the -   attempt to authorize wil fail and an error will be generated. -2. The redirect URIs are case-sensitive. -3. The URI must include a scheme and that scheme must be one of `http` or `https`. -4. The client can ignore rule 3 and use `urn:ietf:wg:oauth:2.0:oob` if it is a [public](#public) client type. - -#### grant_types -<div markdown="1"> -type: list(string) -{: .label .label-config .label-purple }  -default: refresh_token, authorization_code -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -A list of grant types this client can return. _It is recommended that this isn't configured at this time unless you -know what you're doing_. Valid options are: `implicit`, `refresh_token`, `authorization_code`, `password`, -`client_credentials`. - -#### response_types -<div markdown="1"> -type: list(string) -{: .label .label-config .label-purple }  -default: code -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -A list of response types this client can return. _It is recommended that this isn't configured at this time unless you -know what you're doing_. Valid options are: `code`, `code id_token`, `id_token`, `token id_token`, `token`, -`token id_token code`. - -#### response_modes -<div markdown="1"> -type: list(string) -{: .label .label-config .label-purple }  -default: form_post, query, fragment -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -A list of response modes this client can return. It is recommended that this isn't configured at this time unless you -know what you're doing. Potential values are `form_post`, `query`, and `fragment`. - -#### userinfo_signing_algorithm -<div markdown="1"> -type: string -{: .label .label-config .label-purple }  -default: none -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -The algorithm used to sign the userinfo endpoint responses. This can either be `none` or `RS256`. - -## Generating a random secret - -If you must provide a random secret in configuration, you can generate a random string of sufficient length. The command - -```sh -LENGTH=64 -tr -cd '[:alnum:]' < /dev/urandom | fold -w "${LENGTH}" | head -n 1 | tr -d '\n' ; echo -``` - -prints such a string with a length in characters of `${LENGTH}` on `stdout`. The string will only contain alphanumeric -characters. For Kubernetes, see [this section too](../secrets.md#Kubernetes). - -## Scope Definitions - -### openid - -This is the default scope for openid. This field is forced on every client by the configuration validation that Authelia -does. - -_**Important Note:** The subject identifiers or `sub` claim has been changed to a [RFC4122] UUID V4 to identify the  -individual user as per the [Subject Identifier Types] specification. Please use the claim `preferred_username` instead._ - -|   Claim   |   JWT Type    | Authelia Attribute |                         Description                         | -|:---------:|:-------------:|:------------------:|:-----------------------------------------------------------:| -|    sub    |    string     |      username      |    A [RFC4122] UUID V4 linked to the user who logged in     | -|   scope   |    string     |       scopes       |              Granted scopes (space delimited)               | -|    scp    | array[string] |       scopes       |                       Granted scopes                        | -|    iss    |    string     |      hostname      |             The issuer name, determined by URL              | -|  at_hash  |    string     |       _N/A_        |                      Access Token Hash                      | -|    aud    | array[string] |       _N/A_        |                          Audience                           | -|    exp    |    number     |       _N/A_        |                           Expires                           | -| auth_time |    number     |       _N/A_        |        The time the user authenticated with Authelia        | -|    rat    |    number     |       _N/A_        |            The time when the token was requested            | -|    iat    |    number     |       _N/A_        |             The time when the token was issued              | -|    jti    | string(uuid)  |       _N/A_        |     A JWT Identifier in the form of a [RFC4122] UUID V4     | -|    amr    | array[string] |       _N/A_        | An [RFC8176] list of authentication method reference values | -|    azp    |    string     |    id (client)     |                    The authorized party                     | -| client_id |    string     |    id (client)     |                        The client id                        | -     -### groups - -This scope includes the groups the authentication backend reports the user is a member of in the token. - -| Claim  |   JWT Type    | Authelia Attribute |                                                    Description                                                     | -|:------:|:-------------:|:------------------:|:------------------------------------------------------------------------------------------------------------------:| -| groups | array[string] |       groups       | List of user's groups discovered via [authentication](https://www.authelia.com/docs/configuration/authentication/) | - -### email - -This scope includes the email information the authentication backend reports about the user in the token. - -|     Claim      |   JWT Type    | Authelia Attribute |                        Description                        | -|:--------------:|:-------------:|:------------------:|:---------------------------------------------------------:| -|     email      |    string     |      email[0]      |       The first email address in the list of emails       | -| email_verified |     bool      |       _N/A_        | If the email is verified, assumed true for the time being | -|   alt_emails   | array[string] |     email[1:]      |  All email addresses that are not in the email JWT field  | - -### profile - -This scope includes the profile information the authentication backend reports about the user in the token. - -|       Claim        | JWT Type | Authelia Attribute |               Description                | -|:------------------:|:--------:|:------------------:|:----------------------------------------:| -| preferred_username |  string  |      username      | The username the user used to login with | -|        name        |  string  |    display_name    |          The users display name          | - -## Authentication Method References - -Authelia currently supports adding the `amr` claim to the [ID Token](https://openid.net/specs/openid-connect-core-1_0.html#IDToken) -utilizing the [RFC8176] Authentication Method Reference values.  - -The values this claim has are not strictly defined by the [OpenID Connect] specification. As such, some backends may -expect a specification other than [RFC8176] for this purpose. If you have such an application and wish for us to support -it then you're encouraged to create an issue. - -Below is a list of the potential values we place in the claim and their meaning: - -| Value |                           Description                            | Factor | Channel  | -|:-----:|:----------------------------------------------------------------:|:------:|:--------:| -|  mfa  |     User used multiple factors to login (see factor column)      |  N/A   |   N/A    | -|  mca  |    User used multiple channels to login (see channel column)     |  N/A   |   N/A    | -| user  |  User confirmed they were present when using their hardware key  |  N/A   |   N/A    | -|  pin  | User confirmed they are the owner of the hardware key with a pin |  N/A   |   N/A    | -|  pwd  |            User used a username and password to login            |  Know  | Browser  | -|  otp  |                     User used TOTP to login                      |  Have  | Browser  | -|  hwk  |                User used a hardware key to login                 |  Have  | Browser  | -|  sms  |                      User used Duo to login                      |  Have  | External | - -## Endpoint Implementations - -The following section documents the endpoints we implement and their respective paths. This information can traditionally -be discovered by relying parties that utilize [discovery](https://openid.net/specs/openid-connect-discovery-1_0.html), -however this information may be useful for clients which do not implement this. - -The endpoints can be discovered easily by visiting the Discovery and Metadata endpoints. It is recommended regardless -of your version of Authelia that you utilize this version as it will always produce the correct endpoint URLs. The paths -for the Discovery/Metadata endpoints are part of IANA's well known registration but are also documented in a table below. - -These tables document the endpoints we currently support and their paths in the most recent version of Authelia. The paths -are appended to the end of the primary URL used to access Authelia. The tables use the url https://auth.example.com as  -an example of the Authelia root URL which is also the OpenID Connect issuer. - -### Well Known Discovery Endpoints - -These endpoints can be utilized to discover other endpoints and metadata about the Authelia OP. - -|                 Endpoint                  |                              Path                               | -|:-----------------------------------------:|:---------------------------------------------------------------:| -|        [OpenID Connect Discovery]         |    https://auth.example.com/.well-known/openid-configuration    | -| [OAuth 2.0 Authorization Server Metadata] | https://auth.example.com/.well-known/oauth-authorization-server | - - -### Discoverable Endpoints  - -These endpoints implement OpenID Connect elements. - -|      Endpoint       |                      Path                       |  Discovery Attribute   | -|:-------------------:|:-----------------------------------------------:|:----------------------:| -| [JSON Web Key Sets] |       https://auth.example.com/jwks.json        |        jwks_uri        | -|   [Authorization]   | https://auth.example.com/api/oidc/authorization | authorization_endpoint | -|       [Token]       |     https://auth.example.com/api/oidc/token     |     token_endpoint     | -|     [Userinfo]      |   https://auth.example.com/api/oidc/userinfo    |   userinfo_endpoint    | -|   [Introspection]   | https://auth.example.com/api/oidc/introspection | introspection_endpoint | -|    [Revocation]     |  https://auth.example.com/api/oidc/revocation   |  revocation_endpoint   | - -[JSON Web Key Sets]: https://datatracker.ietf.org/doc/html/rfc7517#section-5 -[OpenID Connect]: https://openid.net/connect/ -[Subject Identifier Types]:https://openid.net/specs/openid-connect-core-1_0.html#SubjectIDTypes -[OpenID Connect Discovery]: https://openid.net/specs/openid-connect-discovery-1_0.html -[OAuth 2.0 Authorization Server Metadata]: https://datatracker.ietf.org/doc/html/rfc8414 -[Authorization]: https://openid.net/specs/openid-connect-core-1_0.html#AuthorizationEndpoint -[Token]: https://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint -[Userinfo]: https://openid.net/specs/openid-connect-core-1_0.html#UserInfo -[Introspection]: https://datatracker.ietf.org/doc/html/rfc7662 -[Revocation]: https://datatracker.ietf.org/doc/html/rfc7009 -[RFC8176]: https://datatracker.ietf.org/doc/html/rfc8176 -[RFC4122]: https://datatracker.ietf.org/doc/html/rfc4122 -[token lifespan]: https://docs.apigee.com/api-platform/antipatterns/oauth-long-expiration
\ No newline at end of file diff --git a/docs/configuration/index.md b/docs/configuration/index.md deleted file mode 100644 index c107ecd34..000000000 --- a/docs/configuration/index.md +++ /dev/null @@ -1,209 +0,0 @@ ---- -layout: default -title: Configuration -nav_order: 4 -has_children: true ---- - -# Configuration -Authelia has several methods of configuration available to it. The order of precedence is as follows: - -1. [Secrets](./secrets.md) -2. [Environment Variables](#environment) -3. [Files](#files) (in order of them being specified) - -This order of precedence puts higher weight on things higher in the list. This means anything specified in the  -[files](#files) is overridden by [environment variables](#environment) if specified, and anything specified by  -[environment variables](#environment) is overridden by [secrets](./secrets.md) if specified. - -## Files -When running **Authelia**, you can specify your configuration by passing the file path as shown below. - -```console -$ authelia --config config.custom.yml -``` - -You can have multiple configuration files which will be merged in the order specified. If duplicate keys are specified  -the last one to be specified is the one that takes precedence. Example: - -```console -$ authelia --config configuration.yml --config config-acl.yml --config config-other.yml -$ authelia --config configuration.yml,config-acl.yml,config-other.yml -``` - -Authelia's configuration files use the YAML format. A template with all possible options can be found at the root of the  -repository [here](https://github.com/authelia/authelia/blob/master/config.template.yml). - -### Docker -By default, the container looks for a configuration file at `/config/configuration.yml`. This can be changed using the `command` setting. - -## Environment -You may also provide the configuration by using environment variables. Environment variables are applied after the  -configuration file meaning anything specified as part of the environment overrides the configuration files. The  -environment variables must be prefixed with `AUTHELIA_`. - -_**Please Note:** It is not possible to configure_ the _access control rules section or OpenID Connect identity provider -section using environment variables at this time._ - -_**Please Note:** There are compatability issues with Kubernetes and this particular configuration option. You must  -ensure you have the `enableServiceLinks: false` setting in your pod spec. You can read more about this in the  -[migration documentation](./migration.md#kubernetes-4300)._ - -Underscores replace indented configuration sections or subkeys. For example the following environment variables replace -the configuration snippet that follows it: - -``` -AUTHELIA_LOG_LEVEL=info -AUTHELIA_SERVER_READ_BUFFER_SIZE=4096 -``` - -```yaml -log: -  level: info -server: -  read_buffer_size: 4096 -``` - -# Documentation - -We document the configuration in two ways: - -1. The configuration yaml default has comments documenting it. All documentation lines start with `##`. Lines starting  -   with a single `#` are yaml configuration options which are commented to disable them or as examples. -     -2. This documentation site. Generally each section of the configuration is in its own section of the documentation  -   site. Each configuration option is listed in its relevant section as a heading, under that heading generally are two -   or three colored labels.  -   - The `type` label is purple and indicates the yaml value type of the variable. It optionally includes some  -     additional information in parentheses. -   - The `default` label is blue and indicates the default value if you don't define the option at all. This is not the  -     same value as you will see in the examples in all instances, it is the value set when blank or undefined. -   - The `required` label changes color. When required it will be red, when not required it will be green, when the  -     required state depends on another configuration value it is yellow.   - -# Validation - -Authelia validates the configuration when it starts. This process checks multiple factors including configuration keys -that don't exist, configuration keys that have changed, the values of the keys are valid, and that a configuration -key isn't supplied at the same time as a secret for the same configuration option. - -You may also optionally validate your configuration against this validation process manually by using the validate-config -option with the Authelia binary as shown below. Keep in mind if you're using [secrets](./secrets.md) you will have to -manually provide these if you don't want to get certain validation errors (specifically requesting you provide one of -the secret values). You can choose to ignore them if you know what you're doing. This command is useful prior to -upgrading to prevent configuration changes from impacting downtime in an upgrade. This process does not validate -integrations, it only checks that your configuration syntax is valid. - -```console -$ authelia validate-config --config configuration.yml -``` - -# Regex - -We have several sections of configuration that utilize regular expressions. It's recommended to validate your regex -manually either via tools like [Rego](https://regoio.herokuapp.com/) or some other means.  - -It's important when attempting to utilize a backslash that it's utilized correctly. The YAML parser is likely to parse -this as you trying to use YAML escape syntax instead of regex escape syntax. To avoid this use single quotes instead of -no quotes or double quotes. - -Good Example: - -```yaml -domain_regex: '^(admin|secure)\.example\.com$' -``` - -Bad Example: - -```yaml -domain_regex: "^(admin|secure)\.example\.com$" -``` - -# Duration Notation Format - -We have implemented a string/integer based notation for configuration options that take a duration of time. This section  -describes the implementation of this. You can use this implementation in various areas of configuration such as: - -- session: -  - expiration -  - inactivity -  - remember_me_duration -- regulation: -  - ban_time -  - find_time -- ntp: -  - max_desync -- webauthn: -  - timeout - -The way this format works is you can either configure an integer or a string in the specific configuration areas. If you -supply an integer, it is considered a representation of seconds. If you supply a string, it parses the string in blocks -of quantities and units (number followed by a unit letter).  For example `5h` indicates a quantity of 5 units of `h`. - -While you can use multiple of these blocks in combination, ee suggest keeping it simple and use a single value. - -## Duration Notation Format Unit Legend - -|  Unit   | Associated Letter | -|:-------:|:-----------------:| -|  Years  |         y         | -| Months  |         M         | -|  Weeks  |         w         | -|  Days   |         d         | -|  Hours  |         h         | -| Minutes |         m         | -| Seconds |         s         | - -## Duration Notation Format Examples - -|     Desired Value     |        Configuration Examples         | -|:---------------------:|:-------------------------------------:| -| 1 hour and 30 minutes | `90m` or `1h30m` or `5400` or `5400s` | -|         1 day         | `1d` or `24h` or `86400` or `86400s`  | -|       10 hours        | `10h` or `600m` or `9h60m` or `36000` | - -# TLS Configuration - -Various sections of the configuration use a uniform configuration section called TLS. Notably LDAP and SMTP. -This section documents the usage. - -## Server Name -<div markdown="1"> -type: string -{: .label .label-config .label-purple }  -default: "" -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -The key `server_name` overrides the name checked against the certificate in the verification process. Useful if you -require to use a direct IP address for the address of the backend service but want to verify a specific SNI. - -## Skip Verify -<div markdown="1"> -type: boolean -{: .label .label-config .label-purple }  -default: false -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -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 [certificates directory](./miscellaneous.md#certificates_directory). - -## Minimum Version -<div markdown="1"> -type: string -{: .label .label-config .label-purple }  -default: TLS1.2 -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -The key `minimum_version` controls the minimum TLS version Authelia will use when opening TLS connections. -The possible values are `TLS1.3`, `TLS1.2`, `TLS1.1`, `TLS1.0`. Anything other than `TLS1.3` or `TLS1.2` -are very old and deprecated. You should avoid using these and upgrade your backend service instead of decreasing -this value. diff --git a/docs/configuration/migration.md b/docs/configuration/migration.md deleted file mode 100644 index f1022320b..000000000 --- a/docs/configuration/migration.md +++ /dev/null @@ -1,95 +0,0 @@ ---- -layout: default -title: Migration -parent: Configuration -nav_order: 6 ---- - -This section documents changes in the configuration which may require manual migration by the administrator. Typically -this only occurs when a configuration key is renamed or moved to a more appropriate location. - -## Format - -The migrations are formatted in a table with the old key and the new key. Periods indicate a different section which can -be represented in YAML as a dictionary i.e. it's indented. - -In our table `server.host` with a value of `0.0.0.0` is represented in YAML like this: - -```yaml -server: -  host: 0.0.0.0 -``` - -## Policy -Our deprecation policy for configuration keys is 3 minor versions. For example if a configuration option is deprecated -in version 4.30.0, it will remain as a warning for 4.30.x, 4.31.x, and 4.32.x; then it will become a fatal error in -4.33.0+.  - -## Migrations - -### 4.33.0 -The options deprecated in version [4.30.0](#4300) have been fully removed as per our deprecation policy and warnings -logged for users. - -### 4.30.0 -The following changes occurred in 4.30.0: - -| Previous Key  |        New Key         | -|:-------------:|:----------------------:| -|     host      |      server.host       | -|     port      |      server.port       | -|    tls_key    |     server.tls.key     | -|   tls_cert    | server.tls.certificate | -|   log_level   |       log.level        | -| log_file_path |     log.file_path      | -|  log_format   |       log.format       | - -_**Please Note:** you can no longer define secrets for providers that you are not using. For example if you're using the  -[filesystem notifier](./notifier/filesystem.md) you must ensure that the `AUTHELIA_NOTIFIER_SMTP_PASSWORD_FILE`  -environment variable or other environment variables set. This also applies to other providers like  -[storage](./storage/index.md) and [authentication backend](./authentication/index.md)._ - -#### Kubernetes 4.30.0 - -_**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 set the following option in your PodSpec. Keeping in mind this example is for a Pod, not for -a Deployment, StatefulSet, or DaemonSet; you will need to adapt the `enableServiceLinks` option to fit into the relevant -location depending on your needs._ - -```yaml ---- -apiVersion: v1 -kind: Pod -metadata: -  name: authelia -spec: -  enableServiceLinks: false -... -``` - -### 4.25.0 - -The following changes occurred in 4.25.0: - -|Previous Key                                   |New Key                                        | -|:---------------------------------------------:|:---------------------------------------------:| -|authentication_backend.ldap.tls.skip_verify    |authentication_backend.ldap.tls.skip_verify    | -|authentication_backend.ldap.minimum_tls_version|authentication_backend.ldap.tls.minimum_version| -|notifier.smtp.disable_verify_cert              |notifier.smtp.tls.skip_verify                  | -|notifier.smtp.trusted_cert                     |certificates_directory                         | - -_**Please Note:** `certificates_directory` is not a direct replacement for the `notifier.smtp.trusted_cert`, instead -of being the path to a specific file it is a path to a directory containing certificates trusted by Authelia. This -affects other services like LDAP as well._ - -### 4.7.0 - -The following changes occurred in 4.7.0: - -|Previous Key|New Key  | -|:----------:|:-------:| -|logs_level  |log_level| -|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 -are using [4.30.0](#4.30.0) or newer instead of the new keys listed here._ diff --git a/docs/configuration/notifier/filesystem.md b/docs/configuration/notifier/filesystem.md deleted file mode 100644 index bb5123821..000000000 --- a/docs/configuration/notifier/filesystem.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -layout: default -title: Filesystem -parent: Notifier -grand_parent: Configuration -nav_order: 1 ---- - -# Filesystem - -With this configuration, the message will be sent to a file. This option should only be used for testing purposes. -This method will use the plain text email template for readability purposes. - -## Configuration - -```yaml -notifier: -  disable_startup_check: false -  filesystem: -    filename: /config/notification.txt -``` - -## Options - -### filename -<div markdown="1"> -type: string -{: .label .label-config .label-purple } -required: yes -{: .label .label-config .label-red } -</div> - -The file to add email text to. If it doesn't exist it will be created. diff --git a/docs/configuration/notifier/index.md b/docs/configuration/notifier/index.md deleted file mode 100644 index 92ac07e7c..000000000 --- a/docs/configuration/notifier/index.md +++ /dev/null @@ -1,97 +0,0 @@ ---- -layout: default -title: Notifier -parent: Configuration -nav_order: 8 -has_children: true ---- - -# Notifier - -**Authelia** sometimes needs to send messages to users in order to -verify their identity. - -## Configuration - -```yaml -notifier: -  disable_startup_check: false -  template_path: /path/to/templates/folder -  filesystem: {} -  smtp: {} -``` - -## Options - -### disable_startup_check -<div markdown="1"> -type: boolean -{: .label .label-config .label-purple } -default: false -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -The notifier has a startup check which validates the specified provider -configuration is correct and will be able to send emails. This can be -disabled with the `disable_startup_check` option: - -### template_path -<div markdown="1"> -type: string -{: .label .label-config .label-purple } -default: "" -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -This option allows the administrator to set a path where custom templates for notifications can be found. Each template -has two extensions; `.html` for HTML templates, and `.txt` for plaintext templates. - -|       Template       |                                           Description                                           | -|:--------------------:|:-----------------------------------------------------------------------------------------------:| -| IdentityVerification |                  Template used when registering devices or resetting passwords                  | -|    PasswordReset     | Template used to send the notification to users when their password has successfully been reset | - -For example, to modify the `IdentityVerification` HTML template, if your `template_path` was `/config/email_templates`, -you would create the `/config/email_templates/IdentityVerification.html` file. - -_**Note:** you may configure this directory and add only add the templates you wish to override, any templates not -supplied in this folder will utilize the default templates._ - - -In template files, you can use the following variables: - -|                Placeholder                |      Templates       |                                                                  Description                                                                  | -|:-----------------------------------------:|:--------------------:|:---------------------------------------------------------------------------------------------------------------------------------------------:| -|   `{% raw %}{{ .LinkURL }}{% endraw %}`   | IdentityVerification |                                          The URL of the used with the IdentityVerification template.                                          | -|  `{% raw %}{{ .LinkText }}{% endraw %}`   | IdentityVerification |                                 The display value for the IdentityVerification button intended for the link.                                  | -|    `{% raw %}{{ .Title }}{% endraw %}`    |         All          | A predefined title for the email. <br> It will be `"Reset your password"` or `"Password changed successfully"`, depending on the current step | -| `{% raw %}{{ .DisplayName }}{% endraw %}` |         All          |                                                     The name of the user, i.e. `John Doe`                                                     | -|  `{% raw %}{{ .RemoteIP }}{% endraw %}`   |         All          |                                           The remote IP address that initiated the request or event                                           | - -#### Examples - -This is a basic example: - -```html -<body> -  <h1>{{ .Title }}</h1> -  Hi {{ .DisplayName }}<br/> -  This email has been sent to you in order to validate your identity. -  Click <a href="{{ .LinkURL }}">here</a> to change your password. -</body> -``` - -Some Additional examples for specific purposes can be found in the -[examples directory on GitHub](https://github.com/authelia/authelia/tree/master/examples/templates/notifications). - -### filesystem - -The [filesystem](filesystem.md) provider. - -### smtp - -The [smtp](smtp.md) provider. diff --git a/docs/configuration/ntp.md b/docs/configuration/ntp.md deleted file mode 100644 index 20fbe34f9..000000000 --- a/docs/configuration/ntp.md +++ /dev/null @@ -1,91 +0,0 @@ ---- -layout: default -title: NTP -parent: Configuration -nav_order: 9 ---- - -# NTP - -Authelia has the ability to check the system time against an NTP server. Currently this only occurs at startup. This -section configures and tunes the settings for this check which is primarily used to ensure [TOTP](./one-time-password.md) -can be accurately validated. - -In the instance of inability to contact the NTP server Authelia will just log an error and will continue to run. - -## Configuration - -```yaml -ntp: -  address: "time.cloudflare.com:123" -  version: 3 -  max_desync: 3s -  disable_startup_check: false -  disable_failure: false -``` - -## Options - -### address -<div markdown="1"> -type: string -{: .label .label-config .label-purple }  -default: time.cloudflare.com:123 -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -Determines the address of the NTP server to retrieve the time from. The format is `<host>:<port>`, and both of these are -required. - -### version -<div markdown="1"> -type: integer -{: .label .label-config .label-purple }  -default: 4 -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -Determines the NTP verion supported. Valid values are 3 or 4. - -### max_desync -<div markdown="1"> -type: duration -{: .label .label-config .label-purple }  -default: 3s -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -This is used to tune the acceptable desync from the time reported from the NTP server. This uses our  -[duration notation](./index.md#duration-notation-format) format. - -### disable_startup_check -<div markdown="1"> -type: boolean -{: .label .label-config .label-purple }  -default: false -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -Setting this to true will disable the startup check entirely. - -### disable_failure -<div markdown="1"> -type: boolean -{: .label .label-config .label-purple }  -default: false -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -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 -in [max_desync](#max_desync) that Authelia fails to start and logs a fatal error.
\ No newline at end of file diff --git a/docs/configuration/password_policy.md b/docs/configuration/password_policy.md deleted file mode 100644 index d673e1bd6..000000000 --- a/docs/configuration/password_policy.md +++ /dev/null @@ -1,161 +0,0 @@ ---- -layout: default -title: Password Policy -parent: Configuration -nav_order: 18 ---- - -# Password Policy - -_Authelia_ allows administrators to configure an enforced password policy. - -## Configuration - -```yaml -password_policy: -  standard: -    enabled: false -    min_length: 8 -    max_length: 0 -    require_uppercase: false -    require_lowercase: false -    require_number: false -    require_special: false -  zxcvbn: -    enabled: false -    min_score: 3 -``` - -## Options - -### standard -<div markdown="1"> -type: list -{: .label .label-config .label-purple } -required: no -{: .label .label-config .label-green } -</div> - -This section allows you to enable standard security policies. - -#### enabled -<div markdown="1"> -type: boolean -{: .label .label-config .label-purple } -default: false -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -Enables standard password policy. - -#### min_length -<div markdown="1"> -type: integer -{: .label .label-config .label-purple } -default: 8 -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -Determines the minimum allowed password length. - -#### max_length -<div markdown="1"> -type: integer -{: .label .label-config .label-purple } -default: 0 -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -Determines the maximum allowed password length. - -#### require_uppercase -<div markdown="1"> -type: boolean -{: .label .label-config .label-purple } -default: false -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -Indicates that at least one UPPERCASE letter must be provided as part of the password. - -#### require_lowercase -<div markdown="1"> -type: boolean -{: .label .label-config .label-purple } -default: false -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -Indicates that at least one lowercase letter must be provided as part of the password. - -#### require_number -<div markdown="1"> -type: boolean -{: .label .label-config .label-purple } -default: false -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -Indicates that at least one number must be provided as part of the password. - -#### require_special -<div markdown="1"> -type: boolean -{: .label .label-config .label-purple } -default: false -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -Indicates that at least one special character must be provided as part of the password. - -### zxcvbn - -This password policy enables advanced password strength metering, using [zxcvbn](https://github.com/dropbox/zxcvbn). - -#### enabled -<div markdown="1"> -type: boolean -{: .label .label-config .label-purple } -default: false -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -_**Important Note:** only one password policy can be applied at a time._ - -Enables zxcvbn password policy. - -#### min_score -<div markdown="1"> -type: integer -{: .label .label-config .label-purple } -default: 3 -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -Configures the minimum zxcvbn score allowed for new passwords. There are 5 levels in the zxcvbn score system (taken from [github.com/dropbox/zxcvbn](https://github.com/dropbox/zxcvbn#usage)): - -- score 0: too guessable: risky password (guesses < 10^3) -- score 1: very guessable: protection from throttled online attacks (guesses < 10^6) -- score 2: somewhat guessable: protection from unthrottled online attacks. (guesses < 10^8) -- score 3: safely unguessable: moderate protection from offline slow-hash scenario. (guesses < 10^10) -- score 4: very unguessable: strong protection from offline slow-hash scenario. (guesses >= 10^10) - -We do not allow score 0, if you set the `min_score` value to 0 instead the default will be chosen.
\ No newline at end of file diff --git a/docs/configuration/regulation.md b/docs/configuration/regulation.md deleted file mode 100644 index 5f3815fc1..000000000 --- a/docs/configuration/regulation.md +++ /dev/null @@ -1,61 +0,0 @@ ---- -layout: default -title: Regulation -parent: Configuration -nav_order: 10 ---- - -# Regulation - -**Authelia** can temporarily ban accounts when there are too many -authentication attempts. This helps prevent brute-force attacks. - -## Configuration - -```yaml -regulation: -  max_retries: 3 -  find_time: 2m -  ban_time: 5m -``` - -## Options - -### max_retries -<div markdown="1"> -type: integer  -{: .label .label-config .label-purple }  -default: 3 -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -The number of failed login attempts before a user may be banned. Setting this option to 0 disables regulation entirely. - -### find_time -<div markdown="1"> -type: string (duration)  -{: .label .label-config .label-purple }  -default: 2m -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -The period of time in [duration notation format](index.md#duration-notation-format) analyzed for failed attempts. For -example if you set `max_retries` to 3 and `find_time` to `2m` this means the user must have 3 failed logins in -2 minutes. - -### ban_time -<div markdown="1"> -type: string (duration)  -{: .label .label-config .label-purple }  -default: 5m -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -The period of time in [duration notation format](index.md#duration-notation-format) the user is banned for after meeting -the `max_retries` and `find_time` configuration. After this duration the account will be able to login again. diff --git a/docs/configuration/server.md b/docs/configuration/server.md deleted file mode 100644 index adf33dfb6..000000000 --- a/docs/configuration/server.md +++ /dev/null @@ -1,300 +0,0 @@ ---- -layout: default -title: Server -parent: Configuration -nav_order: 12 ---- - -# Server - -The server section configures and tunes the http server module Authelia uses. - -## Configuration - -```yaml -server: -  host: 0.0.0.0 -  port: 9091 -  path: "" -  read_buffer_size: 4096 -  write_buffer_size: 4096 -  enable_pprof: false -  enable_expvars: false -  disable_healthcheck: false -  tls: -    key: "" -    certificate: "" -    client_certificates: [] -  headers: -    csp_template: "" -``` - -## Options - -## host -<div markdown="1"> -type: string -{: .label .label-config .label-purple }  -default: 0.0.0.0 -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -Defines the address to listen on. See also [port](#port). Should typically be `0.0.0.0` or `127.0.0.1`, the former for -containerized environments and the later for daemonized environments like init.d and systemd. - -Note: If utilising an IPv6 literal address it must be enclosed by square brackets and quoted: - -```yaml -host: "[fd00:1111:2222:3333::1]" -``` - -### port -<div markdown="1"> -type: integer -{: .label .label-config .label-purple }  -default: 9091 -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -Defines the port to listen on. See also [host](#host). - -### path -<div markdown="1"> -type: string  -{: .label .label-config .label-purple }  -default: "" -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -Authelia by default is served from the root `/` location, either via its own domain or subdomain. - -Modifying this setting will allow you to serve Authelia out from a specified base path. Please note -that currently only a single level path is supported meaning slashes are not allowed, and only -alphanumeric characters are supported. - -Example: https://auth.example.com/, https://example.com/ -```yaml -server: -  path: "" -``` - -Example: https://auth.example.com/authelia/, https://example.com/authelia/ -```yaml -server: -  path: authelia -``` - -### asset_path -<div markdown="1"> -type: string  -{: .label .label-config .label-purple }  -default: "" -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -Authelia by default serves all static assets from an embedded filesystem in the Go binary. - -Modifying this setting will allow you to override and serve specific assets for Authelia from a specified path. -All files that can be overridden are documented below and must be placed in the `asset_path` with a flat file structure. - -Example: -```console -/config/assets/ -├── favicon.ico -├── logo.png -└── locales/<lang>[-[variant]]/<namespace>.json -``` - -|  Asset  |   File name   | -|:-------:|:-------------:| -| Favicon |  favicon.ico  | -|  Logo   |   logo.png    | -| locales | see [locales] | - -### read_buffer_size -<div markdown="1"> -type: integer  -{: .label .label-config .label-purple }  -default: 4096 -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -Configures the maximum request size. The default of 4096 is generally sufficient for most use cases. - -### write_buffer_size -<div markdown="1"> -type: integer  -{: .label .label-config .label-purple }  -default: 4096 -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -Configures the maximum response size. The default of 4096 is generally sufficient for most use cases. - -### enable_pprof -<div markdown="1"> -type: boolean -{: .label .label-config .label-purple }  -default: false -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -Enables the go pprof endpoints. - -### enable_expvars -<div markdown="1"> -type: boolean -{: .label .label-config .label-purple }  -default: false -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -Enables the go expvars endpoints. - -### disable_healthcheck -<div markdown="1"> -type: boolean -{: .label .label-config .label-purple }  -default: false -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -On startup Authelia checks for the existence of /app/healthcheck.sh and /app/.healthcheck.env and if both of these exist -it writes the configuration vars for the healthcheck to the /app/.healthcheck.env file. In instances where this is not -desirable it's possible to disable these interactions entirely. - -An example situation where this is the case is in Kubernetes when set security policies that prevent writing to the -ephemeral storage of a container or just don't want to enable the internal health check. - -### tls - -Authelia typically listens for plain unencrypted connections. This is by design as most environments allow to -security on lower areas of the OSI model. However it required, if you specify both the [tls key](#key) and  -[tls certificate](#certificate) options, Authelia will listen for TLS connections. - -#### key -<div markdown="1"> -type: string (path) -{: .label .label-config .label-purple }  -default: "" -{: .label .label-config .label-blue } -required: situational -{: .label .label-config .label-yellow } -</div> - -The path to the private key for TLS connections. Must be in DER base64/PEM format. - -#### certificate -<div markdown="1"> -type: string (path) -{: .label .label-config .label-purple }  -default: "" -{: .label .label-config .label-blue } -required: situational -{: .label .label-config .label-yellow } -</div> - -The path to the public certificate for TLS connections. Must be in DER base64/PEM format. - -#### client_certificates -<div markdown="1"> -type: list(string) -{: .label .label-config .label-purple } -default: [] -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-yellow } -</div> - -The list of file paths to certificates used for authenticating clients. Those certificates can be root -or intermediate certificates. If no item is provided mutual TLS is disabled. - - -### headers - -#### csp_template -<div markdown="1"> -type: string -{: .label .label-config .label-purple }  -default: "" -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -This customizes the value of the Content-Security-Policy header. It will replace all instances of `${NONCE}` with the  -nonce value of the Authelia react bundle. This is an advanced option to customize and you should do sufficient research  -about how browsers utilize and understand this header before attempting to customize it. - -For example, the default CSP template is `default-src 'self'; object-src 'none'; style-src 'self' 'nonce-${NONCE}'`. - -## Additional Notes - -### Buffer Sizes - -The read and write buffer sizes generally should be the same. This is because when Authelia verifies -if the user is authorized to visit a URL, it also sends back nearly the same size response as the request. However -you're able to tune these individually depending on your needs. - -### Asset Overrides - -If replacing the Logo for your Authelia portal it is recommended to upload a transparent PNG of your desired logo. -Authelia will automatically resize the logo to an appropriate size to present in the frontend. - -#### locales - -The locales folder holds folders of internationalization locales. This folder can be utilized to override these locales. -They are the names of locales that are returned by the `navigator.langauge` ECMAScript command. These are generally -those in the [RFC5646 / BCP47 Format](https://datatracker.ietf.org/doc/html/rfc5646) specifically the language codes -from [Crowdin](https://support.crowdin.com/api/language-codes/). - -Each directory has json files which you can explore the format of in the -[internal/server/locales](https://github.com/authelia/authelia/tree/master/internal/server/locales) directory on -GitHub. The important part is the key names you wish to override. Each file represents a translation namespace. The list -of current namespaces are below: - -| Namespace |       Purpose       | -|:---------:|:-------------------:| -|  portal   | Portal translations | - -A full example for the `en-US` locale for the portal namespace is `locales/en-US/portal.json`. - -Languages in browsers are supported in two forms. In their language only form such as `en` for English, and in their -variant form such as `en-AU` for English (Australian). If a user has the browser language `en-AU` we automatically load -the `en` and `en-AU` languages, where any keys in the `en-AU` language take precedence over the `en` language, and the -translations for the `en` language only applying when a translation from `en-AU` is not available. - -List of supported languages and variants: - -| Description | Language | Additional Variants |        Location        | -|:-----------:|:--------:|:-------------------:|:----------------------:| -|   English   |    en    |         N/A         | locales/en/portal.json | -|   Spanish   |    es    |         N/A         | locales/es/portal.json | -|   German    |    de    |         N/A         | locales/de/portal.json | - -_**Important Note** Currently users can only override languages that already exist in this list either by overriding -the language itself, or adding a variant form of that language. If you'd like support for another language feel free -to make a PR. We also encourage people to make PR's for variants where the difference in the variants is important._ - -_**Important Note** Overriding these files will not guarantee any form of stability. Users who planning to utilize these -overrides should either check for changes to the files in the  -[en](https://github.com/authelia/authelia/tree/master/internal/server/locales/en) translation prior to upgrading or PR  -their translation to ensure it is maintained._
\ No newline at end of file diff --git a/docs/configuration/session/index.md b/docs/configuration/session/index.md deleted file mode 100644 index b555d0c42..000000000 --- a/docs/configuration/session/index.md +++ /dev/null @@ -1,147 +0,0 @@ ---- -layout: default -title: Session -parent: Configuration -nav_order: 13 -has_children: true ---- - -# Session - -**Authelia** relies on session cookies to authenticate users. When the user visits -a website of the protected domain `example.com` for the first time, Authelia detects -that there is no cookie for that user. Consequently, Authelia redirects the user -to the login portal through which the user should authenticate to get a cookie which -is valid for `*.example.com`, meaning all websites of the domain. -At the next request, Authelia receives the cookie associated to the authenticated user -and can then order the reverse proxy to let the request pass through to the application. - -## Configuration - -```yaml -session: -  name: authelia_session -  domain: example.com -  same_site: lax -  secret: unsecure_session_secret -  expiration: 1h -  inactivity: 5m -  remember_me_duration:  1M -``` - -## Providers - -There are currently two providers for session storage (three if you count Redis Sentinel as a separate provider): -* Memory (default, stateful, no additional configuration) -* [Redis](./redis.md) (stateless). -* [Redis Sentinel](./redis.md#high_availability) (stateless, highly available). - -### Kubernetes or High Availability - -It's important to note when picking a provider, the stateful providers are not recommended in High Availability -scenarios like Kubernetes. Each provider has a note beside it indicating it is *stateful* or *stateless* the stateless -providers are recommended. - -## Options - -### name -<div markdown="1"> -type: string -{: .label .label-config .label-purple } -default: authelia_session -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -The name of the session cookie. By default this is set to authelia_session. It's mostly useful to change this if you are -doing development or running multiple instances of Authelia. - -### domain -<div markdown="1"> -type: string -{: .label .label-config .label-purple } -required: yes -{: .label .label-config .label-red } -</div> - -The domain the cookie is assigned to protect. This must be the same as the domain Authelia is served on or the root -of the domain. For example if listening on auth.example.com the cookie should be auth.example.com or example.com. - -### same_site -<div markdown="1"> -type: string -{: .label .label-config .label-purple } -default: lax -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -Sets the cookies SameSite value. Prior to offering the configuration choice this defaulted to None. The new default is -Lax. This option is defined in lower-case. So for example if you want to set it to `Strict`, the value in configuration -needs to be `strict`. - -You can read about the SameSite cookie in detail on the  -[MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite). In short setting SameSite to Lax -is generally the most desirable option for Authelia. None is not recommended unless you absolutely know what you're -doing and trust all the protected apps. Strict is not going to work in many use cases and we have not tested it in this -state but it's available as an option anyway. - -### secret -<div markdown="1"> -type: string -{: .label .label-config .label-purple } -required: yes -{: .label .label-config .label-red } -</div> - -The secret key used to encrypt session data in Redis. It's recommended this is set using a [secret](../secrets.md). - -### expiration -<div markdown="1"> -type: string (duration) -{: .label .label-config .label-purple } -default: 1h -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -The time in [duration notation format](../index.md#duration-notation-format) before the cookie expires and the session -is destroyed. This is overriden by remember_me_duration when the remember me box is checked. - -### inactivity -<div markdown="1"> -type: string (duration) -{: .label .label-config .label-purple } -default: 5m -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -The time in [duration notation format](../index.md#duration-notation-format) the user can be inactive for until the -session is destroyed. Useful if you want long session timers but don't want unused devices to be vulnerable. - -### remember_me_duration -<div markdown="1"> -type: string (duration) -{: .label .label-config .label-purple } -default: 1M -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -The time in [duration notation format](../index.md#duration-notation-format) the cookie expires and the session is -destroyed when the remember me box is checked. Setting this to `-1` disables this feature entirely. - -## Security - -Configuration of this section has an impact on security. You should read notes in -[security measures](../../security/measures.md#session-security) for more information. - -## Loading a password from a secret instead of inside the configuration - -Password can also be defined using a [secret](../secrets.md). diff --git a/docs/configuration/storage/index.md b/docs/configuration/storage/index.md deleted file mode 100644 index 4b6caae8e..000000000 --- a/docs/configuration/storage/index.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -layout: default -title: Storage Backends -parent: Configuration -nav_order: 14 -has_children: true ---- - -**Authelia** supports multiple storage backends. The backend is used to store user preferences, 2FA device handles and  -secrets, authentication logs, etc... - -The available storage backends are listed in the table of contents below. - -## Configuration - -```yaml -storage: -  encryption_key: a_very_important_secret -  local: {} -  mysql: {} -  postgres: {} -``` - -## Options - -### encryption_key -<div markdown="1"> -type: string -{: .label .label-config .label-purple } -required: yes -{: .label .label-config .label-red } -</div> - -The encryption key used to encrypt data in the database. We encrypt data by creating a sha256 checksum of the provided  -value, and use that to encrypt the data with the AES-GCM 256bit algorithm. - -The minimum length of this key is 20 characters, however we generally recommend above 64 characters. - -See [securty measures](../../security/measures.md#storage-security-measures) for more information. - -### local -See [SQLite](./sqlite.md). - -### mysql -See [MySQL](./mysql.md). - -### postgres -See [PostgreSQL](./postgres.md).
\ No newline at end of file diff --git a/docs/configuration/storage/mariadb.md b/docs/configuration/storage/mariadb.md deleted file mode 100644 index 8756e6b3c..000000000 --- a/docs/configuration/storage/mariadb.md +++ /dev/null @@ -1,114 +0,0 @@ ---- -layout: default -title: MariaDB -parent: Storage Backends -grand_parent: Configuration -nav_order: 1 ---- - -# MariaDB - -The MySQL storage provider also serves as a MariaDB provider. - -## Version support - -We recommend using the latest version of MariaDB that is officially supported by the MariaDB developers. We also suggest -checking out [PostgreSQL](postgres.md) as an alternative. - -The oldest version of MariaDB that has been tested is 10.6. If using 10.6 you may be required to adjust the  -`explicit_defaults_for_timestamp` setting. This will be evident when the container starts with an error similar to -`Error 1067: Invalid default value for 'exp'`. You can adjust this setting in the mysql.cnf file like so: - -```cnf -[mysqld] -explicit_defaults_for_timestamp = 1 -``` - -## Configuration - -```yaml -storage: -  encryption_key: a_very_important_secret -  mysql: -    host: 127.0.0.1 -    port: 3306 -    database: authelia -    username: authelia -    password: mypassword -``` - -## Options - -### encryption_key -See the [encryption_key docs](./index.md#encryption_key). - -### host -<div markdown="1"> -type: string -{: .label .label-config .label-purple }  -required: yes -{: .label .label-config .label-red } -</div> - -The database server host. - -If utilising an IPv6 literal address it must be enclosed by square brackets and quoted: -```yaml -host: "[fd00:1111:2222:3333::1]" -``` - -### port -<div markdown="1"> -type: integer -{: .label .label-config .label-purple }  -default: 3306 -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -The port the database server is listening on. - -### database -<div markdown="1"> -type: string -{: .label .label-config .label-purple } -required: yes -{: .label .label-config .label-red } -</div> - -The database name on the database server that the assigned [user](#username) has access to for the purpose of -**Authelia**. - -### username -<div markdown="1"> -type: string -{: .label .label-config .label-purple } -required: yes -{: .label .label-config .label-red } -</div> - -The username paired with the password used to connect to the database. - -### password -<div markdown="1"> -type: string -{: .label .label-config .label-purple } -required: yes -{: .label .label-config .label-red } -</div> - -The password paired with the username used to connect to the database. Can also be defined using a -[secret](../secrets.md) which is also the recommended way when running as a container. - -### timeout -<div markdown="1"> -type: duration -{: .label .label-config .label-purple } -default: 5s -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -The SQL connection timeout. diff --git a/docs/configuration/storage/mysql.md b/docs/configuration/storage/mysql.md deleted file mode 100644 index b76874a85..000000000 --- a/docs/configuration/storage/mysql.md +++ /dev/null @@ -1,117 +0,0 @@ ---- -layout: default -title: MySQL -parent: Storage Backends -grand_parent: Configuration -nav_order: 2 ---- - -# MySQL - -The MySQL storage provider. - -## Version support - -We recommend using the latest version of MySQL that is officially supported by the MySQL developers. We also suggest -checking out [PostgreSQL](postgres.md) as an alternative. - -The oldest version of MySQL that has been tested is 5.7. If using 5.7 you may be required to adjust the -`explicit_defaults_for_timestamp` setting. This will be evident when the container starts with an error similar to -`Error 1067: Invalid default value for 'exp'`. You can adjust this setting in the mysql.cnf file like so: - -```cnf -[mysqld] -explicit_defaults_for_timestamp = 1 -``` - -## Configuration - -```yaml -storage: -  encryption_key: a_very_important_secret -  mysql: -    host: 127.0.0.1 -    port: 3306 -    database: authelia -    username: authelia -    password: mypassword -    timeout: 5s -``` - -## Options - -### encryption_key -See the [encryption_key docs](./index.md#encryption_key). - -### host -<div markdown="1"> -type: string -{: .label .label-config .label-purple }  -default: localhost -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -The database server host. - -If utilising an IPv6 literal address it must be enclosed by square brackets and quoted: -```yaml -host: "[fd00:1111:2222:3333::1]" -``` - -### port -<div markdown="1"> -type: integer -{: .label .label-config .label-purple }  -default: 3306 -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -The port the database server is listening on. - -### database -<div markdown="1"> -type: string -{: .label .label-config .label-purple } -required: yes -{: .label .label-config .label-red } -</div> - -The database name on the database server that the assigned [user](#username) has access to for the purpose of -**Authelia**. - -### username -<div markdown="1"> -type: string -{: .label .label-config .label-purple } -required: yes -{: .label .label-config .label-red } -</div> - -The username paired with the password used to connect to the database. - -### password -<div markdown="1"> -type: string -{: .label .label-config .label-purple } -required: yes -{: .label .label-config .label-red } -</div> - -The password paired with the username used to connect to the database. Can also be defined using a -[secret](../secrets.md) which is also the recommended way when running as a container. - -### timeout -<div markdown="1"> -type: duration -{: .label .label-config .label-purple } -default: 5s -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -The SQL connection timeout. diff --git a/docs/configuration/storage/postgres.md b/docs/configuration/storage/postgres.md deleted file mode 100644 index 3e2404013..000000000 --- a/docs/configuration/storage/postgres.md +++ /dev/null @@ -1,180 +0,0 @@ ---- -layout: default -title: PostgreSQL -parent: Storage Backends -grand_parent: Configuration -nav_order: 3 ---- - -# PostgreSQL - -The PostgreSQL storage provider. - -## Version support - -See [PostgreSQL support](https://www.postgresql.org/support/versioning/) for the versions supported by PostgreSQL. We -recommend the _current minor_ version of one of the versions supported by PostgreSQL. - -The versions of PostgreSQL that should be supported by Authelia are: -- 14 -- 13 -- 12 -- 11 -- 10 -- 9.6 - -## Configuration - -```yaml -storage: -  encryption_key: a_very_important_secret -  postgres: -    host: 127.0.0.1 -    port: 5432 -    database: authelia -    schema: public -    username: authelia -    password: mypassword -    ssl: -      mode: disable -      root_certificate: /path/to/root_cert.pem -      certificate: /path/to/cert.pem -      key: /path/to/key.pem -``` - -## Options - -### encryption_key -See the [encryption_key docs](./index.md#encryption_key). - -### host -<div markdown="1"> -type: string -{: .label .label-config .label-purple }  -required: yes -{: .label .label-config .label-red } -</div> - -The database server host. - -If utilising an IPv6 literal address it must be enclosed by square brackets and quoted: -```yaml -host: "[fd00:1111:2222:3333::1]" -``` - -### port -<div markdown="1"> -type: integer -{: .label .label-config .label-purple }  -default: 5432 -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -The port the database server is listening on. - -### database -<div markdown="1"> -type: string -{: .label .label-config .label-purple } -required: yes -{: .label .label-config .label-red } -</div> - -The database name on the database server that the assigned [user](#username) has access to for the purpose of -**Authelia**. - -### schema -<div markdown="1"> -type: string -{: .label .label-config .label-purple }  -default: public -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -The database schema name to use on the database server that the assigned [user](#username) has access to for the purpose -of **Authelia**. By default this is the public schema. - -### username -<div markdown="1"> -type: string -{: .label .label-config .label-purple } -required: yes -{: .label .label-config .label-red } -</div> - -The username paired with the password used to connect to the database. - -### password -<div markdown="1"> -type: string -{: .label .label-config .label-purple } -required: yes -{: .label .label-config .label-red } -</div> - -The password paired with the username used to connect to the database. Can also be defined using a -[secret](../secrets.md) which is also the recommended way when running as a container. - -### timeout -<div markdown="1"> -type: duration -{: .label .label-config .label-purple } -default: 5s -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -The SQL connection timeout. - -### ssl - -#### mode -<div markdown="1"> -type: string -{: .label .label-config .label-purple } -default: disable -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -SSL mode configures how to handle SSL connections with Postgres. -Valid options are 'disable', 'require', 'verify-ca', or 'verify-full'. -See the [PostgreSQL Documentation](https://www.postgresql.org/docs/12/libpq-ssl.html) -or [pgx - PostgreSQL Driver and Toolkit Documentation](https://pkg.go.dev/github.com/jackc/pgx?tab=doc) -for more information. - -#### root_certificate -<div markdown="1"> -type: string -{: .label .label-config .label-purple } -required: no -{: .label .label-config .label-green } -</div> - -The optional location of the root certificate file encoded in the PEM format for validation purposes. - -#### certificate -<div markdown="1"> -type: string -{: .label .label-config .label-purple } -required: no -{: .label .label-config .label-green } -</div> - -The optional location of the certificate file encoded in the PEM format for validation purposes. - -#### key -<div markdown="1"> -type: string -{: .label .label-config .label-purple } -required: no -{: .label .label-config .label-green } -</div> - -The optional location of the key file encoded in the PEM format for authentication purposes. diff --git a/docs/configuration/storage/sqlite.md b/docs/configuration/storage/sqlite.md deleted file mode 100644 index 5d31d1c97..000000000 --- a/docs/configuration/storage/sqlite.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -layout: default -title: SQLite -parent: Storage Backends -grand_parent: Configuration -nav_order: 4 ---- - -# SQLite - -If you don't have a SQL server, you can use [SQLite](https://en.wikipedia.org/wiki/SQLite). -However please note that this setup will prevent you from running multiple -instances of Authelia since the database will be a local file. - -Use of this storage provider leaves Authelia [stateful](../../features/statelessness.md). It's important in highly -available scenarios to use one of the other providers, and we highly recommend it in production environments, but this -requires you setup an external database such as [PostgreSQL](postgres.md). - -## Configuration - -```yaml -storage: -  encryption_key: a_very_important_secret -  local: -    path: /config/db.sqlite3 -``` - -## Options - -### encryption_key -See the [encryption_key docs](./index.md#encryption_key). - -### path -<div markdown="1"> -type: string -{: .label .label-config .label-blue } -required: yes -{: .label .label-config .label-red } -</div> - -The path where the SQLite3 database file will be stored. It will be created if the file does not exist. diff --git a/docs/configuration/theme.md b/docs/configuration/theme.md deleted file mode 100644 index 58ff93bc7..000000000 --- a/docs/configuration/theme.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -layout: default -title: Theme -parent: Configuration -nav_order: 15 ---- - -# Theme - -The theme section configures the theme and style Authelia uses. - -## Configuration - -```yaml -theme: light -``` - -## Options - -### theme -<div markdown="1"> -type: string  -{: .label .label-config .label-purple }  -default: light -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -There are currently 3 available themes for Authelia: -* light (default) -* dark -* grey - -To enable automatic switching between themes, you can set `theme` to `auto`. The theme will be set to either `dark` or `light` depending on the user's system preference which is determined using media queries. To read more technical details about the media queries used, read the [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme). diff --git a/docs/content/en/_index.md b/docs/content/en/_index.md new file mode 100644 index 000000000..19273aca8 --- /dev/null +++ b/docs/content/en/_index.md @@ -0,0 +1,8 @@ +--- +title : "Authelia" +description: "Authelia is an open-source authentication and authorization server and portal fulfilling the identity and access management (IAM) role of information security in providing multi-factor authentication and single sign-on (SSO) for your applications via a web portal. It acts as a companion for common reverse proxies." +lead: "Authelia is an open-source <a href=\"./overview/authentication/introduction/\">authentication</a> and <a href=\"./overview/authorization/access-control/\">authorization</a> server and portal fulfilling the identity and access management (IAM) role of information security in providing <a href=\"./overview/authentication/introduction/\">multi-factor authentication</a> and single sign-on (SSO) for your applications via a web portal. It acts as a companion for <a href=\"./overview/prologue/supported-proxies/\">common reverse proxies</a>." +date: 2020-04-15T15:48:16+02:00 +draft: false +images: [] +--- diff --git a/docs/content/en/blog/_index.md b/docs/content/en/blog/_index.md new file mode 100644 index 000000000..0970d63d1 --- /dev/null +++ b/docs/content/en/blog/_index.md @@ -0,0 +1,7 @@ +--- +title: "Blog" +description: "The Authelia Blog." +date: 2020-04-15T15:48:16+02:00 +draft: false +images: [] +--- diff --git a/docs/content/en/blog/say-hello-to-the-new-website/index.md b/docs/content/en/blog/say-hello-to-the-new-website/index.md new file mode 100644 index 000000000..802bb6df0 --- /dev/null +++ b/docs/content/en/blog/say-hello-to-the-new-website/index.md @@ -0,0 +1,44 @@ +--- +title: "Say hello to the new website 👋" +description: "Introducing the new website" +lead: "Introducing the new website" +date: 2022-03-20T12:52:27+11:00 +draft: false +contributors: ["James Elliott"] +--- + +We're pleased to have you take a look at our new website. It combines both the main landing site and the documentation +all in one neat package. The website is using a [Hugo] theme called [Doks]. + +This does change the development process for documentation slightly compared to what it was previously. However most of +the changes will make it easier for most documentation contributors. This process is documented in the +[Documentation Contributing] section. We will also be looking towards making all +documentation changes getting quickly published to a staging site so they can quickly be seen by the maintainers and +anyone else *too lazy* to follow the steps in the [Documentation Contributing] section command and check it out locally. + +As part of this redesign we've taken the time to rewrite and reorganize key sections of the documentation. This may +result in some links not working, however we've aimed to temporarily redirect links that previously worked to reduce the +number of visitors being presented a 404. + +In particular, you will see improvements in the following areas: + +* The integration documentation is a new area which replaces the deployment documentation: +  * There are several additional proxies +  * There are several additional deployment scenarios +  * It's much better organized +  * There are lots of additional links to additional resources to help people find the configuration that suits them +  * Several of the proxy configurations have been refreshed to make them more modern +  * Some additional docs for k8s now exist +* The roadmap is now heavily documented with stages for areas which require it +* Many areas previously located in the configuration docs have moved into integration docs as that's a more appropriate +  area +* The contribution docs have been slightly tidied up + +You may have also noticed we launched a new blog! This blog will be used to communicate key things about the future of +Authelia as well as key things we believe the Authelia community needs to know about. You can subscribe to this blog +via the [RSS Feed](https://www.authelia.com/blog/index.xml). We may introduce a mail list for the blog sometime in the +future. + +[Hugo]: https://gohugo.io/ +[Doks]: https://getdoks.org/ +[Documentation Contributing]: ../../contributing/prologue/documentation.md diff --git a/docs/content/en/configuration/_index.md b/docs/content/en/configuration/_index.md new file mode 100644 index 000000000..528a84bc4 --- /dev/null +++ b/docs/content/en/configuration/_index.md @@ -0,0 +1,8 @@ +--- +title : "Configuration" +description: "Configuration Docs" +lead: "" +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +--- diff --git a/docs/content/en/configuration/first-factor/_index.md b/docs/content/en/configuration/first-factor/_index.md new file mode 100644 index 000000000..e8e8032c2 --- /dev/null +++ b/docs/content/en/configuration/first-factor/_index.md @@ -0,0 +1,9 @@ +--- +title : "First Factor" +description: "First Factor methods configuration" +lead: "" +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +weight: 102000 +--- diff --git a/docs/content/en/configuration/first-factor/file.md b/docs/content/en/configuration/first-factor/file.md new file mode 100644 index 000000000..c419fdd29 --- /dev/null +++ b/docs/content/en/configuration/first-factor/file.md @@ -0,0 +1,115 @@ +--- +title: "File" +description: "File" +lead: "Authelia supports a file based first factor user provider. This section describes configuring this." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  configuration: +    parent: "first-factor" +weight: 102300 +toc: true +aliases: +  - /docs/configuration/authentication/file.html +--- + +## Configuration + +```yaml +authentication_backend: +  disable_reset_password: false +  file: +    path: /config/users.yml +    password: +      algorithm: argon2id +      iterations: 3 +      key_length: 32 +      salt_length: 16 +      parallelism: 4 +      memory: 64 +``` + +## Options + +### path + +{{< confkey type="string" required="yes" >}} + +The path to the file with the user details list. Supported file types are: + +* [YAML File](../../reference/guides/passwords.md#yaml-format) + +### password + +#### algorithm + +{{< confkey type="string" default="argon2id" required="no" >}} + +Controls the hashing algorithm used for hashing new passwords. Value must be one of: + +* `argon2id` for the [Argon2] `id` variant +* `sha512` for the [SHA Crypt] `SHA512` variant + +#### iterations + +{{< confkey type="integer" required="no" >}} + +Controls the number of hashing iterations done by the other hashing settings ([Argon2] parameter `t`, [SHA Crypt] +parameter `rounds`). This affects the effective cost of hashing. + +| Algorithm | Minimum | Default |                                        Recommended                                         | +|:---------:|:-------:|:-------:|:------------------------------------------------------------------------------------------:| +| argon2id  |    1    |    3    | [See Recommendations](../../reference/guides/passwords.md#recommended-parameters-argon2id) | +|  sha512   |  1000   |  50000  |  [See Recommendations](../../reference/guides/passwords.md#recommended-parameters-sha512)  | + +#### key_length + +{{< confkey type="integer" default="32" required="no" >}} + +*__Important:__ This setting is specific to the `argon2id` algorithm and unused with the `sha512` algorithm.* + +Sets the key length of the [Argon2] hash output. The minimum value is `16` with the recommended value of `32` being set +as the default. + +#### salt_length + +{{< confkey type="integer" default="16" required="no" >}} + +Controls the length of the random salt added to each password before hashing. There is not a compelling reason to have +this set to anything other than `16`, however the minimum is `8` with the recommended value of `16` being set as the +default. + +#### parallelism + +{{< confkey type="integer" default="4" required="no" >}} + +*__Important:__ This setting is specific to the `argon2id` algorithm and unused with the `sha512` algorithm.* + +Sets the number of threads used by [Argon2] when hashing passwords ([Argon2] parameter `p`). The minimum value is `1` +with the recommended value of `4` being set as the default. This affects the effective cost of hashing. + +#### memory + +{{< confkey type="integer" default="64" required="no" >}} + +*__Important:__ This setting is specific to the `argon2id` algorithm and unused with the `sha512` algorithm.* + +Sets the amount of memory in megabytes allocated to a single password hashing calculation ([Argon2] parameter `m`). This +affects the effective cost of hashing. + +This memory is released by go after the hashing process completes, however the operating system may not reclaim the +memory until a later time such as when the system is experiencing memory pressure which may cause the appearance of more +memory being in use than Authelia is actually actively using. Authelia will typically reuse this memory if it has not be +reclaimed as long as another hashing calculation is not still utilizing it. + +## Reference + +A [reference guide](../../reference/guides/passwords.md) exists specifically for choosing password hashing values. This +section contains far more information than is practical to include in this configuration document. See the +[Passwords Reference Guide](../../reference/guides/passwords.md) for more information. + +This guide contains examples such as the [User / Password File](../../reference/guides/passwords.md#user--password-file). + +[Argon2]: https://www.rfc-editor.org/rfc/rfc9106.html +[SHA Crypt]: https://www.akkadia.org/drepper/SHA-crypt.txt diff --git a/docs/content/en/configuration/first-factor/introduction.md b/docs/content/en/configuration/first-factor/introduction.md new file mode 100644 index 000000000..2800d3c9c --- /dev/null +++ b/docs/content/en/configuration/first-factor/introduction.md @@ -0,0 +1,70 @@ +--- +title: "First Factor" +description: "Configuring Authelia First Factor Authentication." +lead: "Authelia uses a username and password for a first factor method. This section describes configuring this." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  configuration: +    parent: "first-factor" +weight: 102100 +toc: true +aliases: +  - /c/1fa +  - /docs/configuration/authentication/ +--- + +There are two ways to integrate *Authelia* with an authentication backend: + +* [LDAP](ldap.md): users are stored in remote servers like [OpenLDAP], [OpenDJ], [FreeIPA], or +  [Microsoft Active Directory]. +* [File](file.md): users are stored in [YAML] file with a hashed version of their password. + +## Configuration + +```yaml +authentication_backend: +  refresh_interval: 5m +  disable_reset_password: false +  password_reset: +    custom_url: "" +``` + +## Options + +### refresh_interval + +{{< confkey type="duration" default="5m" required="no" >}} + +This setting controls the interval at which details are refreshed from the backend. Particularly useful for +[LDAP](#ldap). + +### disable_reset_password + +{{< confkey type="boolean" default="false" required="no" >}} + +This setting controls if users can reset their password from the web frontend or not. + +### password_reset + +#### custom_url + +{{< confkey type="string" required="no" >}} + +The custom password reset URL. This replaces the inbuilt password reset functionality and disables the endpoints if +this is configured to anything other than nothing or an empty string. + +### file + +The [file](file.md) authentication provider. + +### ldap + +The [LDAP](ldap.md) authentication provider. + +[OpenLDAP]: https://www.openldap.org/ +[OpenDJ]: https://www.openidentityplatform.org/opendj +[FreeIPA]: https://www.freeipa.org/ +[Microsoft Active Directory]: https://docs.microsoft.com/en-us/windows-server/identity/ad-ds/ad-ds-getting-started +[YAML]: https://yaml.org/ diff --git a/docs/content/en/configuration/first-factor/ldap.md b/docs/content/en/configuration/first-factor/ldap.md new file mode 100644 index 000000000..496f3a338 --- /dev/null +++ b/docs/content/en/configuration/first-factor/ldap.md @@ -0,0 +1,279 @@ +--- +title: "LDAP" +description: "Configuring LDAP" +lead: "Authelia supports an LDAP server based first factor user provider. This section describes configuring this." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  configuration: +    parent: "first-factor" +weight: 102200 +toc: true +aliases: +  - /c/ldap +  - /docs/configuration/authentication/ldap.html +--- + +## Configuration + +```yaml +authentication_backend: +  ldap: +    implementation: custom +    url: ldap://127.0.0.1 +    timeout: 5s +    start_tls: false +    tls: +      server_name: ldap.example.com +      skip_verify: false +      minimum_version: TLS1.2 +    base_dn: DC=example,DC=com +    additional_users_dn: ou=users +    users_filter: (&({username_attribute}={input})(objectClass=person)) +    username_attribute: uid +    mail_attribute: mail +    display_name_attribute: displayName +    additional_groups_dn: ou=groups +    groups_filter: (&(member={dn})(objectClass=groupOfNames)) +    group_name_attribute: cn +    permit_referrals: false +    user: CN=admin,DC=example,DC=com +    password: password +``` + +## Options + +### implementation + +{{< confkey type="string" default="custom" required="no" >}} + +Configures the LDAP implementation used by Authelia. + +See the [Implementation Guide](#implementation-guide) for information. + +### url + +{{< confkey type="string" required="yes" >}} + +The LDAP URL which consists of a scheme, address, and port. Format is `<scheme>://<address>:<port>` or +`<scheme>://<address>` where scheme is either `ldap` or `ldaps`. + +```yaml +authentication_backend: +  ldap: +    url: ldaps://dc1.example.com +``` + +If utilising an IPv6 literal address it must be enclosed by square brackets: + +```yaml +authentication_backend: +  ldap: +    url: ldap://[fd00:1111:2222:3333::1] +``` + +### timeout + +{{< confkey type="duration" default="5s" required="no" >}} + +The timeout for dialing an LDAP connection. + +### start_tls + +{{< confkey type="boolean" default="false" required="no" >}} + +Enables use of the LDAP StartTLS process which is not commonly used. You should only configure this if you know you need +it. The initial connection will be over plain text, and *Authelia* will try to upgrade it with the LDAP server. LDAPS +URL's are slightly more secure. + +### tls + +Controls the TLS connection validation process. You can see how to configure the tls +section [here](../prologue/common.md#tls-configuration). + +### base_dn + +{{< confkey type="string" required="yes" >}} + +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 +authelia OU: `OU=authelia,DC=example,DC=com`. This is prefixed with the [additional_users_dn](#additional_users_dn) for +user searches and [additional_groups_dn](#additional_groups_dn) for groups searches. + +### additional_users_dn + +{{< 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 +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,DC=example,DC=com`. + +### users_filter + +{{< confkey type="string" required="situational" >}} + +*__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.* + +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 +[attribute defaults](#attribute-defaults) for more information. + +### username_attribute + +{{< confkey type="string" required="situational" >}} + +*__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.* + +The LDAP attribute that maps to the username in *Authelia*. This must contain the `{username_attribute}` +[placeholder](#users-filter-replacements). + +### mail_attribute + +{{< confkey type="string" required="situational" >}} + +*__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.* + +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 +when a user attempts to reset their password or register a second factor device. + +### display_name_attribute + +{{< confkey type="string" required="situational" >}} + +*__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.* + +The attribute to retrieve which is shown on the Web UI to the user when they log in. + +### additional_groups_dn + +{{< confkey type="string" required="no" >}} + +Similar to [additional_users_dn](#additional_users_dn) but it applies to group searches. + +### groups_filter + +{{< confkey type="string" required="situational" >}} + +*__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.* + +Similar to [users_filter](#users_filter) but it applies to group searches. In order to include groups the member is not +a direct member of, but is a member of another group that is a member of those (i.e. recursive groups), you may try +using the following filter which is currently only tested against Microsoft Active Directory: + +`(&(member:1.2.840.113556.1.4.1941:={dn})(objectClass=group)(objectCategory=group))` + +## group_name_attribute + +{{< confkey type="string" required="situational" >}} + +*__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.* + +The LDAP attribute that is used by Authelia to determine the group name. + +## permit_referrals + +{{< confkey type="boolean" default="false" required="no" >}} + +Permits following referrals. This is useful if you have read-only servers in your architecture and thus require +referrals to be followed when performing write operations. + +### user + +{{< confkey type="string" required="yes" >}} + +The distinguished name of the user paired with the password to bind with for lookup and password change operations. + +### password + +{{< confkey type="string" required="yes" >}} + +The password of the user paired with the user to bind with for lookup and password change operations. +Can also be defined using a [secret](../methods/secrets.md) which is the recommended for containerized deployments. + +## Implementation Guide + +There are currently two implementations, `custom` and `activedirectory`. The `activedirectory` implementation +must be used if you wish to allow users to change or reset their password as Active Directory +uses a custom attribute for this, and an input format other implementations do not use. The long term +intention of this is to have logical defaults for various RFC implementations of LDAP. + +### Filter replacements + +Various replacements occur in the user and groups filter. The replacements either occur at startup or upon an LDAP +search. + +#### Users filter replacements + +|       Placeholder        |  Phase  |              Replacement              | +|:------------------------:|:-------:|:-------------------------------------:| +|   {username_attribute}   | startup |   The configured username attribute   | +|     {mail_attribute}     | startup |     The configured mail attribute     | +| {display_name_attribute} | startup | The configured display name attribute | +|         {input}          | search  |   The input into the username field   | + +#### Groups filter replacements + +| Placeholder | Phase  |                                Replacement                                | +|:-----------:|:------:|:-------------------------------------------------------------------------:| +|   {input}   | search |                     The input into the username field                     | +| {username}  | search | The username from the profile lookup obtained from the username attribute | +|    {dn}     | search |              The distinguished name from the profile lookup               | + +### Defaults + +The below tables describes the current attribute defaults for each implementation. + +#### Attribute defaults + +This table describes the attribute defaults for each implementation. i.e. the username_attribute is described by the +Username column. + +| Implementation  |    Username    | Display Name | Mail | Group Name | +|:---------------:|:--------------:|:------------:|:----:|:----------:| +|     custom      |      N/A       | displayName  | mail |     cn     | +| activedirectory | sAMAccountName | displayName  | mail |     cn     | + +#### Filter defaults + +The filters are probably the most important part to get correct when setting up LDAP. You want to exclude disabled +accounts. The active directory example has two attribute filters that accomplish this as an example (more examples would +be appreciated). The userAccountControl filter checks that the account is not disabled and the pwdLastSet makes sure that +value is not 0 which means the password requires changing at the next login. + +| Implementation  |                                                                          Users Filter                                                                           |                       Groups Filter                       | +|:---------------:|:---------------------------------------------------------------------------------------------------------------------------------------------------------------:|:---------------------------------------------------------:| +|     custom      |                                                                               N/A                                                                               |                            N/A                            | +| activedirectory | (&(|({username_attribute}={input})({mail_attribute}={input}))(sAMAccountType=805306368)(!(userAccountControl:1.2.840.113556.1.4.803:=2))(!(pwdLastSet=0))) | (&(member={dn})(objectClass=group)(objectCategory=group)) | + +*__Note:__* The Active Directory filter `(sAMAccountType=805306368)` is exactly the same as +`(&(objectCategory=person)(objectClass=user))` except that the former is more performant, you can read more about this +and other Active Directory filters on the [TechNet wiki](https://social.technet.microsoft.com/wiki/contents/articles/5392.active-directory-ldap-syntax-filters.aspx). + +## Refresh Interval + +It's recommended you either use the default [refresh interval](./introduction.md#refresh_interval) or configure this to +a value low enough to refresh the user groups and status (deleted, disabled, etc) to adequately secure your environment. + +## Important notes + +Users must be uniquely identified by an attribute, this attribute must obviously contain a single value and be guaranteed +by the administrator to be unique. If multiple users have the same value, Authelia will simply fail authenticating the +user and display an error message in the logs. + +In order to avoid such problems, we highly recommended you follow [RFC2307] by using `sAMAccountName` for Active +Directory and `uid` for other implementations as the attribute holding the unique identifier +for your users. + +[username attribute]: #username_attribute +[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 diff --git a/docs/content/en/configuration/identity-providers/_index.md b/docs/content/en/configuration/identity-providers/_index.md new file mode 100644 index 000000000..865b42b55 --- /dev/null +++ b/docs/content/en/configuration/identity-providers/_index.md @@ -0,0 +1,9 @@ +--- +title : "Identity Providers" +description: "Identity Providers Configuration" +lead: "" +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +weight: 190000 +--- diff --git a/docs/content/en/configuration/identity-providers/introduction.md b/docs/content/en/configuration/identity-providers/introduction.md new file mode 100644 index 000000000..95b8d6109 --- /dev/null +++ b/docs/content/en/configuration/identity-providers/introduction.md @@ -0,0 +1,19 @@ +--- +title: "Identity Providers" +description: "Identity Providers Configuration" +lead: "Authelia is evolving to become an identity provider. This section describes how to configure this." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  configuration: +    parent: "identity-providers" +weight: 190100 +toc: true +aliases: +  - /docs/configuration/identity-providers/ +--- + +## OpenID Connect + +The only identity provider implementation supported at this time is [OpenID Connect](open-id-connect.md). diff --git a/docs/content/en/configuration/identity-providers/open-id-connect.md b/docs/content/en/configuration/identity-providers/open-id-connect.md new file mode 100644 index 000000000..a5afc342b --- /dev/null +++ b/docs/content/en/configuration/identity-providers/open-id-connect.md @@ -0,0 +1,406 @@ +--- +title: "OpenID Connect" +description: "OpenID Connect Configuration" +lead: "Authelia can operate as an OpenID Connect provider. This section describes how to configure this." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  configuration: +    parent: "identity-providers" +weight: 190200 +toc: true +aliases: +  - /c/oidc +  - /docs/configuration/identity-providers/oidc.html +--- + +__Authelia__ currently supports the [OpenID Connect] OP role as a [__beta__](../../roadmap/active/openid-connect.md) +feature. The OP role is the [OpenID Connect] Provider role, not the Relying Party or RP role. This means other +applications that implement the [OpenID Connect] RP role can use Authelia as an authentication and authorization backend +similar to how you may use social media or development platforms for login. + +The Relying Party role is the role which allows an application to use GitHub, Google, or other [OpenID Connect] +providers for authentication and authorization. We do not intend to support this functionality at this moment in time. + +More information about the beta can be found in the [roadmap](../../roadmap/active/openid-connect.md). + +## Configuration + +The following snippet provides a sample-configuration for the OIDC identity provider explaining each field in detail. + +```yaml +identity_providers: +  oidc: +    hmac_secret: this_is_a_secret_abc123abc123abc +    issuer_private_key: | +      --- KEY START +      --- KEY END +    access_token_lifespan: 1h +    authorize_code_lifespan: 1m +    id_token_lifespan: 1h +    refresh_token_lifespan: 90m +    enable_client_debug_messages: false +    enforce_pkce: public_clients_only +    cors: +      endpoints: +        - authorization +        - token +        - revocation +        - introspection +      allowed_origins: +        - https://example.com +      allowed_origins_from_client_redirect_uris: false +    clients: +      - id: myapp +        description: My Application +        secret: this_is_a_secret +        sector_identifier: '' +        public: false +        authorization_policy: two_factor +        pre_configured_consent_duration: '' +        audience: [] +        scopes: +          - openid +          - groups +          - email +          - profile +        redirect_uris: +          - https://oidc.example.com:8080/oauth2/callback +        grant_types: +          - refresh_token +          - authorization_code +        response_types: +          - code +        response_modes: +          - form_post +          - query +          - fragment +        userinfo_signing_algorithm: none +``` + +## Options + +### hmac_secret + +{{< confkey type="string" required="yes" >}} + +The HMAC secret used to sign the [JWT]'s. The provided string is hashed to a SHA256 ([RFC6234]) byte string for the +purpose of meeting the required format. This secret must be generated by the administrator and can be done by following +the [Generating a Random Alphanumeric String](../miscellaneous/guides.md#generating-a-random-alphanumeric-string) guide. + +Should be defined using a [secret](../methods/secrets.md) which is the recommended for containerized deployments. + +### issuer_private_key + +{{< confkey type="string" required="yes" >}} + +The private key in DER base64 ([RFC4648]) encoded PEM format used to encrypt the [OpenID Connect] [JWT]'s. The key must +be generated by the administrator and can be done by following the +[Generating an RSA Keypair](../miscellaneous/guides.md#generating-an-rsa-keypair) guide. + +Should be defined using a [secret](../methods/secrets.md) which is the recommended for containerized deployments. + +### access_token_lifespan + +{{< confkey type="duration" default="1h" required="no" >}} + +The maximum lifetime of an access token. It's generally recommended keeping this short similar to the default. +For more information read these docs about [token lifespan]. + +### authorize_code_lifespan + +{{< confkey type="duration" default="1m" required="no" >}} + +The maximum lifetime of an authorize code. This can be rather short, as the authorize code should only be needed to +obtain the other token types. For more information read these docs about [token lifespan]. + +### id_token_lifespan + +{{< confkey type="duration" default="1h" required="no" >}} + +The maximum lifetime of an ID token. For more information read these docs about [token lifespan]. + +### refresh_token_lifespan + +{{< confkey type="string" default="90m" required="no" >}} + +The maximum lifetime of a refresh token. The +refresh token can be used to obtain new refresh tokens as well as access tokens or id tokens with an +up-to-date expiration. For more information read these docs about [token lifespan]. + +A good starting point is 50% more or 30 minutes more (which ever is less) time than the highest lifespan out of the +[access token lifespan](#access_token_lifespan), the [authorize code lifespan](#authorize_code_lifespan), and the +[id token lifespan](#id_token_lifespan). For instance the default for all of these is 60 minutes, so the default refresh +token lifespan is 90 minutes. + +### enable_client_debug_messages + +{{< confkey type="boolean" default="false" required="no" >}} + +Allows additional debug messages to be sent to the clients. + +### minimum_parameter_entropy + +{{< confkey type="integer" default="8" required="no" >}} + +This controls the minimum length of the `nonce` and `state` parameters. + +*__Security Notice:__* Changing this value is generally discouraged, reducing it from the default can theoretically +make certain scenarios less secure. It is highly encouraged that if your OpenID Connect RP does not send these +parameters or sends parameters with a lower length than the default that they implement a change rather than changing +this value. + +### enforce_pkce + +{{< confkey type="string" default="public_clients_only" required="no" >}} + +[Proof Key for Code Exchange](https://www.rfc-editor.org/rfc/rfc7636.html) enforcement policy: if specified, must be +either `never`, `public_clients_only` or `always`. + +If set to `public_clients_only` (default), [PKCE] will be required for public clients using the +[Authorization Code Flow]. + +When set to `always`, [PKCE] will be required for all clients using the Authorization Code flow. + +*__Security Notice:__* Changing this value to `never` is generally discouraged, reducing it from the default can +theoretically make certain client-side applications (mobile applications, SPA) vulnerable to CSRF and authorization code +interception attacks. + +### enable_pkce_plain_challenge + +{{< confkey type="boolean" default="false" required="no" >}} + +Allows [PKCE] `plain` challenges when set to `true`. + +*__Security Notice:__* Changing this value is generally discouraged. Applications should use the `S256` [PKCE] challenge +method instead. + +### cors + +Some [OpenID Connect] Endpoints need to allow cross-origin resource sharing, however some are optional. This section allows +you to configure the optional parts. We reply with CORS headers when the request includes the Origin header. + +#### endpoints + +{{< confkey type="list(string)" required="no" >}} + +A list of endpoints to configure with cross-origin resource sharing headers. It is recommended that the `userinfo` +option is at least in this list. The potential endpoints which this can be enabled on are as follows: + +* authorization +* token +* revocation +* introspection +* userinfo + +#### allowed_origins + +{{< confkey type="list(string)" required="no" >}} + +A list of permitted origins. + +Any origin with https is permitted unless this option is configured or the +[allowed_origins_from_client_redirect_uris](#allowed_origins_from_client_redirect_uris) option is enabled. This means +you must configure this option manually if you want http endpoints to be permitted to make cross-origin requests to the +[OpenID Connect] endpoints, however this is not recommended. + +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 +and the [allowed_origins_from_client_redirect_uris](#allowed_origins_from_client_redirect_uris) MUST NOT be enabled. The +wildcard origin is denoted as `*`. Examples: + +```yaml +identity_providers: +  oidc: +    cors: +      allowed_origins: "*" +``` + +```yaml +identity_providers: +  oidc: +    cors: +      allowed_origins: +        - "*" +``` + +#### allowed_origins_from_client_redirect_uris + +{{< confkey type="boolean" default="false" required="no" >}} + +Automatically adds the origin portion of all redirect URI's on all clients to the list of +[allowed_origins](#allowed_origins), provided they have the scheme http or https and do not have the hostname of +localhost. + +### clients + +{{< confkey type="list" required="yes" >}} + +A list of clients to configure. The options for each client are described below. + +#### id + +{{< confkey type="string" required="yes" >}} + +The Client ID for this client. It must exactly match the Client ID configured in the application +consuming this client. + +#### description + +{{< confkey type="string" default="*same as id*" required="no" >}} + +A friendly description for this client shown in the UI. This defaults to the same as the ID. + +#### secret + +{{< confkey type="string" required="situational" >}} + +The shared secret between Authelia and the application consuming this client. This secret must match the secret +configured in the application. Currently this is stored in plain text. + +This secret must be generated by the administrator and can be done by following the +[Generating a Random Alphanumeric String](../miscellaneous/guides.md#generating-a-random-alphanumeric-string) guide. + +This must be provided when the client is a confidential client type, and must be blank when using the public client +type. To set the client type to public see the [public](#public) configuration option. + +#### sector_identifier + +{{< confkey type="string" required="no" >}} + +*__Important Note:__ because adjusting this option will inevitably change the `sub` claim of all tokens generated for +the specified client, changing this should cause the relying party to detect all future authorizations as completely new +users.* + +Must be an empty string or the host component of a URL. This is commonly just the domain name, but may also include a +port. + +Authelia utilizes UUID version 4 subject identifiers. By default the public [Subject Identifier Type] is utilized for +all clients. This means the subject identifiers will be the same for all clients. This configuration option enables +[Pairwise Identifier Algorithm] for this client, and configures the sector identifier utilized for both the storage and +the lookup of the subject identifier. + +1. All clients who do not have this configured will generate the same subject identifier for a particular user +   regardless of which client obtains the ID token. +2. All clients which have the same sector identifier will: +   1. have the same subject identifier for a particular user when compared to clients with the same sector identifier. +   2. have a completely different subject identifier for a particular user whe compared to: +      1. any client with the public subject identifier type. +      2. any client with a differing sector identifier. + +In specific but limited scenarios this option is beneficial for privacy reasons. In particular this is useful when the +party utilizing the *Authelia* [OpenID Connect] Authorization Server is foreign and not controlled by the user. It would +prevent the third party utilizing the subject identifier with another third party in order to track the user. + +Keep in mind depending on the other claims they may still be able to perform this tracking and it is not a silver +bullet. There are very few benefits when utilizing this in a homelab or business where no third party is utilizing +the server. + +#### public + +{{< confkey type="bool" default="false" required="no" >}} + +This enables the public client type for this client. This is for clients that are not capable of maintaining +confidentiality of credentials, you can read more about client types in [RFC6749 Section 2.1]. This is particularly +useful for SPA's and CLI tools. This option requires setting the [client secret](#secret) to a blank string. + +In addition to the standard rules for redirect URIs, public clients can use the `urn:ietf:wg:oauth:2.0:oob` redirect +URI. + +#### authorization_policy + +{{< confkey type="string" default="two_factor" required="no" >}} + +The authorization policy for this client: either `one_factor` or `two_factor`. + +#### pre_configured_consent_duration + +{{< confkey type="duration" required="no" >}} + +*__Note:__ This setting uses the [duration notation format](../prologue/common.md#duration-notation-format). Please see +the [common options](../prologue/common.md#duration-notation-format) documentation for information on this format.* + +Configuring this enables users of this client to remember their consent as a pre-configured consent. The period of time +dictates how long a users choice to remember the pre-configured consent lasts. + +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. + +#### audience + +{{< confkey type="list(string)" required="no" >}} + +A list of audiences this client is allowed to request. + +#### scopes + +{{< confkey type="list(string)" default="openid, groups, profile, email" required="no" >}} + +A list of scopes to allow this client to consume. See +[scope definitions](../../integration/openid-connect/introduction.md#scope-definitions) for more information. The +documentation for the application you want to use with Authelia will most-likely provide you with the scopes to allow. + +#### redirect_uris + +{{< confkey type="list(string)" required="yes" >}} + +A list of valid callback URIs this client will redirect to. All other callbacks will be considered unsafe. The URIs are +case-sensitive and they differ from application to application - the community has provided +[a list of URL´s for common applications](../../integration/openid-connect/introduction.md). + +Some restrictions that have been placed on clients and +their redirect URIs are as follows: + +1. If a client attempts to authorize with Authelia and its redirect URI is not listed in the client configuration the +   attempt to authorize wil fail and an error will be generated. +2. The redirect URIs are case-sensitive. +3. The URI must include a scheme and that scheme must be one of `http` or `https`. +4. The client can ignore rule 3 and use `urn:ietf:wg:oauth:2.0:oob` if it is a [public](#public) client type. + +#### grant_types + +{{< confkey type="list(string)" default="refresh_token, authorization_code" required="no" >}} + +A list of grant types this client can return. *It is recommended that this isn't configured at this time unless you +know what you're doing*. Valid options are: `implicit`, `refresh_token`, `authorization_code`, `password`, +`client_credentials`. + +#### response_types + +{{< confkey type="list(string)" default="code" required="no" >}} + +A list of response types this client can return. *It is recommended that this isn't configured at this time unless you +know what you're doing*. Valid options are: `code`, `code id_token`, `id_token`, `token id_token`, `token`, +`token id_token code`. + +#### response_modes + +{{< confkey type="list(string)" default="form_post, query, fragment" required="no" >}} + +A list of response modes this client can return. It is recommended that this isn't configured at this time unless you +know what you're doing. Potential values are `form_post`, `query`, and `fragment`. + +#### userinfo_signing_algorithm + +{{< confkey type="string" default="none" required="no" >}} + +The algorithm used to sign the userinfo endpoint responses. This can either be `none` or `RS256`. + +## Integration + +To integrate Authelia's [OpenID Connect] implementation with a relying party please see the +[integration docs](../../integration/openid-connect/introduction.md). + +[token lifespan]: https://docs.apigee.com/api-platform/antipatterns/oauth-long-expiration +[OpenID Connect]: https://openid.net/connect/ +[JWT]: https://www.rfc-editor.org/rfc/rfc7519.html +[RFC6234]: https://www.rfc-editor.org/rfc/rfc6234.html +[RFC4648]: https://www.rfc-editor.org/rfc/rfc4648.html +[RFC7468]: https://www.rfc-editor.org/rfc/rfc7468.html +[RFC6749 Section 2.1]: https://www.rfc-editor.org/rfc/rfc6749.html#section-2.1 +[PKCE]: https://www.rfc-editor.org/rfc/rfc7636.html +[Authorization Code Flow]: https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth +[Subject Identifier Type]: https://openid.net/specs/openid-connect-core-1_0.html#SubjectIDTypes +[Pairwise Identifier Algorithm]: https://openid.net/specs/openid-connect-core-1_0.html#PairwiseAlg diff --git a/docs/content/en/configuration/methods/_index.md b/docs/content/en/configuration/methods/_index.md new file mode 100644 index 000000000..fd1fd0d0b --- /dev/null +++ b/docs/content/en/configuration/methods/_index.md @@ -0,0 +1,9 @@ +--- +title : "Methods" +description: "Methods of Configuration" +lead: "" +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +weight: 101000 +--- diff --git a/docs/content/en/configuration/methods/environment.md b/docs/content/en/configuration/methods/environment.md new file mode 100644 index 000000000..15bdc7314 --- /dev/null +++ b/docs/content/en/configuration/methods/environment.md @@ -0,0 +1,51 @@ +--- +title: "Environment" +description: "Using the Environment Variable Configuration Method." +lead: "Authelia has a layered configuration model. This section describes how to implement the environment configuration." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  configuration: +    parent: "methods" +weight: 101300 +toc: true +--- + +Environment variables are applied after the configuration file meaning anything specified as part of the environment +overrides the configuration files. + +*__Please Note:__ It is not possible to configure the access control rules section or OpenID Connect identity provider +clients section using environment variables at this time.* + +## Prefix + +The environment variables must be prefixed with `AUTHELIA_`. All environment variables that start with this prefix must +be for configuration. Any supplied environment variables that have this prefix and are not meant for configuration will +likely result in an error or even worse misconfiguration. + +### Kubernetes + +Please see the +[Kubernetes Integration: Enable Service Links](../../integration/kubernetes/introduction/index.md#enable-service-links) +documentation for specific requirements for using *Authelia* with Kubernetes. + +## Mapping + +Configuration options are mapped by their name. Levels of indentation / subkeys are replaced by underscores. + +For example this YAML configuration: + +```yaml +log: +  level: info +server: +  read_buffer_size: 4096 +``` + +Can be replaced by this environment variable configuration: + +```bash +AUTHELIA_LOG_LEVEL=info +AUTHELIA_SERVER_READ_BUFFER_SIZE=4096 +``` diff --git a/docs/content/en/configuration/methods/files.md b/docs/content/en/configuration/methods/files.md new file mode 100644 index 000000000..7e02b2bd5 --- /dev/null +++ b/docs/content/en/configuration/methods/files.md @@ -0,0 +1,112 @@ +--- +title: "Files" +description: "Using the YAML File Configuration Method." +lead: "Authelia can be configured via files. This section describes utilizing this method." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  configuration: +    parent: "methods" +weight: 101200 +toc: true +--- + +*Authelia* loads `configuration.yml` as the configuration if you just run it. You can override this behaviour with the +following syntax: + +```bash +authelia --config config.custom.yml +``` + +## Multiple Configuration Files + +You can have multiple configuration files which will be merged in the order specified. If duplicate keys are specified +the last one to be specified is the one that takes precedence. Example: + +```bash +authelia --config configuration.yml --config config-acl.yml --config config-other.yml +authelia --config configuration.yml,config-acl.yml,config-other.yml +``` + +Authelia's configuration files use the YAML format. A template with all possible options can be found at the root of the +repository [here](https://github.com/authelia/authelia/blob/master/config.template.yml). + +*__Important Note:__ You should not have configuration sections such as Access Control Rules or OpenID Connect clients +configured in multiple files. If you wish to split these into their own files that is fine, but if you have two files that +specify these sections and expect them to merge properly you are asking for trouble.* + +### Container + +By default, the container looks for a configuration file at `/config/configuration.yml`. + +### Docker + +This is an example of how to override the configuration files loaded in docker: + +```bash +docker run -d --volume /path/to/config:/config authelia:authelia:latest authelia --config=/config/configuration.yaml --config=/config/configuration.acl.yaml +``` + +See the [Docker Documentation](https://docs.docker.com/engine/reference/commandline/run/) for more information on the +`docker run` command. + +### Docker Compose + +An excerpt from a docker compose that allows you to specify multiple configuration files is as follows: + +```yaml +version: "3.8" +services: +  authelia: +    container_name: authelia +    image: authelia/authelia:latest +    command: +      - "authelia" +      - "--config=/config/configuration.yaml" +      - "--config=/config/configuration.acl.yaml" + +``` + +See the [compose file reference](https://docs.docker.com/compose/compose-file/compose-file-v3/#command) for more +information. + +### Kubernetes + +An excerpt from a Kubernetes container that allows you to specify multiple configuration files is as follows: + +```yaml +kind: Deployment +apiVersion: apps/v1 +metadata: +  name: authelia +  namespace: authelia +  labels: +    app.kubernetes.io/instance: authelia +    app.kubernetes.io/name: authelia +spec: +  replicas: 1 +  selector: +    matchLabels: +      app.kubernetes.io/instance: authelia +      app.kubernetes.io/name: authelia +  template: +    metadata: +      labels: +        app.kubernetes.io/instance: authelia +        app.kubernetes.io/name: authelia +    spec: +      enableServiceLinks: false +      containers: +        - name: authelia +          image: docker.io/authelia/authelia:fix-missing-head-handler +          command: +            - authelia +          args: +            - '--config=/configuration.yaml' +            - '--config=/configuration.acl.yaml' +``` + +See the Kubernetes [workloads documentation](https://kubernetes.io/docs/concepts/workloads/pods/#pod-templates) or the +[Container API docs](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#container-v1-core) for more +information. diff --git a/docs/content/en/configuration/methods/introduction.md b/docs/content/en/configuration/methods/introduction.md new file mode 100644 index 000000000..dc21fdc44 --- /dev/null +++ b/docs/content/en/configuration/methods/introduction.md @@ -0,0 +1,27 @@ +--- +title: "Methods" +description: "Methods of Configuration." +lead: "Authelia has a layered configuration model. This section describes how to implement configuration." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  configuration: +    parent: "methods" +weight: 101100 +toc: true +--- + +## Layers + +Authelia has several methods of configuration available to it. The order of precedence is as follows: + +1. [Secrets](secrets.md) +2. [Environment Variables](environment.md) +3. [Files](files.md) (in order of them being specified) + +This order of precedence puts higher weight on things higher in the list. This means anything specified in the +[files](files.md) is overridden by [environment variables](environment.md) if specified, and anything specified by +[environment variables](environment.md) is overridden by [secrets](secrets.md) if specified. + +[YAML]: https://yaml.org/ diff --git a/docs/configuration/secrets.md b/docs/content/en/configuration/methods/secrets.md index d4510fe24..68996a211 100644 --- a/docs/configuration/secrets.md +++ b/docs/content/en/configuration/methods/secrets.md @@ -1,28 +1,52 @@  --- -layout: default -title: Secrets -parent: Configuration -nav_order: 11 +title: "Secrets" +description: "Using the Secrets Configuration Method." +lead: "Authelia allows providing configuration via secrets method. This section describes how to implement this." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  configuration: +    parent: "methods" +weight: 101400 +toc: true +aliases: +  - /c/secrets +  - /docs/configuration/secrets.html  --- -# Secrets +Configuration of *Authelia* requires several secrets and passwords. Even if they can be set in the configuration file or +standard environment variables, the recommended way to set secrets is to use this configuration method as described below. -Configuration of Authelia requires some secrets and passwords. Even if they can be set in the configuration file or  -standard environment variables, the recommended way to set secrets is to use environment variables as described below. +See the [security](#security) section for more information. + +## Layers + +*__Important Note:__* While this method is the third layer of the layered configuration model as described by the +[introduction](introduction.md#layers), this layer is special in as much as *Authelia* will not start if you define +a secret as well as any other configuration method. + +For example if you define `jwt_secret` in the [files method](files.md) and/or `AUTHELIA_JWT_SECRET` in the +[environment method](environment.md), as well as the `AUTHELIA_JWT_SECRET_FILE`, this will cause the aforementioned error. + +## Security + +This method is a slight improvement over the security of the other methods as it allows you to easily separate your +configuration in a logically secure way.  ## Environment variables -A secret value can be loaded by Authelia when the configuration key ends with one of the following words: `key`,  -`secret`, `password`, or `token`.  +A secret value can be loaded by *Authelia* when the configuration key ends with one of the following words: `key`, +`secret`, `password`, or `token`.  If you take the expected environment variable for the configuration option with the `_FILE` suffix at the end. The value  of these environment variables must be the path of a file that is readable by the Authelia process, if they are not, -Authelia will fail to load. Authelia will automatically remove the newlines from the end of the files contents. +*Authelia* will fail to load. Authelia will automatically remove the newlines from the end of the files contents.  For instance the LDAP password can be defined in the configuration -at the path **authentication_backend.ldap.password**, so this password +at the path __authentication_backend.ldap.password__, so this password  could alternatively be set using the environment variable called -**AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PASSWORD_FILE**. +__AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PASSWORD_FILE__.  Here is the list of the environment variables which are considered secrets and can be defined. Please note that only  secrets can be loaded into the configuration if they end with one of the suffixes above, you can set the value of any @@ -48,7 +72,7 @@ other configuration using the environment but instead of loading a file the valu  If for some reason you decide on keeping the secrets in the configuration file, it is strongly recommended that you  ensure the permissions of the configuration file are appropriately set so that other users or processes cannot access -this file. Generally the UNIX permissions that are appropriate are 0600.  +this file. Generally the UNIX permissions that are appropriate are 0600.  ## Secrets exposed in an environment variable @@ -57,9 +81,9 @@ setting the value to the value you wish to set in configuration, however we stro  and instead use the file-based secrets above.  Prior to implementing file secrets the only way you were able to define secret values was either via configuration or -via environment variables in plain text.  +via environment variables in plain text. -See [this article](https://diogomonica.com/2017/03/27/why-you-shouldnt-use-env-variables-for-secret-data/) for reasons  +See [this article](https://diogomonica.com/2017/03/27/why-you-shouldnt-use-env-variables-for-secret-data/) for reasons  why setting them via the file counterparts is highly encouraged.  ## Docker @@ -67,7 +91,6 @@ why setting them via the file counterparts is highly encouraged.  Secrets can be provided in a `docker-compose.yml` either with Docker secrets or  bind mounted secret files, examples of these are provided below. -  ### Compose with Docker secrets  This example assumes secrets are stored in `/path/to/authelia/secrets/{secretname}` @@ -179,7 +202,7 @@ metadata:  data:    duo_key: >-      UXE1WmM4S0pldnl6eHRwQ3psTGpDbFplOXFueUVyWEZhYjE0Z01IRHN0RT0K -   +    jwt_secret: >-      anotherBase64EncodedSecret @@ -189,7 +212,7 @@ data:  where `UXE1WmM4S0pldnl6eHRwQ3psTGpDbFplOXFueUVyWEZhYjE0Z01IRHN0RT0K` is Base64 encoded for  `Qq5Zc8KJevyzxtpCzlLjClZe9qnyErXFab14gMHDstE`, the actual content of the secret. You can generate these contents with -```sh +```console  LENGTH=64  tr -cd '[:alnum:]' < /dev/urandom \    | fold -w "${LENGTH}"           \ @@ -204,13 +227,11 @@ which writes the secret's content to the `actualSecretContent.txt` file and prin  ### Kustomization -- **Filename:** ./kustomization.yaml -- **Command:** kubectl apply -k -- **Notes:** this kustomization expects the Authelia configuration.yml in -  the same directory. You will need to edit the kustomization.yaml with your -  desired secrets after the equal signs. If you change the value before the -  equal sign you'll have to adjust the volumes section of the daemonset -  template (or deployment template if you're using it). +* __Filename:__ ./kustomization.yaml +* __Command:__ kubectl apply -k +* __Notes:__ this kustomization expects the Authelia configuration.yml in the same directory. You will need to edit the +  kustomization.yaml with your desired secrets after the equal signs. If you change the value before the equal sign +  you'll have to adjust the volumes section of the daemonset template (or deployment template if you're using it).  ```yaml  #filename: ./kustomization.yaml @@ -237,9 +258,10 @@ secretGenerator:  ### DaemonSet -- **Filename:** ./daemonset.yaml -- **Command:** kubectl apply -f ./daemonset.yaml -- **Notes:** assumes Kubernetes API 1.16 or greater +* __Filename:__ ./daemonset.yaml +* __Command:__ kubectl apply -f ./daemonset.yaml +* __Notes:__ assumes Kubernetes API 1.16 or greater +  ```yaml  #filename: daemonset.yaml  #command: kubectl apply -f daemonset.yaml diff --git a/docs/content/en/configuration/miscellaneous/_index.md b/docs/content/en/configuration/miscellaneous/_index.md new file mode 100644 index 000000000..9ff036894 --- /dev/null +++ b/docs/content/en/configuration/miscellaneous/_index.md @@ -0,0 +1,9 @@ +--- +title : "Miscellaneous" +description: "Miscellaneous Configuration" +lead: "" +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +weight: 199000 +--- diff --git a/docs/content/en/configuration/miscellaneous/guides.md b/docs/content/en/configuration/miscellaneous/guides.md new file mode 100644 index 000000000..64b5a4023 --- /dev/null +++ b/docs/content/en/configuration/miscellaneous/guides.md @@ -0,0 +1,77 @@ +--- +title: "Guides" +description: "Miscellaneous Guides for Configuration." +lead: "This section contains miscellaneous guides used in the configuration." +date: 2022-05-16T15:21:22+10:00 +draft: false +images: [] +menu: +  configuration: +    parent: "miscellaneous" +weight: 199500 +toc: true +--- + +## Generating a Random Alphanumeric String + +Some sections of the configuration recommend generating a random string. There are many ways to accomplish this, one +possible way on Linux is utilizing the following command which prints a string with a length in characters of +`${LENGTH}` to `stdout`. The string will only contain alphanumeric characters. + +```bash +LENGTH=64 +tr -cd '[:alnum:]' < /dev/urandom | fold -w "${LENGTH}" | head -n 1 | tr -d '\n' ; echo +``` + +## Generating an RSA Keypair + +Some sections of the configuration need an RSA keypair. There are many ways to achieve this, this section explains two +such ways. + +### openssl + +The `openssl` command on Linux can be used to generate a RSA 4096 bit keypair: + +```bash +openssl genrsa -out private.pem 4096 +openssl rsa -in private.pem -outform PEM -pubout -out public.pem +``` + +### authelia + +The __Authelia__ docker container or CLI binary can be used to generate a RSA 4096 bit keypair: + +```bash +docker run -u "$(id -u):$(id -g)" -v "$(pwd)":/keys authelia/authelia:latest authelia rsa generate --dir /keys +``` + +```bash +authelia rsa generate --dir /path/to/keys +``` + +## Generating an RSA Self-Signed Certificate + +Some sections of the configuration need a certificate and it may be possible to use a self-signed certificate. There are +many ways to achieve this, this section explains two such ways. + +### openssl + +The `openssl` command on Linux can be used to generate a RSA 4096 bit self-signed certificate for the domain +`example.com`: + +```bash +openssl req -x509 -nodes -newkey rsa:4096 -keyout key.pem -out cert.pem -sha256 -days 365 -subj '/CN=example.com' +``` + +### authelia + +The __Authelia__ docker container or binary can be used to generate a RSA 4096 bit self-signed certificate for the +domain `example.com`: + +```bash +docker run -u "$(id -u):$(id -g)" -v "$(pwd)":/keys authelia/authelia authelia certificates generate --host example.com --dir /keys +``` + +```bash +authelia certificates generate --host example.com --dir /path/to/keys +``` diff --git a/docs/configuration/miscellaneous.md b/docs/content/en/configuration/miscellaneous/introduction.md index 137ebaf36..ff572b3f3 100644 --- a/docs/configuration/miscellaneous.md +++ b/docs/content/en/configuration/miscellaneous/introduction.md @@ -1,51 +1,41 @@  --- -layout: default -title: Miscellaneous -parent: Configuration -nav_order: 7 +title: "Miscellaneous" +description: "Miscellaneous Configuration." +lead: "Authelia has a few config items that don't fit into their own area. This describes these options." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  configuration: +    parent: "miscellaneous" +weight: 199100 +toc: true +aliases: +  - /docs/configuration/miscellaneous.html +  - /docs/configuration/theme.html  --- -# Miscellaneous +## Configuration -Here are the main customizable options in Authelia that don't fit into their own sections. +```yaml +certificates_directory: /config/certs/ +default_redirection_url: https://home.example.com:8080/ +jwt_secret: v3ry_important_s3cr3t +theme: light +``` + +## Options -## certificates_directory +### certificates_directory  This option defines the location of additional certificates to load into the trust chain specifically for Authelia.  This currently affects both the SMTP notifier and the LDAP authentication backend. The certificates should all be in the  PEM format and end with the extension `.pem`, `.crt`, or `.cer`. You can either add the individual certificates public  key or the CA public key which signed them (don't add the private key). -```yaml -certificates_directory: /config/certs/ -``` - -## jwt_secret -<div markdown="1"> -type: string -{: .label .label-config .label-purple }  -default: "" -{: .label .label-config .label-blue } -required: yes -{: .label .label-config .label-red } -</div> - -Defines the secret used to craft JWT tokens leveraged by the identity -verification process. This can also be defined using a [secret](./secrets.md). +### default_redirection_url -```yaml -jwt_secret: v3ry_important_s3cr3t -``` - -## default_redirection_url -<div markdown="1"> -type: string -{: .label .label-config .label-purple }  -default: "" -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> +{{< confkey type="string" required="no" >}}  The default redirection URL is the URL where users are redirected when Authelia cannot detect the target URL where the  user was heading. @@ -56,19 +46,9 @@ can redirect them after the authentication process. However, when a user visits  considers the targeted website is the portal. In that case and if the default redirection URL is configured, the user is  redirected to that URL. If not defined, the user is not redirected after authentication. -```yaml -default_redirection_url: https://home.example.com:8080/ -``` +### default_2fa_method -## default_2fa_method -<div markdown="1"> -type: string -{: .label .label-config .label-purple }  -default: "" -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> +{{< confkey type="string" default="totp" required="no" >}}  Sets the default second factor method for users. This must be blank or one of the enabled methods. New users will by  default have this method selected for them. In addition if this was configured to `webauthn` and a user had the `totp` @@ -77,10 +57,32 @@ method, and the `totp` method was disabled in the configuration, the users' meth  Options are: -- totp -- webauthn -- mobile_push +* totp +* webauthn +* mobile_push  ```yaml  default_2fa_method: totp -```
\ No newline at end of file +``` + +### jwt_secret + +{{< confkey type="string" required="yes" >}} + +Defines the secret used to craft JWT tokens leveraged by the identity +verification process. This can also be defined using a [secret](../methods/secrets.md). + +### theme + +{{< confkey type="string " default="light" required="no" >}} + +There are currently 3 available themes for Authelia: + +* light (default) +* dark +* grey + +To enable automatic switching between themes, you can set `theme` to `auto`. The theme will be set to either `dark` or +`light` depending on the user's system preference which is determined using media queries. To read more technical +details about the media queries used, read the +[MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme). diff --git a/docs/configuration/logging.md b/docs/content/en/configuration/miscellaneous/logging.md index b0b5a95bf..c46bec794 100644 --- a/docs/configuration/logging.md +++ b/docs/content/en/configuration/miscellaneous/logging.md @@ -1,12 +1,19 @@  --- -layout: default -title: Logging -parent: Configuration -nav_order: 5 +title: "Log" +description: "Configuring the Log Settings." +lead: "Authelia performs logging to various locations. This section describes how to configure and tune this." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  configuration: +    parent: "miscellaneous" +weight: 199400 +toc: true +aliases: +  - /docs/configuration/logging.html  --- -# Logging -  The logging section tunes the logging settings.  ## Configuration @@ -22,14 +29,8 @@ log:  ## Options  ### level -<div markdown="1"> -type: string -{: .label .label-config .label-purple }  -default: info -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> + +{{< confkey type="string" default="info" required="no" >}}  Defines the level of logs used by Authelia. This level can be set to `trace`, `debug`, `info`, `warn`, or `error`. When  setting level to `trace`, you will generate a large amount of log entries and expose the `/debug/vars` and @@ -41,14 +42,8 @@ log:  ```  ### format -<div markdown="1"> -type: string -{: .label .label-config .label-purple }  -default: text -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> + +{{< confkey type="string" default="text" required="no" >}}  Defines the format of the logs written by Authelia. This format can be set to `json` or `text`. @@ -58,39 +53,40 @@ log:  ```  #### JSON format -``` + +```json  {"level":"info","msg":"Logging severity set to info","time":"2020-01-01T00:00:00+11:00"}  {"level":"info","msg":"Authelia is listening for non-TLS connections on 0.0.0.0:9091","time":"2020-01-01T00:00:00+11:00"}  ``` +  #### Text format -``` + +```text  time="2020-01-01T00:00:00+11:00" level=info msg="Logging severity set to info"  time="2020-01-01T00:00:00+11:00" level=info msg="Authelia is listening for non-TLS connections on 0.0.0.0:9091"  ```  ### file_path -<div markdown="1"> -type: string (path) -{: .label .label-config .label-purple }  -default: "" -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> + +{{< confkey type="string" required="no" >}}  Logs can be stored in a file when file path is provided. Otherwise logs are written to standard output. When setting the  level to `debug` or `trace` this will generate large amount of log entries. Administrators will need to ensure that  they rotate and/or truncate the logs over time to prevent significant long-term disk usage. +If you include the value `%d` in the filename it will replace this value with a date time indicative of the time +the logger was initialized using `2006-02-01T150405Z` as the format. + +#### File Path Examples + +__Standard Example:__ +  ```yaml  log:    file_path: /config/authelia.log  ``` -If you include the value `%d` in the filename it will replace this value with a date time indicative of the time -the logger was initialized in the following format: - -`2006-02-01T150405Z` +__Date Time Example:__  ```yaml  log: @@ -98,14 +94,8 @@ log:  ```  ### keep_stdout -<div markdown="1"> -type: boolean -{: .label .label-config .label-purple }  -default: false -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> + +{{< confkey type="boolean" default="false" required="no" >}}  Overrides the behaviour to redirect logging only to the `file_path`. If set to `true` logs will be written to both  standard output, and the defined logging location. @@ -113,4 +103,4 @@ standard output, and the defined logging location.  ```yaml  log:    keep_stdout: true -```
\ No newline at end of file +``` diff --git a/docs/content/en/configuration/miscellaneous/ntp.md b/docs/content/en/configuration/miscellaneous/ntp.md new file mode 100644 index 000000000..a8c50cbb0 --- /dev/null +++ b/docs/content/en/configuration/miscellaneous/ntp.md @@ -0,0 +1,70 @@ +--- +title: "NTP" +description: "Configuring the NTP Settings." +lead: "Authelia checks the system time is in sync with an NTP server. This section describes how to configure and tune this." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  configuration: +    parent: "miscellaneous" +weight: 199300 +toc: true +aliases: +  - /docs/configuration/ntp.html +--- + +Authelia has the ability to check the system time against an NTP server. Currently this only occurs at startup. This +section configures and tunes the settings for this check which is primarily used to ensure +[TOTP](../second-factor/time-based-one-time-password.md) can be accurately validated. + +In the instance of inability to contact the NTP server Authelia will just log an error and will continue to run. + +## Configuration + +```yaml +ntp: +  address: "time.cloudflare.com:123" +  version: 3 +  max_desync: 3s +  disable_startup_check: false +  disable_failure: false +``` + +## Options + +### address + +{{< confkey type="string" default="time.cloudflare.com:123" required="no" >}} + +Determines the address of the NTP server to retrieve the time from. The format is `<host>:<port>`, and both of these are +required. + +### version + +{{< confkey type="integer" default="4" required="no" >}} + +Determines the NTP version supported. Valid values are 3 or 4. + +### max_desync + +{{< confkey type="duration" default="3s" required="no" >}} + +*__Note:__ This setting uses the [duration notation format](../prologue/common.md#duration-notation-format). Please see +the [common options](../prologue/common.md#duration-notation-format) documentation for information on this format.* + +This is used to tune the acceptable desync from the time reported from the NTP server. + +### disable_startup_check + +{{< confkey type="boolean" default="false" required="no" >}} + +Setting this to true will disable the startup check entirely. + +### disable_failure + +{{< confkey type="boolean" default="false" required="no" >}} + +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 +in [max_desync](#max_desync) that Authelia fails to start and logs a fatal error. diff --git a/docs/content/en/configuration/miscellaneous/server.md b/docs/content/en/configuration/miscellaneous/server.md new file mode 100644 index 000000000..c49bda594 --- /dev/null +++ b/docs/content/en/configuration/miscellaneous/server.md @@ -0,0 +1,188 @@ +--- +title: "Server" +description: "Configuring the Server Settings." +lead: "Authelia runs an internal webserver. This section describes how to configure and tune this." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  configuration: +    parent: "miscellaneous" +weight: 199200 +toc: true +aliases: +  - /c/server +  - /docs/configuration/server.html +--- + +## Configuration + +```yaml +server: +  host: 0.0.0.0 +  port: 9091 +  path: "" +  read_buffer_size: 4096 +  write_buffer_size: 4096 +  enable_pprof: false +  enable_expvars: false +  disable_healthcheck: false +  tls: +    key: "" +    certificate: "" +    client_certificates: [] +  headers: +    csp_template: "" +``` + +## Options + +## host + +{{< confkey type="string" default="0.0.0.0" required="no" >}} + +Defines the address to listen on. See also [port](#port). Should typically be `0.0.0.0` or `127.0.0.1`, the former for +containerized environments and the later for daemonized environments like init.d and systemd. + +Note: If utilising an IPv6 literal address it must be enclosed by square brackets and quoted: + +```yaml +host: "[fd00:1111:2222:3333::1]" +``` + +### port + +{{< confkey type="integer" default="9091" required="no" >}} + +Defines the port to listen on. See also [host](#host). + +### path + +{{< confkey type="string " required="no" >}} + +Authelia by default is served from the root `/` location, either via its own domain or subdomain. + +Modifying this setting will allow you to serve Authelia out from a specified base path. Please note +that currently only a single level path is supported meaning slashes are not allowed, and only +alphanumeric characters are supported. + +__Example:__ + +```yaml +server: +  path: "" +``` + +*Works for https://auth.example.com/, https://example.com/, etc*. + +__Example:__ + +```yaml +server: +  path: authelia +``` + +*Works for https://auth.example.com/authelia/,  https://example.com/authelia/, etc*. + +### asset_path + +{{< confkey type="string " required="no" >}} + +Authelia by default serves all static assets from an embedded filesystem in the Go binary. + +Modifying this setting will allow you to override and serve specific assets for Authelia from a specified path. All +assets that can be overridden must be placed in the `asset_path`. The structure of this directory and the assets which +can be overriden is documented in the +[Sever Asset Overrides Reference Guide](../../reference/guides/server-asset-overrides.md). + +### read_buffer_size + +{{< confkey type="integer " default="4096" required="no" >}} + +Configures the maximum request size. The default of 4096 is generally sufficient for most use cases. + +### write_buffer_size + +{{< confkey type="integer " default="4096" required="no" >}} + +Configures the maximum response size. The default of 4096 is generally sufficient for most use cases. + +### enable_pprof + +{{< confkey type="boolean" default="false" required="no" >}} + +Enables the go pprof endpoints. + +### enable_expvars + +{{< confkey type="boolean" default="false" required="no" >}} + +Enables the go expvars endpoints. + +### disable_healthcheck + +{{< confkey type="boolean" default="false" required="no" >}} + +On startup Authelia checks for the existence of /app/healthcheck.sh and /app/.healthcheck.env and if both of these exist +it writes the configuration vars for the healthcheck to the /app/.healthcheck.env file. In instances where this is not +desirable it's possible to disable these interactions entirely. + +An example situation where this is the case is in Kubernetes when set security policies that prevent writing to the +ephemeral storage of a container or just don't want to enable the internal health check. + +### tls + +Authelia typically listens for plain unencrypted connections. This is by design as most environments allow to +security on lower areas of the OSI model. However it required, if you specify both the [tls key](#key) and +[tls certificate](#certificate) options, Authelia will listen for TLS connections. + +The key must be generated by the administrator and can be done by following the +[Generating an RSA Self Signed Certificate](../miscellaneous/guides.md#generating-an-rsa-self-signed-certificate) +guide provided a self-signed certificate is fit for purpose. If a self-signed certificate is fit for purpose is beyond +the scope of the documentation and if it is not fit for purpose we instead recommend generating a certificate signing +request or obtaining a certificate signed by one of the many ACME certificate providers. Methods to achieve this are +beyond the scope of this guide. + +#### key + +{{< confkey type="string" required="situational" >}} + +The path to the private key for TLS connections. Must be in DER base64/PEM format. + +#### certificate + +{{< confkey type="string" required="situational" >}} + +The path to the public certificate for TLS connections. Must be in DER base64/PEM format. + +#### client_certificates + +{{< confkey type="list(string)" required="situational" >}} + +The list of file paths to certificates used for authenticating clients. Those certificates can be root +or intermediate certificates. If no item is provided mutual TLS is disabled. + +### headers + +#### csp_template + +{{< confkey type="string" required="no" >}} + +This customizes the value of the Content-Security-Policy header. It will replace all instances of `${NONCE}` with the +nonce value of the Authelia react bundle. This is an advanced option to customize and you should do sufficient research +about how browsers utilize and understand this header before attempting to customize it. + +For example, the default CSP template is `default-src 'self'; object-src 'none'; style-src 'self' 'nonce-${NONCE}'`. + +## Additional Notes + +### Buffer Sizes + +The read and write buffer sizes generally should be the same. This is because when Authelia verifies +if the user is authorized to visit a URL, it also sends back nearly the same size response as the request. However +you're able to tune these individually depending on your needs. + +### Asset Overrides + +If replacing the Logo for your Authelia portal it is recommended to upload a transparent PNG of your desired logo. +Authelia will automatically resize the logo to an appropriate size to present in the frontend. diff --git a/docs/content/en/configuration/notifications/_index.md b/docs/content/en/configuration/notifications/_index.md new file mode 100644 index 000000000..a65ea9b99 --- /dev/null +++ b/docs/content/en/configuration/notifications/_index.md @@ -0,0 +1,9 @@ +--- +title : "Notifications" +description: "Notifiations Configuration" +lead: "" +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +weight: 107000 +--- diff --git a/docs/content/en/configuration/notifications/file.md b/docs/content/en/configuration/notifications/file.md new file mode 100644 index 000000000..2e720c0f2 --- /dev/null +++ b/docs/content/en/configuration/notifications/file.md @@ -0,0 +1,37 @@ +--- +title: "File System" +description: "Configuring the File Notifications Settings." +lead: "Authelia can save notifications to a file. This section describes how to configure this." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  configuration: +    parent: "notifications" +weight: 107300 +toc: true +aliases: +  - /docs/configuration/notifier/filesystem.html +--- + +It is recommended in a production environment that you do not use the file notification system, and that it should only +be used for testing purposes. See one of [the other methods](introduction.md) for a production ready solution. + +This method will use the plain text email template for readability purposes. + +## Configuration + +```yaml +notifier: +  disable_startup_check: false +  filesystem: +    filename: /config/notification.txt +``` + +## Options + +### filename + +{{< confkey type="string" required="yes" >}} + +The file to add email text to. If it doesn't exist it will be created. diff --git a/docs/content/en/configuration/notifications/introduction.md b/docs/content/en/configuration/notifications/introduction.md new file mode 100644 index 000000000..3eea1ce15 --- /dev/null +++ b/docs/content/en/configuration/notifications/introduction.md @@ -0,0 +1,53 @@ +--- +title: "Notifications" +description: "Configuring the Notifications Settings." +lead: "Authelia sends messages to users in order to verify their identity. This section describes how to configure this." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  configuration: +    parent: "notifications" +weight: 107100 +toc: true +--- + +Authelia sends messages to users in order to verify their identity. + +## Configuration + +```yaml +notifier: +  disable_startup_check: false +  template_path: '' +  filesystem: {} +  smtp: {} +``` + +## Options + +### disable_startup_check + +{{< confkey type="boolean" default="false" required="no" >}} + +The notifier has a startup check which validates the specified provider configuration is correct and will be able to +send emails. This can be disabled with the `disable_startup_check` option. + +### template_path + +{{< confkey type="string" required="no" >}} + +*__Note:__ you may configure this directory and add only add the templates you wish to override, any templates not +supplied in this folder will utilize the default templates.* + +This option allows the administrator to set a path to a directory where custom templates for notifications can be found. +The specifics are located in the +[Notification Templates Reference Guide](../../reference/guides/notification-templates.md). + +### filesystem + +The [filesystem](file.md) provider. + +### smtp + +The [smtp](smtp.md) provider. diff --git a/docs/configuration/notifier/smtp.md b/docs/content/en/configuration/notifications/smtp.md index 706904586..8c5231fd9 100644 --- a/docs/configuration/notifier/smtp.md +++ b/docs/content/en/configuration/notifications/smtp.md @@ -1,14 +1,19 @@  --- -layout: default -title: SMTP -parent: Notifier -grand_parent: Configuration -nav_order: 2 +title: "SMTP" +description: "Configuring the SMTP Notifications Settings." +lead: "Authelia can send emails to users through an SMTP server. This section describes how to configure this." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  configuration: +    parent: "notifications" +weight: 107200 +toc: true +aliases: +  - /docs/configuration/notifier/smtp.html  --- -# SMTP -**Authelia** can send emails to users through an SMTP server. -It can be configured as described below.  ## Configuration @@ -36,12 +41,8 @@ notifier:  ## Options  ### host -<div markdown="1"> -type: integer -{: .label .label-config .label-purple }  -required: yes -{: .label .label-config .label-red } -</div> + +{{< confkey type="integer" required="yes" >}}  The hostname of the SMTP server. @@ -53,145 +54,97 @@ host: "[fd00:1111:2222:3333::1]"  ### port -<div markdown="1"> -type: integer -{: .label .label-config .label-purple }  -required: yes -{: .label .label-config .label-red } -</div> +{{< confkey type="integer" required="yes" >}}  The port the SMTP service is listening on.  ### timeout -<div markdown="1"> -type: duration -{: .label .label-config .label-purple }  -default: 5s -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> + +{{< confkey type="duration" default="5s" required="no" >}}  The SMTP connection timeout.  ### username -<div markdown="1"> -type: string -{: .label .label-config .label-purple } -required: no -{: .label .label-config .label-green } -</div> + +{{< confkey type="string" required="no" >}}  The username sent for authentication with the SMTP server. Paired with the password.  ### password -<div markdown="1"> -type: string -{: .label .label-config .label-purple }  -required: no -{: .label .label-config .label-green } -</div> + +{{< confkey type="string" required="no" >}}  The password sent for authentication with the SMTP server. Paired with the username. Can also be defined using a -[secret](../secrets.md) which is the recommended for containerized deployments. +[secret](../methods/secrets.md) which is the recommended for containerized deployments. + +We recommend generating a random string with 64 characters or more for this purposes which can be done by following the +[Generating a Random Alphanumeric String](../miscellaneous/guides.md#generating-a-random-alphanumeric-string) +guide.  ### sender -<div markdown="1"> -type: string -{: .label .label-config .label-purple }  -required: yes -{: .label .label-config .label-red } -</div> + +{{< confkey type="string" required="yes" >}}  The sender is used to construct both the SMTP command `MAIL FROM` and to add the `FROM` header. This address must be -in [RFC5322](https://datatracker.ietf.org/doc/html/rfc5322#section-3.4) format. This means it must one of two formats: -- jsmith@domain.com -- John Smith <jsmith@domain.com> +in [RFC5322](https://www.rfc-editor.org/rfc/rfc5322.html#section-3.4) format. This means it must one of two formats: + +* jsmith@domain.com +* John Smith <jsmith@domain.com>  The `MAIL FROM` command sent to SMTP servers will not include the name portion, this is only set in the `FROM` as per  specifications.  ### identifier -<div markdown="1"> -type: string -{: .label .label-config .label-purple }  -default: localhost -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> + +{{< confkey type="string" default="localhost" required="no" >}}  The name to send to the SMTP server as the identifier with the HELO/EHLO command. Some SMTP providers like Google Mail  reject the message if it's localhost.  ### subject -<div markdown="1"> -type: string -{: .label .label-config .label-purple }  -default: [Authelia] {title} -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> + +{{< confkey type="string" default="[Authelia] {title}" required="no" >}}  This is the subject Authelia will use in the email, it has a single placeholder at present `{title}` which should  be included in all emails as it is the internal descriptor for the contents of the email.  ### startup_check_address -<div markdown="1"> -type: string -{: .label .label-config .label-purple }  -default: test@authelia.com -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -**Authelia** checks the SMTP server is valid at startup, one of the checks requires we ask the SMTP server if it can + +{{< confkey type="string" default="test@authelia.com" required="no" >}} + +__Authelia__ checks the SMTP server is valid at startup, one of the checks requires we ask the SMTP server if it can  send an email from us to a specific address, this is that address. No email is actually sent in the process. It is fine  to leave this as is, but you can customize it if you have issues or you desire to.  ### disable_require_tls -<div markdown="1"> -type: boolean -{: .label .label-config .label-purple }  -default: false -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> + +{{< confkey type="boolean" default="false" required="no" >}}  For security reasons the default settings for Authelia require the SMTP connection is encrypted by TLS. See [security]  for more information. This option disables this measure (not recommended).  ### disable_html_emails -<div markdown="1"> -type: boolean -{: .label .label-config .label-purple }  -default: false -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -This setting completely disables HTML formatting of emails and only sends text emails. **Authelia** by default sends + +{{< confkey type="boolean" default="false" required="no" >}} + +This setting completely disables HTML formatting of emails and only sends text emails. __Authelia__ by default sends  mixed emails which contain both HTML and text so this option is rarely necessary.  ### tls  Controls the TLS connection validation process. You can see how to configure the tls section -[here](../index.md#tls-configuration). - +[here](../prologue/common.md#tls-configuration).  ## Using Gmail -You need to generate an app password in order to use Gmail SMTP servers. The process is -described [here](https://support.google.com/accounts/answer/185833?hl=en) + +You need to generate an app password in order to use Gmail SMTP servers. The process is described +[here](https://support.google.com/accounts/answer/185833?hl=en).  ```yaml  notifier:    smtp:      username: myaccount@gmail.com -    # Password can also be set using a secret: https://www.authelia.com/docs/configuration/secrets.html +    # Password can also be set using a secret: https://www.authelia.com/configuration/methods/secrets/      password: yourapppassword      sender: admin@example.com      host: smtp.gmail.com diff --git a/docs/content/en/configuration/prologue/_index.md b/docs/content/en/configuration/prologue/_index.md new file mode 100644 index 000000000..7ed72af88 --- /dev/null +++ b/docs/content/en/configuration/prologue/_index.md @@ -0,0 +1,9 @@ +--- +title : "Prologue" +description: "Configuration Prologue" +lead: "" +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +weight: 100000 +--- diff --git a/docs/content/en/configuration/prologue/common.md b/docs/content/en/configuration/prologue/common.md new file mode 100644 index 000000000..43d28a8bf --- /dev/null +++ b/docs/content/en/configuration/prologue/common.md @@ -0,0 +1,109 @@ +--- +title: "Common" +description: "Common configuration options and notations." +lead: "This section details common configuration elements within the Authelia configuration. This section is mainly used as a reference for other sections as necessary." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  configuration: +    parent: "prologue" +weight: 100200 +toc: true +aliases: +  - /c/common +--- + +## Duration Notation Format + +We have implemented a string/integer based notation for configuration options that take a duration of time. This section +describes the implementation of this. You can use this implementation in various areas of configuration such as: + +* session: +  * expiration +  * inactivity +  * remember_me_duration +* regulation: +  * ban_time +  * find_time +* ntp: +  * max_desync +* webauthn: +  * timeout + +The way this format works is you can either configure an integer or a string in the specific configuration areas. If you +supply an integer, it is considered a representation of seconds. If you supply a string, it parses the string in blocks +of quantities and units (number followed by a unit letter).  For example `5h` indicates a quantity of 5 units of `h`. + +While you can use multiple of these blocks in combination, ee suggest keeping it simple and use a single value. + +### Unit Legend + +|  Unit   | Associated Letter | +|:-------:|:-----------------:| +|  Years  |         y         | +| Months  |         M         | +|  Weeks  |         w         | +|  Days   |         d         | +|  Hours  |         h         | +| Minutes |         m         | +| Seconds |         s         | + +### Examples + +|     Desired Value     |        Configuration Examples         | +|:---------------------:|:-------------------------------------:| +| 1 hour and 30 minutes | `90m` or `1h30m` or `5400` or `5400s` | +|         1 day         | `1d` or `24h` or `86400` or `86400s`  | +|       10 hours        | `10h` or `600m` or `9h60m` or `36000` | + +## Regular Expressions + +We have several sections of configuration that utilize regular expressions. It's recommended to validate your regex +manually either via tools like [Regex 101](https://regex101.com/) (ensure you pick the `Golang` option) or some other +means. + +It's important when attempting to utilize a backslash that it's utilized correctly. The YAML parser is likely to parse +this as you trying to use YAML escape syntax instead of regex escape syntax. To avoid this use single quotes instead of +no quotes or double quotes. + +Good Example: + +```yaml +domain_regex: '^(admin|secure)\.example\.com$' +``` + +Bad Example: + +```yaml +domain_regex: "^(admin|secure)\.example\.com$" +``` + +## TLS Configuration + +Various sections of the configuration use a uniform configuration section called TLS. Notably LDAP and SMTP. +This section documents the usage. + +### server_name + +{{< confkey type="string" required="no" >}} + +The key `server_name` overrides the name checked against the certificate in the verification process. Useful if you +require to use a direct IP address for the address of the backend service but want to verify a specific SNI. + +### skip_verify + +{{< confkey type="boolean" default="false" required="no" >}} + +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 +[certificates directory](../miscellaneous/introduction.md#certificates_directory). + +### minimum_version + +{{< confkey type="string" default="TLS1.2" required="no" >}} + +The key `minimum_version` controls the minimum TLS version Authelia will use when opening TLS connections. +The possible values are `TLS1.3`, `TLS1.2`, `TLS1.1`, `TLS1.0`. Anything other than `TLS1.3` or `TLS1.2` +are very old and deprecated. You should avoid using these and upgrade your backend service instead of decreasing +this value. diff --git a/docs/content/en/configuration/prologue/introduction.md b/docs/content/en/configuration/prologue/introduction.md new file mode 100644 index 000000000..7a19ef039 --- /dev/null +++ b/docs/content/en/configuration/prologue/introduction.md @@ -0,0 +1,48 @@ +--- +title: "Prologue" +description: "An introduction into configuring Authelia." +lead: "An introduction into configuring Authelia." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  configuration: +    parent: "prologue" +weight: 100100 +toc: true +--- + +## Documentation + +We document the configuration in two ways: + +1. The [YAML] configuration template +   [config.template.yml](https://github.com/authelia/authelia/blob/master/config.template.yml) has comments with very +   limited documentation on the effective use of a particular option. All documentation lines start with `##`. Lines +   starting with a single `#` are [YAML] configuration options which are commented to disable them or as examples. +2. This documentation site. Generally each section of the configuration is in its own section of the documentation +   site. Each configuration option is listed in its relevant section as a heading, under that heading generally are two +   or three colored labels. +   * The `type` label is purple and indicates the [YAML] value type of the variable. It optionally includes some +     additional information in parentheses. +   * The `default` label is blue and indicates the default value if you don't define the option at all. This is not the +     same value as you will see in the examples in all instances, it is the value set when blank or undefined. +   * The `required` label changes color. When required it will be red, when not required it will be green, when the +     required state depends on another configuration value it is yellow. + +## Validation + +Authelia validates the configuration when it starts. This process checks multiple factors including configuration keys +that don't exist, configuration keys that have changed, the values of the keys are valid, and that a configuration +key isn't supplied at the same time as a secret for the same configuration option. + +You may also optionally validate your configuration against this validation process manually by using the +`authelia validate-config` command. This command is useful prior to upgrading to prevent configuration changes from +impacting downtime in an upgrade. This process does not validate integrations, it only checks that your configuration +syntax is valid. + +```bash +authelia validate-config --config configuration.yml +``` + +[YAML]: https://yaml.org/ diff --git a/docs/content/en/configuration/prologue/migration.md b/docs/content/en/configuration/prologue/migration.md new file mode 100644 index 000000000..242a01f51 --- /dev/null +++ b/docs/content/en/configuration/prologue/migration.md @@ -0,0 +1,97 @@ +--- +title: "Migration" +description: "Information regarding configuration migration." +lead: "An introduction into configuring Authelia." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  configuration: +    parent: "prologue" +weight: 100300 +toc: true +aliases: +  - /docs/configuration/migration.html +--- + +This section documents changes in the configuration which may require manual migration by the administrator. Typically +this only occurs when a configuration key is renamed or moved to a more appropriate location. + +## Format + +The migrations are formatted in a table with the old key and the new key. Periods indicate a different section which can +be represented in [YAML] as a dictionary i.e. it's indented. + +In our table `server.host` with a value of `0.0.0.0` is represented in [YAML] like this: + +```yaml +server: +  host: 0.0.0.0 +``` + +## Policy + +Our deprecation policy for configuration keys is 3 minor versions. For example if a configuration option is deprecated +in version 4.30.0, it will remain as a warning for 4.30.x, 4.31.x, and 4.32.x; then it will become a fatal error in +4.33.0+. + +## Migrations + +### 4.33.0 + +The options deprecated in version [4.30.0](#4300) have been fully removed as per our deprecation policy and warnings +logged for users. + +### 4.30.0 + +The following changes occurred in 4.30.0: + +| Previous Key  |        New Key         | +|:-------------:|:----------------------:| +|     host      |      server.host       | +|     port      |      server.port       | +|    tls_key    |     server.tls.key     | +|   tls_cert    | server.tls.certificate | +|   log_level   |       log.level        | +| log_file_path |     log.file_path      | +|  log_format   |       log.format       | + +*__Please Note:__ you can no longer define secrets for providers that you are not using. For example if you're using the +[filesystem notifier](../notifications/introduction.md) you must ensure that the `AUTHELIA_NOTIFIER_SMTP_PASSWORD_FILE` +environment variable or other environment variables set. This also applies to other providers like +[storage](../storage/introduction.md) and [authentication backend](../first-factor/introduction.md).* + +#### Kubernetes 4.30.0 + +*__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 +[configure the enableServiceLinks](../../integration/kubernetes/introduction/index.md#enable-service-links) option.* + +### 4.25.0 + +The following changes occurred in 4.25.0: + +|                  Previous Key                   |                     New Key                     | +|:-----------------------------------------------:|:-----------------------------------------------:| +|   authentication_backend.ldap.tls.skip_verify   |   authentication_backend.ldap.tls.skip_verify   | +| authentication_backend.ldap.minimum_tls_version | authentication_backend.ldap.tls.minimum_version | +|        notifier.smtp.disable_verify_cert        |          notifier.smtp.tls.skip_verify          | +|           notifier.smtp.trusted_cert            |             certificates_directory              | + +*__Please Note:__ `certificates_directory` is not a direct replacement for the `notifier.smtp.trusted_cert`, instead +of being the path to a specific file it is a path to a directory containing certificates trusted by Authelia. This +affects other services like LDAP as well.* + +### 4.7.0 + +The following changes occurred in 4.7.0: + +| Previous Key |  New Key  | +|:------------:|:---------:| +|  logs_level  | log_level | +|  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 +are using [4.30.0](#4.30.0) or newer instead of the new keys listed here.* + +[YAML]: https://yaml.org/ diff --git a/docs/content/en/configuration/second-factor/_index.md b/docs/content/en/configuration/second-factor/_index.md new file mode 100644 index 000000000..ddf76c132 --- /dev/null +++ b/docs/content/en/configuration/second-factor/_index.md @@ -0,0 +1,9 @@ +--- +title : "Second Factor" +description: "Second Factor methods configuration" +lead: "" +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +weight: 103000 +--- diff --git a/docs/content/en/configuration/second-factor/duo.md b/docs/content/en/configuration/second-factor/duo.md new file mode 100644 index 000000000..f9cc29e8d --- /dev/null +++ b/docs/content/en/configuration/second-factor/duo.md @@ -0,0 +1,71 @@ +--- +title: "Duo / Mobile Push" +description: "Configuring the Duo Mobile Push Notification Second Factor Method." +lead: "" +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  configuration: +    parent: "second-factor" +weight: 103200 +toc: true +aliases: +  - /docs/configuration/duo-push-notifications.html +--- + +Authelia supports mobile push notifications relying on [Duo]. + +Follow the instructions in the dedicated [documentation](../../overview/authentication/push-notification/index.md) for +instructions on how to set up push notifications in Authelia. + +__Note:__ The configuration options in the following sections are noted as required. They are however only required when +you have this section defined. i.e. if you don't wish to use the [Duo] push notifications you can just not define this +section of the configuration. + +## Configuration + +```yaml +duo_api: +  disable: false +  hostname: api-123456789.example.com +  integration_key: ABCDEF +  secret_key: 1234567890abcdefghifjkl +  enable_self_enrollment: false +``` + +## Options + +### Disable + +{{< confkey type="boolean" default="false" required="no" >}} + +Disables Duo. If the hostname, integration_key, and secret_key are all empty strings or undefined this is automatically +true. + +### hostname + +{{< confkey type="string" required="yes" >}} + +The [Duo] API hostname supplied by [Duo]. + +### integration_key + +{{< confkey type="string" required="yes" >}} + +The non-secret [Duo] integration key. Similar to a client identifier. + +### secret_key + +{{< confkey type="string" required="yes" >}} + +The secret [Duo] key used to verify your application is valid. It's recommended to set this via a +[secret](../methods/secrets.md). + +### enable_self_enrollment + +{{< confkey type="boolean" default="false" required="no" >}} + +Enables [Duo] device self-enrollment from within the Authelia portal. + +[Duo]: https://duo.com/ diff --git a/docs/content/en/configuration/second-factor/introduction.md b/docs/content/en/configuration/second-factor/introduction.md new file mode 100644 index 000000000..ebf14f803 --- /dev/null +++ b/docs/content/en/configuration/second-factor/introduction.md @@ -0,0 +1,25 @@ +--- +title: "Second Factor" +description: "Configuring Authelia Second Factor Authentication." +lead: "Authelia provides a number of 2FA methods. This section describes these methods." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  configuration: +    parent: "second-factor" +weight: 103100 +toc: true +--- + +## One Time Password + +Authelia supports configuring [Time-based One Time Password](time-based-one-time-password.md)'s. + +## Security Key + +Authelia supports configuring [WebAuthn](webauthn.md) Security Keys. + +## Mobile Push + +Authelia supports configuring [Duo](duo.md) to provide a mobile push service. diff --git a/docs/configuration/one-time-password.md b/docs/content/en/configuration/second-factor/time-based-one-time-password.md index 2b85a3d78..e95507a14 100644 --- a/docs/configuration/one-time-password.md +++ b/docs/content/en/configuration/second-factor/time-based-one-time-password.md @@ -1,17 +1,31 @@  --- -layout: default -title: Time-based One-Time Password -parent: Configuration -nav_order: 16 +title: "Time-based One Time Password" +description: "Configuring the Time-based One Time Password Second Factor Method." +lead: "Authelia supports utilizing time-based one-time passwords as a 2FA method." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  configuration: +    parent: "second-factor" +weight: 103300 +toc: true +aliases: +  - /c/totp +  - /docs/configuration/one-time-password.html  --- -# Time-based One-Time Password +The OTP method *Authelia* uses is the Time-Based One-Time Password Algorithm (TOTP) [RFC6238] which is an extension of +HMAC-Based One-Time Password Algorithm (HOTP) [RFC4226]. -The OTP method _Authelia_ uses is the Time-Based One-Time Password Algorithm (TOTP) [RFC6238] which is an extension of -HMAC-Based One-Time Password Algorithm (HOTP) [RFC4226]. You have the option to tune the settings of theTOTP generation,  -and you can see a full example of TOTP configuration below, as well as sections describing them. +You have the option to tune the settings of the TOTP generation, and you can see a full example of TOTP configuration +below, as well as sections describing them. + +Keep in mind the default settings are chosen for compatibility. Many applications do not support digits other than 6, +and many only support SHA1.  ## Configuration +  ```yaml  totp:    disable: false @@ -26,26 +40,14 @@ totp:  ## Options  ### disable -<div markdown="1"> -type: boolean -{: .label .label-config .label-purple }  -default: false -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> + +{{< confkey type="boolean" default="false" required="no" >}}  This disables One-Time Password (TOTP) if set to true.  ### issuer -<div markdown="1"> -type: string -{: .label .label-config .label-purple }  -default: Authelia -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> + +{{< confkey type="string" default="Authelia" required="no" >}}  Applications generating one-time passwords usually display an issuer to  differentiate applications registered by the user. @@ -54,48 +56,37 @@ Authelia allows customisation of the issuer to differentiate the entry created  by Authelia from others.  ### algorithm -<div markdown="1"> -type: string -{: .label .label-config .label-purple }  -default: sha1 -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -_**Important Note:** Many TOTP applications do not support this option. It is strongly advised you find out which + +{{< confkey type="string" default="sha1" required="no" >}} + +*__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 -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  -please see [Issue 2650](https://github.com/authelia/authelia/issues/2650)._ +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 +please see [Issue 2650](https://github.com/authelia/authelia/issues/2650).*  The algorithm used for the TOTP key.  Possible Values (case-insensitive): -- `sha1` -- `sha256` -- `sha512` + +* `sha1` +* `sha256` +* `sha512`  Changing this value only affects newly registered TOTP keys. See the [Registration](#registration) section for more  information.  ### digits -<div markdown="1"> -type: integer -{: .label .label-config .label-purple }  -default: 6 -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -_**Important Note:** Some TOTP applications do not support this option. It is strongly advised you find out which + +{{< confkey type="integer" default="6" required="no" >}} + +*__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  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 -please see [Issue 2650](https://github.com/authelia/authelia/issues/2650)._ +please see [Issue 2650](https://github.com/authelia/authelia/issues/2650).* -The number of digits a user needs to input to perform authentication. It's generally not recommended for this to be  +The number of digits a user needs to input to perform authentication. It's generally not recommended for this to be  altered as many TOTP applications do not support anything other than 6. What's worse is some TOTP applications allow  you to add the key, but do not use the correct number of digits specified by the key. @@ -105,16 +96,10 @@ Changing this value only affects newly registered TOTP keys. See the [Registrati  information.  ### period -<div markdown="1"> -type: integer -{: .label .label-config .label-purple }  -default: 30 -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -The period of time in seconds between key rotations or the time element of TOTP. Please see the  + +{{< confkey type="integer" default="30" required="no" >}} + +The period of time in seconds between key rotations or the time element of TOTP. Please see the  [input validation](#input-validation) section for how this option and the [skew](#skew) option interact with each other.  It is recommended to keep this value set to 30, the minimum is 15. @@ -123,50 +108,40 @@ Changing this value only affects newly registered TOTP keys. See the [Registrati  information.  ### skew -<div markdown="1"> -type: integer -{: .label .label-config .label-purple }  -default: 1 -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -The number of one time passwords either side of the current valid one time password that should also be considered valid.  + +{{< confkey type="integer" default="1" required="no" >}} + +The number of one time passwords either side of the current valid one time password that should also be considered valid.  The default of 1 results in 3 one time passwords valid. A setting of 2 would result in 5. With the default period of 30 -this would result in 90 and 150 seconds of valid one time passwords respectively. Please see the  +this would result in 90 and 150 seconds of valid one time passwords respectively. Please see the  [input validation](#input-validation) section for how this option and the [period](#period) option interact with each  other.  Changing this value affects all TOTP validations, not just newly registered ones.  ### secret_size -<div markdown="1"> -type: integer -{: .label .label-config .label-purple }  -default: 32 -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -The length in bytes of generated shared secrets. The minimum is 20 (or 160 bits), and the default is 32 (or 256 bits).  + +{{< confkey type="integer" default="32" required="no" >}} + +The length in bytes of generated shared secrets. The minimum is 20 (or 160 bits), and the default is 32 (or 256 bits).  In most use cases 32 is sufficient. Though some authenticators may have issues with more than the minimum. Our minimum  is the recommended value in [RFC4226], though technically according to the specification 16 bytes (or 128 bits) is the  minimum.  ## Registration -When users register their TOTP device for the first time, the current [issuer](#issuer), [algorithm](#algorithm), and  + +When users register their TOTP device for the first time, the current [issuer](#issuer), [algorithm](#algorithm), and  [period](#period) are used to generate the TOTP link and QR code. These values are saved to the database for future -validations.  +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 -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.  ## Input Validation -The period and skew configuration parameters affect each other. The default values are a period of 30 and a skew of 1.  + +The period and skew configuration parameters affect each other. The default values are a period of 30 and a skew of 1.  It is highly recommended you do not change these unless you wish to set skew to 0.  These options affect security by changing the length of time a one-time password is valid for. The formula to calculate @@ -174,17 +149,19 @@ the effective validity period is `period + (period * skew * 2)`. For example per  seconds of validity, and period 30 and skew 2 would result in 150 seconds of validity.  ## System time accuracy +  It's important to note that if the system time is not accurate enough then clients will seemingly not generate valid -passwords for TOTP. Conversely this is the same when the client time is not accurate enough. This is due to the Time-based -One Time Passwords being time-based. +passwords for TOTP. Conversely this is the same when the client time is not accurate enough. This is due to the +Time-based One Time Passwords being time-based. -Authelia by default checks the system time against an [NTP server](./ntp.md#address) on startup. This helps to prevent -a time synchronization issue on the server being an issue. There is however no effective and reliable way to check the -clients. +Authelia by default checks the system time against an [NTP server](../miscellaneous/ntp.md) on startup. This helps to +prevent a time synchronization issue on the server being an issue. There is however no effective and reliable way to +check the clients.  ## Encryption -The TOTP secret is [encrypted](storage/index.md#encryption_key) 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. + +The TOTP secret is [encrypted](../storage/introduction.md#encryption_key) 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 may be inconvenient for some users who wish to export TOTP keys from Authelia to other services. As such there is  a command specifically for exporting TOTP configurations from the database. These commands require the configuration or @@ -192,21 +169,21 @@ 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): -```shell -$ authelia storage totp export --format uri +```bash +authelia storage totp export --format uri  ```  Export as CSV: -```shell -$ authelia storage totp export --format csv +```bash +authelia storage totp export --format csv  ```  Help: -```shell -$ authelia storage totp export --help +```bash +authelia storage totp export --help  ``` -[RFC4226]: https://datatracker.ietf.org/doc/html/rfc4226 -[RFC6238]: https://datatracker.ietf.org/doc/html/rfc6238
\ No newline at end of file +[RFC4226]: https://www.rfc-editor.org/rfc/rfc4226.html +[RFC6238]: https://www.rfc-editor.org/rfc/rfc6238.html diff --git a/docs/configuration/webauthn.md b/docs/content/en/configuration/second-factor/webauthn.md index d8ac50e19..c194a16b0 100644 --- a/docs/configuration/webauthn.md +++ b/docs/content/en/configuration/second-factor/webauthn.md @@ -1,13 +1,21 @@  --- -layout: default -title: Webauthn -parent: Configuration -nav_order: 17 +title: "WebAuthn" +description: "Configuring the WebAuthn Second Factor Method." +lead: "WebAuthn is the modern browser security key specification that Authelia supports. This section describes configuring it." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  configuration: +    parent: "second-factor" +weight: 103400 +toc: true +aliases: +  - /docs/configuration/webauthn.html  --- -The Webauthn section has tunable options for the Webauthn implementation. -  ## Configuration +  ```yaml  webauthn:    disable: false @@ -20,46 +28,29 @@ webauthn:  ## Options  ### disable -<div markdown="1"> -type: boolean -{: .label .label-config .label-purple }  -default: false -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> -This disables Webauthn if set to true. +{{< confkey type="boolean" default="false" required="no" >}} + +This disables WebAuthn if set to true.  ### display_name -<div markdown="1"> -type: string -{: .label .label-config .label-purple }  -default: Authelia -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> + +{{< confkey type="string" default="Authelia" required="no" >}}  Sets the display name which is sent to the client to be displayed. It's up to individual browsers and potentially  individual operating systems if and how they display this information. -See the [W3C Webauthn Documentation](https://www.w3.org/TR/webauthn-2/#dom-publickeycredentialentity-name) for more information. +See the [W3C WebAuthn Documentation](https://www.w3.org/TR/webauthn-2/#dom-publickeycredentialentity-name) for more +information.  ### attestation_conveyance_preference -<div markdown="1"> -type: string -{: .label .label-config .label-purple }  -default: indirect -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> + +{{< confkey type="string" default="indirect" required="no" >}}  Sets the conveyance preference. Conveyancing allows collection of attestation statements about the authenticator such as  the AAGUID. The AAGUID indicates the model of the device. -See the [W3C Webauthn Documentation](https://www.w3.org/TR/webauthn-2/#enum-attestation-convey) for more information. +See the [W3C WebAuthn Documentation](https://www.w3.org/TR/webauthn-2/#enum-attestation-convey) for more information.  Available Options: @@ -70,18 +61,12 @@ Available Options:  |  direct  |               The client will be instructed to perform conveyancing with an attestation statement directly signed by the device               |  ### user_verification -<div markdown="1"> -type: string -{: .label .label-config .label-purple }  -default: preferred -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> -Sets the user verification preference.  +{{< confkey type="string" default="preferred" required="no" >}} -See the [W3C Webauthn Documentation](https://www.w3.org/TR/webauthn-2/#enum-userVerificationRequirement) for more information. +Sets the user verification preference. + +See the [W3C WebAuthn Documentation](https://www.w3.org/TR/webauthn-2/#enum-userVerificationRequirement) for more information.  Available Options: @@ -92,18 +77,14 @@ Available Options:  |  required   | The client will ask the user for verification or will fail if the device does not support verification |  ### timeout -<div markdown="1"> -type: string (duration)  -{: .label .label-config .label-purple }  -default: 60s -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> - -This adjusts the requested timeout for a Webauthn interaction. The period of time is in -[duration notation format](index.md#duration-notation-format). + +{{< confkey type="duration" default="60s" required="no" >}} + +*__Note:__ This setting uses the [duration notation format](../prologue/common.md#duration-notation-format). Please see +the [common options](../prologue/common.md#duration-notation-format) documentation for information on this format.* + +This adjusts the requested timeout for a WebAuthn interaction.  ## FAQ -See the [Security Key FAQ](../features/2fa/security-key.md#faq) for the FAQ. +See the [Security Key FAQ](../../overview/authentication/security-key/index.md#faq) for the FAQ. diff --git a/docs/content/en/configuration/security/_index.md b/docs/content/en/configuration/security/_index.md new file mode 100644 index 000000000..077d90171 --- /dev/null +++ b/docs/content/en/configuration/security/_index.md @@ -0,0 +1,9 @@ +--- +title: "Security" +description: "Security Related Configuration" +lead: "" +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +weight: 104000 +--- diff --git a/docs/configuration/access-control.md b/docs/content/en/configuration/security/access-control.md index 7f43ca3b7..32ba44151 100644 --- a/docs/configuration/access-control.md +++ b/docs/content/en/configuration/security/access-control.md @@ -1,14 +1,20 @@  --- -layout: default -title: Access Control -parent: Configuration -nav_order: 1 +title: "Access Control" +description: "Configuring the Access Control or RBAC settings." +lead: "Authelia supports a comprehensive access control system. This section describes configuring this." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  configuration: +    parent: "security" +weight: 104200 +toc: true +aliases: +  - /c/acl +  - /docs/configuration/access-control.html  --- -# Access Control -{: .no_toc } - -  ## Configuration  ```yaml @@ -17,17 +23,16 @@ access_control:    networks:    - name: internal      networks: -    - 10.0.0.0/8 -    - 172.16.0.0/12 -    - 192.168.0.0/18 - +    - '10.0.0.0/8' +    - '172.16.0.0/12' +    - '192.168.0.0/18'    rules: -  - domain: 'public.example.com' -    domain_regex: '^\d+\.public.example.com$' +  - domain: 'private.example.com' +    domain_regex: '^(\d+\-)?priv-img.example.com$'      policy: one_factor      networks: -    - internal -    - 1.1.1.1 +    - 'internal' +    - '1.1.1.1'      subject:      - ['user:adam']      - ['user:fred'] @@ -42,14 +47,8 @@ access_control:  ## Options  ### default_policy -<div markdown="1"> -type: string -{: .label .label-config .label-purple }  -default: deny -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> + +{{< confkey type="string" default="deny" required="no" >}}  The default [policy](#policies) defines the policy applied if no [rules](#rules) section apply to the information known  about the request. It is recommended that this is configured to [deny](#deny) for security reasons. Sites which you do @@ -59,41 +58,32 @@ Authelia at all for performance reasons.  See [Policies](#policies) for more information.  ### networks (global) -<div markdown="1"> -type: list -{: .label .label-config .label-purple }  -required: no -{: .label .label-config .label-green } -</div> - -The main/global networks section contains a list of networks with a name label that can be reused in the  -[rules](#networks) section instead of redefining the same networks over and over again. This additionally makes  + +{{< confkey type="list" required="no" >}} + +The main/global networks section contains a list of networks with a name label that can be reused in the +[rules](#networks) section instead of redefining the same networks over and over again. This additionally makes  complicated network related configuration a lot cleaner and easier to read.  This section has two options, `name` and `networks`. Where the `networks` section is a list of IP addresses in CIDR -notation and where `name` is a friendly name to label the collection of networks for reuse in the [networks](#networks)  +notation and where `name` is a friendly name to label the collection of networks for reuse in the [networks](#networks)  section of the [rules](#rules) section below.  This configuration option *does nothing* by itself, it's only useful if you use these aliases in the [rules](#networks)  section below.  ### rules -<div markdown="1"> -type: list -{: .label .label-config .label-purple }  -required: no -{: .label .label-config .label-green } -</div> + +{{< confkey type="list" required="no" >}}  The rules have many configuration options. A rule matches when all criteria of the rule match the request excluding the  `policy` which is the [policy](#policies) applied to the request.  A rule defines two primary things: -* the policy applied when all criteria match. -   +* the policy applied when all criteria match  * the matching criteria of the request presented to the reverse proxy -   +  The criteria is broken into several parts:  * [domain](#domain): domain or list of domains targeted by the request. @@ -104,51 +94,42 @@ The criteria is broken into several parts:  * [methods](#methods): the http methods used in the request.  A rule is matched when all criteria of the rule match. Rules are evaluated in sequential order, and the first rule that -is a match for a given request is the rule applied; subsequent rules have *no effect*. This is particularly  -**important** for bypass rules. Bypass rules should generally appear near the top of the rules list. However you need to  -carefully evaluate your rule list **in order** to see which rule matches a particular scenario. A comprehensive  +is a match for a given request is the rule applied; subsequent rules have *no effect*. This is particularly +__important__ for bypass rules. Bypass rules should generally appear near the top of the rules list. However you need to +carefully evaluate your rule list __in order__ to see which rule matches a particular scenario. A comprehensive  understanding of how rules apply is also recommended.  #### domain -<div markdown="1"> -type: list(string) -{: .label .label-config .label-purple }  -required: yes -{: .label .label-config .label-red } -</div> - -_**Required:** This criteria OR the [domain_regex](#domain_regex) criteria are required._ - -This criteria matches the domain name and has two methods of configuration, either as a single string or as a list of  -strings. When it's a list of strings the rule matches when **any** of the domains in the list match the request domain. -When used in conjunction with [domain_regex](#domain_regex) the rule will match when either the [domain](#domain) or the  + +{{< confkey type="list(string)" required="yes" >}} + +*__Required:__ This criteria and/or the [domain_regex](#domain_regex) criteria are required.* + +This criteria matches the domain name and has two methods of configuration, either as a single string or as a list of +strings. When it's a list of strings the rule matches when __any__ of the domains in the list match the request domain. +When used in conjunction with [domain_regex](#domain_regex) the rule will match when either the [domain](#domain) or the  [domain_regex](#domain_regex) criteria matches.  Rules may start with a few different wildcards: -* The standard wildcard is `*.`, which when in front of a domain means that any subdomain is effectively a match. For  +* The standard wildcard is `*.`, which when in front of a domain means that any subdomain is effectively a match. For    example `*.example.com` would match `abc.example.com` and `secure.example.com`. When using a wildcard like this the -  string **must** be quoted like `"*.example.com"`. -     +  string __must__ be quoted like `"*.example.com"`.  * The user wildcard is `{user}.`, which when in front of a domain dynamically matches the username of the user. For -  example `{user}.example.com` would match `fred.example.com` if the user logged in was named `fred`. _**Warning:** this is +  example `{user}.example.com` would match `fred.example.com` if the user logged in was named `fred`. *__Warning:__ this is    officially deprecated as the [domain_regex](#domain_regex) criteria completely replaces the functionality in a much    more useful way. It is strongly recommended you do not use this as it will be removed in a future version, most likely -  v5.0.0._ -   +  v5.0.0.*  * The group wildcard is `{group}.`, which when in front of a domain dynamically matches if the logged in user has the    group in that location. For example `{group}.example.com` would match `admins.example.com` if the user logged in was -  in the following groups `admins,users,people` because `admins` is in the list. _**Warning:** this is -  officially deprecated as the [domain_regex](#domain_regex) criteria completely replaces the functionality in a much -  more useful way. It is strongly recommended you do not use this as it will be removed in a future version, most likely -  v5.0.0._ +  in the following groups `admins,users,people` because `admins` is in the list. -Domains in this section must be the domain configured in the [session](./session/index.md#domain) configuration or -subdomains of that domain. This is because a website can only write cookies for a domain it is part of. It is +Domains in this section must be the domain configured in the [session](../session/introduction.md#domain) configuration +or subdomains of that domain. This is because a website can only write cookies for a domain it is part of. It is  theoretically possible for us to do this with multiple domains however we would have to be security conscious in our  implementation, and it is not currently a priority. -Examples: +##### Examples  *Single domain of `*.example.com` matched. All rules in this list are effectively the same rule just expressed in  different ways.* @@ -163,7 +144,7 @@ access_control:      policy: bypass  ``` -*Multiple domains matched. These rules would match either `apple.example.com` or `orange.example.com`. All rules in this +*Multiple domains matched. These rules will match either `apple.example.com` or `orange.example.com`. All rules in this  list are effectively the same rule just expressed in different ways.*  ```yaml @@ -177,27 +158,35 @@ access_control:      policy: bypass  ``` +*Multiple domains matched either via a static domain or via a [domain_regex](#domain_regex). This rule will match +either `apple.example.com`, `pub-data.example.com`, or `img-data.example.com`.* + +```yaml +access_control: +  rules: +  - domain: 'apple.example.com' +    domain_regex: '^(pub|img)-data\.example\.com$' +    policy: bypass +``` +  ### domain_regex -<div markdown="1"> -type: list(string) -{: .label .label-config .label-purple }  -required: yes -{: .label .label-config .label-red } -</div> -_**Required:** This criteria OR the [domain](#domain) criteria are required._ +{{< confkey type="list(string)" required="yes" >}} + +*__Required:__ This criteria and/or the [domain](#domain) criteria are required.* -_**Important Note:** If you intend to use this criteria with a bypass rule please read  -[bypass and subjects](#bypass-and-user-identity) before doing so._ +*__Important Note:__ If you intend to use this criteria with a bypass rule please read +[bypass and subjects](#bypass-and-user-identity) before doing so.* -_**Important Note:** to utilize regex you must escape it properly. See [regex](./index.md#regex) for more information._ +*__Important Note:__ to utilize regex you must escape it properly. See +[regular expressions](../prologue/common.md#regular-expressions) for more information.*  This criteria matches the domain name and has two methods of configuration, either as a single string or as a list of -strings. When it's a list of strings the rule matches when **any** of the domains in the list match the request domain. +strings. When it's a list of strings the rule matches when __any__ of the domains in the list match the request domain.  When used in conjunction with [domain](#domain) the rule will match when either the [domain](#domain) or the  [domain_regex](#domain_regex) criteria matches. -This criteria takes any standard go regex pattern to match the requests. We additionally utilize two special named match  +This criteria takes any standard go regex pattern to match the requests. We additionally utilize two special named match  groups which match attributes of the user:  | Group Name |    Match Value    | @@ -207,61 +196,65 @@ groups which match attributes of the user:  For the group match it matches if the user has any group name that matches, and both matches are case-insensitive due to  the fact domain names should not be compared in a case-sensitive way as per the -[RFC4343](https://datatracker.ietf.org/doc/html/rfc4343) abstract and  -[RFC3986](https://www.rfc-editor.org/rfc/rfc3986#section-3.2.2) section 3.2.2. +[RFC4343](https://www.rfc-editor.org/rfc/rfc4343.html) abstract and +[RFC3986 Section 3.2.2](https://www.rfc-editor.org/rfc/rfc3986#section-3.2.2). + +#### Examples -Examples: +*An advanced multiple domain regex example with user/group matching. This will match the user `john` in the groups +`example` and `example1`, when the request is made to `user-john.example.com`, `group-example.example.com`, or +`group-example1.example.com`, it would not match when the request is made to `user-fred.example.com` or +`group-admin.example.com`.*  ```yaml  access_control:    rules: -  - domain:  -    - apple.example.com -    - banana.example.com -    policy: bypass    - domain_regex:      - '^user-(?P<User>\w+)\.example\.com$'      - '^group-(?P<Group>\w+)\.example\.com$'      policy: one_factor  ``` +*Multiple domains example, one with a static domain and one with a regex domain. This will match requests to +`protected.example.com`, `img-private.example.com`, or `data-private.example.com`.* + +```yaml +access_control: +  rules: +  - domain: 'protected.example.com' +  - domain_regex: '^(img|data)-private\.example\.com' +    policy: one_factor +``` +  #### policy -<div markdown="1"> -type: string -{: .label .label-config .label-purple }  -required: yes -{: .label .label-config .label-red } -</div> + +{{< confkey type="string" required="yes" >}}  The specific [policy](#policies) to apply to the selected rule. This is not criteria for a match, this is the action to  take when a match is made. -### subject -<div markdown="1"> -type: list(list(string)) -{: .label .label-config .label-purple }  -required: no -{: .label .label-config .label-green } -</div> - -***Note:** this rule criteria **may not** be used for the `bypass` policy the minimum required authentication level to -identify the subject is `one_factor`. We have taken an opinionated stance on preventing this configuration as it could  -result in problematic security scenarios with badly thought out configurations and cannot see a likely configuration  -scenario that would require users to do this. If you have a scenario in mind please open an  +#### subject + +{{< confkey type="list(list(string))" required="no" >}} + +*__Note:__ this rule criteria __may not__ be used for the `bypass` policy the minimum required authentication level to +identify the subject is `one_factor`. We have taken an opinionated stance on preventing this configuration as it could +result in problematic security scenarios with badly thought out configurations and cannot see a likely configuration +scenario that would require users to do this. If you have a scenario in mind please open an  [issue](https://github.com/authelia/authelia/issues/new) on GitHub.* -This criteria matches identifying characteristics about the subject. This is either user's name or the name of the -group a user belongs to. This allows you to effectively control exactly what each user is authorized to access or to -specifically require two-factor authentication to specific users. Subjects are prefixed with either `user:` or `group:`  -to identify which part of the identity to check. +This criteria matches identifying characteristics about the subject. Currently this is either user or groups the user +belongs to. This allows you to effectively control exactly what each user is authorized to access or to specifically +require two-factor authentication to specific users. Subjects are prefixed with either `user:` or `group:` to identify +which part of the identity to check.  The format of this rule is unique in as much as it is a list of lists. The logic behind this format is to allow for both  `OR` and `AND` logic. The first level of the list defines the `OR` logic, and the second level defines the `AND` logic.  Additionally each level of these lists does not have to be explicitly defined. -Example: +##### Examples -*Matches when the user has the username `john`, **or** the user is in the groups `admin` **and** `app-name`, **or** the +*Matches when the user has the username `john`, __or__ the user is in the groups `admin` __and__ `app-name`, __or__ the  user is in the group `super-admin`. All rules in this list are effectively the same rule just expressed in different  ways.* @@ -271,15 +264,15 @@ access_control:    - domain: example.com      policy: two_factor      subject: -    - "user:john" -    - ["group:admin", "group:app-name"] -    - "group:super-admin" +    - 'user:john' +    - ['group:admin', 'group:app-name'] +    - 'group:super-admin'    - domain: example.com      policy: two_factor      subject: -    - ["user:john"] -    - ["group:admin", "group:app-name"] -    - ["group:super-admin"] +    - ['user:john'] +    - ['group:admin', 'group:app-name'] +    - ['group:super-admin']  ```  *Matches when the user is in the `super-admin` group. All rules in this list are effectively the same rule just @@ -290,24 +283,20 @@ access_control:    rules:    - domain: example.com      policy: one_factor -    subject: "group:super-admin" +    subject: 'group:super-admin'    - domain: example.com      policy: one_factor -    subject:  -    - "group:super-admin" +    subject: +    - 'group:super-admin'    - domain: example.com      policy: one_factor      subject: -    - ["group:super-admin"] +    - ['group:super-admin']  ``` -### methods -<div markdown="1"> -type: list(string) -{: .label .label-config .label-purple }  -required: no -{: .label .label-config .label-green } -</div> +#### methods + +{{< confkey type="list(string)" required="no" >}}  This criteria matches the HTTP request method. This is primarily useful when trying to bypass authentication for specific  request types when those requests would prevent essential or public operation of the website. An example is when you @@ -319,7 +308,18 @@ permission to do GET requests, their authentication level was `one_factor`, and  who have done requests other than HEAD or GET which means the user experience may suffer. These are the reasons it's  only recommended to use this to increase security where essential and for CORS preflight. -Example: +The accepted and valid methods for this configuration option are those specified in well known RFC's. The RFC's and the +relevant methods are listed in this table: + +|    RFC    |                        Methods                        |                     Additional Documentation                     | +|:---------:|:-----------------------------------------------------:|:----------------------------------------------------------------:| +| [RFC7231] | GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE | [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods) | +| [RFC5789] |                         PATCH                         | [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods) | +| [RFC4918] | PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, UNLOCK  |                                                                  | + +##### Examples + +*Bypass `OPTIONS` requests to the `example.com` domain.*  ```yaml  access_control: @@ -330,29 +330,14 @@ access_control:      - OPTIONS  ``` -The accepted and valid methods for this configuration option are those specified in well known RFC's. The RFC's and the -relevant methods are listed in this table: - -|                           RFC                            |                        Methods                        |                     Additional Documentation                     | -|:--------------------------------------------------------:|:-----------------------------------------------------:|:----------------------------------------------------------------:| -| [RFC7231](https://datatracker.ietf.org/doc/html/rfc7231) | GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE | [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods) | -| [RFC5789](https://datatracker.ietf.org/doc/html/rfc5789) |                         PATCH                         | [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods) | -| [RFC4918](https://datatracker.ietf.org/doc/html/rfc4918) | PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, UNLOCK  |                                                                  | +#### networks +{{< confkey type="list(string)" required="no" >}} - -### networks -<div markdown="1"> -type: list(string) -{: .label .label-config .label-purple }  -required: no -{: .label .label-config .label-green } -</div> - -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  +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  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.*  The main use case for this criteria is adjust the security requirements of a resource based on the location of a user. @@ -367,9 +352,9 @@ privileges when a user is on the local networks.  There are a large number of scenarios regarding networks and the order of the rules. This provides a lot of flexibility  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](#two_factor) 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.*  ```yaml @@ -378,45 +363,47 @@ access_control:    networks:    - name: internal      networks: -      - 10.0.0.0/8 -      - 172.16.0.0/12 -      - 192.168.0.0/18 +      - '10.0.0.0/8' +      - '172.16.0.0/12' +      - '192.168.0.0/18'    rules:    - domain: secure.example.com      policy: one_factor      networks: -    - 10.0.0.0/8 -    - 172.16.0.0/12 -    - 192.168.0.0/18 -    - 112.134.145.167/32 +    - '10.0.0.0/8' +    - '172.16.0.0/12' +    - '192.168.0.0/18' +    - '112.134.145.167/32'    - domain: secure.example.com      policy: one_factor      networks: -    - internal -    - 112.134.145.167/32 +    - 'internal' +    - '112.134.145.167/32'    - domain: secure.example.com      policy: two_factor  ``` -### resources -<div markdown="1"> -type: list(string) -{: .label .label-config .label-purple }  -required: no -{: .label .label-config .label-green } -</div> +#### resources + +{{< confkey type="list(string)" required="no" >}} -_**Important Note:** to utilize regex you must escape it properly. See [regex](./index.md#regex) for more information._ +*__Important Note:__ to utilize regex you must escape it properly. See +[regular expressions](../prologue/common.md#regular-expressions) for more information.*  This criteria matches the path and query of the request using regular expressions. The rule is expressed as a list of  strings. If any one of the regular expressions in the list matches the request it's considered a match. A useful tool -for debugging these regular expressions is called [Rego](https://regoio.herokuapp.com/). +for debugging these regular expressions is called [Regex 101](https://regex101.com/) (ensure you pick the `Golang` +option). -_**Note:** Prior to 4.27.0 the regular expressions only matched the path excluding the query parameters. After 4.27.0  -they match the entire path including the query parameters. When upgrading you may be required to alter some of your  -resource rules to get them to operate as they previously did._ +*__Note:__ Prior to 4.27.0 the regular expressions only matched the path excluding the query parameters. After 4.27.0 +they match the entire path including the query parameters. When upgrading you may be required to alter some of your +resource rules to get them to operate as they previously did.* -Examples: +It's important when configuring resource rules that you enclose them in quotes otherwise you may run into some issues +with escaping the expressions. Failure to do so may prevent Authelia from starting. It's technically optional but will +likely save you a lot of time if you do it for all resource rules. + +##### Examples  *Applies the [bypass](#bypass) policy when the domain is `app.example.com` and the url is `/api`, or starts with either  `/api/` or `/api?`.* @@ -432,36 +419,36 @@ access_control:  ## 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.  ### deny  This is the policy applied by default, and is what we recommend as the default policy for all installs. Its effect -is literally to deny the user access to the resource. Additionally you can use this policy to conditionally deny  +is literally to deny the user access to the resource. Additionally you can use this policy to conditionally deny  access in desired situations. Examples include denying access to an API that has no authentication mechanism built in.  ### bypass  This policy skips all authentication and allows anyone to use the resource. This policy is not available with a rule -that includes a [subject](#subject) restriction because the minimum authentication level required to obtain information  +that includes a [subject](#subject) restriction because the minimum authentication level required to obtain information  about the subject is [one_factor](#one_factor).  #### bypass and user identity  The [bypass](#bypass) policy cannot be used when the rule uses a criteria that requires we know the users identity. This -means:  +means: -- If the rule defines [subjects](#subject) criteria -- If the rule defines [domain regex](#domain_regex) criteria which contains either the user or group named match groups  +* If the rule defines [subjects](#subject) criteria +* If the rule defines [domain regex](#domain_regex) criteria which contains either the user or group named match groups -This is because these criteria types require knowing who the user is in order to determine if their identity matches the  -request. This information can only be known after 1FA, which means the minimum policy that can be used logically is  -[one_factor](#one_factor).  +This is because these criteria types require knowing who the user is in order to determine if their identity matches the +request. This information can only be known after 1FA, which means the minimum policy that can be used logically is +[one_factor](#one_factor).  ### one_factor -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.  ### two_factor @@ -479,8 +466,8 @@ access_control:    networks:      - name: internal        networks: -        - 10.10.0.0/16 -        - 192.168.2.0/24 +        - '10.10.0.0/16' +        - '192.168.2.0/24'      - name: VPN        networks: 10.9.0.0/16    rules: @@ -495,10 +482,10 @@ access_control:      - domain: 'secure.example.com'        policy: one_factor        networks: -        - internal -        - VPN -        - 192.168.1.0/24 -        - 10.0.0.1 +        - 'internal' +        - 'VPN' +        - '192.168.1.0/24' +        - '10.0.0.1'      - domain:        - 'secure.example.com' @@ -509,7 +496,7 @@ access_control:        policy: one_factor      - domain: 'mx2.mail.example.com' -      subject: "group:admins" +      subject: 'group:admins'        policy: deny      - domain: '*.example.com' @@ -527,7 +514,7 @@ access_control:      - domain: dev.example.com        resources:        - '^/users/john/.*$' -      subject:  +      subject:        - ['group:dev', 'user:john']        - 'group:admins'        policy: two_factor @@ -535,3 +522,7 @@ access_control:      - domain: '{user}.example.com'        policy: bypass  ``` + +[RFC7231]: https://www.rfc-editor.org/rfc/rfc7231.html +[RFC5789]: https://www.rfc-editor.org/rfc/rfc5789.html +[RFC4918]: https://www.rfc-editor.org/rfc/rfc4918.html diff --git a/docs/content/en/configuration/security/introduction.md b/docs/content/en/configuration/security/introduction.md new file mode 100644 index 000000000..569f02ea2 --- /dev/null +++ b/docs/content/en/configuration/security/introduction.md @@ -0,0 +1,13 @@ +--- +title: "Security" +description: "Security Related Configuration" +lead: "An introduction into configuring the security settings." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  configuration: +    parent: "security" +weight: 104100 +toc: true +--- diff --git a/docs/content/en/configuration/security/password-policy.md b/docs/content/en/configuration/security/password-policy.md new file mode 100644 index 000000000..6722adce8 --- /dev/null +++ b/docs/content/en/configuration/security/password-policy.md @@ -0,0 +1,112 @@ +--- +title: "Password Policy" +description: "Password Policy Configuration" +lead: "Configuring the Password Policy." +date: 2022-04-12T14:40:22+10:00 +draft: false +images: [] +menu: +  configuration: +    parent: "security" +weight: 104400 +toc: true +aliases: +  - /docs/configuration/password_policy.html +--- + +*Authelia* allows administrators to configure an enforced password policy. + +## Configuration + +```yaml +password_policy: +  standard: +    enabled: false +    min_length: 8 +    max_length: 0 +    require_uppercase: false +    require_lowercase: false +    require_number: false +    require_special: false +  zxcvbn: +    enabled: false +    min_score: 3 +``` + +## Options + +### standard + +This section allows you to enable standard security policies. + +#### enabled + +{{< confkey type="boolean" default="false" required="no" >}} + +Enables standard password policy. + +#### min_length + +{{< confkey type="integer" default="8" required="no" >}} + +Determines the minimum allowed password length. + +#### max_length + +{{< confkey type="integer" default="0" required="no" >}} + +Determines the maximum allowed password length. + +#### require_uppercase + +{{< confkey type="boolean" default="false" required="no" >}} + +Indicates that at least one UPPERCASE letter must be provided as part of the password. + +#### require_lowercase + +{{< confkey type="boolean" default="false" required="no" >}} + +Indicates that at least one lowercase letter must be provided as part of the password. + +#### require_number + +{{< confkey type="boolean" default="false" required="no" >}} + +Indicates that at least one number must be provided as part of the password. + +#### require_special + +{{< confkey type="boolean" default="false" required="no" >}} + +Indicates that at least one special character must be provided as part of the password. + +### zxcvbn + +This password policy enables advanced password strength metering, using [zxcvbn](https://github.com/dropbox/zxcvbn). + +Note that this password policy do not restrict the user's entry it just gives the user feedback as to how strong their +password is. + +#### enabled + +{{< confkey type="boolean" default="false" required="no" >}} + +*__Important Note:__ only one password policy can be applied at a time.* + +Enables zxcvbn password policy. + +#### min_score + +{{< confkey type="integer" default="3" required="no" >}} + +Configures the minimum zxcvbn score allowed for new passwords. There are 5 levels in the zxcvbn score system (taken from +[github.com/dropbox/zxcvbn](https://github.com/dropbox/zxcvbn#usage)): + +* score 0: too guessable: risky password (guesses < 10^3) +* score 1: very guessable: protection from throttled online attacks (guesses < 10^6) +* score 2: somewhat guessable: protection from unthrottled online attacks. (guesses < 10^8) +* score 3: safely unguessable: moderate protection from offline slow-hash scenario. (guesses < 10^10) +* score 4: very unguessable: strong protection from offline slow-hash scenario. (guesses >= 10^10) + +We do not allow score 0, if you set the `min_score` value to 0 instead the default will be used instead. diff --git a/docs/content/en/configuration/security/regulation.md b/docs/content/en/configuration/security/regulation.md new file mode 100644 index 000000000..b425c480f --- /dev/null +++ b/docs/content/en/configuration/security/regulation.md @@ -0,0 +1,57 @@ +--- +title: "Regulation" +description: "Regulation Configuration" +lead: "Configuring the Regulation system." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  configuration: +    parent: "security" +weight: 104300 +toc: true +aliases: +  - /docs/configuration/regulation.html +--- + + +__Authelia__ can temporarily ban accounts when there are too many +authentication attempts. This helps prevent brute-force attacks. + +## Configuration + +```yaml +regulation: +  max_retries: 3 +  find_time: 2m +  ban_time: 5m +``` + +## Options + +### max_retries + +{{< confkey type="integer " default="3" required="no" >}} + +The number of failed login attempts before a user may be banned. Setting this option to 0 disables regulation entirely. + +### find_time + +{{< confkey type="duration " default="2m" required="no" >}} + +*__Note:__ This setting uses the [duration notation format](../prologue/common.md#duration-notation-format). Please see +the [common options](../prologue/common.md#duration-notation-format) documentation for information on this format.* + +The period of time analyzed for failed attempts. For +example if you set `max_retries` to 3 and `find_time` to `2m` this means the user must have 3 failed logins in +2 minutes. + +### ban_time + +{{< confkey type="duration" default="5m" required="no" >}} + +*__Note:__ This setting uses the [duration notation format](../prologue/common.md#duration-notation-format). Please see +the [common options](../prologue/common.md#duration-notation-format) documentation for information on this format.* + +The period of time the user is banned for after meeting the `max_retries` and `find_time` configuration. After this +duration the account will be able to login again. diff --git a/docs/content/en/configuration/session/_index.md b/docs/content/en/configuration/session/_index.md new file mode 100644 index 000000000..01866387d --- /dev/null +++ b/docs/content/en/configuration/session/_index.md @@ -0,0 +1,9 @@ +--- +title: "Session" +description: "Session Configuration" +lead: "" +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +weight: 105000 +--- diff --git a/docs/content/en/configuration/session/introduction.md b/docs/content/en/configuration/session/introduction.md new file mode 100644 index 000000000..f96918bd1 --- /dev/null +++ b/docs/content/en/configuration/session/introduction.md @@ -0,0 +1,129 @@ +--- +title: "Session" +description: "Session Configuration" +lead: "Configuring the Session / Cookie settings." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  configuration: +    parent: "session" +weight: 105100 +toc: true +aliases: +  - /c/session +  - /docs/configuration/session/ +--- + +__Authelia__ relies on session cookies to authenticate users. When the user visits a website of the protected domain +`example.com` for the first time, Authelia detects that there is no cookie for that user. Consequently, Authelia +redirects the user to the login portal through which the user should authenticate to get a cookie which is valid for +`*.example.com`, meaning all websites of the domain. At the next request, Authelia receives the cookie associated to the +authenticated user and can then order the reverse proxy to let the request pass through to the application. + +## Configuration + +```yaml +session: +  name: authelia_session +  domain: example.com +  same_site: lax +  secret: unsecure_session_secret +  expiration: 1h +  inactivity: 5m +  remember_me_duration:  1M +``` + +## Providers + +There are currently two providers for session storage (three if you count Redis Sentinel as a separate provider): + +* Memory (default, stateful, no additional configuration) +* [Redis](redis.md) (stateless). +* [Redis Sentinel](redis.md#high_availability) (stateless, highly available). + +### Kubernetes or High Availability + +It's important to note when picking a provider, the stateful providers are not recommended in High Availability +scenarios like Kubernetes. Each provider has a note beside it indicating it is *stateful* or *stateless* the stateless +providers are recommended. + +## Options + +### name + +{{< confkey type="string" default="authelia_session" required="no" >}} + +The name of the session cookie. By default this is set to authelia_session. It's mostly useful to change this if you are +doing development or running multiple instances of Authelia. + +### domain + +{{< confkey type="string" required="yes" >}} + +The domain the cookie is assigned to protect. This must be the same as the domain Authelia is served on or the root +of the domain. For example if listening on auth.example.com the cookie should be auth.example.com or example.com. + +### same_site + +{{< confkey type="string" default="lax" required="no" >}} + +Sets the cookies SameSite value. Prior to offering the configuration choice this defaulted to None. The new default is +Lax. This option is defined in lower-case. So for example if you want to set it to `Strict`, the value in configuration +needs to be `strict`. + +You can read about the SameSite cookie in detail on the +[MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite). In short setting SameSite to Lax +is generally the most desirable option for Authelia. None is not recommended unless you absolutely know what you're +doing and trust all the protected apps. Strict is not going to work in many use cases and we have not tested it in this +state but it's available as an option anyway. + +### secret + +{{< confkey type="string" required="yes" >}} + +The secret key used to encrypt session data in Redis. It's recommended this is set using a +[secret](../methods/secrets.md). + +We recommend generating a random string with 64 characters or more for this purposes which can be done by following the +[Generating a Random Alphanumeric String](../miscellaneous/guides.md#generating-a-random-alphanumeric-string) +guide. + +### expiration + +{{< confkey type="duration" default="1h" required="no" >}} + +*__Note:__ This setting uses the [duration notation format](../prologue/common.md#duration-notation-format). Please see +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 +[remember_me_duration](#remember_me_duration) when the remember me box is checked. + +### inactivity + +{{< confkey type="duration" default="5m" required="no" >}} + +*__Note:__ This setting uses the [duration notation format](../prologue/common.md#duration-notation-format). Please see +the [common options](../prologue/common.md#duration-notation-format) documentation for information on this format.* + +The period of time the user can be inactive for until the session is destroyed. Useful if you want long session timers +but don't want unused devices to be vulnerable. + +### remember_me_duration + +{{< confkey type="duration" default="1M" required="no" >}} + +*__Note:__ This setting uses the [duration notation format](../prologue/common.md#duration-notation-format). Please see +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 when the remember me box is checked. Setting +this to `-1` disables this feature entirely. + +## Security + +Configuration of this section has an impact on security. You should read notes in +[security measures](../../overview/security/measures.md#session-security) for more information. + +## Loading a password from a secret instead of inside the configuration + +Password can also be defined using a [secret](../methods/secrets.md). diff --git a/docs/configuration/session/redis.md b/docs/content/en/configuration/session/redis.md index a8b438b47..d06276490 100644 --- a/docs/configuration/session/redis.md +++ b/docs/content/en/configuration/session/redis.md @@ -1,16 +1,22 @@  --- -layout: default -title: Redis -parent: Session -grand_parent: Configuration -nav_order: 1 +title: "Redis" +description: "Redis Session Configuration" +lead: "Configuring the Redis Session Storage." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  configuration: +    parent: "session" +weight: 105200 +toc: true +aliases: +  - /docs/configuration/session/redis.html  --- -# Redis -  This is a session provider. By default Authelia uses an in-memory provider. Not configuring redis leaves Authelia -[stateful](../../features/statelessness.md). It's important in highly available scenarios to configure this option and -we highly recommend it in production environments. It requires you setup [redis] as well. +[stateful](../../overview/authorization/statelessness.md). It's important in highly available scenarios to configure +this option and we highly recommend it in production environments. It requires you setup [redis] as well.  ## Configuration @@ -46,86 +52,55 @@ session:  ## Options  ### host -<div markdown="1"> -type: string -{: .label .label-config .label-purple } -required: yes -{: .label .label-config .label-red } -</div> + +{{< confkey type="string" required="yes" >}}  The [redis] host or unix socket path. If utilising an IPv6 literal address it must be enclosed by square brackets and  quoted: +  ```yaml  host: "[fd00:1111:2222:3333::1]"  ```  ### port -<div markdown="1"> -type: integer -{: .label .label-config .label-purple } -default: 6379 -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> + +{{< confkey type="integer" default="6379" required="no" >}}  The port [redis] is listening on.  ### username -<div markdown="1"> -type: string -{: .label .label-config .label-purple } -required: no -{: .label .label-config .label-green } -</div> + +{{< confkey type="string" required="no" >}}  The username for [redis authentication](https://redis.io/commands/auth). Only supported in [redis] 6.0+, and [redis]  currently offers backwards compatibility with password-only auth. You probably do not need to set this unless you went  through the process of setting up [redis ACLs](https://redis.io/topics/acl).  ### password -<div markdown="1"> -type: string -{: .label .label-config .label-purple } -required: no -{: .label .label-config .label-green } -</div> + +{{< confkey type="string" required="no" >}}  The password for [redis authentication](https://redis.io/commands/auth). +We recommend generating a random string with 64 characters or more for this purposes which can be done by following the +[Generating a Random Alphanumeric String](../miscellaneous/guides.md#generating-a-random-alphanumeric-string) +guide. +  ### database_index -<div markdown="1"> -type: integer -{: .label .label-config .label-purple } -default: 0 -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> + +{{< confkey type="integer" default="0" required="no" >}}  The index number of the [redis] database, the same value as specified with the redis SELECT command.  ### maximum_active_connections -<div markdown="1"> -type: integer -{: .label .label-config .label-purple } -default: 8 -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> + +{{< confkey type="integer" default="8" required="no" >}}  The maximum connections open to [redis] at the same time.  ### minimum_idle_connections -<div markdown="1"> -type: integer -{: .label .label-config .label-purple } -default: 0 -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> + +{{< confkey type="integer" default="0" required="no" >}}  The minimum number of [redis] connections to keep open as long as they don't exceed the maximum active connections. This  is useful if there are long delays in establishing connections. @@ -133,7 +108,7 @@ is useful if there are long delays in establishing connections.  ### tls  If defined enables [redis] over TLS, and additionally controls the TLS connection validation process. You can see how to -configure the tls section [here](../index.md#tls-configuration). +configure the tls section [here](../prologue/common.md#tls-configuration).  ### high_availability @@ -141,38 +116,26 @@ When defining this session it enables [redis sentinel] connections. It's possibl  the future we may add [redis cluster](https://redis.io/topics/cluster-tutorial).  #### sentinel_name -<div markdown="1"> -type: string -{: .label .label-config .label-purple } -required: yes -{: .label .label-config .label-red } -</div> + +{{< confkey type="string" required="yes" >}}  The [redis sentinel] master name. This is defined in your [redis sentinel] configuration, it is not a hostname. This  must be defined currently for a high availability configuration.  #### sentinel_username -<div markdown="1"> -type: string -{: .label .label-config .label-purple } -required: no -{: .label .label-config .label-green } -</div> + +{{< confkey type="string" required="no" >}}  The username for the [redis sentinel] connection. If this is provided, it will be used along with the sentinel_password  for ACL-based authentication to the Redis Sentinel. If only a password is provided, the [redis sentinel] connection will -be authenticated with traditional requirepass authentication. +be authenticated with traditional [requirepass] authentication.  #### sentinel_password -<div markdown="1"> -type: string -{: .label .label-config .label-purple } -required: no (yes if sentinel_username is supplied) -{: .label .label-config .label-green } -</div> + +{{< confkey type="string" required="no (yes if sentinel_username is supplied)" >}}  The password for the [redis sentinel] connection. If specified with sentinel_username, configures Authelia to -authenticate to the Redis Sentinel with ACL-based authentication. Otherwise, this is used for requirepass +authenticate to the Redis Sentinel with ACL-based authentication. Otherwise, this is used for [requirepass]  authentication.  #### nodes @@ -189,52 +152,29 @@ Each node has a host and port configuration. Example:  ```  ##### host -<div markdown="1"> -type: boolean -{: .label .label-config .label-purple } -default: false -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> + +{{< confkey type="boolean" default="false" required="no" >}}  The host of this [redis sentinel] node.  ##### port -<div markdown="1"> -type: integer -{: .label .label-config .label-purple } -default: 26379 -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> + +{{< confkey type="integer" default="26379" required="no" >}}  The port of this [redis sentinel] node.  #### route_by_latency -<div markdown="1"> -type: boolean -{: .label .label-config .label-purple } -default: false -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> + +{{< confkey type="boolean" default="false" required="no" >}}  Prioritizes low latency [redis sentinel] nodes when set to true.  #### route_randomly -<div markdown="1"> -type: boolean -{: .label .label-config .label-purple } -default: false -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> + +{{< confkey type="boolean" default="false" required="no" >}}  Randomly chooses [redis sentinel] nodes when set to true.  [redis]: https://redis.io  [redis sentinel]: https://redis.io/topics/sentinel +[requirepass]: https://redis.io/topics/config diff --git a/docs/content/en/configuration/storage/_index.md b/docs/content/en/configuration/storage/_index.md new file mode 100644 index 000000000..60f7cca21 --- /dev/null +++ b/docs/content/en/configuration/storage/_index.md @@ -0,0 +1,9 @@ +--- +title: "Storage" +description: "Storage Configuration" +lead: "" +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +weight: 106000 +--- diff --git a/docs/content/en/configuration/storage/introduction.md b/docs/content/en/configuration/storage/introduction.md new file mode 100644 index 000000000..0d565c539 --- /dev/null +++ b/docs/content/en/configuration/storage/introduction.md @@ -0,0 +1,60 @@ +--- +title: "Storage" +description: "Storage Configuration" +lead: "Configuring the SQL Storage." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  configuration: +    parent: "storage" +weight: 106100 +toc: true +aliases: +  - /docs/configuration/storage/ +--- + +__Authelia__ supports multiple storage backends. The backend is used to store user preferences, 2FA device handles and +secrets, authentication logs, etc... + +The available storage backends are listed in the table of contents below. + +## Configuration + +```yaml +storage: +  encryption_key: a_very_important_secret +  local: {} +  mysql: {} +  postgres: {} +``` + +## Options + +### encryption_key + +{{< confkey type="string" required="yes" >}} + +The encryption key used to encrypt data in the database. We encrypt data by creating a sha256 checksum of the provided +value, and use that to encrypt the data with the AES-GCM 256bit algorithm. + +The minimum length of this key is 20 characters, however we generally recommend above 64 characters. + +This secret must be generated by the administrator and can +be done by following the +[Generating a Random Alphanumeric String](../miscellaneous/guides.md#generating-a-random-alphanumeric-string) +guide. + +See [securty measures](../../overview/security/measures.md#storage-security-measures) for more information. + +### postgres + +See [PostgreSQL](postgres.md). + +### local + +See [SQLite](sqlite.md). + +### mysql + +See [MySQL](mysql.md). diff --git a/docs/configuration/storage/migrations.md b/docs/content/en/configuration/storage/migrations.md index 6666fedb2..b2a77512f 100644 --- a/docs/configuration/storage/migrations.md +++ b/docs/content/en/configuration/storage/migrations.md @@ -1,9 +1,17 @@  --- -layout: default -title: Migrations -parent: Storage Backends -grand_parent: Configuration -nav_order: 5 +title: "Migrations" +description: "Storage Migrations" +lead: "A migration ." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  configuration: +    parent: "storage" +weight: 106200 +toc: true +aliases: +  - /docs/configuration/storage/migrations.html  ---  Storage migrations are important for keeping your database compatible with Authelia. Authelia will automatically upgrade @@ -13,16 +21,16 @@ downgrade your schema with a version of Authelia that supports your current sche  ## Schema Version to Authelia Version map  This table contains a list of schema versions and the corresponding release of Authelia that shipped with that version. -This means all Authelia versions between two schema versions use the first schema version.  +This means all Authelia versions between two schema versions use the first schema version. -For example for version pre1, it is used for all versions between it and the version 1 schema, so 4.0.0 to 4.32.2. In  +For example for version pre1, it is used for all versions between it and the version 1 schema, so 4.0.0 to 4.32.2. In  this instance if you wanted to downgrade to pre1 you would need to use an Authelia binary with version 4.33.0 or higher.  | Schema Version | Authelia Version |                                               Notes                                                |  |:--------------:|:----------------:|:--------------------------------------------------------------------------------------------------:|  |      pre1      |      4.0.0       |                    Downgrading to this version requires you use the --pre1 flag                    |  |       1        |      4.33.0      |                                 Initial migration managed version                                  | -|       2        |      4.34.0      | Webauthn - added webauthn_devices table, altered totp_config to include device created/used dates  | -|       3        |      4.34.2      |     Webauthn - fix V2 migration kid column length and provide migration path for anyone on V2      | +|       2        |      4.34.0      | WebAuthn - added webauthn_devices table, altered totp_config to include device created/used dates  | +|       3        |      4.34.2      |     WebAuthn - fix V2 migration kid column length and provide migration path for anyone on V2      |  |       4        |      4.35.0      |               Added OpenID Connect storage tables and opaque user identifier tables                |  |       5        |      4.35.1      | Fixed the oauth2_consent_session table to accept NULL subjects for users who are not yet signed in | diff --git a/docs/content/en/configuration/storage/mysql.md b/docs/content/en/configuration/storage/mysql.md new file mode 100644 index 000000000..6b0ffb827 --- /dev/null +++ b/docs/content/en/configuration/storage/mysql.md @@ -0,0 +1,100 @@ +--- +title: "MySQL" +description: "MySQL Configuration" +lead: "The MySQL storage provider which supports both MySQL and MariaDB." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  configuration: +    parent: "storage" +weight: 106600 +toc: true +aliases: +  - /docs/configuration/storage/mariadb.html +  - /docs/configuration/storage/mysql.html +--- + +## Version support + +When using MySQL or MariaDB we recommend using the latest version that is officially supported by the MySQL or MariaDB +developers. We also suggest checking out [PostgreSQL](postgres.md) as an alternative. + +The oldest versions that have been tested are MySQL 5.7 and MariaDB 10.6. + +If using MySQL 5.7 or MariaDB 10.6 you may be required to adjust the `explicit_defaults_for_timestamp` setting. This +will be evident when the container starts with an error similar to `Error 1067: Invalid default value for 'exp'`. You +can adjust this setting in the mysql.cnf file like so: + +```cnf +[mysqld] +explicit_defaults_for_timestamp = 1 +``` + +## Configuration + +```yaml +storage: +  encryption_key: a_very_important_secret +  mysql: +    host: 127.0.0.1 +    port: 3306 +    database: authelia +    username: authelia +    password: mypassword +    timeout: 5s +``` + +## Options + +### encryption_key + +See the [encryption_key docs](introduction.md#encryption_key). + +### host + +{{< confkey type="string" default="localhost" required="no" >}} + +The database server host. + +If utilising an IPv6 literal address it must be enclosed by square brackets and quoted: + +```yaml +host: "[fd00:1111:2222:3333::1]" +``` + +### port + +{{< confkey type="integer" default="3306" required="no" >}} + +The port the database server is listening on. + +### database + +{{< confkey type="string" required="yes" >}} + +The database name on the database server that the assigned [user](#username) has access to for the purpose of +__Authelia__. + +### username + +{{< confkey type="string" required="yes" >}} + +The username paired with the password used to connect to the database. + +### password + +{{< confkey type="string" required="yes" >}} + +The password paired with the username used to connect to the database. Can also be defined using a +[secret](../methods/secrets.md) which is also the recommended way when running as a container. + +We recommend generating a random string with 64 characters or more for this purposes which can be done by following the +[Generating a Random Alphanumeric String](../miscellaneous/guides.md#generating-a-random-alphanumeric-string) +guide. + +### timeout + +{{< confkey type="duration" default="5s" required="no" >}} + +The SQL connection timeout. diff --git a/docs/content/en/configuration/storage/postgres.md b/docs/content/en/configuration/storage/postgres.md new file mode 100644 index 000000000..2dd22859a --- /dev/null +++ b/docs/content/en/configuration/storage/postgres.md @@ -0,0 +1,139 @@ +--- +title: "PostgreSQL" +description: "PostgreSQL Configuration" +lead: "The PostgreSQL storage provider." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  configuration: +    parent: "storage" +weight: 106400 +toc: true +aliases: +  - /docs/configuration/storage/postgres.html +--- + +## Version support + +See [PostgreSQL support](https://www.postgresql.org/support/versioning/) for the versions supported by PostgreSQL. We +recommend the *current minor* version of one of the versions supported by PostgreSQL. + +The versions of PostgreSQL that should be supported by Authelia are: + +* 14 +* 13 +* 12 +* 11 +* 10 +* 9.6 + +## Configuration + +```yaml +storage: +  encryption_key: a_very_important_secret +  postgres: +    host: 127.0.0.1 +    port: 5432 +    database: authelia +    schema: public +    username: authelia +    password: mypassword +    ssl: +      mode: disable +      root_certificate: /path/to/root_cert.pem +      certificate: /path/to/cert.pem +      key: /path/to/key.pem +``` + +## Options + +### encryption_key + +See the [encryption_key docs](introduction.md#encryption_key). + +### host + +{{< confkey type="string" required="yes" >}} + +The database server host. + +If utilising an IPv6 literal address it must be enclosed by square brackets and quoted: + +```yaml +host: "[fd00:1111:2222:3333::1]" +``` + +### port + +{{< confkey type="integer" default="5432" required="no" >}} + +The port the database server is listening on. + +### database + +{{< confkey type="string" required="yes" >}} + +The database name on the database server that the assigned [user](#username) has access to for the purpose of +__Authelia__. + +### schema + +{{< confkey type="string" default="public" required="no" >}} + +The database schema name to use on the database server that the assigned [user](#username) has access to for the purpose +of __Authelia__. By default this is the public schema. + +### username + +{{< confkey type="string" required="yes" >}} + +The username paired with the password used to connect to the database. + +### password + +{{< confkey type="string" required="yes" >}} + +The password paired with the username used to connect to the database. Can also be defined using a +[secret](../methods/secrets.md) which is also the recommended way when running as a container. + +We recommend generating a random string with 64 characters or more for this purposes which can be done by following the +[Generating a Random Alphanumeric String](../miscellaneous/guides.md#generating-a-random-alphanumeric-string) +guide. + +### timeout + +{{< confkey type="duration" default="5s" required="no" >}} + +The SQL connection timeout. + +### ssl + +#### mode + +{{< confkey type="string" default="disable" required="no" >}} + +SSL mode configures how to handle SSL connections with Postgres. +Valid options are 'disable', 'require', 'verify-ca', or 'verify-full'. +See the [PostgreSQL Documentation](https://www.postgresql.org/docs/12/libpq-ssl.html) +or [pgx - PostgreSQL Driver and Toolkit Documentation](https://pkg.go.dev/github.com/jackc/pgx?tab=doc) +for more information. + +#### root_certificate + +{{< confkey type="string" required="no" >}} + +The optional location of the root certificate file encoded in the PEM format for validation purposes. + +#### certificate + +{{< confkey type="string" required="no" >}} + +The optional location of the certificate file encoded in the PEM format for validation purposes. + +#### key + +{{< confkey type="string" required="no" >}} + +The optional location of the key file encoded in the PEM format for authentication purposes. diff --git a/docs/content/en/configuration/storage/sqlite.md b/docs/content/en/configuration/storage/sqlite.md new file mode 100644 index 000000000..9e54ee04a --- /dev/null +++ b/docs/content/en/configuration/storage/sqlite.md @@ -0,0 +1,44 @@ +--- +title: "SQLite3" +description: "SQLite3 Configuration" +lead: "The SQLite3 storage provider." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  configuration: +    parent: "storage" +weight: 106500 +toc: true +aliases: +  - /docs/configuration/storage/sqlite.html +--- + +If you don't have a SQL server, you can use [SQLite](https://en.wikipedia.org/wiki/SQLite). +However please note that this setup will prevent you from running multiple +instances of Authelia since the database will be a local file. + +Use of this storage provider leaves Authelia [stateful](../../overview/authorization/statelessness.md). It's important +in highly available scenarios to use one of the other providers, and we highly recommend it in production environments, +but this requires you setup an external database such as [PostgreSQL](postgres.md). + +## Configuration + +```yaml +storage: +  encryption_key: a_very_important_secret +  local: +    path: /config/db.sqlite3 +``` + +## Options + +### encryption_key + +See the [encryption_key docs](introduction.md#encryption_key). + +### path + +{{< confkey type="string" required="yes" >}} + +The path where the SQLite3 database file will be stored. It will be created if the file does not exist. diff --git a/docs/content/en/configuration/telemetry/_index.md b/docs/content/en/configuration/telemetry/_index.md new file mode 100644 index 000000000..41b578d6e --- /dev/null +++ b/docs/content/en/configuration/telemetry/_index.md @@ -0,0 +1,9 @@ +--- +title: "Telemetry" +description: "Telemetry Configuration" +lead: "" +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +weight: 108000 +--- diff --git a/docs/content/en/configuration/telemetry/introduction.md b/docs/content/en/configuration/telemetry/introduction.md new file mode 100644 index 000000000..acbcf9f0b --- /dev/null +++ b/docs/content/en/configuration/telemetry/introduction.md @@ -0,0 +1,20 @@ +--- +title: "Telemetry" +description: "Configuring the Telemetry settings" +lead: "Configuring the Telemetry settings." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  configuration: +    parent: "telemetry" +weight: 108100 +toc: true +--- + +*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 +administrator. + +No metrics or telemetry are reported from an *Authelia* binary to any location the administrator doesn't explicitly +configure. This means by default all metrics are disabled. diff --git a/docs/content/en/configuration/telemetry/metrics.md b/docs/content/en/configuration/telemetry/metrics.md new file mode 100644 index 000000000..73a399662 --- /dev/null +++ b/docs/content/en/configuration/telemetry/metrics.md @@ -0,0 +1,45 @@ +--- +title: "Metrics" +description: "Configuring the Metrics Telemetry settings" +lead: "Configuring the Metrics Telemetry settings." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  configuration: +    parent: "telemetry" +weight: 108200 +toc: true +--- + +*Authelia* allows administrators to configure a [Prometheus] Metrics Exporter. + +## Configuration + +```yaml +telemetry: +  metrics: +    enabled: false +    address: "0.0.0.0:9959" +``` + +## Options + +### enabled + +{{< confkey type="boolean" default="false" required="no" >}} + +Determines if the [Prometheus] HTTP Metrics Exporter is enabled. + +### address + +{{< confkey type="address" default="0.0.0.0:9959" required="no" >}} + +Configures the listener address for the [Prometheus] HTTP Metrics Exporter. The address must be a IPv4 or IPv6 address +followed by the port in the `<address>:<port>` format. + +## See More + +- [Telemetry Reference Documentation](../../reference/guides/metrics.md) + +[Prometheus]: https://prometheus.io/ diff --git a/docs/content/en/contributing/_index.md b/docs/content/en/contributing/_index.md new file mode 100644 index 000000000..3e73d799e --- /dev/null +++ b/docs/content/en/contributing/_index.md @@ -0,0 +1,8 @@ +--- +title : "Contributing" +description: "Contributing Docs" +lead: "" +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +--- diff --git a/docs/content/en/contributing/development/_index.md b/docs/content/en/contributing/development/_index.md new file mode 100644 index 000000000..7dd3500ad --- /dev/null +++ b/docs/content/en/contributing/development/_index.md @@ -0,0 +1,9 @@ +--- +title : "Development" +description: "Contributing via Development" +lead: "" +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +weight: 200 +--- diff --git a/docs/content/en/contributing/development/build-and-test.md b/docs/content/en/contributing/development/build-and-test.md new file mode 100644 index 000000000..8c0d34735 --- /dev/null +++ b/docs/content/en/contributing/development/build-and-test.md @@ -0,0 +1,104 @@ +--- +title: "Building and Testing" +description: "Building and Testing Authelia." +lead: "This section covers the build process and how to perform tests in development." +date: 2022-05-15T13:52:27+10:00 +draft: false +images: [] +menu: +  contributing: +    parent: "development" +weight: 240 +toc: true +aliases: +  - /docs/contributing/build-and-dev.html +--- + +__Authelia__ is built a [React] frontend user portal bundled in a [Go] application which acts as a basic webserver for +the [React] assets and a dedicated API. + +The GitHub repository comes with a CLI dedicated to developers called +[authelia-scripts](reference-authelia-scripts.md) which can be setup by looking at +[Reference: authelia-scripts](reference-authelia-scripts.md). + +In order to build and contribute to __Authelia__, you need to make sure that you have looked at the +[Environment](environment.md) guide to configure your development environment. + +## Get started + +In order to ease development, __Authelia__ uses the concept of [suites] to run Authelia from source code so that your +patches are included. This is a kind of virtual environment running __Authelia__ in a complete ecosystem +(LDAP, Redis, SQL server). Note that __Authelia__ is hot-reloaded in the environment so that your patches are instantly +included. + +The next command starts the suite called *Standalone*: + +```bash +authelia-scripts suites setup Standalone +``` + +Most of the suites are using docker-compose to bootstrap the environment. Therefore, you can check the logs of all +application by running the following command on the component you want to monitor. + +```bash +docker logs authelia_authelia-backend_1 -f +``` + +Then, edit the code and observe how __Authelia__ is automatically reloaded. + +### Unit tests + +To run the unit tests, run: + +```bash +authelia-scripts unittest +``` + +### Integration tests + +Integration tests are located under the `internal/suites` directory and are based on Selenium. A suite is a combination +of environment and tests. Executing a suite therefore means starting the environment, running the tests and tearing down +the environment. Each step can be run independently: + +```bash +# List the available suites +$ authelia-scripts suites list +Standalone +DuoPush +LDAP +Traefik + +# Start the environment of Standalone suite. +$ authelia-scripts suites setup Standalone + +# Run the tests related to the currently running suite. +$ authelia-scripts suites test + +# Tear down the environment +$ authelia-scripts suites teardown Standalone +``` + +In order to test all suites (approx 30 minutes), you need to make sure there is no currently running sui te and then you +should run: + +```bash +authelia-scripts suites test +``` + +Also, you don't need to start the suite before testing it. Given you're not running any suite, just use the following +command to test the *Standalone* suite. + +```bash +authelia-scripts suites test Standalone +``` + +The suite will be spawned, tests will be run and then the suite will be torn down automatically. + +[suites]: ./integration-suites.md +[React]: https://reactjs.org/ +[go]: https://go.dev/dl/ +[Node.js]: https://nodejs.org/en/download/ +[Docker]: https://docs.docker.com/get-docker/ +[Docker Compose]: https://docs.docker.com/compose/install/ +[golangci-lint]: https://golangci-lint.run/usage/install/ +[goimports-reviser]: https://github.com/incu6us/goimports-reviser#install diff --git a/docs/content/en/contributing/development/environment.md b/docs/content/en/contributing/development/environment.md new file mode 100644 index 000000000..87c94d342 --- /dev/null +++ b/docs/content/en/contributing/development/environment.md @@ -0,0 +1,82 @@ +--- +title: "Environment" +description: "How to configure your development environment." +lead: "This section covers the environment we recommend for development." +date: 2022-05-15T13:52:27+10:00 +draft: false +images: [] +menu: +  contributing: +    parent: "development" +weight: 220 +toc: true +--- + +__Authelia__ and its development workflow can be tested with [Docker] and [Docker Compose] on Linux. + +## Setup + +In order to build and contribute to __Authelia__, you need to make sure the following are installed in your environment: + +* [go] *(v1.18 or greater)* +* [Docker] +* [Docker Compose] +* [Node.js] *(v16 or greater)* +* [pnpm] + +The additional tools are recommended: + +* [golangci-lint] +* [goimports-reviser] +* [yamllint] +* Either the [VSCodium] or [GoLand] IDE + +## Scripts + +There is a scripting context provided with __Authelia__ which can easily be configured. It allows running integration +[suites] and various other tasks. Read more about it in the [authelia-scripts](reference-authelia-scripts.md) reference +guide. + +## FAQ + +### Do you support development under Windows or OSX? + +At the present time this is not officially supported. Some of the maintainers utilize Windows however running suites +under Windows or OSX is not something that is currently possible to do easily. As such we recommend utilizing Linux. + +### What version of Docker and docker-compose should I use? + +We have no firm recommendations on the version to use but we actively use the latest versions available to us in the +distributions of our choice. As long as it's a modern version it should be sufficient for the development environment. + +### How can I serve my application under example.com? + +Don't worry, you don't need to own the domain `example.com` to test Authelia. Copy the following lines in +your `/etc/hosts`: + +```text +192.168.240.100 home.example.com +192.168.240.100 login.example.com +192.168.240.100 singlefactor.example.com +192.168.240.100 public.example.com +192.168.240.100 secure.example.com +192.168.240.100 mail.example.com +192.168.240.100 mx1.mail.example.com +``` + +The IP address `192.168.240.100` is the IP attributed by [Docker] to the reverse proxy. Once added you can access the +listed subdomains from your browser, and they will be served by the reverse proxy. + +[suites]: ./integration-suites.md +[Buildkite]: https://buildkite.com/ +[React]: https://reactjs.org/ +[go]: https://go.dev/dl/ +[Node.js]: https://nodejs.org/en/download/ +[pnpm]: https://pnpm.io/installation +[Docker]: https://docs.docker.com/get-docker/ +[Docker Compose]: https://docs.docker.com/compose/install/ +[golangci-lint]: https://golangci-lint.run/usage/install/ +[goimports-reviser]: https://github.com/incu6us/goimports-reviser#install +[yamllint]: https://yamllint.readthedocs.io/en/stable/quickstart.html +[VSCodium]: https://vscodium.com/ +[GoLand]: https://www.jetbrains.com/go/ diff --git a/docs/contributing/commitmsg-guidelines.md b/docs/content/en/contributing/development/guidelines-commit-message.md index 670734873..0a8ff7dbc 100644 --- a/docs/contributing/commitmsg-guidelines.md +++ b/docs/content/en/contributing/development/guidelines-commit-message.md @@ -1,19 +1,27 @@  --- -layout: default -title: Commit Message Guidelines -parent: Contributing -nav_order: 3 +title: "Commit Message Guidelines" +description: "Authelia Development Commit Message Guidelines" +lead: "This section covers the git commit message guidelines we use for development." +date: 2022-05-15T13:52:27+10:00 +draft: false +images: [] +menu: +  contributing: +    parent: "development" +weight: 231 +toc: true +aliases: +  - /docs/contributing/commitmsg-guidelines.html  --- -# Commit Message Guidelines +The reasons for these conventions are as follows: -## The reasons for these conventions: +* simple navigation though git history +* easier to read git history -- simple navigation though and easier to read git history +## Commit Message Format -## Format of the commit message: - -Each commit message consists of a **header**, a **body**, and a **footer**. +Each commit message consists of a __header__, a __body__, and a __footer__.  ```bash  <header> @@ -23,19 +31,18 @@ Each commit message consists of a **header**, a **body**, and a **footer**.  <footer>  ``` -The `header` is mandatory and must conform to the [Commit Message Header](#commit-message-header) format. -The header cannot be longer than 72 characters. +The `header` is mandatory and must conform to the [Commit Message Header](#commit-message-header) format. The header +cannot be longer than 72 characters. -The `body` is mandatory for all commits except for those of type "docs". -When the body is present it must be at least 20 characters long and must conform to the  -[Commit Message Body](#commit-message-body) format. +The `body` is mandatory for all commits except for those of type "docs". When the body is present it must be at least 20 +characters long and must conform to the [Commit Message Body](#commit-message-body) format. -The `footer` is optional. The [Commit Message Footer](#commit-message-footer) format describes what the footer is used  +The `footer` is optional. The [Commit Message Footer](#commit-message-footer) format describes what the footer is used  for, and the structure it must have.  ### Commit Message Header -``` +```text  <type>(<scope>): <summary>    │       │             │    │       │             └─⫸ Summary in present tense. Not capitalized. No period at the end. @@ -49,25 +56,24 @@ for, and the structure it must have.  The `<type>` and `<summary>` fields are mandatory, the `(<scope>)` field is optional. -#### Allowed `<type>` values: +#### Allowed type values: -* **build** Changes that affect the build system or external dependencies  +* __build__ Changes that affect the build system or external dependencies    (example scopes: bundler, deps, docker, go, npm) -* **ci** Changes to our CI configuration files and scripts  +* __ci__ Changes to our CI configuration files and scripts    (example scopes: autheliabot, buildkite, codecov, golangci-lint, renovate, reviewdog) -* **docs** Documentation only changes -* **feat** A new feature -* **fix** A bug fix -* **i18n** Internationalization changes -* **perf** A code change that improves performance -* **refactor** A code change that neither fixes a bug nor adds a feature -* **release** Releasing a new version of Authelia -* **test** Adding missing tests or correcting existing tests +* __docs__ Documentation only changes +* __feat__ A new feature +* __fix__ A bug fix +* __perf__ A code change that improves performance +* __refactor__ A code change that neither fixes a bug nor adds a feature +* __release__ Releasing a new version of Authelia +* __test__ Adding missing tests or correcting existing tests -#### Allowed `<scope>` values: +#### Allowed scope values: -The scope should be the name of the package affected  -(as perceived by the person reading the changelog generated from commit messages). +The scope should be the name of the package affected (as perceived by the person reading the changelog generated from +commit messages).  * authentication  * authorization @@ -76,6 +82,7 @@ The scope should be the name of the package affected  * duo  * handlers  * logging +* metrics  * middlewares  * mocks  * model @@ -94,14 +101,11 @@ The scope should be the name of the package affected  There are currently a few exceptions to the "use package name" rule:  * `api`: used for changes that change the openapi specification -  * `cmd`: used for changes to the `authelia|authelia-scripts|authelia-suites` top level binaries -  * `web`: used for changes to the React based frontend - -* none/empty string: useful for `test`, `refactor` and changes that are done across multiple packages  -  (e.g. `test: add missing unit tests`) and for docs changes that are not related to a  -  specific package (e.g. `docs: fix typo in tutorial`). +* none/empty string: useful for `test`, `refactor` and changes that are done across multiple packages +  (e.g. `test: add missing unit tests`) and for docs changes that are not related to a specific package +  (e.g. `docs: fix typo in tutorial`).  #### Summary @@ -111,22 +115,20 @@ Use the summary field to provide a succinct description of the change:  * don't capitalize the first letter  * no dot (.) at the end -  ### Commit Message Body  Just as in the summary, use the imperative, present tense: "fix" not "fixed" nor "fixes". -Explain the motivation for the change in the commit message body. This commit message should explain _why_ you are  -making the change. You can include a comparison of the previous behavior with the new behavior in order to illustrate  +Explain the motivation for the change in the commit message body. This commit message should explain *why* you are +making the change. You can include a comparison of the previous behavior with the new behavior in order to illustrate  the impact of the change. -  ### Commit Message Footer -The footer can contain information about breaking changes and is also the place to reference GitHub issues and other PRs  +The footer can contain information about breaking changes and is also the place to reference GitHub issues and other PRs  that this commit closes or is related to. -``` +```text  BREAKING CHANGE: <breaking change summary>  <BLANK LINE>  <breaking change description + migration instructions> @@ -135,21 +137,19 @@ BREAKING CHANGE: <breaking change summary>  Fixes #<issue number>  ``` -Breaking Change section should start with the phrase "BREAKING CHANGE: " followed by a summary of the breaking change, a  +Breaking Change section should start with the phrase "BREAKING CHANGE: " followed by a summary of the breaking change, a  blank line, and a detailed description of the breaking change that also includes migration instructions. +### Revert Commits -### Revert commits - -If the commit reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit. +If the commit reverts a previous commit, it should begin with `revert:`, followed by the header of the reverted commit.  The content of the commit message body should contain: -- information about the SHA of the commit being reverted in the following format: `This reverts commit <SHA>`, -- a clear description of the reason for reverting the commit message. - +* information about the SHA of the commit being reverted in the following format: `This reverts commit <SHA>`, +* a clear description of the reason for reverting the commit message. -## Example commit message: +## Commit Message Examples  ```bash  fix(logging): disabled colored logging outputs when file is specified @@ -164,4 +164,4 @@ Fixes #1480.  This document is based on [AngularJS Git Commit Message Format]. -[AngularJS Git Commit Message Format]: https://github.com/angular/angular/blob/master/CONTRIBUTING.md#commit
\ No newline at end of file +[AngularJS Git Commit Message Format]: https://github.com/angular/angular/blob/master/CONTRIBUTING.md#commit diff --git a/docs/content/en/contributing/development/guidelines-pull-request.md b/docs/content/en/contributing/development/guidelines-pull-request.md new file mode 100644 index 000000000..1a5f7d12f --- /dev/null +++ b/docs/content/en/contributing/development/guidelines-pull-request.md @@ -0,0 +1,31 @@ +--- +title: "Pull Request Guidelines" +description: "Authelia Development Pull Request Guidelines" +lead: "This section covers the pull request guidelines." +date: 2022-05-23T22:03:03+10:00 +draft: false +images: [] +menu: +  contributing: +    parent: "development" +weight: 232 +toc: true +--- + +[Pull Request] guidelines are in place in order to maintain consistency and clearly communicate our process for +processing merges into the [master] branch. + +## Overview + +* Ensure the `Allow edits by maintainers` checkbox is checked due to our [Squash Merge](#squash-merge) policy +* Ensure you avoid a force push due to our [Squash Merge](#squash-merge) policy and [Review](#review) complications + +## Squash Merge + +Every [Pull Request] will be squash merged into [master]. This requires the [Pull Request] branch to be up-to-date with +the [master] branch. + +## Review + +Every [Pull Request] will undergo a formal review process. This process is heavily complicated if you rewrite history +and/or perform a force push, especially after a maintainer has started a review. As such we request that any action that diff --git a/docs/contributing/style-guide.md b/docs/content/en/contributing/development/guidelines-style.md index 1aabc517d..19f4f8ac6 100644 --- a/docs/contributing/style-guide.md +++ b/docs/content/en/contributing/development/guidelines-style.md @@ -1,30 +1,38 @@  --- -layout: default -title: Style Guide -parent: Contributing -nav_order: 4 +title: "Style Guidelines" +description: "Authelia Development Style Guidelines" +lead: "This section covers the style guidelines we use for development." +date: 2022-05-15T13:52:27+10:00 +draft: false +images: [] +menu: +  contributing: +    parent: "development" +weight: 230 +toc: true +aliases: +  - /docs/contributing/style-guide.html  --- -# Style Guide -  This is a general guide to the code style we aim to abide by. This is by no means an exhaustive list and we're  constantly changing and improving it. This is also a work in progress document. -For our commit messages please see our [Commit Message Guidelines](./commitmsg-guidelines.md). +For our commit messages please see our [Commit Message Guidelines](guidelines-commit-message.md).  ## Tools  We implement the following tools that help us abide by our style guide and include the configuration for them inside  our repository: -- [golangci-lint](https://github.com/golangci/golangci-lint) -- [yamllint](https://yamllint.readthedocs.io/en/stable/) -- [eslint](https://eslint.org/) -- [prettier](https://prettier.io/) + +* [golangci-lint](https://github.com/golangci/golangci-lint) +* [yamllint](https://yamllint.readthedocs.io/en/stable/) +* [eslint](https://eslint.org/) +* [prettier](https://prettier.io/)  ## Exceptions -This is a style **guide** not a cudgel, there are always going to be exceptions to these guidelines when it makes sense  -not to follow them. One notable exception is the README.md for the repository. The line length of the  +This is a style __guide__ not a cudgel, there are always going to be exceptions to these guidelines when it makes sense +not to follow them. One notable exception is the README.md for the repository. The line length of the  [All Contributors](https://allcontributors.org/) individual sections are longer than 120 characters and it doesn't make  sense to apply the [line length](#line-length) guidelines. @@ -37,20 +45,21 @@ display two files side by side (vertically split). As always, keep in mind you s  when it doesn't make sense to.  This includes but is not limited to the following file types: -- Go (*.go) -- YAML (*.yml, *.yaml) -- Markdown (*.md) -- JavaScript (*.js)   -- TypeScript (*.ts, *.tsx) + +* Go (`*.go`) +* YAML (`*.yml`, `*.yaml`) +* Markdown (`*.md`) +* JavaScript (`*.js`) +* TypeScript (`*.ts`, `*.tsx`)  ### Error Strings  Error messages should follow the standard go format. This format can be found in the [golang code review comments](https://github.com/golang/go/wiki/CodeReviewComments#error-strings)  however the key points are: -- errors should not start with capital letters (excluding proper nouns, acronyms, or initialism) -- errors should not end with punctuation -- these restrictions do not apply to logging, only the error type itself +* errors should not start with capital letters (excluding proper nouns, acronyms, or initialism) +* errors should not end with punctuation +* these restrictions do not apply to logging, only the error type itself  ### Configuration Documentation @@ -62,73 +71,69 @@ to check additional sections for examples.  The first thing in the configuration documentation should be a description of the area. This is promptly followed by the  configuration heading (h2 / indent 2) which has an example full configuration. -Under the configuration example each option in the configuration needs to be documented with its own heading  -(h3 / indent 3). Immediately following the heading is a div with some stylized icons.  +Under the configuration example each option in the configuration needs to be documented with its own heading +(h3 / indent 3). Immediately following the heading is a div with some stylized icons.  The body of the section is to contain paragraphs describing the usage and information specific to that value. - -**Example Stylized Icons:** +__Example Stylized Icons:__  ```html -<div markdown="1"> -type: string -{: .label .label-config .label-purple }  -default: example -{: .label .label-config .label-blue } -required: no -{: .label .label-config .label-green } -</div> +{{< print "{{< confkey type=\"string\" default=\"none\" required=\"no\" >}}" >}}  ```  ##### type -This section has the type of the value in a semi human readable format. Some example values are `string`, `integer`,  -`boolean`, `list(string)`, `duration`. This is immediately followed by the styles `.label`, `.label-config`,  -`.label-purple`. +This section has the type of the value in a semi human readable format. Some example values are `string`, `integer`, +`boolean`, `list(string)`, `duration`.  ##### default  This section has the default of the value if one exists, this section can be completely omitted if there is no default. -This is immediately followed by the styles `.label`, `.label-config`, -`.label-blue`.  ##### required  This section has the required status of the value and must be one of `yes`, `no`, or `situational`. Situational means it -depends on other configuration options. If it's situational the situational usage should be documented. This is  -immediately followed by the styles `.label`, `.label-config`, and a traffic lights color label, i.e. if yes `.label-red`,  -if no `.label-green`, or if situational `.label-yellow`. +depends on other configuration options. If it's situational the situational usage should be documented.  ### Storage +  This section outlines some rules for storage contributions. Including but not limited to migrations, schema rules, etc.  #### Migrations +  All migrations must have an up and down migration, preferably idempotent.  All migrations must be named in the following format: +  ```text  V<version>.<name>.<engine>.<direction>.sql  ```  ##### version +  A 4 digit version number, should be in sequential order.  ##### name +  A name containing alphanumeric characters, underscores (treated as spaces), hyphens, and no spaces.  ##### engine +  The target engine for the migration, options are all, mysql, postgres, and sqlite.  #### Primary Key -All tables must have a primary key. This primary key must be an integer with auto increment enabled, or in the case of  + +All tables must have a primary key. This primary key must be an integer with auto increment enabled, or in the case of  PostgreSQL a serial type.  #### Table/Column Names -Table and Column names must be in snake case format. This means they must have only lowercase letters, and have words  + +Table and Column names must be in snake case format. This means they must have only lowercase letters, and have words  seperated by underscores. The reasoning for this is that some database engines ignore case by default and this makes it  easy to be consistent with the casing.  #### Context +  All database methods should include the context attribute so that database requests that are no longer needed are  terminated appropriately. diff --git a/docs/content/en/contributing/development/integration-suites.md b/docs/content/en/contributing/development/integration-suites.md new file mode 100644 index 000000000..bf1a0babf --- /dev/null +++ b/docs/content/en/contributing/development/integration-suites.md @@ -0,0 +1,83 @@ +--- +title: "Integration Suites" +description: "Integration Suites." +lead: "This section covers the build process and how to perform tests in development." +date: 2022-05-15T13:52:27+10:00 +draft: false +images: [] +menu: +  contributing: +    parent: "development" +weight: 240 +toc: true +aliases: +  - /docs/contributing/suites.html +--- + +__Authelia__ is a single component in interaction with many others in a complete ecosystem. Consequently, testing the +features is not as easy as we might think. In order to solve this problem, Authelia came up with the concept of suite +which is a kind of virtual environment for Authelia and a set of tests. A suite can setup components such as NGINX, +Redis or MariaDB in which __Authelia__ can run and be tested. + +This abstraction allows to prepare an environment for manual testing during development and also to craft and run +integration tests efficiently. + +## Start a suite + +Starting a suite called *Standalone* is done with the following command: + +```bash +authelia-scripts suites setup Standalone +``` + +This command deploys the environment of the suite. + +## Run tests of a suite + +### Run tests of running suite + +If a suite is already running, you can simply type the test command that will run the test related to the currently +running suite: + +```bash +authelia-scripts suites test +``` + +### Run tests of non-running suite + +However, if no suite is running yet and you just want to run the tests of a specific suite like *HighAvailability*, you +can do so with the next command: + +```bash +authelia-scripts suites test HighAvailability +``` + +### Run all tests of all suites + +Running all tests is easy. Make sure that no suite is already running and run: + +```bash +authelia-scripts suites test +``` + +### Run tests in headless mode + +As you might have noticed, the tests are run using chromedriver and selenium. It means that the tests open an instance +of Chrome that might interfere with your other activities. In order to run the tests in headless mode to avoid the +interference, use the following command: + +```bash +authelia-scripts suites test --headless +``` + +## Create a suite + +Creating a suite is as easy. Let's take the example of the __Standalone__ suite: + +* __suite_standalone.go__ - It defines the setup and teardown phases. It likely uses docker-compose to setup the +  ecosystem. This file also defines the timeouts. +* __suite_standalone_test.go__ - It defines the set of tests to run against the suite. +* __Standalone__ directory - It contains resources required by the suite and likely mounted in the containers. + +A suite can also be much more complex like setting up a complete Kubernetes ecosystem. You can check the Kubernetes +suite as example. diff --git a/docs/content/en/contributing/development/introduction.md b/docs/content/en/contributing/development/introduction.md new file mode 100644 index 000000000..cbdbe3488 --- /dev/null +++ b/docs/content/en/contributing/development/introduction.md @@ -0,0 +1,24 @@ +--- +title: "Development" +description: "An introduction into contributing to the Authelia project via development." +lead: "An introduction into contributing to the Authelia project via development." +date: 2022-05-15T13:52:27+10:00 +draft: false +images: [] +menu: +  contributing: +    parent: "development" +weight: 210 +toc: true +--- + +We encourage anyone who wishes to contribute via development to utilize GitHub [Issues] or [Discussions] or one of the +[other contact methods](../../information/contact.md) to discuss their contribution in advance and come up with a design +plan. + +It's also important that you read guidelines and try to follow them. The development section is arranged in the order +we recommend reading it, and you can utilize the pagination at the bottom to navigate to the next part of the +development guide. + +[Issues]: https://github.com/authelia/authelia/issues +[Discussions]: https://github.com/authelia/authelia/discussions diff --git a/docs/content/en/contributing/development/reference-authelia-scripts.md b/docs/content/en/contributing/development/reference-authelia-scripts.md new file mode 100644 index 000000000..ca3a065c1 --- /dev/null +++ b/docs/content/en/contributing/development/reference-authelia-scripts.md @@ -0,0 +1,65 @@ +--- +title: "Reference: authelia-scripts" +description: "This section covers the authelia-scripts tool." +lead: "This section covers the authelia-scripts tool." +date: 2022-05-15T13:52:27+10:00 +draft: false +images: [] +menu: +  contributing: +    parent: "development" +weight: 290 +toc: true +aliases: +  - /docs/contributing/authelia-scripts.html +--- + +__Authelia__ comes with a set of dedicated scripts to perform a broad range of operations such as building the +distributed version of Authelia, building the Docker image, running suites, testing the code, etc. This is a small +reference guide for the command, the full guide can be found in the +[CLI Reference](../../reference/cli/authelia-scripts/authelia-scripts.md). + +## Examples + +Those scripts become available after sourcing the `bootstrap.sh` script with: + +```bash +source bootstrap.sh +``` + +Then, you can access the scripts usage by running the following command: + +```bash +authelia-scripts --help +``` + +For instance, you can build __Authelia__ ([go] binary and [React] frontend) with: + +```bash +authelia-scripts build +``` + +Or build the official [Docker] image with: + +```bash +authelia-scripts docker build +``` + +Or start the *Standalone* suite with: + +```bash +authelia-scripts suites setup Standalone +``` + +## Help + +The `authelia-scripts` provides help using the `--help` or `-h` flags. Every command should provide some form of help +when provided with either flag. Examples: + +```bash +authelia-scripts --help +``` + +```bash +authelia-scripts build --help +``` diff --git a/docs/content/en/contributing/prologue/_index.md b/docs/content/en/contributing/prologue/_index.md new file mode 100644 index 000000000..a7f8fbb8c --- /dev/null +++ b/docs/content/en/contributing/prologue/_index.md @@ -0,0 +1,9 @@ +--- +title : "Prologue" +description: "Contributing Prologue" +lead: "" +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +weight: 100 +--- diff --git a/docs/content/en/contributing/prologue/documentation.md b/docs/content/en/contributing/prologue/documentation.md new file mode 100644 index 000000000..bfb6c457b --- /dev/null +++ b/docs/content/en/contributing/prologue/documentation.md @@ -0,0 +1,127 @@ +--- +title: "Documentation" +description: "Information on contributing documentation to the Authelia project." +lead: "Authelia has great documentation however there are always things that can be added. This section describes the contribution process for the documentation even though it's incredibly easy." +date: 2022-05-19T14:18:33+10:00 +draft: false +images: [] +menu: +  contributing: +    parent: "prologue" +weight: 130 +toc: true +--- + +## Introduction + +The website is built on [Hugo] using the [Doks] theme. [Hugo] is a powerful website building tool which allows several +simple workflows for developers as well as numerous handy features like [Shortcodes] which allow building reusable +parameterized sections of content. + +## Making a Change + +Anyone can simply edit the [Markdown] of the relevant document which shares a path with the website URL under the +[docs folder on GitHub]. In most if not all pages there is a link included at the very bottom which links directly to +the [Markdown] file responsible for the document. + +## Viewing Changes + +It's relatively easy to run the __Authelia__ website locally to test out the changes you've made. + +### Requirements + +* [git] *(though this can be skipped if you just download the repository)* +* [Node.js] and npm *(bundled with [Node.js])* + +### Directions + +The following steps will allow you to run the website on the localhost and view it live in your browser: + +1. Run the following commands: + +  ```bash +  git clone https://github.com/authelia/authelia.git +  cd authelia/docs +  npm run install +  npm run start +  ``` + +2. Visit [http://localhost:1313/](http://localhost:1313/) in your browser. +3. Modify pages to see the effects live in your browser. + +## Front Matter + +Most documents come with a front matter that looks similar to this: + +```yaml +--- +title: "A Page Title" +description: "This is a description of the page." +lead: "This is a page lead." +date: 2022-03-19T04:53:05+00:00 +draft: false +menu: +  development: +    parent: "prologue" +weight: 100 +toc: true +--- +``` + +The front matter controls several aspects about how the page is displayed and varying other aspects. + +### Open Graph Protocol + +First of all it's important to understand the [Open Graph Protocol]. This is a protocol developed by Meta / Facebook +which is utilized by most social media platforms to display a preview of a website. This is done by customizing special +HTML `<meta />` tags. + +### Fields + +This section documents each of the fields that we commonly use. + +#### title + +String. Configures the `<title />` element, the first `<h1 />` element, and the [Open Graph Protocol] `og:title` value. + +#### description + +String. Configures the and the [Open Graph Protocol] `og:description` value. + +#### lead + +String. Configures the first paragraph of a page which occurs directly after the [title](#title). + +#### date + +Timestamp. Configures the [Open Graph Protocol] `og:article:published_time` value. Also used in the [Blog](../../blog). + +#### draft + +Boolean. Configures the visibility of a page. If it's set to `true` it is invisible. + +#### menu + +Dictionary. Configures the menu linkage. + +#### weight + +Integer. Configures the position in the menu and the order in which pagination occurs. + +#### toc + +Boolean. Enables or disables the Table of Contents or `On This Page` section. + +#### community + +Boolean. Enables or disables the Community page header. This value only has an effect in the Integration section at this +stage. + +[docs folder on GitHub]: https://github.com/authelia/authelia/tree/master/docs +[Hugo]: https://gohugo.io/ +[Shortcodes]: https://gohugo.io/content-management/shortcodes/ +[Doks]: https://getdoks.org/ +[Markdown]: https://www.markdownguide.org/ +[git]: https://git-scm.com/ +[Node.js]: https://nodejs.org/en/ +[Open Graph Protocol]: https://ogp.me/ diff --git a/docs/content/en/contributing/prologue/financial.md b/docs/content/en/contributing/prologue/financial.md new file mode 100644 index 000000000..b4f9639cf --- /dev/null +++ b/docs/content/en/contributing/prologue/financial.md @@ -0,0 +1,73 @@ +--- +title: "Financial" +description: "Information on contributing financially to the Authelia project." +lead: "The Authelia team is small and all of the maintainers spend their free time managing the project. Some may wish to contribute financially for various reasons, this page provides information about doing so." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  contributing: +    parent: "prologue" +weight: 120 +toc: true +--- + +## Where the Money Is Used + +Financial contribution methods on the Authelia GitHub repositories and on the Authelia website are always utilized in +the development of Authelia in some way. None of the money is utilized for any personal expense. The Authelia +maintainers are unpaid. + +At this stage the usage of money donated has been minimal with only a single instance of money being used. This money +was voluntarily given to security researchers who discovered a vulnerability which has since been fixed. This exchange +was not prompted by any bug bounty program as we do not have one, but we hope to in the future. + +Potential usage for the money, ranked in order of priority: + +1. Put Authelia through a comprehensive [Security Audit](../../information/security.md#help-wanted). +   1. Audit of Code Security via Analysis. +   2. Audit via Penetration Testing. +2. Bug Bounty Program. + +## How to Contribute Financially + +Please visit [Open Collective] in order to financially contribute to Authelia. + +## Sponsorship + +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. + +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: + +* [Security Audit](../../information/security.md#help-wanted) + +### Balto + +Our [apt repository](https://apt.authelia.com) is hosted thanks to [Balto](https://www.getbalto.com/?from=Authelia). + +### Buildkite + +Our [continuous integration and continuous deployment pipelines](https://buildkite.com/authelia/?from=Authelia) are hosted by +[Buildkite](https://buildkite.com/features?from=Authelia). + +### Crowdin + +Our [localization platform](https://translate.authelia.com) is hosted by [Crowdin](https://crowdin.com/?from=Authelia). + +### JetBrains + +Our development IDE's are provided by [JetBrains](https://www.jetbrains.com/?from=Authelia). + +### Microsoft + +Our pipeline agents which we rely on for productivity are hosted on [Azure](https://azure.microsoft.com/?from=Authelia) +and our [git repositories](https://github.com/authelia) are hosted on [GitHub](https://github.com/?from=Authela) +which are both [Microsoft](https://www.microsoft.com/?from=Authelia) products. + +### Netlify + +Our [website and documentation](https://www.authelia.com) are built and hosted by +[Netlify](https://www.netlify.com/?from=Authelia). diff --git a/docs/content/en/contributing/prologue/introduction.md b/docs/content/en/contributing/prologue/introduction.md new file mode 100644 index 000000000..10aaa33ea --- /dev/null +++ b/docs/content/en/contributing/prologue/introduction.md @@ -0,0 +1,30 @@ +--- +title: "Prologue" +description: "An introduction into contributing to the Authelia project." +lead: "An introduction into contributing to the Authelia project." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  contributing: +    parent: "prologue" +weight: 110 +toc: true +aliases: +  - /docs/contributing/ +--- + +Contributions to __Authelia__ have four main forms: + +* Utilizing GitHub [Issues] or [Discussions] to make commentary about bugs, ideas, etc. +* [Development](../development/introduction.md) +* [Documentation](../documentation/introduction.md) +* [Financial](financial.md) + +We encourage our community to be part of __Authelia__ by contributing in these ways. We encourage anyone who wishes to +contribute via development to utilize GitHub [Issues] or [Discussions] or one of the +[other contact methods](../../information/contact.md) to discuss their contribution in advance and come up with a design +plan. + +[Issues]: https://github.com/authelia/authelia/issues +[Discussions]: https://github.com/authelia/authelia/discussions diff --git a/docs/content/en/contributing/prologue/translations.md b/docs/content/en/contributing/prologue/translations.md new file mode 100644 index 000000000..48a2067af --- /dev/null +++ b/docs/content/en/contributing/prologue/translations.md @@ -0,0 +1,35 @@ +--- +title: "Translations" +description: "Information on contributing translations to the Authelia project." +lead: "Authelia has translations for many using facing areas of the web portal. Contributing to these translations is a very easy process." +date: 2022-05-16T13:42:36+10:00 +draft: false +images: [] +menu: +  contributing: +    parent: "prologue" +weight: 130 +toc: true +aliases: +  - /docs/contributing/translations.html +--- + +The way the translation process is facilitated is via [Crowdin]. We encourage members of the community to +[join the Authelia Crowdin project](https://translate.authelia.com) and help translate their preferred language. + +## New Langauges + +If the language you wish to translate is not on [Crowdin] then you have a few options: + +1. Ask for the language to be added via the [Crowdin] interface. +2. Ask a maintainer to add it via one of the [contact options](../../information/contact.md). +3. Make a pull request directly on GitHub modifying the translation files within +[this directory](https://github.com/authelia/authelia/tree/master/internal/server/locales). + +## Overrides + +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 +translation and see if it looks correct in the browser. + +[Crowdin]: https://translate.authelia.com diff --git a/docs/content/en/contributors/_index.md b/docs/content/en/contributors/_index.md new file mode 100644 index 000000000..2ce6b1acd --- /dev/null +++ b/docs/content/en/contributors/_index.md @@ -0,0 +1,9 @@ +--- +title: "Contributors" +description: "The Doks contributors." +date: 2020-11-04T08:26:58+01:00 +draft: false +images: [] +--- + +The Doks contributors. diff --git a/docs/content/en/contributors/james-elliott/_index.md b/docs/content/en/contributors/james-elliott/_index.md new file mode 100644 index 000000000..415c2f463 --- /dev/null +++ b/docs/content/en/contributors/james-elliott/_index.md @@ -0,0 +1,15 @@ +--- +title: "James Elliott" +description: "Authelia Core Team" +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +--- + +*__Authelia Core Team Member.__* + +__GitHub:__ [james-d-elliott](https://github.com/james-d-elliott) + +__Email:__ [james.elliott@authelia.com](mailto:james.elliott@authelia.com) + +__Matrix:__ [@james:authelia.com](https://matrix.to/#/@james:authelia.com) __Discord:__ [James#6549](https://discord.com/users/209869584814047232/) diff --git a/docs/content/en/information/_index.md b/docs/content/en/information/_index.md new file mode 100644 index 000000000..0501a5a3e --- /dev/null +++ b/docs/content/en/information/_index.md @@ -0,0 +1,7 @@ +--- +title: "Information" +description: "Information about the project." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +--- diff --git a/docs/content/en/information/code-of-conduct.md b/docs/content/en/information/code-of-conduct.md new file mode 100644 index 000000000..42d441197 --- /dev/null +++ b/docs/content/en/information/code-of-conduct.md @@ -0,0 +1,125 @@ +--- +title: "Code of Conduct" +description: "An introduction into contributing to the Authelia project." +lead: "An introduction into contributing to the Authelia project." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  contributing: +    parent: "information" +weight: 100 +toc: true +aliases: +  - /code-of-conduct +  - /code-of-conduct.html +  - /conduct +  - /conduct.html +  - /coc +  - /coc.html +--- + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for +everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity +and expression, level of experience, education, socioeconomic status, nationality, personal appearance, race, religion, +or sexual identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience +* Focusing on what is best not just for us as individuals, but for the overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take +appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, +issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for +moderation decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing +the community in public spaces. Examples of representing our community include using an official e-mail address, posting +via an official social media account, or acting as an appointed representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible +for enforcement at team@authelia.com. + +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem +in violation of this Code of Conduct: + +### 1. Correction + +__Community Impact:__ Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the +community. + +__Consequence:__ A private, written warning from community leaders, providing clarity around the nature of the violation +and an explanation of why the behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +__Community Impact:__ A violation through a single incident or series of actions. + +__Consequence:__ A warning with consequences for continued behavior. No interaction with the people involved, including +unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding +interactions in community spaces as well as external channels like social media. Violating these terms may lead to a +temporary or permanent ban. + +### 3. Temporary Ban + +__Community Impact:__ A serious violation of community standards, including sustained inappropriate behavior. + +__Consequence:__ A temporary ban from any sort of interaction or public communication with the community for a specified +period of time. No public or private interaction with the people involved, including unsolicited interaction with those +enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +__Community Impact:__ Demonstrating a pattern of violation of community standards, including sustained inappropriate +behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. + +__Consequence:__ A permanent ban from any sort of public interaction within the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0, available at +[https://www.contributor-covenant.org/version/2/0/code_of_conduct.html](https://www.contributor-covenant.org/version/2/0/code_of_conduct.html). + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity). + +For answers to common questions about this code of conduct, see the FAQ at +[https://www.contributor-covenant.org/faq](https://www.contributor-covenant.org/faq). Translations are available at +[https://www.contributor-covenant.org/translations](https://www.contributor-covenant.org/translations). + +__Effective Date:__ *16th May 2022* + +[homepage]: https://www.contributor-covenant.org diff --git a/docs/content/en/information/contact.md b/docs/content/en/information/contact.md new file mode 100644 index 000000000..706f3bd3b --- /dev/null +++ b/docs/content/en/information/contact.md @@ -0,0 +1,53 @@ +--- +title: "Contact" +description: "Drop us an email." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +aliases: +  - /contact +  - /contact.html +--- + +## Security + +If you believe you have identified a security related bug with Authelia please visit the [security policy](security.md) +documentation. + +## GitHub + +### Issues + +If you have found a bug or have a feature request please visit +[GitHub Issues](https://github.com/authelia/authelia/issues) and once you've checked an existing bug or feature request +has not been lodged feel free to lodge your own. + +Bug reports should be reserved for bugs with Authelia, not for issues with the documentation or problems with +integration. If you are having an issue with one of these areas please utilize [discussions](#discussions) or one of +the [chat](#chat) methods. + +### Discussions + +If you have a general question or want to discuss an idea that's not entirely hashed out please visit +[GitHub Discussions](https://github.com/authelia/authelia/discussions) and start a new discussion. + +## Chat + +Authelia has a community chat service which can either be accessed via Matrix or Discord. + +### Matrix + +The Matrix chat is organized into a space which can be accessed at +[community:authelia.com](https://matrix.to/#/#community:authelia.com) which has two main rooms +[support:authelia.com](https://matrix.to/#/#support:authelia.com) and +[contributing:authelia.com](https://matrix.to/#/#contributing:authelia.com). + +### Discord + +Discord can be accessed via [https://discord.authelia.com](https://discord.authelia.com). + +## Email + +To contact the team for anything not security related you can utilized {{< email user="team" domain="authelia.com" >}}. + +For all security related matters over email please ensure you use {{< email user="security" domain="authelia.com" >}}. diff --git a/docs/content/en/information/privacy-policy.md b/docs/content/en/information/privacy-policy.md new file mode 100644 index 000000000..4b8ff644b --- /dev/null +++ b/docs/content/en/information/privacy-policy.md @@ -0,0 +1,34 @@ +--- +title: "Privacy Policy" +description: "We do not use cookies and we do not collect any personal data." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  contributing: +    parent: "information" +weight: 110 +toc: true +aliases: +  - /privacy-policy +  - /privacy-policy.html +  - /privacy +  - /privacy.html +--- + +__TLDR__: We do not use cookies and we do not collect any personal data. + +## Website visitors + +* No personal information is collected. +* No information is stored in the browser. +* No information is shared with, sent to or sold to third-parties. +* No information is shared with advertising companies. +* No information is mined and harvested for personal and behavioral trends. +* No information is monetized. + +## Contact us + +[Contact us](contact.md) if you have any questions. + +__Effective Date:__ *16th May 2022* diff --git a/docs/content/en/information/security.md b/docs/content/en/information/security.md new file mode 100644 index 000000000..4793e3f2d --- /dev/null +++ b/docs/content/en/information/security.md @@ -0,0 +1,73 @@ +--- +title: "Security" +description: "Report security issues." +date: 2022-05-15T13:52:27+10:00 +draft: false +images: [] +aliases: +  - /security +  - /security.html +--- + +The __Authelia__ team takes security very seriously. Because __Authelia__ is intended as a security product a lot of +decisions are made with security being the priority. + +## Coordinated vulnerability disclosure + +__Authelia__ follows the +[coordinated vulnerability disclosure](https://en.wikipedia.org/wiki/Coordinated_vulnerability_disclosure) model when +dealing with security vulnerabilities. This was previously known as responsible disclosure. We strongly urge anyone +reporting vulnerabilities to __Authelia__ or any other project to follow this model as it is considered as a best +practice by many in the security industry. + +If you believe you have identified a security related bug with Authelia please do not open an issue, do not notify us in +public, and do not disclose this issue to third parties. Please use one of the [contact options](#contact-options) +below. + +## Contact Options + +### Email + +Please either utilize the {{< email user="security" domain="authelia.com" >}} email address for security issues +discovered. This email address is only accessible by key members of the team for the purpose of disclosing security +issues within the __Authelia__ code base. + +This is the preferred method of reporting. + +### Chat + +If you wish to chat directly instead of sending an email please use one of the [chat options](contact.md#chat) but it +is vital that when you do that you only do so privately with one of the maintainers. In order to start a private +discussion you should ask to have a private discussion with a team member without mentioning the reason why you wish to +have a private discussion so that provided the bug is confirmed we can coordinate the release of fixes and information +responsibly. + +## Credit + +Users who report bugs will optionally be credited for the discovery in the +[security advisory](https://github.com/authelia/authelia/security/advisories) and/or in our +[all contributors](https://github.com/authelia/authelia/blob/master/README.md#contribute) configuration/documentation. + +## Process + +1. User privately reports a potential vulnerability. +2. The core team reviews the report and ascertain if additional information is required. +3. The core team reproduces the bug. +4. The bug is patched, and if possible the user reporting te bug is given access to a fixed version or git patch. +5. The fix is confirmed to resolve the vulnerability. +6. The fix is released. +7. The security advisory is published sometime after users have had a chance to update. + +## Help wanted + +We are actively looking for sponsorship to obtain security audits to comprehensively ensure the security of Authelia. +As security is imperative to us we see this as one of the main financial priorities. + +We believe that we should obtain the following categories of security audits: + +* Code Security Audit / Analysis +* Penetration Testing + +If you know of a company which either performs these kinds of audits and would be willing to sponsor the audit in some +way such as doing it pro bono or at a discounted rate, or wants to help improve Authelia in a meaningful way and is +willing to make a financial contribution towards this then please feel free to contact us. diff --git a/docs/content/en/integration/_index.md b/docs/content/en/integration/_index.md new file mode 100644 index 000000000..62d2ef55f --- /dev/null +++ b/docs/content/en/integration/_index.md @@ -0,0 +1,8 @@ +--- +title : "Integration" +description: "Integration Docs" +lead: "" +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +--- diff --git a/docs/content/en/integration/deployment/_index.md b/docs/content/en/integration/deployment/_index.md new file mode 100644 index 000000000..1e21a81ff --- /dev/null +++ b/docs/content/en/integration/deployment/_index.md @@ -0,0 +1,9 @@ +--- +title: "Deployment" +description: "Deployment" +lead: "" +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +weight: 200 +--- diff --git a/docs/content/en/integration/deployment/automation.md b/docs/content/en/integration/deployment/automation.md new file mode 100644 index 000000000..b71312b87 --- /dev/null +++ b/docs/content/en/integration/deployment/automation.md @@ -0,0 +1,24 @@ +--- +title: "Automation" +description: "Automated Deployment of Authelia." +lead: "Authelia has several features which make automation easy." +date: 2022-05-28T08:20:42+10:00 +draft: false +images: [] +menu: +  integration: +    parent: "deployment" +weight: 220 +toc: true +--- + +1. The [configuration](../../configuration/prologue/introduction.md) can be defined statically by YAML. +2. Most areas of the configuration can be defined by [environment variables](../../configuration/methods/environment.md). + +## Ansible + +*Authelia* could theoretically be easily deployed via [Ansible] however we do not have an [Ansible Role] at this time. +It would be a desirable [Contribution](../../contributing/development/introduction.md). + +[Ansible]: https://www.ansible.com/ +[Ansible Role]: https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_roles.html diff --git a/docs/content/en/integration/deployment/bare-metal.md b/docs/content/en/integration/deployment/bare-metal.md new file mode 100644 index 000000000..ea41f8717 --- /dev/null +++ b/docs/content/en/integration/deployment/bare-metal.md @@ -0,0 +1,49 @@ +--- +title: "Bare-Metal" +description: "Deploying Authelia on Bare-Metal." +lead: "Authelia can be deployed on Bare-Metal as long as it sits behind a proxy." +date: 2022-05-27T22:24:38+10:00 +draft: false +images: [] +menu: +  integration: +    parent: "deployment" +weight: 250 +toc: true +--- + +There are several ways to achieve this, as *Authelia* runs as a daemon. We do not provide specific examples for running +*Authelia* as a service excluding the [systemd unit](#systemd) files. + +## systemd + +We publish two example [systemd] unit files: + +* [authelia.service](https://github.com/authelia/authelia/blob/master/authelia.service) +* [authelia@.service](https://github.com/authelia/authelia/blob/master/authelia%40.service) + +## Arch Linux + +In addition to the [binaries](#binaries) we publish, we also publish an +[AUR Package](https://aur.archlinux.org/packages/authelia). + +## Debian + +We publish `.deb` packages with our [releases] which can be installed +on most Debian based operating systems. + +### APT Repository + +In addition to the `.deb` packages we also have an [APT Repository](https://apt.authelia.com). + +## FreeBSD + +In addition to the [binaries](#binaries) we publish, [FreshPorts](https://www.freshports.org/www/authelia/) offer a +package. + +## Binaries + +We publish binaries with our [releases] which can be installed on many operating systems. + +[releases]: https://github.com/authelia/authelia/releases +[systemd]: https://systemd.io/ diff --git a/docs/content/en/integration/deployment/docker.md b/docs/content/en/integration/deployment/docker.md new file mode 100644 index 000000000..9e8347cf7 --- /dev/null +++ b/docs/content/en/integration/deployment/docker.md @@ -0,0 +1,160 @@ +--- +title: "Docker" +description: "A guide on installing Authelia in Docker." +lead: "This is one of the primary ways we deliver Authelia to users and the recommended path." +date: 2022-05-27T22:24:38+10:00 +draft: false +images: [] +menu: +  integration: +    parent: "deployment" +weight: 230 +toc: true +--- + +The [Docker] container is deployed with the following image names: + +* [authelia/authelia](https://hub.docker.com/r/authelia/authelia) +* [docker.io/authelia/authelia](https://hub.docker.com/r/authelia/authelia) +* [ghcr.io/authelia/authelia](https://github.com/authelia/authelia/pkgs/container/authelia) + +## Docker Compose + +We provide two main [Docker Compose] examples which can be utilized to help test *Authelia* or can be adapted into your +existing [Docker Compose]. + +* [Unbundled Example](#standalone-example) +* [Bundle: lite](#lite) +* [Bundle: local](#local) + +### Standalone Example + +The following is an example [Docker Compose] deployment with just *Authelia* and no bundled applications or proxies. + +It expects the following: + +* The file `data/authelia/config/configuration.yml` is present and the configuration file. +* The files `data/authelia/secrets/*` exist and contain the relevant secrets. +* You're using PostgreSQL. +* You have an external network named `net` which is in bridge mode. + +```yaml +version: "3.8" +secrets: +  JWT_SECRET: +    file: ${PWD}/data/authelia/secrets/JWT_SECRET +  SESSION_SECRET: +    file: ${PWD}/data/authelia/secrets/SESSION_SECRET +  STORAGE_PASSWORD: +    file: ${PWD}/data/authelia/secrets/STORAGE_PASSWORD +  STORAGE_ENCRYPTION_KEY: +    file: ${PWD}/data/authelia/secrets/STORAGE_ENCRYPTION_KEY +  OIDC_HMAC_KEY: +    file: ${PWD}/data/authelia/secrets/OIDC_HMAC_KEY +  OIDC_PRIVATE_KEY: +    file: ${PWD}/data/authelia/secrets/OIDC_PRIVATE_KEY +services: +  authelia: +    container_name: authelia +    image: docker.io/authelia/authelia:latest +    restart: unless-stopped +    networks: +      net: +        aliases: [] +    expose: +      - 9091 +    secrets: [JWT_SECRET, SESSION_SECRET, STORAGE_PASSWORD, STORAGE_ENCRYPTION_KEY, OIDC_HMAC_KEY, OIDC_PRIVATE_KEY] +    environment: +      AUTHELIA_JWT_SECRET_FILE: /run/secrets/JWT_SECRET +      AUTHELIA_SESSION_SECRET_FILE: /run/secrets/SESSION_SECRET +      AUTHELIA_STORAGE_POSTGRES_PASSWORD_FILE: /run/secrets/STORAGE_PASSWORD +      AUTHELIA_STORAGE_ENCRYPTION_KEY_FILE: /run/secrets/STORAGE_ENCRYPTION_KEY +      AUTHELIA_IDENTITY_PROVIDERS_OIDC_HMAC_SECRET_FILE: /run/secrets/OIDC_HMAC_KEY +      AUTHELIA_IDENTITY_PROVIDERS_OIDC_ISSUER_PRIVATE_KEY_FILE: /run/secrets/OIDC_PRIVATE_KEY +    volumes: +      - ${PWD}/data/authelia/config:/config +networks: +  net: +    external: true +    name: net +``` + +#### Running the Proxy on the Host Instead of in a Container + +If you wish to run the proxy as a systemd service or other daemon, you will need to adjust the configuration. While this +configuration is not specific to *Authelia* and is mostly a [Docker] concept we explain this here to help alleviate the +users asking how to accomplish this. It should be noted that we can't provide documentation or support for every +architectural choice our users make and you should expect to do your own research to figure this out where possible. + +The example below includes the additional `ports` option which must be added in order to allow communication to +*Authelia* from daemons on the [Docker] host. The other values are used to show context within the +[Standalone Example](#standalone-example) above. The example allows *Authelia* to be communicated with over the +localhost IP address `127.0.0.1` on port `9091`. You need to adjust this to your specific needs. + +```yaml +services: +  authelia: +    container_name: authelia +    image: docker.io/authelia/authelia:latest +    restart: unless-stopped +    networks: +      net: +        aliases: [] +    expose: +      - 9091 +    ports: +      - "127.0.0.1:9091:9091" +``` + +### Bundles + +To use the bundles we recommend first cloning the git repository and checking out the latest release on a Linux Desktop: + +```bash +git clone https://github.com/authelia/authelia.git +cd authelia +git checkout $(git describe --tags `git rev-list --tags --max-count=1`) +``` + +#### lite + +The [lite bundle](https://github.com/authelia/authelia/tree/master/examples/compose/lite) can be used by following this +process: + +1. Perform the commands in [the bundles section](#bundles). +2. Run the `cd examples/compose/lite` command. +3. Edit `users_database.yml` and either change the username of the `authelia` user, or +   [generate a new password](../../reference/guides/passwords.md#passwords), or both. The default password is +   `authelia`. +4. Edit the `configuration.yml` and `docker-compose.yml` with your respective domains and secrets. +5. Run `docker compose up -d` or `docker-compose up -d`. + +#### local + +The [local bundle](https://github.com/authelia/authelia/tree/master/examples/compose/local) can be setup after cloning +the repository as per the [bundles](#bundles) section then running the following commands on a Linux Desktop: + +```bash +cd examples/compose/local +./setup.sh +``` + +The bundle setup modifies the `/etc/hosts` file which is performed with `sudo`. Once it is successfully setup you can +visit the following URL's to see Authelia in action (`example.com` will be replaced by the domain you specified): + +* [https://public.example.com](https://public.example.com) - Bypasses Authelia +* [https://traefik.example.com](https://traefik.example.com) - Secured with Authelia one-factor authentication +* [https://secure.example.com](https://secure.example.com) - Secured with Authelia two-factor authentication (see note below) + +You will need to authorize the self-signed certificate upon visiting each domain. To visit +[https://secure.example.com](https://secure.example.com) you will need to register a device for second factor +authentication and confirm by clicking on a link sent by email. Since this is a demo with a fake email address, the +content of the email will be stored in `./authelia/notification.txt`. Upon registering, you can grab this link easily by +running the following command: + +```bash +grep -Eo '"https://.*" ' ./authelia/notification.txt. +``` + +[Docker]: https://docker.com +[Docker Compose]: https://docs.docker.com/compose/ diff --git a/docs/content/en/integration/deployment/introduction.md b/docs/content/en/integration/deployment/introduction.md new file mode 100644 index 000000000..ba70f2912 --- /dev/null +++ b/docs/content/en/integration/deployment/introduction.md @@ -0,0 +1,19 @@ +--- +title: "Deployment" +description: "An introduction into integrating Authelia with a product." +lead: "An introduction into integrating Authelia within your architecture." +date: 2022-05-27T22:24:38+10:00 +draft: false +images: [] +menu: +  integration: +    parent: "deployment" +weight: 210 +toc: true +--- + +There are three main methods to deploy *Authelia*. + +1. [Docker](docker.md) +2. [Kubernetes](../kubernetes/introduction/index.md) +3. [Bare-Metal](bare-metal.md) diff --git a/docs/content/en/integration/deployment/kubernetes.md b/docs/content/en/integration/deployment/kubernetes.md new file mode 100644 index 000000000..efe6f74ba --- /dev/null +++ b/docs/content/en/integration/deployment/kubernetes.md @@ -0,0 +1,17 @@ +--- +title: "Kubernetes" +description: "Test Description" +lead: "An introduction into integrating Authelia with Kubernetes." +date: 2022-05-28T08:20:42+10:00 +draft: false +images: [] +menu: +  integration: +    parent: "deployment" +    identifier: "kubernetes-deployment" +weight: 240 +toc: true +search: false +--- + +Please see the dedicated [Kubernetes Documentation](../kubernetes/introduction/index.md). diff --git a/docs/content/en/integration/kubernetes/_index.md b/docs/content/en/integration/kubernetes/_index.md new file mode 100644 index 000000000..945e8c52e --- /dev/null +++ b/docs/content/en/integration/kubernetes/_index.md @@ -0,0 +1,9 @@ +--- +title: "Kubernetes" +description: "Kubernetes Integration" +lead: "" +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +weight: 500 +--- diff --git a/docs/content/en/integration/kubernetes/introduction/index.md b/docs/content/en/integration/kubernetes/introduction/index.md new file mode 100644 index 000000000..9b70d4d63 --- /dev/null +++ b/docs/content/en/integration/kubernetes/introduction/index.md @@ -0,0 +1,71 @@ +--- +title: "Kubernetes" +description: "An introduction into integrating Authelia with Kubernetes." +lead: "An introduction into integrating Authelia with Kubernetes." +date: 2022-05-15T13:52:27+10:00 +draft: false +images: [] +menu: +  integration: +    parent: "kubernetes" +weight: 510 +toc: true +aliases: +  - /i/k8s +--- + +{{< figure src="kubernetes.png" alt="Kubernetes" width="100" style="padding-right: 10px" >}} + +## UNDER CONSTRUCTION + +The following areas are actively being worked on for Kubernetes: + +1. Detailed Documentation +2. [Helm Chart](https://github.com/authelia/chartrepo) for Helm v3 see our [chart repository](https://charts.authelia.com) +3. Kustomize Deployment +4. Manifest Examples + +Users are welcome to reach out directly by using any of our various [contact options](../../information/contact.md). + +## Important Notes + +The following section has special notes regarding utilizing Authelia with Kubernetes. + +### External Traffic Policy + +Authelia (and all of your other applications) may receive an invalid remote IP if the service handling traffic to the +Kubernetes Ingress of your choice doesn't have the `externalTrafficPolicy` setting configured to `local` as per the +Kubernetes [preserving the client source ip] documentation. + +### Enable Service Links + +Authelia's configuration management system conflicts with the `enableServiceLinks` option when it's set to `true` which +is the default. This should be changed to `false`. See the +[PodSpec v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#podspec-v1-core) documentation +for more details. + +#### Pod Example + +```yaml +--- +apiVersion: v1 +kind: Pod +metadata: +  name: authelia +spec: +  enableServiceLinks: false +... +``` + +## FAQ + +### RAM usage + +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 +node, alternatively you can +[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) +for more info. + +[preserving the client source ip]: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip diff --git a/docs/images/logos/kubernetes.png b/docs/content/en/integration/kubernetes/introduction/kubernetes.png Binary files differindex 5e2b1ab75..5e2b1ab75 100644 --- a/docs/images/logos/kubernetes.png +++ b/docs/content/en/integration/kubernetes/introduction/kubernetes.png diff --git a/docs/content/en/integration/kubernetes/nginx-ingress.md b/docs/content/en/integration/kubernetes/nginx-ingress.md new file mode 100644 index 000000000..b8b949351 --- /dev/null +++ b/docs/content/en/integration/kubernetes/nginx-ingress.md @@ -0,0 +1,41 @@ +--- +title: "NGINX Ingress" +description: "A guide to integrating Authelia with the NGINX Kubernetes Ingress." +lead: "A guide to integrating Authelia with the NGINX Kubernetes Ingress." +date: 2022-05-15T13:52:27+10:00 +draft: false +images: [] +menu: +  integration: +    parent: "kubernetes" +weight: 530 +toc: true +--- + +There are two nginx ingress controllers for Kubernetes. The Kubernetes official one [ingress-nginx], and the F5 nginx +official one [nginx-ingress-controller]. Currently we only have support docs for [ingress-nginx]. + +The [nginx documentation](../proxies/nginx.md) may also be useful for crafting advanced snippets to use with annotations +even though it's not specific to Kubernetes. + +## NGINX Ingress Controller (ingress-nginx) + +If you use NGINX Ingress Controller (ingress-nginx) you can protect an ingress with the following annotations. The +example assumes that the public domain Authelia is served on is `https://auth.example.com` and there is a +Kubernetes service with the name `authelia` in the `default` namespace with TCP port `80` configured to route to the +Authelia HTTP port and that your cluster is configured with the default +DNS domain name of `cluster.local`. + +### Ingress Annotations + +```yaml +annotations: +  nginx.ingress.kubernetes.io/auth-response-headers: Remote-User,Remote-Name,Remote-Groups,Remote-Email +  nginx.ingress.kubernetes.io/auth-signin: https://auth.example.com +  nginx.ingress.kubernetes.io/auth-snippet: | +    proxy_set_header X-Forwarded-Method $request_method; +  nginx.ingress.kubernetes.io/auth-url: http://authelia.default.svc.cluster.local/api/verify +``` + +[ingress-nginx]: https://kubernetes.github.io/ingress-nginx/ +[nginx-ingress-controller]: https://docs.nginx.com/nginx-ingress-controller/ diff --git a/docs/content/en/integration/kubernetes/traefik-ingress.md b/docs/content/en/integration/kubernetes/traefik-ingress.md new file mode 100644 index 000000000..25b3cda9c --- /dev/null +++ b/docs/content/en/integration/kubernetes/traefik-ingress.md @@ -0,0 +1,126 @@ +--- +title: "Traefik Ingress" +description: "A guide to integrating Authelia with the Traefik Kubernetes Ingress." +lead: "A guide to integrating Authelia with the Traefik Kubernetes Ingress." +date: 2022-05-15T13:52:27+10:00 +draft: false +images: [] +menu: +  integration: +    parent: "kubernetes" +weight: 520 +toc: true +--- + +We officially support the Traefik 2.x Kubernetes ingress controllers. These come in two flavors: + +* [Traefik Kubernetes Ingress](https://doc.traefik.io/traefik/providers/kubernetes-ingress/) +* [Traefik Kubernetes CRD](https://doc.traefik.io/traefik/providers/kubernetes-crd/) + +The [Traefik documentation](../proxies/traefik.md) may also be useful for crafting advanced annotations to use with +this ingress even though it's not specific to Kubernetes. + +## Special Notes + +### Cross-Namespace Resources + +Depending on your Traefik version you may be required to configure the +[allowCrossNamespace](https://doc.traefik.io/traefik/providers/kubernetes-crd/#allowcrossnamespace) to reuse a +[Middleware] from a namespace different to the Ingress or IngressRoute. Alternatively you can create the [Middleware] in +every namespace you need to use it. + +## Middleware + +Regardless if you're using the [Traefik Kubernetes Ingress] or purely the [Traefik Kubernetes CRD], you must configure +the [Traefik Kubernetes CRD] as far as we're aware at this time in order to configure a [ForwardAuth] [Middleware]. + +This is an example [Middleware] manifest. This eample assumes that you have deployed an Authelia pod and you have +configured it to be served on the URL `https://auth.example.com` and there is a Kubernetes Service with the name +`authelia` in the `default` namespace with TCP port `80` configured to route to the Authelia pod's HTTP port and that +your cluster is configured with the default DNS domain name of `cluster.local`. + +```yaml +apiVersion: traefik.containo.us/v1alpha1 +kind: Middleware +metadata: +  labels: +    app.kubernetes.io/instance: authelia +    app.kubernetes.io/name: authelia +    argocd.argoproj.io/instance: authelia +  name: forwardauth-authelia +  namespace: default +spec: +  forwardAuth: +    address: http://authelia.default.svc.cluster.local/api/verify?rd=https%3A%2F%2Fauth.example.com%2F +    authResponseHeaders: +      - Remote-User +      - Remote-Name +      - Remote-Email +      - Remote-Groups +``` + +## Ingress + +This is an example Ingress manifest which uses the above [Middleware](#middleware). This example assumes you have an +application you wish to serve on `https://app.example.com` and there is a Kubernetes Service with the name `app` in the +`default` namespace with TCP port `80` configured to route to the application pod's HTTP port. + +```yaml +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: +  name: app +  namespace: default +  annotations: +    traefik.ingress.kubernetes.io/router.entrypoints: websecure +    traefik.ingress.kubernetes.io/router.middlewares: default-forwardauth-authelia@kubernetescrd +    traefik.ingress.kubernetes.io/router.tls: "true" +spec: +  rules: +    - host: app.example.com +      http: +        paths: +          - path: /bar +            pathType: Prefix +            backend: +              service: +                name:  app +                port: +                  number: 80 +``` + +## IngressRoute + +This is an example IngressRoute manifest which uses the above [Middleware](#middleware). This example assumes you have an +application you wish to serve on `https://app.example.com` and there is a Kubernetes Service with the name `app` in the +`default` namespace with TCP port `80` configured to route to the application pod's HTTP port. + +```yaml +apiVersion: traefik.containo.us/v1alpha1 +kind: IngressRoute +metadata: +  name: app +  namespace: default +spec: +  entryPoints: +    - websecure +  routes: +    - kind: Rule +      match: Host(`app.example.com`) +      middlewares: +        - name: forwardauth-authelia +          namespace: default +      services: +        - kind: Service +          name: app +          namespace: default +          port: 80 +          scheme: http +          strategy: RoundRobin +          weight: 10 +``` + +[Traefik Kubernetes Ingress]: https://doc.traefik.io/traefik/providers/kubernetes-ingress/ +[Traefik Kubernetes CRD]: https://doc.traefik.io/traefik/providers/kubernetes-crd/ +[Middleware]: https://doc.traefik.io/traefik/middlewares/overview/ +[ForwardAuth]: https://doc.traefik.io/traefik/middlewares/http/forwardauth/ diff --git a/docs/content/en/integration/ldap/_index.md b/docs/content/en/integration/ldap/_index.md new file mode 100644 index 000000000..bc5c95652 --- /dev/null +++ b/docs/content/en/integration/ldap/_index.md @@ -0,0 +1,9 @@ +--- +title : "LDAP" +description: "LDAP Integration" +lead: "" +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +weight: 700 +--- diff --git a/docs/content/en/integration/ldap/introduction.md b/docs/content/en/integration/ldap/introduction.md new file mode 100644 index 000000000..bba3c24b1 --- /dev/null +++ b/docs/content/en/integration/ldap/introduction.md @@ -0,0 +1,17 @@ +--- +title: "LDAP" +description: "An introduction into integrating Authelia with LDAP." +lead: "An introduction into integrating Authelia with LDAP." +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  integration: +    parent: "ldap" +weight: 710 +toc: true +--- + +## UNDER CONSTRUCTION + +This section of the documentation is under construction. diff --git a/docs/content/en/integration/openid-connect/_index.md b/docs/content/en/integration/openid-connect/_index.md new file mode 100644 index 000000000..517531b91 --- /dev/null +++ b/docs/content/en/integration/openid-connect/_index.md @@ -0,0 +1,9 @@ +--- +title: "OpenID Connect" +description: "OpenID Connect Integration" +lead: "" +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +weight: 600 +--- diff --git a/docs/content/en/integration/openid-connect/bookstack/index.md b/docs/content/en/integration/openid-connect/bookstack/index.md new file mode 100644 index 000000000..3f10367fe --- /dev/null +++ b/docs/content/en/integration/openid-connect/bookstack/index.md @@ -0,0 +1,78 @@ +--- +title: "BookStack" +description: "Integrating BookStack with Authelia via OpenID Connect." +lead: "" +date: 2022-05-16T21:15:52+10:00 +draft: false +images: [] +menu: +  integration: +    parent: "openid-connect" +weight: 620 +toc: true +community: true +--- + +## Tested Versions + +* [Authelia] +  * [v4.35.5](https://github.com/authelia/authelia/releases/tag/v4.35.5) +* [BookStack] +  * 20.10 + +## Before You Begin + +You are required to utilize a unique client id and a unique and random client secret for all [OpenID Connect] relying +parties. You should not use the client secret in this example, you should randomly generate one yourself. You may also +choose to utilize a different client id, it's completely up to you. + +This example makes the following assumptions: + +* __Application Root URL:__ `https://bookstack.example.com` +* __Authelia Root URL:__ `https://auth.example.com` +* __Client ID:__ `bookstack` +* __Client Secret:__ `bookstack_client_secret` + +## Configuration + +### Application + +To configure [BookStack] to utilize Authelia as an [OpenID Connect] Provider: + +1. Edit your .env file +2. Set the following values: +   1. AUTH_METHOD: `oidc` +   2. OIDC_NAME: `Authelia` +   3. OIDC_DISPLAY_NAME_CLAIMS: `name` +   4. OIDC_CLIENT_ID: `bookstack` +   5. OIDC_CLIENT_SECRET: `bookstack_client_secret` +   6. OIDC_ISSUER: `https://auth.example.com` +   7. OIDC_ISSUER_DISCOVER: `true` + +### Authelia + +The following YAML configuration is an example __Authelia__ +[client configuration](../../../configuration/identity-providers/open-id-connect.md#clients) for use with [BookStack] +which will operate with the above example: + +```yaml +- id: bookstack +  secret: bookstack_client_secret +  public: false +  authorization_policy: two_factor +  scopes: +    - openid +    - profile +    - email +  redirect_uris: +    - https://bookstack.example.com/oidc/callback +  userinfo_signing_algorithm: none +``` + +## See Also + +* [BookStack OpenID Connect Documentation](https://www.bookstackapp.com/docs/admin/oidc-auth/) + +[Authelia]: https://www.authelia.com +[BookStack]: https://www.bookstackapp.com/ +[OpenID Connect]: ../../openid-connect/introduction.md diff --git a/docs/content/en/integration/openid-connect/cloudflare-zerotrust/index.md b/docs/content/en/integration/openid-connect/cloudflare-zerotrust/index.md new file mode 100644 index 000000000..135b6e025 --- /dev/null +++ b/docs/content/en/integration/openid-connect/cloudflare-zerotrust/index.md @@ -0,0 +1,83 @@ +--- +title: "Cloudflare Zero Trust" +description: "Integrating Cloudflare Zero Trust with Authelia via OpenID Connect." +lead: "" +date: 2022-05-17T07:45:58+10:00 +draft: false +images: [] +menu: +  integration: +    parent: "openid-connect" +weight: 620 +toc: true +community: true +--- + +## Tested Versions + +* [Authelia] +  * [v4.35.6](https://github.com/authelia/authelia/releases/tag/v4.35.6) + +## Before You Begin + +You are required to utilize a unique client id and a unique and random client secret for all [OpenID Connect] relying +parties. You should not use the client secret in this example, you should randomly generate one yourself. You may also +choose to utilize a different client id, it's completely up to you. + +This example makes the following assumptions: + +* __Cloudflare Team Name:__ `example-team` +* __Authelia Root URL:__ `https://auth.example.com` +* __Client ID:__ `cloudflare` +* __Client Secret:__ `cloudflare_client_secret` + +## Configuration + +### Application + +To configure [Cloudflare Zero Trust] to utilize Authelia as an [OpenID Connect] Provider: + +1. Visit the [Cloudflare Zero Trust Dashboard](https://dash.teams.cloudflare.com) +2. Visit `Settings` +3. Visit `Authentication` +4. Under `Login nethods` select `Add new` +5. Select `OpenID Connect` +6. Enter the following values: +   1. Name: `Authelia` +   2. App ID: `cloudflare` +   3. Client Secret: `cloudflare_client_secret` +   4. Auth URL: `https://auth.example.com/api/oidc/authorization` +   5. Token URL: `https://auth.example.com/api/oidc/token` +   6. Certificate URL: `https://auth.example.com/jwks.json` +   7. Add the following OIDC Claims: `preferred_username`, `mail`, `groups` +7. Click Save + +### Authelia + +The following YAML configuration is an example __Authelia__ +[client configuration](../../../configuration/identity-providers/open-id-connect.md#clients) for use with [Cloudflare] +which will operate with the above example: + +```yaml +- id: cloudflare +  secret: cloudflare_client_secret +  public: false +  authorization_policy: two_factor +  scopes: +    - openid +    - profile +    - groups +    - email +  redirect_uris: +    - https://example-team.cloudflareaccess.com/cdn-cgi/access/callback +  userinfo_signing_algorithm: none +``` + +## See Also + +* [Cloudflare Zero Trust Generic OIDC Documentation](https://developers.cloudflare.com/cloudflare-one/identity/idp-integration/generic-oidc/) + +[Authelia]: https://www.authelia.com +[Cloudflare]: https://www.cloudflare.com/ +[Cloudflare Zero Trust]: https://www.cloudflare.com/products/zero-trust/ +[OpenID Connect]: ../../openid-connect/introduction.md diff --git a/docs/content/en/integration/openid-connect/gitlab/index.md b/docs/content/en/integration/openid-connect/gitlab/index.md new file mode 100644 index 000000000..26873bda6 --- /dev/null +++ b/docs/content/en/integration/openid-connect/gitlab/index.md @@ -0,0 +1,96 @@ +--- +title: "GitLab" +description: "Integrating GitLab with Authelia via OpenID Connect." +lead: "" +date: 2022-05-16T21:15:52+10:00 +draft: false +images: [] +menu: +  integration: +    parent: "openid-connect" +weight: 620 +toc: true +community: true +--- + +## Tested Versions + +* [Authelia] +  * [v4.35.5](https://github.com/authelia/authelia/releases/tag/v4.35.5) +* [GitLab] CE +  * 14.0.1 + +## Before You Begin + +You are required to utilize a unique client id and a unique and random client secret for all [OpenID Connect] relying +parties. You should not use the client secret in this example, you should randomly generate one yourself. You may also +choose to utilize a different client id, it's completely up to you. + +This example makes the following assumptions: + +* __Application Root URL:__ `https://gitlab.example.com` +* __Authelia Root URL:__ `https://auth.example.com` +* __Client ID:__ `gitlab` +* __Client Secret:__ `gitlab_client_secret` + +## Configuration + +### Application + +To configure [GitLab] to utilize Authelia as an [OpenID Connect] Provider: + +1. Add the Omnibus [OpenID Connect] OmniAuth configuration to `gitlab.rb`: + +```ruby +gitlab_rails['omniauth_providers'] = [ +  { +    name: "openid_connect", +    label: "Authelia", +    icon: "https://avatars.githubusercontent.com/u/59122411?s=280&v=4", +    args: { +      name: "openid_connect", +      scope: ["openid","profile","email","groups"], +      response_type: "code", +      issuer: "https://auth.example.com", +      discovery: true, +      client_auth_method: "query", +      uid_field: "preferred_username", +      send_scope_to_token_endpoint: "false", +      client_options: { +        identifier: "gitlab", +        secret: "gitlab_client_secret", +        redirect_uri: "https://gitlab.example.com/users/auth/openid_connect/callback" +      } +    } +  } +] +``` + +### Authelia + +The following YAML configuration is an example __Authelia__ +[client configuration](../../../configuration/identity-providers/open-id-connect.md#clients) for use with [GitLab] +which will operate with the above example: + +```yaml +- id: gitlab +  secret: gitlab_client_secret +  public: false +  authorization_policy: two_factor +  scopes: +    - openid +    - profile +    - groups +    - email +  redirect_uris: +    - https://gitlab.example.com/users/auth/openid_connect/callback +  userinfo_signing_algorithm: none +``` + +## See Also + +* [GitLab OpenID Connect OmniAuth Documentation](https://docs.gitlab.com/ee/administration/auth/oidc.html) + +[Authelia]: https://www.authelia.com +[GitLab]: https://about.gitlab.com/ +[OpenID Connect]: ../../openid-connect/introduction.md diff --git a/docs/content/en/integration/openid-connect/grafana/index.md b/docs/content/en/integration/openid-connect/grafana/index.md new file mode 100644 index 000000000..350738cae --- /dev/null +++ b/docs/content/en/integration/openid-connect/grafana/index.md @@ -0,0 +1,89 @@ +--- +title: "Grafana" +description: "Integrating Grafana with Authelia via OpenID Connect." +lead: "" +date: 2022-05-16T21:15:52+10:00 +draft: false +images: [] +menu: +  integration: +    parent: "openid-connect" +weight: 620 +toc: true +community: true +--- + +## Tested Versions + +* [Authelia] +  * [v4.35.5](https://github.com/authelia/authelia/releases/tag/v4.35.5) +* [Grafana] +  * 8.0.0 + +## Before You Begin + +You are required to utilize a unique client id and a unique and random client secret for all [OpenID Connect] relying +parties. You should not use the client secret in this example, you should randomly generate one yourself. You may also +choose to utilize a different client id, it's completely up to you. + +This example makes the following assumptions: + +* __Application Root URL:__ `https://grafana.example.com` +* __Authelia Root URL:__ `https://auth.example.com` +* __Client ID:__ `grafana` +* __Client Secret:__ `grafana_client_secret` + +## Configuration + +### Application + +To configure [Grafana] to utilize Authelia as an [OpenID Connect] Provider: + +1. Add the following Generic OAuth configuration to the [Grafana] configuration: + +```ruby +[auth.generic_oauth] +enabled = true +name = Authelia +icon = signin +client_id = grafana +client_secret = grafana_client_secret +scopes = openid profile email groups +empty_scopes = false +auth_url = https://auth.example.com/api/oidc/authorization +token_url = https://auth.example.com/api/oidc/token +api_url = https://auth.example.com/api/oidc/userinfo +login_attribute_path = preferred_username +groups_attribute_path = groups +name_attribute_path = name +use_pkce = true +``` + +### Authelia + +The following YAML configuration is an example __Authelia__ +[client configuration](../../../configuration/identity-providers/open-id-connect.md#clients) for use with [Grafana] +which will operate with the above example: + +```yaml +- id: grafana +  secret: grafana_client_secret +  public: false +  authorization_policy: two_factor +  scopes: +    - openid +    - profile +    - groups +    - email +  redirect_uris: +    - https://grafana.example.com/login/generic_oauth +  userinfo_signing_algorithm: none +``` + +## See Also + +* [Grafana OAuth Documentation](https://grafana.com/docs/grafana/latest/auth/generic-oauth/) + +[Authelia]: https://www.authelia.com +[Grafana]: https://grafana.com/ +[OpenID Connect]: ../../openid-connect/introduction.md diff --git a/docs/content/en/integration/openid-connect/harbor/index.md b/docs/content/en/integration/openid-connect/harbor/index.md new file mode 100644 index 000000000..331ddfca9 --- /dev/null +++ b/docs/content/en/integration/openid-connect/harbor/index.md @@ -0,0 +1,88 @@ +--- +title: "Harbor" +description: "Integrating Harbor with Authelia via OpenID Connect." +lead: "" +date: 2022-05-16T21:44:13+10:00 +draft: false +images: [] +menu: +  integration: +    parent: "openid-connect" +weight: 620 +toc: true +community: true +--- + +## Tested Versions + +* [Authelia] +  * [v4.35.5](https://github.com/authelia/authelia/releases/tag/v4.35.5) +* [Harbor] +  * 2.5.0 + +## Before You Begin + +You are required to utilize a unique client id and a unique and random client secret for all [OpenID Connect] relying +parties. You should not use the client secret in this example, you should randomly generate one yourself. You may also +choose to utilize a different client id, it's completely up to you. + +This example makes the following assumptions: + +* __Application Root URL:__ `https://harbor.example.com` +* __Authelia Root URL:__ `https://auth.example.com` +* __Client ID:__ `harbor` +* __Client Secret:__ `harbor_client_secret` + +## Configuration + +### Application + +To configure [Harbor] to utilize Authelia as an [OpenID Connect] Provider: + +1. Visit Administration +2. Visit Configuration +3. Visit Authentication +4. Select `OIDC` from the `Auth Mode` drop down +5. Enter the following information: +   1. OIDC Provider Name: `Authelia` +   2. OIDC Provider Endpoint: `https://auth.example.com` +   3. OIDC Client ID: `harbor` +   4. OIDC Client Secret: `harbor_client_secret` +   5. Group Claim Name: `groups` +   6. OIDC Scope: `openid,profile,email,groups` +   7. For OIDC Admin Group you can specify a group name that matches your authentication backend. +   8. Ensure `Verify Certificate` is checked. +   9. Ensure `Automatic onboarding` is checked if you want users to be created by default. +   10. Username Claim: `preferred_username` +6. Click `Test OIDC Server` +7. Click `Save` + +### Authelia + +The following YAML configuration is an example __Authelia__ +[client configuration](../../../configuration/identity-providers/open-id-connect.md#clients) for use with [Harbor] +which will operate with the above example: + +```yaml +- id: harbor +  secret: harbor_client_secret +  public: false +  authorization_policy: two_factor +  scopes: +    - openid +    - profile +    - groups +    - email +  redirect_uris: +    - https://vault.example.com/oidc/callback +    - https://vault.example.com/ui/vault/auth/oidc/oidc/callback +  userinfo_signing_algorithm: none +``` + +## See Also + +* [Harbor OpenID Connect Provider Documentation](https://goharbor.io/docs/2.5.0/administration/configure-authentication/oidc-auth/) + +[Authelia]: https://www.authelia.com +[Harbor]: https://goharbor.io/ +[OpenID Connect]: ../../openid-connect/introduction.md diff --git a/docs/content/en/integration/openid-connect/hashicorp-vault/index.md b/docs/content/en/integration/openid-connect/hashicorp-vault/index.md new file mode 100644 index 000000000..4a0db13ca --- /dev/null +++ b/docs/content/en/integration/openid-connect/hashicorp-vault/index.md @@ -0,0 +1,72 @@ +--- +title: "HashiCorp Vault" +description: "Integrating HashiCorp Vault with Authelia via OpenID Connect." +lead: "" +date: 2022-05-16T21:15:52+10:00 +draft: false +images: [] +menu: +  integration: +    parent: "openid-connect" +weight: 620 +toc: true +community: true +--- + +## Tested Versions + +* [Authelia] +  * [v4.35.5](https://github.com/authelia/authelia/releases/tag/v4.35.5) +* [HashiCorp Vault] +  * 1.8.1 + +## Before You Begin + +You are required to utilize a unique client id and a unique and random client secret for all [OpenID Connect] relying +parties. You should not use the client secret in this example, you should randomly generate one yourself. You may also +choose to utilize a different client id, it's completely up to you. + +This example makes the following assumptions: + +* __Application Root URL:__ `https://vault.example.com` +* __Authelia Root URL:__ `https://auth.example.com` +* __Client ID:__ `vault` +* __Client Secret:__ `vault_client_secret` + +## Configuration + +### Application + +To configure [HashiCorp Vault] to utilize Authelia as an [OpenID Connect] Provider please see the links in the +[see also](#see-also) section. + +### Authelia + +The following YAML configuration is an example __Authelia__ +[client configuration](../../../configuration/identity-providers/open-id-connect.md#clients) for use with [HashiCorp Vault] +which will operate with the above example: + +```yaml +- id: vault +  secret: vault_client_secret +  public: false +  authorization_policy: two_factor +  scopes: +    - openid +    - profile +    - groups +    - email +  redirect_uris: +    - https://vault.example.com/oidc/callback +    - https://vault.example.com/ui/vault/auth/oidc/oidc/callback +  userinfo_signing_algorithm: none +``` + +## See Also + +* [HashiCorp Vault JWT/OIDC Auth Documentation](https://www.vaultproject.io/docs/auth/jwt) +* [HashiCorp Vault OpenID Connect Providers Documentation](https://www.vaultproject.io/docs/auth/jwt/oidc_providers) + +[Authelia]: https://www.authelia.com +[HashiCorp Vault]: https://www.vaultproject.io/ +[OpenID Connect]: ../../openid-connect/introduction.md diff --git a/docs/content/en/integration/openid-connect/introduction.md b/docs/content/en/integration/openid-connect/introduction.md new file mode 100644 index 000000000..00cfa62af --- /dev/null +++ b/docs/content/en/integration/openid-connect/introduction.md @@ -0,0 +1,152 @@ +--- +title: "OpenID Connect" +description: "An introduction into integrating Authelia with an OpenID Connect relying party." +lead: "An introduction into integrating Authelia with an OpenID Connect relying party." +date: 2022-05-15T13:52:27+10:00 +draft: false +images: [] +menu: +  integration: +    parent: "openid-connect" +weight: 610 +toc: true +aliases: +  - /docs/community/oidc-integrations.html +--- + +Authelia supports [OpenID Connect] as part of an open beta. This section details implementation specifics that can be +used for integrating Authelia with relying parties, as well as specific documentation for some relying parties. + +See the [configuration documentation](../../configuration/identity-providers/open-id-connect.md) for information on how +to configure [OpenID Connect]. + +## Scope Definitions + +### openid + +This is the default scope for openid. This field is forced on every client by the configuration validation that Authelia +does. + +*__Important Note:__ The subject identifiers or `sub` claim has been changed to a [RFC4122] UUID V4 to identify the +individual user as per the [Subject Identifier Types] specification. Please use the claim `preferred_username` instead.* + +|   Claim   |   JWT Type    | Authelia Attribute |                         Description                         | +|:---------:|:-------------:|:------------------:|:-----------------------------------------------------------:| +|    iss    |    string     |      hostname      |             The issuer name, determined by URL              | +|    jti    | string(uuid)  |       *N/A*        |     A [RFC4122] UUID V4 representing the JWT Identifier     | +|    rat    |    number     |       *N/A*        |            The time when the token was requested            | +|    exp    |    number     |       *N/A*        |                           Expires                           | +|    iat    |    number     |       *N/A*        |             The time when the token was issued              | +| auth_time |    number     |       *N/A*        |        The time the user authenticated with Authelia        | +|    sub    | string(uuid)  |     opaque id      |    A [RFC4122] UUID V4 linked to the user who logged in     | +|   scope   |    string     |       scopes       |              Granted scopes (space delimited)               | +|    scp    | array[string] |       scopes       |                       Granted scopes                        | +|    aud    | array[string] |       *N/A*        |                          Audience                           | +|    amr    | array[string] |       *N/A*        | An [RFC8176] list of authentication method reference values | +|    azp    |    string     |    id (client)     |                    The authorized party                     | +| client_id |    string     |    id (client)     |                        The client id                        | + +### groups + +This scope includes the groups the authentication backend reports the user is a member of in the token. + +| Claim  |   JWT Type    | Authelia Attribute |                                               Description                                               | +|:------:|:-------------:|:------------------:|:-------------------------------------------------------------------------------------------------------:| +| groups | array[string] |       groups       | List of user's groups discovered via [authentication](../../configuration/first-factor/introduction.md) | + +### email + +This scope includes the email information the authentication backend reports about the user in the token. + +|     Claim      |   JWT Type    | Authelia Attribute |                        Description                        | +|:--------------:|:-------------:|:------------------:|:---------------------------------------------------------:| +|     email      |    string     |      email[0]      |       The first email address in the list of emails       | +| email_verified |     bool      |       *N/A*        | If the email is verified, assumed true for the time being | +|   alt_emails   | array[string] |     email[1:]      |  All email addresses that are not in the email JWT field  | + +### profile + +This scope includes the profile information the authentication backend reports about the user in the token. + +|       Claim        | JWT Type | Authelia Attribute |               Description                | +|:------------------:|:--------:|:------------------:|:----------------------------------------:| +| preferred_username |  string  |      username      | The username the user used to login with | +|        name        |  string  |    display_name    |          The users display name          | + +## Authentication Method References + +Authelia currently supports adding the `amr` claim to the [ID Token] utilizing the [RFC8176] Authentication Method +Reference values. + +The values this claim has are not strictly defined by the [OpenID Connect] specification. As such, some backends may +expect a specification other than [RFC8176] for this purpose. If you have such an application and wish for us to support +it then you're encouraged to create an issue. + +Below is a list of the potential values we place in the claim and their meaning: + +| Value |                           Description                            | Factor | Channel  | +|:-----:|:----------------------------------------------------------------:|:------:|:--------:| +|  mfa  |     User used multiple factors to login (see factor column)      |  N/A   |   N/A    | +|  mca  |    User used multiple channels to login (see channel column)     |  N/A   |   N/A    | +| user  |  User confirmed they were present when using their hardware key  |  N/A   |   N/A    | +|  pin  | User confirmed they are the owner of the hardware key with a pin |  N/A   |   N/A    | +|  pwd  |            User used a username and password to login            |  Know  | Browser  | +|  otp  |                     User used TOTP to login                      |  Have  | Browser  | +|  hwk  |                User used a hardware key to login                 |  Have  | Browser  | +|  sms  |                      User used Duo to login                      |  Have  | External | + +## Endpoint Implementations + +The following section documents the endpoints we implement and their respective paths. This information can +traditionally be discovered by relying parties that utilize [OpenID Connect Discovery], however this information may be +useful for clients which do not implement this. + +The endpoints can be discovered easily by visiting the Discovery and Metadata endpoints. It is recommended regardless +of your version of Authelia that you utilize this version as it will always produce the correct endpoint URLs. The paths +for the Discovery/Metadata endpoints are part of IANA's well known registration but are also documented in a table +below. + +These tables document the endpoints we currently support and their paths in the most recent version of Authelia. The +paths are appended to the end of the primary URL used to access Authelia. The tables use the url +https://auth.example.com as an example of the Authelia root URL which is also the OpenID Connect issuer. + +### Well Known Discovery Endpoints + +These endpoints can be utilized to discover other endpoints and metadata about the Authelia OP. + +|                 Endpoint                  |                              Path                               | +|:-----------------------------------------:|:---------------------------------------------------------------:| +|        [OpenID Connect Discovery]         |    https://auth.example.com/.well-known/openid-configuration    | +| [OAuth 2.0 Authorization Server Metadata] | https://auth.example.com/.well-known/oauth-authorization-server | + +### Discoverable Endpoints + +These endpoints implement OpenID Connect elements. + +|      Endpoint       |                      Path                       |  Discovery Attribute   | +|:-------------------:|:-----------------------------------------------:|:----------------------:| +| [JSON Web Key Sets] |       https://auth.example.com/jwks.json        |        jwks_uri        | +|   [Authorization]   | https://auth.example.com/api/oidc/authorization | authorization_endpoint | +|       [Token]       |     https://auth.example.com/api/oidc/token     |     token_endpoint     | +|     [Userinfo]      |   https://auth.example.com/api/oidc/userinfo    |   userinfo_endpoint    | +|   [Introspection]   | https://auth.example.com/api/oidc/introspection | introspection_endpoint | +|    [Revocation]     |  https://auth.example.com/api/oidc/revocation   |  revocation_endpoint   | + +[ID Token]: https://openid.net/specs/openid-connect-core-1_0.html#IDToken + +[OpenID Connect]: https://openid.net/connect/ + +[OpenID Connect Discovery]: https://openid.net/specs/openid-connect-discovery-1_0.html +[OAuth 2.0 Authorization Server Metadata]: https://www.rfc-editor.org/rfc/rfc8414.html + +[JSON Web Key Sets]: https://www.rfc-editor.org/rfc/rfc7517.html#section-5 + +[Authorization]: https://openid.net/specs/openid-connect-core-1_0.html#AuthorizationEndpoint +[Token]: https://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint +[Userinfo]: https://openid.net/specs/openid-connect-core-1_0.html#UserInfo +[Introspection]: https://www.rfc-editor.org/rfc/rfc7662.html +[Revocation]: https://www.rfc-editor.org/rfc/rfc7009.html + +[RFC8176]: https://www.rfc-editor.org/rfc/rfc8176.html +[RFC4122]: https://www.rfc-editor.org/rfc/rfc4122.html +[Subject Identifier Types]: https://openid.net/specs/openid-connect-core-1_0.html#SubjectIDTypes diff --git a/docs/content/en/integration/openid-connect/nextcloud/index.md b/docs/content/en/integration/openid-connect/nextcloud/index.md new file mode 100644 index 000000000..435f15c3d --- /dev/null +++ b/docs/content/en/integration/openid-connect/nextcloud/index.md @@ -0,0 +1,109 @@ +--- +title: "Nextcloud" +description: "Integrating Nextcloud with Authelia via OpenID Connect." +lead: "" +date: 2022-05-16T21:57:40+10:00 +draft: false +images: [] +menu: +  integration: +    parent: "openid-connect" +weight: 620 +toc: true +community: true +--- + +## Tested Versions + +* [Authelia] +  * [v4.35.5](https://github.com/authelia/authelia/releases/tag/v4.35.5) +* [Nextcloud] +  * 22.1.0 + +## Before You Begin + +You are required to utilize a unique client id and a unique and random client secret for all [OpenID Connect] relying +parties. You should not use the client secret in this example, you should randomly generate one yourself. You may also +choose to utilize a different client id, it's completely up to you. + +This example makes the following assumptions: + +* __Application Root URL:__ `https://nextcloud.example.com` +* __Authelia Root URL:__ `https://auth.example.com` +* __Client ID:__ `nextcloud` +* __Client Secret:__ `nextcloud_client_secret` + +## Configuration + +### Application + +To configure [Nextcloud] to utilize Authelia as an [OpenID Connect] Provider: + +1. Install the [Nextcloud OpenID Connect Login app] +2. Add the following to the [Nextcloud] `config.php` configuration: + +```php +$CONFIG = array ( +    'allow_user_to_change_display_name' => false, +    'lost_password_link' => 'disabled', +    'oidc_login_provider_url' => 'https://auth.example.com', +    'oidc_login_client_id' => 'nextcloud', +    'oidc_login_client_secret' => 'nextcloud_client_secret', +    'oidc_login_auto_redirect' => false, +    'oidc_login_end_session_redirect' => false, +    'oidc_login_button_text' => 'Log in with Authelia', +    'oidc_login_hide_password_form' => false, +    'oidc_login_use_id_token' => true, +    'oidc_login_attributes' => array ( +        'id' => 'preferred_username', +        'name' => 'name', +        'mail' => 'email', +        'groups' => 'groups', +    ), +    'oidc_login_default_group' => 'oidc', +    'oidc_login_use_external_storage' => false, +    'oidc_login_scope' => 'openid profile groups', +    'oidc_login_proxy_ldap' => false, +    'oidc_login_disable_registration' => true, +    'oidc_login_redir_fallback' => false, +    'oidc_login_alt_login_page' => 'assets/login.php', +    'oidc_login_tls_verify' => true, +    'oidc_create_groups' => false, +    'oidc_login_webdav_enabled' => false, +    'oidc_login_password_authentication' => false, +    'oidc_login_public_key_caching_time' => 86400, +    'oidc_login_min_time_between_jwks_requests' => 10, +    'oidc_login_well_known_caching_time' => 86400, +    'oidc_login_update_avatar' => false, +); +``` + +### Authelia + +The following YAML configuration is an example __Authelia__ +[client configuration](../../../configuration/identity-providers/open-id-connect.md#clients) for use with [Nextcloud] +which will operate with the above example: + +```yaml +- id: nextcloud +  secret: nextcloud_client_secret +  public: false +  authorization_policy: two_factor +  scopes: +    - openid +    - profile +    - groups +  redirect_uris: +    - https://nextcloud.example.com/apps/oidc_login/oidc +  userinfo_signing_algorithm: none +``` + +## See Also + +* [Nextcloud OpenID Connect Login app] +* [Nextcloud OpenID Connect Login Documentation](https://github.com/pulsejet/nextcloud-oidc-login) + +[Authelia]: https://www.authelia.com +[Nextcloud]: https://nextcloud.com/ +[Nextcloud OpenID Connect Login app]: https://apps.nextcloud.com/apps/oidc_login +[OpenID Connect]: ../../openid-connect/introduction.md diff --git a/docs/content/en/integration/openid-connect/portainer/index.md b/docs/content/en/integration/openid-connect/portainer/index.md new file mode 100644 index 000000000..13fb579e3 --- /dev/null +++ b/docs/content/en/integration/openid-connect/portainer/index.md @@ -0,0 +1,89 @@ +--- +title: "Portainer" +description: "Integrating Portainer with Authelia via OpenID Connect." +lead: "" +date: 2022-05-15T13:52:27+10:00 +draft: false +images: [] +menu: +  integration: +    parent: "openid-connect" +weight: 620 +toc: true +community: true +aliases: +  - /docs/community/oidc-integrations/portainer.html +--- + +## Tested Versions + +* [Authelia] +  * [v4.35.5](https://github.com/authelia/authelia/releases/tag/v4.35.5) +* [Portainer] CE and EE +  * 2.12.2 + +## Before You Begin + +You are required to utilize a unique client id and a unique and random client secret for all [OpenID Connect] relying +parties. You should not use the client secret in this example, you should randomly generate one yourself. You may also +choose to utilize a different client id, it's completely up to you. + +This example makes the following assumptions: + +* __Application Root URL:__ `https://portainer.example.com` +* __Authelia Root URL:__ `https://auth.example.com` +* __Client ID:__ `portainer` +* __Client Secret:__ `portainer_client_secret` + +## Configuration + +### Application + +To configure [Portainer] to utilize Authelia as an [OpenID Connect] Provider: + +1. Visit Settings +2. Visit Authentication +3. Select: +   1. Authentication Method: OAuth +   2. Provider: Custom +   3. Enable *Automatic User Provision* if you want users to automatically be created in [Portainer]. +4. Configure the following: +   1. Client ID: `portainer` +   2. Client Secret: `portainer_client_secret` +   3. Authorization URL: `https://auth.example.com/api/oidc/authorization` +   4. Access Token URL: `https://auth.example.com/api/oidc/token` +   5. Resource URL: `https://auth.example.com/api/oidc/userinfo` +   6. Redirect URL: `https://portainer.example.com` +   7. User Identifier: `preferred_username` +   8. Scopes: `openid profile groups email` + +{{< figure src="portainer.png" alt="Portainer" width="736" style="padding-right: 10px" >}} + +### Authelia + +The following YAML configuration is an example __Authelia__ +[client configuration](../../../configuration/identity-providers/open-id-connect.md#clients) for use with [Portainer] +which will operate with the above example: + +```yaml +- id: portainer +  secret: portainer_client_secret +  public: false +  authorization_policy: two_factor +  scopes: +    - openid +    - profile +    - groups +    - email +  redirect_uris: +    - https://portainer.example.com +  userinfo_signing_algorithm: none +``` + +## See Also + +* [Portainer OAuth Documentation](https://docs.portainer.io/admin/settings/authentication/oauth) + +[Authelia]: https://www.authelia.com +[Portainer]: https://www.portainer.io/ +[OpenID Connect]: ../../openid-connect/introduction.md diff --git a/docs/images/portainer.gif b/docs/content/en/integration/openid-connect/portainer/portainer.gif Binary files differindex 093a3d54f..093a3d54f 100644 --- a/docs/images/portainer.gif +++ b/docs/content/en/integration/openid-connect/portainer/portainer.gif diff --git a/docs/content/en/integration/openid-connect/portainer/portainer.png b/docs/content/en/integration/openid-connect/portainer/portainer.png Binary files differnew file mode 100644 index 000000000..6a643350b --- /dev/null +++ b/docs/content/en/integration/openid-connect/portainer/portainer.png diff --git a/docs/content/en/integration/openid-connect/proxmox/index.md b/docs/content/en/integration/openid-connect/proxmox/index.md new file mode 100644 index 000000000..7e0918afc --- /dev/null +++ b/docs/content/en/integration/openid-connect/proxmox/index.md @@ -0,0 +1,85 @@ +--- +title: "Proxmox" +description: "Integrating Proxmox with Authelia via OpenID Connect." +lead: "" +date: 2022-05-15T13:52:27+10:00 +draft: false +images: [] +menu: +  integration: +    parent: "openid-connect" +weight: 620 +toc: true +community: true +aliases: +  - /docs/community/oidc-integrations/proxmox.html +--- + +## Tested Versions + +* [Authelia] +  * [v4.35.6](https://github.com/authelia/authelia/releases/tag/v4.35.6) +* [Proxmox] +  * 7.1-10 + +## Before You Begin + +You are required to utilize a unique client id and a unique and random client secret for all [OpenID Connect] relying +parties. You should not use the client secret in this example, you should randomly generate one yourself. You may also +choose to utilize a different client id, it's completely up to you. + +This example makes the following assumptions: + +* __Application Root URL:__ `https://proxmox.example.com` +* __Authelia Root URL:__ `https://auth.example.com` +* __Client ID:__ `proxmox` +* __Client Secret:__ `proxmox_client_secret` + +## Configuration + +### Application + +To configure [Proxmox] to utilize Authelia as an [OpenID Connect] Provider: + +1. Visit Datacenter +2. Visit Permission +3. Visit Realms +4. Add an OpenID Connect Server +5. Configure the following: +   1. Issuer URL: `https://auth.example.com` +   2. Realm: anything you wish +   3. Client ID: `proxmox` +   4. Client Key: `proxmox_client_secret` +   5. Username Claim `preferred_username` +   6. Scopes: `openid profile email` +   7. Enable *Autocreate Users* if you want users to automatically be created in [Proxmox]. + +{{< figure src="proxmox.gif" alt="Proxmox" width="736" style="padding-right: 10px" >}} + +### Authelia + +The following YAML configuration is an example __Authelia__ +[client configuration](../../../configuration/identity-providers/open-id-connect.md#clients) for use with [Proxmox] +which will operate with the above example: + +```yaml +- id: proxmox +  secret: proxmox_client_secret +  public: false +  authorization_policy: two_factor +  scopes: +    - openid +    - profile +    - email +  redirect_uris: +    - https://proxmox.example.com +  userinfo_signing_algorithm: none +``` + +## See Also + +* [Proxmox User Management Documentation](https://pve.proxmox.com/wiki/User_Management) + +[Authelia]: https://www.authelia.com +[Proxmox]: https://www.proxmox.com/ +[OpenID Connect]: ../../openid-connect/introduction.md diff --git a/docs/images/proxmox.gif b/docs/content/en/integration/openid-connect/proxmox/proxmox.gif Binary files differindex d6f82a2db..d6f82a2db 100644 --- a/docs/images/proxmox.gif +++ b/docs/content/en/integration/openid-connect/proxmox/proxmox.gif diff --git a/docs/content/en/integration/openid-connect/seafile/index.md b/docs/content/en/integration/openid-connect/seafile/index.md new file mode 100644 index 000000000..9b7520e28 --- /dev/null +++ b/docs/content/en/integration/openid-connect/seafile/index.md @@ -0,0 +1,93 @@ +--- +title: "Seafile" +description: "Integrating Seafile with Authelia via OpenID Connect." +lead: "" +date: 2022-05-17T09:17:01+10:00 +draft: false +images: [] +menu: +  integration: +    parent: "openid-connect" +weight: 620 +toc: true +community: true +--- + +## Tested Versions + +* [Authelia] +  * [v4.35.5](https://github.com/authelia/authelia/releases/tag/v4.35.5) +* [Seafile] Server +  * 9.0.4 + +## Before You Begin + +You are required to utilize a unique client id and a unique and random client secret for all [OpenID Connect] relying +parties. You should not use the client secret in this example, you should randomly generate one yourself. You may also +choose to utilize a different client id, it's completely up to you. + +This example makes the following assumptions: + +* __Application Root URL:__ `https://seafile.example.com` +* __Authelia Root URL:__ `https://auth.example.com` +* __Client ID:__ `seafile` +* __Client Secret:__ `seafile_client_secret` + +## Configuration + +### Application + +To configure [Seafile] to utilize Authelia as an [OpenID Connect] Provider: + +1. Edit your [Seafile] `seahub_settings.py` configuration file and add configure the following: + +```python +ENABLE_OAUTH = True +OAUTH_ENABLE_INSECURE_TRANSPORT = False +OAUTH_CLIENT_ID = "seafile" +OAUTH_CLIENT_SECRET = "seafile_client_secret" +OAUTH_REDIRECT_URL = 'https://seafile.example.com/oauth/callback/' +OAUTH_PROVIDER_DOMAIN = 'auth.example.com' +OAUTH_AUTHORIZATION_URL = 'https://auth.example.com/api/oidc/authorization' +OAUTH_TOKEN_URL = 'https://auth.example.com/api/oidc/token' +OAUTH_USER_INFO_URL = 'https://auth.example.com/api/oidc/userinfo' +OAUTH_SCOPE = [ +  "openid", +  "profile", +  "email", +  "groups", +] +OAUTH_ATTRIBUTE_MAP = { +    "id": (True, "preferred_username"), +    "name": (False, "name"), +    "email": (False, "email"), +} +``` + +### Authelia + +The following YAML configuration is an example __Authelia__ +[client configuration](../../../configuration/identity-providers/open-id-connect.md#clients) for use with [Seafile] +which will operate with the above example: + +```yaml +- id: seafile +  secret: seafile_client_secret +  public: false +  authorization_policy: two_factor +  scopes: +    - openid +    - profile +    - email +  redirect_uris: +    - https://seafile.example.com/oauth/callback/ +  userinfo_signing_algorithm: none +``` + +## See Also + +* [Seafile OAuth Authentication Documentation](https://manual.seafile.com/deploy/oauth/) + +[Authelia]: https://www.authelia.com +[Seafile]: https://www.seafile.com/ +[OpenID Connect]: ../../openid-connect/introduction.md diff --git a/docs/content/en/integration/openid-connect/synapse/index.md b/docs/content/en/integration/openid-connect/synapse/index.md new file mode 100644 index 000000000..9f01295e3 --- /dev/null +++ b/docs/content/en/integration/openid-connect/synapse/index.md @@ -0,0 +1,83 @@ +--- +title: "Synapse" +description: "Integrating Synapse with Authelia via OpenID Connect." +lead: "" +date: 2022-05-17T09:17:01+10:00 +draft: false +images: [] +menu: +  integration: +    parent: "openid-connect" +weight: 620 +toc: true +community: true +--- + +## Tested Versions + +* [Authelia] +  * [v4.35.6](https://github.com/authelia/authelia/releases/tag/v4.35.6) +* [Synapse] +  * [v1.60.0](https://github.com/matrix-org/synapse/releases/tag/v1.60.0) + +## Before You Begin + +You are required to utilize a unique client id and a unique and random client secret for all [OpenID Connect] relying +parties. You should not use the client secret in this example, you should randomly generate one yourself. You may also +choose to utilize a different client id, it's completely up to you. + +This example makes the following assumptions: + +* __Application Root URL:__ `https://matrix.example.com/` +* __Authelia Root URL:__ `https://auth.example.com` +* __Client ID:__ `synapse` +* __Client Secret:__ `synapse_client_secret` + +## Configuration + +### Application + +To configure [Synapse] to utilize Authelia as an [OpenID Connect] Provider: + +1. Edit your [Synapse] `homeserver.yaml` configuration file and add configure the following: + +```yaml +oidc_providers: +  - idp_id: synapse +    idp_name: "Authelia" +    issuer: "https://auth.example.com" +    client_id: "synapse" +    client_secret: "synapse_client_secret" +    allow_existing_users: true +    scopes: ["openid", "profile"] +    user_mapping_provider: +      config: +        localpart_template: "{{ openid.preferred_username }}" +``` + +### Authelia + +The following YAML configuration is an example __Authelia__ +[client configuration](../../../configuration/identity-providers/open-id-connect.md#clients) for use with [Synapse] +which will operate with the above example: + +```yaml +- id: synapse +  secret: synapse_client_secret +  public: false +  authorization_policy: two_factor +  scopes: +    - openid +    - profile +  redirect_uris: +    - https://synapse.example.com/_synapse/client/oidc/callback +  userinfo_signing_algorithm: none +``` + +## See Also + +* [Synapse OpenID Connect Authentication Documentation](https://matrix-org.github.io/synapse/latest/openid.html) + +[Authelia]: https://www.authelia.com +[Synapse]: https://github.com/matrix-org/synapse +[OpenID Connect]: ../../openid-connect/introduction.md diff --git a/docs/content/en/integration/prologue/_index.md b/docs/content/en/integration/prologue/_index.md new file mode 100644 index 000000000..3d3912df0 --- /dev/null +++ b/docs/content/en/integration/prologue/_index.md @@ -0,0 +1,9 @@ +--- +title: "Prologue" +description: "Integration Prologue" +lead: "" +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +weight: 100 +--- diff --git a/docs/content/en/integration/prologue/get-started.md b/docs/content/en/integration/prologue/get-started.md new file mode 100644 index 000000000..7130db908 --- /dev/null +++ b/docs/content/en/integration/prologue/get-started.md @@ -0,0 +1,81 @@ +--- +title: "Get Started" +description: "A getting started guide for Authelia." +lead: "This document serves as a get started guide for Authelia. It contains links to various sections and has some key notes in questions frequently asked by people looking to perform setup for the first time." +date: 2022-05-27T22:24:38+10:00 +draft: false +images: [] +menu: +  integration: +    parent: "prologue" +weight: 120 +toc: true +--- + +It's important to note that this guide has a layout which we suggest as the best order in areas to tackle, but you may +obviously choose a different path if you are so inclined. + +## Configuration + +It's important to customize the configuration for *Authelia* in advance of deploying it. The configuration is static and +not configured via web GUI. You can find a +[configuration template](https://github.com/authelia/authelia/blob/master/config.template.yml) on GitHub which can be +used as a basis for configuration. + +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 +   verification emails +2. [default_redirection_url](../../configuration/miscellaneous/introduction.md#default_redirection_url) which is the +   default URL users will be redirected to when visiting *Authelia* directly +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 +   essential for users to authenticate. +4. [storage](../../configuration/storage/introduction.md) which you must pick between the SQL Storage Providers, the +   recommended one for testing and lite deployments is [SQLite3](../../configuration/storage/sqlite.md) and the +   recommended one for production deployments otherwise is [PostgreSQL](../../configuration/storage/postgres.md). +5. [session](../../configuration/session/introduction.md) which is used to configure the session cookies, the +   [domain](../../configuration/session/introduction.md#domain) and +   [secret](../../configuration/session/introduction.md#secret) are the most important, and +   [redis](../../configuration/session/redis.md) is recommended for production environments. +6. [notifier](../../configuration/notifications/introduction.md) which is used to send 2FA registration emails etc, +   there is an option for local file delivery but the [SMTP](../../configuration/notifications/smtp.md) option is +   recommended for production. +7. [access_control](../../configuration/security/access-control.md) is also important but should be configured with a +   very basic policy to begin with. Something like: + +  ```yaml +  access_control: +    default_policy: deny +    rules: +      - domain: "*.example.com" +        policy: one_factor +  ``` + +## Deployment + +There are several methods of deploying *Authelia* and we recommend reading the +[Deployment Documentation](../deployment/introduction.md) in order to perform deployment. + +## Proxy Integration + +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). + +*__Important Note:__ When your [Deployment](#deployment) is on [Kubernetes](../kubernetes/introduction/index.md) we +recommend viewing the dedicated [Kubernetes Documentation](../kubernetes/introduction/index.md) prior to viewing the +[Proxy Integration Documentation](../proxies/introduction.md).* + +## Moving to Production + +We consider it important to do several things in moving to a production environment. + +1. Move all [secret values](../../configuration/methods/secrets.md#environment-variables) out of the configuration and +   into [secrets](../../configuration/methods/secrets.md). +2. Spend time understanding [access control](../../configuration/security/access-control.md) and granularly configure it +   to your requirements. +3. Review the [Security Measures](../../overview/security/measures.md) and +   [Threat Model](../../overview/security/threat-model.md) documentation. +4. Ensure you have reviewed the [Forwarded Headers](../proxies/fowarded-headers/index.md) documentation to ensure your +   proxy is not allowing insecure headers to be passed to *Authelia*. +5. Review the other [Configuration Options](../../configuration/prologue/introduction.md). diff --git a/docs/content/en/integration/prologue/introduction.md b/docs/content/en/integration/prologue/introduction.md new file mode 100644 index 000000000..6405b21d9 --- /dev/null +++ b/docs/content/en/integration/prologue/introduction.md @@ -0,0 +1,17 @@ +--- +title: "Prologue" +description: "An introduction into integrating Authelia with a product." +lead: "An introduction into integrating Authelia within your architecture." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  integration: +    parent: "prologue" +weight: 110 +toc: true +--- + +Authelia's [architecture](../../overview/prologue/architecture) is relatively simple which makes the methods of +integrating it within your existing architecture fairly vast. This section of the documentation provides non-exhaustive +insights and examples into how administrators may achieve integration. diff --git a/docs/content/en/integration/proxies/_index.md b/docs/content/en/integration/proxies/_index.md new file mode 100644 index 000000000..045d22949 --- /dev/null +++ b/docs/content/en/integration/proxies/_index.md @@ -0,0 +1,9 @@ +--- +title : "Proxies" +description: "Proxies Integration" +lead: "" +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +weight: 300 +--- diff --git a/docs/content/en/integration/proxies/caddy.md b/docs/content/en/integration/proxies/caddy.md new file mode 100644 index 000000000..90831c7fe --- /dev/null +++ b/docs/content/en/integration/proxies/caddy.md @@ -0,0 +1,238 @@ +--- +title: "Caddy" +description: "An integration guide for Authelia and the Caddy reverse proxy" +lead: "A guide on integrating Authelia with the Caddy reverse proxy." +date: 2022-05-13T12:06:00+10:00 +draft: false +images: [] +menu: +  integration: +    parent: "proxies" +weight: 320 +toc: true +aliases: +  - /i/caddy +  - /docs/deployment/supported-proxies/caddy.html +--- + +[Caddy] is a reverse proxy supported by __Authelia__. + +__Authelia__ offers integration support for the official forward auth integration method Caddy provides, we don't +officially support any plugin that supports this though we don't specifically prevent such plugins working and there may +be plugins that work fine provided they support the forward authentication specification correctly. + +*__Important:__ When using these guides it's important to recognize that we cannot provide a guide for every possible +method of deploying a proxy. These guides show a suggested setup only and you need to understand the proxy +configuration and customize it to your needs. To-that-end we include links to the official proxy documentation +throughout this documentation and in the [See Also](#see-also) section.* + +## Requirements + +You need the following to run __Authelia__ with [Caddy]: + +* [Caddy] [v2.5.1](https://github.com/caddyserver/caddy/releases/tag/v2.5.1) or greater + +## Trusted Proxies + +*__Important:__ You should read the [Forwarded Headers] section and this section as part of any proxy configuration. +Especially if you have never read it before.* + +*__Important:__ The included example is __NOT__ meant for production use. It's used expressly as an example to showcase +how you can configure multiple IP ranges. You should customize this example to fit your specific architecture and needs. +You should only include the specific IP address ranges of the trusted proxies within your architecture and should not +trust entire subnets unless that subnet only has trusted proxies and no other services.* + +[Caddy] by default doesn't trust any other proxies and removes potentially fabricated headers that are likely to lead +to security issues, and it is difficult to configure this incorrectly. This is an important security feature that is +common with proxies with good security practices. + +You should read the [Caddy Trusted Proxies Documentation] as part of configuring this. It's important to ensure you take +the time to configure this carefully and correctly. + +In the example we have a commented `trusted_proxies` directive which shows an example on adding the following networks +to the trusted proxy list in [Caddy]: + +* 10.0.0.0/8 +* 172.16.0.0/16 +* 192.168.0.0/16 +* fc00::/7 + +## Configuration + +Below you will find commented examples of the following configuration: + +* Authelia Portal +* Protected Endpoint (Nextcloud) + +### Basic examples + +This example is the preferred example for integration with [Caddy]. There is an [advanced example](#advanced-example) +but we *__strongly urge__* anyone who needs to use this for a particular reason to either reach out to us or Caddy for +support to ensure the basic example covers your use case in a secure way. + +#### Subdomain + +##### Caddyfile + +```caddyfile +## It is important to read the following document before enabling this section: +##     https://www.authelia.com/integration/proxies/caddy/#forwarded-header-trust#trusted-proxies +(trusted_proxy_list) { +       ## Uncomment & adjust the following line to configure specific ranges which should be considered as trustworthy. +       # trusted_proxies 10.0.0.0/8 172.16.0.0/16 192.168.0.0/16 fc00::/7 +} + +# Authelia Portal. +auth.example.com { +        reverse_proxy authelia:9091 { +                ## This import needs to be included if you're relying on a trusted proxies configuration. +                import trusted_proxy_list +        } +} + +# Protected Endpoint. +nextcloud.example.com { +        forward_auth authelia:9091 { +                uri /api/verify?rd=https://auth.example.com/ +                copy_headers Remote-User Remote-Groups Remote-Name Remote-Email + +                ## This import needs to be included if you're relying on a trusted proxies configuration. +                import trusted_proxy_list +        } +        reverse_proxy nextcloud:80 { +                ## This import needs to be included if you're relying on a trusted proxies configuration. +                import trusted_proxy_list +        } +} +``` + +#### Subpath + +##### Caddyfile + +```caddyfile +## It is important to read the following document before enabling this section: +##     https://www.authelia.com/integration/proxies/caddy/#forwarded-header-trust#trusted-proxies +(trusted_proxy_list) { +       ## Uncomment & adjust the following line to configure specific ranges which should be considered as trustworthy. +       # trusted_proxies 10.0.0.0/8 172.16.0.0/16 192.168.0.0/16 fc00::/7 +} + +example.com { +        # Authelia Portal. +        @authelia path /authelia /authelia/* +        handle @authelia { +                reverse_proxy authelia:9091 { +                        ## This import needs to be included if you're relying on a trusted proxies configuration. +                        import trusted_proxy_list +                } +        } + +        # Protected Endpoint. +        @nextcloud path /nextcloud /nextcloud/* +        handle @nextcloud { +                forward_auth authelia:9091 { +                        uri /api/verify?rd=https://example.com/authelia/ +                        copy_headers Remote-User Remote-Groups Remote-Name Remote-Email + +                        ## This import needs to be included if you're relying on a trusted proxies configuration. +                        import trusted_proxy_list +                } +                reverse_proxy nextcloud:80 { +                        ## This import needs to be included if you're relying on a trusted proxies configuration. +                        import trusted_proxy_list +                } +        } +} +``` + +### Advanced example + +The advanced example allows for more flexible customization, however the [basic example](#basic-examples) should be +preferred in *most* situations. If you are unsure of what you're doing please don't use this method. + +*__Important:__ Making a mistake when configuring the advanced example could lead to authentication bypass or errors.* + +##### Caddyfile + +```caddyfile +## It is important to read the following document before enabling this section: +##     https://www.authelia.com/integration/proxies/caddy/#forwarded-header-trust#trusted-proxies +(trusted_proxy_list) { +       ## Uncomment & adjust the following line to configure specific ranges which should be considered as trustworthy. +       # trusted_proxies 10.0.0.0/8 172.16.0.0/16 192.168.0.0/16 fc00::/7 +} + +# Authelia Portal. +auth.example.com { +        reverse_proxy authelia:9091 { +                ## This import needs to be included if you're relying on a trusted proxies configuration. +                import trusted_proxy_list +        } +} + +# Protected Endpoint. +nextcloud.example.com { +        route { +                reverse_proxy authelia:9091 { +                        ## This import needs to be included if you're relying on a trusted proxies configuration. +                        import trusted_proxy_list + +                        method GET +                        rewrite "/api/verify?rd=https://auth.example.com/" + +                        header_up X-Forwarded-Method {method} +                        header_up X-Forwarded-Uri {uri} + +                        ## If the auth request: +                        ##   1. Responds with a status code IN the 200-299 range. +                        ## Then: +                        ##   1. Proxy the request to the backend. +                        ##   2. Copy the relevant headers from the auth request and provide them to the backend. +                        @good status 2xx +                        handle_response @good { +                                request_header { +                                        Remote-User {http.reverse_proxy.header.Remote-User} +                                        Remote-Groups {http.reverse_proxy.header.Remote-Groups} +                                        Remote-Name {http.reverse_proxy.header.Remote-Name} +                                        Remote-Email {http.reverse_proxy.header.Remote-Email} +                                } +                        } + +                        ## If the auth request: +                        ##   1. Responds with a status code NOT IN the 200-299 range. +                        ## Then: +                        ##   1. Respond with the status code of the auth request. +                        ##   1. Copy the response except for several headers. +                        @denied { +                                status 1xx 3xx 4xx 5xx +                        } +                        handle_response @denied { +                                copy_response +                                copy_response_headers { +                                        exclude Connection Keep-Alive Te Trailers Transfer-Encoding Upgrade +                                } +                        } +                } + +                reverse_proxy nextcloud:80 { +                        ## This import needs to be included if you're relying on a trusted proxies configuration. +                        import trusted_proxy_list +                } +        } +} +``` + +## See Also + +* [Caddy General Documentation](https://caddyserver.com/docs/) +* [Caddy Forward Auth Documentation] +* [Caddy Trusted Proxies Documentation] +* [Caddy Snippet] Documentation +* [Forwarded Headers] + +[Caddy]: https://caddyserver.com +[Caddy Snippet]: https://caddyserver.com/docs/caddyfile/concepts#snippets +[Caddy Forward Auth Documentation]: https://caddyserver.com/docs/caddyfile/directives/forward_auth +[Caddy Trusted Proxies Documentation]: https://caddyserver.com/docs/caddyfile/directives/reverse_proxy#trusted_proxies +[Forwarded Headers]: fowarded-headers diff --git a/docs/content/en/integration/proxies/envoy.md b/docs/content/en/integration/proxies/envoy.md new file mode 100644 index 000000000..41eb9981e --- /dev/null +++ b/docs/content/en/integration/proxies/envoy.md @@ -0,0 +1,52 @@ +--- +title: "Envoy" +description: "An integration guide for Authelia and the Envoy reverse proxy" +lead: "A guide on integrating Authelia with the Envoy reverse proxy." +date: 2022-05-15T13:52:27+10:00 +draft: false +images: [] +menu: +  integration: +    parent: "proxies" +weight: 330 +toc: true +aliases: +  - /i/envoy +--- + +[Envoy] is probably supported by __Authelia__. + +*__Important:__ When using these guides it's important to recognize that we cannot provide a guide for every possible +method of deploying a proxy. These guides show a suggested setup only and you need to understand the proxy +configuration and customize it to your needs. To-that-end we include links to the official proxy documentation +throughout this documentation and in the [See Also](#see-also) section.* + +## UNDER CONSTRUCTION + +It's currently not certain, but fairly likely that [Envoy] is supported by __Authelia__. We wish to add documentation +and thus if anyone has this working please let us know. + +We will aim to perform documentation for this on our own but there is no current timeframe. + +## Trusted Proxies + +*__Important:__ You should read the [Forwarded Headers] section and this section as part of any proxy configuration. +Especially if you have never read it before.* + +*__Important:__ The included example is __NOT__ meant for production use. It's used expressly as an example to showcase +how you can configure multiple IP ranges. You should customize this example to fit your specific architecture and needs. +You should only include the specific IP address ranges of the trusted proxies within your architecture and should not +trust entire subnets unless that subnet only has trusted proxies and no other services.* + +## Potential + +Support for [Envoy] should be possible via [Envoy]'s +[external authorization](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ext_authz/v3/ext_authz.proto.html#extensions-filters-http-ext-authz-v3-extauthz). + +## See Also + +* [Envoy External Authorization Documentation](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ext_authz/v3/ext_authz.proto.html#extensions-filters-http-ext-authz-v3-extauthz) +* [Forwarded Headers] + +[Envoy]: https://www.envoyproxy.io/ +[Forwarded Headers]: fowarded-headers diff --git a/docs/content/en/integration/proxies/fowarded-headers/cloudflare_1.png b/docs/content/en/integration/proxies/fowarded-headers/cloudflare_1.png Binary files differnew file mode 100644 index 000000000..016c33ba8 --- /dev/null +++ b/docs/content/en/integration/proxies/fowarded-headers/cloudflare_1.png diff --git a/docs/content/en/integration/proxies/fowarded-headers/cloudflare_2.png b/docs/content/en/integration/proxies/fowarded-headers/cloudflare_2.png Binary files differnew file mode 100644 index 000000000..c0236c091 --- /dev/null +++ b/docs/content/en/integration/proxies/fowarded-headers/cloudflare_2.png diff --git a/docs/content/en/integration/proxies/fowarded-headers/index.md b/docs/content/en/integration/proxies/fowarded-headers/index.md new file mode 100644 index 000000000..8eb17fe8f --- /dev/null +++ b/docs/content/en/integration/proxies/fowarded-headers/index.md @@ -0,0 +1,88 @@ +--- +title: "Forwarded Headers" +description: "An introduction into the importance of forwarded headers coming from trusted sources" +lead: "An introduction into the importance of forwarded headers coming from trusted sources." +date: 2022-05-18T13:05:25+10:00 +draft: false +images: [] +menu: +  integration: +    parent: "proxies" +weight: 312 +toc: true +--- + +The`X-Forwarded-*` headers presented to __Authelia__ must be from trusted sources. As such you must ensure that the +reverse proxies and load balances utilized with __Authelia__ are configured to remove and replace specific headers when +they come directly from clients and not from proxies in your trusted environment. + +Some proxies require users explicitly configure the proxy to trust another proxy, however some implicitly trust all +headers regardless of the source and you have to manually + +## Network Rules + +In particular this is important for [Access Control Rules](../../../configuration/security/access-control.md#rules) as +the [network criteria](../../../configuration/security/access-control.md#networks) relies on the [X-Forwarded-For] +header. This header is expected to have a true representation of the clients actual IP address. + +If this is not removed from non-trusted proxies a user could theoretically hijack any rule that contains this criteria +to potentially skip an authentication criteria depending on how it is configured. + +## Cloud Proxies + +In addition to configuring your own proxies to remove this header from untrusted sources, when using a cloud proxy like +[Cloudflare](#cloudflare) you must ensure they do this or you configure a rule to do it. We aim to have documentation +in this section for cloud proxies that do this, but you should test this yourself and check the documentation for the +cloud proxy. + +In addition to this it's important if you wish to preserve the clients actual IP address that you trust the IP addresses +of the cloud proxy in your on-premise proxies. If you don't do this most if not all proxies configured as per our guides +will remove the header and everyone external will appear to come from a proxies source IP address rather than their real +IP address in both logging and access control. + +These same rules apply to any off-site hosted proxy or load balancing solution that alters the source IP address. + +### Cloudflare + +[Cloudflare] adds the [X-Forwarded-For] header if it does not exist, and if it does exist it will just append another IP +to it. This means a client can forge their remote IP address with the most widely accepted remote IP header out of the +box. + +It is therefore important you configure [Cloudflare] to remove this IP address. *__Please Note:__ This is by no means an +exhaustive guide on using [Cloudflare] transform rules, however it's enough to configure a couple rules which should +achieve a secure result. Please see the [Cloudflare] documentation on +[transform rules](https://developers.cloudflare.com/rules/transform/) for more information._ + +Steps: + +1. Click `Rules`. +2. Click `Transform Rules`. +3. Click `Create transform rules`. +4. Click `Modify Request Header`. +5. Set the `Rule name` to something appropriate like `Remove X-Forwarded-For Header`. +6. Set the `Field` option in the `When incoming requests match` section to an appropriate value (see criteria table +   below). +7. Set the `Operator` option in the `When incoming requests match` section to an appropriate value (see criteria table +   below). +8. Set the `Value` option in the `When incoming requests match` section to an appropriate value (see criteria table +   below). +9. Set the `Then` section dropdown to `Remove`. +10. Set the `Then` section `Header name` to `X-Forwarded-For`. +11. Click `Save`. + +{{< figure src="cloudflare_1.png" alt="Steps 1 to 4" width="736" style="padding-right: 10px" >}} +{{< figure src="cloudflare_2.png" alt="Steps 5 to 11" width="736" style="padding-right: 10px" >}} + +Criteria: + +|           Desired Result            |       Field       |    Operator    |               Value                | +|:-----------------------------------:|:-----------------:|:--------------:|:----------------------------------:| +|            Always Remove            |  X-Forwarded-For  | does not equal |              *blank*               | +| Remove When Not From Trusted Source | IP Source Address |   is not in    | *list of trusted source addresses* | + +Cloudflare publishes its IP address ranges publicly at the easy to remember address +[https://www.cloudflare.com/ips/](https://www.cloudflare.com/ips/). You should use this with the trusted proxies section +of your relevant proxy to ensure it's trusted if you intend to use Cloudflare. + +[X-Forwarded-For]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For +[Cloudflare]: https://www.cloudflare.com diff --git a/docs/deployment/supported-proxies/haproxy.md b/docs/content/en/integration/proxies/haproxy.md index 0cde183d8..bc1517ea6 100644 --- a/docs/deployment/supported-proxies/haproxy.md +++ b/docs/content/en/integration/proxies/haproxy.md @@ -1,60 +1,105 @@  --- -layout: default -title: HAProxy -parent: Proxy Integration -grand_parent: Deployment -nav_order: 2 +title: "HAProxy" +description: "An integration guide for Authelia and the HAProxy reverse proxy" +lead: "A guide on integrating Authelia with the HAProxy reverse proxy." +date: 2022-03-20T20:23:41+11:00 +draft: false +images: [] +menu: +  integration: +    parent: "proxies" +weight: 340 +toc: true +aliases: +  - /i/haproxy +  - /docs/deployment/supported-proxies/haproxy.html  --- -# HAProxy +[HAProxy] is a reverse proxy supported by __Authelia__. -[HAProxy] is a reverse proxy supported by **Authelia**. +*__Important:__ When using these guides it's important to recognize that we cannot provide a guide for every possible +method of deploying a proxy. These guides show a suggested setup only and you need to understand the proxy +configuration and customize it to your needs. To-that-end we include links to the official proxy documentation +throughout this documentation and in the [See Also](#see-also) section.*  ## Requirements -You need the following to run Authelia with HAProxy: +You need the following to run __Authelia__ with [HAProxy]: -* HAProxy 1.8.4+ (2.2.0+ recommended) -  * `USE_LUA=1` set at compile time +* [HAProxy] 1.8.4+ (2.2.0+ recommended) +  -`USE_LUA=1` set at compile time    * [haproxy-lua-http](https://github.com/haproxytech/haproxy-lua-http) must be available within the Lua path      * A `json` library within the Lua path (dependency of haproxy-lua-http, usually found as OS package `lua-json`) -    * With HAProxy 2.1.3+ you can use the [`lua-prepend-path`] configuration option to specify the search path. +    * With [HAProxy] 2.1.3+ you can use the `lua-prepend-path` configuration option to specify the search path    * [haproxy-auth-request](https://github.com/TimWolla/haproxy-auth-request/blob/master/auth-request.lua) +## Trusted Proxies + +*__Important:__ You should read the [Forwarded Headers] section and this section as part of any proxy configuration. +Especially if you have never read it before.* + +*__Important:__ The included example is __NOT__ meant for production use. It's used expressly as an example to showcase +how you can configure multiple IP ranges. You should customize this example to fit your specific architecture and needs. +You should only include the specific IP address ranges of the trusted proxies within your architecture and should not +trust entire subnets unless that subnet only has trusted proxies and no other services.* + +With [HAProxy] the most convenient method to configure trusted proxies is to create a src ACL from the contents of a +file. The example utilizes this method and trusted proxies can then easily be added or removed from the ACL file. + +[HAProxy] implicitly trusts all external proxies by default so it's important you configure this for a trusted +environment. + +[HAProxy] by default __does__ trust all other proxies. This means it's essential that you configure this correctly. + +In the example we have a `trusted_proxies.src.acl` file which is used by one `http-request del-header X-Forwarded-For` +line in the main configuration which shows an example of not trusting any proxies or alternatively an example on adding +the following networks to the trusted proxy list in [HAProxy]: + +* 10.0.0.0/8 +* 172.16.0.0/16 +* 192.168.0.0/16 +* fc00::/7  ## Configuration  Below you will find commented examples of the following configuration: -* Authelia portal -* Protected endpoint (Nextcloud) -* Protected endpoint with `Authorization` header for basic authentication (Heimdall) -* [haproxy-auth-request](https://github.com/TimWolla/haproxy-auth-request/blob/master/auth-request.lua) +* Authelia Portal +* Protected Endpoint (Nextcloud) +* Protected Endpoint with `Authorization` header for basic authentication (Heimdall)  With this configuration you can protect your virtual hosts with Authelia, by following the steps below: +  1. Add host(s) to the `protected-frontends` or `protected-frontends-basic` ACLs to support protection with Authelia.  You can separate each subdomain with a `|` in the regex, for example: -    ``` + +    ```text      acl protected-frontends hdr(host) -m reg -i ^(?i)(jenkins|nextcloud|phpmyadmin)\.example\.com      acl protected-frontends-basic hdr(host) -m reg -i ^(?i)(heimdall)\.example\.com      ``` +  2. Add host ACL(s) in the form of `host-service`, this will be utilised to route to the correct  backend upon successful authentication, for example: -    ``` + +    ```text      acl host-jenkins hdr(host) -i jenkins.example.com      acl host-nextcloud hdr(host) -i nextcloud.example.com      acl host-phpmyadmin hdr(host) -i phpmyadmin.example.com      acl host-heimdall hdr(host) -i heimdall.example.com      ``` +  3. Add backend route for your service(s), for example: -    ``` + +    ```text      use_backend be_jenkins if host-jenkins      use_backend be_nextcloud if host-nextcloud      use_backend be_phpmyadmin if host-phpmyadmin      use_backend be_heimdall if host-heimdall      ``` +  4. Add backend definitions for your service(s), for example: -    ``` + +    ```text      backend be_jenkins          server jenkins jenkins:8080      backend be_nextcloud @@ -62,19 +107,31 @@ backend upon successful authentication, for example:      backend be_phpmyadmin          server phpmyadmin phpmyadmin:80      backend be_heimdall -            server heimdall heimdall:443 ssl verify none +        server heimdall heimdall:443 ssl verify none      ```  ### Secure Authelia with TLS -There is a [known limitation](https://github.com/TimWolla/haproxy-auth-request/issues/12) with haproxy-auth-request with regard to TLS-enabled backends. -If you want to run Authelia TLS enabled the recommended workaround utilises HAProxy itself to proxy the requests. -This comes at a cost of two additional TCP connections, but allows the full HAProxy configuration flexibility with regard -to TLS verification as well as header rewriting. An example of this configuration is also be provided below. + +There is a [known limitation](https://github.com/TimWolla/haproxy-auth-request/issues/12) with haproxy-auth-request with +regard to TLS-enabled backends. If you want to run Authelia TLS enabled the recommended workaround utilises [HAProxy] +itself to proxy the requests. This comes at a cost of two additional TCP connections, but allows the full [HAProxy] +configuration flexibility with regard to TLS verification as well as header rewriting. An example of this configuration +is also be provided below.  #### Configuration -##### haproxy.cfg +##### trusted_proxies.src.acl + +```text +10.0.0.0/8 +172.16.0.0/12 +192.168.0.0/16 +fc00::/7  ``` + +##### haproxy.cfg + +```text  global      # Path to haproxy-lua-http, below example assumes /usr/local/etc/haproxy/haproxy-lua-http/http.lua      lua-prepend-path /usr/local/etc/haproxy/?/http.lua @@ -86,11 +143,22 @@ defaults      mode http      log global      option httplog -    option forwardfor  frontend fe_http -    bind *:443 ssl crt /usr/local/etc/haproxy/haproxy.pem -     +    bind *:443 ssl crt example.com.pem + +    ## Trusted Proxies. +    http-request del-header X-Forwarded-For + +    ## Comment the above directive and the two directives below to enable the trusted proxies ACL. +    # acl src-trusted_proxies src -f trusted_proxies.src.acl +    # http-request del-header X-Forwarded-For if !src-trusted_proxies + +    ## Ensure X-Forwarded-For is set for the auth request. +    acl hdr-xff_exists req.hdr(X-Forwarded-For) -m found +    http-request set-header X-Forwarded-For %[src] if !hdr-xff_exists +    option forwardfor +      # Host ACLs      acl protected-frontends hdr(host) -m reg -i ^(?i)(nextcloud)\.example\.com      acl protected-frontends-basic hdr(host) -m reg -i ^(?i)(heimdall)\.example\.com @@ -104,7 +172,7 @@ frontend fe_http      http-request set-var(req.scheme) str(https) if { ssl_fc }      http-request set-var(req.scheme) str(http) if !{ ssl_fc }      http-request set-var(req.questionmark) str(?) if { query -m found } -    +      # These are optional if you wish to use the Methods rule in the access_control section.      #http-request set-var(req.method) str(CONNECT) if { method CONNECT }      #http-request set-var(req.method) str(GET) if { method GET } @@ -173,7 +241,8 @@ backend be_heimdall  ```  ##### haproxy.cfg (TLS enabled Authelia) -``` + +```text  global      # Path to haproxy-lua-http, below example assumes /usr/local/etc/haproxy/haproxy-lua-http/http.lua      lua-prepend-path /usr/local/etc/haproxy/?/http.lua @@ -189,7 +258,7 @@ defaults  frontend fe_http      bind *:443 ssl crt /usr/local/etc/haproxy/haproxy.pem -     +      # Host ACLs      acl protected-frontends hdr(host) -m reg -i ^(?i)(nextcloud)\.example\.com      acl protected-frontends-basic hdr(host) -m reg -i ^(?i)(heimdall)\.example\.com @@ -203,7 +272,7 @@ frontend fe_http      http-request set-var(req.scheme) str(https) if { ssl_fc }      http-request set-var(req.scheme) str(http) if !{ ssl_fc }      http-request set-var(req.questionmark) str(?) if { query -m found } -     +      # These are optional if you wish to use the Methods rule in the access_control section.      #http-request set-var(req.method) str(CONNECT) if { method CONNECT }      #http-request set-var(req.method) str(GET) if { method GET } @@ -215,7 +284,7 @@ frontend fe_http      #http-request set-var(req.method) str(PATCH) if { method PATCH }      #http-request set-var(req.method) str(DELETE) if { method DELETE }      #http-request set-header X-Forwarded-Method %[var(req.method)] -     +      # Required headers      http-request set-header X-Real-IP %[src]      http-request set-header X-Forwarded-Proto %[var(req.scheme)] @@ -279,4 +348,10 @@ backend be_heimdall      server heimdall heimdall:443 ssl verify none  ``` +## See Also + +* [HAProxy Auth Request lua plugin Documentation](https://github.com/TimWolla/haproxy-auth-request) +* [Forwarded Headers] +  [HAproxy]: https://www.haproxy.org/ +[Forwarded Headers]: fowarded-headers diff --git a/docs/content/en/integration/proxies/introduction.md b/docs/content/en/integration/proxies/introduction.md new file mode 100644 index 000000000..18b05fa3d --- /dev/null +++ b/docs/content/en/integration/proxies/introduction.md @@ -0,0 +1,86 @@ +--- +title: "Proxies" +description: "An integration guide for Authelia and several supported reverse proxies" +lead: "An introduction into integrating Authelia with a reverse proxy." +date: 2022-03-20T20:23:41+11:00 +draft: false +images: [] +menu: +  integration: +    parent: "proxies" +weight: 310 +toc: true +aliases: +  - /i/proxies +--- + +__Authelia__ works in collaboration with several reverse proxies. In this section you will find the documentation of the +various tested proxies with examples of how you may configure them. We are eager for users to help us provide better +examples of already documented proxies, as well as provide us examples of undocumented proxies. + +## Support + +See [support](support.md) for support information. + +## Integration Implementation + +Authelia is capable of being integrated into many proxies due to the decisions regarding the implementation. We handle +requests to the `/api/verify` endpoint with specific headers and return standardized responses based on the headers and +the policy engines determination about what must be done. + +### Destination Identification + +The method to identify the destination of a request relies on metadata headers which need to be set by your reverse +proxy. The headers we rely on are as follows: + +* [X-Forwarded-Proto](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Proto) +* [X-Forwarded-Host](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Host) +* X-Forwarded-Uri +* [X-Forwarded-For](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For) +* X-Forwarded-Method + +Alternatively we utilize `X-Original-URL` header which is expected to contain a fully formatted URL. + +### User Identification + +A logged in user must be identified via standard means. Users are identified by one of two methods: + +* A session cookie with the HTTP only option set, and the secure option set meaning the cookie must only be sent over the +  [HTTPS scheme](https://developer.mozilla.org/en-US/docs/Glossary/https). +* The [Proxy-Authorization](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Proxy-Authorization) header +  utilizing the +  [basic authentication scheme](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication#basic_authentication_scheme). + +### Response Statuses + +Authelia responds in various ways depending on the result of the authorization policies. + +When the user is authenticated and authorized to access a resource we respond with a HTTP +[200 OK](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/200). When the user is not logged in and we need them +to authenticate with 1FA, or if they are already authenticated with only 1FA and they need to perform 2FA, the user is +redirected to the portal with: + +* A HTTP [401 Unauthorized](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/401) status if the original request +  was an [XMLHTTPRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) provided Authelia is able to +  detect it. +* A HTTP [302 Found](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/302) status if the original request had +  the [GET](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET) or +  [OPTIONS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS) method verb. +* A HTTP [303 See Other](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/303) status if neither of the above +  conditions is met. + +When the user is denied either by a default policy, or by an explicit policy we respond with a HTTP +[403 Forbidden](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/403) status. + +### Response Headers + +With the exception of the [403 Forbidden](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/403) and +[200 OK](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/200) status responses above, +Authelia responds with a [Location](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Location) header to +redirect the user to the authentication portal. + +In the instance of a [200 OK](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/200) status response Authelia +also responds with various headers which can be forwarded by your reverse proxy to the backend application which are +potentially useful for SSO depending on if the backend application supports it. + +See the [Trusted Header SSO](../trusted-header-sso/introduction.md) documentation for more information. diff --git a/docs/content/en/integration/proxies/nginx-proxy-manager.md b/docs/content/en/integration/proxies/nginx-proxy-manager.md new file mode 100644 index 000000000..97fa389cb --- /dev/null +++ b/docs/content/en/integration/proxies/nginx-proxy-manager.md @@ -0,0 +1,50 @@ +--- +title: "NGINX Proxy Manager" +description: "An integration guide for Authelia and the NGINX Proxy Manager reverse proxy" +lead: "A guide on integrating Authelia with NGINX Proxy Manager." +date: 2022-05-15T13:52:27+10:00 +draft: false +images: [] +menu: +  integration: +    parent: "proxies" +weight: 352 +toc: true +aliases: +  - /i/npm +--- + +[NGINX Proxy Manager] is supported by __Authelia__. It's a [NGINX] proxy with a configuration UI. + +*__Important:__ When using these guides it's important to recognize that we cannot provide a guide for every possible +method of deploying a proxy. These guides show a suggested setup only and you need to understand the proxy +configuration and customize it to your needs. To-that-end we include links to the official proxy documentation +throughout this documentation and in the [See Also](#see-also) section.* + +## UNDER CONSTRUCTION + +While this proxy is supported we don't have any specific documentation for it at the present time. Please see the +[NGINX integration documentation](nginx.md) for hints on how to configure this. + +## Requirements + +[NGINX Proxy Manager] supports the required [NGINX](nginx.md#requirements) requirements for __Authelia__ out-of-the-box. + +## Trusted Proxies + +*__Important:__ You should read the [Forwarded Headers] section and this section as part of any proxy configuration. +Especially if you have never read it before.* + +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 +this documentation. + +## See Also + +* [NGINX Proxy Manager Documentation](https://nginxproxymanager.com/setup/) +* [NGINX ngx_http_auth_request_module Module Documentation](https://nginx.org/en/docs/http/ngx_http_auth_request_module.html) +* [Forwarded Headers] + +[NGINX Proxy Manager]: https://nginxproxymanager.com/ +[NGINX]: https://www.nginx.com/ +[Forwarded Headers]: fowarded-headers diff --git a/docs/content/en/integration/proxies/nginx.md b/docs/content/en/integration/proxies/nginx.md new file mode 100644 index 000000000..3251ea11a --- /dev/null +++ b/docs/content/en/integration/proxies/nginx.md @@ -0,0 +1,434 @@ +--- +title: "NGINX" +description: "An integration guide for Authelia and the NGINX reverse proxy" +lead: "A guide on integrating Authelia with the nginx reverse proxy." +date: 2022-03-20T20:23:41+11:00 +draft: false +images: [] +menu: +  integration: +    parent: "proxies" +weight: 350 +toc: true +aliases: +  - /i/nginx +  - /docs/deployment/supported-proxies/nginx.html +--- + +[NGINX] is a reverse proxy supported by __Authelia__. + +*__Important:__ When using these guides it's important to recognize that we cannot provide a guide for every possible +method of deploying a proxy. These guides show a suggested setup only and you need to understand the proxy +configuration and customize it to your needs. To-that-end we include links to the official proxy documentation +throughout this documentation and in the [See Also](#see-also) section.* + +## Requirements + +You need the following to run __Authelia__ with [NGINX]: + +* [NGINX] must be built with the `http_auth_request` module which is relatively common +* [NGINX] must be built with the `http_realip` module which is relatively common + +## Trusted Proxies + +*__Important:__ You should read the [Forwarded Headers] section and this section as part of any proxy configuration. +Especially if you have never read it before.* + +*__Important:__ The included example is __NOT__ meant for production use. It's used expressly as an example to showcase +how you can configure multiple IP ranges. You should customize this example to fit your specific architecture and needs. +You should only include the specific IP address ranges of the trusted proxies within your architecture and should not +trust entire subnets unless that subnet only has trusted proxies and no other services.* + +[NGINX]'s `http_realip` module is used to configure the trusted proxies' configuration. In our examples this is +configured in the `proxy.conf` file. Each `set_realip_from` directive adds a trusted proxy address range to the trusted +proxies list. Any request that comes from a source IP not in one of the configured ranges results in the header being +replaced with the source IP of the client. + +## Configuration + +Below you will find commented examples of the following configuration: + +* [Authelia Portal](#authelia-portal) +  * Running in Docker +  * Has the container name `authelia` +* [Protected Endpoint (Nextcloud)](#protected-endpoint) +  * Running in Docker +  * Has the container name `nextcloud` +* [Supporting Configuration Snippets](#supporting-configuration-snippets) +* Assumes the following since we cannot reasonably provide a configuration for every architecture: +  * [NGINX] is also running in Docker and uses Docker DNS as a +    [resolver](https://nginx.org/en/docs/http/ngx_http_core_module.html#resolver) which is standard +  * [NGINX] shares a network with the `authelia` and `nextcloud` containers + +### Standard Example + +This example is for using the __Authelia__ portal redirection flow on a specific endpoint. It requires you to have the +[authelia-location.conf](#authelia-locationconf), +[authelia-authrequest.conf](#authelia-authrequestconf), and [proxy.conf](#proxyconf) snippets. In the example these +files exist in the `/config/nginx/` directory. The `/config/nginx/ssl.conf` snippet is expected to have +the configuration for TLS or SSL but is not included as part of the examples. + +#### Authelia Portal + +##### auth.example.com.conf + +```nginx +server { +    listen 80; +    server_name auth.example.com; + +    return 301 https://$server_name$request_uri; +} + +server { +    listen 443 ssl http2; +    server_name auth.example.com; + +    include /config/nginx/ssl.conf; + +    location / { +        include /config/nginx/proxy.conf; + +        set $upstream_authelia http://authelia:9091; +        proxy_pass $upstream_authelia; +    } +} +``` + +#### Protected Endpoint + +##### nextcloud.example.com.conf + +```nginx +server { +    listen 80; +    server_name nextcloud.example.com; + +    return 301 https://$server_name$request_uri; +} + +server { +    listen 443 ssl http2; +    server_name nextcloud.example.com; + +    include /config/nginx/ssl.conf; +    include /config/nginx/authelia-location.conf; + +    location / { +        include /config/nginx/proxy.conf; +        include /config/nginx/authelia-authrequest.conf; + +        set $upstream_nextcloud https://nextcloud; +        proxy_pass $upstream_nextcloud; +    } +} +``` + +### HTTP Basic Authentication Example + +This example is for using HTTP basic auth on a specific endpoint. It is based on the full example above. It requires you +to have the [authelia-location-basic.conf](#authelia-location-basicconf), +[authelia-authrequest-basic.conf](#authelia-authrequest-basicconf), and [proxy.conf](#proxyconf) snippets. In the +example these files exist in the `/config/nginx/` directory. The `/config/nginx/ssl.conf` snippet is expected to have +the configuration for TLS or SSL but is not included as part of the examples. + +The [Authelia Portal](#authelia-portal) configuration can be reused for this example as such it isn't repeated. + +#### HTTP Basic Authentication Protected Endpoint + +```nginx +server { +    listen 80; +    server_name nextcloud.example.com; + +    return 301 https://$server_name$request_uri; +} + +server { +    listen 443 ssl http2; +    server_name nextcloud.example.com; + +    include /config/nginx/ssl.conf; +    include /config/nginx/authelia-location-basic.conf; # Use the "basic" endpoint + +    location / { +        include /config/nginx/proxy.conf; +        include /config/nginx/authelia-authrequest-basic.conf; + +        set $upstream_nextcloud https://nextcloud; +        proxy_pass $upstream_nextcloud; +    } +} +``` + +### Supporting Configuration Snippets + +The following configuration files are snippets that are used as includes in other files. The includes in the other files +match the headings, so if you wish to put them in a specific location or rename them, then make sure to update the +includes appropriately. Only the [proxy.conf](#proxyconf), [authelia-location.conf](#authelia-locationconf), and +[authelia-authrequest.conf](#authelia-authrequestconf) are required; see the descriptions for the others as to their +use cases. + +#### proxy.conf + +The following is an example `proxy.conf`. The important directives include the `real_ip` directives which you should read +[Trusted Proxies](#trusted-proxies) section to understand, or set the `X-Forwarded-Proto`, `X-Forwarded-Host`, +`X-Forwarded-Uri`, and `X-Forwarded-For` headers. + +```nginx +## Headers +proxy_set_header Host $host; +proxy_set_header X-Forwarded-Proto $scheme; +proxy_set_header X-Forwarded-Host $http_host; +proxy_set_header X-Forwarded-Uri $request_uri; +proxy_set_header X-Forwarded-Ssl on; +proxy_set_header X-Forwarded-For $remote_addr; +proxy_set_header X-Real-IP $remote_addr; +proxy_set_header Connection ""; + +## Basic Proxy Configuration +client_body_buffer_size 128k; +proxy_next_upstream error timeout invalid_header http_500 http_502 http_503; ## Timeout if the real server is dead. +proxy_redirect  http://  $scheme://; +proxy_http_version 1.1; +proxy_cache_bypass $cookie_session; +proxy_no_cache $cookie_session; +proxy_buffers 64 256k; + +## Trusted Proxies Configuration +## Please read the following documentation before configuring this: +##     https://www.authelia.com/integration/proxies/nginx/#trusted-proxies +# set_real_ip_from 10.0.0.0/8; +# set_real_ip_from 172.16.0.0/12; +# set_real_ip_from 192.168.0.0/16; +# set_real_ip_from fc00::/7; +real_ip_header X-Forwarded-For; +real_ip_recursive on; + +## Advanced Proxy Configuration +send_timeout 5m; +proxy_read_timeout 360; +proxy_send_timeout 360; +proxy_connect_timeout 360; +``` + +#### authelia-location.conf + +*The following snippet is used within the `server` block of a virtual host as a supporting endpoint used by +`auth_request` and is paired with [authelia-authrequest.conf](#authelia-authrequestconf).* +```nginx +set $upstream_authelia http://authelia:9091/api/verify; + +## Virtual endpoint created by nginx to forward auth requests. +location /authelia { +    ## Essential Proxy Configuration +    internal; +    proxy_pass $upstream_authelia; + +    ## Headers +    ## The headers starting with X-* are required. +    proxy_set_header X-Original-URL $scheme://$http_host$request_uri; +    proxy_set_header X-Forwarded-Method $request_method; +    proxy_set_header X-Forwarded-Proto $scheme; +    proxy_set_header X-Forwarded-Host $http_host; +    proxy_set_header X-Forwarded-Uri $request_uri; +    proxy_set_header X-Forwarded-For $remote_addr; +    proxy_set_header Content-Length ""; +    proxy_set_header Connection ""; + +    ## Basic Proxy Configuration +    proxy_pass_request_body off; +    proxy_next_upstream error timeout invalid_header http_500 http_502 http_503; # Timeout if the real server is dead +    proxy_redirect http:// $scheme://; +    proxy_http_version 1.1; +    proxy_cache_bypass $cookie_session; +    proxy_no_cache $cookie_session; +    proxy_buffers 4 32k; +    client_body_buffer_size 128k; + +    ## Advanced Proxy Configuration +    send_timeout 5m; +    proxy_read_timeout 240; +    proxy_send_timeout 240; +    proxy_connect_timeout 240; +} +``` + +#### authelia-authrequest.conf + +*The following snippet is used within a `location` block of a virtual host which uses the appropriate location block +and is paired with [authelia-location.conf](#authelia-locationconf).* + +```nginx +## Send a subrequest to Authelia to verify if the user is authenticated and has permission to access the resource. +auth_request /authelia; + +## Set the $target_url variable based on the original request. +auth_request_set $target_url $scheme://$http_host$request_uri; + +## Save the upstream response headers from Authelia to variables. +auth_request_set $user $upstream_http_remote_user; +auth_request_set $groups $upstream_http_remote_groups; +auth_request_set $name $upstream_http_remote_name; +auth_request_set $email $upstream_http_remote_email; + +## Inject the response headers from the variables into the request made to the backend. +proxy_set_header Remote-User $user; +proxy_set_header Remote-Groups $groups; +proxy_set_header Remote-Name $name; +proxy_set_header Remote-Email $email; + +## If the subreqest returns 200 pass to the backend, if the subrequest returns 401 redirect to the portal. +error_page 401 =302 https://auth.example.com/?rd=$target_url; +``` + +#### authelia-location-basic.conf + +*The following snippet is used within the `server` block of a virtual host as a supporting endpoint used by +`auth_request` and is paired with [authelia-authrequest-basic.conf](#authelia-authrequest-basicconf). This particular +snippet is rarely required. It's only used if you want to only allow +[HTTP Basic Authentication](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication) for a particular +endpoint. It's recommended to use [authelia-location.conf](#authelia-locationconf) instead.* + +```nginx +set $upstream_authelia http://authelia:9091/api/verify?auth=basic; + +# Virtual endpoint created by nginx to forward auth requests. +location /authelia-basic { +    ## Essential Proxy Configuration +    internal; +    proxy_pass $upstream_authelia; + +    ## Headers +    ## The headers starting with X-* are required. +    proxy_set_header X-Original-URL $scheme://$http_host$request_uri; +    proxy_set_header X-Forwarded-Method $request_method; +    proxy_set_header X-Forwarded-Proto $scheme; +    proxy_set_header X-Forwarded-Host $http_host; +    proxy_set_header X-Forwarded-Uri $request_uri; +    proxy_set_header X-Forwarded-For $remote_addr; +    proxy_set_header Content-Length ""; +    proxy_set_header Connection ""; + +    ## Basic Proxy Configuration +    proxy_pass_request_body off; +    proxy_next_upstream error timeout invalid_header http_500 http_502 http_503; # Timeout if the real server is dead +    proxy_redirect http:// $scheme://; +    proxy_http_version 1.1; +    proxy_cache_bypass $cookie_session; +    proxy_no_cache $cookie_session; +    proxy_buffers 4 32k; +    client_body_buffer_size 128k; + +    ## Advanced Proxy Configuration +    send_timeout 5m; +    proxy_read_timeout 240; +    proxy_send_timeout 240; +    proxy_connect_timeout 240; +} +``` + +#### authelia-authrequest-basic.conf + +*The following snippet is used within a `location` block of a virtual host which uses the appropriate location block +and is paired with [authelia-location-basic.conf](#authelia-location-basicconf). This particular snippet is rarely +required. It's only used if you want to only allow +[HTTP Basic Authentication](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication) for a particular +endpoint. It's recommended to use [authelia-authrequest.conf](#authelia-authrequestconf) instead.* + +```nginx +## Send a subrequest to Authelia to verify if the user is authenticated and has permission to access the resource. +auth_request /authelia-basic; + +## Set the $target_url variable based on the original request. +auth_request_set $target_url $scheme://$http_host$request_uri; + +## Save the upstream response headers from Authelia to variables. +auth_request_set $user $upstream_http_remote_user; +auth_request_set $groups $upstream_http_remote_groups; +auth_request_set $name $upstream_http_remote_name; +auth_request_set $email $upstream_http_remote_email; + +## Inject the response headers from the variables into the request made to the backend. +proxy_set_header Remote-User $user; +proxy_set_header Remote-Groups $groups; +proxy_set_header Remote-Name $name; +proxy_set_header Remote-Email $email; +``` + +#### authelia-location-detect.conf + +*The following snippet is used within the `server` block of a virtual host as a supporting endpoint used by +`auth_request` and is paired with [authelia-authrequest-detect.conf](#authelia-authrequest-detectconf). This particular +snippet is rarely required. It's only used if you want to conditionally require +[HTTP Basic Authentication](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication) for a particular +endpoint. It's recommended to use [authelia-location.conf](#authelia-locationconf) instead.* + +```nginx +include /config/nginx/authelia-location.conf; + +set $is_basic_auth ""; # false value + +## Detect the client you want to force basic auth for here +## For the example we just match a path on the original request +if ($request_uri = "/force-basic") { +    set $is_basic_auth "true"; +    set $upstream_authelia "$upstream_authelia?auth=basic"; +} + +## A new virtual endpoint to used if the auth_request failed +location  /authelia-detect { +    internal; + +    if ($is_basic_auth) { +        ## This is a request where we decided to use basic auth, return a 401. +        ## Nginx will also proxy back the WWW-Authenticate header from Authelia's +        ## response. This is what informs the client we're expecting basic auth. +        return 401; +    } + +    ## The original request didn't target /force-basic, redirect to the pretty login page +    ## This is what `error_page 401 =302 https://auth.example.com/?rd=$target_url;` did. +    return 302 https://auth.example.com/$is_args$args; +} +``` + +#### authelia-authrequest-detect.conf + +*The following snippet is used within a `location` block of a virtual host which uses the appropriate location block +and is paired with [authelia-location-detect.conf](#authelia-location-detectconf). This particular snippet is rarely +required. It's only used if you want to conditionally require +[HTTP Basic Authentication](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication) for a particular +endpoint. It's recommended to use [authelia-authrequest.conf](#authelia-authrequestconf) instead.* + +```nginx +## Send a subrequest to Authelia to verify if the user is authenticated and has permission to access the resource. +auth_request /authelia; + +## Set the $target_url variable based on the original request. +auth_request_set $target_url $scheme://$http_host$request_uri; + +## Save the upstream response headers from Authelia to variables. +auth_request_set $user $upstream_http_remote_user; +auth_request_set $groups $upstream_http_remote_groups; +auth_request_set $name $upstream_http_remote_name; +auth_request_set $email $upstream_http_remote_email; + +## Inject the response headers from the variables into the request made to the backend. +proxy_set_header Remote-User $user; +proxy_set_header Remote-Groups $groups; +proxy_set_header Remote-Name $name; +proxy_set_header Remote-Email $email; + +## If the subreqest returns 200 pass to the backend, if the subrequest returns 401 redirect to the portal. +error_page 401 =302 /authelia-detect?rd=$target_url; +``` + +## See Also + +* [NGINX ngx_http_auth_request_module Module Documentation](https://nginx.org/en/docs/http/ngx_http_auth_request_module.html) +* [NGINX ngx_http_realip_module Module Documentation](https://nginx.org/en/docs/http/ngx_http_realip_module.html) +* [Forwarded Headers] + +[NGINX]: https://www.nginx.com/ +[Forwarded Headers]: fowarded-headers diff --git a/docs/content/en/integration/proxies/skipper.md b/docs/content/en/integration/proxies/skipper.md new file mode 100644 index 000000000..0f2edf210 --- /dev/null +++ b/docs/content/en/integration/proxies/skipper.md @@ -0,0 +1,52 @@ +--- +title: "Skipper" +description: "An integration guide for Authelia and the Skipper reverse proxy" +lead: "A guide on integrating Authelia with the Skipper reverse proxy." +date: 2022-05-15T13:52:27+10:00 +draft: false +images: [] +menu: +  integration: +    parent: "proxies" +weight: 360 +toc: true +aliases: +  - /i/skipper +--- + +[Skipper] is probably supported by __Authelia__. + +*__Important:__ When using these guides it's important to recognize that we cannot provide a guide for every possible +method of deploying a proxy. These guides show a suggested setup only and you need to understand the proxy +configuration and customize it to your needs. To-that-end we include links to the official proxy documentation +throughout this documentation and in the [See Also](#see-also) section.* + +## UNDER CONSTRUCTION + +It's currently not certain, but fairly likely that [Skipper] is supported by __Authelia__. We wish to add documentation +and thus if anyone has this working please let us know. + +We will aim to perform documentation for this on our own but there is no current timeframe. + +## Trusted Proxies + +*__Important:__ You should read the [Forwarded Headers] section and this section as part of any proxy configuration. +Especially if you have never read it before.* + +*__Important:__ The included example is __NOT__ meant for production use. It's used expressly as an example to showcase +how you can configure multiple IP ranges. You should customize this example to fit your specific architecture and needs. +You should only include the specific IP address ranges of the trusted proxies within your architecture and should not +trust entire subnets unless that subnet only has trusted proxies and no other services.* + +## Potential + +Support for [Skipper] should be possible via [Skipper]'s +[Webhook Filter](https://opensource.zalando.com/skipper/reference/filters/#webhook). + +## See Also + +* [Skipper Webhook Filter Documentation](https://opensource.zalando.com/skipper/reference/filters/#webhook) +* [Forwarded Headers] + +[Skipper]: https://opensource.zalando.com/skipper/ +[Forwarded Headers]: fowarded-headers diff --git a/docs/content/en/integration/proxies/support.md b/docs/content/en/integration/proxies/support.md new file mode 100644 index 000000000..402483ca4 --- /dev/null +++ b/docs/content/en/integration/proxies/support.md @@ -0,0 +1,122 @@ +--- +title: "Support" +description: "An support matrix for Authelia and several supported reverse proxies" +lead: "This documentation details a support matrix for Authelia features and specific reverse proxies as well as several caveats etc." +date: 2022-05-13T12:34:15+10:00 +draft: false +images: [] +menu: +  integration: +    parent: "proxies" +weight: 311 +toc: true +aliases: +  - /i/proxy +  - /docs/home/supported-proxies.html +--- + +|         Proxy         |                      [Standard](#standard)                       |                              [Kubernetes](#kubernetes)                               |    [XHR Redirect](#xhr-redirect)     |  [Request Method](#request-method)   | +|:---------------------:|:----------------------------------------------------------------:|:------------------------------------------------------------------------------------:|:------------------------------------:|:------------------------------------:| +|       [Traefik]       |         [<i class="icon-support-full"></i>](traefik.md)          | [<i class="icon-support-full"></i>](../../integration/kubernetes/traefik-ingress.md) |  <i class="icon-support-full"></i>   |  <i class="icon-support-full"></i>   | +|        [NGINX]        |          [<i class="icon-support-full"></i>](nginx.md)           |  [<i class="icon-support-full"></i>](../../integration/kubernetes/nginx-ingress.md)  |  <i class="icon-support-none"></i>   |  <i class="icon-support-full"></i>   | +| [NGINX Proxy Manager] |   [<i class="icon-support-full"></i>](nginx-proxy-manager.md)    |                         <i class="icon-support-unknown"></i>                         |  <i class="icon-support-none"></i>   |  <i class="icon-support-full"></i>   | +|        [SWAG]         |           [<i class="icon-support-full"></i>](swag.md)           |                         <i class="icon-support-unknown"></i>                         |  <i class="icon-support-none"></i>   |  <i class="icon-support-full"></i>   | +|       [HAProxy]       |         [<i class="icon-support-full"></i>](haproxy.md)          |                         <i class="icon-support-unknown"></i>                         | <i class="icon-support-unknown"></i> |  <i class="icon-support-full"></i>   | +|        [Caddy]        |          [<i class="icon-support-full"></i>](caddy.md)           |                         <i class="icon-support-unknown"></i>                         |  <i class="icon-support-full"></i>   |  <i class="icon-support-full"></i>   | +|     [Traefik] 1.x     |        [<i class="icon-support-full"></i>](traefikv1.md)         |                         <i class="icon-support-unknown"></i>                         |  <i class="icon-support-full"></i>   |  <i class="icon-support-full"></i>   | +|        [Envoy]        |         [<i class="icon-support-unknown"></i>](envoy.md)         |                         <i class="icon-support-unknown"></i>                         | <i class="icon-support-unknown"></i> | <i class="icon-support-unknown"></i> | +|       [Skipper]       |        [<i class="icon-support-unknown"></i>](skipper.md)        |                         <i class="icon-support-unknown"></i>                         | <i class="icon-support-unknown"></i> | <i class="icon-support-unknown"></i> | +|       [Apache]        | [<i class="icon-support-none" alt="Not Supported"></i>](#apache) |                          <i class="icon-support-none"></i>                           |  <i class="icon-support-none"></i>   |  <i class="icon-support-none"></i>   | +|         [IIS]         |            [<i class="icon-support-none"></i>](#iis)             |                          <i class="icon-support-none"></i>                           |  <i class="icon-support-none"></i>   |  <i class="icon-support-none"></i>   | + +Legend: + +|                 Icon                 |       Meaning       | +|:------------------------------------:|:-------------------:| +|  <i class="icon-support-full"></i>   |      Supported      | +| <i class="icon-support-unknown"></i> |       Unknown       | +| <i class="icon-support-partial"></i> | Partially Supported | +|  <i class="icon-support-none"></i>   |    Not Supported    | + +## Support + +### Standard + +Standard support includes the essential features in securing an application with Authelia such as: + +* Redirecting users to the Authelia portal if they are not authenticated. +* Redirecting users to the target application after authentication has occurred successfully. + +It does not include actually running Authelia as a service behind the proxy, any proxy should be compatible with serving +the Authelia portal itself. Standard support is only important for protected applications. + +### Kubernetes + +While proxies that generally support Authelia outside a [Kubernetes] cluster, there are a few situations where that does +not translate to being possible when used as an [Ingress Controller]. There are various reasons for this such as the +reverse proxy in question does not even support running as a [Kubernetes] [Ingress Controller], or the required modules +to perform authentication transparently to the user are not typically available inside a cluster. + +More information about [Kubernetes] deployments of Authelia can be read in the +[documentation](../../integration/kubernetes/introduction.md). + +### XHR Redirect + +*__Note:__ The XHR is a deprecated web feature and applications should be using the new [Fetch API] which does not have +the same issues regarding redirects (the [Fetch API] allows developers to +[control how to handle them](https://developer.mozilla.org/en-US/docs/Web/API/Request/redirect)). As such the fact +a proxy does not support it should only be seen as a means to communicate a feature not that the proxy should not be +used.* + +XML HTTP Requests do not typically redirect browsers when returned 30x status codes. Instead, the standard method is to +return a 401 status code with a Location header. While this may seem trivial; currently there isn't wide support for it. +For example the nginx ngx_http_auth_request_module does not seem to support this in any way. + +### Request Method + +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 +[Standard Support](#standard-support) do support this. + +## Specific proxy notes + +### HAProxy + +[HAProxy] is only supported via a lua [module](https://github.com/haproxytech/haproxy-lua-http). Lua is typically not +available in [Kubernetes]. You would likely have to build your own [HAProxy] image. + +### Envoy + +[Envoy] is currently not documented however we believe it is likely to be technically supported. This should be possible +via [Envoy]'s [external authorization](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ext_authz/v3/ext_authz.proto.html#extensions-filters-http-ext-authz-v3-extauthz). + +### Caddy + +[Caddy] needs to be version 2.5.1 or greater. + +### Apache + +[Apache] is not supported as it has no module that supports this kind of authentication method. It's not certain this +would even be possible, however if anyone did something like this in the future we'd be interested in a contribution. + +### IIS + +Microsoft [IIS] is not supported as it has no module that supports this kind of authentication method. It's not certain +this would even be possible, however if anyone did something like this in the future we'd be interested in a +contribution. + +[NGINX]: https://www.nginx.com/ +[NGINX Proxy Manager]: https://nginxproxymanager.com/ +[SWAG]: https://docs.linuxserver.io/general/swag +[Traefik]: https://traefik.io/ +[Caddy]: https://caddyserver.com/ +[HAProxy]: https://www.haproxy.com/ +[Envoy]: https://www.envoyproxy.io/ +[Skipper]: https://opensource.zalando.com/skipper/ +[Caddy]: https://caddyserver.com/ +[Apache]: https://httpd.apache.org/ +[IIS]: https://www.iis.net/ +[Kubernetes]: https://kubernetes.io/ +[Ingress Controller]: https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/ + +[Fetch API]: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API diff --git a/docs/content/en/integration/proxies/swag.md b/docs/content/en/integration/proxies/swag.md new file mode 100644 index 000000000..fe0de20bc --- /dev/null +++ b/docs/content/en/integration/proxies/swag.md @@ -0,0 +1,130 @@ +--- +title: "SWAG" +description: "An integration guide for Authelia and the SWAG reverse proxy" +lead: "A guide on integrating Authelia with SWAG." +date: 2022-05-17T10:57:38+10:00 +draft: false +images: [] +menu: +  integration: +    parent: "proxies" +weight: 351 +toc: true +aliases: +  - /i/swag +--- + +[SWAG] is a reverse proxy supported by __Authelia__. It's an [NGINX] proxy container with bundled configurations to make +your life easier. + +*__Important:__ When using these guides it's important to recognize that we cannot provide a guide for every possible +method of deploying a proxy. These guides show a suggested setup only and you need to understand the proxy +configuration and customize it to your needs. To-that-end we include links to the official proxy documentation +throughout this documentation and in the [See Also](#see-also) section.* + +## Introduction + +As [SWAG] is a [NGINX] proxy with curated configurations, integration of __Authelia__ with [SWAG] is very easy and you +only need to enabled two includes. + +*__Note:__ All paths in this guide are the locations inside the container. You will have to either edit the files within +the container or adapt the path to the path you have mounted the relevant container path to.* + +## Requirements + +[SWAG] supports the required [NGINX](nginx.md#requirements) requirements for __Authelia__ out-of-the-box. + +## Trusted Proxies + +*__Important:__ You should read the [Forwarded Headers] section and this section as part of any proxy configuration. +Especially if you have never read it before.* + +To configure trusted proxies for [SWAG] see the [NGINX] section on [Trusted Proxies](nginx.md#trusted-proxies). +Adapting this to [SWAG] is beyond the scope of this documentation. + +## Prerequisite Steps + +These steps must be followed regardless of the choice of [subdomain](#subdomain-steps) or [subpath](#subpath-steps). + +1. Deploy __Authelia__ to your docker network with the `container_name` of `authelia` and ensure it's listening on the +   default port and you have not configured the __Authelia__ server TLS settings. + +## Subdomain Steps + +In the server configuration for the application you want to protect: + +1. Edit the `/config/nginx/proxy-confs/` file for the application you wish to protect. +2. Uncomment the `#include /config/nginx/authelia-server.conf;` line which should be within the `server` block +   but not inside any `location` blocks. +3. Uncomment the `#include /config/nginx/authelia-location.conf;` line which should be within the applications +   `location` block. + +### Example + +```nginx +server { +    listen 443 ssl; +    listen [::]:443 ssl; + +    server_name heimdall.*; + +    include /config/nginx/ssl.conf; + +    client_max_body_size 0; + +    # Authelia: Step 1. +    include /config/nginx/authelia-server.conf; + +    location / { +        # Authelia: Step 2. +        include /config/nginx/authelia-location.conf; + +        include /config/nginx/proxy.conf; +        resolver 127.0.0.11 valid=30s; +        set $upstream_app heimdall; +        set $upstream_port 443; +        set $upstream_proto https; +        proxy_pass $upstream_proto://$upstream_app:$upstream_port; +    } +} +``` + +## Subpath Steps + +*__Note:__ Steps 1 and 2 only need to be done once, even if you wish to protect multiple applications.* + +1. Edit `/config/nginx/proxy-confs/default`. +2. Uncomment the `#include /config/nginx/authelia-server.conf;` line. +3. Edit the `/config/nginx/proxy-confs/` file for the application you wish to protect. +4. Uncomment the `#include /config/nginx/authelia-location.conf;` line which should be within the applications +   `location` block. + +### Example + +```nginx +location ^~ /bazarr/ { +    # Authelia: Step 4. +    include /config/nginx/authelia-location.conf; + +    include /config/nginx/proxy.conf; +    resolver 127.0.0.11 valid=30s; +    set $upstream_app bazarr; +    set $upstream_port 6767; +    set $upstream_proto http; +    proxy_pass $upstream_proto://$upstream_app:$upstream_port; + +    proxy_set_header Upgrade $http_upgrade; +    proxy_set_header Connection "Upgrade"; +} +``` + +## See Also + +* [Authelia NGINX Integration Documentation](nginx.md) +* [LinuxServer.io Setting Up Authelia With SWAG Documentation / Blog Post](https://www.linuxserver.io/blog/2020-08-26-setting-up-authelia) +* [NGINX ngx_http_auth_request_module Module Documentation](https://nginx.org/en/docs/http/ngx_http_auth_request_module.html) +* [Forwarded Headers] + +[SWAG]: https://docs.linuxserver.io/general/swag +[NGINX]: https://www.nginx.com/ +[Forwarded Headers]: fowarded-headers diff --git a/docs/content/en/integration/proxies/traefik.md b/docs/content/en/integration/proxies/traefik.md new file mode 100644 index 000000000..b8b6e87d8 --- /dev/null +++ b/docs/content/en/integration/proxies/traefik.md @@ -0,0 +1,499 @@ +--- +title: "Traefik" +description: "An integration guide for Authelia and the Traefik reverse proxy" +lead: "A guide on integrating Authelia with the Traefik reverse proxy." +date: 2022-03-20T20:23:41+11:00 +draft: false +images: [] +menu: +  integration: +    parent: "proxies" +weight: 370 +toc: true +aliases: +  - /i/traefik +  - /docs/deployment/supported-proxies/traefik2.x.html +--- + +[Traefik] is a reverse proxy supported by __Authelia__. + +*__Important:__ When using these guides it's important to recognize that we cannot provide a guide for every possible +method of deploying a proxy. These guides show a suggested setup only and you need to understand the proxy +configuration and customize it to your needs. To-that-end we include links to the official proxy documentation +throughout this documentation and in the [See Also](#see-also) section.* + +## Requirements + +You need the following to run __Authelia__ with [Traefik]: + +* [Traefik] [v2.0.0](https://github.com/traefik/traefik/releases/tag/v2.0.0) or greater +  (a guide exists for 1.x [here](traefikv1.md)) +* [Traefik] [v2.4.1](https://github.com/traefik/traefik/releases/tag/v2.4.1) or greater if you wish to use +  [basic authentication](#basic-authentication) + +## Trusted Proxies + +*__Important:__ You should read the [Forwarded Headers] section and this section as part of any proxy configuration. +Especially if you have never read it before.* + +*__Important:__ The included example is __NOT__ meant for production use. It's used expressly as an example to showcase +how you can configure multiple IP ranges. You should customize this example to fit your specific architecture and needs. +You should only include the specific IP address ranges of the trusted proxies within your architecture and should not +trust entire subnets unless that subnet only has trusted proxies and no other services.* + +[Traefik] by default doesn't trust any other proxies requiring explicit configuration of which proxies are trusted +and removes potentially fabricated headers that are likely to lead to security issues, and it is difficult to configure +this incorrectly. This is an important security feature that is common with proxies with good security practices. + +In the example we have four commented lines which configure `trustedIPs` which show an example on adding the following +networks to the trusted proxy list in [Traefik]: + +* 10.0.0.0/8 +* 172.16.0.0/16 +* 192.168.0.0/16 +* fc00::/7 + +See the [Entry Points](https://doc.traefik.io/traefik/routing/entrypoints) documentation for more information. + +## Configuration + +Below you will find commented examples of the following docker deployment: + +* [Traefik] +* Authelia portal +* Protected endpoint (Nextcloud) +* Protected endpoint with [Authorization] header for basic authentication (Heimdall) + +The below configuration looks to provide examples of running [Traefik] 2.x with labels to protect your endpoint +(Nextcloud in this case). + +Please ensure that you also setup the respective [ACME configuration](https://docs.traefik.io/https/acme/) for your +[Traefik] setup as this is not covered in the example below. + +### Docker Compose + +This is an example configuration using [docker compose] labels: + +##### docker-compose.yml + +```yaml +version: "3.8" +networks: +  net: +    driver: bridge +services: +  traefik: +    container_name: traefik +    image: traefik:v2.6 +    restart: unless-stopped +    command: +      - '--api=true' +      - '--api.dashboard=true' +      - '--api.insecure=false' +      - '--pilot.dashboard=false' +      - '--global.sendAnonymousUsage=false' +      - '--global.checkNewVersion=false' +      - '--log=true' +      - '--log.level=DEBUG' +      - '--log.filepath=/config/traefik.log' +      - '--providers.docker=true' +      - '--providers.docker.exposedByDefault=false' +      - '--entryPoints.http=true' +      - '--entryPoints.http.address=:8080/tcp' +      - '--entryPoints.http.http.redirections.entryPoint.to=https' +      - '--entryPoints.http.http.redirections.entryPoint.scheme=https' +      ## Please see the Forwarded Header Trust section of the Authelia Traefik Integration documentation. +      # - '--entryPoints.http.forwardedHeaders.trustedIPs=10.0.0.0/8,172.16.0.0/16,192.168.0.0/16,fc00::/7' +      # - '--entryPoints.http.proxyProtocol.trustedIPs=10.0.0.0/8,172.16.0.0/16,192.168.0.0/16,fc00::/7' +      - '--entryPoints.http.forwardedHeaders.insecure=false' +      - '--entryPoints.http.proxyProtocol.insecure=false' +      - '--entryPoints.https=true' +      - '--entryPoints.https.address=:8443/tcp' +      ## Please see the Forwarded Header Trust section of the Authelia Traefik Integration documentation. +      # - '--entryPoints.https.forwardedHeaders.trustedIPs=10.0.0.0/8,172.16.0.0/16,192.168.0.0/16,fc00::/7' +      # - '--entryPoints.https.proxyProtocol.trustedIPs=10.0.0.0/8,172.16.0.0/16,192.168.0.0/16,fc00::/7' +      - '--entryPoints.https.forwardedHeaders.insecure=false' +      - '--entryPoints.https.proxyProtocol.insecure=false' +    networks: +      net: {} +    ports: +      - "80:8080" +      - "443:8443" +    volumes: +      - /var/run/docker.sock:/var/run/docker.sock +      - ${PWD}/data/traefik:/config +    labels: +      - 'traefik.enable=true' +      - 'traefik.http.routers.api.rule=Host(`traefik.example.com`)' +      - 'traefik.http.routers.api.entryPoints=https' +      - 'traefik.http.routers.api.tls=true' +      - 'traefik.http.routers.api.service=api@internal' +      - 'traefik.http.routers.api.middlewares=authelia@docker' +  authelia: +    container_name: authelia +    image: authelia/authelia +    restart: unless-stopped +    networks: +      net: {} +    expose: +      - 9091 +    volumes: +      - ${PWD}/data/authelia/config:/config +    environment: +      TZ: "Australia/Melbourne" +    labels: +      - 'traefik.enable=true' +      - 'traefik.http.routers.authelia.rule=Host(`auth.example.com`)' +      - 'traefik.http.routers.authelia.entryPoints=https' +      - 'traefik.http.routers.authelia.tls=true' +      - 'traefik.http.middlewares.authelia.forwardAuth.address=http://authelia:9091/api/verify?rd=https%3A%2F%2Fauth.example.com%2F' +      - 'traefik.http.middlewares.authelia.forwardAuth.trustForwardHeader=true' +      - 'traefik.http.middlewares.authelia.forwardAuth.authResponseHeaders=Remote-User,Remote-Groups,Remote-Name,Remote-Email' +      - 'traefik.http.middlewares.authelia-basic.forwardAuth.address=http://authelia:9091/api/verify?auth=basic' +      - 'traefik.http.middlewares.authelia-basic.forwardAuth.trustForwardHeader=true' +      - 'traefik.http.middlewares.authelia-basic.forwardAuth.authResponseHeaders=Remote-User,Remote-Groups,Remote-Name,Remote-Email' +  nextcloud: +    container_name: nextcloud +    image: linuxserver/nextcloud +    restart: unless-stopped +    networks: +      net: {} +    expose: +      - 443 +    volumes: +      - ${PWD}/data/nextcloud/config:/config +      - ${PWD}/data/nextcloud/data:/data +    environment: +      PUID: "1000" +      PGID: "1000" +      TZ: "Australia/Melbourne" +    labels: +      - 'traefik.enable=true' +      - 'traefik.http.routers.nextcloud.rule=Host(`nextcloud.example.com`)' +      - 'traefik.http.routers.nextcloud.entryPoints=https' +      - 'traefik.http.routers.nextcloud.tls=true' +      - 'traefik.http.routers.nextcloud.middlewares=authelia@docker' +  heimdall: +    container_name: heimdall +    image: linuxserver/heimdall +    restart: unless-stopped +    networks: +      net: {} +    expose: +      - 443 +    volumes: +      - ${PWD}/data/heimdall/config:/config +    environment: +      PUID: "1000" +      PGID: "1000" +      TZ: "Australia/Melbourne" +    labels: +      - 'traefik.enable=true' +      - 'traefik.http.routers.heimdall.rule=Host(`heimdall.example.com`)' +      - 'traefik.http.routers.heimdall.entryPoints=https' +      - 'traefik.http.routers.heimdall.tls=true' +      - 'traefik.http.routers.heimdall.middlewares=authelia-basic@docker' +``` + +### YAML + +This example uses a `docker-compose.yml` similar to the one above however it has two major differences: + +1. A majority of the configuration is in YAML instead of the `labels` section of the `docker-compose.yml` file. +2. It connects to __Authelia__ over TLS with client certificates which ensures that [Traefik] is a proxy +   authorized to communicate with __Authelia__. This expects that the +   [Server TLS](../../configuration/miscellaneous/server.md#tls) section is configured correctly. +   * The client certificates can easily be disabled by commenting the `cert` and `key` options in the `http.middlewares` +     section for the `forwardAuth` middlewares and the `certificates` in the `http.serversTransports` section. +   * The TLS communication can be disabled by commenting the entire `tls` section in the `http.middlewares` section for +     all `forwardAuth` middlewares, adjusting the `authelia` router in the `http.routers` section to use the +     `authelia-net@docker` service, and commenting the `authelia` service in the `http.service` section. + +##### docker-compose.yml + +```yaml +version: "3.8" +networks: +  net: +    driver: bridge +services: +  traefik: +    container_name: traefik +    image: traefik:v2.6 +    restart: unless-stopped +    command: +      - '--api=true' +      - '--api.dashboard=true' +      - '--api.insecure=false' +      - '--pilot.dashboard=false' +      - '--global.sendAnonymousUsage=false' +      - '--global.checkNewVersion=false' +      - '--log=true' +      - '--log.level=DEBUG' +      - '--log.filepath=/config/traefik.log' +      - '--providers.docker=true' +      - '--providers.docker.exposedByDefault=false' +      - '--providers.file=true' +      - '--providers.file.watch=true' +      - '--providers.file.directory=/config/dynamic' +      - '--entryPoints.http=true' +      - '--entryPoints.http.address=:8080/tcp' +      - '--entryPoints.http.http.redirections.entryPoint.to=https' +      - '--entryPoints.http.http.redirections.entryPoint.scheme=https' +      - '--entryPoints.https=true' +      - '--entryPoints.https.address=:8443/tcp' +    networks: +      net: {} +    ports: +      - "80:8080" +      - "443:8443" +    volumes: +      - /var/run/docker.sock:/var/run/docker.sock +      - ${PWD}/data/traefik/config:/config +      - ${PWD}/data/traefik/certificates:/certificates +    labels: +      - 'traefik.enable=true' +  authelia: +    container_name: authelia +    image: authelia/authelia +    restart: unless-stopped +    networks: +      net: {} +    expose: +      - 9091 +    volumes: +      - ${PWD}/data/authelia/config:/config +      - ${PWD}/data/authelia/certificates:/certificates +    environment: +      TZ: "Australia/Melbourne" +    labels: +      - 'traefik.enable=true' +  nextcloud: +    container_name: nextcloud +    image: linuxserver/nextcloud +    restart: unless-stopped +    networks: +      net: {} +    expose: +      - 443 +    volumes: +      - ${PWD}/data/nextcloud/config:/config +      - ${PWD}/data/nextcloud/data:/data +    environment: +      PUID: "1000" +      PGID: "1000" +      TZ: "Australia/Melbourne" +    labels: +      - 'traefik.enable=true' +  heimdall: +    container_name: heimdall +    image: linuxserver/heimdall +    restart: unless-stopped +    networks: +      net: {} +    expose: +      - 443 +    volumes: +      - ${PWD}/data/heimdall/config:/config +    environment: +      PUID: "1000" +      PGID: "1000" +      TZ: "Australia/Melbourne" +    labels: +      - 'traefik.enable=true' +  whoami: +    container_name: whoami +    image: traefik/whoami:latest +    restart: unless-stopped +    networks: +      net: {} +    expose: +      - 80 +    environment: +      TZ: "Australia/Melbourne" +    labels: +      - "traefik.enable=true" + +``` + +##### traefik.yml + +This file is part of the dynamic configuration and should have the path +`${PWD}/data/traefik/config/dynamic/traefik.yml`. Please see the [Traefik] service and the volume that mounts the +`${PWD}/data/traefik/config` in the docker compose above. + +```yaml +entryPoints: +  web: +    proxyProtocol: +      insecure: false +      trustedIPs: [] +    forwardedHeaders: +      insecure: false +      trustedIPs: [] +  websecure: +    proxyProtocol: +      insecure: false +      trustedIPs: [] +    forwardedHeaders: +      insecure: false +      trustedIPs: [] +tls: +  options: +    modern: +      minVersion: "VersionTLS13" +    intermediate: +      minVersion: "VersionTLS12" +      cipherSuites: +        - "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" +        - "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" +        - "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" +        - "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384" +        - "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305" +        - "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305" +http: +  middlewares: +    authelia: +      forwardAuth: +        address: https://authelia:9091/api/verify?rd=https%3A%2F%2Fauth.example.com%2F +        trustForwardHeader: true +        authResponseHeaders: +          - "Remote-User" +          - "Remote-Groups" +          - "Remote-Email" +          - "Remote-Name" +        tls: +          ca: /certificates/ca.public.crt +          cert: /certificates/traefik.public.crt +          key: /certificates/traefik.private.pem +    authelia-basic: +      forwardAuth: +        address: https://authelia:9091/api/verify?auth=basic +        trustForwardHeader: true +        authResponseHeaders: +          - "Remote-User" +          - "Remote-Groups" +          - "Remote-Email" +          - "Remote-Name" +        tls: +          ca: /certificates/ca.public.crt +          cert: /certificates/traefik.public.crt +          key: /certificates/traefik.private.pem +  routers: +    traefik: +      rule: Host(`traefik.example.com`) +      entryPoints: websecure +      service: api@internal +      middlewares: +        - authelia@file +      tls: +        options: modern@file +        certResolver: default +        domains: +          - main: "example.com" +            sans: +              - "*.example.com" +    whoami: +      rule: Host(`whoami.example.com`) +      entryPoints: websecure +      service: whoami-net@docker +      middlewares: +        - authelia@file +      tls: +        options: modern@file +        certResolver: default +        domains: +          - main: "example.com" +            sans: +              - "*.example.com" +    nextcloud: +      rule: Host(`nextcloud.example.com`) +      entryPoints: websecure +      service: nextcloud-net@docker +      middlewares: +        - authelia@file +      tls: +        options: modern@file +        certResolver: default +        domains: +          - main: "example.com" +            sans: +              - "*.example.com" +    heimdall: +      rule: Host(`heimdall.example.com`) +      entryPoints: websecure +      service: heimdall-net@docker +      middlewares: +        - authelia-basic@file +      tls: +        options: modern@file +        certResolver: default +        domains: +          - main: "example.com" +            sans: +              - "*.example.com" +    authelia: +      rule: Host(`auth.example.com`) +      entryPoints: websecure +      service: authelia@file +      tls: +        options: modern@file +        certResolver: default +        domains: +          - main: "example.com" +            sans: +              - "*.example.com" +  services: +    authelia: +      loadBalancer: +        servers: +          - url: https://authelia:9091/ +        serversTransport: autheliaMutualTLS +  serversTransports: +    autheliaMutualTLS: +      certificates: +        - certFile: /certificates/traefik.public.crt +          keyFile: /certificates/traefik.private.pem +      rootCAs: +        - /certificates/ca.public.crt +``` + +## FAQ + +### Basic Authentication + +Authelia provides the means to be able to authenticate your first factor via the [Proxy-Authorization] header, this +is compatible with [Traefik]. + +If you have a use-case which requires the use of the [Authorization] header/basic authentication login prompt you can +call Authelia's `/api/verify?auth=basic` endpoint to force a switch to the [Authorization] header. + +### Middleware authelia@docker not found + +If [Traefik] and __Authelia__ are defined in different docker compose stacks you may experience an issue where [Traefik] +complains that: `middleware authelia@docker not found`. + +This can be avoided a couple different ways: + +1. Ensure __Authelia__ container is up before [Traefik] is started: +   * Utilise the [depends_on](https://docs.docker.com/compose/compose-file/#depends_on) option +2. Define the __Authelia__ middleware on your [Traefik] container. See the below example. + +```yaml +- 'traefik.http.middlewares.authelia.forwardAuth.address=http://authelia:9091/api/verify?rd=https%3A%2F%2Fauth.example.com%2F' +- 'traefik.http.middlewares.authelia.forwardAuth.trustForwardHeader=true' +- 'traefik.http.middlewares.authelia.forwardAuth.authResponseHeaders=Remote-User,Remote-Groups,Remote-Name,Remote-Email' +``` + +## See Also + +* [Traefik ForwardAuth Documentation](https://doc.traefik.io/traefik/middlewares/http/forwardauth/) +* [Traefik Forwarded Headers Documentation](https://doc.traefik.io/traefik/routing/entrypoints/#forwarded-headers) +* [Traefik Proxy Protocol Documentation](https://doc.traefik.io/traefik/routing/entrypoints/#proxyprotocol) +* [Forwarded Headers] + +[docker compose]: https://docs.docker.com/compose/ +[Traefik]: https://docs.traefik.io/ +[Forwarded Headers]: fowarded-headers +[Authorization]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization +[Proxy-Authorization]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Proxy-Authorization diff --git a/docs/content/en/integration/proxies/traefikv1.md b/docs/content/en/integration/proxies/traefikv1.md new file mode 100644 index 000000000..bfe0b82f3 --- /dev/null +++ b/docs/content/en/integration/proxies/traefikv1.md @@ -0,0 +1,167 @@ +--- +title: "Traefik v1" +description: "An integration guide for Authelia and the Traefik v1 reverse proxy" +lead: "A guide on integrating Authelia with the Traefik reverse proxy." +date: 2022-03-20T20:23:41+11:00 +draft: false +images: [] +menu: +  integration: +    parent: "proxies" +weight: 371 +toc: true +aliases: +  - /docs/deployment/supported-proxies/traefik1.x.html +--- + +[Traefik] v1 is a reverse proxy supported by __Authelia__. + +*__Important:__ When using these guides it's important to recognize that we cannot provide a guide for every possible +method of deploying a proxy. These guides show a suggested setup only and you need to understand the proxy +configuration and customize it to your needs. To-that-end we include links to the official proxy documentation +throughout this documentation and in the [See Also](#see-also) section.* + +## Trusted Proxies + +*__Important:__ You should read the [Forwarded Headers] section and this section as part of any proxy configuration. +Especially if you have never read it before.* + +*__Important:__ The included example is __NOT__ meant for production use. It's used expressly as an example to showcase +how you can configure multiple IP ranges. You should customize this example to fit your specific architecture and needs. +You should only include the specific IP address ranges of the trusted proxies within your architecture and should not +trust entire subnets unless that subnet only has trusted proxies and no other services.* + +[Traefik] by default doesn't trust any other proxies requiring explicit configuration of which proxies are trusted +and removes potentially fabricated headers that are likely to lead to security issues, and it is difficult to configure +this incorrectly. This is an important security feature that is common with proxies with good security practices. + +In the example we have four commented lines which configure `TrustedIPs` which show an example on adding the following +networks to the trusted proxy list in [Traefik]: + +* 10.0.0.0/8 +* 172.16.0.0/16 +* 192.168.0.0/16 +* fc00::/7 + +## Configuration + +Below you will find commented examples of the following docker deployment: + +* [Traefik] 1.x +* Authelia portal +* Protected endpoint (Nextcloud) +* Protected endpoint with `Authorization` header for basic authentication (Heimdall) + +The below configuration looks to provide examples of running [Traefik] v1 with labels to protect your endpoint +(Nextcloud in this case). + +Please ensure that you also setup the respective [ACME](https://docs.traefik.io/v1.7/configuration/acme/) configuration +for your [Traefik] setup as this is not covered in the example below. + +### Basic Authentication + +Authelia provides the means to be able to authenticate your first factor via the `Proxy-Authorization` header. +Given that this is not compatible with [Traefik] 1.x you can call the __Authelia__ `/api/verify` endpoint with the +`auth=basic` query parameter to force a switch to the `Authentication` header. + +##### docker-compose.yml + +```yaml +version: '3' + +networks: +  net: +    driver: bridge +services: +  traefik: +    image: traefik:v1.7.34-alpine +    container_name: traefik +    volumes: +      - /var/run/docker.sock:/var/run/docker.sock +    networks: +      - net +    labels: +      - 'traefik.frontend.rule=Host:traefik.example.com' +      - 'traefik.port=8081' +    ports: +      - 80:80 +      - 443:443 +      - 8081:8081 +    restart: unless-stopped +    command: +      - '--api' +      - '--api.entrypoint=api' +      - '--docker' +      - '--defaultEntryPoints=https' +      - '--logLevel=DEBUG' +      - '--traefikLog=true' +      - '--traefikLog.filepath=/var/log/traefik.log' +      - '--entryPoints=Name:http Address::80' +      - '--entryPoints=Name:https Address::443 TLS' +      ## See the Forwarded Header Trust section. Comment the above two lines, then uncomment and customize the next two lines to configure the TrustedIPs. +      # - '--entryPoints=Name:http Address::80 ForwardedHeaders.TrustedIPs:10.0.0.0/8,172.16.0.0/16,192.168.0.0/16,fc00::/7 ProxyProtocol.TrustedIPs:10.0.0.0/8,172.16.0.0/16,192.168.0.0/16,fc00::/7' +      # - '--entryPoints=Name:https Address::443 TLS ForwardedHeaders.TrustedIPs:10.0.0.0/8,172.16.0.0/16,192.168.0.0/16,fc00::/7 ProxyProtocol.TrustedIPs:10.0.0.0/8,172.16.0.0/16,192.168.0.0/16,fc00::/7' +      - '--entryPoints=Name:api Address::8081' +  authelia: +    image: authelia/authelia +    container_name: authelia +    volumes: +      - /path/to/authelia:/config +    networks: +      - net +    labels: +      - 'traefik.frontend.rule=Host:auth.example.com' +    expose: +      - 9091 +    restart: unless-stopped +    environment: +      - TZ=Australia/Melbourne +  nextcloud: +    image: linuxserver/nextcloud +    container_name: nextcloud +    volumes: +      - /path/to/nextcloud/config:/config +      - /path/to/nextcloud/data:/data +    networks: +      - net +    labels: +      - 'traefik.frontend.rule=Host:nextcloud.example.com' +      - 'traefik.frontend.auth.forward.address=http://authelia:9091/api/verify?rd=https://auth.example.com/' +      - 'traefik.frontend.auth.forward.trustForwardHeader=true' +      - 'traefik.frontend.auth.forward.authResponseHeaders=Remote-User,Remote-Groups,Remote-Name,Remote-Email' +    expose: +      - 443 +    restart: unless-stopped +    environment: +      - PUID=1000 +      - PGID=1000 +      - TZ=Australia/Melbourne +  heimdall: +    image: linuxserver/heimdall +    container_name: heimdall +    volumes: +      - /path/to/heimdall/config:/config +    networks: +      - net +    labels: +      - 'traefik.frontend.rule=Host:heimdall.example.com' +      - 'traefik.frontend.auth.forward.address=http://authelia:9091/api/verify?auth=basic' +      - 'traefik.frontend.auth.forward.trustForwardHeader=true' +      - 'traefik.frontend.auth.forward.authResponseHeaders=Remote-User,Remote-Groups,Remote-Name,Remote-Email' +    expose: +      - 443 +    restart: unless-stopped +    environment: +      - PUID=1000 +      - PGID=1000 +      - TZ=Australia/Melbourne +``` + +## See Also + +* [Traefik v1 Documentation](https://doc.traefik.io/traefik/v1.7/) +* [Traefik v1 All Available Options](https://doc.traefik.io/traefik/v1.7/configuration/entrypoints/#all-available-options) +* [Forwarded Headers] + +[Traefik]: https://docs.traefik.io/v1.7/ +[Forwarded Headers]: fowarded-headers diff --git a/docs/content/en/integration/trusted-header-sso/_index.md b/docs/content/en/integration/trusted-header-sso/_index.md new file mode 100644 index 000000000..73fbc7f4b --- /dev/null +++ b/docs/content/en/integration/trusted-header-sso/_index.md @@ -0,0 +1,9 @@ +--- +title : "Trusted Header SSO" +description: "Trusted Header SSO Integration" +lead: "" +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +weight: 400 +--- diff --git a/docs/content/en/integration/trusted-header-sso/introduction.md b/docs/content/en/integration/trusted-header-sso/introduction.md new file mode 100644 index 000000000..c843d5033 --- /dev/null +++ b/docs/content/en/integration/trusted-header-sso/introduction.md @@ -0,0 +1,104 @@ +--- +title: "Trusted Header SSO" +description: "Trusted Header SSO Integration" +lead: "An introduction into integrating Authelia with an application which implements authentication via trusted headers." +date: 2022-05-15T13:52:27+10:00 +draft: false +images: [] +menu: +  integration: +    parent: "trusted-header-sso" +weight: 410 +toc: true +--- + +Authelia will respond to requests via the forward authentication flow with specific headers that can be utilized by some +applications to perform authentication. This section of the documentation discusses how to integrate these products with +this model. + +Please see the [proxy integration](../proxies/introduction.md) for more information on how to return these headers to +the application. + +## Terminology + +This authentication method is referred to by many names; notably `trusted header authentication`, +`header authentication`, `header sso`, and probably many more. + +## Specifics + +The headers are not intended to be returned to a browser, instead these headers are meant for internal communications +only. These headers are returned to the reverse proxy and then injected into the request which the reverse proxy makes +to the application's http endpoints. + +This allows these applications to decide if they wish to trust these headers, and if they do trust them, perform some +form of authentication flow. This flow usually takes the form of automatically logging users into the application, +however it can vary depending on how the application decides to do this. + +## Response Headers + +The following table represents the response headers that Authelia's `/api/verify` endpoint returns which can be +forwarded over a trusted network via the reverse proxy when using the forward authentication flow. + +|    Header     |      Description / Notes       |      Example       | +|:-------------:|:------------------------------:|:------------------:| +|  Remote-User  |       The users username       |        john        | +| Remote-Groups | The groups the user belongs to |     admin,dev      | +|  Remote-Name  |     The users display name     |     John Smith     | +| Remote-Email  |    The users email address     | jsmith@example.com | + +## Forwarding the Response Headers + +It's essential if you wish to utilize the trusted header single sign-on flow that you forward the +[response headers](#response-headers) via the reverse proxy to the backend application, not the browser. Please refer to +the relevant [proxy documentation](../proxies/introduction.md) for more information. + +## Trusted Remote Networks + +Several applications which implement this authentication method allow or require you to configure a list of IP addresses +which are trusted to deliver these headers. It is our recommendation that you configure this even if it is optional. + +The application itself will have a way to detect this IP address and most implementations utilize the TCP source address +as this is the most appropriate. This is the TCP source address of your *proxy*, it is __not__ the TCP source address of +Authelia. This is because headers may be returned by Authelia to the proxy, however the backend application is *not +able* to determine this reliably, instead the TCP source address of the request to the application is used, which is +made by the reverse proxy. This also means your proxy must ensure only Authelia is setting these headers, and any other +headers are never forwarded to the backend and are instead replaced by the Authelia headers. + +In some environments the TCP source address of the proxy may be difficult to determine. For example in a docker +environment a container may be a member of multiple networks. This means the TCP source address that you must use is the +IP address of the proxy on the network that both the proxy and the application are members of. In this environment it +is also imperative that you utilize a static IP for the proxy container as configuring an entire docker network is not +considered secure as any compromised container may be able to be used to bypass authentication for any container +configured to use this authentication flow. + +### Docker + +In a [Docker] environment a [container] may be a member of multiple networks. This means the TCP source address that you +must use is the IP address of the proxy on the [Docker Network] that both the proxy and the application are members of. +In this environment it is also imperative that you utilize a static IP for the proxy [container] as configuring an +entire [Docker Network] is not considered secure as any compromised [container] may be able to be used to bypass +authentication for any [container] configured to use this authentication flow. + +The following command will print out the IP for a container named `traefik` on the `authelia` network: + +```bash +docker inspect -f '{{.NetworkSettings.Networks.authelia.IPAddress}}' traefik +``` + +The following command will print out all network names and the associated IP address for a container named `traefik`: + +```bash +docker inspect -f '{{range $network, $config := .NetworkSettings.Networks}}{{ $network }}: {{ $config.IPAddress }} {{end}}' traefik +``` + +### Kubernetes + +In a [Kubernetes] the TCP source address is likely the [Pod] IP. Generally these cannot be static and you should instead +ensure a [Pod] that is configured to utilize this method is secured via one of the various means available such as a +service mesh. Configuring any of these security methods is well beyond the scope of this document. + +[Docker]: https://docker.com +[Kubernetes]: https://kubernetes.io/ +[Pod]: https://kubernetes.io/docs/concepts/workloads/pods/ +[container]: https://www.docker.com/resources/what-container/ +[Docker Network]: https://docs.docker.com/network/ diff --git a/docs/content/en/integration/trusted-header-sso/jira/index.md b/docs/content/en/integration/trusted-header-sso/jira/index.md new file mode 100644 index 000000000..4347ff845 --- /dev/null +++ b/docs/content/en/integration/trusted-header-sso/jira/index.md @@ -0,0 +1,49 @@ +--- +title: "Jira" +description: "Trusted Header SSO Integration for Jira" +lead: "" +date: 2022-05-16T21:15:52+10:00 +draft: false +images: [] +menu: +  integration: +    parent: "trusted-header-sso" +weight: 420 +toc: true +community: true +aliases: +  - /docs/community/using-remote-user-header-for-sso-with-jira.html +--- + +## Introduction + +This is a guide on integration of __Authelia__ and [Jira] via the trusted header SSO authentication. + +As with all guides in this section it's important you read the [introduction](../introduction.md) first. + +## Tested Versions + +* Authelia: v4.35.5 +* Jira: Unknown +* EasySSO: Unknown + +## Before You Begin + +This example makes the following assumptions: + +* The user accounts with the same names already exist in [Jira]. +* You have purchased the third-party plugin from the [Atlassian marketplace](https://marketplace.atlassian.com/apps/1212581/easy-sso-jira-kerberos-ntlm-saml?hosting=server&tab=overview) + +## Configuration + +To configure [Jira] to trust the `Remote-User` and `Remote-Email` header do the following: + +1. Visit the Easy SSO plugin settings +2. Under HTTP configure the `Remote-User` header +3. Check the `Username` checkbox + +## See Also + +* [EasySSO Documentation](https://techtime.co.nz/display/TECHTIME/EasySSO#documentation-area) + +[Jira]: https://www.atlassian.com/software/jira diff --git a/docs/content/en/integration/trusted-header-sso/organizr/index.md b/docs/content/en/integration/trusted-header-sso/organizr/index.md new file mode 100644 index 000000000..37ddd1ea3 --- /dev/null +++ b/docs/content/en/integration/trusted-header-sso/organizr/index.md @@ -0,0 +1,56 @@ +--- +title: "Organizr" +description: "Trusted Header SSO Integration for Organizr" +lead: "" +date: 2022-05-16T16:34:50+10:00 +draft: false +images: [] +menu: +  integration: +    parent: "trusted-header-sso" +weight: 420 +toc: true +community: true +--- + +## Introduction + +This is a guide on integration of __Authelia__ and [Organizr] via the trusted header SSO authentication. + +As with all guides in this section it's important you read the [introduction](../introduction.md) first. + +## Tested Versions + +* Authelia: v4.35.5 +* Organizr: 2.1.1890 + +## Before You Begin + +This example makes the following assumptions: + +* __Application Root URL:__ `https://organizr.example.com` +* __Authelia Root URL:__ `https://auth.example.com` +* __Reverse Proxy IP:__ `172.16.0.1` + +## Configuration + +To configure [Organizr] to trust the `Remote-User` and `Remote-Email` header do the following: + +1. Visit System Settings +2. Visit Main +3. Visit Auth Proxy +4. Fill in the following information: +   1. Auth Proxy: `Enabled` +   2. Auth Proxy Whitelist: `172.16.0.1` +   3. Auth Proxy Header Name: `Remote-User` +   4. Auth Proxy Header Name for Email: `Remote-Email` +   5. Override Logout: `Enabled` +   6. Logout URL: `https://auth.example.com/logout` + +{{< figure src="organizr.png" alt="Organizr" width="736" style="padding-right: 10px" >}} + +## See Also + +[Organizr] does not appear to have documentation around their `Auth Proxy` configuration. + +[Organizr]: https://organizr.app/ diff --git a/docs/content/en/integration/trusted-header-sso/organizr/organizr.png b/docs/content/en/integration/trusted-header-sso/organizr/organizr.png Binary files differnew file mode 100644 index 000000000..588f97eca --- /dev/null +++ b/docs/content/en/integration/trusted-header-sso/organizr/organizr.png diff --git a/docs/content/en/overview/_index.md b/docs/content/en/overview/_index.md new file mode 100644 index 000000000..458611aa0 --- /dev/null +++ b/docs/content/en/overview/_index.md @@ -0,0 +1,8 @@ +--- +title : "Overview" +description: "Authelia Overview" +lead: "" +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +--- diff --git a/docs/content/en/overview/authentication/_index.md b/docs/content/en/overview/authentication/_index.md new file mode 100644 index 000000000..dda7a5ce6 --- /dev/null +++ b/docs/content/en/overview/authentication/_index.md @@ -0,0 +1,9 @@ +--- +title : "Authentication" +description: "Authentication" +lead: "" +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +weight: 200 +--- diff --git a/docs/images/1FA.png b/docs/content/en/overview/authentication/first-factor/1FA.png Binary files differindex e28a104da..e28a104da 100644 --- a/docs/images/1FA.png +++ b/docs/content/en/overview/authentication/first-factor/1FA.png diff --git a/docs/content/en/overview/authentication/first-factor/index.md b/docs/content/en/overview/authentication/first-factor/index.md new file mode 100644 index 000000000..431134e99 --- /dev/null +++ b/docs/content/en/overview/authentication/first-factor/index.md @@ -0,0 +1,24 @@ +--- +title: "First Factor" +description: "Authelia utilizes the standard username and password combination for first factor authentication." +lead: "Authelia utilizes the standard username and password combination for first factor authentication." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  overview: +    parent: "authentication" +weight: 220 +toc: true +aliases: +  - /docs/features/first-factor.html +--- + +{{< figure src="1FA.png" caption="An example of the first factor sign in portal" alt="First Factor Authentication View" width=400 >}} + +*__IMPORTANT:__ This is currently the only method available for first factor authentication.* + +Authelia supports several kind of user databases: + +* An LDAP server like OpenLDAP, OpenAM, Active Directory etc. +* A YAML file diff --git a/docs/content/en/overview/authentication/introduction.md b/docs/content/en/overview/authentication/introduction.md new file mode 100644 index 000000000..11183c284 --- /dev/null +++ b/docs/content/en/overview/authentication/introduction.md @@ -0,0 +1,35 @@ +--- +title: "Authentication" +description: "An overview of a authentication." +lead: "An overview of a authentication." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  overview: +    parent: "prologue" +weight: 210 +toc: false +aliases: +  - /docs/features/2fa/ +--- + +Multi-Factor Authentication or MFA as a concept is separated into three major categories. These categories are: + +* something you know +* something you have +* something you are + +Modern best security practice dictates that using multiple of these categories is necessary for security. Users are +unreliable and simple usernames and passwords are not sufficient for security. + +__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* +  categorization. +* 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. + +In addition to this Authelia can apply authorization policies to individual website resources which restrict which +identities can access which resources from a given remote address. These policies can require 1FA, 2FA, or outright deny +access depending on the criteria you configure. diff --git a/docs/images/2FA-TOTP.png b/docs/content/en/overview/authentication/one-time-password/2FA-TOTP.png Binary files differindex 9fb637cda..9fb637cda 100644 --- a/docs/images/2FA-TOTP.png +++ b/docs/content/en/overview/authentication/one-time-password/2FA-TOTP.png diff --git a/docs/images/REGISTER-TOTP.png b/docs/content/en/overview/authentication/one-time-password/REGISTER-TOTP.png Binary files differindex 695ab82bf..695ab82bf 100644 --- a/docs/images/REGISTER-TOTP.png +++ b/docs/content/en/overview/authentication/one-time-password/REGISTER-TOTP.png diff --git a/docs/images/google-authenticator.png b/docs/content/en/overview/authentication/one-time-password/google-authenticator.png Binary files differindex b299eee21..b299eee21 100644 --- a/docs/images/google-authenticator.png +++ b/docs/content/en/overview/authentication/one-time-password/google-authenticator.png diff --git a/docs/content/en/overview/authentication/one-time-password/index.md b/docs/content/en/overview/authentication/one-time-password/index.md new file mode 100644 index 000000000..b1f45c864 --- /dev/null +++ b/docs/content/en/overview/authentication/one-time-password/index.md @@ -0,0 +1,43 @@ +--- +title: "One Time Password" +description: "Authelia utilizes one time passwords as one of it's second factor authentication methods." +lead: "Authelia utilizes one time passwords as one of it's second factor authentication methods." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  overview: +    parent: "authentication" +weight: 230 +toc: true +aliases: +  - /docs/features/2fa/one-time-password.html +--- + +__Authelia__ supports time-based one-time password generated by apps like [Google Authenticator]. + +{{< figure src="2FA-TOTP.png" caption="An example of the time-based one time password authentication view" alt="Second Factor OTP Authentication View" width=300 >}} + +After having successfully completed the first factor, select __One-Time Password method__ +option and click on __Register device__ link. This will e-mail you to confirm your identity. + +*NOTE: If you're testing __Authelia__, this e-mail has likely been sent to the mailbox available at https://mail.example.com:8080/* + +Once this validation step is completed, a QR Code gets displayed. + +{{< figure src="REGISTER-TOTP.png" caption="An example of the time-based one time password registration view" alt="Second Factor OTP Registration View" width=400 >}} + +You can then use [Google Authenticator] or an authenticator of your choice to scan the code in order to register your device. + +{{< figure src="google-authenticator.png" caption="The Google Authenticator application" alt="Second Factor OTP Registration View" width=150 >}} + +From now on, you get tokens generated every 30 seconds that +you can use to validate the second factor in __Authelia__. + +## Limitations + +Users currently can only enroll a single TOTP device in __Authelia__. This is standard practice, as a user can obviously +register a second device with the same QR Code. As there is no tangible benefit and it is harder to keep track of +multiple devices it's not a feature we will implement. + +[Google Authenticator]: https://google-authenticator.com/ diff --git a/docs/content/en/overview/authentication/password-policy/index.md b/docs/content/en/overview/authentication/password-policy/index.md new file mode 100644 index 000000000..1d4d6d634 --- /dev/null +++ b/docs/content/en/overview/authentication/password-policy/index.md @@ -0,0 +1,41 @@ +--- +title: "Password Policy" +description: "Authelia implements a password policy feature." +lead: "Authelia implements a password policy feature." +date: 2022-04-12T14:40:22+10:00 +draft: false +images: [] +menu: +  overview: +    parent: "authentication" +weight: 260 +toc: true +aliases: +  - /docs/features/password-policy.html +--- + +Password policy enforces security by requiring the users to use strong passwords. + +Currently, two methods are supported: + +## classic + +This mode of operation allows administrators to set the rules that user passwords must comply with when changing their +password. + +The available options are: + +* Minimum password length +* Require Uppercase +* Require Lowercase +* Require Numbers +* Require Special characters + +{{< figure src="password-policy-classic-1.png" caption="Classic Password Policy" alt="Classic Password Policy" width=400 >}} + +## zxcvbn + +This mode uses [zxcvbn](https://github.com/dropbox/zxcvbn) for password strength checking. In this mode of operation, +the user is not forced to follow any rules. The user is notified if their passwords is weak or strong. + +{{< figure src="password-policy-zxcvbn-1.png" caption="zxcvbn Password Policy" alt="zxcvbn Password Policy" width=400 >}} diff --git a/docs/images/password-policy-classic-1.png b/docs/content/en/overview/authentication/password-policy/password-policy-classic-1.png Binary files differindex 3f844827d..3f844827d 100644 --- a/docs/images/password-policy-classic-1.png +++ b/docs/content/en/overview/authentication/password-policy/password-policy-classic-1.png diff --git a/docs/images/password-policy-zxcvbn-1.png b/docs/content/en/overview/authentication/password-policy/password-policy-zxcvbn-1.png Binary files differindex 1aa2d14ee..1aa2d14ee 100644 --- a/docs/images/password-policy-zxcvbn-1.png +++ b/docs/content/en/overview/authentication/password-policy/password-policy-zxcvbn-1.png diff --git a/docs/images/2FA-PUSH.png b/docs/content/en/overview/authentication/push-notification/2FA-PUSH.png Binary files differindex 550e65935..550e65935 100644 --- a/docs/images/2FA-PUSH.png +++ b/docs/content/en/overview/authentication/push-notification/2FA-PUSH.png diff --git a/docs/images/duo-push-1.jpg b/docs/content/en/overview/authentication/push-notification/duo-push-1.jpg Binary files differindex d1a74a8cb..d1a74a8cb 100644 --- a/docs/images/duo-push-1.jpg +++ b/docs/content/en/overview/authentication/push-notification/duo-push-1.jpg diff --git a/docs/images/duo-push-2.png b/docs/content/en/overview/authentication/push-notification/duo-push-2.png Binary files differindex 23b5d73e3..23b5d73e3 100644 --- a/docs/images/duo-push-2.png +++ b/docs/content/en/overview/authentication/push-notification/duo-push-2.png diff --git a/docs/content/en/overview/authentication/push-notification/index.md b/docs/content/en/overview/authentication/push-notification/index.md new file mode 100644 index 000000000..87e0960dd --- /dev/null +++ b/docs/content/en/overview/authentication/push-notification/index.md @@ -0,0 +1,57 @@ +--- +title: "Duo / Mobile Push" +description: "Authelia utilizes Duo Push Notifications as one of it's second factor authentication methods." +lead: "Authelia utilizes Duo Push Notifications as one of it's second factor authentication methods." +date: 2022-03-20T22:52:38+11:00 +draft: false +images: [] +menu: +  overview: +    parent: "authentication" +weight: 250 +toc: true +aliases: +  - /docs/features/2fa/push-notifications.html +--- + +Mobile Push notifications are a really convenient and trendy method to perform 2FA. When 2FA is required Authelia sends +a notification directly to an application on your mobile phone where you can instantly choose to accept or deny. + +Authelia leverages [Duo] third party to provide this feature. + +{{< figure src="duo-push-1.jpg" caption="The Duo Mobile Push authorization notification" alt="The Duo Mobile Push authorization notification" width=200 >}} + +{{< figure src="duo-push-2.png" caption="The Duo Mobile Push authorization consent view" alt="The Duo Mobile Push authorization consent view" width=200 >}} + +First, sign up on their website, log in, create a user account and attach it a mobile device. Beware that the name of +the user must match the name of the user in Authelia, or must have an alias that matches the user in Authelia. + +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__ +and then you must add the generated information to Authelia [configuration](../../deployment/index.md) as shown below: + +```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. + +Now that Authelia is configured, pass the first factor and select the Push notification option. + +{{< figure src="2FA-PUSH.png" caption="The Mobile Push 2FA view" alt="The Mobile Push 2FA view" width=400 >}} + +You should now receive a notification on your mobile phone with all the details about the authentication request. In +case you have multiple devices available, you will be asked to select your preferred device. + +## FAQ + +### Why don't I have access to the *Push Notification* option? + +It's likely that you have not configured __Authelia__ correctly. Please read this documentation again and be sure you +had a look at [config.template.yml](https://github.com/authelia/authelia/blob/master/config.template.yml) and +[configuration documentation](../../../configuration/second-factor/duo.md). + +[Duo]: https://duo.com/ diff --git a/docs/images/2FA-U2F.png b/docs/content/en/overview/authentication/security-key/2FA-U2F.png Binary files differindex e6e7708ee..e6e7708ee 100644 --- a/docs/images/2FA-U2F.png +++ b/docs/content/en/overview/authentication/security-key/2FA-U2F.png diff --git a/docs/images/REGISTER-U2F.png b/docs/content/en/overview/authentication/security-key/REGISTER-U2F.png Binary files differindex 2393bf5c5..2393bf5c5 100644 --- a/docs/images/REGISTER-U2F.png +++ b/docs/content/en/overview/authentication/security-key/REGISTER-U2F.png diff --git a/docs/features/2fa/security-key.md b/docs/content/en/overview/authentication/security-key/index.md index 54d72de7f..c54b0eff2 100644 --- a/docs/features/2fa/security-key.md +++ b/docs/content/en/overview/authentication/security-key/index.md @@ -1,51 +1,51 @@  --- -layout: default -title: Security Keys -nav_order: 2 -parent: Second Factor -grand_parent: Features +title: "Security Key" +description: "Authelia utilizes WebAuthn security keys as one of it's second factor authentication methods." +lead: "Authelia utilizes WebAuthn security keys as one of it's second factor authentication methods." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  overview: +    parent: "authentication" +weight: 240 +toc: true +aliases: +  - /docs/features/2fa/security-key  --- -# Security Keys - -**Authelia** supports hardware-based second factors leveraging [FIDO2] [Webauthn] compatible security keys like +__Authelia__ supports hardware-based second factors leveraging [FIDO2] [WebAuthn] compatible security keys like  [YubiKey]'s. -Security keys are among the most secure second factor. This method is already supported by many major applications and  +Security keys are among the most secure second factor. This method is already supported by many major applications and  platforms like Google, Facebook, GitHub, some banks, and much more. -<p align="center"> -  <img src="../../images/yubikey.jpg" width="150"> -</p> +{{< figure src="yubikey.jpg" caption="A YubiKey Security Key" alt="A YubiKey Security Key" width=150 >}} -Normally, the protocol requires your security key to be enrolled on each site before being able to authenticate with it.  +Normally, the protocol requires your security key to be enrolled on each site before being able to authenticate with it.  Since Authelia provides Single Sign-On, your users will need to enroll their device only once to get access to all your  applications. -<p align="center"> -  <img src="../../images/REGISTER-U2F.png" width="400"> -</p> +{{< figure src="REGISTER-U2F.png" caption="The WebAuthn Registration View" alt="2FA WebAuthn Registration View" width=400 >}}  After having successfully passed the first factor, select *Security Key* method and click on *Register device* link.  This will send you an email to verify your identity.  *NOTE: This e-mail has likely been sent to the mailbox at https://mail.example.com:8080/ if you're testing Authelia.* -Confirm your identity by clicking on **Register** and you'll be asked to touch the token of your security key to +Confirm your identity by clicking on __Register__ and you'll be asked to touch the token of your security key to  complete the enrollment.  Upon successful enrollment, you can authenticate using your security key by simply touching the token again when  requested: -<p align="center"> -  <img src="../../images/2FA-U2F.png" width="400"> -</p> +{{< figure src="2FA-U2F.png" caption="The WebAuthn Authentication View" alt="2FA WebAuthn Authentication View" width=400 >}}  Easy, right?!  ## FAQ -### Can I register multiple FIDO2 Webauthn devices? +### Can I register multiple FIDO2 WebAuthn devices?  At present this is not possible in the frontend. However the backend technically supports it. We plan to add this to the  frontend in the near future. Subscribe to [this issue](https://github.com/authelia/authelia/issues/275) for updates. @@ -56,19 +56,19 @@ Not at this time. We will tackle this at a later date.  ### Why don't I have access to the *Security Key* option? -The [Webauthn] protocol is a new protocol that is only supported by modern browsers. Please ensure your browser is up to -date, supports [Webauthn], and that the feature is not disabled if the option is not available to you in **Authelia**. +The [WebAuthn] protocol is a new protocol that is only supported by modern browsers. Please ensure your browser is up to +date, supports [WebAuthn], and that the feature is not disabled if the option is not available to you in __Authelia__.  ### Can my FIDO U2F device operate with Authelia?  At the present time there is no plan to support [FIDO U2F] within Authelia. We do implement a backwards compatible appid -extension within **Authelia** however this only works for devices registered before the upgrade to the [FIDO2] [Webauthn] -protocol. +extension within __Authelia__ however this only works for devices registered before the upgrade to the [FIDO2] +[WebAuthn] protocol. -If there was sufficient interest in supporting registration of old U2F / FIDO devices in **Authelia** we would consider +If there was sufficient interest in supporting registration of old U2F / FIDO devices in __Authelia__ we would consider  adding support for this after or at the same time of the multi-device enhancements.  [FIDO U2F]: https://www.yubico.com/authentication-standards/fido-u2f/  [FIDO2]: https://www.yubico.com/authentication-standards/fido2/ -[Webauthn]: https://www.yubico.com/authentication-standards/webauthn/ +[WebAuthn]: https://www.yubico.com/authentication-standards/webauthn/  [YubiKey]: https://www.yubico.com/products/yubikey-5-overview/ diff --git a/docs/images/yubikey.jpg b/docs/content/en/overview/authentication/security-key/yubikey.jpg Binary files differindex d70cd5725..d70cd5725 100644 --- a/docs/images/yubikey.jpg +++ b/docs/content/en/overview/authentication/security-key/yubikey.jpg diff --git a/docs/content/en/overview/authorization/_index.md b/docs/content/en/overview/authorization/_index.md new file mode 100644 index 000000000..0ade02185 --- /dev/null +++ b/docs/content/en/overview/authorization/_index.md @@ -0,0 +1,9 @@ +--- +title : "Authorization" +description: "Authorization Overview" +lead: "" +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +weight: 300 +--- diff --git a/docs/content/en/overview/authorization/access-control.md b/docs/content/en/overview/authorization/access-control.md new file mode 100644 index 000000000..0f9138561 --- /dev/null +++ b/docs/content/en/overview/authorization/access-control.md @@ -0,0 +1,47 @@ +--- +title: "Access Control" +description: "Access Control is the main authorization system in Authelia." +lead: "Access Control is the main authorization system in Authelia." +date: 2022-03-20T22:52:38+11:00 +draft: false +images: [] +menu: +  overview: +    parent: "authorization" +weight: 310 +toc: false +aliases: +  - /docs/features/access-control.html +--- + +__Authelia__ allows defining fine-grained rules-based access control policies. This list of rules is tested against +any requests protected by Authelia and defines the level of authentication the user must pass to get authorization to +the resource. + +## Example + +For instance a rule can look like this: + +```yaml +access_control: +  rules: +    - domain: dev.example.com +      resources: +        - '^/groups/dev/.*$' +      subject: 'group:dev' +      policy: two_factor +      methods: +        - GET +        - POST +      networks: +        - 192.168.1.0/24 +``` + +This rule matches when the request targets the domain `dev.example.com`, the path matches the regular expression +`^/groups/dev/.*$`, the user is a member of the `dev` group, the request comes from a client on the 192.168.2.0/24 +subnet, and the HTTP method verb is GET or POST. In that case, a two-factor policy is applied requiring the user to +authenticate with two factors. + +## Configuration + +Please check the dedicated [documentation](../../configuration/security/access-control.md). diff --git a/docs/content/en/overview/authorization/regulation.md b/docs/content/en/overview/authorization/regulation.md new file mode 100644 index 000000000..c29eef497 --- /dev/null +++ b/docs/content/en/overview/authorization/regulation.md @@ -0,0 +1,23 @@ +--- +title: "Regulation" +description: "Regulation of failed attempts is an important function of an IAM system." +lead: "Regulation of failed attempts is an important function of an IAM system." +date: 2022-03-20T22:52:38+11:00 +draft: false +images: [] +menu: +  overview: +    parent: "authorization" +weight: 320 +toc: false +aliases: +  - /docs/features/regulation.html +--- + +__Authelia__ takes the security of users very seriously and comes with a way to avoid brute-forcing the first factor +credentials by regulating the authentication attempts and temporarily banning an account when too many attempts have +been made. + +## Configuration + +Please check the dedicated [documentation](../../configuration/security/regulation.md). diff --git a/docs/content/en/overview/authorization/statelessness.md b/docs/content/en/overview/authorization/statelessness.md new file mode 100644 index 000000000..010873173 --- /dev/null +++ b/docs/content/en/overview/authorization/statelessness.md @@ -0,0 +1,63 @@ +--- +title: "Statelessness" +description: "Statelessness is the ability for a system to operate without an in-memory state. A crash could result in loss of the in-memory state causing a bad user experience." +lead: "Statelessness is the ability for a system to operate without an in-memory state. A crash could result in loss of the in-memory state causing a bad user experience." +date: 2022-03-20T22:52:38+11:00 +draft: false +images: [] +menu: +  overview: +    parent: "authorization" +weight: 390 +toc: false +aliases: +  - /t/statelessness +  - /docs/features/statelessness.html +--- + +__Authelia__ supports operating as a stateless application. This is incredibly important when running in highly +available deployments like you may see in platforms like Kubernetes. + +## Stateful Considerations + +There are some components within __Authelia__ that may optionally be made stateful by using certain providers. Examples +of this are as follows: + +### Session Provider + +__Severity:__ *BREAKING*. + +__Solution:__ Use a session provider other than memory (Redis). + +If you do not configure an external provider for the session configuration +it stores the session in memory. This is unacceptable for the operation of +__Authelia__ and is thus not supported for high availability. + +### Storage Provider + +__Severity:__ *BREAKING*. + +__Solution:__ Use a session provider other than SQLite3 (MySQL, MariaDB, PostgreSQL). + +Use of the local storage provider (SQLite3) is not supported in high availability setups +due to a design limitation with how SQLite3 operates. Use any of the other storage providers. + +### Notification Provider + +__Severity:__ *HIGH*. + +__Solution:__ Use a notification provider other than file system (SMTP). + +Use of the file system notification provider prevents users from several key tasks which heavily impact usability of +the system, and technically reduce security. Users will be unable to reset passwords or register new 2FA devices on +their own. The file system provider is not supported for high availability. + +### Authentication Provider + +__Severity:__ *MEDIUM (limiting)*. + +__Solution:__ Use an authentication provider other than file (LDAP), or distribute the file and disable password reset. + +Use of the file authentication provider (YAML) is only partially supported with high availability setups. It's +recommended if you don't use a stateless provider that you disable password reset and make sure the file is distributed +to all instances. We do not support using the file type in these scenarios. diff --git a/docs/content/en/overview/prologue/_index.md b/docs/content/en/overview/prologue/_index.md new file mode 100644 index 000000000..2a713f8d0 --- /dev/null +++ b/docs/content/en/overview/prologue/_index.md @@ -0,0 +1,9 @@ +--- +title : "Prologue" +description: "Overview Prologue" +lead: "" +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +weight: 100 +--- diff --git a/docs/images/archi.png b/docs/content/en/overview/prologue/architecture/architecture-diagram.png Binary files differindex bda611cfc..bda611cfc 100644 --- a/docs/images/archi.png +++ b/docs/content/en/overview/prologue/architecture/architecture-diagram.png diff --git a/docs/content/en/overview/prologue/architecture/index.md b/docs/content/en/overview/prologue/architecture/index.md new file mode 100644 index 000000000..dc90ad749 --- /dev/null +++ b/docs/content/en/overview/prologue/architecture/index.md @@ -0,0 +1,58 @@ +--- +title: "Architecture" +description: "An overview of the Authelia architecture." +lead: "An overview of the Authelia architecture." +date: 2022-05-13T12:34:15+10:00 +draft: false +images: [] +menu: +  overview: +    parent: "prologue" +weight: 120 +toc: false +aliases: +  - /docs/home/architecture.html +--- + +__Authelia__ is a companion of reverse proxies like Traefik (see [supported proxies](../supported-proxies.md) for a full +list). It can be seen as an extension of those proxies providing authentication functions and a login portal. + +As shown in the following architecture diagram, Authelia is directly connected to the reverse proxy but never directly +connected to application backends and therefore the payloads sent by the clients of the protected API will never reach +Authelia, only the authentication pieces will, like the Authorization header for instance. Consequently, the protected +APIs can be a REST, a GraphQL or any other kind of API on top of HTTP. + +{{< figure src="architecture-diagram.png" caption="Architecture Diagram" alt="Architecture Diagram" >}} + +## Workflow + +Reverse proxies are configured so that every incoming request generates an authentication request sent to Authelia. +Authelia responds and will instruct the reverse proxy to either allow the incoming request to pass through, or block it +because the user is not authenticated or is not sufficiently authorized. + +### Step by step + +When the first request of an unauthenticated user hits the reverse proxy, Authelia determines the user is not +authenticated because no session cookie has been sent along with the request. Consequently, Authelia redirects the user +to the authentication portal provided by Authelia itself. The user can then execute the authentication workflow using +that portal to obtain a session cookie valid for all subdomains of the domain protected by Authelia. + +When the user visits the initial website again, the query is sent along with the session cookie which is forwarded in +the authentication request to Authelia. This time, Authelia can verify the user is authenticated and order the reverse +proxy to let the query pass through. + +### Sequence Diagram + +Here is a description of the complete workflow: + +{{< figure src="sequence-diagram.png" caption="Sequence Diagram" alt="Sequence Diagram" >}} + +## HTTP/HTTPS + +Authelia only works for websites served over HTTPS because the session cookie can only be transmitted over secure +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)). + +If a self-signed certificate is required, the +[Generating an RSA Self-Signed Certificate](../../../configuration/miscellaneous/guides.md#generating-an-rsa-self-signed-certificate) +guide should be followed. diff --git a/docs/images/sequence-diagram.png b/docs/content/en/overview/prologue/architecture/sequence-diagram.png Binary files differindex e0ae5269c..e0ae5269c 100644 --- a/docs/images/sequence-diagram.png +++ b/docs/content/en/overview/prologue/architecture/sequence-diagram.png diff --git a/docs/content/en/overview/prologue/introduction.md b/docs/content/en/overview/prologue/introduction.md new file mode 100644 index 000000000..5e130725e --- /dev/null +++ b/docs/content/en/overview/prologue/introduction.md @@ -0,0 +1,22 @@ +--- +title: "Prologue" +description: "An introduction into the Authelia overview." +lead: "An introduction into the Authelia overview." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  overview: +    parent: "prologue" +weight: 110 +toc: false +--- + +__Authelia__ is a 2FA & SSO authentication server which is dedicated to the security of applications and users. It can +be considered an extension of reverse proxies by providing features specific to authentication. You will find among +other features: + +* Several two-factor authentication methods. +* Identity verification when registering second factor devices. +* Self-service reset of user passwords. +* Banning accounts after too many attempts (known as regulation). diff --git a/docs/content/en/overview/prologue/supported-proxies.md b/docs/content/en/overview/prologue/supported-proxies.md new file mode 100644 index 000000000..bfd7ef419 --- /dev/null +++ b/docs/content/en/overview/prologue/supported-proxies.md @@ -0,0 +1,53 @@ +--- +title: "Supported Proxies" +description: "An introduction into the Authelia overview." +lead: "An introduction into the Authelia overview." +date: 2022-05-13T12:34:15+10:00 +draft: false +images: [] +menu: +  overview: +    parent: "prologue" +weight: 130 +toc: false +--- + +The following table is a support matrix for Authelia features and specific reverse proxies. + +|         Proxy         |                                       Standard                                        |                                      Kubernetes                                      |             XHR Redirect             |            Request Method            | +|:---------------------:|:-------------------------------------------------------------------------------------:|:------------------------------------------------------------------------------------:|:------------------------------------:|:------------------------------------:| +|       [Traefik]       |       [<i class="icon-support-full"></i>](../../integration/proxies/traefik.md)       | [<i class="icon-support-full"></i>](../../integration/kubernetes/traefik-ingress.md) |  <i class="icon-support-full"></i>   |  <i class="icon-support-full"></i>   | +|        [NGINX]        |        [<i class="icon-support-full"></i>](../../integration/proxies/nginx.md)        |  [<i class="icon-support-full"></i>](../../integration/kubernetes/nginx-ingress.md)  |  <i class="icon-support-none"></i>   |  <i class="icon-support-full"></i>   | +| [NGINX Proxy Manager] | [<i class="icon-support-full"></i>](../../integration/proxies/nginx-proxy-manager.md) |                         <i class="icon-support-unknown"></i>                         |  <i class="icon-support-none"></i>   |  <i class="icon-support-full"></i>   | +|        [SWAG]         |        [<i class="icon-support-full"></i>](../../integration/proxies/swag.md)         |                         <i class="icon-support-unknown"></i>                         |  <i class="icon-support-none"></i>   |  <i class="icon-support-full"></i>   | +|       [HAProxy]       |       [<i class="icon-support-full"></i>](../../integration/proxies/haproxy.md)       |                         <i class="icon-support-unknown"></i>                         | <i class="icon-support-unknown"></i> |  <i class="icon-support-full"></i>   | +|        [Caddy]        |        [<i class="icon-support-full"></i>](../../integration/proxies/caddy.md)        |                         <i class="icon-support-unknown"></i>                         |  <i class="icon-support-full"></i>   |  <i class="icon-support-full"></i>   | +|     [Traefik] 1.x     |      [<i class="icon-support-full"></i>](../../integration/proxies/traefikv1.md)      |                         <i class="icon-support-unknown"></i>                         |  <i class="icon-support-full"></i>   |  <i class="icon-support-full"></i>   | +|        [Envoy]        |      [<i class="icon-support-unknown"></i>](../../integration/proxies/envoy.md)       |                         <i class="icon-support-unknown"></i>                         | <i class="icon-support-unknown"></i> | <i class="icon-support-unknown"></i> | +|       [Apache]        |                 <i class="icon-support-none" alt="Not Supported"></i>                 |                          <i class="icon-support-none"></i>                           |  <i class="icon-support-none"></i>   |  <i class="icon-support-none"></i>   | +|         [IIS]         |                           <i class="icon-support-none"></i>                           |                          <i class="icon-support-none"></i>                           |  <i class="icon-support-none"></i>   |  <i class="icon-support-none"></i>   | + +Legend: + +|                 Icon                 |       Meaning       | +|:------------------------------------:|:-------------------:| +|  <i class="icon-support-full"></i>   |      Supported      | +| <i class="icon-support-unknown"></i> |       Unknown       | +| <i class="icon-support-partial"></i> | Partially Supported | +|  <i class="icon-support-none"></i>   |    Not Supported    | + +## More Information + +For more comprehensive support information please see the +[Proxy Integration Support](../../integration/proxies/support.md) guide. + +[NGINX]: https://www.nginx.com/ +[NGINX Proxy Manager]: https://nginxproxymanager.com/ +[SWAG]: https://docs.linuxserver.io/general/swag +[Traefik]: https://traefik.io/ +[Caddy]: https://caddyserver.com/ +[HAProxy]: https://www.haproxy.com/ +[Envoy]: https://www.envoyproxy.io/ +[Caddy]: https://caddyserver.com/ +[Apache]: https://httpd.apache.org/ +[IIS]: https://www.iis.net/ diff --git a/docs/content/en/overview/security/_index.md b/docs/content/en/overview/security/_index.md new file mode 100644 index 000000000..2f888d074 --- /dev/null +++ b/docs/content/en/overview/security/_index.md @@ -0,0 +1,9 @@ +--- +title : "Security" +description: "Overview Prologue" +lead: "" +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +weight: 400 +--- diff --git a/docs/content/en/overview/security/introduction.md b/docs/content/en/overview/security/introduction.md new file mode 100644 index 000000000..ee143fa83 --- /dev/null +++ b/docs/content/en/overview/security/introduction.md @@ -0,0 +1,26 @@ +--- +title: "Security" +description: "An overview introduction into Authelia's security features." +lead: "An overview introduction into Authelia's security features." +date: 2022-05-13T12:34:15+10:00 +draft: false +images: [] +menu: +  overview: +    parent: "security" +weight: 410 +toc: false +aliases: +  - /docs/security/ +--- + +The __Authelia__ team takes security very seriously. Because __Authelia__ is intended as a security product a lot of +decisions are made with security being the priority. This section discusses these decisions as well as considerations +users should make when implementing __Authelia__. + +## Coordinated vulnerability disclosure + +__Authelia__ follows the [coordinated vulnerability disclosure](https://en.wikipedia.org/wiki/Coordinated_vulnerability_disclosure) +model when dealing with security vulnerabilities. This was previously known as responsible disclosure. We strongly +urge anyone reporting vulnerabilities to __Authelia__ or any other project to follow this model as it is considered +as a best practice by many in the security industry. diff --git a/docs/security/measures.md b/docs/content/en/overview/security/measures.md index d1410e6cb..45af7a3a8 100644 --- a/docs/security/measures.md +++ b/docs/content/en/overview/security/measures.md @@ -1,40 +1,51 @@  --- -layout: default -title: Security Measures -parent: Security -nav_order: 1 +title: "Measures" +description: "An overview of the security measures Authelia implements." +lead: "An overview of the security measures Authelia implements." +date: 2022-05-13T12:34:15+10:00 +draft: false +images: [] +menu: +  overview: +    parent: "security" +weight: 420 +toc: false +aliases: +  - /docs/security/measures.html  --- -# Security Measures -  ## Protection against cookie theft -Authelia sets several key cookie attributes to prevent cookie theft: +Authelia sets several +[cookie attributes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#attributes) to help prevent +cookie theft: +  1. `HttpOnly` is set forbidding client-side code like javascript from access to the cookie. -2. `Secure` is set forbidding the browser from sending the cookie to sites which do not use the https scheme. +2. `Secure` is set forbidding the browser from sending the cookie to sites which do not use the [HTTPS] scheme.  3. `SameSite` is by default set to `Lax` which prevents it being sent over cross-origin requests. -Read about these attributes in detail on the  +Read about these attributes in detail on the  [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie).  ## Protection against multi-domain cookie attacks -Since Authelia uses multi-domain cookies to perform single sign-on, an attacker who poisoned a user's DNS cache can  +Since Authelia uses multi-domain cookies to perform single sign-on, an attacker who poisoned a user's DNS cache can  easily retrieve the user's cookies by making the user send a request to one of the attacker's IPs.  This is technically mitigated by the `Secure` attribute set in cookies by Authelia, however it's still advisable to -only use HTTPS connections with valid certificates and enforce it with HTTP Strict Transport Security ([HSTS]) which -will prevent domains from serving over HTTP at all as long as the user has visited the domain before. This means even +only use [HTTPS] connections with valid certificates and enforce it with HTTP Strict Transport Security ([HSTS]) which +will prevent domains from serving over [HTTP] at all as long as the user has visited the domain before. This means even  if the attacker poisons DNS they are unable to get modern browsers to connect to a compromised host unless they can also  obtain the certificate. -Note that using [HSTS] has consequences. That's why you should read the blog post nginx has written on [HSTS]. +Note that using [HSTS] has consequences and you should do adequate research into understanding [HSTS] before you enable +it. For example the [nginx blog] has a good article helping users understand it.  ## Protection against username enumeration  Authelia adaptively delays authentication attempts based on the mean (average) of the previous 10 successful attempts  in addition to a small random interval of time. The result of this delay is that it makes it incredibly difficult to -determine if the unsuccessful login was the result of a bad password, a bad username, or both. The random interval of  +determine if the unsuccessful login was the result of a bad password, a bad username, or both. The random interval of  time is anything between 0 milliseconds and 85 milliseconds.  When Authelia first starts it assumes the last 10 attempts took 1000 milliseconds each. As users login successfully it @@ -42,26 +53,26 @@ quickly adjusts to the actual time the login attempts take. This process is inde  configured.  The cost of this is low since in the instance of a user not existing it just stops processing the request to delay the -login. Lastly the absolute minimum time authentication can take is 250 milliseconds. Both of these measures also have  +login. Lastly the absolute minimum time authentication can take is 250 milliseconds. Both of these measures also have  the added effect of creating an additional delay for all authentication attempts increasing the time that a brute-force  attack will take, this combined with regulation greatly delays brute-force attacks and the effectiveness of them in  general.  ## Protections against password cracking (File authentication provider) -Authelia implements a variety of measures to prevent an attacker cracking passwords if they somehow obtain the file used  +Authelia implements a variety of measures to prevent an attacker cracking passwords if they somehow obtain the file used  by the file authentication provider, this is unrelated to LDAP auth. -First and foremost Authelia only uses very secure hashing algorithms with sane and secure defaults. The first and  -default hashing algorithm we use is Argon2id which is currently considered the most secure hashing algorithm. We also  +First and foremost Authelia only uses very secure hashing algorithms with sane and secure defaults. The first and +default hashing algorithm we use is Argon2id which is currently considered the most secure hashing algorithm. We also  support SHA512, which previously was the default. -Secondly Authelia uses salting with all hashing algorithms. These salts are generated with a random string generator,  -which is seeded every time it's used by a cryptographically secure 1024bit prime number. This ensures that even if an  +Secondly Authelia uses salting with all hashing algorithms. These salts are generated with a random string generator, +which is seeded every time it's used by a cryptographically secure 1024bit prime number. This ensures that even if an  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  -(time), parallelism, and memory usage. To read more about this please read how to  +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  [configure](../configuration/authentication/file.md) file authentication.  ## User profile and group membership always kept up-to-date (LDAP authentication provider) @@ -72,13 +83,13 @@ Authelia by default refreshes the user's profile and membership every 5 minutes.  groups in LDAP that their new groups are obtained relatively quickly in order to adjust their access level for  applications secured by Authelia. -Additionally, it will invalidate any session where the user could not be retrieved from LDAP based on the user filter,  -for example if they were deleted or disabled provided the user filter is set correctly. These updates occur when a user  +Additionally, it will invalidate any session where the user could not be retrieved from LDAP based on the user filter, +for example if they were deleted or disabled provided the user filter is set correctly. These updates occur when a user  accesses a resource protected by Authelia. This means you should ensure disabled users or users with expired passwords -are not obtainable using the LDAP filter, the default filter for Active Directory implements this behaviour.  +are not obtainable using the LDAP filter, the default filter for Active Directory implements this behaviour.  LDAP implementations vary, so please ask if you need some assistance in configuring this. -These protections can be [tuned](../configuration/authentication/ldap.md#refresh-interval) according to your security  +These protections can be [tuned](../../configuration/first-factor/ldap.md#refresh-interval) according to your security  policy by changing refresh_interval, however we believe that 5 minutes is a fairly safe interval.  ## Storage security measures @@ -110,13 +121,13 @@ A bad actor who has the SQL password and access to the database can theoreticall  theoretically bypasses authentication. Columns encrypted for this purpose prevent this attack vector.  A bad actor may also be able to use data in the database to bypass 2FA silently depending on the credentials. In the -instance of the U2F public key this is not possible, they can only change it which would eventually alert the user in  +instance of the U2F public key this is not possible, they can only change it which would eventually alert the user in  question. But in the case of TOTP they can use the secret to authenticate without knowledge of the user in question.  ### Encryption key management -You must supply the encryption key in the recommended method of a [secret](../configuration/secrets.md) or in one of -the other methods available for [configuration](../configuration/index.md#configuration). +You must supply the encryption key in the recommended method of a [secret](../../configuration/methods/secrets.md) or in +one of the other [methods available for configuration](../../configuration/methods/introduction.md).  If you wish to change your encryption key for any reason you can do so using the following steps: @@ -126,10 +137,10 @@ If you wish to change your encryption key for any reason you can do so using the     it.  2. Run the `./authelia storage encryption change-key --help` command.  3. Stop Authelia. -   - You can skip this step, however note that any data changed between the time you make the change and the time when  +   * You can skip this step, however note that any data changed between the time you make the change and the time when     you stop Authelia i.e. via user registering a device; will be encrypted with the incorrect key.  4. Run the `./authelia storage encryption change-key` command with the appropriate parameters. -   - The help from step 1 will be useful here. The easiest method to accomplish this is with the `--config`, +   * The help from step 1 will be useful here. The easiest method to accomplish this is with the `--config`,     `--encryption-key`, and `--new-encryption-key` parameters.  5. Update the encryption key Authelia uses on startup.  6. Start Authelia. @@ -145,46 +156,46 @@ As such all SMTP connections require the following:  connections require it as well)  2. Valid X509 Certificate presented to the client during the TLS handshake -There is an option to disable both of these security measures however they are **not recommended**. +There is an option to disable both of these security measures however they are __not recommended__. -The following configuration options exist to configure the security level in order of most preferable to least  +The following configuration options exist to configure the security level in order of most preferable to least  preferable:  ### Configuration Option: certificates_directory -You can [configure a directory](../configuration/miscellaneous.md#certificates_directory) of certificates for Authelia  +You can [configure a directory](../../configuration/miscellaneous/introduction.md#certificates_directory) of certificates for Authelia  to trust. These certificates can either be CA's or individual public certificates that should be trusted. These  are added in addition to the environments PKI trusted certificates if available. This is useful for trusting a  certificate that is self-signed without drastically reducing security. This is the most recommended workaround to not  having a valid PKI trusted certificate as it gives you complete control over which ones are trusted without disabling  critically needed validation of the identity of the target service. -Read more in the [documentation](../configuration/miscellaneous.md#certificates_directory) for this option. +Read more in the [documentation](../../configuration/miscellaneous/introduction.md#certificates_directory) for this option.  ### Configuration Option: tls.skip_verify -The [tls.skip_verify](../configuration/notifier/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. -This will effectively mean you cannot be sure the certificate is valid which means an attacker via DNS poisoning or MITM  +This will effectively mean you cannot be sure the certificate is valid which means an attacker via DNS poisoning or MITM  attacks could intercept emails from Authelia compromising a user's security without their knowledge.  ### Configuration Option: disable_require_tls  Authelia by default ensures that the SMTP server connection is secured via STARTTLS or SMTPS prior to sending sensitive -information. The [disable_require_tls](../configuration/notifier/smtp.md#disable_require_tls) disables this requirement +information. The [disable_require_tls](../../configuration/notifications/smtp.md#disable_require_tls) disables this requirement  which means the emails are sent in plain text. This is the least secure option as it effectively removes the validation  of SMTP certificates and removes the encryption offered by the STARTTLS/SMTPS connection all together.  This means not only can the vulnerabilities of the [skip_verify](#configuration-option-tlsskip_verify) option be  exploited, but any router or switch along the route of the email which receives the packets could be used to silently -exploit the plain text nature of the email. This is only usable currently with authentication disabled (comment out the  +exploit the plain text nature of the email. This is only usable currently with authentication disabled (comment out the  password) and as such is only an option for SMTP servers that allow unauthenticated relay (bad practice).  ### SMTPS vs STARTTLS  All connections start as plain text and are upgraded via STARTTLS. SMTPS is an exception to this rule where the -connection is over TLS. As SMTPS is deprecated, the only way to configure this is to set the SMTP  -[port](../configuration/notifier/smtp.md#port) to the officially recognized SMTPS port of 465 which will cause Authelia +connection is over TLS. As SMTPS is deprecated, the only way to configure this is to set the SMTP +[port](../../configuration/notifications/smtp.md#port) to the officially recognized SMTPS port of 465 which will cause Authelia  to automatically consider it to be a SMTPS connection. As such your SMTP server, if not offering SMTPS, should not be  listening on port 465 which is bad practice anyway. @@ -196,36 +207,37 @@ infected websites leveraging legit links.  ## Mutual TLS -For the best security protection, configuration with TLS is highly recommended. TLS is used to secure the connection between -the proxies and Authelia instances meaning that an attacker on the network cannot perform a man-in-the-middle attack on those -connections. However, an attacker on the network can still impersonate proxies but this can be prevented by configuring mutual -TLS. +For the best security protection, configuration with TLS is highly recommended. TLS is used to secure the connection +between the proxies and Authelia instances meaning that an attacker on the network cannot perform a man-in-the-middle +attack on those connections. However, an attacker on the network can still impersonate proxies but this can be prevented +by configuring mutual TLS. +  Mutual TLS brings mutual authentication between Authelia and the proxies. Any other party attempting to contact Authelia -would not even be able to create a TCP connection. This measure is recommended in all cases except if you already 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. +would not even be able to create a TCP connection. This measure is recommended in all cases except if you already +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. -To configure mutual TLS, please refer to [this document](../configuration/server.md#client_certificates) +To configure mutual TLS, please refer to [this document](../../configuration/miscellaneous/server.md#client_certificates)  ## Additional security  ### Reset Password  It's possible to disable the reset password functionality and is an optional adjustment to consider for anyone wanting -to increase security. See the [configuration](../configuration/authentication/index.md#disable_reset_password) for more  -information. +to increase security. See the [configuration](../../configuration/first-factor/introduction.md#disable_reset_password) +for more information.  ### Session security  We have a few options to configure the security of a session. The main and most important one is the session secret. -This is used to encrypt the session data when it is stored in the [Redis](../configuration/session/redis.md) key value +This is used to encrypt the session data when it is stored in the [Redis](../../configuration/session/redis.md) key value  database. The value of this option should be long and as random as possible. See more in the -[documentation](../configuration/session/index.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 -set the session [remember_me_duration](../configuration/session/index.md#remember_me_duration) to 0 to disable this -feature, and set the [expiration](../configuration/session/index.md#expiration) to 2 hours and the -[inactivity](../configuration/session/index.md#inactivity) of 10 minutes. Configuring the session security in this +set the session [remember_me_duration](../../configuration/session/introduction.md#remember_me_duration) to 0 to disable this +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  manner would mean if the cookie age was more than 2 hours or if the user was inactive for more than 10 minutes the  session would be destroyed. @@ -239,16 +251,16 @@ Users who need custom behaviours in this area can submit a request or remove/rep  #### X-Content-Type-Options -**Value:** `nosniff` -**Endpoints:** All +__Value:__ `nosniff` +__Endpoints:__ All  Prevents MIME type sniffing. See the  [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options) for more information.  #### Referrer-Policy -**Value:** `strict-origin-when-cross-origin` -**Endpoints:** All +__Value:__ `strict-origin-when-cross-origin` +__Endpoints:__ All  Sends only the origin as the referrer in cross-origin requests, but sends the origin, path, and query string in  same-origin requests. See the @@ -256,16 +268,16 @@ same-origin requests. See the  #### X-Frame-Options -**Value:** `SAMEORIGIN` -**Endpoints:** All +__Value:__ `SAMEORIGIN` +__Endpoints:__ All  Prevents Authelia rendering in a `frame`, `iframe`, `embed`, or `object` element. See the  [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options) for more information.  #### X-XSS-Protection -**Value:** `0` -**Endpoints:** All +__Value:__ `0` +__Endpoints:__ All  We disable this as this feature is not present in any modern browser and could introduce vulnerabilities if enabled at  all. Going forward [CORS], [CORP], CORB, and [COEP] are the standards for browser centric site security. See the @@ -273,38 +285,38 @@ all. Going forward [CORS], [CORP], CORB, and [COEP] are the standards for browse  #### Permissions-Policy -**Value:** `interest-cohort=()` -**Endpoints:** All +__Value:__ `interest-cohort=()` +__Endpoints:__ All  Disables FLoC Cohorts.  #### Pragma -**Value:** `no-cache` -**Endpoints:** API +__Value:__ `no-cache` +__Endpoints:__ API  Disables caching of API requests on HTTP/1.0 browsers. See the  [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Pragma) for more information.  #### Cache-Control -**Value:** `no-store` -**Endpoints:** API +__Value:__ `no-store` +__Endpoints:__ API  Disables caching responses entirely on HTTP/1.1 browsers. See the  [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control) for more information.  ### More protections measures with fail2ban -If you are running fail2ban, adding a filter and jail for Authelia can reduce load on the application / web server.  -Fail2ban will ban IPs exceeding a threshold of repeated failed logins at the firewall level of your host. If you are  -using Docker, the Authelia log file location has to be mounted from the host system to the container for  +If you are running fail2ban, adding a filter and jail for Authelia can reduce load on the application / web server. +Fail2ban will ban IPs exceeding a threshold of repeated failed logins at the firewall level of your host. If you are +using Docker, the Authelia log file location has to be mounted from the host system to the container for  fail2ban to access it. -Create a configuration file in the `filter.d` folder with the content below. In Debian-based systems the folder is  +Create a configuration file in the `filter.d` folder with the content below. In Debian-based systems the folder is  typically located at `/etc/fail2ban/filter.d`. -``` +```ini  # Fail2Ban filter for Authelia  # Make sure that the HTTP header "X-Forwarded-For" received by Authelia's backend @@ -324,11 +336,11 @@ ignoreregex = ^.*level=debug.*                ^.*level=warning.*  ``` -Modify the `jail.local` file. In Debian-based systems the folder is typically located at `/etc/fail2ban/`. If the file  -does not exist, create it by copying the jail.conf `cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local`. Add an  +Modify the `jail.local` file. In Debian-based systems the folder is typically located at `/etc/fail2ban/`. If the file +does not exist, create it by copying the jail.conf `cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local`. Add an  Authelia entry to the "Jails" section of the file: -``` +```ini  [authelia]  enabled = true  port = http,https,9091 @@ -345,10 +357,10 @@ changes to take effect.  ## Container privilege de-escalation -Authelia will run as the root user and group by default, there are two options available to run as a non-root user and  -group.  +Authelia will run as the root user and group by default, there are two options available to run as a non-root user and +group. -It is recommended which ever approach you take that to secure the sensitive files Authelia requires access to that you  +It is recommended which ever approach you take that to secure the sensitive files Authelia requires access to that you  make sure the chmod of the files does not inadvertently allow read access to the files by users who do not need access  to them. @@ -389,7 +401,7 @@ docker run --user 8000:9000 -v /authelia:/config authelia/authelia:latest  Example for docker-compose: -``` +```yaml  version: '3.8'  services:    authelia: @@ -406,8 +418,8 @@ PGID environment variables below, so if you use it then changing the PUID and PG  ### PUID/PGID environment variables using the entrypoint -The second option is to use the `PUID` and `PGID` environment variables. When the container entrypoint is executed  -as root, the entrypoint automatically runs the Authelia process as this user. An added benefit of using the environment  +The second option is to use the `PUID` and `PGID` environment variables. When the container entrypoint is executed +as root, the entrypoint automatically runs the Authelia process as this user. An added benefit of using the environment  variables is the mounted volumes ownership will automatically be changed for you. It is still recommended that  you run the find chmod examples above in order to secure the files even further especially on servers multiple people  have access to. @@ -422,7 +434,7 @@ docker run -e PUID=1000 -e PGID=1000 -v /authelia:/config authelia/authelia:late  Example for docker-compose: -``` +```yaml  version: '3.8'  services:    authelia: @@ -435,7 +447,21 @@ services:        - ./authelia:/config  ``` -[HSTS]: https://www.nginx.com/blog/http-strict-transport-security-hsts-and-nginx/ +## Privacy + +### Opaque Identifiers + +Where possible we utilize opaque identifiers which link to user accounts. The primary example at this time is +[OpenID Connect](../../integration/openid-connect/introduction.md) which utilizes an opaque identifier for the +[subject claim](../../integration/openid-connect/introduction.md#openid). + +This will also be utilized in the future for the [WebAuthn](../authentication/security-key) passwordless flow +(discoverable logins). + +[HTTP]: https://developer.mozilla.org/en-US/docs/Glossary/http +[HTTPS]: https://developer.mozilla.org/en-US/docs/Glossary/https +[HSTS]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security +[nginx blog]: https://www.nginx.com/blog/http-strict-transport-security-hsts-and-nginx/  [CORS]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS  [CORP]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Cross-Origin_Resource_Policy_(CORP) -[COEP]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy
\ No newline at end of file +[COEP]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy diff --git a/docs/security/threat-model.md b/docs/content/en/overview/security/threat-model.md index 0f549e301..9e2bdcf1a 100644 --- a/docs/security/threat-model.md +++ b/docs/content/en/overview/security/threat-model.md @@ -1,23 +1,31 @@  --- -layout: default -title: Threat Model -parent: Security -nav_order: 2 +title: "Threat Model" +description: "An overview of the Authelia threat model." +lead: "An overview of the Authelia threat model." +date: 2022-05-13T12:34:15+10:00 +draft: false +images: [] +menu: +  overview: +    parent: "security" +weight: 430 +toc: false +aliases: +  - /o/threatmodel +  - /docs/security/threat-model.html  --- -# Threat Model -  The design goals for Authelia is to protect access to applications by collaborating with reverse proxies to prevent  attacks coming from the edge of the network. This document gives an overview of what Authelia is protecting against. -Some of these ideas are expanded on or otherwise described in [Security Measures](./measures.md). +Some of these ideas are expanded on or otherwise described in [Security Measures](measures.md).  ## General assumptions -Authelia is considered to be running within a trusted network and it heavily relies on the first level of security  -provided by reverse proxies. It's very important that you take time configuring your reverse proxy properly to get all  +Authelia is considered to be running within a trusted network and it heavily relies on the first level of security +provided by reverse proxies. It's very important that you take time configuring your reverse proxy properly to get all  the authentication benefits brought by Authelia. -Some general security tweaks are listed in [Security Measures](./measures.md#additional-proxy-protection-measures) to  -give you some ideas. + +Some general security tweaks are listed in [Security Measures](measures.md) to give you some ideas.  ## Guarantees @@ -28,31 +36,31 @@ If properly configured, Authelia guarantees the following for security of your u  * Applications can be protected with two-factor authentication in order to fight against credential theft and protect    highly sensitive data or operations.  * Sessions are bound in time, limiting the impact of a cookie theft. Sessions can have both soft and hard expiration -  time limits. With the soft limit, the user is logged out when inactive for a certain period of time. With the hard  +  time limits. With the soft limit, the user is logged out when inactive for a certain period of time. With the hard    limit, the user has to authenticate again after a certain period of time, whether they were active or not.  * Brute force attacks against credentials are protected thanks to a regulation mechanism temporarily blocking the user    account after too many attempts and delays to the authentication process. -* Identity validation is required for performing administrative actions such as registering 2FA devices, preventing  +* Identity validation is required for performing administrative actions such as registering 2FA devices, preventing    attackers to pass two-factor authentication by self-registering their own device. An email with a link is sent to the    user with a link providing them access to the registration flow which can only be opened by a single session.  * Prevention against session fixation by regenerating a new session after each privilege elevation.  * Prevention against LDAP injection by following    [OWASP recommendations](https://cheatsheetseries.owasp.org/cheatsheets/LDAP_Injection_Prevention_Cheat_Sheet.html)    regarding valid input characters. -* Connections between Authelia and third-party components like the SMTP server, database, session cache, and LDAP server  +* Connections between Authelia and third-party components like the SMTP server, database, session cache, and LDAP server    can be made over TLS to mitigate against man-in-the-middle attacks.  * Validation of user group memberships gets refreshed regularly from the authentication backend (LDAP only). -  +  ## Potential future guarantees -* Define and enforce a password policy (to be designed since such a policy can clash with a policy set by the LDAP  +* Define and enforce a password policy (to be designed since such a policy can clash with a policy set by the LDAP    server).  * Detect credential theft and prevent malicious actions.  * Detect session cookie theft and prevent malicious actions. -* Binding session cookies to single IP addresses.   +* Binding session cookies to single IP addresses.  * Authenticate communication between Authelia and reverse proxy.  * Securely transmit authentication data to backends (OAuth2 with bearer tokens). -* Least privilege on LDAP binding operations (currently administrative user is used to bind while it could be anonymous  +* Least privilege on LDAP binding operations (currently administrative user is used to bind while it could be anonymous    for most operations).  * Extend the check of user group memberships to authentication backends other than LDAP (File currently).  * Allow administrators to configure policies regarding password resets so a compromised email account does not leave @@ -61,9 +69,9 @@ If properly configured, Authelia guarantees the following for security of your u    administrator, or both.  * Allow administrators to temporarily restrict users that are suspected of being compromised no matter which backend is    being used. -* Log comprehensive information about user sessions so administrators can identify malicious activity and potential  +* Log comprehensive information about user sessions so administrators can identify malicious activity and potential    consequences or damage caused by identified malicious activity. -* Ensure the X-Forwarded-* and X-Original-* headers are able to be trusted by allowing configuration of trusted proxy +* Ensure the `X-Forwarded-*` and `X-Original-*` headers are able to be trusted by allowing configuration of trusted proxy    servers.  ## Trusted environment diff --git a/docs/content/en/reference/_index.md b/docs/content/en/reference/_index.md new file mode 100644 index 000000000..89df12c33 --- /dev/null +++ b/docs/content/en/reference/_index.md @@ -0,0 +1,8 @@ +--- +title : "Reference" +description: "Authelia Reference" +lead: "" +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +--- diff --git a/docs/content/en/reference/cli/_index.md b/docs/content/en/reference/cli/_index.md new file mode 100644 index 000000000..6cbd0a1e2 --- /dev/null +++ b/docs/content/en/reference/cli/_index.md @@ -0,0 +1,10 @@ +--- +title: "CLI" +description: "" +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +weight: 300 +toc: true +--- diff --git a/docs/content/en/reference/cli/authelia-gen/_index.md b/docs/content/en/reference/cli/authelia-gen/_index.md new file mode 100644 index 000000000..02b76ddeb --- /dev/null +++ b/docs/content/en/reference/cli/authelia-gen/_index.md @@ -0,0 +1,14 @@ +--- +title: "authelia-gen" +description: "" +lead: "" +date: 2022-06-03T10:57:43+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli" +    identifier: "cli-authelia-gen" +weight: 900 +toc: true +--- diff --git a/docs/content/en/reference/cli/authelia-gen/authelia-gen.md b/docs/content/en/reference/cli/authelia-gen/authelia-gen.md new file mode 100644 index 000000000..9f67ef67c --- /dev/null +++ b/docs/content/en/reference/cli/authelia-gen/authelia-gen.md @@ -0,0 +1,31 @@ +--- +title: "authelia-gen" +description: "Reference for the authelia-gen command." +lead: "" +date: 2022-06-03T10:57:43+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia-gen" +weight: 320 +toc: true +--- + +## authelia-gen + +Authelia's generator tooling + +### Options + +``` +  -h, --help   help for authelia-gen +``` + +### SEE ALSO + +* [authelia-gen all](authelia-gen_all.md)	 - Run all generators with default options +* [authelia-gen code](authelia-gen_code.md)	 - Generate code +* [authelia-gen docs](authelia-gen_docs.md)	 - Generate docs + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-gen/authelia-gen_all.md b/docs/content/en/reference/cli/authelia-gen/authelia-gen_all.md new file mode 100644 index 000000000..8af830638 --- /dev/null +++ b/docs/content/en/reference/cli/authelia-gen/authelia-gen_all.md @@ -0,0 +1,33 @@ +--- +title: "authelia-gen all" +description: "Reference for the authelia-gen all command." +lead: "" +date: 2022-06-03T10:57:43+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia-gen" +weight: 330 +toc: true +--- + +## authelia-gen all + +Run all generators with default options + +``` +authelia-gen all [flags] +``` + +### Options + +``` +  -h, --help   help for all +``` + +### SEE ALSO + +* [authelia-gen](authelia-gen.md)	 - Authelia's generator tooling + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-gen/authelia-gen_code.md b/docs/content/en/reference/cli/authelia-gen/authelia-gen_code.md new file mode 100644 index 000000000..b065e6144 --- /dev/null +++ b/docs/content/en/reference/cli/authelia-gen/authelia-gen_code.md @@ -0,0 +1,34 @@ +--- +title: "authelia-gen code" +description: "Reference for the authelia-gen code command." +lead: "" +date: 2022-06-03T10:57:43+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia-gen" +weight: 330 +toc: true +--- + +## authelia-gen code + +Generate code + +``` +authelia-gen code [flags] +``` + +### Options + +``` +  -h, --help   help for code +``` + +### SEE ALSO + +* [authelia-gen](authelia-gen.md)	 - Authelia's generator tooling +* [authelia-gen code keys](authelia-gen_code_keys.md)	 - Generate the list of valid configuration keys + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-gen/authelia-gen_code_keys.md b/docs/content/en/reference/cli/authelia-gen/authelia-gen_code_keys.md new file mode 100644 index 000000000..59b40514f --- /dev/null +++ b/docs/content/en/reference/cli/authelia-gen/authelia-gen_code_keys.md @@ -0,0 +1,35 @@ +--- +title: "authelia-gen code keys" +description: "Reference for the authelia-gen code keys command." +lead: "" +date: 2022-06-03T10:57:43+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia-gen" +weight: 330 +toc: true +--- + +## authelia-gen code keys + +Generate the list of valid configuration keys + +``` +authelia-gen code keys [flags] +``` + +### Options + +``` +  -f, --file string      Sets the path of the keys file (default "./internal/configuration/schema/keys.go") +  -h, --help             help for keys +      --package string   Sets the package name of the keys file (default "schema") +``` + +### SEE ALSO + +* [authelia-gen code](authelia-gen_code.md)	 - Generate code + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-gen/authelia-gen_docs.md b/docs/content/en/reference/cli/authelia-gen/authelia-gen_docs.md new file mode 100644 index 000000000..470c325eb --- /dev/null +++ b/docs/content/en/reference/cli/authelia-gen/authelia-gen_docs.md @@ -0,0 +1,36 @@ +--- +title: "authelia-gen docs" +description: "Reference for the authelia-gen docs command." +lead: "" +date: 2022-06-03T10:57:43+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia-gen" +weight: 330 +toc: true +--- + +## authelia-gen docs + +Generate docs + +``` +authelia-gen docs [flags] +``` + +### Options + +``` +  -C, --cwd string   Sets the CWD for git commands +  -h, --help         help for docs +``` + +### SEE ALSO + +* [authelia-gen](authelia-gen.md)	 - Authelia's generator tooling +* [authelia-gen docs cli](authelia-gen_docs_cli.md)	 - Generate CLI docs +* [authelia-gen docs date](authelia-gen_docs_date.md)	 - Generate doc dates + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-gen/authelia-gen_docs_cli.md b/docs/content/en/reference/cli/authelia-gen/authelia-gen_docs_cli.md new file mode 100644 index 000000000..f9f82f88d --- /dev/null +++ b/docs/content/en/reference/cli/authelia-gen/authelia-gen_docs_cli.md @@ -0,0 +1,40 @@ +--- +title: "authelia-gen docs cli" +description: "Reference for the authelia-gen docs cli command." +lead: "" +date: 2022-06-03T10:57:43+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia-gen" +weight: 330 +toc: true +--- + +## authelia-gen docs cli + +Generate CLI docs + +``` +authelia-gen docs cli [flags] +``` + +### Options + +``` +  -d, --directory string   The directory to store the markdown in (default "./docs/content/en/reference/cli") +  -h, --help               help for cli +``` + +### Options inherited from parent commands + +``` +  -C, --cwd string   Sets the CWD for git commands +``` + +### SEE ALSO + +* [authelia-gen docs](authelia-gen_docs.md)	 - Generate docs + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-gen/authelia-gen_docs_time.md b/docs/content/en/reference/cli/authelia-gen/authelia-gen_docs_time.md new file mode 100644 index 000000000..f9fd43925 --- /dev/null +++ b/docs/content/en/reference/cli/authelia-gen/authelia-gen_docs_time.md @@ -0,0 +1,42 @@ +--- +title: "authelia-gen docs time" +description: "Reference for the authelia-gen docs time command." +lead: "" +date: 2022-06-03T11:17:29+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia-gen" +weight: 330 +toc: true +--- + +## authelia-gen docs time + +Generate doc timestamps + +``` +authelia-gen docs time [flags] +``` + +### Options + +``` +      --commit-since string   The commit to check the logs since +      --commit-until string   The commit to check the logs until (default "HEAD") +  -d, --directory string      The directory to modify (default "./docs/content") +  -h, --help                  help for time +``` + +### Options inherited from parent commands + +``` +  -C, --cwd string   Sets the CWD for git commands +``` + +### SEE ALSO + +* [authelia-gen docs](authelia-gen_docs.md)	 - Generate docs + +###### Auto generated by spf13/cobra on 12-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-scripts/_index.md b/docs/content/en/reference/cli/authelia-scripts/_index.md new file mode 100644 index 000000000..d5900faba --- /dev/null +++ b/docs/content/en/reference/cli/authelia-scripts/_index.md @@ -0,0 +1,14 @@ +--- +title: "authelia-scripts" +description: "" +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli" +    identifier: "cli-authelia-scripts" +weight: 900 +toc: true +--- diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts.md new file mode 100644 index 000000000..1ca489024 --- /dev/null +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts.md @@ -0,0 +1,52 @@ +--- +title: "authelia-scripts" +description: "Reference for the authelia-scripts command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia-scripts" +weight: 320 +toc: true +--- + +## authelia-scripts + +A utility used in the Authelia development process. + +### Synopsis + +The authelia-scripts utility is utilized by developers and the CI/CD pipeline for configuring +testing suites and various other aspects of the environment. + +It can be used to automate or manually run unit testing, integration testing, etc. + +### Examples + +``` +authelia-scripts help +``` + +### Options + +``` +      --buildkite          Set CI flag for Buildkite +  -h, --help               help for authelia-scripts +      --log-level string   Set the log level for the command (default "info") +``` + +### SEE ALSO + +* [authelia-scripts bootstrap](authelia-scripts_bootstrap.md)	 - Prepare environment for development and testing +* [authelia-scripts build](authelia-scripts_build.md)	 - Build Authelia binary and static assets +* [authelia-scripts ci](authelia-scripts_ci.md)	 - Run the continuous integration script +* [authelia-scripts clean](authelia-scripts_clean.md)	 - Clean build artifacts +* [authelia-scripts docker](authelia-scripts_docker.md)	 - Commands related to building and publishing docker image +* [authelia-scripts serve](authelia-scripts_serve.md)	 - Serve compiled version of Authelia +* [authelia-scripts suites](authelia-scripts_suites.md)	 - Commands related to suites management +* [authelia-scripts unittest](authelia-scripts_unittest.md)	 - Run unit tests +* [authelia-scripts xflags](authelia-scripts_xflags.md)	 - Generate X LDFlags for building Authelia + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_bootstrap.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_bootstrap.md new file mode 100644 index 000000000..f06f7d773 --- /dev/null +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_bootstrap.md @@ -0,0 +1,50 @@ +--- +title: "authelia-scripts bootstrap" +description: "Reference for the authelia-scripts bootstrap command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia-scripts" +weight: 330 +toc: true +--- + +## authelia-scripts bootstrap + +Prepare environment for development and testing + +### Synopsis + +Prepare environment for development and testing. + +``` +authelia-scripts bootstrap [flags] +``` + +### Examples + +``` +authelia-scripts bootstrap +``` + +### Options + +``` +  -h, --help   help for bootstrap +``` + +### Options inherited from parent commands + +``` +      --buildkite          Set CI flag for Buildkite +      --log-level string   Set the log level for the command (default "info") +``` + +### SEE ALSO + +* [authelia-scripts](authelia-scripts.md)	 - A utility used in the Authelia development process. + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_build.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_build.md new file mode 100644 index 000000000..959f7c64b --- /dev/null +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_build.md @@ -0,0 +1,50 @@ +--- +title: "authelia-scripts build" +description: "Reference for the authelia-scripts build command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia-scripts" +weight: 330 +toc: true +--- + +## authelia-scripts build + +Build Authelia binary and static assets + +### Synopsis + +Build Authelia binary and static assets. + +``` +authelia-scripts build [flags] +``` + +### Examples + +``` +authelia-scripts build +``` + +### Options + +``` +  -h, --help   help for build +``` + +### Options inherited from parent commands + +``` +      --buildkite          Set CI flag for Buildkite +      --log-level string   Set the log level for the command (default "info") +``` + +### SEE ALSO + +* [authelia-scripts](authelia-scripts.md)	 - A utility used in the Authelia development process. + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_certificates.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_certificates.md new file mode 100644 index 000000000..5179e329e --- /dev/null +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_certificates.md @@ -0,0 +1,39 @@ +--- +title: "authelia-scripts certificates" +description: "Reference for the authelia-scripts certificates command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +lastmod: 2022-06-03T11:17:29+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia-scripts" +weight: 330 +toc: true +--- + +## authelia-scripts certificates + +Commands related to certificate generation + +### Options + +``` +  -h, --help           help for certificates +      --host strings   Comma-separated hostnames and IPs to generate a certificate for +``` + +### Options inherited from parent commands + +``` +      --buildkite          Set CI flag for Buildkite +      --log-level string   Set the log level for the command (default "info") +``` + +### SEE ALSO + +* [authelia-scripts](authelia-scripts.md)	 -  +* [authelia-scripts certificates generate](authelia-scripts_certificates_generate.md)	 - Generate a self-signed certificate + +###### Auto generated by spf13/cobra on 3-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_certificates_generate.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_certificates_generate.md new file mode 100644 index 000000000..462cb2d80 --- /dev/null +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_certificates_generate.md @@ -0,0 +1,49 @@ +--- +title: "authelia-scripts certificates generate" +description: "Reference for the authelia-scripts certificates generate command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +lastmod: 2022-06-03T11:17:29+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia-scripts" +weight: 330 +toc: true +--- + +## authelia-scripts certificates generate + +Generate a self-signed certificate + +``` +authelia-scripts certificates generate [flags] +``` + +### Options + +``` +      --ca                   Whether this cert should be its own Certificate Authority +      --dir string           Target directory where the certificate and keys will be stored +      --duration duration    Duration that certificate is valid for (default 8760h0m0s) +      --ecdsa-curve string   ECDSA curve to use to generate a key. Valid values are P224, P256 (recommended), P384, P521 +      --ed25519              Generate an Ed25519 key +  -h, --help                 help for generate +      --rsa-bits int         Size of RSA key to generate. Ignored if --ecdsa-curve is set (default 2048) +      --start-date string    Creation date formatted as Jan 1 15:04:05 2011 +``` + +### Options inherited from parent commands + +``` +      --buildkite          Set CI flag for Buildkite +      --host strings       Comma-separated hostnames and IPs to generate a certificate for +      --log-level string   Set the log level for the command (default "info") +``` + +### SEE ALSO + +* [authelia-scripts certificates](authelia-scripts_certificates.md)	 - Commands related to certificate generation + +###### Auto generated by spf13/cobra on 3-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_ci.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_ci.md new file mode 100644 index 000000000..2ff57852a --- /dev/null +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_ci.md @@ -0,0 +1,50 @@ +--- +title: "authelia-scripts ci" +description: "Reference for the authelia-scripts ci command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia-scripts" +weight: 330 +toc: true +--- + +## authelia-scripts ci + +Run the continuous integration script + +### Synopsis + +Run the continuous integration script. + +``` +authelia-scripts ci [flags] +``` + +### Examples + +``` +authelia-scripts ci +``` + +### Options + +``` +  -h, --help   help for ci +``` + +### Options inherited from parent commands + +``` +      --buildkite          Set CI flag for Buildkite +      --log-level string   Set the log level for the command (default "info") +``` + +### SEE ALSO + +* [authelia-scripts](authelia-scripts.md)	 - A utility used in the Authelia development process. + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_clean.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_clean.md new file mode 100644 index 000000000..00bf92dcc --- /dev/null +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_clean.md @@ -0,0 +1,50 @@ +--- +title: "authelia-scripts clean" +description: "Reference for the authelia-scripts clean command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia-scripts" +weight: 330 +toc: true +--- + +## authelia-scripts clean + +Clean build artifacts + +### Synopsis + +Clean build artifacts. + +``` +authelia-scripts clean [flags] +``` + +### Examples + +``` +authelia-scripts clean +``` + +### Options + +``` +  -h, --help   help for clean +``` + +### Options inherited from parent commands + +``` +      --buildkite          Set CI flag for Buildkite +      --log-level string   Set the log level for the command (default "info") +``` + +### SEE ALSO + +* [authelia-scripts](authelia-scripts.md)	 - A utility used in the Authelia development process. + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_docker.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_docker.md new file mode 100644 index 000000000..864c0afc5 --- /dev/null +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_docker.md @@ -0,0 +1,52 @@ +--- +title: "authelia-scripts docker" +description: "Reference for the authelia-scripts docker command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia-scripts" +weight: 330 +toc: true +--- + +## authelia-scripts docker + +Commands related to building and publishing docker image + +### Synopsis + +Commands related to building and publishing docker image. + +``` +authelia-scripts docker [flags] +``` + +### Examples + +``` +authelia-scripts docker +``` + +### Options + +``` +  -h, --help   help for docker +``` + +### Options inherited from parent commands + +``` +      --buildkite          Set CI flag for Buildkite +      --log-level string   Set the log level for the command (default "info") +``` + +### SEE ALSO + +* [authelia-scripts](authelia-scripts.md)	 - A utility used in the Authelia development process. +* [authelia-scripts docker build](authelia-scripts_docker_build.md)	 - Build the docker image of Authelia +* [authelia-scripts docker push-manifest](authelia-scripts_docker_push-manifest.md)	 - Push Authelia docker manifest to the Docker registries + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_docker_build.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_docker_build.md new file mode 100644 index 000000000..796797888 --- /dev/null +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_docker_build.md @@ -0,0 +1,51 @@ +--- +title: "authelia-scripts docker build" +description: "Reference for the authelia-scripts docker build command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia-scripts" +weight: 330 +toc: true +--- + +## authelia-scripts docker build + +Build the docker image of Authelia + +### Synopsis + +Build the docker image of Authelia. + +``` +authelia-scripts docker build [flags] +``` + +### Examples + +``` +authelia-scripts docker build +``` + +### Options + +``` +      --container string   target container among: dev, coverage (default "dev") +  -h, --help               help for build +``` + +### Options inherited from parent commands + +``` +      --buildkite          Set CI flag for Buildkite +      --log-level string   Set the log level for the command (default "info") +``` + +### SEE ALSO + +* [authelia-scripts docker](authelia-scripts_docker.md)	 - Commands related to building and publishing docker image + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_docker_push-manifest.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_docker_push-manifest.md new file mode 100644 index 000000000..91c820afc --- /dev/null +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_docker_push-manifest.md @@ -0,0 +1,50 @@ +--- +title: "authelia-scripts docker push-manifest" +description: "Reference for the authelia-scripts docker push-manifest command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia-scripts" +weight: 330 +toc: true +--- + +## authelia-scripts docker push-manifest + +Push Authelia docker manifest to the Docker registries + +### Synopsis + +Push Authelia docker manifest to the Docker registries. + +``` +authelia-scripts docker push-manifest [flags] +``` + +### Examples + +``` +authelia-scripts docker push-manifest +``` + +### Options + +``` +  -h, --help   help for push-manifest +``` + +### Options inherited from parent commands + +``` +      --buildkite          Set CI flag for Buildkite +      --log-level string   Set the log level for the command (default "info") +``` + +### SEE ALSO + +* [authelia-scripts docker](authelia-scripts_docker.md)	 - Commands related to building and publishing docker image + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_hash-password.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_hash-password.md new file mode 100644 index 000000000..8fc11527a --- /dev/null +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_hash-password.md @@ -0,0 +1,49 @@ +--- +title: "authelia-scripts hash-password" +description: "Reference for the authelia-scripts hash-password command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +lastmod: 2022-06-03T11:17:29+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia-scripts" +weight: 330 +toc: true +--- + +## authelia-scripts hash-password + +Hash a password to be used in file-based users database. Default algorithm is argon2id. + +``` +authelia-scripts hash-password [flags] -- <password> +``` + +### Options + +``` +  -c, --config strings    Configuration files +  -h, --help              help for hash-password +  -i, --iterations int    set the number of hashing iterations (default 3) +  -k, --key-length int    [argon2id] set the key length param (default 32) +  -m, --memory int        [argon2id] set the amount of memory param (in MB) (default 64) +  -p, --parallelism int   [argon2id] set the parallelism param (default 4) +  -s, --salt string       set the salt string +  -l, --salt-length int   set the auto-generated salt length (default 16) +  -z, --sha512            use sha512 as the algorithm (changes iterations to 50000, change with -i) +``` + +### Options inherited from parent commands + +``` +      --buildkite          Set CI flag for Buildkite +      --log-level string   Set the log level for the command (default "info") +``` + +### SEE ALSO + +* [authelia-scripts](authelia-scripts.md)	 -  + +###### Auto generated by spf13/cobra on 3-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_rsa.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_rsa.md new file mode 100644 index 000000000..e12a7c54b --- /dev/null +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_rsa.md @@ -0,0 +1,38 @@ +--- +title: "authelia-scripts rsa" +description: "Reference for the authelia-scripts rsa command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +lastmod: 2022-06-03T11:17:29+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia-scripts" +weight: 330 +toc: true +--- + +## authelia-scripts rsa + +Commands related to rsa keypair generation + +### Options + +``` +  -h, --help   help for rsa +``` + +### Options inherited from parent commands + +``` +      --buildkite          Set CI flag for Buildkite +      --log-level string   Set the log level for the command (default "info") +``` + +### SEE ALSO + +* [authelia-scripts](authelia-scripts.md)	 -  +* [authelia-scripts rsa generate](authelia-scripts_rsa_generate.md)	 - Generate a RSA keypair + +###### Auto generated by spf13/cobra on 3-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_rsa_generate.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_rsa_generate.md new file mode 100644 index 000000000..353b7a1ab --- /dev/null +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_rsa_generate.md @@ -0,0 +1,43 @@ +--- +title: "authelia-scripts rsa generate" +description: "Reference for the authelia-scripts rsa generate command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +lastmod: 2022-06-03T11:17:29+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia-scripts" +weight: 330 +toc: true +--- + +## authelia-scripts rsa generate + +Generate a RSA keypair + +``` +authelia-scripts rsa generate [flags] +``` + +### Options + +``` +  -d, --dir string     Target directory where the keypair will be stored +  -h, --help           help for generate +  -b, --key-size int   Sets the key size in bits (default 2048) +``` + +### Options inherited from parent commands + +``` +      --buildkite          Set CI flag for Buildkite +      --log-level string   Set the log level for the command (default "info") +``` + +### SEE ALSO + +* [authelia-scripts rsa](authelia-scripts_rsa.md)	 - Commands related to rsa keypair generation + +###### Auto generated by spf13/cobra on 3-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_serve.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_serve.md new file mode 100644 index 000000000..b7a4b68eb --- /dev/null +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_serve.md @@ -0,0 +1,50 @@ +--- +title: "authelia-scripts serve" +description: "Reference for the authelia-scripts serve command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia-scripts" +weight: 330 +toc: true +--- + +## authelia-scripts serve + +Serve compiled version of Authelia + +### Synopsis + +Serve compiled version of Authelia. + +``` +authelia-scripts serve [config] [flags] +``` + +### Examples + +``` +authelia-scripts serve test.yml +``` + +### Options + +``` +  -h, --help   help for serve +``` + +### Options inherited from parent commands + +``` +      --buildkite          Set CI flag for Buildkite +      --log-level string   Set the log level for the command (default "info") +``` + +### SEE ALSO + +* [authelia-scripts](authelia-scripts.md)	 - A utility used in the Authelia development process. + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_suites.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_suites.md new file mode 100644 index 000000000..b95dbbc6c --- /dev/null +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_suites.md @@ -0,0 +1,54 @@ +--- +title: "authelia-scripts suites" +description: "Reference for the authelia-scripts suites command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia-scripts" +weight: 330 +toc: true +--- + +## authelia-scripts suites + +Commands related to suites management + +### Synopsis + +Commands related to suites management. + +``` +authelia-scripts suites [flags] +``` + +### Examples + +``` +authelia-scripts suites +``` + +### Options + +``` +  -h, --help   help for suites +``` + +### Options inherited from parent commands + +``` +      --buildkite          Set CI flag for Buildkite +      --log-level string   Set the log level for the command (default "info") +``` + +### SEE ALSO + +* [authelia-scripts](authelia-scripts.md)	 - A utility used in the Authelia development process. +* [authelia-scripts suites list](authelia-scripts_suites_list.md)	 - List available suites +* [authelia-scripts suites setup](authelia-scripts_suites_setup.md)	 - Setup a test suite environment +* [authelia-scripts suites teardown](authelia-scripts_suites_teardown.md)	 - Teardown a test suite environment +* [authelia-scripts suites test](authelia-scripts_suites_test.md)	 - Run a test suite + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_suites_list.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_suites_list.md new file mode 100644 index 000000000..6f6890c2d --- /dev/null +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_suites_list.md @@ -0,0 +1,52 @@ +--- +title: "authelia-scripts suites list" +description: "Reference for the authelia-scripts suites list command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia-scripts" +weight: 330 +toc: true +--- + +## authelia-scripts suites list + +List available suites + +### Synopsis + +List available suites. + +Suites can be ran with the authelia-scripts suites test [suite] command. + +``` +authelia-scripts suites list [flags] +``` + +### Examples + +``` +authelia-scripts suites list +``` + +### Options + +``` +  -h, --help   help for list +``` + +### Options inherited from parent commands + +``` +      --buildkite          Set CI flag for Buildkite +      --log-level string   Set the log level for the command (default "info") +``` + +### SEE ALSO + +* [authelia-scripts suites](authelia-scripts_suites.md)	 - Commands related to suites management + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_suites_setup.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_suites_setup.md new file mode 100644 index 000000000..cd18eb486 --- /dev/null +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_suites_setup.md @@ -0,0 +1,52 @@ +--- +title: "authelia-scripts suites setup" +description: "Reference for the authelia-scripts suites setup command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia-scripts" +weight: 330 +toc: true +--- + +## authelia-scripts suites setup + +Setup a test suite environment + +### Synopsis + +Setup a test suite environment. + +Suites can be listed with the authelia-scripts suites list command. + +``` +authelia-scripts suites setup [suite] [flags] +``` + +### Examples + +``` +authelia-scripts suites setup Standalone +``` + +### Options + +``` +  -h, --help   help for setup +``` + +### Options inherited from parent commands + +``` +      --buildkite          Set CI flag for Buildkite +      --log-level string   Set the log level for the command (default "info") +``` + +### SEE ALSO + +* [authelia-scripts suites](authelia-scripts_suites.md)	 - Commands related to suites management + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_suites_teardown.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_suites_teardown.md new file mode 100644 index 000000000..684c353c1 --- /dev/null +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_suites_teardown.md @@ -0,0 +1,52 @@ +--- +title: "authelia-scripts suites teardown" +description: "Reference for the authelia-scripts suites teardown command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia-scripts" +weight: 330 +toc: true +--- + +## authelia-scripts suites teardown + +Teardown a test suite environment + +### Synopsis + +Teardown a test suite environment. + +Suites can be listed with the authelia-scripts suites list command. + +``` +authelia-scripts suites teardown [suite] [flags] +``` + +### Examples + +``` +authelia-scripts suites setup Standalone +``` + +### Options + +``` +  -h, --help   help for teardown +``` + +### Options inherited from parent commands + +``` +      --buildkite          Set CI flag for Buildkite +      --log-level string   Set the log level for the command (default "info") +``` + +### SEE ALSO + +* [authelia-scripts suites](authelia-scripts_suites.md)	 - Commands related to suites management + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_suites_test.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_suites_test.md new file mode 100644 index 000000000..40107937f --- /dev/null +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_suites_test.md @@ -0,0 +1,55 @@ +--- +title: "authelia-scripts suites test" +description: "Reference for the authelia-scripts suites test command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia-scripts" +weight: 330 +toc: true +--- + +## authelia-scripts suites test + +Run a test suite + +### Synopsis + +Run a test suite. + +Suites can be listed with the authelia-scripts suites list command. + +``` +authelia-scripts suites test [suite] [flags] +``` + +### Examples + +``` +authelia-scripts suites test Standalone +``` + +### Options + +``` +      --failfast      Stops tests on first failure +      --headless      Run tests in headless mode +  -h, --help          help for test +      --test string   The single test to run +``` + +### Options inherited from parent commands + +``` +      --buildkite          Set CI flag for Buildkite +      --log-level string   Set the log level for the command (default "info") +``` + +### SEE ALSO + +* [authelia-scripts suites](authelia-scripts_suites.md)	 - Commands related to suites management + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_unittest.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_unittest.md new file mode 100644 index 000000000..cab5550d1 --- /dev/null +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_unittest.md @@ -0,0 +1,50 @@ +--- +title: "authelia-scripts unittest" +description: "Reference for the authelia-scripts unittest command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia-scripts" +weight: 330 +toc: true +--- + +## authelia-scripts unittest + +Run unit tests + +### Synopsis + +Run unit tests. + +``` +authelia-scripts unittest [flags] +``` + +### Examples + +``` +authelia-scripts unittest +``` + +### Options + +``` +  -h, --help   help for unittest +``` + +### Options inherited from parent commands + +``` +      --buildkite          Set CI flag for Buildkite +      --log-level string   Set the log level for the command (default "info") +``` + +### SEE ALSO + +* [authelia-scripts](authelia-scripts.md)	 - A utility used in the Authelia development process. + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_xflags.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_xflags.md new file mode 100644 index 000000000..faa84356e --- /dev/null +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_xflags.md @@ -0,0 +1,52 @@ +--- +title: "authelia-scripts xflags" +description: "Reference for the authelia-scripts xflags command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia-scripts" +weight: 330 +toc: true +--- + +## authelia-scripts xflags + +Generate X LDFlags for building Authelia + +### Synopsis + +Generate X LDFlags for building Authelia. + +``` +authelia-scripts xflags [flags] +``` + +### Examples + +``` +authelia-scripts xflags +``` + +### Options + +``` +  -b, --build string   Sets the BuildNumber flag value (default "0") +  -e, --extra string   Sets the BuildExtra flag value +  -h, --help           help for xflags +``` + +### Options inherited from parent commands + +``` +      --buildkite          Set CI flag for Buildkite +      --log-level string   Set the log level for the command (default "info") +``` + +### SEE ALSO + +* [authelia-scripts](authelia-scripts.md)	 - A utility used in the Authelia development process. + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia/_index.md b/docs/content/en/reference/cli/authelia/_index.md new file mode 100644 index 000000000..012ba9930 --- /dev/null +++ b/docs/content/en/reference/cli/authelia/_index.md @@ -0,0 +1,14 @@ +--- +title: "authelia" +description: "" +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli" +    identifier: "cli-authelia" +weight: 320 +toc: true +--- diff --git a/docs/content/en/reference/cli/authelia/authelia.md b/docs/content/en/reference/cli/authelia/authelia.md new file mode 100644 index 000000000..5bfeff7b5 --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia.md @@ -0,0 +1,58 @@ +--- +title: "authelia" +description: "Reference for the authelia command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia" +weight: 320 +toc: true +--- + +## authelia + +authelia untagged-unknown-dirty (master, unknown) + +### Synopsis + +authelia untagged-unknown-dirty (master, unknown) + +An open-source authentication and authorization server providing +two-factor authentication and single sign-on (SSO) for your +applications via a web portal. + +Documentation is available at: https://www.authelia.com/docs + +``` +authelia [flags] +``` + +### Examples + +``` +authelia --config /etc/authelia/config.yml --config /etc/authelia/access-control.yml +authelia --config /etc/authelia/config.yml,/etc/authelia/access-control.yml +authelia --config /etc/authelia/config/ +``` + +### Options + +``` +  -c, --config strings   configuration files to load +  -h, --help             help for authelia +``` + +### SEE ALSO + +* [authelia access-control](authelia_access-control.md)	 - Helpers for the access control system +* [authelia build-info](authelia_build-info.md)	 - Show the build information of Authelia +* [authelia certificates](authelia_certificates.md)	 - Commands related to certificate generation +* [authelia hash-password](authelia_hash-password.md)	 - Hash a password to be used in file-based users database. +* [authelia rsa](authelia_rsa.md)	 - Commands related to rsa keypair generation +* [authelia storage](authelia_storage.md)	 - Manage the Authelia storage +* [authelia validate-config](authelia_validate-config.md)	 - Check a configuration against the internal configuration validation mechanisms + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia/authelia_access-control.md b/docs/content/en/reference/cli/authelia/authelia_access-control.md new file mode 100644 index 000000000..d525b6585 --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_access-control.md @@ -0,0 +1,40 @@ +--- +title: "authelia access-control" +description: "Reference for the authelia access-control command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia access-control + +Helpers for the access control system + +### Synopsis + +Helpers for the access control system. + +### Examples + +``` +authelia access-control --help +``` + +### Options + +``` +  -h, --help   help for access-control +``` + +### SEE ALSO + +* [authelia](authelia.md)	 - authelia untagged-unknown-dirty (master, unknown) +* [authelia access-control check-policy](authelia_access-control_check-policy.md)	 - Checks a request against the access control rules to determine what policy would be applied + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia/authelia_access-control_check-policy.md b/docs/content/en/reference/cli/authelia/authelia_access-control_check-policy.md new file mode 100644 index 000000000..fbfba5fe5 --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_access-control_check-policy.md @@ -0,0 +1,70 @@ +--- +title: "authelia access-control check-policy" +description: "Reference for the authelia access-control check-policy command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia access-control check-policy + +Checks a request against the access control rules to determine what policy would be applied + +### Synopsis + + +Checks a request against the access control rules to determine what policy would be applied. + +Legend: + +	#		The rule position in the configuration. +	*		The first fully matched rule. +	~		Potential match i.e. if the user was authenticated they may match this rule. +	hit     The criteria in this column is a match to the request. +	miss    The criteria in this column is not match to the request. +	may     The criteria in this column is potentially a match to the request. + +Notes: + +	A rule that potentially matches a request will cause a redirection to occur in order to perform one-factor +	authentication. This is so Authelia can adequately determine if the rule actually matches. + + +``` +authelia access-control check-policy [flags] +``` + +### Examples + +``` +authelia access-control check-policy --config config.yml --url https://example.com +authelia access-control check-policy --config config.yml --url https://example.com --username john +authelia access-control check-policy --config config.yml --url https://example.com --groups admin,public +authelia access-control check-policy --config config.yml --url https://example.com --username john --method GET +authelia access-control check-policy --config config.yml --url https://example.com --username john --method GET --verbose +``` + +### Options + +``` +  -c, --config strings    configuration files to load (default [config.yml]) +      --groups strings    the groups of the subject +  -h, --help              help for check-policy +      --ip string         the ip of the subject +      --method string     the HTTP method of the object (default "GET") +      --url string        the url of the object +      --username string   the username of the subject +      --verbose           enables verbose output +``` + +### SEE ALSO + +* [authelia access-control](authelia_access-control.md)	 - Helpers for the access control system + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia/authelia_build-info.md b/docs/content/en/reference/cli/authelia/authelia_build-info.md new file mode 100644 index 000000000..20c17b546 --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_build-info.md @@ -0,0 +1,52 @@ +--- +title: "authelia build-info" +description: "Reference for the authelia build-info command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia build-info + +Show the build information of Authelia + +### Synopsis + +Show the build information of Authelia. + +This outputs detailed version information about the specific version +of the Authelia binary. This information is embedded into Authelia +by the continuous integration. + +This could be vital in debugging if you're not using a particular +tagged build of Authelia. It's suggested to provide it along with +your issue. + + +``` +authelia build-info [flags] +``` + +### Examples + +``` +authelia build-info +``` + +### Options + +``` +  -h, --help   help for build-info +``` + +### SEE ALSO + +* [authelia](authelia.md)	 - authelia untagged-unknown-dirty (master, unknown) + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia/authelia_certificates.md b/docs/content/en/reference/cli/authelia/authelia_certificates.md new file mode 100644 index 000000000..8583c53ff --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_certificates.md @@ -0,0 +1,43 @@ +--- +title: "authelia certificates" +description: "Reference for the authelia certificates command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia certificates + +Commands related to certificate generation + +### Synopsis + +Commands related to certificate generation. + +This subcommand allows preforming X509 certificate tasks. + +### Examples + +``` +authelia certificates --help +``` + +### Options + +``` +  -h, --help           help for certificates +      --host strings   Comma-separated hostnames and IPs to generate a certificate for +``` + +### SEE ALSO + +* [authelia](authelia.md)	 - authelia untagged-unknown-dirty (master, unknown) +* [authelia certificates generate](authelia_certificates_generate.md)	 - Generate a self-signed certificate + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia/authelia_certificates_generate.md b/docs/content/en/reference/cli/authelia/authelia_certificates_generate.md new file mode 100644 index 000000000..672549c5f --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_certificates_generate.md @@ -0,0 +1,59 @@ +--- +title: "authelia certificates generate" +description: "Reference for the authelia certificates generate command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia certificates generate + +Generate a self-signed certificate + +### Synopsis + +Generate a self-signed certificate. + +This subcommand allows generating self-signed certificates. + +``` +authelia certificates generate [flags] +``` + +### Examples + +``` +authelia certificates generate +authelia certificates generate --dir ./out +``` + +### Options + +``` +      --ca                   Whether this cert should be its own Certificate Authority +      --dir string           Target directory where the certificate and keys will be stored +      --duration duration    Duration that certificate is valid for (default 8760h0m0s) +      --ecdsa-curve string   ECDSA curve to use to generate a key. Valid values are P224, P256 (recommended), P384, P521 +      --ed25519              Generate an Ed25519 key +  -h, --help                 help for generate +      --rsa-bits int         Size of RSA key to generate. Ignored if --ecdsa-curve is set (default 2048) +      --start-date string    Creation date formatted as Jan 1 15:04:05 2011 +``` + +### Options inherited from parent commands + +``` +      --host strings   Comma-separated hostnames and IPs to generate a certificate for +``` + +### SEE ALSO + +* [authelia certificates](authelia_certificates.md)	 - Commands related to certificate generation + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia/authelia_hash-password.md b/docs/content/en/reference/cli/authelia/authelia_hash-password.md new file mode 100644 index 000000000..cd66e6de8 --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_hash-password.md @@ -0,0 +1,56 @@ +--- +title: "authelia hash-password" +description: "Reference for the authelia hash-password command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia hash-password + +Hash a password to be used in file-based users database. + +### Synopsis + +Hash a password to be used in file-based users database. + +``` +authelia hash-password [flags] -- <password> +``` + +### Examples + +``` +authelia hash-password -- 'mypass' +authelia hash-password --sha512 -- 'mypass' +authelia hash-password --iterations=4 -- 'mypass' +authelia hash-password --memory=128 -- 'mypass' +authelia hash-password --parallelism=1 -- 'mypass' +authelia hash-password --key-length=64 -- 'mypass' +``` + +### Options + +``` +  -c, --config strings    Configuration files +  -h, --help              help for hash-password +  -i, --iterations int    set the number of hashing iterations (default 3) +  -k, --key-length int    [argon2id] set the key length param (default 32) +  -m, --memory int        [argon2id] set the amount of memory param (in MB) (default 64) +  -p, --parallelism int   [argon2id] set the parallelism param (default 4) +  -s, --salt string       set the salt string +  -l, --salt-length int   set the auto-generated salt length (default 16) +  -z, --sha512            use sha512 as the algorithm (changes iterations to 50000, change with -i) +``` + +### SEE ALSO + +* [authelia](authelia.md)	 - authelia untagged-unknown-dirty (master, unknown) + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia/authelia_rsa.md b/docs/content/en/reference/cli/authelia/authelia_rsa.md new file mode 100644 index 000000000..ea3b6469b --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_rsa.md @@ -0,0 +1,42 @@ +--- +title: "authelia rsa" +description: "Reference for the authelia rsa command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia rsa + +Commands related to rsa keypair generation + +### Synopsis + +Commands related to rsa keypair generation. + +This subcommand allows performing RSA keypair tasks. + +### Examples + +``` +authelia rsa --help +``` + +### Options + +``` +  -h, --help   help for rsa +``` + +### SEE ALSO + +* [authelia](authelia.md)	 - authelia untagged-unknown-dirty (master, unknown) +* [authelia rsa generate](authelia_rsa_generate.md)	 - Generate a RSA keypair + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia/authelia_rsa_generate.md b/docs/content/en/reference/cli/authelia/authelia_rsa_generate.md new file mode 100644 index 000000000..9b80d345c --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_rsa_generate.md @@ -0,0 +1,48 @@ +--- +title: "authelia rsa generate" +description: "Reference for the authelia rsa generate command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia rsa generate + +Generate a RSA keypair + +### Synopsis + +Generate a RSA keypair. + +This subcommand allows generating an RSA keypair. + +``` +authelia rsa generate [flags] +``` + +### Examples + +``` +authelia rsa generate +authelia rsa generate --dir ./out +``` + +### Options + +``` +  -d, --dir string     Target directory where the keypair will be stored +  -h, --help           help for generate +  -b, --key-size int   Sets the key size in bits (default 2048) +``` + +### SEE ALSO + +* [authelia rsa](authelia_rsa.md)	 - Commands related to rsa keypair generation + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia/authelia_storage.md b/docs/content/en/reference/cli/authelia/authelia_storage.md new file mode 100644 index 000000000..0423b9b68 --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_storage.md @@ -0,0 +1,65 @@ +--- +title: "authelia storage" +description: "Reference for the authelia storage command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia storage + +Manage the Authelia storage + +### Synopsis + +Manage the Authelia storage. + +This subcommand has several methods to interact with the Authelia SQL Database. This allows doing several advanced +operations which would be much harder to do manually. + + +### Examples + +``` +authelia storage --help +``` + +### Options + +``` +  -c, --config strings                         configuration files to load (default [configuration.yml]) +      --encryption-key string                  the storage encryption key to use +  -h, --help                                   help for storage +      --mysql.database string                  the MySQL database name (default "authelia") +      --mysql.host string                      the MySQL hostname +      --mysql.password string                  the MySQL password +      --mysql.port int                         the MySQL port (default 3306) +      --mysql.username string                  the MySQL username (default "authelia") +      --postgres.database string               the PostgreSQL database name (default "authelia") +      --postgres.host string                   the PostgreSQL hostname +      --postgres.password string               the PostgreSQL password +      --postgres.port int                      the PostgreSQL port (default 5432) +      --postgres.schema string                 the PostgreSQL schema name (default "public") +      --postgres.ssl.certificate string        the PostgreSQL ssl certificate file location +      --postgres.ssl.key string                the PostgreSQL ssl key file location +      --postgres.ssl.mode string               the PostgreSQL ssl mode (default "disable") +      --postgres.ssl.root_certificate string   the PostgreSQL ssl root certificate file location +      --postgres.username string               the PostgreSQL username (default "authelia") +      --sqlite.path string                     the SQLite database path +``` + +### SEE ALSO + +* [authelia](authelia.md)	 - authelia untagged-unknown-dirty (master, unknown) +* [authelia storage encryption](authelia_storage_encryption.md)	 - Manage storage encryption +* [authelia storage migrate](authelia_storage_migrate.md)	 - Perform or list migrations +* [authelia storage schema-info](authelia_storage_schema-info.md)	 - Show the storage information +* [authelia storage user](authelia_storage_user.md)	 - Manages user settings + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_encryption.md b/docs/content/en/reference/cli/authelia/authelia_storage_encryption.md new file mode 100644 index 000000000..a119ec7f4 --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_storage_encryption.md @@ -0,0 +1,66 @@ +--- +title: "authelia storage encryption" +description: "Reference for the authelia storage encryption command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia storage encryption + +Manage storage encryption + +### Synopsis + +Manage storage encryption. + +This subcommand allows management of the storage encryption. + +### Examples + +``` +authelia storage encryption --help +``` + +### Options + +``` +  -h, --help   help for encryption +``` + +### Options inherited from parent commands + +``` +  -c, --config strings                         configuration files to load (default [configuration.yml]) +      --encryption-key string                  the storage encryption key to use +      --mysql.database string                  the MySQL database name (default "authelia") +      --mysql.host string                      the MySQL hostname +      --mysql.password string                  the MySQL password +      --mysql.port int                         the MySQL port (default 3306) +      --mysql.username string                  the MySQL username (default "authelia") +      --postgres.database string               the PostgreSQL database name (default "authelia") +      --postgres.host string                   the PostgreSQL hostname +      --postgres.password string               the PostgreSQL password +      --postgres.port int                      the PostgreSQL port (default 5432) +      --postgres.schema string                 the PostgreSQL schema name (default "public") +      --postgres.ssl.certificate string        the PostgreSQL ssl certificate file location +      --postgres.ssl.key string                the PostgreSQL ssl key file location +      --postgres.ssl.mode string               the PostgreSQL ssl mode (default "disable") +      --postgres.ssl.root_certificate string   the PostgreSQL ssl root certificate file location +      --postgres.username string               the PostgreSQL username (default "authelia") +      --sqlite.path string                     the SQLite database path +``` + +### SEE ALSO + +* [authelia storage](authelia_storage.md)	 - Manage the Authelia storage +* [authelia storage encryption change-key](authelia_storage_encryption_change-key.md)	 - Changes the encryption key +* [authelia storage encryption check](authelia_storage_encryption_check.md)	 - Checks the encryption key against the database data + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_encryption_change-key.md b/docs/content/en/reference/cli/authelia/authelia_storage_encryption_change-key.md new file mode 100644 index 000000000..f6fb2d41e --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_storage_encryption_change-key.md @@ -0,0 +1,70 @@ +--- +title: "authelia storage encryption change-key" +description: "Reference for the authelia storage encryption change-key command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia storage encryption change-key + +Changes the encryption key + +### Synopsis + +Changes the encryption key. + +This subcommand allows you to change the encryption key of an Authelia SQL database. + +``` +authelia storage encryption change-key [flags] +``` + +### Examples + +``` +authelia storage encryption change-key --config config.yml --new-encryption-key 0e95cb49-5804-4ad9-be82-bb04a9ddecd8 +authelia storage encryption change-key --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --new-encryption-key 0e95cb49-5804-4ad9-be82-bb04a9ddecd8 --postgres.host postgres --postgres.password autheliapw +``` + +### Options + +``` +  -h, --help                        help for change-key +      --new-encryption-key string   the new key to encrypt the data with +``` + +### Options inherited from parent commands + +``` +  -c, --config strings                         configuration files to load (default [configuration.yml]) +      --encryption-key string                  the storage encryption key to use +      --mysql.database string                  the MySQL database name (default "authelia") +      --mysql.host string                      the MySQL hostname +      --mysql.password string                  the MySQL password +      --mysql.port int                         the MySQL port (default 3306) +      --mysql.username string                  the MySQL username (default "authelia") +      --postgres.database string               the PostgreSQL database name (default "authelia") +      --postgres.host string                   the PostgreSQL hostname +      --postgres.password string               the PostgreSQL password +      --postgres.port int                      the PostgreSQL port (default 5432) +      --postgres.schema string                 the PostgreSQL schema name (default "public") +      --postgres.ssl.certificate string        the PostgreSQL ssl certificate file location +      --postgres.ssl.key string                the PostgreSQL ssl key file location +      --postgres.ssl.mode string               the PostgreSQL ssl mode (default "disable") +      --postgres.ssl.root_certificate string   the PostgreSQL ssl root certificate file location +      --postgres.username string               the PostgreSQL username (default "authelia") +      --sqlite.path string                     the SQLite database path +``` + +### SEE ALSO + +* [authelia storage encryption](authelia_storage_encryption.md)	 - Manage storage encryption + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_encryption_check.md b/docs/content/en/reference/cli/authelia/authelia_storage_encryption_check.md new file mode 100644 index 000000000..96c225e87 --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_storage_encryption_check.md @@ -0,0 +1,72 @@ +--- +title: "authelia storage encryption check" +description: "Reference for the authelia storage encryption check command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia storage encryption check + +Checks the encryption key against the database data + +### Synopsis + +Checks the encryption key against the database data. + +This is useful for validating all data that can be encrypted is intact. + +``` +authelia storage encryption check [flags] +``` + +### Examples + +``` +authelia storage encryption check +authelia storage encryption check --verbose +authelia storage encryption check --verbose --config config.yml +authelia storage encryption check --verbose --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw +``` + +### Options + +``` +  -h, --help      help for check +      --verbose   enables verbose checking of every row of encrypted data +``` + +### Options inherited from parent commands + +``` +  -c, --config strings                         configuration files to load (default [configuration.yml]) +      --encryption-key string                  the storage encryption key to use +      --mysql.database string                  the MySQL database name (default "authelia") +      --mysql.host string                      the MySQL hostname +      --mysql.password string                  the MySQL password +      --mysql.port int                         the MySQL port (default 3306) +      --mysql.username string                  the MySQL username (default "authelia") +      --postgres.database string               the PostgreSQL database name (default "authelia") +      --postgres.host string                   the PostgreSQL hostname +      --postgres.password string               the PostgreSQL password +      --postgres.port int                      the PostgreSQL port (default 5432) +      --postgres.schema string                 the PostgreSQL schema name (default "public") +      --postgres.ssl.certificate string        the PostgreSQL ssl certificate file location +      --postgres.ssl.key string                the PostgreSQL ssl key file location +      --postgres.ssl.mode string               the PostgreSQL ssl mode (default "disable") +      --postgres.ssl.root_certificate string   the PostgreSQL ssl root certificate file location +      --postgres.username string               the PostgreSQL username (default "authelia") +      --sqlite.path string                     the SQLite database path +``` + +### SEE ALSO + +* [authelia storage encryption](authelia_storage_encryption.md)	 - Manage storage encryption + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_migrate.md b/docs/content/en/reference/cli/authelia/authelia_storage_migrate.md new file mode 100644 index 000000000..383f29757 --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_storage_migrate.md @@ -0,0 +1,69 @@ +--- +title: "authelia storage migrate" +description: "Reference for the authelia storage migrate command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia storage migrate + +Perform or list migrations + +### Synopsis + +Perform or list migrations. + +This subcommand handles schema migration tasks. + +### Examples + +``` +authelia storage migrate --help +``` + +### Options + +``` +  -h, --help   help for migrate +``` + +### Options inherited from parent commands + +``` +  -c, --config strings                         configuration files to load (default [configuration.yml]) +      --encryption-key string                  the storage encryption key to use +      --mysql.database string                  the MySQL database name (default "authelia") +      --mysql.host string                      the MySQL hostname +      --mysql.password string                  the MySQL password +      --mysql.port int                         the MySQL port (default 3306) +      --mysql.username string                  the MySQL username (default "authelia") +      --postgres.database string               the PostgreSQL database name (default "authelia") +      --postgres.host string                   the PostgreSQL hostname +      --postgres.password string               the PostgreSQL password +      --postgres.port int                      the PostgreSQL port (default 5432) +      --postgres.schema string                 the PostgreSQL schema name (default "public") +      --postgres.ssl.certificate string        the PostgreSQL ssl certificate file location +      --postgres.ssl.key string                the PostgreSQL ssl key file location +      --postgres.ssl.mode string               the PostgreSQL ssl mode (default "disable") +      --postgres.ssl.root_certificate string   the PostgreSQL ssl root certificate file location +      --postgres.username string               the PostgreSQL username (default "authelia") +      --sqlite.path string                     the SQLite database path +``` + +### SEE ALSO + +* [authelia storage](authelia_storage.md)	 - Manage the Authelia storage +* [authelia storage migrate down](authelia_storage_migrate_down.md)	 - Perform a migration down +* [authelia storage migrate history](authelia_storage_migrate_history.md)	 - Show migration history +* [authelia storage migrate list-down](authelia_storage_migrate_list-down.md)	 - List the down migrations available +* [authelia storage migrate list-up](authelia_storage_migrate_list-up.md)	 - List the up migrations available +* [authelia storage migrate up](authelia_storage_migrate_up.md)	 - Perform a migration up + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_migrate_down.md b/docs/content/en/reference/cli/authelia/authelia_storage_migrate_down.md new file mode 100644 index 000000000..07ee94ffc --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_storage_migrate_down.md @@ -0,0 +1,74 @@ +--- +title: "authelia storage migrate down" +description: "Reference for the authelia storage migrate down command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia storage migrate down + +Perform a migration down + +### Synopsis + +Perform a migration down. + +This subcommand performs the schema migrations available in this version of Authelia which are less than the current +schema version of the database. + +``` +authelia storage migrate down [flags] +``` + +### Examples + +``` +authelia storage migrate down --target 20 +authelia storage migrate down --target 20 --config config.yml +authelia storage migrate down --target 20 --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw +``` + +### Options + +``` +      --destroy-data   confirms you want to destroy data with this migration +  -h, --help           help for down +      --pre1           sets pre1 as the version to migrate to +  -t, --target int     sets the version to migrate to +``` + +### Options inherited from parent commands + +``` +  -c, --config strings                         configuration files to load (default [configuration.yml]) +      --encryption-key string                  the storage encryption key to use +      --mysql.database string                  the MySQL database name (default "authelia") +      --mysql.host string                      the MySQL hostname +      --mysql.password string                  the MySQL password +      --mysql.port int                         the MySQL port (default 3306) +      --mysql.username string                  the MySQL username (default "authelia") +      --postgres.database string               the PostgreSQL database name (default "authelia") +      --postgres.host string                   the PostgreSQL hostname +      --postgres.password string               the PostgreSQL password +      --postgres.port int                      the PostgreSQL port (default 5432) +      --postgres.schema string                 the PostgreSQL schema name (default "public") +      --postgres.ssl.certificate string        the PostgreSQL ssl certificate file location +      --postgres.ssl.key string                the PostgreSQL ssl key file location +      --postgres.ssl.mode string               the PostgreSQL ssl mode (default "disable") +      --postgres.ssl.root_certificate string   the PostgreSQL ssl root certificate file location +      --postgres.username string               the PostgreSQL username (default "authelia") +      --sqlite.path string                     the SQLite database path +``` + +### SEE ALSO + +* [authelia storage migrate](authelia_storage_migrate.md)	 - Perform or list migrations + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_migrate_history.md b/docs/content/en/reference/cli/authelia/authelia_storage_migrate_history.md new file mode 100644 index 000000000..c1b5af4ea --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_storage_migrate_history.md @@ -0,0 +1,70 @@ +--- +title: "authelia storage migrate history" +description: "Reference for the authelia storage migrate history command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia storage migrate history + +Show migration history + +### Synopsis + +Show migration history. + +This subcommand allows users to list previous migrations. + +``` +authelia storage migrate history [flags] +``` + +### Examples + +``` +authelia storage migrate history +authelia storage migrate history --config config.yml +authelia storage migrate history --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw +``` + +### Options + +``` +  -h, --help   help for history +``` + +### Options inherited from parent commands + +``` +  -c, --config strings                         configuration files to load (default [configuration.yml]) +      --encryption-key string                  the storage encryption key to use +      --mysql.database string                  the MySQL database name (default "authelia") +      --mysql.host string                      the MySQL hostname +      --mysql.password string                  the MySQL password +      --mysql.port int                         the MySQL port (default 3306) +      --mysql.username string                  the MySQL username (default "authelia") +      --postgres.database string               the PostgreSQL database name (default "authelia") +      --postgres.host string                   the PostgreSQL hostname +      --postgres.password string               the PostgreSQL password +      --postgres.port int                      the PostgreSQL port (default 5432) +      --postgres.schema string                 the PostgreSQL schema name (default "public") +      --postgres.ssl.certificate string        the PostgreSQL ssl certificate file location +      --postgres.ssl.key string                the PostgreSQL ssl key file location +      --postgres.ssl.mode string               the PostgreSQL ssl mode (default "disable") +      --postgres.ssl.root_certificate string   the PostgreSQL ssl root certificate file location +      --postgres.username string               the PostgreSQL username (default "authelia") +      --sqlite.path string                     the SQLite database path +``` + +### SEE ALSO + +* [authelia storage migrate](authelia_storage_migrate.md)	 - Perform or list migrations + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_migrate_list-down.md b/docs/content/en/reference/cli/authelia/authelia_storage_migrate_list-down.md new file mode 100644 index 000000000..b1d8f0481 --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_storage_migrate_list-down.md @@ -0,0 +1,71 @@ +--- +title: "authelia storage migrate list-down" +description: "Reference for the authelia storage migrate list-down command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia storage migrate list-down + +List the down migrations available + +### Synopsis + +List the down migrations available. + +This subcommand lists the schema migrations available in this version of Authelia which are less than the current +schema version of the database. + +``` +authelia storage migrate list-down [flags] +``` + +### Examples + +``` +authelia storage migrate list-down +authelia storage migrate list-down --config config.yml +authelia storage migrate list-down --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw +``` + +### Options + +``` +  -h, --help   help for list-down +``` + +### Options inherited from parent commands + +``` +  -c, --config strings                         configuration files to load (default [configuration.yml]) +      --encryption-key string                  the storage encryption key to use +      --mysql.database string                  the MySQL database name (default "authelia") +      --mysql.host string                      the MySQL hostname +      --mysql.password string                  the MySQL password +      --mysql.port int                         the MySQL port (default 3306) +      --mysql.username string                  the MySQL username (default "authelia") +      --postgres.database string               the PostgreSQL database name (default "authelia") +      --postgres.host string                   the PostgreSQL hostname +      --postgres.password string               the PostgreSQL password +      --postgres.port int                      the PostgreSQL port (default 5432) +      --postgres.schema string                 the PostgreSQL schema name (default "public") +      --postgres.ssl.certificate string        the PostgreSQL ssl certificate file location +      --postgres.ssl.key string                the PostgreSQL ssl key file location +      --postgres.ssl.mode string               the PostgreSQL ssl mode (default "disable") +      --postgres.ssl.root_certificate string   the PostgreSQL ssl root certificate file location +      --postgres.username string               the PostgreSQL username (default "authelia") +      --sqlite.path string                     the SQLite database path +``` + +### SEE ALSO + +* [authelia storage migrate](authelia_storage_migrate.md)	 - Perform or list migrations + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_migrate_list-up.md b/docs/content/en/reference/cli/authelia/authelia_storage_migrate_list-up.md new file mode 100644 index 000000000..075ef56a2 --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_storage_migrate_list-up.md @@ -0,0 +1,71 @@ +--- +title: "authelia storage migrate list-up" +description: "Reference for the authelia storage migrate list-up command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia storage migrate list-up + +List the up migrations available + +### Synopsis + +List the up migrations available. + +This subcommand lists the schema migrations available in this version of Authelia which are greater than the current +schema version of the database. + +``` +authelia storage migrate list-up [flags] +``` + +### Examples + +``` +authelia storage migrate list-up +authelia storage migrate list-up --config config.yml +authelia storage migrate list-up --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw +``` + +### Options + +``` +  -h, --help   help for list-up +``` + +### Options inherited from parent commands + +``` +  -c, --config strings                         configuration files to load (default [configuration.yml]) +      --encryption-key string                  the storage encryption key to use +      --mysql.database string                  the MySQL database name (default "authelia") +      --mysql.host string                      the MySQL hostname +      --mysql.password string                  the MySQL password +      --mysql.port int                         the MySQL port (default 3306) +      --mysql.username string                  the MySQL username (default "authelia") +      --postgres.database string               the PostgreSQL database name (default "authelia") +      --postgres.host string                   the PostgreSQL hostname +      --postgres.password string               the PostgreSQL password +      --postgres.port int                      the PostgreSQL port (default 5432) +      --postgres.schema string                 the PostgreSQL schema name (default "public") +      --postgres.ssl.certificate string        the PostgreSQL ssl certificate file location +      --postgres.ssl.key string                the PostgreSQL ssl key file location +      --postgres.ssl.mode string               the PostgreSQL ssl mode (default "disable") +      --postgres.ssl.root_certificate string   the PostgreSQL ssl root certificate file location +      --postgres.username string               the PostgreSQL username (default "authelia") +      --sqlite.path string                     the SQLite database path +``` + +### SEE ALSO + +* [authelia storage migrate](authelia_storage_migrate.md)	 - Perform or list migrations + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_migrate_up.md b/docs/content/en/reference/cli/authelia/authelia_storage_migrate_up.md new file mode 100644 index 000000000..bd3d19fb0 --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_storage_migrate_up.md @@ -0,0 +1,73 @@ +--- +title: "authelia storage migrate up" +description: "Reference for the authelia storage migrate up command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia storage migrate up + +Perform a migration up + +### Synopsis + +Perform a migration up. + +This subcommand performs the schema migrations available in this version of Authelia which are greater than the current +schema version of the database. By default this will migrate up to the latest available, but you can customize this. + +``` +authelia storage migrate up [flags] +``` + +### Examples + +``` +authelia storage migrate up +authelia storage migrate up --config config.yml +authelia storage migrate up --target 20 --config config.yml +authelia storage migrate up --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw +``` + +### Options + +``` +  -h, --help         help for up +  -t, --target int   sets the version to migrate to, by default this is the latest version +``` + +### Options inherited from parent commands + +``` +  -c, --config strings                         configuration files to load (default [configuration.yml]) +      --encryption-key string                  the storage encryption key to use +      --mysql.database string                  the MySQL database name (default "authelia") +      --mysql.host string                      the MySQL hostname +      --mysql.password string                  the MySQL password +      --mysql.port int                         the MySQL port (default 3306) +      --mysql.username string                  the MySQL username (default "authelia") +      --postgres.database string               the PostgreSQL database name (default "authelia") +      --postgres.host string                   the PostgreSQL hostname +      --postgres.password string               the PostgreSQL password +      --postgres.port int                      the PostgreSQL port (default 5432) +      --postgres.schema string                 the PostgreSQL schema name (default "public") +      --postgres.ssl.certificate string        the PostgreSQL ssl certificate file location +      --postgres.ssl.key string                the PostgreSQL ssl key file location +      --postgres.ssl.mode string               the PostgreSQL ssl mode (default "disable") +      --postgres.ssl.root_certificate string   the PostgreSQL ssl root certificate file location +      --postgres.username string               the PostgreSQL username (default "authelia") +      --sqlite.path string                     the SQLite database path +``` + +### SEE ALSO + +* [authelia storage migrate](authelia_storage_migrate.md)	 - Perform or list migrations + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_schema-info.md b/docs/content/en/reference/cli/authelia/authelia_storage_schema-info.md new file mode 100644 index 000000000..08a1a7cd8 --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_storage_schema-info.md @@ -0,0 +1,70 @@ +--- +title: "authelia storage schema-info" +description: "Reference for the authelia storage schema-info command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia storage schema-info + +Show the storage information + +### Synopsis + +Show the storage information. + +This subcommand shows advanced information about the storage schema useful in some diagnostic tasks. + +``` +authelia storage schema-info [flags] +``` + +### Examples + +``` +authelia storage schema-info +authelia storage schema-info --config config.yml +authelia storage schema-info --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw +``` + +### Options + +``` +  -h, --help   help for schema-info +``` + +### Options inherited from parent commands + +``` +  -c, --config strings                         configuration files to load (default [configuration.yml]) +      --encryption-key string                  the storage encryption key to use +      --mysql.database string                  the MySQL database name (default "authelia") +      --mysql.host string                      the MySQL hostname +      --mysql.password string                  the MySQL password +      --mysql.port int                         the MySQL port (default 3306) +      --mysql.username string                  the MySQL username (default "authelia") +      --postgres.database string               the PostgreSQL database name (default "authelia") +      --postgres.host string                   the PostgreSQL hostname +      --postgres.password string               the PostgreSQL password +      --postgres.port int                      the PostgreSQL port (default 5432) +      --postgres.schema string                 the PostgreSQL schema name (default "public") +      --postgres.ssl.certificate string        the PostgreSQL ssl certificate file location +      --postgres.ssl.key string                the PostgreSQL ssl key file location +      --postgres.ssl.mode string               the PostgreSQL ssl mode (default "disable") +      --postgres.ssl.root_certificate string   the PostgreSQL ssl root certificate file location +      --postgres.username string               the PostgreSQL username (default "authelia") +      --sqlite.path string                     the SQLite database path +``` + +### SEE ALSO + +* [authelia storage](authelia_storage.md)	 - Manage the Authelia storage + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_user.md b/docs/content/en/reference/cli/authelia/authelia_storage_user.md new file mode 100644 index 000000000..31ff94c2f --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_storage_user.md @@ -0,0 +1,66 @@ +--- +title: "authelia storage user" +description: "Reference for the authelia storage user command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia storage user + +Manages user settings + +### Synopsis + +Manages user settings. + +This subcommand allows modifying and exporting user settings. + +### Examples + +``` +authelia storage user --help +``` + +### Options + +``` +  -h, --help   help for user +``` + +### Options inherited from parent commands + +``` +  -c, --config strings                         configuration files to load (default [configuration.yml]) +      --encryption-key string                  the storage encryption key to use +      --mysql.database string                  the MySQL database name (default "authelia") +      --mysql.host string                      the MySQL hostname +      --mysql.password string                  the MySQL password +      --mysql.port int                         the MySQL port (default 3306) +      --mysql.username string                  the MySQL username (default "authelia") +      --postgres.database string               the PostgreSQL database name (default "authelia") +      --postgres.host string                   the PostgreSQL hostname +      --postgres.password string               the PostgreSQL password +      --postgres.port int                      the PostgreSQL port (default 5432) +      --postgres.schema string                 the PostgreSQL schema name (default "public") +      --postgres.ssl.certificate string        the PostgreSQL ssl certificate file location +      --postgres.ssl.key string                the PostgreSQL ssl key file location +      --postgres.ssl.mode string               the PostgreSQL ssl mode (default "disable") +      --postgres.ssl.root_certificate string   the PostgreSQL ssl root certificate file location +      --postgres.username string               the PostgreSQL username (default "authelia") +      --sqlite.path string                     the SQLite database path +``` + +### SEE ALSO + +* [authelia storage](authelia_storage.md)	 - Manage the Authelia storage +* [authelia storage user identifiers](authelia_storage_user_identifiers.md)	 - Manage user opaque identifiers +* [authelia storage user totp](authelia_storage_user_totp.md)	 - Manage TOTP configurations + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_user_identifiers.md b/docs/content/en/reference/cli/authelia/authelia_storage_user_identifiers.md new file mode 100644 index 000000000..c5c853ece --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_storage_user_identifiers.md @@ -0,0 +1,68 @@ +--- +title: "authelia storage user identifiers" +description: "Reference for the authelia storage user identifiers command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia storage user identifiers + +Manage user opaque identifiers + +### Synopsis + +Manage user opaque identifiers. + +This subcommand allows performing various tasks related to the opaque identifiers for users. + +### Examples + +``` +authelia storage user identifiers --help +``` + +### Options + +``` +  -h, --help   help for identifiers +``` + +### Options inherited from parent commands + +``` +  -c, --config strings                         configuration files to load (default [configuration.yml]) +      --encryption-key string                  the storage encryption key to use +      --mysql.database string                  the MySQL database name (default "authelia") +      --mysql.host string                      the MySQL hostname +      --mysql.password string                  the MySQL password +      --mysql.port int                         the MySQL port (default 3306) +      --mysql.username string                  the MySQL username (default "authelia") +      --postgres.database string               the PostgreSQL database name (default "authelia") +      --postgres.host string                   the PostgreSQL hostname +      --postgres.password string               the PostgreSQL password +      --postgres.port int                      the PostgreSQL port (default 5432) +      --postgres.schema string                 the PostgreSQL schema name (default "public") +      --postgres.ssl.certificate string        the PostgreSQL ssl certificate file location +      --postgres.ssl.key string                the PostgreSQL ssl key file location +      --postgres.ssl.mode string               the PostgreSQL ssl mode (default "disable") +      --postgres.ssl.root_certificate string   the PostgreSQL ssl root certificate file location +      --postgres.username string               the PostgreSQL username (default "authelia") +      --sqlite.path string                     the SQLite database path +``` + +### SEE ALSO + +* [authelia storage user](authelia_storage_user.md)	 - Manages user settings +* [authelia storage user identifiers add](authelia_storage_user_identifiers_add.md)	 - Add an opaque identifier for a user to the database +* [authelia storage user identifiers export](authelia_storage_user_identifiers_export.md)	 - Export the identifiers to a YAML file +* [authelia storage user identifiers generate](authelia_storage_user_identifiers_generate.md)	 - Generate opaque identifiers in bulk +* [authelia storage user identifiers import](authelia_storage_user_identifiers_import.md)	 - Import the identifiers from a YAML file + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_user_identifiers_add.md b/docs/content/en/reference/cli/authelia/authelia_storage_user_identifiers_add.md new file mode 100644 index 000000000..7ca3f171c --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_storage_user_identifiers_add.md @@ -0,0 +1,73 @@ +--- +title: "authelia storage user identifiers add" +description: "Reference for the authelia storage user identifiers add command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia storage user identifiers add + +Add an opaque identifier for a user to the database + +### Synopsis + +Add an opaque identifier for a user to the database. + +This subcommand allows manually adding an opaque identifier for a user to the database provided it's in the correct format. + +``` +authelia storage user identifiers add <username> [flags] +``` + +### Examples + +``` +authelia storage user identifiers add john --identifier f0919359-9d15-4e15-bcba-83b41620a073 +authelia storage user identifiers add john --identifier f0919359-9d15-4e15-bcba-83b41620a073 --config config.yml +authelia storage user identifiers add john --identifier f0919359-9d15-4e15-bcba-83b41620a073 --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw +``` + +### Options + +``` +  -h, --help                help for add +      --identifier string   The optional version 4 UUID to use, if not set a random one will be used +      --sector string       The sector identifier to use (should usually be blank) +      --service string      The service to add the identifier for, valid values are: openid (default "openid") +``` + +### Options inherited from parent commands + +``` +  -c, --config strings                         configuration files to load (default [configuration.yml]) +      --encryption-key string                  the storage encryption key to use +      --mysql.database string                  the MySQL database name (default "authelia") +      --mysql.host string                      the MySQL hostname +      --mysql.password string                  the MySQL password +      --mysql.port int                         the MySQL port (default 3306) +      --mysql.username string                  the MySQL username (default "authelia") +      --postgres.database string               the PostgreSQL database name (default "authelia") +      --postgres.host string                   the PostgreSQL hostname +      --postgres.password string               the PostgreSQL password +      --postgres.port int                      the PostgreSQL port (default 5432) +      --postgres.schema string                 the PostgreSQL schema name (default "public") +      --postgres.ssl.certificate string        the PostgreSQL ssl certificate file location +      --postgres.ssl.key string                the PostgreSQL ssl key file location +      --postgres.ssl.mode string               the PostgreSQL ssl mode (default "disable") +      --postgres.ssl.root_certificate string   the PostgreSQL ssl root certificate file location +      --postgres.username string               the PostgreSQL username (default "authelia") +      --sqlite.path string                     the SQLite database path +``` + +### SEE ALSO + +* [authelia storage user identifiers](authelia_storage_user_identifiers.md)	 - Manage user opaque identifiers + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_user_identifiers_export.md b/docs/content/en/reference/cli/authelia/authelia_storage_user_identifiers_export.md new file mode 100644 index 000000000..325a1c7b4 --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_storage_user_identifiers_export.md @@ -0,0 +1,72 @@ +--- +title: "authelia storage user identifiers export" +description: "Reference for the authelia storage user identifiers export command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia storage user identifiers export + +Export the identifiers to a YAML file + +### Synopsis + +Export the identifiers to a YAML file. + +This subcommand allows exporting the opaque identifiers for users in order to back them up. + +``` +authelia storage user identifiers export [flags] +``` + +### Examples + +``` +authelia storage user identifiers export +authelia storage user identifiers export --file export.yaml +authelia storage user identifiers export --file export.yaml --config config.yml +authelia storage user identifiers export --file export.yaml --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw +``` + +### Options + +``` +  -f, --file string   The file name for the YAML export (default "user-opaque-identifiers.yml") +  -h, --help          help for export +``` + +### Options inherited from parent commands + +``` +  -c, --config strings                         configuration files to load (default [configuration.yml]) +      --encryption-key string                  the storage encryption key to use +      --mysql.database string                  the MySQL database name (default "authelia") +      --mysql.host string                      the MySQL hostname +      --mysql.password string                  the MySQL password +      --mysql.port int                         the MySQL port (default 3306) +      --mysql.username string                  the MySQL username (default "authelia") +      --postgres.database string               the PostgreSQL database name (default "authelia") +      --postgres.host string                   the PostgreSQL hostname +      --postgres.password string               the PostgreSQL password +      --postgres.port int                      the PostgreSQL port (default 5432) +      --postgres.schema string                 the PostgreSQL schema name (default "public") +      --postgres.ssl.certificate string        the PostgreSQL ssl certificate file location +      --postgres.ssl.key string                the PostgreSQL ssl key file location +      --postgres.ssl.mode string               the PostgreSQL ssl mode (default "disable") +      --postgres.ssl.root_certificate string   the PostgreSQL ssl root certificate file location +      --postgres.username string               the PostgreSQL username (default "authelia") +      --sqlite.path string                     the SQLite database path +``` + +### SEE ALSO + +* [authelia storage user identifiers](authelia_storage_user_identifiers.md)	 - Manage user opaque identifiers + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_user_identifiers_generate.md b/docs/content/en/reference/cli/authelia/authelia_storage_user_identifiers_generate.md new file mode 100644 index 000000000..5f6fd17c8 --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_storage_user_identifiers_generate.md @@ -0,0 +1,75 @@ +--- +title: "authelia storage user identifiers generate" +description: "Reference for the authelia storage user identifiers generate command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia storage user identifiers generate + +Generate opaque identifiers in bulk + +### Synopsis + +Generate opaque identifiers in bulk. + +This subcommand allows various options for generating the opaque identifies for users in bulk. + +``` +authelia storage user identifiers generate [flags] +``` + +### Examples + +``` +authelia storage user identifiers generate --users john,mary +authelia storage user identifiers generate --users john,mary --services openid +authelia storage user identifiers generate --users john,mary --services openid --sectors=",example.com,test.com" +authelia storage user identifiers generate --users john,mary --services openid --sectors=",example.com,test.com" --config config.yml +authelia storage user identifiers generate --users john,mary --services openid --sectors=",example.com,test.com" --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw +``` + +### Options + +``` +  -h, --help               help for generate +      --sectors strings    The list of sectors to generate identifiers for +      --services strings   The list of services to generate the opaque identifiers for, valid values are: openid (default [openid]) +      --users strings      The list of users to generate the opaque identifiers for +``` + +### Options inherited from parent commands + +``` +  -c, --config strings                         configuration files to load (default [configuration.yml]) +      --encryption-key string                  the storage encryption key to use +      --mysql.database string                  the MySQL database name (default "authelia") +      --mysql.host string                      the MySQL hostname +      --mysql.password string                  the MySQL password +      --mysql.port int                         the MySQL port (default 3306) +      --mysql.username string                  the MySQL username (default "authelia") +      --postgres.database string               the PostgreSQL database name (default "authelia") +      --postgres.host string                   the PostgreSQL hostname +      --postgres.password string               the PostgreSQL password +      --postgres.port int                      the PostgreSQL port (default 5432) +      --postgres.schema string                 the PostgreSQL schema name (default "public") +      --postgres.ssl.certificate string        the PostgreSQL ssl certificate file location +      --postgres.ssl.key string                the PostgreSQL ssl key file location +      --postgres.ssl.mode string               the PostgreSQL ssl mode (default "disable") +      --postgres.ssl.root_certificate string   the PostgreSQL ssl root certificate file location +      --postgres.username string               the PostgreSQL username (default "authelia") +      --sqlite.path string                     the SQLite database path +``` + +### SEE ALSO + +* [authelia storage user identifiers](authelia_storage_user_identifiers.md)	 - Manage user opaque identifiers + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_user_identifiers_import.md b/docs/content/en/reference/cli/authelia/authelia_storage_user_identifiers_import.md new file mode 100644 index 000000000..cdd838cd2 --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_storage_user_identifiers_import.md @@ -0,0 +1,75 @@ +--- +title: "authelia storage user identifiers import" +description: "Reference for the authelia storage user identifiers import command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia storage user identifiers import + +Import the identifiers from a YAML file + +### Synopsis + +Import the identifiers from a YAML file. + +This subcommand allows you to import the opaque identifiers for users from a YAML file. + +The YAML file can either be automatically generated using the authelia storage user identifiers export command, or +manually provided the file is in the same format. + +``` +authelia storage user identifiers import [flags] +``` + +### Examples + +``` +authelia storage user identifiers import +authelia storage user identifiers import --file export.yaml +authelia storage user identifiers import --file export.yaml --config config.yml +authelia storage user identifiers import --file export.yaml --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw +``` + +### Options + +``` +  -f, --file string   The file name for the YAML import (default "user-opaque-identifiers.yml") +  -h, --help          help for import +``` + +### Options inherited from parent commands + +``` +  -c, --config strings                         configuration files to load (default [configuration.yml]) +      --encryption-key string                  the storage encryption key to use +      --mysql.database string                  the MySQL database name (default "authelia") +      --mysql.host string                      the MySQL hostname +      --mysql.password string                  the MySQL password +      --mysql.port int                         the MySQL port (default 3306) +      --mysql.username string                  the MySQL username (default "authelia") +      --postgres.database string               the PostgreSQL database name (default "authelia") +      --postgres.host string                   the PostgreSQL hostname +      --postgres.password string               the PostgreSQL password +      --postgres.port int                      the PostgreSQL port (default 5432) +      --postgres.schema string                 the PostgreSQL schema name (default "public") +      --postgres.ssl.certificate string        the PostgreSQL ssl certificate file location +      --postgres.ssl.key string                the PostgreSQL ssl key file location +      --postgres.ssl.mode string               the PostgreSQL ssl mode (default "disable") +      --postgres.ssl.root_certificate string   the PostgreSQL ssl root certificate file location +      --postgres.username string               the PostgreSQL username (default "authelia") +      --sqlite.path string                     the SQLite database path +``` + +### SEE ALSO + +* [authelia storage user identifiers](authelia_storage_user_identifiers.md)	 - Manage user opaque identifiers + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_user_totp.md b/docs/content/en/reference/cli/authelia/authelia_storage_user_totp.md new file mode 100644 index 000000000..caf7c97a6 --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_storage_user_totp.md @@ -0,0 +1,67 @@ +--- +title: "authelia storage user totp" +description: "Reference for the authelia storage user totp command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia storage user totp + +Manage TOTP configurations + +### Synopsis + +Manage TOTP configurations. + +This subcommand allows deleting, exporting, and creating user TOTP configurations. + +### Examples + +``` +authelia storage user totp --help +``` + +### Options + +``` +  -h, --help   help for totp +``` + +### Options inherited from parent commands + +``` +  -c, --config strings                         configuration files to load (default [configuration.yml]) +      --encryption-key string                  the storage encryption key to use +      --mysql.database string                  the MySQL database name (default "authelia") +      --mysql.host string                      the MySQL hostname +      --mysql.password string                  the MySQL password +      --mysql.port int                         the MySQL port (default 3306) +      --mysql.username string                  the MySQL username (default "authelia") +      --postgres.database string               the PostgreSQL database name (default "authelia") +      --postgres.host string                   the PostgreSQL hostname +      --postgres.password string               the PostgreSQL password +      --postgres.port int                      the PostgreSQL port (default 5432) +      --postgres.schema string                 the PostgreSQL schema name (default "public") +      --postgres.ssl.certificate string        the PostgreSQL ssl certificate file location +      --postgres.ssl.key string                the PostgreSQL ssl key file location +      --postgres.ssl.mode string               the PostgreSQL ssl mode (default "disable") +      --postgres.ssl.root_certificate string   the PostgreSQL ssl root certificate file location +      --postgres.username string               the PostgreSQL username (default "authelia") +      --sqlite.path string                     the SQLite database path +``` + +### SEE ALSO + +* [authelia storage user](authelia_storage_user.md)	 - Manages user settings +* [authelia storage user totp delete](authelia_storage_user_totp_delete.md)	 - Delete a TOTP configuration for a user +* [authelia storage user totp export](authelia_storage_user_totp_export.md)	 - Perform exports of the TOTP configurations +* [authelia storage user totp generate](authelia_storage_user_totp_generate.md)	 - Generate a TOTP configuration for a user + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_user_totp_delete.md b/docs/content/en/reference/cli/authelia/authelia_storage_user_totp_delete.md new file mode 100644 index 000000000..6d0becae9 --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_storage_user_totp_delete.md @@ -0,0 +1,70 @@ +--- +title: "authelia storage user totp delete" +description: "Reference for the authelia storage user totp delete command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia storage user totp delete + +Delete a TOTP configuration for a user + +### Synopsis + +Delete a TOTP configuration for a user. + +This subcommand allows deleting a TOTP configuration directly from the database for a given user. + +``` +authelia storage user totp delete <username> [flags] +``` + +### Examples + +``` +authelia storage user totp delete john +authelia storage user totp delete john --config config.yml +authelia storage user totp delete john --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw +``` + +### Options + +``` +  -h, --help   help for delete +``` + +### Options inherited from parent commands + +``` +  -c, --config strings                         configuration files to load (default [configuration.yml]) +      --encryption-key string                  the storage encryption key to use +      --mysql.database string                  the MySQL database name (default "authelia") +      --mysql.host string                      the MySQL hostname +      --mysql.password string                  the MySQL password +      --mysql.port int                         the MySQL port (default 3306) +      --mysql.username string                  the MySQL username (default "authelia") +      --postgres.database string               the PostgreSQL database name (default "authelia") +      --postgres.host string                   the PostgreSQL hostname +      --postgres.password string               the PostgreSQL password +      --postgres.port int                      the PostgreSQL port (default 5432) +      --postgres.schema string                 the PostgreSQL schema name (default "public") +      --postgres.ssl.certificate string        the PostgreSQL ssl certificate file location +      --postgres.ssl.key string                the PostgreSQL ssl key file location +      --postgres.ssl.mode string               the PostgreSQL ssl mode (default "disable") +      --postgres.ssl.root_certificate string   the PostgreSQL ssl root certificate file location +      --postgres.username string               the PostgreSQL username (default "authelia") +      --sqlite.path string                     the SQLite database path +``` + +### SEE ALSO + +* [authelia storage user totp](authelia_storage_user_totp.md)	 - Manage TOTP configurations + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_user_totp_export.md b/docs/content/en/reference/cli/authelia/authelia_storage_user_totp_export.md new file mode 100644 index 000000000..1d186d978 --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_storage_user_totp_export.md @@ -0,0 +1,73 @@ +--- +title: "authelia storage user totp export" +description: "Reference for the authelia storage user totp export command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia storage user totp export + +Perform exports of the TOTP configurations + +### Synopsis + +Perform exports of the TOTP configurations. + +This subcommand allows exporting TOTP configurations to various formats. + +``` +authelia storage user totp export [flags] +``` + +### Examples + +``` +authelia storage user totp export --format csv +authelia storage user totp export --format png --dir ./totp-qr +authelia storage user totp export --format png --dir ./totp-qr --config config.yml +authelia storage user totp export --format png --dir ./totp-qr --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw +``` + +### Options + +``` +      --dir string      used with the png output format to specify which new directory to save the files in +      --format string   sets the output format, valid values are: csv, uri, png (default "uri") +  -h, --help            help for export +``` + +### Options inherited from parent commands + +``` +  -c, --config strings                         configuration files to load (default [configuration.yml]) +      --encryption-key string                  the storage encryption key to use +      --mysql.database string                  the MySQL database name (default "authelia") +      --mysql.host string                      the MySQL hostname +      --mysql.password string                  the MySQL password +      --mysql.port int                         the MySQL port (default 3306) +      --mysql.username string                  the MySQL username (default "authelia") +      --postgres.database string               the PostgreSQL database name (default "authelia") +      --postgres.host string                   the PostgreSQL hostname +      --postgres.password string               the PostgreSQL password +      --postgres.port int                      the PostgreSQL port (default 5432) +      --postgres.schema string                 the PostgreSQL schema name (default "public") +      --postgres.ssl.certificate string        the PostgreSQL ssl certificate file location +      --postgres.ssl.key string                the PostgreSQL ssl key file location +      --postgres.ssl.mode string               the PostgreSQL ssl mode (default "disable") +      --postgres.ssl.root_certificate string   the PostgreSQL ssl root certificate file location +      --postgres.username string               the PostgreSQL username (default "authelia") +      --sqlite.path string                     the SQLite database path +``` + +### SEE ALSO + +* [authelia storage user totp](authelia_storage_user_totp.md)	 - Manage TOTP configurations + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_user_totp_generate.md b/docs/content/en/reference/cli/authelia/authelia_storage_user_totp_generate.md new file mode 100644 index 000000000..23346f7c4 --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_storage_user_totp_generate.md @@ -0,0 +1,82 @@ +--- +title: "authelia storage user totp generate" +description: "Reference for the authelia storage user totp generate command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia storage user totp generate + +Generate a TOTP configuration for a user + +### Synopsis + +Generate a TOTP configuration for a user. + +This subcommand allows generating a new TOTP configuration for a user, +and overwriting the existing configuration if applicable. + +``` +authelia storage user totp generate <username> [flags] +``` + +### Examples + +``` +authelia storage user totp generate john +authelia storage user totp generate john --period 90 +authelia storage user totp generate john --digits 8 +authelia storage user totp generate john --algorithm SHA512 +authelia storage user totp generate john --algorithm SHA512 --config config.yml +authelia storage user totp generate john --algorithm SHA512 --config config.yml --path john.png +``` + +### Options + +``` +      --algorithm string   set the TOTP algorithm (default "SHA1") +      --digits uint        set the TOTP digits (default 6) +  -f, --force              forces the TOTP configuration to be generated regardless if it exists or not +  -h, --help               help for generate +      --issuer string      set the TOTP issuer (default "Authelia") +  -p, --path string        path to a file to create a PNG file with the QR code (optional) +      --period uint        set the TOTP period (default 30) +      --secret string      Optionally set the TOTP shared secret as base32 encoded bytes (no padding), it's recommended to not set this option unless you're restoring an TOTP config +      --secret-size uint   set the TOTP secret size (default 32) +``` + +### Options inherited from parent commands + +``` +  -c, --config strings                         configuration files to load (default [configuration.yml]) +      --encryption-key string                  the storage encryption key to use +      --mysql.database string                  the MySQL database name (default "authelia") +      --mysql.host string                      the MySQL hostname +      --mysql.password string                  the MySQL password +      --mysql.port int                         the MySQL port (default 3306) +      --mysql.username string                  the MySQL username (default "authelia") +      --postgres.database string               the PostgreSQL database name (default "authelia") +      --postgres.host string                   the PostgreSQL hostname +      --postgres.password string               the PostgreSQL password +      --postgres.port int                      the PostgreSQL port (default 5432) +      --postgres.schema string                 the PostgreSQL schema name (default "public") +      --postgres.ssl.certificate string        the PostgreSQL ssl certificate file location +      --postgres.ssl.key string                the PostgreSQL ssl key file location +      --postgres.ssl.mode string               the PostgreSQL ssl mode (default "disable") +      --postgres.ssl.root_certificate string   the PostgreSQL ssl root certificate file location +      --postgres.username string               the PostgreSQL username (default "authelia") +      --sqlite.path string                     the SQLite database path +``` + +### SEE ALSO + +* [authelia storage user totp](authelia_storage_user_totp.md)	 - Manage TOTP configurations + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia/authelia_validate-config.md b/docs/content/en/reference/cli/authelia/authelia_validate-config.md new file mode 100644 index 000000000..a7a4a9842 --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_validate-config.md @@ -0,0 +1,48 @@ +--- +title: "authelia validate-config" +description: "Reference for the authelia validate-config command." +lead: "" +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia validate-config + +Check a configuration against the internal configuration validation mechanisms + +### Synopsis + +Check a configuration against the internal configuration validation mechanisms. + +This subcommand allows validation of the YAML and Environment configurations so that a configuration can be checked +prior to deploying it. + +``` +authelia validate-config [flags] +``` + +### Examples + +``` +authelia validate-config +authelia validate-config --config config.yml +``` + +### Options + +``` +  -c, --config strings   configuration files to load (default [configuration.yml]) +  -h, --help             help for validate-config +``` + +### SEE ALSO + +* [authelia](authelia.md)	 - authelia untagged-unknown-dirty (master, unknown) + +###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/guides/_index.md b/docs/content/en/reference/guides/_index.md new file mode 100644 index 000000000..a3fa35d3a --- /dev/null +++ b/docs/content/en/reference/guides/_index.md @@ -0,0 +1,9 @@ +--- +title: "Guides" +description: "Reference Prologue" +lead: "" +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +weight: 200 +--- diff --git a/docs/content/en/reference/guides/introduction.md b/docs/content/en/reference/guides/introduction.md new file mode 100644 index 000000000..65784543a --- /dev/null +++ b/docs/content/en/reference/guides/introduction.md @@ -0,0 +1,16 @@ +--- +title: "Guides" +description: "A collection of reference guides" +lead: "This section contains reference guides for Authelia." +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "guides" +weight: 210 +toc: true +--- + +The guides in the section are usually for something fairly specific that doesn't warrant its own section in the +reference documentation. diff --git a/docs/content/en/reference/guides/log-messages.md b/docs/content/en/reference/guides/log-messages.md new file mode 100644 index 000000000..88acca5d9 --- /dev/null +++ b/docs/content/en/reference/guides/log-messages.md @@ -0,0 +1,37 @@ +--- +title: "Log Messages" +description: "A collection of log message reference information" +lead: "This section contains log message references for Authelia." +date: 2022-06-09T18:25:02+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "guides" +weight: 220 +toc: true +--- + +## Request Header Too Large + +The `request header too large` error with a status code of `431` indicates the HTTP request made to *Authelia* had +headers exceeding the server [read_buffer_size](../../configuration/miscellaneous/server.md#read_buffer_size) parameter. + +Usually the defaults are sufficient however some applications cause fairly large headers to be added to requests. + +It's suggested you increase the [read_buffer_size](../../configuration/miscellaneous/server.md#read_buffer_size) +configuration option (by either doubling or quadrupling it) in order to alleviate this issue or use the reverse proxy to +remove the excessive headers which are causing this issue. + +It's generally recommended the [write_buffer_size](../../configuration/miscellaneous/server.md#write_buffer_size) is +also increased. + +## User Has Been Inactive Too Long + +An error with the text `User john has been inactive for too long` where `john` is the username indicates the user did +not decide to utilize the remember me option, and their session has not been used for more time than is configured in +the session [inactivity](../../configuration/session/introduction.md#inactivity) configuration option. + +This error can safely be ignored as it is meant to be informative. You can reduce this error from occurring by adjusting +the session [inactivity](../../configuration/session/introduction.md#inactivity) configuration option or by having users +select the remember me box. diff --git a/docs/content/en/reference/guides/metrics.md b/docs/content/en/reference/guides/metrics.md new file mode 100644 index 000000000..933702d4b --- /dev/null +++ b/docs/content/en/reference/guides/metrics.md @@ -0,0 +1,68 @@ +--- +title: "Telemetry" +description: "A reference guide on the telemetry collection" +lead: "This section contains reference documentation for Authelia's telemetry systems." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  reference: +    parent: "guides" +weight: 220 +toc: true +--- + +No telemetry data is collected by any *Authelia* binaries, tooling, etc by default and all telemetry data is intended +to be used by administrators of their individual *Authelia* installs. + +## Metrics + +### Prometheus + +*Authelia* supports exporting [Prometheus] metrics. These metrics are served on a separate port at the `/metrics` path +when configured. If metrics are enabled the metrics listener listens on `0.0.0.0:9959` as per the officially +[registered port] unless configured otherwise. + +#### Recorded Metrics + +##### Vectored Histograms + +|          Name           | Vectors |                                                    Buckets                                                    | +|:-----------------------:|:-------:|:-------------------------------------------------------------------------------------------------------------:| +| authentication_duration | success | .0005, .00075, .001, .005, .01, .025, .05, .075, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 0.9, 1, 5, 10, 15, 30, 60 | +|    request_duration     |  code   |                   .005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10, 15, 20, 30, 40, 50, 60                    | + +##### Vectored Counters + +|             Name             |        Vectors        | +|:----------------------------:|:---------------------:| +|           request            |     code, method      | +|        verify_request        |         code          | +| authentication_first_factor  |    success, banned    | +| authentication_second_factor | success, banned, type | + + +#### Vector Definitions + +##### code + +The HTTP response status code. + +##### method + +The HTTP request method. + +##### success + +If the authentication was successful (`true`) or not (`false`). + +##### banned + +If the authentication was considered banned (`true`) or not (`false`). + +##### type + +The authentication type `webauthn`, `totp`, or `duo`. + +[Prometheus]: https://prometheus.io/ +[registered port]: https://github.com/prometheus/prometheus/wiki/Default-port-allocations diff --git a/docs/content/en/reference/guides/notification-templates.md b/docs/content/en/reference/guides/notification-templates.md new file mode 100644 index 000000000..f56cbb293 --- /dev/null +++ b/docs/content/en/reference/guides/notification-templates.md @@ -0,0 +1,64 @@ +--- +title: "Notification Templates" +description: "A reference guide on overriding notification templates" +lead: "This section contains reference documentation for Authelia's notification templates." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  reference: +    parent: "guides" +weight: 220 +toc: true +--- + +Authelia uses templates to generate the HTML and plaintext emails sent via the notification service. Each template has +two extensions; `.html` for HTML templates, and `.txt` for plaintext templates. + +This guide effectively documents the usage of the +[template_path](../../configuration/notifications/introduction.md#template_path) notification configuration option. + +## Template Names + +|       Template       |                                    Description                                    | +|:--------------------:|:---------------------------------------------------------------------------------:| +| IdentityVerification | Used to render notifications sent when registering devices or resetting passwords | +|    PasswordReset     |    Used to render notifications sent when password has successfully been reset    | + +For example, to modify the `IdentityVerification` HTML template, if your +[template_path](../../configuration/notifications/introduction.md#template_path) was configured as +`/config/email_templates`, you would create the `/config/email_templates/IdentityVerification.html` file to override the +HTML `IdentityVerification` template. + +## Placeholder Variables + +In template files, you can use the following placeholders which are automatically injected into the templates: + +|     Placeholder      |      Templates       |                                                                  Description                                                                   | +|:--------------------:|:--------------------:|:----------------------------------------------------------------------------------------------------------------------------------------------:| +|   `{{ .LinkURL }}`   | IdentityVerification |                                            The URL associated with the notification if applicable.                                             | +|  `{{ .LinkText }}`   | IdentityVerification |                                 The display value for the URL associated with the notification if applicable.                                  | +|    `{{ .Title }}`    |         All          | A predefined title for the email. <br> It will be `"Reset your password"` or `"Password changed successfully"`, depending on the current step. | +| `{{ .DisplayName }}` |         All          |                                                     The name of the user, i.e. `John Doe`                                                      | +|  `{{ .RemoteIP }}`   |         All          |                                      The remote IP address (client) that initiated the request or event.                                       | + +## Examples + +This is a basic example: + +```html +<body> +  <h1>{{ .Title }}</h1> +  Hi {{ .DisplayName }}<br/> +  This email has been sent to you in order to validate your identity. +  Click <a href="{{ .LinkURL }}">here</a> to change your password. +</body> +``` + +Some Additional examples for specific purposes can be found in the +[examples directory on GitHub](https://github.com/authelia/authelia/tree/master/examples/templates/notifications). + +## Original Templates + +The original template content can be found on +[GitHub](https://github.com/authelia/authelia/tree/master/internal/templates). diff --git a/docs/content/en/reference/guides/passwords.md b/docs/content/en/reference/guides/passwords.md new file mode 100644 index 000000000..e7cc7b3c5 --- /dev/null +++ b/docs/content/en/reference/guides/passwords.md @@ -0,0 +1,166 @@ +--- +title: "Passwords" +description: "A reference guide on passwords and hashing etc" +lead: "This section contains reference documentation for Authelia." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  reference: +    parent: "guides" +weight: 220 +toc: true +aliases: +  - /r/passwords +--- + +## User / Password File + +This file should be set with read/write permissions as it could be updated by users resetting their passwords. + +### YAML Format + +The format of the [YAML] file is as follows: + +```yaml +users: +  john: +    displayname: "John Doe" +    password: "$argon2id$v=19$m=65536,t=3,p=2$BpLnfgDsc2WD8F2q$o/vzA4myCqZZ36bUGsDY//8mKUYNZZaR0t4MFFSs+iM" +    email: john.doe@authelia.com +    groups: +      - admins +      - dev +  harry: +    displayname: "Harry Potter" +    password: "$argon2id$v=19$m=65536,t=3,p=2$BpLnfgDsc2WD8F2q$o/vzA4myCqZZ36bUGsDY//8mKUYNZZaR0t4MFFSs+iM" +    email: harry.potter@authelia.com +    groups: [] +  bob: +    displayname: "Bob Dylan" +    password: "$argon2id$v=19$m=65536,t=3,p=2$BpLnfgDsc2WD8F2q$o/vzA4myCqZZ36bUGsDY//8mKUYNZZaR0t4MFFSs+iM" +    email: bob.dylan@authelia.com +    groups: +      - dev +  james: +    displayname: "James Dean" +    password: "$argon2id$v=19$m=65536,t=3,p=2$BpLnfgDsc2WD8F2q$o/vzA4myCqZZ36bUGsDY//8mKUYNZZaR0t4MFFSs+iM" +    email: james.dean@authelia.com +``` + +## Passwords + +The file contains hashed passwords instead of plain text passwords for security reasons. + +You can use Authelia binary or docker image to generate the hash of any password. The [hash-password] command has many +tunable options, you can view them with the `authelia hash-password --help` command. For example if you wanted to +improve the entropy you could generate a 16 byte salt and provide it with the `--salt` flag. + +Example: `authelia hash-password --salt abcdefghijklhijl -- 'password'`. + +Passwords passed to [hash-password] should be single quoted if using special characters to prevent parameter +substitution. In addition the password should be the last parameter, and should be after a `--`. For instance to +generate a hash with the docker image just run: + +```bash +$ docker run authelia/authelia:latest authelia hash-password -- 'password' +Password hash: $argon2id$v=19$m=65536$3oc26byQuSkQqksq$zM1QiTvVPrMfV6BVLs2t4gM+af5IN7euO0VB6+Q8ZFs +``` + +You may also use the `--config` flag to point to your existing configuration. When used, the values defined in the +config will be used instead. + +See the [full CLI reference documentation](../cli/authelia/authelia_hash-password.md). + +### Cost + +The most important part about choosing a password hashing function is the cost. It's generally recommended that the cost +takes roughly 500 milliseconds on your hardware to complete, however if you have very old hardware you may want to +consider more than 500 milliseconds, or if you have really high end hardware you may want to consider slightly less +depending on if you have a large quantity of users. + +Ideally on average hardware the amount of time would be roughly 500 milliseconds at minimum. + +In consideration of your cost you should take into account the fact some algorithms only support scaling the cost for +one factor and not others It's usually considered better to have a mix of cost types however this is not possible with +all algorithms. The main cost type measurements are: + +* CPU +* Memory + +*__Important Note:__ When using algorithms that use a memory cost like [Argon2] it should be noted that this memory is +released by Go after the hashing process completes, however the operating system may not reclaim the memory until a +later time such as when the system is experiencing memory pressure which may cause the appearance of more memory being +in use than Authelia is actually actively using. Authelia will typically reuse this memory if it has not be reclaimed as +long as another hashing calculation is not still utilizing it.* + +To get a rough estimate of how much memory should be utilized with these algorithms you can utilize the following +command: + +```bash +stress-ng --vm-bytes $(awk '/MemFree/{printf "%d\n", $2 * 0.9;}' < /proc/meminfo)k --vm-keep -m 1 +``` + +If this is not desirable we recommend investigating the following options in order of most to least secure: + +1. Use the [LDAP](../../configuration/first-factor/ldap.md) authentication provider instead +2. Adjusting the [memory](../../configuration/first-factor/file.md#memory) parameter +3. Changing the [algorithm](../../configuration/first-factor/file.md#algorithm) + +### Algorithms + +The default hash algorithm is the [Argon2] `id` variant version 19 with a salt. [Argon2] is at the time of this writing +widely considered to be the best hashing algorithm, and in 2015 won the [Password Hashing Competition]. It benefits from +customizable parameters including a memory parameter allowing the [cost](#cost) of computing a hash to scale into the +future with better hardware which makes it harder to brute-force. + +For backwards compatibility and user choice support for the [SHA Crypt] algorithm (`SHA512` variant) is still available. +While it's a reasonable hashing function given high enough iterations, as hardware improves it has a higher chance of +being brute-forced since it only allows scaling the CPU [cost](#cost) whereas [Argon2] allows scaling both for CPU and +Memory [cost](#cost). + +#### Identification + +The algorithm that a hash is utilizing is identifiable by its prefix: + +|  Algorithm  | Variant  |    Prefix    | +|:-----------:|:--------:|:------------:| +|  [Argon2]   |   `id`   | `$argon2id$` | +| [SHA Crypt] | `SHA512` |    `$6$`     | + +See the [Crypt (C) Wiki page](https://en.wikipedia.org/wiki/Crypt_(C)) for more information. + +#### Tuning + +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 +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). + +While there are recommended parameters for each algorithm it's your responsibility to tune these individually for your +particular system. + +#### Recommended Parameters: Argon2id + +This table adapts the [RFC9106 Parameter Choice] recommendations to our configuration options: + +|  Situation  | Iterations (t) | Parallelism (p) | Memory (m) | Salt Size | Key Size | +|:-----------:|:--------------:|:---------------:|:----------:|:---------:|:--------:| +| Low Memory  |       3        |        4        |     64     |    16     |    32    | +| Recommended |       1        |        4        |    2048    |    16     |    32    | + +#### Recommended Parameters: SHA512 + +This table suggests the parameters for the [SHA Crypt] (`SHA512` variant) algorithm: + +|  Situation   | Iterations (rounds) | Salt Size | +|:------------:|:-------------------:|:---------:| +| Standard CPU |        50000        |    16     | +| High End CPU |       150000        |    16     | + +[RFC9106 Parameter Choice]: https://www.rfc-editor.org/rfc/rfc9106.html#section-4 +[YAML]: https://yaml.org/ +[Argon2]: https://www.rfc-editor.org/rfc/rfc9106.html +[SHA Crypt]: https://www.akkadia.org/drepper/SHA-crypt.txt +[hash-password]: ../cli/authelia/authelia_hash-password.md +[Password Hashing Competition]: https://en.wikipedia.org/wiki/Password_Hashing_Competition diff --git a/docs/content/en/reference/guides/server-asset-overrides.md b/docs/content/en/reference/guides/server-asset-overrides.md new file mode 100644 index 000000000..bf8d277dd --- /dev/null +++ b/docs/content/en/reference/guides/server-asset-overrides.md @@ -0,0 +1,83 @@ +--- +title: "Server Asset Overrides" +description: "A reference guide on overriding server assets" +lead: "This section contains reference documentation for Authelia's server asset override capabilities." +date: 2022-06-02T20:24:29+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "guides" +weight: 220 +toc: true +--- + +This guide effectively documents the usage of the +[asset_path](../../configuration/miscellaneous/server.md#asset_path) server configuration option. + +## Structure + +```console +/config/assets/ +├── favicon.ico +├── logo.png +└── locales/<lang>[-[variant]]/<namespace>.json +``` + +## Assets + +|        Asset        |  File Name  | Directory |     Notes     | +|:-------------------:|:-----------:|:---------:|:-------------:| +|       Favicon       | favicon.ico |    No     |      N/A      | +|        Logo         |  logo.png   |    No     |      N/A      | +| Translation Locales |   locales   |    Yes    | see [locales](#locales) | + +## locales + +*__Important Note__ Currently users can only override languages that already exist in this list either by overriding +the language itself, or adding a variant form of that language. If you'd like support for another language feel free +to make a PR. We also encourage people to make PR's for variants where the difference in the variants is significant.* + +*__Important Note__ Users wishing to override the locales files should be aware that we do not provide any guarantee +that the file will not change in a breaking way between releases. Users who planning to utilize these +overrides should either check for changes to the files in the +[en](https://github.com/authelia/authelia/tree/master/internal/server/locales/en) translation prior to upgrading or +[Contribute](../../contributing/prologue/translations.md) their translation to ensure it is maintained.* + +The locales directory holds folders of internationalization locales. This directory can be utilized to override these +locales. They are the names of locales that are returned by the `navigator.langauge` ECMAScript command. These are +generally those in the [RFC5646 / BCP47 Format](https://www.rfc-editor.org/rfc/rfc5646.html) specifically the language +codes from [Crowdin](https://support.crowdin.com/api/language-codes/). + +Each directory has JSON files which you can explore the format of in the +[internal/server/locales](https://github.com/authelia/authelia/tree/master/internal/server/locales) directory on +GitHub. The important part is the key names you wish to override. + +A full example for the `en-US` locale for the portal namespace is `locales/en-US/portal.json`. + +Languages in browsers are supported in two forms. In their language only form such as `en` for English, and in their +variant form such as `en-AU` for English (Australian). If a user has the browser language `en-AU` we automatically load +the `en` and `en-AU` languages, where any keys in the `en-AU` language take precedence over the `en` language, and the +translations for the `en` language only applying when a translation from `en-AU` is not available. + +### Namespaces + +Each file in a locale directory represents a translation namespace. The list of current namespaces are below: + +| Namespace |       Purpose       | +|:---------:|:-------------------:| +|  portal   | Portal Translations | + +### Supported Languages + +List of supported languages and variants: + +|      Description      | Language | Additional Variants |       Location       | +|:---------------------:|:--------:|:-------------------:|:--------------------:| +|        English        |    en    |         N/A         |  locales/en/*.json   | +|        Spanish        |    es    |         N/A         |  locales/es/*.json   | +|        German         |    de    |         N/A         |  locales/de/*.json   | +|        French         |    fr    |         N/A         |  locales/fr/*.json   | +|        Russian        |    ru    |         N/A         |  locales/ru/*.json   | +|        Swedish        |    sv    |   sv-SE (Sweden)    |  locales/sv/*.json   | +| Chinese (Traditional) |  zh-TW   |         N/A         | locales/zh-TW/*.json | diff --git a/docs/content/en/reference/prologue/_index.md b/docs/content/en/reference/prologue/_index.md new file mode 100644 index 000000000..5f9246cf9 --- /dev/null +++ b/docs/content/en/reference/prologue/_index.md @@ -0,0 +1,9 @@ +--- +title: "Reference" +description: "Reference Prologue" +lead: "" +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +weight: 100 +--- diff --git a/docs/content/en/reference/prologue/introduction.md b/docs/content/en/reference/prologue/introduction.md new file mode 100644 index 000000000..40e72f391 --- /dev/null +++ b/docs/content/en/reference/prologue/introduction.md @@ -0,0 +1,17 @@ +--- +title: "Prologue" +description: "An introduction into Authelia reference documentation." +lead: "This section contains reference documentation for Authelia." +date: 2022-05-31T11:13:56+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "prologue" +weight: 110 +toc: true +--- + +This section of the docs is for reference documentation. Other sections of the documentation may reference this or it +may be stored here if it does not fit any other particular sections. Generally this section of the documentation is only +needed if you are linked to it from another area of the documentation or you're looking for something specific. diff --git a/docs/content/en/roadmap/_index.md b/docs/content/en/roadmap/_index.md new file mode 100644 index 000000000..ae274b082 --- /dev/null +++ b/docs/content/en/roadmap/_index.md @@ -0,0 +1,8 @@ +--- +title : "Roadmap" +description: "Authelia Roadmap" +lead: "" +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +--- diff --git a/docs/content/en/roadmap/active/_index.md b/docs/content/en/roadmap/active/_index.md new file mode 100644 index 000000000..979d2cd7f --- /dev/null +++ b/docs/content/en/roadmap/active/_index.md @@ -0,0 +1,9 @@ +--- +title : "Active" +description: "Active Roadmap Details" +lead: "" +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +weight: 200 +--- diff --git a/docs/content/en/roadmap/active/dashboard-control-panel.md b/docs/content/en/roadmap/active/dashboard-control-panel.md new file mode 100644 index 000000000..b68c82e55 --- /dev/null +++ b/docs/content/en/roadmap/active/dashboard-control-panel.md @@ -0,0 +1,55 @@ +--- +title: "Dashboard / Control Panel" +description: "Authelia Dashboard Implementation" +lead: "A dashboard or control panel for users and administrators to adjust their settings or Authelia's settings is easily one of the most impactful features we can implment." +date: 2022-03-20T21:18:42+11:00 +draft: false +images: [] +menu: +  roadmap: +    parent: "active" +weight: 240 +toc: true +--- + +This feature has several major impacts on other roadmap items. For example several OpenID Connect features would greatly +benefit from a dashboard. It would also be important when we implement WebAuthn features like passwordless +authentication allowing users to intentionally register a passwordless credential. + +## Stages + +This section represents the stages involved in implementation of this feature. The stages are either in order of +implementation due to there being an underlying requirement to implement them in this order, or in their likely order +due to how important or difficult to implement they are. + +### Initial Implementation + +{{< roadmap-status >}} + +Add control panel with the ability to control all of the current settings, with the added benefit of being able to +register multiple WebAuthn keys. + +Users should also be able to view all of their registered devices, and revoke them individually. + +### Password Reset + +{{< roadmap-status >}} + +Add a method for users to reset their password given they know their current password. + +### Language Option + +{{< roadmap-status >}} + +Allow users to override the detected language in their browser and choose from one of the available languages. + +### Session Management + +{{< roadmap-status >}} + +Add ability for users to view their own sessions and end them, administrators the ability to view all sessions and end +them, and for administrators to be notified of and add/view/remove bans on users. + +### Much More + +The practical usage of this is endless. diff --git a/docs/content/en/roadmap/active/internationalization.md b/docs/content/en/roadmap/active/internationalization.md new file mode 100644 index 000000000..62decdd0c --- /dev/null +++ b/docs/content/en/roadmap/active/internationalization.md @@ -0,0 +1,48 @@ +--- +title: "Internationalization" +description: "Authelia Internationalization Implementation" +lead: "Implementation of internationalization will make Authelia more accessible to more people." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  roadmap: +    parent: "active" +weight: 230 +toc: true +--- + +This can easily be done in the web interface and automatically adapt to the users browser. + +## Stages + +This section represents the stages involved in implementation of this feature. The stages are either in order of +implementation due to there being an underlying requirement to implement them in this order, or in their likely order +due to how important or difficult to implement they are. + +### Initial Implementation + +{{< roadmap-status stage="complete" version="v4.34.0" >}} + +This stage will add the ability to easily translate the web interface in all views. + +### Crowd Translation Service + +{{< roadmap-status stage="complete" >}} + +This stage will configure the Authelia repository to be easily translatable via a crowd sourced translation platform. + +*__Implemented:__ You can now help translate __Authelia__ by checking out the +[Translations Contributing Guide](../../contributing/prologue/translations.md).* + +### Picker + +{{< roadmap-status >}} + +Add a language picker to the web interface. The picker will be a per-browser choice which overrides the browser +language advertisement as the language of choice for that browser. The information will be stored in the browser +[local storage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) implementation. + +### Ongoing + +There will be an ongoing effort to keep the interface translated. diff --git a/docs/content/en/roadmap/active/kubernetes-documentation.md b/docs/content/en/roadmap/active/kubernetes-documentation.md new file mode 100644 index 000000000..4b64278c2 --- /dev/null +++ b/docs/content/en/roadmap/active/kubernetes-documentation.md @@ -0,0 +1,45 @@ +--- +title: "Kubernetes Documentation" +description: "Add better Kubernetes documentation." +lead: "While there is some documentation for Kubernetes, and several people have it working, better documentation is needed." +date: 2022-03-20T21:18:42+11:00 +draft: false +images: [] +menu: +  roadmap: +    parent: "active" +weight: 250 +toc: true +--- + +## Stages + +This section represents the stages involved in implementation of this feature. The stages are either in order of +implementation due to there being an underlying requirement to implement them in this order, or in their likely order +due to how important or difficult to implement they are. + +### Integration Documentation + +{{< roadmap-status stage="in-progress" >}} + +Provide some generalized integration documentation for [Kubernetes]. + +### Helm Chart + +{{< roadmap-status stage="in-progress" >}} + +Develop and release a [Helm] [Chart](https://helm.sh/docs/topics/charts/) which makes implementation on [Kubernetes] +easy. + +This is currently in progress and there is a [Helm Chart Repository](https://charts.authelia.com). This is considered +beta and the chart itself has a lot of work to go. + +### Kustomize + +{{< roadmap-status >}} + +Implement a [Kustomize] bundle people can utilize with [Kubernetes]. + +[Helm]: https://helm.sh/ +[Kubernetes]: https://kubernetes.io/ +[Kustomize]: https://kustomize.io/ diff --git a/docs/content/en/roadmap/active/multi-domain-protection.md b/docs/content/en/roadmap/active/multi-domain-protection.md new file mode 100644 index 000000000..089d38825 --- /dev/null +++ b/docs/content/en/roadmap/active/multi-domain-protection.md @@ -0,0 +1,53 @@ +--- +title: "Multi Domain Protection" +description: "Authelia Multi Domain Protection Implementation" +lead: "Multi Domain Protection is one of the most requested Authelia features." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  roadmap: +    parent: "active" +weight: 230 +toc: true +--- + +We have seen and heard the feedback from our users and we are acting on it. This feature is being prioritized. Allowing +administrators to protect more than one root domain utilizing a single Authelia instance is going to be a difficult +feature to implement but we'll actively take steps to implement it. + +## Stages + +This section represents the stages involved in implementation of this feature. The stages are either in order of +implementation due to there being an underlying requirement to implement them in this order, or in their likely order +due to how important or difficult to implement they are. + +### Decide on a Method + +{{< roadmap-status stage="complete" >}} + +We need to decide on a method to implement this feature initially and how it will finally look to provide SSO between +root domains. + +*__UPDATE:__* The [initial implementation](#initial-implementation) has been decided as well as the +[SSO implementation](#sso-implementation). + +### Decide on a Session Library + +{{< roadmap-status stage="in-progress" >}} + +We need to make a choice going forward about what method we will use to manage cookies and sessions. The current library +has many drawbacks that just are not satisfactory in order to easily facilitate this. + +### Initial Implementation + +{{< roadmap-status stage="waiting" >}} + +This stage is waiting on the choice to handle sessions. Initial implementation will involve just a basic cookie +implementation where users will be required to sign in to each root domain and no SSO functionality will exist. + +### SSO Implementation + +{{< roadmap-status >}} + +The SSO implementation will leverage [OpenID Connect](openid-connect.md) to perform Single-Sign On. diff --git a/docs/content/en/roadmap/active/openid-connect.md b/docs/content/en/roadmap/active/openid-connect.md new file mode 100644 index 000000000..297818fd7 --- /dev/null +++ b/docs/content/en/roadmap/active/openid-connect.md @@ -0,0 +1,194 @@ +--- +title: "OpenID Connect" +description: "Authelia OpenID Connect Implementation" +lead: "The OpenID Connect Provider role is a very useful but complex feature to enhance interoperability of Authelia with other products. " +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  roadmap: +    parent: "active" +weight: 221 +toc: true +aliases: +  - /docs/roadmap/oidc.html +--- + +We have decided to implement [OpenID Connect] as a beta feature, it's suggested you only utilize it for testing and +providing feedback, and should take caution in relying on it in production as of now. [OpenID Connect] and it's related +endpoints are not enabled by default unless you specifically configure the [OpenID Connect] section. + +As [OpenID Connect] is fairly complex (the [OpenID Connect] Provider role especially so) it's intentional that it is +both a beta and that the implemented features are part of a thoughtful roadmap. Items that are not immediately obvious +as required (i.e. bug fixes or spec features), will likely be discussed in team meetings or on GitHub issues before +being added to the list. We want to implement this feature in a very thoughtful way in order to avoid security issues. + +## Stages + +This section represents the stages involved in implementation of this feature. The stages are either in order of +implementation due to there being an underlying requirement to implement them in this order, or in a rough order due to +how important or difficult to implement they are. + +### Beta 1 + +{{< roadmap-status stage="complete" version="v4.29.0" >}} + +Feature List: + +* [User Consent](https://openid.net/specs/openid-connect-core-1_0.html#Consent) +* [Authorization Code Flow](https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowSteps) +* [OpenID Connect Discovery](https://openid.net/specs/openid-connect-discovery-1_0.html) +* [RS256 Signature Strategy](https://www.rfc-editor.org/rfc/rfc7518.html#section-3.1) +* Per Client Scope/Grant Type/Response Type Restriction +* Per Client Authorization Policy (1FA/2FA) +* Per Client List of Valid Redirection URI's +* [Confidential Client Type](https://www.rfc-editor.org/rfc/rfc6749.html#section-2.1) + +### Beta 2 + +{{< roadmap-status stage="complete" version="v4.30.0" >}} + +Feature List: + +* [Userinfo Endpoint](https://openid.net/specs/openid-connect-core-1_0.html#UserInfo) +* Parameter Entropy +* Token/Code Lifespan +* Client Debug Messages +* Client Audience +* [Public Client Type](https://www.rfc-editor.org/rfc/rfc6749.html#section-2.1) + +### Beta 3 + +{{< roadmap-status stage="complete" version="v4.34.0" >}} + +Feature List: + +* [Proof Key Code Exchange (PKCE)](https://www.rfc-editor.org/rfc/rfc7636.html) for Authorization Code Flow +* Claims: +  * `preferred_username` - sending the username in this claim instead of the `sub` claim. + +### Beta 4 + +{{< roadmap-status stage="complete" version="v4.35.0" >}} + +Feature List: + +* Persistent Storage +  * Tokens +  * Auditable Information +  * Subject to User Mapping +* Opaque [RFC4122] UUID v4's for subject identifiers +* Support for Pairwise and Plain subject identifier types as per [OpenID Connect Core (Subject Identifier Types)] +  * Utilize the pairwise example method 3 as per [OpenID Connect Core (Pairwise Identifier Algorithm)] +* Claims: +  * `sub` - replace username with opaque random [RFC4122] UUID v4 +  * `amr` - authentication method references as per [RFC8176] +  * `azp` - authorized party as per [OpenID Connect Core (ID Token)] +  * `client_id` - the Client ID as per [RFC8693 Section 4.3] +* [Cross Origin Resource Sharing] (CORS): +  * Automatically allow all cross-origin requests to the discovery endpoints +  * Automatically allow all cross-origin requests to the JSON Web Keys endpoint +  * Optionally allow cross-origin requests to the other endpoints individually + +### Beta 5 + +{{< roadmap-status >}} + +Feature List: + +* Prompt Handling +* Display Handling + +See [OpenID Connect Core (Mandatory to Implement Features for All OpenID Providers)]. + +### Beta 6 + +{{< roadmap-status >}} + +Feature List: + +* Revoke Tokens on User Logout or Expiration +* [JSON Web Key Rotation](https://openid.net/specs/openid-connect-messages-1_0-20.html#rotate.sig.keys) +* Hashed Client Secrets + +### General Availability + +{{< roadmap-status >}} + +Feature List: + +* Enable by Default +* Only after all previous stages are checked for bugs + +### Miscellaneous + +This stage lists features which individually do not fit into a specific stage and may or may not be implemented. + +#### OpenID Connect Dynamic Client Registration + +{{< roadmap-status >}} + +See the [OpenID Connect] website for the [OpenID Connect Dynamic Client Registration] specification. + +#### OpenID Connect Back-Channel Logout + +{{< roadmap-status >}} + +See the [OpenID Connect] website for the [OpenID Connect Back-Channel Logout] specification. + +Should be implemented alongside [Dynamic Client Registration](#openid-connect-dynamic-client-registration). + +#### OpenID Connect Front-Channel Logout + +{{< roadmap-status >}} + +See the [OpenID Connect] website for the [OpenID Connect Front-Channel Logout] specification. + +Should be implemented alongside [Dynamic Client Registration](#openid-connect-dynamic-client-registration). + +#### OAuth 2.0 Authorization Server Metadata + +{{< roadmap-status stage="complete" version="v4.34.0" >}} + +See the [IETF Specification RFC8414](https://www.rfc-editor.org/rfc/rfc8414.html) for more information. + +#### OpenID Connect Session Management + +{{< roadmap-status >}} + +See the [OpenID Connect] website for the [OpenID Connect Session Management] specification. + +#### End-User Scope Grants + +{{< roadmap-status >}} + +Allow users to choose which scopes they grant. + +#### Client RBAC + +{{< roadmap-status >}} + +Allow clients to be configured with a list of users and groups who have access to them. + +#### Preferred Username Claim + +{{< roadmap-status stage="complete" version="v4.33.2" >}} + +The `preferred_username` claim was missing and was fixed. + +[Cross Origin Resource Sharing]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS + +[RFC8176]: https://www.rfc-editor.org/rfc/rfc8176.html +[RFC8693 Section 4.3]: https://www.rfc-editor.org/rfc/rfc8693.html/#section-4.3 +[RFC4122]: https://www.rfc-editor.org/rfc/rfc4122.html + +[OpenID Connect]: https://openid.net/connect/ +[OpenID Connect Front-Channel Logout]: https://openid.net/specs/openid-connect-frontchannel-1_0.html +[OpenID Connect Back-Channel Logout]: https://openid.net/specs/openid-connect-backchannel-1_0.html +[OpenID Connect Session Management]: https://openid.net/specs/openid-connect-session-1_0.html +[OpenID Connect Dynamic Client Registration]: https://openid.net/specs/openid-connect-registration-1_0.html + +[OpenID Connect Core (ID Token)]: https://openid.net/specs/openid-connect-core-1_0.html#IDToken +[OpenID Connect Core (Subject Identifier Types)]: https://openid.net/specs/openid-connect-core-1_0.html#SubjectIDTypes +[OpenID Connect Core (Pairwise Identifier Algorithm)]: https://openid.net/specs/openid-connect-core-1_0.html#PairwiseAlg +[OpenID Connect Core (Mandatory to Implement Features for All OpenID Providers)]: https://openid.net/specs/openid-connect-core-1_0.html#ServerMTI diff --git a/docs/content/en/roadmap/active/webauthn.md b/docs/content/en/roadmap/active/webauthn.md new file mode 100644 index 000000000..11d38b011 --- /dev/null +++ b/docs/content/en/roadmap/active/webauthn.md @@ -0,0 +1,75 @@ +--- +title: "WebAuthn" +description: "Authelia WebAuthn Implementation" +lead: "An introduction into the Authelia roadmap." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  roadmap: +    parent: "active" +weight: 220 +toc: true +--- + +[WebAuthn] requires urgent implementation as it is being deprecated by Chrome. It is a modern evolution of the +[FIDO U2F] protocol and is very similar in many ways. It even includes a backwards compatability extension called +the [FIDO AppID Extension] which allows a previously registered [FIDO U2F] device to be used with the protocol to +authenticate. + +## Stages + +This section represents the stages involved in implementation of this feature. The stages are either in order of +implementation due to there being an underlying requirement to implement them in this order, or in their likely order +due to how important or difficult to implement they are. + +### Initial Implementation + +{{< roadmap-status stage="complete" version="v4.34.0" >}} + +Implement [WebAuthn] as a replacement for [FIDO U2F] with backwards compatibility. + +|                       Setting                        |     Value      |                                                                Effect                                                                | +|:----------------------------------------------------:|:--------------:|:------------------------------------------------------------------------------------------------------------------------------------:| +|              [Conveyancing Preference]               |    indirect    | Configurable: ask users to permit collection of the AAGUID, this is like a model number, this GUID will be stored in the SQL storage | +|           [User Verification Requirement]            |   preferred    |                           Configurable: ask the browser to prompt for the users PIN or other verification                            | +|              [Resident Key Requirement]              |  discouraged   |                                       See the [passwordless login stage](#passwordless-login)                                        | +|              [Authenticator Attachment]              | cross-platform |                                   See the [platform authenticator stage](#platform-authenticator)                                    | +|              Multi-Device Registration               |  unavailable   |                                see the [multi device registration stage](#multi-device-registration)                                 | + +### Multi Device Registration + +{{< roadmap-status >}} + +Implement multi device registration as part of the user interface. This is technically implemented for the most part in +the backend, it's just the public facing interface elements remaining. + +### Platform Authenticator + +{{< roadmap-status >}} + +Implement [WebAuthn] Platform Authenticators so that people can use things like [Windows Hello], [TouchID], [FaceID], +or [Android Security Key]. This would also allow configuration of the [Authenticator Attachment] setting most likely, +or at least allow admins to configure which ones are available for registration. + +### Passwordless Login + +{{< roadmap-status >}} + +Implement the [WebAuthn] flow for [Passwordless Login]. This would also allow configuration of the +[Resident Key Requirement] setting most likely, or at least allow admins to configure which ones are available for +registration. + +[FIDO U2F]: https://fidoalliance.org/specs/u2f-specs-master/fido-u2f-overview.html +[WebAuthn]: https://www.w3.org/TR/webauthn-2/ +[Passwordless Login]: https://www.w3.org/TR/webauthn-2/#client-side-discoverable-public-key-credential-source +[Conveyancing Preference]: https://www.w3.org/TR/webauthn-2/#enum-attestation-convey +[User Verification Requirement]: https://www.w3.org/TR/webauthn-2/#enum-userVerificationRequirement +[Resident Key Requirement]: https://www.w3.org/TR/webauthn-2/#enum-residentKeyRequirement +[Authenticator Attachment]: https://www.w3.org/TR/webauthn-2/#enum-attachment +[FIDO AppID Extension]: https://www.w3.org/TR/webauthn-2/#sctn-appid-extension + +[Windows Hello]: https://support.microsoft.com/en-us/windows/learn-about-windows-hello-and-set-it-up-dae28983-8242-bb2a-d3d1-87c9d265a5f0 +[TouchID]: https://support.apple.com/en-us/HT201371 +[FaceID]: https://support.apple.com/en-au/HT208109 +[Android Security Key]: https://support.google.com/accounts/answer/9289445?hl=en&co=GENIE.Platform%3DAndroid diff --git a/docs/content/en/roadmap/prologue/_index.md b/docs/content/en/roadmap/prologue/_index.md new file mode 100644 index 000000000..94e51a167 --- /dev/null +++ b/docs/content/en/roadmap/prologue/_index.md @@ -0,0 +1,9 @@ +--- +title : "Prologue" +description: "Roadmap Prologue" +lead: "" +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +weight: 100 +--- diff --git a/docs/content/en/roadmap/prologue/introduction.md b/docs/content/en/roadmap/prologue/introduction.md new file mode 100644 index 000000000..add3f6b1c --- /dev/null +++ b/docs/content/en/roadmap/prologue/introduction.md @@ -0,0 +1,32 @@ +--- +title: "Prologue" +description: "An introduction into the Authelia roadmap." +lead: "An introduction into the Authelia roadmap." +date: 2022-03-20T12:52:27+11:00 +draft: false +images: [] +menu: +  roadmap: +    parent: "prologue" +weight: 110 +toc: true +aliases: +  - /docs/roadmap/ +--- + +The Authelia team consists of 3 globally distributed developers working actively on improving Authelia in our spare time +and we define our priorities based on a roadmap that we share here for transparency. We also try to balance features and +improvements as much as possible with the maintenance tasks we have to perform to keep the backlog of open issues in a +reasonable state. If you're willing to contribute and help us move forward faster, get in touch with us on Matrix. We'll +be glad to share ideas and plans with you. + +## Summary + +This is a summary of the features which are currently on the roadmap with links to further details: + +1. [WebAuthn](../active/webauthn.md) +2. [OpenID Connect Provider](../active/openid-connect.md) +3. [Internationalization or Multilingual Support](../active/internationalization.md) +4. [Multiple Domain Protection](../active/multi-domain-protection.md) +5. [Control Panel / Dashboard for User / Administration Settings](../active/dashboard-control-panel.md) +6. [Kubernetes Documentation](../active/kubernetes-documentation.md) diff --git a/docs/contributing/authelia-scripts.md b/docs/contributing/authelia-scripts.md deleted file mode 100644 index 293ff717a..000000000 --- a/docs/contributing/authelia-scripts.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -layout: default -title: Authelia Scripts -parent: Contributing -nav_order: 2 ---- - -# Authelia Scripts - -Authelia comes with a set of dedicated scripts to perform a broad range of operations such as building the distributed  -version of Authelia, building the Docker image, running suites, testing the code, etc... - -Those scripts become available after sourcing the bootstrap.sh script with - -```console -$ source bootstrap.sh -``` - -Then, you can access the scripts usage by running the following command: - -```console -$ authelia-scripts --help -``` - -For instance, you can build Authelia (Go binary and frontend) with: - -```console -$ authelia-scripts build -``` -     - -Or build the official Docker image with: - -```console -$ authelia-scripts docker build -``` - -Or start the *Standalone* suite with: - -```console -$ authelia-scripts suites setup Standalone -``` - -You will find more information in the scripts usage helpers. diff --git a/docs/contributing/build-and-dev.md b/docs/contributing/build-and-dev.md deleted file mode 100644 index b0ef4b1ae..000000000 --- a/docs/contributing/build-and-dev.md +++ /dev/null @@ -1,88 +0,0 @@ ---- -layout: default -title: Build & Dev -parent: Contributing -nav_order: 1 ---- - -# Build & Dev - -**Authelia** is written in Go and comes with a dedicated CLI called [authelia-scripts](./authelia-scripts.md) which is  -available after running `source bootstrap.sh`. This CLI provides many useful tools to help you during development. - -In order to build and contribute to **Authelia**, you need to make sure Go >= v1.16, Docker, docker-compose and  -Node >= v12 are installed on your machine. - -## Get started - -**Authelia** is made of Go application serving the API and a [React](https://reactjs.org/) application for the portal. - -In order to ease development, Authelia uses the concept of [suites] to run Authelia from source code so that your  -patches are included. This is a kind of virtual environment running **Authelia** in a complete ecosystem  -(LDAP, Redis, SQL server). Note that Authelia is hot-reloaded in the environment so that your patches are instantly  -included. - -The next command starts the suite called *Standalone*: - -```console -$ authelia-scripts suites setup Standalone -``` - -Most of the suites are using docker-compose to bootstrap the environment. Therefore, you can check the logs of all  -application by running the following command on the component you want to monitor. - -```console -$ docker logs authelia_authelia-backend_1 -f -``` - -Then, edit the code and observe how **Authelia** is automatically reloaded. - -### Unit tests - -To run the unit tests, run: - -```console -$ authelia-scripts unittest -``` - -### Integration tests - -Integration tests are located under the `internal/suites` directory and are based on Selenium. A suite is a combination  -of environment and tests. Executing a suite therefore means starting the environment, running the tests and tearing down  -the environment. Each step can be run independently: - -```console -# List the available suites -$ authelia-scripts suites list -Standalone -DuoPush -LDAP -Traefik - -# Start the environment of Standalone suite. -$ authelia-scripts suites setup Standalone - -# Run the tests related to the currently running suite. -$ authelia-scripts suites test - -# Tear down the environment -$ authelia-scripts suites teardown Standalone -``` - -In order to test all suites (approx 30 minutes), you need to make sure there is no currently running suite and then you  -should run: - -```console -$ authelia-scripts suites test -``` - -Also, you don't need to start the suite before testing it. Given you're not running any suite, just use the following  -command to test the *Standalone* suite. - -```console -$ authelia-scripts suites test Standalone -``` - -The suite will be spawned, tests will be run and then the suite will be torn down automatically. - -[suites]: ./suites.md diff --git a/docs/contributing/index.md b/docs/contributing/index.md deleted file mode 100644 index e4cfc77cc..000000000 --- a/docs/contributing/index.md +++ /dev/null @@ -1,61 +0,0 @@ ---- -layout: default -title: Contributing -nav_order: 7 -has_children: true ---- - -# Contributing - -## Development workflow - -**Authelia** and its development workflow can be tested with Docker and docker-compose on Linux. - -In order to deploy the current version of Authelia locally, run the following command and follow the instructions of  -bootstrap.sh: - -```console -$ source bootstrap.sh -``` - -Then, start the *Standalone* [suite]. -```console -$ authelia-scripts suites setup Standalone -``` - -A [suite] is kind of a virtual environment for running Authelia in a complete ecosystem. If you want more details please  -read the related [documentation](./suites.md). - -## FAQ - -### What version of Docker and docker-compose should I use? - -Here are the versions used for testing in Buildkite: - -```console -$ docker --version -Docker version 20.10.8, build 3967b7d - -$ docker-compose --version -docker-compose version 1.28.0, build unknown -``` - -### How can I serve my application under example.com? - -Don't worry, you don't need to own the domain *example.com* to test Authelia. Copy the following lines in  -your `/etc/hosts`. - -``` -192.168.240.100 home.example.com -192.168.240.100 login.example.com -192.168.240.100 singlefactor.example.com -192.168.240.100 public.example.com -192.168.240.100 secure.example.com -192.168.240.100 mail.example.com -192.168.240.100 mx1.mail.example.com -``` - -`192.168.240.100` is the IP attributed by Docker to the reverse proxy. Once added you can access the listed sub-domains  -from your browser, and they will target the reverse proxy. - -[suite]: ./suites.md
\ No newline at end of file diff --git a/docs/contributing/suites.md b/docs/contributing/suites.md deleted file mode 100644 index 096481a51..000000000 --- a/docs/contributing/suites.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -layout: default -title: Suites -parent: Contributing -nav_order: 5 ---- - -# Suites - -Authelia is a single component in interaction with many others in a complete -ecosystem. Consequently, testing the features is not as easy as we might -think. In order to solve this problem, Authelia came up with the concept of -suite which is a kind of virtual environment for Authelia and a set of tests. -A suite can setup components such as nginx, redis or mariadb in which -Authelia can run and be tested. - -This abstraction allows to prepare an environment for manual testing during -development and also to craft and run integration tests efficiently. - -## Start a suite. - -Starting a suite called *Standalone* is done with the following command: - -    $ authelia-scripts suites setup Standalone - -This command deploys the environment of the suite. - -## Run tests of a suite - -### Run tests of running suite - -If a suite is already running, you can simply type the test command -that will run the test related to the currently running suite: - -    $ authelia-scripts suites test - -### Run tests of non-running suite - -However, if no suite is running yet and you just want to run the tests of a -specific suite like *HighAvailability*, you can do so with the next command: - -    # Set up the env, run the tests and tear down the env -    $ authelia-scripts suites test HighAvailability - -### Run all tests of all suites - -Running all tests is easy. Make sure that no suite is already running and run: - -    $ authelia-scripts suites test - -### Run tests in headless mode - -As you might have noticed, the tests are run using chromedriver and selenium. It means -that the tests open an instance of Chrome that might interfere with your other activities. -In order to run the tests in headless mode to avoid the interference, use the following -command: - -    $ authelia-scripts suites test --headless - - -## Create a suite - -Creating a suite is as easy. Let's take the example of the **Standalone** suite: - -* **suite_standalone.go** - It defines the setup and teardown phases. It likely uses -docker-compose to setup the ecosystem. This file also defines the timeouts. -* **suite_standalone_test.go** - It defines the set of tests to run against the suite. -* **Standalone** directory - It contains resources required by the suite and likely -mounted in the containers. - -A suite can also be much more complex like setting up a complete Kubernetes ecosystem. -You can check the Kubernetes suite as example.
\ No newline at end of file diff --git a/docs/contributing/translations.md b/docs/contributing/translations.md deleted file mode 100644 index ae3b50aa2..000000000 --- a/docs/contributing/translations.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -layout: default -title: Translations -parent: Contributing -nav_order: 6 ---- - -# Translations - -Authelia has translations for many using facing areas of the web portal. Contributing to these translations is a very -easy process. - -The way the translation process is facilitated is via [Crowdin]. We encourage members of the community to -[join the Authelia Crowdin project](https://crwd.in/authelia) and help translate their preferred language. - -## Adding a New Language - -If the language you wish to translate is not on [Crowdin] then you can either reach out to one of the maintainers and -ask them to add it or you may make a pull request directly on GitHub. The translation files are stored within  -[this directory](https://github.com/authelia/authelia/tree/master/internal/server/locales). - -## Overrides - -Users can override translations easily locally using the [assets](../configuration/server.md#locales) directory. This is -useful if you wish to perform a translation and see if it looks correct in the browser. - - -[Crowdin]: https://crowdin.com/project/authelia
\ No newline at end of file diff --git a/docs/data/.gitkeep b/docs/data/.gitkeep new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/docs/data/.gitkeep diff --git a/docs/deployment/deployment-ha.md b/docs/deployment/deployment-ha.md deleted file mode 100644 index eecb7b922..000000000 --- a/docs/deployment/deployment-ha.md +++ /dev/null @@ -1,60 +0,0 @@ ---- -layout: default -title: Deployment - Highly-Available -parent: Deployment -nav_order: 2 ---- - -# Highly-Available Deployment - -**Authelia** can be deployed on bare metal or on Kubernetes with two -different kind of artifacts: the distributable version (binary and public_html) -or a Docker image. - -**NOTE:** If not done already, we highly recommend you first follow the -[Getting Started] documentation. - -## On Bare Metal - -**Authelia** has been designed to be a proxy companion handling the  -authentication and authorization requests for your entire infrastructure. - -As **Authelia** will be key to your architecture, it requires several -components to make it highly-available. Deploying it in production means having -an LDAP server for storing the information about the users, a Redis cache to -store the user sessions in a distributed manner, a SQL server like MariaDB to -persist user configurations and one or more nginx reverse proxies configured to -be used with Authelia. With such a setup **Authelia** can easily be scaled to -multiple instances to evenly handle the traffic. - -Here are the available steps to deploy **Authelia** given  -the configuration file is **/path/to/your/configuration.yml**. Note that you can -create your own configuration file from [config.template.yml] located at -the root of the repo. - -**NOTE**: Prefer using environment variables to set secrets in production otherwise -pay attention to the permissions of the configuration file. See -[secrets](../configuration/secrets.md) for more information. - -### Deploy with the distributable version - -    # Build it if not done already -    $ authelia-scripts build -    $ authelia --config /path/to/your/configuration.yml - -### Deploy With Docker - -    $ docker run -v /path/to/your/configuration.yml:/config/configuration.yml -e TZ=Europe/Paris authelia/authelia - -## FAQ - -### Why is this not automated? - -Ansible would be a very good candidate to automate the installation of such -an infrastructure on bare metal. We would be more than happy to review any PR on that matter. - - - -[config.template.yml]: https://github.com/authelia/authelia/blob/master/config.template.yml -[Getting Started]: ../getting-started.md -[Kubernetes]: https://kubernetes.io/ diff --git a/docs/deployment/deployment-kubernetes.md b/docs/deployment/deployment-kubernetes.md deleted file mode 100644 index 103bca226..000000000 --- a/docs/deployment/deployment-kubernetes.md +++ /dev/null @@ -1,56 +0,0 @@ ---- -layout: default -title: Deployment - Kubernetes -parent: Deployment -nav_order: 3 ---- - -# Deployment on Kubernetes - -<p> -    <img src="../images/logos/kubernetes.png" width="100" style="padding-right: 10px"> -</p> - -## UNDER CONSTRUCTION - -The following areas are actively being worked on for Kubernetes: -1. Detailed Documentaiton -2. [Helm Chart (v3)](https://github.com/authelia/chartrepo) -3. Kustomize Deployment -4. Manifest Examples - -Users are welcome to reach out directly by using any of our various [contact options](../about-us.md#contact-options).  - -### Important Notes - -The following section has special notes regarding utilizing Authelia with Kubernetes. - -1. Authelia (and all of your other applications) may receive an invalid remote IP if the service handling traffic to -   the Kubernetes Ingress of your choice doesn't have the `externalTrafficPolicy` setting configured to `local` as per -   the Kubernetes [preserving the client source ip] documentation. -2. Authelia's configuration management system conflicts with the `enableServiceLinks` option when it's set to `true` -   which is the default. This shoudld be changed to `false`. - -###  NGINX Ingress Controller  -If you use NGINX Ingress Controller you can protect an ingress with the following annotations. -The assumptions are that your public domain where authelia is running would be https://auth.mypublicdomain.com -and there would be a service called authelia with port 80 in the default namespace. - -```yaml -annotations: -  nginx.ingress.kubernetes.io/auth-response-headers: Remote-User,Remote-Name,Remote-Groups,Remote-Email -  nginx.ingress.kubernetes.io/auth-signin: https://auth.mypublicdomain.com -  nginx.ingress.kubernetes.io/auth-snippet: | -    proxy_set_header X-Forwarded-Method $request_method; -  nginx.ingress.kubernetes.io/auth-url: http://authelia.default.svc.cluster.local/api/verify -  nginx.ingress.kubernetes.io/configuration-snippet: | -    proxy_set_header X-Forwarded-Method $request_method; -``` - -## FAQ - -### RAM usage - -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 node, alternatively you can [tweak the providers settings](https://www.authelia.com/docs/configuration/authentication/file.html#memory). Otherwise, your Authelia may OOM during login. See [here](https://github.com/authelia/authelia/issues/1234#issuecomment-663910799) for more info. - -[preserving the client source ip]: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip
\ No newline at end of file diff --git a/docs/deployment/deployment-lite.md b/docs/deployment/deployment-lite.md deleted file mode 100644 index 978ff886c..000000000 --- a/docs/deployment/deployment-lite.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -layout: default -title: Deployment - Lite -parent: Deployment -nav_order: 1 ---- - -# Lite Deployment - -**Authelia** can be deployed as a lite setup with minimal external dependencies. -The setup is called lite because it reduces the number of components in the architecture -to a reverse proxy such as Nginx, Traefik or HAProxy, Authelia and Redis. - -This setup assumes you have basic knowledge and understanding of IP addresses, DNS and port -forwarding. You should setup the domain you intend to protect with Authelia to point to your -external IP address and port forward ports `80` and `443` to the host you plan to host the -`docker-compose.yml` bundle. - -Port 80 is utilised by LetsEncrypt for certificate challenges, this will [automatically -provision](https://docs.traefik.io/https/acme/) up-to-date certificates for your domain(s). - -Traefik publishes the respective services with LetsEncrypt provided certificates on port `443`. -The provided examples protect the Traefik dashboard with Authelia's one-factor auth -(traefik.example.com) and two instances of the -[whoami container](https://hub.docker.com/r/traefik/whoami) with Authelia being -bypassed (public.example.com) and another with it's two-factor auth (secure.example.com).  - -If you happen to already have an external SQL instance (MariaDB, MySQL or Postgres) this  -setup can easily be adapted to utilise said [service](../configuration/storage/index.md). - -## Steps - -- `git clone https://github.com/authelia/authelia.git` -- `cd authelia/examples/compose/lite` -- ``git checkout $(git describe --tags `git rev-list --tags --max-count=1`)`` -- Modify the `users_database.yml` the default username and password is `authelia` -- Modify the `configuration.yml` and `docker-compose.yml` with your respective domains and secrets -- `docker-compose up -d` - -## Reverse Proxy - -The [Lite bundle](https://github.com/authelia/authelia/blob/master/examples/compose/lite/docker-compose.yml) -provides pre-made examples with [Traefik2.x](./supported-proxies/traefik2.x.md), you can swap this -out for any of the [supported proxies](./supported-proxies/index.md). - -## FAQ - -### Can you give more details on why this is not suitable for production environments? - -This documentation gives instructions that will make **Authelia** non -resilient to failures and non scalable by preventing you from running multiple -instances of the application. This means that **Authelia** won't be able to distribute -the load across multiple servers and it will prevent failover in case of a -crash or an hardware issue. diff --git a/docs/deployment/index.md b/docs/deployment/index.md deleted file mode 100644 index 197b8c35b..000000000 --- a/docs/deployment/index.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -layout: default -title: Deployment -nav_order: 5 -has_children: true ---- - -# Deployment
\ No newline at end of file diff --git a/docs/deployment/supported-proxies/caddy.md b/docs/deployment/supported-proxies/caddy.md deleted file mode 100644 index 7c310b6f4..000000000 --- a/docs/deployment/supported-proxies/caddy.md +++ /dev/null @@ -1,127 +0,0 @@ ---- -layout: default -title: Caddy -parent: Proxy Integration -grand_parent: Deployment -nav_order: 1 ---- - -# Caddy - -[Caddy] is a reverse proxy supported by **Authelia**.  - -_**Important:** Caddy officially supports the forward auth flow in version 2.5.1 and greater. You must be using this  -version in order to use either Caddyfile._ - -Authelia offers integration support for the official forward auth integration method Caddy provides, we -can't reasonably be expected to offer support for all of the different plugins that exist. - -## Configuration - -Below you will find commented examples of the following configuration: - -* Authelia portal -* Protected endpoint (Nextcloud) - -### Basic examples - -This example is the preferred example for integration with Caddy. There is an [advanced example](#advanced-example) but -we _**strongly urge**_ anyone who needs to use this for a particular reason to either reach out to us or Caddy for support -to ensure the basic example covers your use case in a secure way. - - -#### Subdomain - -```Caddyfile -authelia.example.com { -	reverse_proxy authelia:9091 -} - -nextcloud.example.com { -	forward_auth authelia:9091 { -		uri /api/verify?rd=https://authelia.example.com -		copy_headers Remote-User Remote-Groups Remote-Name Remote-Email -	} -	reverse_proxy nextcloud:80 -} -``` - -#### Subpath - -```Caddyfile -example.com { -	@authelia path /authelia /authelia/* -	handle @authelia { -		reverse_proxy authelia:9091 -	} -	 -	@nextcloud path /nextcloud /nextcloud/* -	handle @nextcloud { -		forward_auth authelia:9091 { -			uri /api/verify?rd=https://example.com/authelia -			copy_headers Remote-User Remote-Groups Remote-Name Remote-Email -		} -		reverse_proxy nextcloud:80 -	} -} -``` - -## Advanced example - -The advanced example allows for more flexible customization, however the [basic example](#basic-example) should be -preferred in _most_ situations. If you are unsure of what you're doing please don't use this method. - -_**Important:** Making a mistake when configuring the advanced example could lead to authentication bypass or errors._ - -```Caddyfile -authelia.example.com { -	reverse_proxy authelia:9091 -} - -nextcloud.example.com { -	route { -		reverse_proxy authelia:9091 { -			method GET -			rewrite "/api/verify?rd=https://authelia.example.com" - -			header_up X-Forwarded-Method {method} -			header_up X-Forwarded-Uri {uri} - -			## If the auth request: -			##   1. Responds with a status code IN the 200-299 range. -			## Then: -			##   1. Proxy the request to the backend. -			##   2. Copy the relevant headers from the auth request and provide them to the backend. -			@good status 2xx -			handle_response @good { -				request_header { -					Remote-User {http.reverse_proxy.header.Remote-User} -					Remote-Groups {http.reverse_proxy.header.Remote-Groups} -					Remote-Name {http.reverse_proxy.header.Remote-Name} -					Remote-Email {http.reverse_proxy.header.Remote-Email} -				} -			} - -			## If the auth request: -			##   1. Responds with a status code NOT IN the 200-299 range. -			## Then: -			##   1. Respond with the status code of the auth request. -			##   1. Copy the response except for several headers. -			@denied { -				status 1xx 3xx 4xx 5xx -			} -			handle_response @denied { -				copy_response -				copy_response_headers { -					exclude Connection Keep-Alive Te Trailers Transfer-Encoding Upgrade -				} -			} -		} - -		reverse_proxy nextcloud:80 -	} -} -``` - - -[Caddy]: https://caddyserver.com diff --git a/docs/deployment/supported-proxies/index.md b/docs/deployment/supported-proxies/index.md deleted file mode 100644 index b99658a07..000000000 --- a/docs/deployment/supported-proxies/index.md +++ /dev/null @@ -1,65 +0,0 @@ ---- -layout: default -title: Proxy Integration -parent: Deployment -nav_order: 4 -has_children: true ---- - -# Integration with proxies - -**Authelia** works in collaboration with reverse proxies. In the sub-pages you -can find the documentation of the configuration required for every supported -proxy. - -If you are not aware of the workflow of an authentication request, reading this -[documentation](../../home/architecture.md) first is highly recommended. - - -## How Authelia integrates with proxies? - -Authelia takes authentication requests coming from the proxy and targeting the  -`/api/verify` endpoint exposed by Authelia. Two pieces of information are required for -Authelia to be able to authenticate the user request: - -* The session cookie or a `Proxy-Authorization` header (see [single factor authentication](../../features/single-factor.md)). -* The target URL of the user request (used primarily for [access control](../../features/access-control.md)). - -The target URL can be provided using one of the following ways: - -* With `X-Original-URL` header containing the complete URL of the initial request. -* With a combination of `X-Forwarded-Proto`, `X-Forwarded-Host` and `X-Forwarded-URI` headers. - -In the case of Traefik, these headers are automatically provided and therefore don't -appear in the configuration examples. - -## How can the backend be aware of the authenticated users? - -The only way Authelia can share information about the authenticated user currently is through the use of four HTTP headers: -`Remote-User`, `Remote-Name`, `Remote-Email` and `Remote-Groups`. -Those headers are returned by Authelia on requests to `/api/verify` and must be forwarded by the reverse proxy to the backends -needing them. The headers will be provided with each call to the backend once the user is authenticated. -Please note that the backend must support the use of those headers to leverage that information, many -backends still don't (and probably won't) support it. However, we are working on solving this issue with OpenID Connect/OAuth2 -which is a widely adopted open standard for access delegation. - -So, if you're developing your own application, you can read those headers and use them. If you don't own the codebase of the -backend, you need to check whether it supports this type of authentication or not. If it does not, you have three options: - -1. Enable authentication on the backend and make your users authenticate twice (not user-friendly). -2. Completely disable the authentication of your backend. This works only if all your users share the same privileges in the backend. -3. Many applications support OAuth2 so the last option would be to just wait for Authelia to be an OpenID Connect provider (https://github.com/authelia/authelia/issues/189). - -## Redirection to the login portal - -The endpoint `/api/verify` has different behaviors depending on whether -the `rd` (for redirection) query parameter is provided. - -If redirection parameter is provided and contains the URL to the login portal -served by Authelia, the request will either generate a 200 response -if the request is authenticated or perform a redirection (302 response) to the -login portal if not authenticated yet. - -If no redirection parameter is provided, the response code is either 200 or 401. The -redirection must then be handled by the proxy when an error is detected -(see [nginx](./nginx.md) example). diff --git a/docs/deployment/supported-proxies/nginx.md b/docs/deployment/supported-proxies/nginx.md deleted file mode 100644 index 6ad5799c2..000000000 --- a/docs/deployment/supported-proxies/nginx.md +++ /dev/null @@ -1,355 +0,0 @@ ---- -layout: default -title: NGINX -parent: Proxy Integration -grand_parent: Deployment -nav_order: 3 ---- - -# NGINX - -[NGINX] is a reverse proxy supported by **Authelia**. - -## Configuration - -Below you will find commented examples of the following configuration: - -* Authelia portal -* Protected endpoint (Nextcloud) -* Supplementary config - -With the below configuration you can add `authelia.conf` to virtual hosts to support protection with Authelia. -`auth.conf` is utilised to enable the protection either at the root location or a more specific location/route. -`proxy.conf` is included just for completeness. - -#### Supplementary config - -##### authelia.conf - -```nginx -set $upstream_authelia http://authelia:9091/api/verify; - -# Virtual endpoint created by nginx to forward auth requests. -location /authelia { -    internal; -    proxy_pass_request_body off; -    proxy_pass $upstream_authelia; -    proxy_set_header Content-Length ""; - -    # Timeout if the real server is dead -    proxy_next_upstream error timeout invalid_header http_500 http_502 http_503; - -    # [REQUIRED] Needed by Authelia to check authorizations of the resource. -    # Provide either X-Original-URL and X-Forwarded-Proto or -    # X-Forwarded-Proto, X-Forwarded-Host and X-Forwarded-Uri or both. -    # Those headers will be used by Authelia to deduce the target url of the user. -    # Basic Proxy Config -    client_body_buffer_size 128k; -    proxy_set_header Host $host; -    proxy_set_header X-Original-URL $scheme://$http_host$request_uri; -    proxy_set_header X-Real-IP $remote_addr; -    proxy_set_header X-Forwarded-Method $request_method; -    proxy_set_header X-Forwarded-Proto $scheme; -    proxy_set_header X-Forwarded-Host $http_host; -    proxy_set_header X-Forwarded-Uri $request_uri; -    proxy_set_header X-Forwarded-For $remote_addr; -    proxy_set_header X-Forwarded-Ssl on; -    proxy_redirect  http://  $scheme://; -    proxy_http_version 1.1; -    proxy_set_header Connection ""; -    proxy_cache_bypass $cookie_session; -    proxy_no_cache $cookie_session; -    proxy_buffers 4 32k; - -    # Advanced Proxy Config -    send_timeout 5m; -    proxy_read_timeout 240; -    proxy_send_timeout 240; -    proxy_connect_timeout 240; -} -``` - -##### auth.conf - -```nginx -# Basic Authelia Config -# Send a subsequent request to Authelia to verify if the user is authenticated -# and has the right permissions to access the resource. -auth_request /authelia; -# Set the `target_url` variable based on the request. It will be used to build the portal -# URL with the correct redirection parameter. -auth_request_set $target_url $scheme://$http_host$request_uri; -# Set the X-Forwarded-User and X-Forwarded-Groups with the headers -# returned by Authelia for the backends which can consume them. -# This is not safe, as the backend must make sure that they come from the -# proxy. In the future, it's gonna be safe to just use OAuth. -auth_request_set $user $upstream_http_remote_user; -auth_request_set $groups $upstream_http_remote_groups; -auth_request_set $name $upstream_http_remote_name; -auth_request_set $email $upstream_http_remote_email; -proxy_set_header Remote-User $user; -proxy_set_header Remote-Groups $groups; -proxy_set_header Remote-Name $name; -proxy_set_header Remote-Email $email; -# If Authelia returns 401, then nginx redirects the user to the login portal. -# If it returns 200, then the request pass through to the backend. -# For other type of errors, nginx will handle them as usual. -error_page 401 =302 https://auth.example.com/?rd=$target_url; -``` - -##### proxy.conf - -```nginx -client_body_buffer_size 128k; - -#Timeout if the real server is dead -proxy_next_upstream error timeout invalid_header http_500 http_502 http_503; - -# Advanced Proxy Config -send_timeout 5m; -proxy_read_timeout 360; -proxy_send_timeout 360; -proxy_connect_timeout 360; - -# Basic Proxy Config -proxy_set_header Host $host; -proxy_set_header X-Real-IP $remote_addr; -proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; -proxy_set_header X-Forwarded-Proto $scheme; -proxy_set_header X-Forwarded-Host $http_host; -proxy_set_header X-Forwarded-Uri $request_uri; -proxy_set_header X-Forwarded-Ssl on; -proxy_redirect  http://  $scheme://; -proxy_http_version 1.1; -proxy_set_header Connection ""; -proxy_cache_bypass $cookie_session; -proxy_no_cache $cookie_session; -proxy_buffers 64 256k; - -# If behind reverse proxy, forwards the correct IP -set_real_ip_from 10.0.0.0/8; -set_real_ip_from 172.16.0.0/12; -set_real_ip_from 192.168.0.0/16; -set_real_ip_from fc00::/7; -real_ip_header X-Forwarded-For; -real_ip_recursive on; -``` - -#### Authelia Portal - -```nginx -server { -    server_name auth.example.com; -    listen 80; -    return 301 https://$server_name$request_uri; -} - -server { -    server_name auth.example.com; -    listen 443 ssl http2; -    include /config/nginx/ssl.conf; - -    location / { -        set $upstream_authelia http://authelia:9091; # This example assumes a Docker deployment -        proxy_pass $upstream_authelia; -        include /config/nginx/proxy.conf; -    } -} -``` - -#### Protected Endpoint - -```nginx -server { -    server_name nextcloud.example.com; -    listen 80; -    return 301 https://$server_name$request_uri; -} - -server { -    server_name nextcloud.example.com; -    listen 443 ssl http2; -    include /config/nginx/ssl.conf; -    include /config/nginx/authelia.conf; # Virtual endpoint to forward auth requests - -    location / { -        set $upstream_nextcloud https://nextcloud; -        proxy_pass $upstream_nextcloud; -        include /config/nginx/auth.conf; # Activates Authelia for specified route/location, please ensure you have setup the domain in your configuration.yml -        include /config/nginx/proxy.conf; # Reverse proxy configuration -    } -} -``` - -### Basic Auth Example - -Here's an example for using HTTP basic auth on a specific endpoint. It is based on the full example above. - -##### authelia-basic.conf - -```nginx -# Notice we added the auth=basic query arg here -set $upstream_authelia http://authelia:9091/api/verify?auth=basic; - -location /authelia { -    internal; -    proxy_pass_request_body off; -    proxy_pass $upstream_authelia; -    proxy_set_header Content-Length ""; - -    # Timeout if the real server is dead -    proxy_next_upstream error timeout invalid_header http_500 http_502 http_503; - -    # [REQUIRED] Needed by Authelia to check authorizations of the resource. -    # Provide either X-Original-URL and X-Forwarded-Proto or -    # X-Forwarded-Proto, X-Forwarded-Host and X-Forwarded-Uri or both. -    # Those headers will be used by Authelia to deduce the target url of the user. -    # Basic Proxy Config -    client_body_buffer_size 128k; -    proxy_set_header Host $host; -    proxy_set_header X-Original-URL $scheme://$http_host$request_uri; -    proxy_set_header X-Real-IP $remote_addr; -    proxy_set_header X-Forwarded-Method $request_method; -    proxy_set_header X-Forwarded-Proto $scheme; -    proxy_set_header X-Forwarded-Host $http_host; -    proxy_set_header X-Forwarded-Uri $request_uri; -    proxy_set_header X-Forwarded-For $remote_addr; -    proxy_set_header X-Forwarded-Ssl on; -    proxy_redirect  http://  $scheme://; -    proxy_http_version 1.1; -    proxy_set_header Connection ""; -    proxy_cache_bypass $cookie_session; -    proxy_no_cache $cookie_session; -    proxy_buffers 4 32k; - -    # Advanced Proxy Config -    send_timeout 5m; -    proxy_read_timeout 240; -    proxy_send_timeout 240; -    proxy_connect_timeout 240; -} -``` - -##### auth-basic.conf - -Same as `auth.conf` but without the `error_page` directive. We want nginx to proxy the 401 back to the client, not to return a 301. - -```nginx -# Basic Authelia Config -# Send a subsequent request to Authelia to verify if the user is authenticated -# and has the right permissions to access the resource. -auth_request /authelia; -# Set the `target_url` variable based on the request. It will be used to build the portal -# URL with the correct redirection parameter. -auth_request_set $target_url $scheme://$http_host$request_uri; -# Set the X-Forwarded-User and X-Forwarded-Groups with the headers -# returned by Authelia for the backends which can consume them. -# This is not safe, as the backend must make sure that they come from the -# proxy. In the future, it's gonna be safe to just use OAuth. -auth_request_set $user $upstream_http_remote_user; -auth_request_set $groups $upstream_http_remote_groups; -auth_request_set $name $upstream_http_remote_name; -auth_request_set $email $upstream_http_remote_email; -proxy_set_header Remote-User $user; -proxy_set_header Remote-Groups $groups; -proxy_set_header Remote-Name $name; -proxy_set_header Remote-Email $email; -# If Authelia returns 401, then nginx passes it to the user. -# If it returns 200, then the request pass through to the backend. -``` - -#### Protected Endpoint - -```nginx -server { -    server_name nextcloud.example.com; -    listen 80; -    return 301 https://$server_name$request_uri; -} - -server { -    server_name nextcloud.example.com; -    listen 443 ssl http2; -    include /config/nginx/ssl.conf; -    include /config/nginx/authelia-basic.conf; # Use the "basic" endpoint - -    location / { -        set $upstream_nextcloud https://nextcloud; -        proxy_pass $upstream_nextcloud; -        include /config/nginx/auth-basic.conf; # Activate authelia with basic auth -        include /config/nginx/proxy.conf; # this file is the exact same as above -    } -} -``` - - -### Basic auth for specific client - -If you'd like to force basic auth for some requests, you can use the following template: - -##### authelia-detect.conf - -```nginx -set $is_basic_auth ""; # false value -set $upstream_authelia http://authelia:9091/api/verify; - -# Detect the client you want to force basic auth for here -# For the example we just match a path on the original request -if ($request_uri = "/force-basic") { -    set $is_basic_auth "true"; -    set $upstream_authelia "$upstream_authelia?auth=basic"; -} - -location = /authelia { -    # Same as above -} - -# A new virtual endpoint to used if the auth_request failed -location = /authelia-redirect { -    internal; - -    if ($is_basic_auth) { -        # This is a request where we decided to use basic auth, return a 401. -        # Nginx will also proxy back the WWW-Authenticate header from Authelia's -        # response. This is what informs the client we're expecting basic auth. -        return 401; -    } - -    # The original request didn't target /force-basic, redirect to the pretty login page -    # This is what `error_page 401 =302 https://auth.example.com/?rd=$target_url;` did. -    return 302 https://auth.example.com/$is_args$args; -} -``` - -##### auth.conf - -Here we replace `error_page` directive to determine if basic auth should be utilised or not. - -```nginx -# Basic Authelia Config -# Send a subsequent request to Authelia to verify if the user is authenticated -# and has the right permissions to access the resource. -auth_request /authelia; -# Set the `target_url` variable based on the request. It will be used to build the portal -# URL with the correct redirection parameter. -auth_request_set $target_url $scheme://$http_host$request_uri; -# Set the X-Forwarded-User and X-Forwarded-Groups with the headers -# returned by Authelia for the backends which can consume them. -# This is not safe, as the backend must make sure that they come from the -# proxy. In the future, it's gonna be safe to just use OAuth. -auth_request_set $user $upstream_http_remote_user; -auth_request_set $groups $upstream_http_remote_groups; -auth_request_set $name $upstream_http_remote_name; -auth_request_set $email $upstream_http_remote_email; -proxy_set_header Remote-User $user; -proxy_set_header Remote-Groups $groups; -proxy_set_header Remote-Name $name; -proxy_set_header Remote-Email $email; -# If Authelia returns 401, then nginx passes it to the user. -# If it returns 200, then the request pass through to the backend. -error_page 401 /authelia-redirect?rd=$target_url; -``` - -This tells nginx to use the virtual endpoint we defined above in case the auth_request failed. - -[NGINX]: https://www.nginx.com/ diff --git a/docs/deployment/supported-proxies/traefik1.x.md b/docs/deployment/supported-proxies/traefik1.x.md deleted file mode 100644 index 20ee9dade..000000000 --- a/docs/deployment/supported-proxies/traefik1.x.md +++ /dev/null @@ -1,125 +0,0 @@ ---- -layout: default -title: Traefik 1.x -parent: Proxy Integration -grand_parent: Deployment -nav_order: 4 ---- - -# Traefik - -[Traefik 1.x] is a reverse proxy supported by **Authelia**. - -## Configuration - -Below you will find commented examples of the following configuration: - -* Traefik 1.x -* Authelia portal -* Protected endpoint (Nextcloud) -* Protected endpoint with `Authorization` header for basic authentication (Heimdall) - -The below configuration looks to provide examples of running Traefik 1.x with labels to protect your endpoint (Nextcloud in this case). - -Please ensure that you also setup the respective [ACME configuration](https://docs.traefik.io/v1.7/configuration/acme/) for your Traefik setup as this is not covered in the example below. - -### Basic Authentication - -Authelia provides the means to be able to authenticate your first factor via the `Proxy-Authorization` header. -Given that this is not compatible with Traefik 1.x you can call Authelia's `/api/verify` endpoint with the `auth=basic` query parameter to force a switch to the `Authentication` header. - -##### docker-compose.yml -```yml -version: '3' - -networks: -  net: -    driver: bridge - -services: - -  traefik: -    image: traefik:v1.7.20-alpine -    container_name: traefik -    volumes: -      - /var/run/docker.sock:/var/run/docker.sock -    networks: -      - net -    labels: -      - 'traefik.frontend.rule=Host:traefik.example.com' -      - 'traefik.port=8081' -    ports: -      - 80:80 -      - 443:443 -      - 8081:8081 -    restart: unless-stopped -    command: -      - '--api' -      - '--api.entrypoint=api' -      - '--docker' -      - '--defaultentrypoints=https' -      - '--logLevel=DEBUG' -      - '--traefiklog=true' -      - '--traefiklog.filepath=/var/log/traefik.log' -      - '--entryPoints=Name:http Address::80' -      - '--entryPoints=Name:https Address::443 TLS' -      - '--entryPoints=Name:api Address::8081' - -  authelia: -    image: authelia/authelia -    container_name: authelia -    volumes: -      - /path/to/authelia:/config -    networks: -      - net -    labels: -      - 'traefik.frontend.rule=Host:login.example.com' -    expose: -      - 9091 -    restart: unless-stopped -    environment: -      - TZ=Australia/Melbourne - -  nextcloud: -    image: linuxserver/nextcloud -    container_name: nextcloud -    volumes: -      - /path/to/nextcloud/config:/config -      - /path/to/nextcloud/data:/data -    networks: -      - net -    labels: -      - 'traefik.frontend.rule=Host:nextcloud.example.com' -      - 'traefik.frontend.auth.forward.address=http://authelia:9091/api/verify?rd=https://login.example.com/' -      - 'traefik.frontend.auth.forward.trustForwardHeader=true' -      - 'traefik.frontend.auth.forward.authResponseHeaders=Remote-User,Remote-Groups,Remote-Name,Remote-Email' -    expose: -      - 443 -    restart: unless-stopped -    environment: -      - PUID=1000 -      - PGID=1000 -      - TZ=Australia/Melbourne -       -  heimdall: -    image: linuxserver/heimdall -    container_name: heimdall -    volumes: -      - /path/to/heimdall/config:/config -    networks: -      - net -    labels: -      - 'traefik.frontend.rule=Host:heimdall.example.com' -      - 'traefik.frontend.auth.forward.address=http://authelia:9091/api/verify?auth=basic' -      - 'traefik.frontend.auth.forward.trustForwardHeader=true' -      - 'traefik.frontend.auth.forward.authResponseHeaders=Remote-User,Remote-Groups,Remote-Name,Remote-Email' -    expose: -      - 443 -    restart: unless-stopped -    environment: -      - PUID=1000 -      - PGID=1000 -      - TZ=Australia/Melbourne -``` - -[Traefik 1.x]: https://docs.traefik.io/v1.7/ diff --git a/docs/deployment/supported-proxies/traefik2.x.md b/docs/deployment/supported-proxies/traefik2.x.md deleted file mode 100644 index 03c384941..000000000 --- a/docs/deployment/supported-proxies/traefik2.x.md +++ /dev/null @@ -1,156 +0,0 @@ ---- -layout: default -title: Traefik 2.x -parent: Proxy Integration -grand_parent: Deployment -nav_order: 5 ---- - -# Traefik2 - -[Traefik 2.x] is a reverse proxy supported by **Authelia**. - -## Configuration - -Below you will find commented examples of the following configuration: - -* Traefik 2.x -* Authelia portal -* Protected endpoint (Nextcloud) -* Protected endpoint with `Authorization` header for basic authentication (Heimdall) - -The below configuration looks to provide examples of running Traefik 2.x with labels to protect your endpoint (Nextcloud in this case). - -Please ensure that you also setup the respective [ACME configuration](https://docs.traefik.io/https/acme/) for your Traefik setup as this is not covered in the example below. - -### Basic Authentication - -Authelia provides the means to be able to authenticate your first factor via the `Proxy-Authorization` header, this is compatible with Traefik >= 2.4.1. -If you are running Traefik < 2.4.1, or you have a use-case which requires the use of the `Authorization` header/basic authentication login prompt you can call Authelia's `/api/verify` endpoint with the `auth=basic` query parameter to force a switch to the `Authentication` header. - -##### docker-compose.yml -```yml -version: '3' - -networks: -  net: -    driver: bridge - -services: - -  traefik: -    image: traefik:v2.2 -    container_name: traefik -    volumes: -      - /var/run/docker.sock:/var/run/docker.sock -    networks: -      - net -    labels: -      - 'traefik.enable=true' -      - 'traefik.http.routers.api.rule=Host(`traefik.example.com`)' -      - 'traefik.http.routers.api.entrypoints=https' -      - 'traefik.http.routers.api.service=api@internal' -      - 'traefik.http.routers.api.tls=true' -    ports: -      - 80:80 -      - 443:443 -    command: -      - '--api' -      - '--providers.docker=true' -      - '--providers.docker.exposedByDefault=false' -      - '--entrypoints.http=true' -      - '--entrypoints.http.address=:80' -      - '--entrypoints.http.http.redirections.entrypoint.to=https' -      - '--entrypoints.http.http.redirections.entrypoint.scheme=https' -      - '--entrypoints.https=true' -      - '--entrypoints.https.address=:443' -      - '--log=true' -      - '--log.level=DEBUG' -      - '--log.filepath=/var/log/traefik.log' - -  authelia: -    image: authelia/authelia -    container_name: authelia -    volumes: -      - /path/to/authelia:/config -    networks: -      - net -    labels: -      - 'traefik.enable=true' -      - 'traefik.http.routers.authelia.rule=Host(`login.example.com`)' -      - 'traefik.http.routers.authelia.entrypoints=https' -      - 'traefik.http.routers.authelia.tls=true' -      - 'traefik.http.middlewares.authelia.forwardauth.address=http://authelia:9091/api/verify?rd=https://login.example.com/' -      - 'traefik.http.middlewares.authelia.forwardauth.trustForwardHeader=true' -      - 'traefik.http.middlewares.authelia.forwardauth.authResponseHeaders=Remote-User, Remote-Groups, Remote-Name, Remote-Email' -      - 'traefik.http.middlewares.authelia-basic.forwardauth.address=http://authelia:9091/api/verify?auth=basic' -      - 'traefik.http.middlewares.authelia-basic.forwardauth.trustForwardHeader=true' -      - 'traefik.http.middlewares.authelia-basic.forwardauth.authResponseHeaders=Remote-User, Remote-Groups, Remote-Name, Remote-Email' -    expose: -      - 9091 -    restart: unless-stopped -    environment: -      - TZ=Australia/Melbourne - -  nextcloud: -    image: linuxserver/nextcloud -    container_name: nextcloud -    volumes: -      - /path/to/nextcloud/config:/config -      - /path/to/nextcloud/data:/data -    networks: -      - net -    labels: -      - 'traefik.enable=true' -      - 'traefik.http.routers.nextcloud.rule=Host(`nextcloud.example.com`)' -      - 'traefik.http.routers.nextcloud.entrypoints=https' -      - 'traefik.http.routers.nextcloud.tls=true' -      - 'traefik.http.routers.nextcloud.middlewares=authelia@docker' -    expose: -      - 443 -    restart: unless-stopped -    environment: -      - PUID=1000 -      - PGID=1000 -      - TZ=Australia/Melbourne -       -  heimdall: -    image: linuxserver/heimdall -    container_name: heimdall -    volumes: -      - /path/to/heimdall/config:/config -    networks: -      - net -    labels: -      - 'traefik.enable=true' -      - 'traefik.http.routers.heimdall.rule=Host(`heimdall.example.com`)' -      - 'traefik.http.routers.heimdall.entrypoints=https' -      - 'traefik.http.routers.heimdall.tls=true' -      - 'traefik.http.routers.heimdall.middlewares=authelia-basic@docker' -    expose: -      - 443 -    restart: unless-stopped -    environment: -      - PUID=1000 -      - PGID=1000 -      - TZ=Australia/Melbourne -``` - -## FAQ - -### Middleware authelia@docker not found - -If Traefik and Authelia are defined in different docker compose stacks you may experience -an issue where Traefik complains that: `middleware authelia@docker not found`. - -This can be avoided a couple different ways: -1. Ensure Authelia container is up before Traefik is started: -    - Utilise the [`depends_on` option](https://docs.docker.com/compose/compose-file/#depends_on) -2. Define the Authelia middleware on your Traefik container -```yaml -- 'traefik.http.middlewares.authelia.forwardauth.address=http://authelia:9091/api/verify?rd=https://login.example.com/' -- 'traefik.http.middlewares.authelia.forwardauth.trustForwardHeader=true' -- 'traefik.http.middlewares.authelia.forwardauth.authResponseHeaders=Remote-User, Remote-Groups, Remote-Name, Remote-Email' -``` -     -[Traefik 2.x]: https://docs.traefik.io/ diff --git a/docs/faq.md b/docs/faq.md deleted file mode 100644 index a3dccf9fc..000000000 --- a/docs/faq.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -layout: default -title: FAQ -nav_order: 8 ---- - -# Frequently asked questions - -## How can the backend be aware of the authenticated users? - -This question is solved -[here](https://www.authelia.com/docs/deployment/supported-proxies/#how-can-the-backend-be-aware-of-the-authenticated-users). - -## Why only use a private issuer key and no public key with OIDC? - -The reason for using only the private key here is that one is able to calculate the public key easily from the private -key (`openssl rsa -in rsa.key -pubout > rsa.pem`). - -## My installation broke after updating. What do I need to fix? - -Check the [migration log](https://www.authelia.com/docs/configuration/migration.html) for any steps you need to follow. It's a good idea to consult this prior to running an update. diff --git a/docs/features/2fa/index.md b/docs/features/2fa/index.md deleted file mode 100644 index 06dba31e2..000000000 --- a/docs/features/2fa/index.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -layout: default -title: Second Factor -parent: Features -nav_order: 2 -has_children: true ---- - -# Second Factor - -There are multiple supported options for the second factor. - -* Time-based One-Time passwords with compatible authenticator applications. -* Security Keys that support [FIDO2] [Webauthn] with devices like a [YubiKey]. -* Push notifications on your mobile using [Duo]. - -<p align="center"> -  <img src="../../images/2FA-METHODS.png" width="400"> -</p> - - -[Duo]: https://duo.com/ -[FIDO2]: https://www.yubico.com/authentication-standards/fido2/ -[Webauthn]: https://www.yubico.com/authentication-standards/webauthn/ -[YubiKey]: https://www.yubico.com/products/yubikey-5-overview/
\ No newline at end of file diff --git a/docs/features/2fa/one-time-password.md b/docs/features/2fa/one-time-password.md deleted file mode 100644 index 7481a960a..000000000 --- a/docs/features/2fa/one-time-password.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -layout: default -title: Time-based One-Time Password -nav_order: 1 -parent: Second Factor -grand_parent: Features ---- - -# Time-based One-Time Password - -**Authelia** supports Time-base one-time password generated by apps like [Google Authenticator]. - -<p align="center"> -  <img src="../../images/2FA-TOTP.png" width="300"> -  <img src="../../images/google-authenticator.png" width="150" class="no-border" style="margin-left: 50px"> -</p> - - -After having successfully completed the first factor, select **One-Time Password method** -option and click on **Register device** link. This will e-mail you to confirm your identity. - -*NOTE: If you're testing **Authelia**, this e-mail has likely been sent to the mailbox available at https://mail.example.com:8080/* - -Once this validation step is completed, a QR Code gets displayed. - -<p align="center"> -  <img src="../../images/REGISTER-TOTP.png" width="400"> -</p> - -You can then use [Google Authenticator] to scan the code in order to register your device. - -From now on, you get tokens generated every 30 seconds that -you can use to validate the second factor in **Authelia**. - - -## Limitations - -Users currently can only enroll a single TOTP device in **Authelia**. -Multiple single type device enrollment will be available when [this issue](https://github.com/authelia/authelia/issues/275) has been resolved. - -[Google Authenticator]: https://google-authenticator.com/ diff --git a/docs/features/2fa/push-notifications.md b/docs/features/2fa/push-notifications.md deleted file mode 100644 index 5443fb912..000000000 --- a/docs/features/2fa/push-notifications.md +++ /dev/null @@ -1,60 +0,0 @@ ---- -layout: default -title: Push Notification -parent: Second Factor -nav_order: 3 -grand_parent: Features ---- - -# Mobile Push Notification - -Mobile push notifications is the new trendy second factor method. When second factor is requested -by Authelia, a notification is sent on your phone that you can either accept or deny. - -<p align="center"> -  <img src="../../images/duo-push-1.jpg" width="200"> -  <img src="../../images/duo-push-2.png" width="200"> -</p> - - -Authelia leverages [Duo] third party to provide this feature. - -First, sign up on their website, log in, create a user account and attach it a mobile device. -Beware that the name of the user must match the name of the user in Authelia. - -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** and then you must add the generated information -to Authelia [configuration](../../deployment/index.md) as shown below: - -    duo_api: -      hostname: api-123456789.example.com -      integration_key: ABCDEF -      secret_key: 1234567890abcdefghifjkl - -Now that Authelia is configured, pass the first factor and select the Push notification -option. - -<p align="center"> -  <img src="../../images/2FA-PUSH.png" width="400"> -</p> - -You should now receive a notification on your mobile phone with all the details -about the authentication request. -In case you have multiple devices available, you will be asked to select your preferred device. - - -## Limitation - -Users must be enrolled via the Duo Admin panel, they cannot enroll a device from -**Authelia** yet. - - -## FAQ - -### Why don't I have access to the *Push Notification* option? - -It's likely that you have not configured **Authelia** correctly. Please read this -documentation again and be sure you had a look at [config.template.yml](https://github.com/authelia/authelia/blob/master/config.template.yml). - -[Duo]: https://duo.com/ diff --git a/docs/features/access-control.md b/docs/features/access-control.md deleted file mode 100644 index 62d3c5a9c..000000000 --- a/docs/features/access-control.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -layout: default -title: Access Control -parent: Features -nav_order: 5 ---- - -# Access Control - -**Authelia** allows to define a fine-grained rule-based access control policy in -configuration. This list of rules is tested against any requests protected by -Authelia and defines the level of authentication the user must pass to get access -to the resource. - -For instance a rule can look like this: - -```yaml -- domain: dev.example.com -  resources: -    - '^/groups/dev/.*$' -  subject: 'group:dev' -  policy: two_factor -``` - - -This rule matches when the request targets the domain `dev.example.com` and the path -matches the regular expression `^/groups/dev/.*$`. In that case, a two-factor policy -is applied requiring the user to authenticate with two factors. - -## Configuration - -Please check the dedicated [documentation](../configuration/access-control.md) diff --git a/docs/features/first-factor.md b/docs/features/first-factor.md deleted file mode 100644 index fb61c225e..000000000 --- a/docs/features/first-factor.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -layout: default -title: First Factor -parent: Features -nav_order: 1 ---- - -# First Factor - -2-Factor authentication is a method in which a user is granted access by presenting -two pieces of evidence that she is who she claims to be. - -**Authelia** requires usual username and password as a first factor. - -<p align="center"> -  <img src="../images/1FA.png" width="400"> -</p> - -*IMPORTANT: This is currently the only method available as first factor. Using other methods will likely be possible when [WebAuthN](https://github.com/authelia/authelia/issues/241) is implemented* - -Authelia supports several kind of users databases: - -* An LDAP server like OpenLDAP or OpenAM. -* An Active Directory. -* A YAML file diff --git a/docs/features/index.md b/docs/features/index.md deleted file mode 100644 index ebc8196a5..000000000 --- a/docs/features/index.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -layout: default -title: Features -nav_order: 3 -has_children: true ---- - -# Features - -**Authelia** is a 2FA & SSO authentication server which is dedicated -to the security of applications and users. It can be considered -as an extension of reverse proxies by providing features specific -to authentication. You will find among other features: - -* Multiple two-factor methods. -* Identity verification when registering second factor devices. -* Reset password. -* Ban account after too many attempts (known as regulation). diff --git a/docs/features/logout.md b/docs/features/logout.md deleted file mode 100644 index 6f7137778..000000000 --- a/docs/features/logout.md +++ /dev/null @@ -1,51 +0,0 @@ ---- -layout: default -title: Logout -parent: Features -nav_order: 8 ---- - -# Logout - -Authelia is able to log out your users to ensure their account is not exposed anymore when they stop -surfing the web. - -When user is logged out, the cookie attached to this user is reset on the backend side. Therefore, any -subsequent request using this old cookie is considered unauthenticated by Authelia. In this case the user -is simply redirected to the login page and has to authenticate again to generate a new session with a new cookie. - -## Methods to log out - -## Frontend - -In most websites and applications, users can usually click on a logout button to be signed out and Authelia -offers the same feature. - -Implementing logout is as easy as putting a link or button somewhere on your application or website with -the following href: `https://auth.example.com/logout` where `auth.example.com` is the domain serving Authelia. -By default, this would redirect the user to the login page of Authelia but one can force the redirection to any -domain protected by Authelia by appending the 'rd' query parameter which should be set to the target URL where -the user should be redirected. For instance, `https://auth.example.com/logout?rd=https://homepage.example.com`. - -Please note that an attempt of redirection to a domain which is not a subdomain protected by Authelia will be -skipped for security reasons described later in this page. - -## Backend - -The backend API can also be called directly from your applications if needed. The endpoint is /api/logout which -is taking a POST request with a body like: - -    { -        "targetURL": "https://homepage.example.com" -    } - -Please note that an attempt of redirection to a domain which is not a subdomain protected by Authelia will be -skipped for security reasons described later in this page. - -## Why preventing redirection to some domains? - -This is a security feature which is protecting your users against attacks called open redirect. This kind of attack -is described [here](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) -by the [OWASP](https://en.wikipedia.org/wiki/OWASP#:~:text=The%20Open%20Web%20Application%20Security,field%20of%20web%20application%20security.&text=It%20is%20led%20by%20a%20non%2Dprofit%20called%20The%20OWASP%20Foundation.). -In a nutshell, hackers can send phishing emails to your users and trick them by making them click on a legit link -eventually redirecting to an infected website.
\ No newline at end of file diff --git a/docs/features/password-policy.md b/docs/features/password-policy.md deleted file mode 100644 index afe658d6e..000000000 --- a/docs/features/password-policy.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -layout: default -title: Password Policy -parent: Features -nav_order: 8 ---- - -# Password Policy - -Password policy enforces the security by requiring the users to use strong passwords. - -Currently, two methods are supported: - -## classic - -This mode of operation allows administrators to set the rules that user passwords must comply with when changing their -password. - -The available options are:  -  * Minimum password length -  * Require Uppercase -  * Require Lowercase -  * Require Numbers -  * Require Special characters - - -<p align="center"> -  <img src="../images/password-policy-classic-1.png" width="400"> -</p> - - -## zxcvbn - -This mode uses [zxcvbn](https://github.com/dropbox/zxcvbn) for password strength checking. In this mode of operation,  -the user is not forced to follow any rules. The user is notified if their passwords is weak or strong. - -<p align="center"> -  <img src="../images/password-policy-zxcvbn-1.png" width="400"> -</p> - - - - diff --git a/docs/features/password-reset.md b/docs/features/password-reset.md deleted file mode 100644 index 7e1c3f729..000000000 --- a/docs/features/password-reset.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -layout: default -title: Password Reset -parent: Features -nav_order: 4 ---- - -# Password Reset - -**Authelia** provides a workflow to let users reset their password when they lose it. -To disable reset password functionality please see the [configuration docs](../configuration/authentication/index.md#disable_reset_password). - -A simple click on `Reset password?` for starting the process. Note that resetting a -password requires a new identity verification using the e-mail of the user. - -<p align="center"> -  <img src="../images/1FA.png" width="400"> -</p> - -Give your username and receive an e-mail to verify your identity. - -<p align="center"> -  <img src="../images/RESET-PASSWORD-STEP1.png" width="400"> -</p> - -Once your identity has been verified, fill in the form to reset your password. - -<p align="center"> -  <img src="../images/RESET-PASSWORD-STEP2.png" width="400"> -</p> - -Now you can authenticate with your new credentials.
\ No newline at end of file diff --git a/docs/features/regulation.md b/docs/features/regulation.md deleted file mode 100644 index 7b77bb636..000000000 --- a/docs/features/regulation.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -layout: default -title: Regulation -parent: Features -nav_order: 6 ---- - -# Regulation - -**Authelia** takes the security of users very seriously and comes with -a way to avoid brute-forcing the first factor credentials by regulating the -authentication attempts and temporarily banning an account when too many -attempts have been made. - -## Configuration - -Please check the dedicated [documentation](../configuration/regulation.md).
\ No newline at end of file diff --git a/docs/features/single-factor.md b/docs/features/single-factor.md deleted file mode 100644 index b7b4bd568..000000000 --- a/docs/features/single-factor.md +++ /dev/null @@ -1,90 +0,0 @@ ---- -layout: default -title: Single Factor -parent: Features -nav_order: 3 ---- - -# Single Factor - -**Authelia** supports single factor authentication to let applications -send authenticated requests to other applications. - -Single or two-factor authentication can be configured per resource of an -application for flexibility. - -For instance, you can configure Authelia to grant access to all resources -matching `app1.example.com/api/(.*)` with only a single factor and all -resources matching `app1.example.com/admin` with two factors. - -To know more about the configuration of the feature, please visit the -documentation about the [configuration](../configuration/access-control.md). - - -## HTTP Basic Auth - -Authelia supports two different methods for basic auth. - -### Proxy-Authorization header - -Authelia reads credentials from the header `Proxy-Authorization` instead of -the usual `Authorization` header. This is because in some circumstances both Authelia -and the application could require authentication in order to provide specific -authorizations at the level of the application. - -### API argument - -If instead of the `Proxy-Authorization` header you want, or need, to use the more -conventional `Authorization` header, you should then configure your reverse-proxy -to use `/api/verify?auth=basic`.   -When authentication fails and `auth=basic` was set, Authelia's response will include -the `WWW-Authenticate` header. This will cause browsers to prompt for authentication, -and users will not land on the HTML login page. - - -## Session-Username header - -Authelia by default only verifies the cookie and the associated user with that cookie can -access a protected resource. The client browser does not know the username and does not send -this to Authelia, it's stored by Authelia for security reasons. - -The Session-Username header has been implemented as a means -to use Authelia with non-web services such as PAM. Basically how it works is if the -Session-Username header is sent in the request to the /api/verify endpoint it will -only respond with a sucess message if the cookie username and the header username -match. - -### Example - -These examples are for demonstration purposes only, the original use case and full instructions -are described [here](https://github.com/authelia/authelia/issues/1322#issuecomment-729519155). -You will need to adjust the FORWARDED_HOST and VERIFY_URL vars to achieve a functional result. - -#### PAM Rule - -`auth    [success=1 default=ignore]      pam_exec.so expose_authtok /usr/bin/pam-authelia ` - -#### PAM Script - -```bash -#!/bin/bash -# The password from stdin -PAM_PASSWORD=$(cat -) - -# url from which authelia session key was created -FORWARDED_HOST=auth.example.com - -# internal path to verify api -VERIFY_URL=http://127.0.0.1:80/api/verify - -AUTH_RESULT=$(curl -b "authelia_session=${PAM_PASSWORD}" -H "Session-Username: ${PAM_USER}" -H "X-Forwarded-Host: ${FORWARDED_HOST}" -H "X-Forwarded-Proto: https" -s -o /dev/null -I -w "%{http_code}" -L "${VERIFY_URL}") - -if [[ "$AUTH_RESULT" == 200 ]]; then -  echo "Auth verify ok" -  exit 0 -else -  echo "Auth verify failed $AUTH_RESULT" -  exit 1 -fi -``` - diff --git a/docs/features/statelessness.md b/docs/features/statelessness.md deleted file mode 100644 index 89a7d7940..000000000 --- a/docs/features/statelessness.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -layout: default -title: Statelessness -parent: Features -nav_order: 7 ---- - -# Statelessness - -**Authelia** supports operating as a stateless application. This is incredibly important -when running in highly available deployments like you may see in platforms like Kubernetes. - -## Stateful Considerations - -There are some components within **Authelia** that may optionally be made stateful by using -certain providers. Examples of this are as follows: - -### Session Provider - -**Severity:** *BREAKING*. - -**Solution:** Use a session provider other than memory (Redis). - -If you do not configure an external provider for the session configuration -it stores the session in memory. This is unacceptable for the operation of -**Authelia** and is thus not supported for high availability. - - -### Storage Provider - -**Severity:** *BREAKING*. - -**Solution:** Use a session provider other than SQLite3 (MySQL, MariaDB, PostgreSQL). - -Use of the local storage provider (SQLite3) is not supported in high availability setups -due to a design limitation with how SQLite3 operates. Use any of the other storage providers. - - -### Notification Provider - -**Severity:** *HIGH*. - -**Solution:** Use a notification provider other than file system (SMTP). - -Use of the file system notification provider prevents users from several key tasks which heavily impact usability of -the system, and technically reduce security. Users will be unable to reset passwords or register new 2FA devices on -their own. The file system provider is not supported for high availability.  - -### Authentication Provider - -**Severity:** *MEDIUM (limiting)*. - -**Solution:** Use an authentication provider other than file (LDAP), or distribute the file and disable password reset. - -Use of the file authentication provider (YAML) is only partially supported with high availability setups. It's  -recommended if you don't use a stateless provider that you disable password reset and make sure the file is distributed  -to all instances. We do not support using the file type in these scenarios.
\ No newline at end of file diff --git a/docs/functions/.gitkeep b/docs/functions/.gitkeep new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/docs/functions/.gitkeep diff --git a/docs/getting-started.md b/docs/getting-started.md deleted file mode 100644 index 0f27c3a5d..000000000 --- a/docs/getting-started.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -layout: default -title: Getting Started -nav_order: 2 ---- - -# Getting Started - -## Docker Compose - -### Steps - -These commands are to be run sequentially: - -- `git clone https://github.com/authelia/authelia.git` -- `cd authelia/examples/compose/local` -- ``git checkout $(git describe --tags `git rev-list --tags --max-count=1`)`` -- `./setup.sh` *sudo is required to modify the `/etc/hosts` file, the user will be prompted for access if not run as root* - -You can now visit the following locations; replace example.com with the domain you specified in the setup script: -- https://public.example.com - Bypasses Authelia -- https://traefik.example.com - Secured with Authelia one-factor authentication -- https://secure.example.com - Secured with Authelia two-factor authentication (see note below) - -You will need to authorize the self-signed certificate upon visiting each domain. -To visit https://secure.example.com you will need to register a device for second factor authentication and confirm by clicking on a link sent by email. -Since this is a demo with a fake email address, the content of the email will be stored in `./authelia/notification.txt`. -Upon registering, you can grab this link easily by running the following command: `grep -Eo '"https://.*" ' ./authelia/notification.txt`. - -## Deployment - -So you're convinced that Authelia is what you need. You can head to the deployment documentation [here](./deployment/index.md). -Some recipes have been crafted for helping with the bootstrap of your environment. -You can choose between a [lite](./deployment/deployment-lite.md) deployment which is deployment advised for a single server setup. -However, this setup just does not scale. If you want a full environment that can scale out, use the [HA](./deployment/deployment-ha.md) or [Kubernetes](./deployment/deployment-kubernetes.md) deployment documentation.
\ No newline at end of file diff --git a/docs/home/architecture.md b/docs/home/architecture.md deleted file mode 100644 index 5f6fc5783..000000000 --- a/docs/home/architecture.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -layout: default -title: Architecture -parent: Home -nav_order: 1 ---- - -# Architecture - -**Authelia** is a companion of reverse proxies like Nginx, Traefik and HAProxy. -It can be seen as an extension of those proxies providing authentication functions -and a login portal. - -As shown in the following architecture diagram, Authelia is directly connected to -the reverse proxy but never directly connected to application backends and therefore -the payloads sent by the clients of the protected API will never reach Authelia, only -the authentication pieces will, like the Authorization header for instance. Consequently, -the protected APIs can be a REST, a GraphQL or any other kind of API on top of HTTP. - -<p align="center" style="margin:50px"> -  <img src="../images/archi.png"/> -</p> - -## Workflow - -Reverse proxies are configured so that every incoming request generates an authentication -request sent to Authelia. Authelia responds and will instruct the reverse proxy to either allow -the incoming request to pass through, or block it because the user is not authenticated -or is not sufficiently authorized. - -### Step by step - -When the first request of an unauthenticated user hits the reverse proxy, Authelia -determines the user is not authenticated because no session cookie has been sent along with -the request. Consequently, Authelia redirects the user to the authentication portal provided -by Authelia itself. The user can then execute the authentication workflow using that portal -to obtain a session cookie valid for all subdomains of the domain protected by Authelia. - -When the user visits the initial website again, the query is sent along with the -session cookie which is forwarded in the authentication request to Authelia. This time, -Authelia can verify the user is authenticated and order the reverse proxy to let the query -pass through. - -### Sequence Diagram - -Here is a description of the complete workflow: - -<p align="center"> -  <img src="../images/sequence-diagram.png"/> -</p> - -## HTTP/HTTPS - -Authelia only works for websites served over HTTPS because the session cookie can only be -transmitted over secure 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)). - -If a self-signed certificate is required, the following command can be used to generate one: - -    # Generate a certificate covering "example.com" for one year in the /tmp/certs/ directory. -    $ docker run authelia/authelia authelia certificates generate --host example.com --dir /tmp/certs/ diff --git a/docs/home/supported-proxies.md b/docs/home/supported-proxies.md deleted file mode 100644 index 3b119aea3..000000000 --- a/docs/home/supported-proxies.md +++ /dev/null @@ -1,97 +0,0 @@ ---- -layout: default -title: Supported Proxies -parent: Home -nav_order: 2 ---- - -The following table is a support matrix for Authelia features and specific reverse proxies. - -|     Proxy      |                                      [Standard Support](#standard)                                      |                                [Kubernetes Support](#kubernetes)                                 |             [XHR Redirect](#xhr-redirect)              |           [Request Method](#request-method)            | -|:--------------:|:-------------------------------------------------------------------------------------------------------:|:------------------------------------------------------------------------------------------------:|:------------------------------------------------------:|:------------------------------------------------------:| -|    [NGINX]     |   [<span class="material-icons green">check_circle</span>](../deployment/supported-proxies/nginx.md)    | [<span class="material-icons green">check_circle</span>](../deployment/deployment-kubernetes.md) |     <span class="material-icons red">cancel</span>     | <span class="material-icons green">check_circle</span> | -| [Traefik] 1.x  | [<span class="material-icons green">check_circle</span>](../deployment/supported-proxies/traefik1.x.md) |                         <span class="material-icons orange">error</span>                         | <span class="material-icons green">check_circle</span> | <span class="material-icons green">check_circle</span> | -| [Traefik] 2.x  | [<span class="material-icons green">check_circle</span>](../deployment/supported-proxies/traefik2.x.md) | [<span class="material-icons green">check_circle</span>](../deployment/deployment-kubernetes.md) | <span class="material-icons green">check_circle</span> | <span class="material-icons green">check_circle</span> | -|   [HAProxy]    |  [<span class="material-icons green">check_circle</span>](../deployment/supported-proxies/haproxy.md)   |                          <span class="material-icons red">cancel</span>                          |    <span class="material-icons orange">error</span>    | <span class="material-icons green">check_circle</span> | -| [Caddy] 2.5.1+ |   [<span class="material-icons green">check_circle</span>](../deployment/supported-proxies/caddy.md)    |                          <span class="material-icons red">cancel</span>                          | <span class="material-icons green">check_circle</span> | <span class="material-icons green">check_circle</span> | -|    [Envoy]     |                            <span class="material-icons orange">error</span>                             |                         <span class="material-icons orange">error</span>                         |    <span class="material-icons orange">error</span>    |    <span class="material-icons orange">error</span>    | -|    [Apache]    |                             <span class="material-icons red">cancel</span>                              |                          <span class="material-icons red">cancel</span>                          |     <span class="material-icons red">cancel</span>     |     <span class="material-icons red">cancel</span>     | -|     [IIS]      |                             <span class="material-icons red">cancel</span>                              |                          <span class="material-icons red">cancel</span>                          |     <span class="material-icons red">cancel</span>     |     <span class="material-icons red">cancel</span>     | - -<span class="material-icons green">check_circle</span> *Support confirmed, additionally these icons are links to documentation for both the Standard and Kubernetes support columns* - -<span class="material-icons orange">error</span> *Support is likely and being investigated* - -<span class="material-icons red">cancel</span> *Either not supported or unlikely to be supported* - -## Support - -### Standard - -Standard support includes the essential features in securing an application with Authelia such as: - -- Redirecting users to the Authelia portal if they are not authenticated. -- Redirecting users to the target application after authentication has occurred successfully. - -It does not include actually running Authelia as a service behind the proxy, any proxy should be compatible with serving -the Authelia portal itself. Standard support is only important for protected applications. - -### Kubernetes - -While proxies that generally support Authelia outside a [Kubernetes] cluster, there are a few situations where that does -not translate to being possible when used as an [Ingress Controller]. There are various reasons for this such as the -reverse proxy in question does not even support running as a [Kubernetes] [Ingress Controller], or the required modules -to perform authentication transparently to the user are not typically available inside a cluster. - -More information about [Kubernetes] deployments of Authelia can be read in the  -[documentation](../deployment/deployment-kubernetes.md). - -### XHR Redirect - -XML HTTP Requests do not typically redirect browsers when returned 30x status codes. Instead, the standard method is to -return a 401 status code with a Location header. While this may seem trivial; currently there isn't wide support for it. -For example nginx's ngx_http_auth_request_module does not seem to support this in any way. - -### Request Method - -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  -[Standard Support](#standard-support) do support this. - -## Specific proxy notes - -### HAProxy - -[HAProxy] is only supported via a lua [module](https://github.com/haproxytech/haproxy-lua-http). Lua is typically not  -available in [Kubernetes]. You would likely have to build your own [HAProxy] image. - -### Envoy - -[Envoy] is currently not documented however we believe it is likely to be technically supported. This should be possible -via [Envoy]'s [external authorization](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ext_authz/v3/ext_authz.proto.html#extensions-filters-http-ext-authz-v3-extauthz). - -### Caddy - -[Work](https://github.com/authelia/caddy-forwardauth) is being done to support Caddy 2.x, however this is a low  -priority. You can see the progress and try it for yourself if you're interested. Regular feedback would accelerate this -work. - -### Apache - -[Apache] has no module that supports this kind of authentication method. It's not certain this would even be possible, -however if anyone did something like this in the past we'd be interested in a contribution. - -### IIS - -Microsoft [IIS] not currently supported since no auth module exists for this purpose out-of-the-box or from any known -third party. It's likely possible but unlikely to be highly used so there is little to be gained by supporting this proxy. - -[NGINX]: https://www.nginx.com/ -[Traefik]: https://traefik.io/ -[HAProxy]: https://www.haproxy.com/ -[Envoy]: https://www.envoyproxy.io/ -[Caddy]: https://caddyserver.com/ -[Apache]: https://httpd.apache.org/ -[IIS]: https://www.iis.net/ -[Kubernetes]: https://kubernetes.io/ -[Ingress Controller]: https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/
\ No newline at end of file diff --git a/docs/i18n/en.toml b/docs/i18n/en.toml new file mode 100644 index 000000000..cb52685f7 --- /dev/null +++ b/docs/i18n/en.toml @@ -0,0 +1,2 @@ +[get-started] +   other = "Get Started"
\ No newline at end of file diff --git a/docs/images/2FA-METHODS-noborder.png b/docs/images/2FA-METHODS-noborder.png Binary files differdeleted file mode 100644 index 24bf87070..000000000 --- a/docs/images/2FA-METHODS-noborder.png +++ /dev/null diff --git a/docs/images/RESET-PASSWORD-STEP1.png b/docs/images/RESET-PASSWORD-STEP1.png Binary files differdeleted file mode 100644 index 577c7d96a..000000000 --- a/docs/images/RESET-PASSWORD-STEP1.png +++ /dev/null diff --git a/docs/images/RESET-PASSWORD-STEP2.png b/docs/images/RESET-PASSWORD-STEP2.png Binary files differdeleted file mode 100644 index 3cd8f3cd1..000000000 --- a/docs/images/RESET-PASSWORD-STEP2.png +++ /dev/null diff --git a/docs/images/logos/digitalocean.svg b/docs/images/logos/digitalocean.svg deleted file mode 100644 index ff38d8f4d..000000000 --- a/docs/images/logos/digitalocean.svg +++ /dev/null @@ -1,3 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="192" height="64"> -        <image width="192" height="64" xlink:href="data:false;base64,iVBORw0KGgoAAAANSUhEUgAAAYAAAACACAYAAAACsL4LAAAACXBIWXMAAAsSAAALEgHS3X78AAAWHUlEQVR42u2de5BkZXXAp2dmSyALIiCWBSEiWfPY8AiSQNQiLwJlFGIwQdRQQJFUkWASRcQYtrx3nruLqQCCqIQSofjDwhKKh49o0DUVDIiCChYSHwgSVAICIq/t6e/m3O91v+92z+7M7P26e3p+v6pTt6dnpu/t213nnO+c850zNgaw2sgLI+ZxS2R8LFeT+piaTM6RFZNjmRq3566uCQAAEij8UPEbKRXw5CJ/v15kH1HSR4hheIM8PlvkApGPi3xMnrtCjl8QuUvka6LQPyvHK+3vPyzyHpFz5O+Ol+Oh8vt95bi7Vvjd5yoNz0Tt2sRQKIwCAEADXn7peRtPPyt6KeCNoqxPlOP5IteIfFvk2bHpotAyY2U2kDmReStztd+5v3f/nxfPiXxVzvEpOf6TXMObtGHIiz1qq4PqOutGCwAAlu3xT4hSnaj9fm+Rk0UhXyTH20R+opX4hVahz2ilXYqy0ukhC5FkPf/G/b95zfAcefGoyB0iV4mcIddy4CKrg1b0ngAAYAfefq5MiCdTrcC7PlCeK738q0X+T35W3oM3XnqpyLfbY8cr7uq4Eglfo2MNRXmOtj5nee4tIlP6b54W2SbyD3Z10Are30SUL8hYFQAAVArfPG718PZ/X+RDIg+ObbZe+LRX0AtaGTen8JdmEDJvENpWlDYC5Sphs/678rlbRP5O/vZlUYjI5QtYFQAAXr9/PBn8bg+Rt8sK4E5Rms+NbfVKv22VvorCM/Hjfkn93KFRUNoQzOrf/6/IpSKHda0IwvuAMQCANaX4MxvqqX63j8jfi3zPJ2ZNeGV7LSbfb2W/VIMQGgUTjnK5A/N8Gb46Jni/3QljAIA14PVXFT3G43+3yHe052y8fZOINcnZog/hnZShoo5+vEX/7nmRT4gcWVsRYAQAYNQVf+n1q4ngd38uyvEeX4JZhlAqpa9WkdLfWajIrGSmfBWRvEf1UTkeEtwLVgMAMGLKPwu8/ur5jSLXa29/1id0F2reczFC4t6XyxO4hPHPbNhrwobFxikdBYDRUfwuzFE9fqfIk1oBZl0196Pg9S81cdzWKwKTI7hNVgSHBSum8a7VEwDA8Ct/FffqKb1a8/jXRT6nFd6UVv7tPpVvDnPC2BjAOX0/ntU7jUOjGYbOAACG3vPPe4Z8zhIF94SOf2eNbtYalRXBQpAfKHsTHdhtBFgNAMCw0ivkkxfrRD7oe+uY8sgC6WkITH7AGIGfiNf/B34VVd83AAAwVJ5/paCc8j9A5ItBrH8hSPAqFP+iq4HtQWL8H4N7PB7dawCAgSv+LGyD7JX/q/WGrnm/g7dY4+GepUlV/bRQJYjVZV1GgH5CADCUnn9WHCePn9Je7NpN9DYVElqw5aIf7yqnxQAAwECVf+X5O6X0Nt+L34V8UP67niA2paKfl/u8Z5cRwBAAwMA9/1z9jQ5bxMofxd9MS4m2bSWxTX5eTzgIAIZB+U/ax2cGbZo7KP9EyWETDvpi9Vkodg0DQL+Uvwq7ebr2BcfpJmd4/v3YONa2RuDqwCBjBACgD55/NbzFVfv8nsjPUf59MwLhSuASGwJqsWMYAPoV+nEJyIPF+38oqFkfDuWfBWGTrKtPv2kxnenxjgt2V/JCbQ5wscjQmeEJB5Xvyxjdc6PPBAAgSegnDje8SJ77T9vaoT0ESlL1GAQftpwweYnpYMB7KDPBqMksGiS/0DUgfjjeZ8cOyynlT2urMr6vANC452/CDebxlbYqpT1ESdK2bzUxaxX7bKD08+IXenNaXnxT5GYxYDfJ8SY9vzcr7hX5rs5lzNi/nw2MQ+7bWLSHoGW1O3/bXtuDIr9SW53xvQWABnAbkKpdvn/dI+yjBujtL/iOmlusYszUA/LcZ0RmRN4s8iqRl4q8WGS9bbIWyp4ie8v/7aendeXFKSKzuuImUz+U13xev/a8D8EMdmUQ7hies5VBfi+GGsMIAEBz3r+r+MmLI0Sese2c+13uGSrbhahdggnf3C4yLfIGkb0aDH+Vs4pPENkk73mbH/o+7Y3BIHY7x/fChOI22c9qvGseAwDAspV/PMR9UivZuL+P6ouyy4KwS2abpc3biVqZHq34Wu3Zx9cvitBO2KokeF8qfo9Gwr81/x+/Zjm/+FCRC0S+q0MwbsRj1rUiUn3OB7ygq7LMdZIPAIAGvP9KmWwaiPKv98zfqn/+ochmkZfXvPXJRnrox3OMW/o1M7vprfqbF4mcpnfnzkSjLfs5yL7aH2BCQXfo63KhIFYBANCA8j866OXfSe7hZl3hno4NczxhwzyV4s+ct15OH/P5igbvhQqNQnWu6l6Vz50s8jUdGpqKKqNSG4HuUJCbKsYqAABWhO4vo0Ild2uP1s6pE5zmfDO+Euc6PVayuqbJKjzVRyXXqw+S+Xl3kfN1J9Q5f69UnxLlpnR12g+aP8SHwQAAVqDgXEnhWYHy74ciq3fB/LEYozOC6xsfeDfMePRlq2YIfiswmKpP1VL1XcLXBKsjVgEAsETFlkUtH9brePt08iZvqlZfr6wCvVWu5ZBAmbUG4vXvKDyURUnk0BDM6nDQlJ+DnNIIxCsNkxQ+1l7jOEYAAJbj/bsWz7n2wo0CU8mVv8svGM//0sDTn4xCL8NqOMN7Z+7fn8nzT9sEcbtPRsCtnG6ODCUJYQBYgjJzSvcgHX6Z6RruknIClqum+eeu6xlW5d/LCGSqFQzJKRvmPdTDCKROCpfHP/RhKgCAHSowI05x5bbkcnsipaV61LIv6NkCTomuxn734bVWK6lflcc/6IsRcANkTAjtRuv9EwYCgJ0ZAK9wDxB5zMav04QssprnbwzAW73Xv5r73PcemmOMwExfVgIuX/OcLuGth6YAAHooLOf9n2c9yIUkjc+yWotmM0D+fOutTgx1vH9lKwFnBI7ROYG08xOUb15nGvZdbO9rixUAACwe/jGKYjd5fJ/2VE3v/FShHxVsXtpiwz7jI6H8HVmUHHZG4KSglXMnaS7AnOdxkf1tKKrF0BgA6GUEnII61SqO1NUqLk796WDX6uiNN4zCQa6pnsoSt9WowmumIuicaIUHABB5/5Wnep0NHWxPWqpoYuEP+bYOrvHaKIYp6qsas5/h1j4YgQUTXlNf9gYgIxkMAFGowivfX7OJwzQrgCwI/5g4+Mm11cdoG9rQC8/VBp9oTxcKcu0hyh5Kv+3PjwEAgGAF4EIv59hWAim80nrTsivXnEKq2lC7kNd7bJO7FBvtlJ+Utlmf4zxreNbxpQcA6/1H4Z8v29BMp1FlFJZ8Trt2zuqlPhwy6t5/eK/D95zpltJft/sDOmlyLqptjfpNjIwEgMW8/w1+2lc6b9S1Kfhbe86JNbdBqbvk9i2BAWi65FYFm+ye0p+xWQWQDAaAsTAc8Q4/5jBNQrJt+wrdWQ0tWaMtCuKBM+vkntwe9FwqEuReXBjolCrsRjkoACuAql3BJ231TztZ2wcTXjrTnnv0E787vPdhLkCdGkwUS7H6ciuvy6NQFACsaQPgwj/7inzLKomFJMp/Wpcjfi9u7rbGvdCq9cZeIvckuv9mQ58xvt8eqY12ANBI+Oe1oiReqI18bHbTl1ld2HYPiu6UeX2HsJqvtd5u1gibPMAzcu9fiQEAANN3xyiDs4POn6mSkE+K8nmVPd84YYixehJ+o8iziRrwKb8SyIs3WYNDIhhgjRsAp4guq9X/NymuKdm19pw0Jeu1EjCPv5qkDDfOA8xHKw8AWMsKSJXDzP87geJR1pO18Wd1OopnEQOQ+X0B74u6sDZdhWUM8Q32vLSHBkABqb10q4CpBG2fq41fj+p++EbxsALoDgO5PQFHJVoBhM337hDZnRsPAKXS+c1g81eRKOxwmz0XfWh6fwYuD7C/rtSZiUpCm/sszOv+SAz9Bm46AJRK582JNoBVw15cv3/aES+2AgjzMZ9M1I214yuBysE0AACiDN4VhB2a7vzp6s9PIfyz089hnT2+P2FF1oI1yCdywwGgrMm/JOpF06TCyXzb5w1RqANqn4HuEup2Rp+WcCDPC2P/oo9v56YDQKlwrrFx+k6izUc/FXmJORcbwHbwObhE8OtEnk4wJ0BVJbkq44YDQOl9bkvUgsBNo/qKnGN3q9y434sbAJcIfoXII34mc5o9GTPccAAY0/3o5xMZAGNYrvfebUYHyiUYgPUi308SlnNdQfPiQ9xwADC7T+f8LuBOg7LdGpYP25UGK4AdrsRUGAb6RrJVmek3dAP5GAAoFfNdNixQ6LhzU1LGnC/Ux632PFQA7dgQ988A5MWnMAAAUCqbbdZj/5mdGtWUPG4NwXRlAAgB7fizUH0yAOp6DAAAlMrmUN0OOi+O1huEmpOjbUXLQVa5EQLCAADAUIUdRuk8q/2zyLwB+CYhIADoh+IZTyPKPW55BYch2Nln4eYz3J3EAGTeANxAWw4AgKFR/jY/kqlJUc73BzOCmy0Dndd7M67ihgMADI8BcCulA0QeTtKfyc8EUHPccACAoVD+RZgAPlJXZE2nbAVR5Nx0AIDhMQIu/v+XXbN8m2wG9wEdCjqTGw4AMCwrgMy2g86KTQnbQZsQUFaczE0HABgG5R/vAr46MABNJoA7viFcXhzLjQcAGA4j4BLA+4l8K6gASjES8kE/nxkAAAa+AnDe/+8mUP71TWB3ibyYGw8Aw6kQ49BIWtHnUoN9v9UK4L22XXO78eE8Vfz/Rn2uzCadAQCGzwAo00I6pYTGZnDKPxwI//Wg/l81PJ/ZrQC22nNN8mUDgOE1AqN2rt4rHev9qyO1kp7yCrvpFYB7fJo9L60gAGDIqBqi/YbIFSJXivybPTYh5Wt9TORSUbqvtMq3NYD36VYArv7/cjusJUX8381nflbk4IEaPgCAHXjGTiEerxOicwlks+6HUyra1wzUG66Sv2X7hwfMDOXGO4AqHVIyoaV7+YIBwCowAOqPbM16x1bFNDWq0iVYn9AzCwZhAEzrh9AAvNO2aHCbv5reAObmAFxkVh90ZgWA4V4B/HHQDbPJnjgdGw55Sg+uGYQBiBPQe+va/Okkzd+UrwDS1UXq9QNd8QAArFkDEJWe+pXOJt2iuXqvzXr/mX+/P66ms2EAAAAD0H8DECv/g0VBPx54/ypB5Y/rAHqtXX20CP8AwGLKqVWb6LWc6V/ju1xbP/IrABVu/LrWev/tJJU/cQL4dHtO6v8BoJeCamhH7K54mKNoAHqGfoq/shuzOgmUf1z9kxWP6EqjysDzXQeASEk5r/TlIr8jcrjIEcuUcjPTXqwAFltd+T0OB4k8Ukv8qiQGwBiZ6/q60gGAVWcA1tnjBVZBll7jY8uQR0WeFjkhMihr3QDUd/yaGPzng9BPKuVv3qsxMsfi/QPAzg1ApraM/WugPJYqpVI1Su0kDIAlC/IhmW/5cIkZzJ5kx2+l/MvX151F1V3yeLddDs0BwJpYAcyOXagVyXPL3GDl+s2/EQMwZlo9VMp/whqE82y7506gqFXDg1+q2n9tkNU7rOGZwAAAwE4MgJrTc2PL+bErazdw4po2AK7Sxz/2yv90e39Sxv2r3v/G0Nwv531J8jAXAGAAMABjccw/860eTtUrqqlkG77qpZ+u9fN8fE8V33MAwAA0agDyrvkC41X8X52rzzeV3PNXPvxjzlUm5V8WXR8AAAYggQGoh3xM2GfOVuGEXT5ThX3c69rYf/H+6HMg/g8AGIAGDUBe8/qray/3Utxkxzt2+hDzV7XY/3dE9vWfA8ofADAADRiAvDZK0rR2mAh+/0bd2981eKuqfFIp/7jtg4n9n2U/S9o+AAAGoBEDECv/VjRYvfS4M3W5fu2Zrv4+qZV/6P1vs9dG0hcAMAC7ZADqQ+qN1z8Z/H43kTNEHrIhn/r1plP+3auLtm7HEb4nwj8AgAFYhgGIk7quqmc8qqTJi911h828uFt73v31+hcZ+OITvxN+5jAAAAZgCQbAePctn9DNerROzotfFnmfVvxlvH02SvSm2d27s6ofE/e/I9jN3eILDQArMAArbgXRtgbgJK/IlzxPIJot4K7jOOtRNz0TeCGYCfwa/97dXINeBikvDhZ5q8gtIk9qpV81c+vUvPGij8rf1fyXn9VRhH4AYNcMQFZcOHax3bg0uwwplb+ZPHVCQ9fzOl1D7157tiGZsco700rzsB7n3VMPi8+Lt4xlalaOn9bdTjfb/5/S/9sZQLin18Yvl/g9t7Z64vsMAMtSuJP2WMa1v6Lr2PPiM0uSTB9LRfk5kctF3i1y/grlvSLvErlI5D/ktW9Z8nUs/VpvFvmSyBdErpLnrpbjv4vcI4+/L/KUVrJbRTb7XbxtH+bJ+hrq6RXzL89t4v5Z8YngM2xFO5IBAJZuBBooG8yLh/VKYGaFMu1XEj8Q2T/hez1c5zrc6mLOyqxX+ErP0x1cmGexLp9G+Zu4/90i+0WhHwCAZeMqXIwHaTzJ5YhTQJko7hnf9GwlMXqXSyh3sx7oldtyr2fx63RhkqNsKOgFG9JZqF2zGnCIZ/F6f3N/HhbZECl/PH8AGED4KOw580BQGbOyVsYztpVxaACau1anLF9tSyfbQ6Dcl9LkrbqnOn+h3OQ14v4AgAEYSQNQV/5myPvb7Gprgi8fAGAARs8AqGi2b+43m51jlH9Qsor3DwAYgJExACqK+deVf9jhE+UPABiAkTMA5l5M+d3GKH8AwACMrAEI9xWUpZ5mmMx23WwO5Q8AGICRNQBhyel2ew/LDWmvt9c7EQ2bBwDAAKx6A1Dfb+B2+N6vr9Ep//BeAwBgAFa9AQgVv0n2miZzNwY7fCcI+wAABmB0DEDs9WfFdlvfX96zTf5ao1JPpnsBAAZgNRsA1cPr79jruE+U/J9Uyp/2DgCAARgNA5B11fa3fQO8vPiIninsrq+6l3y3AAADsIoNgKoZAFPeqRO96ht68E392jIUPwBgAFazAQjbN3dqSd5H9PzevNjDKHw17uP9Of38AWA1kQUGICv+x/bTf97OFV6uPGf//16RA6xSbG7GbVoDoHokeF/QHv+8G92oPijHV0TXQ5UPAKxeA6BKcSuAX+iRkuVc4Q+sQMr/u1h7zY/Lax20SlYAYWK3Yz1+M3xez1dWT8rPV8hxQ3AdE8T6AWBUQkBuNfAX8vgs3b5gZXK6+X91sg+RNKkgmzUA8QaucgfvVDBhLC9+KjIj72VjsFpq0dIBAEYzFNS4cWm4/n1lBkDVhrO4Y8ePjJzzoyyfkWv+LzmeLbIPHj8ArJ0VQK4m9YD5ZqR5L3lpBkBFMf0qidv2ydxpW8K52T7Oi9tFZkWOiY2iGqePDwDAcBirygDM+26bbg7wgih7o+jL3bmZTkqbWL7z8Od8Hf/PRb4kcp7I0SJ7BudoicIfjw0j1T0AAMNiAI7SCdop68FPW+U+Z736rTaBa7z7x0TuFLlBPPrNcjxJZO8erz1JVQ8AwPAbgI0iP7LlpvdZ+azI9SKX6Z48JiF9vHjzh8txfddrlTkPk9Q1u3ezonoeAACGzgBUhqBU6nnxS/a4PkrU9v7fCePlK7x8WPX8P1QliJAPyXNCAAAAAElFTkSuQmCC"/> -      </svg>
\ No newline at end of file diff --git a/docs/images/plus.png b/docs/images/plus.png Binary files differdeleted file mode 100644 index 88f0a1fdd..000000000 --- a/docs/images/plus.png +++ /dev/null diff --git a/docs/images/user.svg b/docs/images/user.svg deleted file mode 100644 index db78e7d94..000000000 --- a/docs/images/user.svg +++ /dev/null @@ -1,51 +0,0 @@ -<?xml version="1.0" encoding="iso-8859-1"?>
 -<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
 -<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
 -	 viewBox="0 0 55 55" style="enable-background:new 0 0 55 55;" xml:space="preserve">
 -<path d="M55,27.5C55,12.337,42.663,0,27.5,0S0,12.337,0,27.5c0,8.009,3.444,15.228,8.926,20.258l-0.026,0.023l0.892,0.752
 -	c0.058,0.049,0.121,0.089,0.179,0.137c0.474,0.393,0.965,0.766,1.465,1.127c0.162,0.117,0.324,0.234,0.489,0.348
 -	c0.534,0.368,1.082,0.717,1.642,1.048c0.122,0.072,0.245,0.142,0.368,0.212c0.613,0.349,1.239,0.678,1.88,0.98
 -	c0.047,0.022,0.095,0.042,0.142,0.064c2.089,0.971,4.319,1.684,6.651,2.105c0.061,0.011,0.122,0.022,0.184,0.033
 -	c0.724,0.125,1.456,0.225,2.197,0.292c0.09,0.008,0.18,0.013,0.271,0.021C25.998,54.961,26.744,55,27.5,55
 -	c0.749,0,1.488-0.039,2.222-0.098c0.093-0.008,0.186-0.013,0.279-0.021c0.735-0.067,1.461-0.164,2.178-0.287
 -	c0.062-0.011,0.125-0.022,0.187-0.034c2.297-0.412,4.495-1.109,6.557-2.055c0.076-0.035,0.153-0.068,0.229-0.104
 -	c0.617-0.29,1.22-0.603,1.811-0.936c0.147-0.083,0.293-0.167,0.439-0.253c0.538-0.317,1.067-0.648,1.581-1
 -	c0.185-0.126,0.366-0.259,0.549-0.391c0.439-0.316,0.87-0.642,1.289-0.983c0.093-0.075,0.193-0.14,0.284-0.217l0.915-0.764
 -	l-0.027-0.023C51.523,42.802,55,35.55,55,27.5z M2,27.5C2,13.439,13.439,2,27.5,2S53,13.439,53,27.5
 -	c0,7.577-3.325,14.389-8.589,19.063c-0.294-0.203-0.59-0.385-0.893-0.537l-8.467-4.233c-0.76-0.38-1.232-1.144-1.232-1.993v-2.957
 -	c0.196-0.242,0.403-0.516,0.617-0.817c1.096-1.548,1.975-3.27,2.616-5.123c1.267-0.602,2.085-1.864,2.085-3.289v-3.545
 -	c0-0.867-0.318-1.708-0.887-2.369v-4.667c0.052-0.52,0.236-3.448-1.883-5.864C34.524,9.065,31.541,8,27.5,8
 -	s-7.024,1.065-8.867,3.168c-2.119,2.416-1.935,5.346-1.883,5.864v4.667c-0.568,0.661-0.887,1.502-0.887,2.369v3.545
 -	c0,1.101,0.494,2.128,1.34,2.821c0.81,3.173,2.477,5.575,3.093,6.389v2.894c0,0.816-0.445,1.566-1.162,1.958l-7.907,4.313
 -	c-0.252,0.137-0.502,0.297-0.752,0.476C5.276,41.792,2,35.022,2,27.5z"/>
 -<g>
 -</g>
 -<g>
 -</g>
 -<g>
 -</g>
 -<g>
 -</g>
 -<g>
 -</g>
 -<g>
 -</g>
 -<g>
 -</g>
 -<g>
 -</g>
 -<g>
 -</g>
 -<g>
 -</g>
 -<g>
 -</g>
 -<g>
 -</g>
 -<g>
 -</g>
 -<g>
 -</g>
 -<g>
 -</g>
 -</svg>
 diff --git a/docs/index.md b/docs/index.md deleted file mode 100644 index 759d141c1..000000000 --- a/docs/index.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -layout: default -title: Home -nav_order: 1 -has_children: true ---- - -# Home - -*It has never been so easy to secure your applications with Single Sign-On -and Two-Factor.* - - -With **Authelia** you can login once and get access to all your web apps -safely from the Web thanks to two-factor authentication. - -<p align="center"> -  <img src="./images/1FA.png" width="400" /> -</p> - -**Authelia** is an open source authentication and authorization server -protecting modern web applications by collaborating with reverse proxies -such as NGINX, Traefik and HAProxy. Consequently, no code is required to -protect your apps. - -<p align="center" style="margin:50px"> -  <img src="./images/archi.png"/> -</p> - -Multiple 2-factor methods are available for satisfying every users. - -* Time-based One-Time passwords with compatible authenticator applications. -* Security Keys that support [FIDO2] [Webauthn] with devices like a [YubiKey]. -* Push notifications on your mobile using [Duo]. - -**Authelia** is available as Docker images, static binaries and AUR packages -so that you can test it in minutes. Let's begin with the -[Getting Started](./getting-started.md). - - -## However, Authelia... - -* [OpenID Connect](./configuration/identity-providers/oidc.md) is still in preview. -* is not a SAML provider yet. -* does not support authentication against an OAuth or OpenID Connect provider yet. -* does not support authentication against a SAML provider yet. -* does not support using hardware devices as single factor. -* does not provide a PAM module yet. - - -[Duo]: https://duo.com/ -[FIDO2]: https://www.yubico.com/authentication-standards/fido2/ -[Webauthn]: https://www.yubico.com/authentication-standards/webauthn/ -[YubiKey]: https://www.yubico.com/products/yubikey-5-overview/ diff --git a/docs/layouts/404.html b/docs/layouts/404.html new file mode 100644 index 000000000..bb3d98f23 --- /dev/null +++ b/docs/layouts/404.html @@ -0,0 +1,11 @@ +{{ define "main" }} +<div class="row justify-content-center"> +  <div class="col-md-12 col-lg-10 col-xl-8"> +    <article> +      <h1 class="text-center">Page not found :(</h1> +      <p class="text-center">The page you are looking for doesn't exist or has been moved.</p> +      <p class="text-center">If you followed a link to get to this page please report it if it was on this site, the official GitHub repository, or the logs on the latest version.</p> +    </article> +  </div> +</div> +{{ end }} diff --git a/docs/layouts/_default/_markup/render-heading.html b/docs/layouts/_default/_markup/render-heading.html new file mode 100644 index 000000000..8abeac6c8 --- /dev/null +++ b/docs/layouts/_default/_markup/render-heading.html @@ -0,0 +1 @@ +<h{{ .Level }} id="{{ .Anchor | safeURL }}">{{ .Text | safeHTML }} <a href="#{{ .Anchor | safeURL }}" class="anchor" aria-hidden="true">#</a></h{{ .Level }}> diff --git a/docs/layouts/_default/_markup/render-image.html b/docs/layouts/_default/_markup/render-image.html new file mode 100644 index 000000000..4a44740e4 --- /dev/null +++ b/docs/layouts/_default/_markup/render-image.html @@ -0,0 +1,36 @@ +{{ $image := "" -}} +{{ if (urls.Parse .Destination).IsAbs }} +  {{ $image = resources.GetRemote .Destination -}} +{{ else -}} +  {{ $image = .Page.Resources.GetMatch .Destination -}} +{{ end -}} +{{ with $image -}} +  {{ $lqip := $image.Resize site.Params.lqipWidth -}} + +  {{ $imgSrc := "" -}} +  {{ $imgSrcSet := slice -}} + +  {{ $widths := site.Params.landscapePhotoWidths -}} +  {{ if gt $image.Height $image.Width -}} +    {{ $widths = site.Params.portraitPhotoWidths -}} +  {{ end -}} + +  {{ range $widths -}} +    {{ $srcUrl := (printf "%dx" . | $image.Resize).Permalink -}} +    {{ if eq $imgSrc "" -}}{{ $imgSrc = $srcUrl -}}{{ end -}} +    {{ $imgSrcSet = $imgSrcSet | append (printf "%s %dw" $srcUrl .) -}} +  {{ end -}} +  {{ $imgSrcSet = (delimit $imgSrcSet ",") -}} + +  {{ if gt $image.Width site.Params.smallLimit -}} +    <figure class="figure"> +      <img class="figure-img img-fluid lazyload blur-up" data-sizes="auto" src="{{ $lqip.Permalink }}" data-srcset="{{ $imgSrcSet }}" width="{{ $image.Width }}" height="{{ $image.Height }}" alt="{{ $.Text }}"> +      <noscript><img class="figure-img img-fluid" sizes="100vw" srcset="{{ $imgSrcSet }}" src="{{ $image.Permalink }}" width="{{ $image.Width }}" height="{{ $image.Height }}" alt="{{ $.Text }}"></noscript> +      {{ with $.Title }}<figcaption class="figure-caption">{{ . | safeHTML }}</figcaption>{{ end -}} +    </figure> +  {{ else -}} +    <img class="img-fluid lazyload blur-up" src="{{ $lqip.Permalink }}" data-src="{{ $image.Permalink }}" width="{{ $image.Width }}" height="{{ $image.Height }}" alt="{{ $.Text }}"> +  {{ end -}} +{{ else -}} +  {{ erroridf "image-not-found" "Image not found" -}} +{{ end -}}
\ No newline at end of file diff --git a/docs/layouts/_default/_markup/render-link.html b/docs/layouts/_default/_markup/render-link.html new file mode 100644 index 000000000..279132679 --- /dev/null +++ b/docs/layouts/_default/_markup/render-link.html @@ -0,0 +1,11 @@ +{{ $link := .Destination -}} +{{ $isRemote := strings.HasPrefix $link "http" -}} +{{ if not $isRemote -}} +{{ $url := urls.Parse .Destination -}} +{{ if $url.Path -}} +{{ $fragment := "" -}} +{{ with $url.Fragment }}{{ $fragment = printf "#%s" . }}{{ end -}} +{{ with .Page.GetPage $url.Path }}{{ $link = printf "%s%s" .RelPermalink $fragment }}{{ end }}{{ end -}} +{{ end -}} +<a href="{{ $link | safeURL }}"{{ with .Title}} title="{{ . }}"{{ end }}{{ if $isRemote }} target="_blank"{{ end }}>{{ .Text | safeHTML }}</a> +{{- /* This comment removes trailing newlines. */ -}} diff --git a/docs/layouts/_default/baseof.html b/docs/layouts/_default/baseof.html new file mode 100644 index 000000000..8d2eb0c52 --- /dev/null +++ b/docs/layouts/_default/baseof.html @@ -0,0 +1,27 @@ +<!doctype html> +<html lang="{{ .Site.LanguageCode | default "en" }}"> +  {{ partial "head/head.html" . }} +  {{ if eq .Kind "home" -}} +    {{ .Scratch.Set "class" "home" -}} +  {{ else if eq .Kind "404" -}} +    {{ .Scratch.Set "class" "error404" -}} +  {{ else if eq .Kind "page" -}} +    {{ .Scratch.Set "class" .Type -}} +    {{ .Scratch.Add "class" " single" -}} +  {{ else -}} +    {{ .Scratch.Set "class" .Type -}} +    {{ .Scratch.Add "class" " list" -}} +  {{ end -}} +  <body class="{{ .Scratch.Get "class" }}"> +    {{ partial "header/header.html" . }} +    <div class="wrap container-{{ if .Site.Params.options.fullWidth }}fluid{{ else }}xxl{{ end }}" role="document"> +      <div class="content"> +        {{ block "main" . }}{{ end }} +      </div> +    </div> +    {{ block "sidebar-prefooter" . }}{{ end }} +    {{ block "sidebar-footer" . }}{{ end }} +    {{ partial "footer/footer.html" . }} +    {{ partial "footer/script-footer.html" . }} +  </body> +</html> diff --git a/docs/layouts/_default/index.js b/docs/layouts/_default/index.js new file mode 100644 index 000000000..2408016ec --- /dev/null +++ b/docs/layouts/_default/index.js @@ -0,0 +1,10 @@ +var docs = [ +{{ range $index, $page := (where .Site.Pages "Section" "configuration") -}} +  { +    id: {{ $index }}, +    title: "{{ .Title }}", +    description: "{{ .Params.description }}", +    href: "{{ .URL | relURL }}" +  }, +{{ end -}} +]; diff --git a/docs/layouts/_default/index.json b/docs/layouts/_default/index.json new file mode 100644 index 000000000..684287153 --- /dev/null +++ b/docs/layouts/_default/index.json @@ -0,0 +1,5 @@ +{{- $.Scratch.Add "index" slice -}} +{{- range .Site.RegularPages -}} +  {{- $.Scratch.Add "index" (dict "title" .Title "description" .Params.description "contents" .Plain "RelPermalink" .RelPermalink) -}} +{{- end -}} +{{- $.Scratch.Get "index" | jsonify -}}
\ No newline at end of file diff --git a/docs/layouts/_default/list.html b/docs/layouts/_default/list.html new file mode 100644 index 000000000..a43b6e8f0 --- /dev/null +++ b/docs/layouts/_default/list.html @@ -0,0 +1,13 @@ +{{ define "main" }} +<div class="row justify-content-center"> +  <div class="col-md-12 col-lg-10 col-xl-8"> +  {{ range .Paginator.Pages }} +    <article> +      <h2><a href="{{ .RelPermalink }}">{{ .Title }}</a></h2> +      {{ .Description }} +    </article> +  {{ end }} +  {{ template "_internal/pagination.html" . }} +  </div> +</div> +{{ end }} diff --git a/docs/layouts/_default/section.sitemap.xml b/docs/layouts/_default/section.sitemap.xml new file mode 100644 index 000000000..701951d63 --- /dev/null +++ b/docs/layouts/_default/section.sitemap.xml @@ -0,0 +1,46 @@ +{{ printf "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>" | safeHTML -}} +<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" +  xmlns:xhtml="http://www.w3.org/1999/xhtml"> +  {{ range $i, $e := .Data.Pages -}} +    {{ if ne .Params.sitemap_exclude true }} +    <url> +      <loc>{{ .Permalink }}</loc>{{ if not .Lastmod.IsZero }} +      <lastmod>{{ safeHTML ( .Lastmod.Format "2006-01-02T15:04:05-07:00" ) }}</lastmod>{{ end }}{{ with .Sitemap.ChangeFreq }} +      <changefreq>{{ . }}</changefreq>{{ end }}{{ if ge .Sitemap.Priority 0.0 }} +      <priority>{{ .Sitemap.Priority }}</priority>{{ end }}{{ if .IsTranslated }}{{ range .Translations }} +      <xhtml:link +                  rel="alternate" +                  hreflang="{{ .Lang }}" +                  href="{{ .Permalink }}" +                  />{{ end }} +      <xhtml:link +                  rel="alternate" +                  hreflang="{{ .Lang }}" +                  href="{{ .Permalink }}" +                  />{{ end }} +    </url> +    {{ end -}} +  {{ end -}} +  {{ range .Sections -}} +    {{ range $i, $e := .Data.Pages -}} +      {{ if ne .Params.sitemap_exclude true -}} +      <url> +        <loc>{{ .Permalink }}</loc>{{ if not .Lastmod.IsZero }} +        <lastmod>{{ safeHTML ( .Lastmod.Format "2006-01-02T15:04:05-07:00" ) }}</lastmod>{{ end }}{{ with .Sitemap.ChangeFreq }} +        <changefreq>{{ . }}</changefreq>{{ end }}{{ if ge .Sitemap.Priority 0.0 }} +        <priority>{{ .Sitemap.Priority }}</priority>{{ end }}{{ if .IsTranslated }}{{ range .Translations }} +        <xhtml:link +                    rel="alternate" +                    hreflang="{{ .Lang }}" +                    href="{{ .Permalink }}" +                    />{{ end }} +        <xhtml:link +                    rel="alternate" +                    hreflang="{{ .Lang }}" +                    href="{{ .Permalink }}" +                    />{{ end }} +      </url> +      {{ end -}} +    {{ end -}} +  {{ end -}} +</urlset>
\ No newline at end of file diff --git a/docs/layouts/_default/single.html b/docs/layouts/_default/single.html new file mode 100644 index 000000000..2f8fc9991 --- /dev/null +++ b/docs/layouts/_default/single.html @@ -0,0 +1,10 @@ +{{ define "main" }} +<div class="row justify-content-center"> +  <div class="col-md-12 col-lg-10 col-xl-8"> +    <article> +      <h1>{{ .Title }}</h1> +      {{ .Content }} +    </article> +  </div> +</div> +{{ end }} diff --git a/docs/layouts/_default/versions.html b/docs/layouts/_default/versions.html new file mode 100644 index 000000000..3101b825d --- /dev/null +++ b/docs/layouts/_default/versions.html @@ -0,0 +1,27 @@ +{{ define "main" }} +  <article> +    <h1>{{ .Title }}</h1> +    <p class="lead">{{ .Params.lead | safeHTML }}</p> +    {{ .Content }} +    <div class="row"> +      {{ range $release := sort (index $.Site.Data "docs-versions") "group" "desc" -}} +      <div class="col-md-8 col-lg-4 col-xl mb-4"> +        <h2>{{ $release.group }}</h2> +        <p>{{ $release.description }}</p> +        {{ $versions := sort $release.versions "v" "desc" -}} +        {{ range $i, $version := $versions -}} +          {{ $len := len $versions -}} +          {{ if (eq $i 0) }}<div class="list-group">{{ end }} +            <a class="list-group-item list-group-item-action py-2 text-primary{{ if (eq $version.v $.Site.Params.docsVersion) }} d-flex justify-content-between align-items-center{{ end }}" href="{{ $release.baseurl }}/{{ $version.v }}/"> +              {{ $version.v }} +              {{ if (eq $version.v $.Site.Params.docsVersion) -}} +              <span class="badge bg-primary">Latest</span> +              {{ end -}} +            </a> +          {{ if (eq (add $i 1) $len) }}</div>{{ end }} +        {{ end -}} +      </div> +      {{ end -}} +    </div> +  </article> +{{ end }} diff --git a/docs/layouts/blog/list.html b/docs/layouts/blog/list.html new file mode 100644 index 000000000..6267d4bce --- /dev/null +++ b/docs/layouts/blog/list.html @@ -0,0 +1,24 @@ +{{ define "main" }} +<div class="row justify-content-center"> +  <div class="col-md-12 col-lg-10 col-xl-8"> +    <article> +      <h1 class="text-center">{{ .Title }}</h1> +      <div class="text-center">{{ .Content }}</div> +			<div class="card-list"> +				{{ $paginator := .Paginate (.Data.Pages) -}} +				{{ range $paginator.Pages -}} +					<div class="card"> +						<div class="card-body"> +							<h2 class="h3"><a class="stretched-link text-body" href="{{ .RelPermalink }}">{{ .Params.title }}</a></h2> +							<p>{{ .Params.lead | safeHTML }}</p> +							{{ partial "main/blog-meta.html" . -}} +						</div> +					</div> +				{{ end -}} +				{{ $.Scratch.Set "paginator" true }} +				{{ template "_internal/pagination.html" . }} +			</div> +    </article> +  </div> +</div> +{{ end }} diff --git a/docs/layouts/blog/single.html b/docs/layouts/blog/single.html new file mode 100644 index 000000000..48fdb82a5 --- /dev/null +++ b/docs/layouts/blog/single.html @@ -0,0 +1,14 @@ +{{ define "main" }} +<div class="row justify-content-center"> +  <div class="col-md-12 col-lg-10 col-xl-8"> +    <article> +      <div class="blog-header"> +        <h1>{{ .Title }}</h1> +        {{ partial "main/blog-meta.html" . }} +      </div> +      <p class="lead">{{ .Params.lead | safeHTML }}</p> +      {{ .Content }} +    </article> +  </div> +</div> +{{ end }}
\ No newline at end of file diff --git a/docs/layouts/configuration/list.html b/docs/layouts/configuration/list.html new file mode 100644 index 000000000..41b36f8c7 --- /dev/null +++ b/docs/layouts/configuration/list.html @@ -0,0 +1,22 @@ +{{ define "main" }} +<div class="row justify-content-center"> +  <div class="col-md-12 col-lg-10 col-xl-8"> +    <article> +      <h1 class="text-center">{{ if eq .CurrentSection .FirstSection }}{{ .Section | humanize }}{{ else }}{{ .Title }}{{ end }}</h1> +      <div class="text-center">{{ .Content }}</div> +			<div class="card-list"> +				{{ $currentSection := .CurrentSection }} +				{{ range where .Site.RegularPages.ByWeight "Section" .Section }} +					{{ if in (.RelPermalink | string) $currentSection.RelPermalink }} +						<div class="card my-3"> +							<div class="card-body"> +								<a class="stretched-link" href="{{ .RelPermalink }}">{{ if (eq $currentSection.Title .Title) }}Introduction{{ else }}{{ .Params.title | title }}{{ end }} →</a> +							</div> +						</div> +					{{ end }} +				{{ end }} +			</div> +    </article> +  </div> +</div> +{{ end }} diff --git a/docs/layouts/configuration/single.html b/docs/layouts/configuration/single.html new file mode 100644 index 000000000..3c996056a --- /dev/null +++ b/docs/layouts/configuration/single.html @@ -0,0 +1,53 @@ +{{ define "main" }} +	<div class="row flex-xl-nowrap"> +		<div class="col-lg-5 col-xl-4 docs-sidebar d-none d-lg-block"> +			<nav {{ if eq .Site.Params.menu.section.collapsibleSidebar false }}id="sidebar-default" {{ end }}class="docs-links" aria-label="Main navigation"> +        {{ partial "sidebar/docs-menu.html" . }} +			</nav> +		</div> +		{{ if ne .Params.toc false -}} +		<nav class="docs-toc d-none d-xl-block col-xl-3" aria-label="Secondary navigation"> +      {{ partial "sidebar/docs-toc.html" . }} +		</nav> +		{{ end -}} +		{{ if .Params.toc -}} +		<main class="docs-content col-lg-11 col-xl{{ if eq .Site.Params.options.fullWidth false }}-9{{ end }}"> +		{{ else -}} +		<main class="docs-content col-lg-11 col-xl-9 mx-xl-auto"> +		{{ end -}} +			{{ if .Site.Params.options.breadCrumb -}} +				<!-- https://discourse.gohugo.io/t/breadcrumb-navigation-for-highly-nested-content/27359/6 --> +				<nav aria-label="breadcrumb"> +					<ol class="breadcrumb"> +						{{ partial "main/breadcrumb" . -}} +						<li class="breadcrumb-item active" aria-current="page">{{ if (eq .CurrentSection.Title .Title) }}Introduction{{ else }}{{ .Title }}{{ end }}</li> +					</ol> +				</nav> +			{{ end }} +			<h1>{{ .Title }}</h1> +			<p class="lead">{{ .Params.lead | safeHTML }}</p> +			{{ if ne .Params.toc false -}} +			<nav class="d-xl-none" aria-label="Quaternary navigation"> +        {{ partial "sidebar/docs-toc.html" . }} +			</nav> +			{{ end -}} +			{{ .Content }} +			<div class="page-footer-meta d-flex flex-column flex-md-row justify-content-between"> +				{{ if .Site.Params.lastMod -}} +					{{ partial "main/last-modified.html" . }} +				{{ end -}} +				{{ if .Site.Params.editPage -}} +					{{ partial "main/edit-page.html" . }} +				{{ end -}} +			</div> +      {{ partial "main/docs-navigation.html" . }} +			<!-- +			{{ if not .Site.Params.options.collapsibleSidebar -}} +				{{ partial "main/docs-navigation.html" . }} +			{{ else -}} +				<div class="my-n3"></div> +			{{ end -}} +			--> +		</main> +	</div> +{{ end }} diff --git a/docs/layouts/contributing/list.html b/docs/layouts/contributing/list.html new file mode 100644 index 000000000..41b36f8c7 --- /dev/null +++ b/docs/layouts/contributing/list.html @@ -0,0 +1,22 @@ +{{ define "main" }} +<div class="row justify-content-center"> +  <div class="col-md-12 col-lg-10 col-xl-8"> +    <article> +      <h1 class="text-center">{{ if eq .CurrentSection .FirstSection }}{{ .Section | humanize }}{{ else }}{{ .Title }}{{ end }}</h1> +      <div class="text-center">{{ .Content }}</div> +			<div class="card-list"> +				{{ $currentSection := .CurrentSection }} +				{{ range where .Site.RegularPages.ByWeight "Section" .Section }} +					{{ if in (.RelPermalink | string) $currentSection.RelPermalink }} +						<div class="card my-3"> +							<div class="card-body"> +								<a class="stretched-link" href="{{ .RelPermalink }}">{{ if (eq $currentSection.Title .Title) }}Introduction{{ else }}{{ .Params.title | title }}{{ end }} →</a> +							</div> +						</div> +					{{ end }} +				{{ end }} +			</div> +    </article> +  </div> +</div> +{{ end }} diff --git a/docs/layouts/contributing/single.html b/docs/layouts/contributing/single.html new file mode 100644 index 000000000..3c996056a --- /dev/null +++ b/docs/layouts/contributing/single.html @@ -0,0 +1,53 @@ +{{ define "main" }} +	<div class="row flex-xl-nowrap"> +		<div class="col-lg-5 col-xl-4 docs-sidebar d-none d-lg-block"> +			<nav {{ if eq .Site.Params.menu.section.collapsibleSidebar false }}id="sidebar-default" {{ end }}class="docs-links" aria-label="Main navigation"> +        {{ partial "sidebar/docs-menu.html" . }} +			</nav> +		</div> +		{{ if ne .Params.toc false -}} +		<nav class="docs-toc d-none d-xl-block col-xl-3" aria-label="Secondary navigation"> +      {{ partial "sidebar/docs-toc.html" . }} +		</nav> +		{{ end -}} +		{{ if .Params.toc -}} +		<main class="docs-content col-lg-11 col-xl{{ if eq .Site.Params.options.fullWidth false }}-9{{ end }}"> +		{{ else -}} +		<main class="docs-content col-lg-11 col-xl-9 mx-xl-auto"> +		{{ end -}} +			{{ if .Site.Params.options.breadCrumb -}} +				<!-- https://discourse.gohugo.io/t/breadcrumb-navigation-for-highly-nested-content/27359/6 --> +				<nav aria-label="breadcrumb"> +					<ol class="breadcrumb"> +						{{ partial "main/breadcrumb" . -}} +						<li class="breadcrumb-item active" aria-current="page">{{ if (eq .CurrentSection.Title .Title) }}Introduction{{ else }}{{ .Title }}{{ end }}</li> +					</ol> +				</nav> +			{{ end }} +			<h1>{{ .Title }}</h1> +			<p class="lead">{{ .Params.lead | safeHTML }}</p> +			{{ if ne .Params.toc false -}} +			<nav class="d-xl-none" aria-label="Quaternary navigation"> +        {{ partial "sidebar/docs-toc.html" . }} +			</nav> +			{{ end -}} +			{{ .Content }} +			<div class="page-footer-meta d-flex flex-column flex-md-row justify-content-between"> +				{{ if .Site.Params.lastMod -}} +					{{ partial "main/last-modified.html" . }} +				{{ end -}} +				{{ if .Site.Params.editPage -}} +					{{ partial "main/edit-page.html" . }} +				{{ end -}} +			</div> +      {{ partial "main/docs-navigation.html" . }} +			<!-- +			{{ if not .Site.Params.options.collapsibleSidebar -}} +				{{ partial "main/docs-navigation.html" . }} +			{{ else -}} +				<div class="my-n3"></div> +			{{ end -}} +			--> +		</main> +	</div> +{{ end }} diff --git a/docs/layouts/contributors/list.html b/docs/layouts/contributors/list.html new file mode 100644 index 000000000..adc53aad4 --- /dev/null +++ b/docs/layouts/contributors/list.html @@ -0,0 +1,23 @@ +{{ define "main" }} +<div class="row justify-content-center"> +  <div class="col-md-12 col-lg-10 col-xl-8"> +    <article> +      <h1 class="text-center">{{ .Title }}</h1> +      <div class="text-center">{{ .Content }}</div> +			<div class="card-list"> +				{{ range .Data.Pages -}} +					<div class="card"> +						<div class="card-body"> +							<h2 class="h3"><a class="stretched-link text-body" href="{{ .RelPermalink }}">{{ .Params.title }}</a></h2> +							{{ if eq .Section "blog" -}} +								<p>{{ .Params.lead | safeHTML }}</p> +								{{ partial "main/blog-meta.html" . -}} +							{{ end -}} +						</div> +					</div> +				{{ end -}} +			</div> +    </article> +  </div> +</div> +{{ end }}
\ No newline at end of file diff --git a/docs/layouts/contributors/single.html b/docs/layouts/contributors/single.html new file mode 100644 index 000000000..92c7de26d --- /dev/null +++ b/docs/layouts/contributors/single.html @@ -0,0 +1,45 @@ +{{ define "main" }} +<div class="row flex-xl-nowrap"> +  <div class="col-lg-5 col-xl-4 docs-sidebar d-none d-lg-block"> +    <nav class="docs-links" aria-label="Main navigation"> +      {{ partial "sidebar/docs-menu.html" . }} +    </nav> +  </div> +  {{ if ne .Params.toc false -}} +  <nav class="docs-toc d-none d-xl-block col-xl-3" aria-label="Secondary navigation"> +    {{ partial "sidebar/docs-toc.html" . }} +  </nav> +  {{ end -}} +  {{ if .Params.toc -}} +  <main class="docs-content col-lg-11 col-xl-9"> +    {{ else -}} +    <main class="docs-content col-lg-11 col-xl-9 mx-xl-auto"> +      {{ end -}} +      {{ if .Site.Params.options.breadCrumb -}} +      <!-- https://discourse.gohugo.io/t/breadcrumb-navigation-for-highly-nested-content/27359/6 --> +      <nav aria-label="breadcrumb"> +        <ol class="breadcrumb"> +          {{ partial "main/breadcrumb" . -}} +          <li class="breadcrumb-item active" aria-current="page">{{ .Title }}</li> +        </ol> +      </nav> +      {{ end }} +      <h1>{{ .Title }}</h1> +      <p class="lead">{{ .Params.lead | safeHTML }}</p> +      {{ if ne .Params.toc false -}} +      <nav class="d-xl-none" aria-label="Quaternary navigation"> +        {{ partial "sidebar/docs-toc.html" . }} +      </nav> +      {{ end -}} +      {{ .Content }} +      {{ if .Site.Params.editPage -}} +      {{ partial "main/edit-page.html" . }} +      {{ end -}} +      {{ if not .Site.Params.options.collapsibleSidebar -}} +      {{ partial "main/docs-navigation.html" . }} +      {{ else -}} +      <div class="my-n3"></div> +      {{ end -}} +    </main> +</div> +{{ end }} diff --git a/docs/layouts/index.headers b/docs/layouts/index.headers new file mode 100644 index 000000000..5232a8356 --- /dev/null +++ b/docs/layouts/index.headers @@ -0,0 +1,9 @@ +/* +  Strict-Transport-Security: max-age=31536000; includeSubDomains; preload +  X-Content-Type-Options: nosniff +  X-XSS-Protection: 1; mode=block +  Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' 'sha512-RGGByJUOP98hE4wFZM78RM/3MijWJs0Tm0DbfrFhCDCXKXfDx60fii+syp5iMs3UcNX/1H4zJNgmqSejfhHrYw==' 'sha512-+T2H7TEv2U6umnIOWYijvTIrzdCZUYhm/FZo4YYQzKAHf8NWs+38cn3t9fdz2rCm2HqHDkthZZXnY4EWPdWnMA==' 'sha512-okYuGnNmmUuCX64AD7FVra0445z43U8riOY3jZue+WZ2KeVOWLo17hE/wZXGUIJh9WBiSHZ2epTd36MMP6R66w==' 'sha512-bv9WRsSROhTW5djDurORNUCGITVeRfjDXkhqg4Ez/4vTY6FcaVBPy4MXpn4EGC3J3oZNcxpfQIScElDKlmiLhw==' 'sha512-RBYr6Ld4w1yVqaACrgrBLQfPgGhj/1jyacA74WxJ1KM6KVcSWymwrdDwb3HDcdpwiNJ5yssot1He0U9vXoQVlg==' 'sha256-aWZ3y/RxbBYKHXH0z8+8ljrHG1mSBvyzSfxSMjBSaXk=' 'sha256-vOgyKS2vkH4n5TxBJpeh9SgzrE6LVGsAeOAvEST6oCc='; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; object-src 'none'; frame-src 'none'; frame-ancestors 'none'; base-uri 'none'; require-trusted-types-for 'script' +  X-Frame-Options: SAMEORIGIN +  Referrer-Policy: strict-origin +  Feature-Policy: geolocation 'self' +  Access-Control-Allow-Origin: * diff --git a/docs/layouts/index.html b/docs/layouts/index.html new file mode 100644 index 000000000..2d9ac257c --- /dev/null +++ b/docs/layouts/index.html @@ -0,0 +1,120 @@ +{{ define "main" }} +<section class="section container-fluid mt-n3 pb-3"> +  <div class="row justify-content-center"> +    <div class="col-lg-12 text-center"> +      <h1 class="mt-0">{{ .Title }}</h1> +    </div> +    <div class="col-lg-9 col-xl-8 text-center"> +      <p class="lead">{{ .Params.lead | safeHTML }}</p> +      <a class="btn btn-primary btn-lg px-4 mb-2" href="/integration/prologue/get-started/" role="button">Get Started</a> +      <p class="meta">Open-source Apache 2.0 Licensed. <a href="https://github.com/authelia/authelia">GitHub v{{ $data := getJSON "https://raw.githubusercontent.com/authelia/authelia/master/web/package.json" }}{{ $data.version }}</a></p> +    </div> +  </div> +</section> +{{ end }} + +{{ define "sidebar-prefooter" }} +<div class="d-flex justify-content-start mb-3"> +  <div class="bg-dots"></div> +</div> + +  {{ if eq $.Site.Language.LanguageName "English" }} +  <section class="section section-sm"> +    <div class="container"> +      <div class="row justify-content-center text-center"> +        <div class="col-lg-5"> +          <h2 class="h4">Lightweight 🪶</h2> +          <p>With a compressed container size smaller than 20 megabytes and observed memory usage normally under 30 megabytes, it's one of the most lightweight solutions available.</p> +        </div> +        <div class="col-lg-5"> +          <h2 class="h4">Blazing Fast ⚡</h2> +          <p>Written in <a href="https://go.dev/" target="_blank">Go</a> and <a href="https://reactjs.org/" target="_blank">React</a>, authorization policies and many other backend tasks are completed in mere milliseconds and login portal loading times of 100 milliseconds makes it one of the fastest solutions available.</p> +        </div> +        <div class="col-lg-5"> +          <h2 class="h4">Efficient ♻</h2> +          <p>Processors can use a lot of electricity, but when idle usage is basically so low that you can't measure it, and active usage in a small business environment being under 1% you can rest easy (with the exclusion of password hashing).</p> +        </div> +      </div> +      <div class="row justify-content-center text-center"> +        <div class="col-lg-5"> +          <h2 class="h4">Security by Design 🔒</h2> +          <p>Not just another IAM portal, <a href="./overview/security/introduction/">security</a> is heavily considered as part of our design process.</p> +        </div> +        <div class="col-lg-5"> +          <h2 class="h4">Login Regulation 🛡️</h2> +          <p>Prevent brute force login attempts by only allowing a <a href="./overview/authorization/regulation/">certain number of logins</a> before the user is locked for a period.</p> +        </div> +        <div class="col-lg-5"> +          <h2 class="h4">Password Reset 📧</h2> +          <p>In-built support for users to reset their LDAP or internal passwords with email validation right from the web interface.</p> +        </div> +      </div> +      <div class="row justify-content-center text-center"> +        <div class="col-lg-5"> +          <h2 class="h4">Single Sign-On 🎟️</h2> +          <p>Allow your users the convenience of just being required to login once to a wide range of web applications.</p> +        </div> +        <div class="col-lg-5"> +          <h2 class="h4">Authorization Policies 👮</h2> +          <p>Control which users and groups have access to which specific resources or domains with incredibly <a href="./overview/authorization/access-control/">granular policy definitions</a>.</p> +        </div> +        <div class="col-lg-5"> +          <h2 class="h4">Identity Validation ✔</h2> +          <p>Users who have not configured a second-factor device are required to validate their identity via an email reducing the chance an attacker could exploit a lazy user.</p> +        </div> +      </div> +      <div class="row justify-content-center text-center"> +        <div class="col-lg-5"> +          <h2 class="h4">Scalability ⚙</h2> +          <p>Designed with high availability in mind, deployment options exist to easily allow multiple parallel containers on lifecycle management platforms like Kubernetes.</p> +        </div> +        <div class="col-lg-5"> +          <h2 class="h4">Multi-Factor Authentication 🗝️</h2> +          <p>Support for multiple second-factor methods including <a href="./overview/authentication/one-time-password/">One Time Passwords</a>, <a href="./overview/authentication/push-notification/">Mobile Push Notifications</a>, and <a href="./overview/authentication/security-key/">WebAuthn</a>.</p> +        </div> +        <div class="col-lg-5"> +          <h2 class="h4">Intuitive User Interface 💡</h2> +          <p>The login portal is super straight forward and the workflow is completely transparent to your users.</p> +        </div> +      </div> +    </div> +  </section> +  {{ end }} +{{ end }} + +{{ define "sidebar-footer" }} +<div class="d-flex justify-content-end mt-5"> +  <div class="bg-dots"></div> +</div> + +{{ partial "main/support.html" . -}} + +<section class="section section-sm mt-3 pt-3"> +  <div class="container"> +    <div class="row justify-content-center"> +      <div class="col-md-12 col-lg-10 col-xl-8"> +        <h2 class="h3 mt-3 text-center">Latest from the Authelia blog</h2> +        <div class="card-list"> +          {{ range first 3 (where .Site.RegularPages.ByDate.Reverse "Section" "blog")  -}} +          <div class="card"> +            <div class="card-body"> +              <h3><a class="stretched-link text-body" href="{{ .RelPermalink }}">{{ .Params.title }}</a></h3> +              <p>{{ .Params.lead | safeHTML }}</p> +              {{ partial "main/blog-meta.html" . -}} +            </div> +          </div> +          {{ end -}} +        </div> +      </div> +    </div> +  </div> +</section> + +<section class="section section-sm container-fluid"> +  <div class="row justify-content-center text-center"> +    <div class="col-lg-9"> +      {{- .Content -}} +    </div> +  </div> +</section> +{{ end }} diff --git a/docs/layouts/index.redirects b/docs/layouts/index.redirects new file mode 100644 index 000000000..9ae778ce3 --- /dev/null +++ b/docs/layouts/index.redirects @@ -0,0 +1,15 @@ +{{- range $p := .Site.Pages -}} +{{- range .Aliases }} +{{ . }} {{ $p.RelPermalink }} +{{- end }} +{{- end }} + +## Short Links +/l/charts               https://charts.authelia.com +/l/translate            https://translate.authelia.com +/l/github               https://github.com/authelia/authelia +/l/bug                  https://github.com/authelia/authelia/issues/new?assignees=&labels=Possible+Bug&template=bug_report.md +/l/fr                   https://github.com/authelia/authelia/issues/new?assignees=&labels=Feature+Request&template=feature_request.md + +## The following maps the old site to the new one. +/docs/						                                  / diff --git a/docs/layouts/integration/list.html b/docs/layouts/integration/list.html new file mode 100644 index 000000000..41b36f8c7 --- /dev/null +++ b/docs/layouts/integration/list.html @@ -0,0 +1,22 @@ +{{ define "main" }} +<div class="row justify-content-center"> +  <div class="col-md-12 col-lg-10 col-xl-8"> +    <article> +      <h1 class="text-center">{{ if eq .CurrentSection .FirstSection }}{{ .Section | humanize }}{{ else }}{{ .Title }}{{ end }}</h1> +      <div class="text-center">{{ .Content }}</div> +			<div class="card-list"> +				{{ $currentSection := .CurrentSection }} +				{{ range where .Site.RegularPages.ByWeight "Section" .Section }} +					{{ if in (.RelPermalink | string) $currentSection.RelPermalink }} +						<div class="card my-3"> +							<div class="card-body"> +								<a class="stretched-link" href="{{ .RelPermalink }}">{{ if (eq $currentSection.Title .Title) }}Introduction{{ else }}{{ .Params.title | title }}{{ end }} →</a> +							</div> +						</div> +					{{ end }} +				{{ end }} +			</div> +    </article> +  </div> +</div> +{{ end }} diff --git a/docs/layouts/integration/single.html b/docs/layouts/integration/single.html new file mode 100644 index 000000000..8229337c7 --- /dev/null +++ b/docs/layouts/integration/single.html @@ -0,0 +1,56 @@ +{{ define "main" }} +	<div class="row flex-xl-nowrap"> +		<div class="col-lg-5 col-xl-4 docs-sidebar d-none d-lg-block"> +			<nav {{ if eq .Site.Params.menu.section.collapsibleSidebar false }}id="sidebar-default" {{ end }}class="docs-links" aria-label="Main navigation"> +        {{ partial "sidebar/docs-menu.html" . }} +			</nav> +		</div> +		{{ if ne .Params.toc false -}} +		<nav class="docs-toc d-none d-xl-block col-xl-3" aria-label="Secondary navigation"> +      {{ partial "sidebar/docs-toc.html" . }} +		</nav> +		{{ end -}} +		{{ if .Params.toc -}} +		<main class="docs-content col-lg-11 col-xl{{ if eq .Site.Params.options.fullWidth false }}-9{{ end }}"> +		{{ else -}} +		<main class="docs-content col-lg-11 col-xl-9 mx-xl-auto"> +		{{ end -}} +			{{ if .Site.Params.options.breadCrumb -}} +				<!-- https://discourse.gohugo.io/t/breadcrumb-navigation-for-highly-nested-content/27359/6 --> +				<nav aria-label="breadcrumb"> +					<ol class="breadcrumb"> +						{{ partial "main/breadcrumb" . -}} +						<li class="breadcrumb-item active" aria-current="page">{{ if (eq .CurrentSection.Title .Title) }}Introduction{{ else }}{{ .Title }}{{ end }}</li> +					</ol> +				</nav> +			{{ end }} +			<h1>{{ .Title }}</h1> +			<p class="lead">{{ .Params.lead | safeHTML }}</p> +			{{ if ne .Params.toc false -}} +			<nav class="d-xl-none" aria-label="Quaternary navigation"> +        {{ partial "sidebar/docs-toc.html" . }} +			</nav> +			{{ end -}} +      {{ if eq .Params.community true -}} +      {{ partial "main/community.html" }} +      {{ end -}} +			{{ .Content }} +			<div class="page-footer-meta d-flex flex-column flex-md-row justify-content-between"> +				{{ if .Site.Params.lastMod -}} +					{{ partial "main/last-modified.html" . }} +				{{ end -}} +				{{ if .Site.Params.editPage -}} +					{{ partial "main/edit-page.html" . }} +				{{ end -}} +			</div> +      {{ partial "main/docs-navigation.html" . }} +			<!-- +			{{ if not .Site.Params.options.collapsibleSidebar -}} +				{{ partial "main/docs-navigation.html" . }} +			{{ else -}} +				<div class="my-n3"></div> +			{{ end -}} +			--> +		</main> +	</div> +{{ end }} diff --git a/docs/layouts/overview/list.html b/docs/layouts/overview/list.html new file mode 100644 index 000000000..41b36f8c7 --- /dev/null +++ b/docs/layouts/overview/list.html @@ -0,0 +1,22 @@ +{{ define "main" }} +<div class="row justify-content-center"> +  <div class="col-md-12 col-lg-10 col-xl-8"> +    <article> +      <h1 class="text-center">{{ if eq .CurrentSection .FirstSection }}{{ .Section | humanize }}{{ else }}{{ .Title }}{{ end }}</h1> +      <div class="text-center">{{ .Content }}</div> +			<div class="card-list"> +				{{ $currentSection := .CurrentSection }} +				{{ range where .Site.RegularPages.ByWeight "Section" .Section }} +					{{ if in (.RelPermalink | string) $currentSection.RelPermalink }} +						<div class="card my-3"> +							<div class="card-body"> +								<a class="stretched-link" href="{{ .RelPermalink }}">{{ if (eq $currentSection.Title .Title) }}Introduction{{ else }}{{ .Params.title | title }}{{ end }} →</a> +							</div> +						</div> +					{{ end }} +				{{ end }} +			</div> +    </article> +  </div> +</div> +{{ end }} diff --git a/docs/layouts/overview/single.html b/docs/layouts/overview/single.html new file mode 100644 index 000000000..92c7de26d --- /dev/null +++ b/docs/layouts/overview/single.html @@ -0,0 +1,45 @@ +{{ define "main" }} +<div class="row flex-xl-nowrap"> +  <div class="col-lg-5 col-xl-4 docs-sidebar d-none d-lg-block"> +    <nav class="docs-links" aria-label="Main navigation"> +      {{ partial "sidebar/docs-menu.html" . }} +    </nav> +  </div> +  {{ if ne .Params.toc false -}} +  <nav class="docs-toc d-none d-xl-block col-xl-3" aria-label="Secondary navigation"> +    {{ partial "sidebar/docs-toc.html" . }} +  </nav> +  {{ end -}} +  {{ if .Params.toc -}} +  <main class="docs-content col-lg-11 col-xl-9"> +    {{ else -}} +    <main class="docs-content col-lg-11 col-xl-9 mx-xl-auto"> +      {{ end -}} +      {{ if .Site.Params.options.breadCrumb -}} +      <!-- https://discourse.gohugo.io/t/breadcrumb-navigation-for-highly-nested-content/27359/6 --> +      <nav aria-label="breadcrumb"> +        <ol class="breadcrumb"> +          {{ partial "main/breadcrumb" . -}} +          <li class="breadcrumb-item active" aria-current="page">{{ .Title }}</li> +        </ol> +      </nav> +      {{ end }} +      <h1>{{ .Title }}</h1> +      <p class="lead">{{ .Params.lead | safeHTML }}</p> +      {{ if ne .Params.toc false -}} +      <nav class="d-xl-none" aria-label="Quaternary navigation"> +        {{ partial "sidebar/docs-toc.html" . }} +      </nav> +      {{ end -}} +      {{ .Content }} +      {{ if .Site.Params.editPage -}} +      {{ partial "main/edit-page.html" . }} +      {{ end -}} +      {{ if not .Site.Params.options.collapsibleSidebar -}} +      {{ partial "main/docs-navigation.html" . }} +      {{ else -}} +      <div class="my-n3"></div> +      {{ end -}} +    </main> +</div> +{{ end }} diff --git a/docs/layouts/partials/footer/footer.html b/docs/layouts/partials/footer/footer.html new file mode 100644 index 000000000..6f4546d32 --- /dev/null +++ b/docs/layouts/partials/footer/footer.html @@ -0,0 +1,18 @@ +<footer class="footer text-muted"> +  <div class="container-{{ if .Site.Params.options.fullWidth }}fluid{{ else }}xxl{{ end }}"> +    <div class="row"> +      <div class="col-lg-8 order-last order-lg-first"> +        <ul class="list-inline"> +          <li class="list-inline-item">{{ .Site.Params.footer | safeHTML }}. {{ (printf .Site.Params.copyRight (now.Format "2006")) | safeHTML }}.</li> +        </ul> +      </div> +      <div class="col-lg-8 order-first order-lg-last text-lg-end"> +        <ul class="list-inline"> +          {{ range .Site.Menus.footer -}} +            <li class="list-inline-item"><a href="{{ .URL | relURL }}">{{ .Name }}</a></li> +          {{ end -}} +        </ul> +      </div> +    </div> +  </div> +</footer> diff --git a/docs/layouts/partials/footer/script-footer.html b/docs/layouts/partials/footer/script-footer.html new file mode 100644 index 000000000..a68339d45 --- /dev/null +++ b/docs/layouts/partials/footer/script-footer.html @@ -0,0 +1,108 @@ +{{ $indexTemplate := resources.Get "js/index.js" -}} +{{ $index := $indexTemplate | resources.ExecuteAsTemplate "index.js" . -}} + +{{ $bs := resources.Get "js/bootstrap.js" -}} +{{ $bs := $bs | js.Build -}} + +{{ $highlight := resources.Get "js/highlight.js" -}} +{{ $highlight := $highlight | js.Build -}} + +{{ $katex := resources.Get "js/vendor/katex/dist/katex.js" -}} +{{ $katexAutoRender := resources.Get "js/vendor/katex/dist/contrib/auto-render.js" -}} + +{{ $mermaid := resources.Get "js/mermaid.js" | js.Build -}} + +{{ $app := resources.Get "js/app.js" -}} + +{{ $slice := slice $app -}} + +{{ if .Site.Params.options.lazySizes -}} +  {{ $lazySizes := resources.Get "js/lazysizes.js" -}} +  {{ $lazySizes := $lazySizes | js.Build -}} +  {{ $slice = $slice | append $lazySizes -}} +{{ end -}} + +{{ if .Site.Params.options.clipBoard -}} +  {{ $clipBoard := resources.Get "js/clipboard.js" -}} +  {{ $clipBoard := $clipBoard | js.Build -}} +  {{ $slice = $slice | append $clipBoard -}} +{{ end -}} + +{{ if .Site.Params.options.instantPage -}} +  {{ $instantPage := resources.Get "js/instant.page.js" -}} +  {{ $instantPage := $instantPage | js.Build -}} +  {{ $slice = $slice | append $instantPage -}} +{{ end -}} + +{{ if .Site.Params.options.flexSearch -}} +  {{ $flexSearch := resources.Get "js/vendor/flexsearch/dist/flexsearch.bundle.js" -}} +  {{ $slice = $slice | append $flexSearch -}} +{{ end -}} + +{{ if .Site.Params.options.darkMode -}} +  {{ $darkMode := resources.Get "js/darkmode.js" -}} +  {{ $darkMode := $darkMode | js.Build -}} +  {{ $slice = $slice | append $darkMode -}} +{{ end -}} + +{{ if and (.Site.Params.alert) (.Site.Params.alertDismissable) -}} +  {{ $alert := resources.Get "js/alert.js" -}} +  {{ $alert := $alert | js.Build -}} +  {{ $slice = $slice | append $alert -}} +{{ end -}} + +{{ if .Site.Params.options.kaTex -}} +  {{ $katexConfig := resources.Get "js/katex.js" -}} +  {{ $katexConfig := $katexConfig | js.Build -}} +  {{ $slice = $slice | append $katexConfig -}} +{{ end -}} + +{{ $scrollLock := resources.Get "js/scroll-lock.js" | js.Build -}} +{{ $slice = $slice | append $scrollLock -}} + +{{ $js := $slice | resources.Concat "main.js" -}} + +{{ if eq (hugo.Environment) "development" -}} +  {{ if .Site.Params.options.bootStrapJs -}} +    <script src="{{ $bs.RelPermalink }}" defer></script> +  {{ end -}} +  {{ if .Site.Params.options.highLight -}} +    <script src="{{ $highlight.RelPermalink }}" defer></script> +  {{ end -}} +  {{ if .Site.Params.options.kaTex -}} +    <script src="{{ $katex.RelPermalink }}" defer></script> +    <script src="{{ $katexAutoRender.RelPermalink }}" onload="renderMathInElement(document.body);" defer></script> +  {{ end -}} +  <script src="{{ $js.RelPermalink }}" defer></script> +  {{ with .Params.mermaid -}} +    <script src="{{ $mermaid.RelPermalink }}" defer></script> +  {{ end -}} +{{ if and (.Site.Params.options.flexSearch) (in .Site.Params.Sections.Search .Section) -}} +    <script src="{{ $index.RelPermalink }}" defer></script> +  {{ end -}} +{{ else -}} +  {{ $js := $js | minify | fingerprint "sha512" -}} +  {{ $index := $index | minify | fingerprint "sha512" -}} +  {{ $bs := $bs | minify | fingerprint "sha512" -}} +  {{ $highlight := $highlight | minify | fingerprint "sha512" -}} +  {{ $katex := $katex | minify | fingerprint "sha512" -}} +  {{ $katexAutoRender := $katexAutoRender | minify | fingerprint "sha512" -}} +  {{ $mermaid := $mermaid | minify | fingerprint "sha512" -}} +  {{ if .Site.Params.options.bootStrapJs -}} +    <script src="{{ $bs.RelPermalink }}" integrity="{{ $bs.Data.Integrity }}" crossorigin="anonymous" defer></script> +  {{ end -}} +  {{ if .Site.Params.options.highLight -}} +    <script src="{{ $highlight.RelPermalink }}" integrity="{{ $highlight.Data.Integrity }}" crossorigin="anonymous" defer></script> +  {{ end -}} +  {{ if .Site.Params.options.kaTex -}} +    <script src="{{ $katex.RelPermalink }}" integrity="{{ $katex.Data.Integrity }}" crossorigin="anonymous" defer></script> +    <script src="{{ $katexAutoRender.RelPermalink }}" integrity="{{ $katexAutoRender.Data.Integrity }}" crossorigin="anonymous" defer></script> +  {{ end -}} +  <script src="{{ $js.RelPermalink }}" integrity="{{ $js.Data.Integrity }}" crossorigin="anonymous" defer></script> +  {{ with .Params.mermaid -}} +    <script src="{{ $mermaid.RelPermalink }}" integrity="{{ $mermaid.Data.Integrity }}" crossorigin="anonymous" defer></script> +  {{ end -}} +{{ if and (.Site.Params.options.flexSearch) (in .Site.Params.Sections.Search .Section) -}} +    <script src="{{ $index.Permalink }}" integrity="{{ $index.Data.Integrity }}" crossorigin="anonymous" defer></script> +  {{ end -}} +{{ end -}} diff --git a/docs/layouts/partials/head/favicons.html b/docs/layouts/partials/head/favicons.html new file mode 100644 index 000000000..c034df1f2 --- /dev/null +++ b/docs/layouts/partials/head/favicons.html @@ -0,0 +1,5 @@ +<meta name="theme-color" content="{{ $.Site.Params.themeColor }}"> +<link rel="apple-touch-icon" sizes="180x180" href="{{ "apple-touch-icon.png" | absURL }}"> +<link rel="icon" type="image/png" sizes="32x32" href="{{ "favicon-32x32.png" | absURL }}"> +<link rel="icon" type="image/png" sizes="16x16" href="{{ "favicon-16x16.png" | absURL }}"> +<link rel="manifest" crossorigin="use-credentials" href="{{ "site.webmanifest" | absURL }}"> diff --git a/docs/layouts/partials/head/head.html b/docs/layouts/partials/head/head.html new file mode 100644 index 000000000..9c1ecb351 --- /dev/null +++ b/docs/layouts/partials/head/head.html @@ -0,0 +1,10 @@ +<head> +  <meta charset="utf-8"> +  <meta http-equiv="x-ua-compatible" content="ie=edge"> +  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> +  {{ block "head/resource-hints" . }}{{ partial "head/resource-hints.html" . }}{{ end }} +  {{ block "head/script-header" . }}{{ partial "head/script-header.html" . }}{{ end }} +  {{ block "head/stylesheet" . }}{{ partial "head/stylesheet.html" . }}{{ end }} +  {{ block "head/seo" . }}{{ partial "head/seo.html" . }}{{ end }} +  {{ block "head/favicons" . }}{{ partial "head/favicons.html" . }}{{ end }} +</head>
\ No newline at end of file diff --git a/docs/layouts/partials/head/opengraph.html b/docs/layouts/partials/head/opengraph.html new file mode 100644 index 000000000..6127e8269 --- /dev/null +++ b/docs/layouts/partials/head/opengraph.html @@ -0,0 +1,69 @@ +<meta property="og:locale" content="{{ .Site.Params.ogLocale }}"> +<meta property="og:type" content="{{ if .IsPage }}article{{ else }}website{{ end }}"> +<meta property="og:title" content="{{ .Title }}"> +<meta property="og:description" content="{{ with .Description }}{{ . }}{{ else }}{{if .IsPage}}{{ .Summary }}{{ else }}{{ with .Site.Params.description }}{{ . }}{{ end }}{{ end }}{{ end }}"> +{{ if $.Scratch.Get "paginator" -}} +  {{ $paginator := .Paginate (where .Site.RegularPages.ByDate.Reverse "Section" "blog" ) -}} +  <meta property="og:url" content="{{ .Paginator.URL | absURL }}"> +{{ else -}} +  <meta property="og:url" content="{{ .Permalink }}"> +{{ end -}} +{{ with .Site.Params.title -}} +  <meta property="og:site_name" content="{{ . }}"> +{{ end -}} + +{{ $iso8601 := "2006-01-02T15:04:05-07:00" -}} +{{ if .IsPage -}} +  {{ if not .PublishDate.IsZero -}} +    <meta property="article:published_time" {{ .PublishDate.Format $iso8601 | printf "content=%q" | safeHTMLAttr }}> +  {{ else if not .Date.IsZero -}} +    <meta property="article:published_time" {{ .Date.Format $iso8601 | printf "content=%q" | safeHTMLAttr }}> +  {{ end -}} +  {{ if not .Lastmod.IsZero -}} +    <meta property="article:modified_time" {{ .Lastmod.Format $iso8601 | printf "content=%q" | safeHTMLAttr }}> +  {{ end -}} +{{ else -}} +  {{ if not .Date.IsZero -}} +    <meta property="og:updated_time" {{ .Lastmod.Format $iso8601 | printf "content=%q" | safeHTMLAttr }}> +  {{ end -}} +{{ end -}} + +{{ if eq .Kind "home" -}} +  {{ .Scratch.Set "title" .Site.Params.titleHome -}} +{{ else -}} +  {{ .Scratch.Set "title" .Title -}} +{{ end -}} + +{{ with $.Params.images -}} +  {{ range first 6 . -}} +  <meta property="og:image" content="{{ $.Permalink }}{{ . }}"> +  {{ end -}} +{{ else -}} +  {{ $images := $.Resources.ByType "image" -}} +  {{ $featured := $images.GetMatch "*feature*" -}} +  {{ if not $featured -}} +    {{ $featured = $images.GetMatch "{*cover*,*thumbnail*}" }} +  {{ end -}} +  {{ with $featured -}} +    <meta property="og:image" content="{{ $featured.Permalink }}"/> +  {{ else -}} +    {{ with $.Site.Params.images -}} +      <meta property="og:image" content="{{ index . 0 | absURL }}"/> +      <meta property="og:image:alt" content="{{ $.Site.Params.title }}"> +    {{ end -}} +  {{ end -}} +{{ end -}} + +{{ with $.Site.Params.images -}} +  {{ $.Scratch.Set "primaryImage" (index . 0 | absURL) -}} +{{ end -}} + +{{ with .Params.audio -}} +  <meta property="og:audio" content="{{ . | absURL }}"> +{{ end -}} + +{{ with .Params.videos -}} +  {{ range . -}} +    <meta property="og:video" content="{{ . | absURL }}"> +  {{ end -}} +{{ end -}} diff --git a/docs/layouts/partials/head/resource-hints.html b/docs/layouts/partials/head/resource-hints.html new file mode 100644 index 000000000..73bccd946 --- /dev/null +++ b/docs/layouts/partials/head/resource-hints.html @@ -0,0 +1,7 @@ +<link rel="preload" as="font" href="{{ "fonts/vendor/jost/jost-v4-latin-regular.woff2" | absURL }}" type="font/woff2" crossorigin> +<link rel="preload" as="font" href="{{ "fonts/vendor/jost/jost-v4-latin-500.woff2" | absURL }}" type="font/woff2" crossorigin> +<link rel="preload" as="font" href="{{ "fonts/vendor/jost/jost-v4-latin-700.woff2" | absURL }}" type="font/woff2" crossorigin> +{{ if .Site.Params.options.kaTex -}} +  <link rel="preload" as="font" href="{{ "fonts/KaTeX_Main-Regular.woff2" | absURL }}" type="font/woff2" crossorigin> +  <link rel="preload" as="font" href="{{ "fonts/KaTeX_Math-Italic.woff2" | absURL }}" type="font/woff2" crossorigin> +{{ end -}}
\ No newline at end of file diff --git a/docs/layouts/partials/head/script-header.html b/docs/layouts/partials/head/script-header.html new file mode 100644 index 000000000..38e5b5b94 --- /dev/null +++ b/docs/layouts/partials/head/script-header.html @@ -0,0 +1,8 @@ +{{ if .Site.Params.options.darkMode -}} +  {{ $darkModeInit := resources.Get "js/darkmode-init.js" | js.Build | minify -}} +  <script>{{ $darkModeInit.Content | safeJS }}</script> +{{ end -}} +{{- if and (.Site.Params.alert) (.Site.Params.alertDismissable) -}} +  {{ $alertInit := resources.Get "js/alert-init.js" | js.Build | minify -}} +  <script>{{ $alertInit.Content | safeJS }}</script> +{{- end -}}
\ No newline at end of file diff --git a/docs/layouts/partials/head/seo.html b/docs/layouts/partials/head/seo.html new file mode 100644 index 000000000..ac31d7299 --- /dev/null +++ b/docs/layouts/partials/head/seo.html @@ -0,0 +1,48 @@ +{{ if eq .Kind "404" -}} +  <meta name="robots" content="noindex, follow"> +{{ else -}} +  {{ with .Params.robots -}} +    <meta name="robots" content="{{ . }}"> +  {{ else -}} +    <meta name="robots" content="index, follow"> +    <meta name="googlebot" content="index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1"> +    <meta name="bingbot" content="index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1"> +  {{ end -}} +{{ end -}} + +{{ if .IsHome -}} +  <title>{{ .Site.Params.title }} {{ .Site.Params.titleSeparator }} {{ .Site.Params.titleAddition }}</title> +{{ else -}} +  <title>{{ .Title }} {{ .Site.Params.titleSeparator }} {{ .Site.Params.title }}</title> +{{ end -}} + +{{ with .Description -}} +  <meta name="description" content="{{ . }}"> +{{ else -}} +  {{ with .Summary | plainify -}} +    <meta name="description" content="{{ . }}"> +  {{ else -}} +    <meta name="description" content="{{ .Site.Params.description }}"> +  {{ end -}} +{{ end -}} + +{{ if $.Scratch.Get "paginator" }} +  <link rel="canonical" href="{{ .Paginator.URL | absURL }}"> +  {{ if .Paginator.HasPrev -}} +    <link rel="prev" href="{{ .Paginator.Prev.URL | absURL }}"> +  {{ end -}} +  {{ if .Paginator.HasNext -}} +    <link rel="next" href="{{ .Paginator.Next.URL | absURL }}"> +  {{ end -}} +{{ else  -}} +  <link rel="canonical" href="{{ .Permalink }}"> +{{ end -}} + +{{ partial "head/opengraph.html" . }} +{{ partial "head/twitter_cards.html" . }} + +{{ range .AlternativeOutputFormats -}} +  <link rel="{{ .Rel }}" type="{{ .MediaType.Type }}" href="{{ .Permalink | safeURL }}"> +{{ end -}} + +{{ partial "head/structured-data.html" . }} diff --git a/docs/layouts/partials/head/structured-data.html b/docs/layouts/partials/head/structured-data.html new file mode 100644 index 000000000..1f153a359 --- /dev/null +++ b/docs/layouts/partials/head/structured-data.html @@ -0,0 +1,210 @@ +{{ $baseURL := "/" | absURL -}} + +{{ $dot := . -}} +{{ $dot.Scratch.Set "path" "" -}} +{{ $dot.Scratch.Set "breadcrumb" slice -}} + +{{ $url := replace .Permalink ( printf "%s" .Site.BaseURL) "" -}} +{{ $.Scratch.Add "path" .Site.BaseURL -}} + +{{ $.Scratch.Add "breadcrumb" (slice (dict "url" .Site.BaseURL "name" "home" "position" 1 )) -}} +  {{ range $index, $element := split $url "/" -}} +    {{ $dot.Scratch.Add "path" $element -}} +    {{ $.Scratch.Add "path" "/" -}} +    {{ if ne $element "" -}} +    {{ $.Scratch.Add "breadcrumb" (slice (dict "url" ($.Scratch.Get "path") "name" . "position" (add $index 2))) -}} +  {{ end -}} +{{ end -}} + +<script type="application/ld+json"> +{ +  "@context": "https://schema.org", +  "@graph": [ +    { +      {{ if eq .Site.Params.schemaType "Organization" -}} +        "@type": "Organization", +        "@id": {{ print $baseURL "#/schema/organization/1" }}, +      {{ else -}} +        "@type": "Person", +        "@id": {{ print $baseURL "#/schema/person/1" }}, +      {{ end -}} +      "name": "{{ .Site.Params.schemaName }}", +      "url": {{ print $baseURL }}, +      "sameAs": [ +        {{ with .Site.Params.schemaTwitter -}} +        {{ . }} +        {{ end -}} +        {{ with .Site.Params.schemaLinkedIn -}} +        , {{ . }} +        {{ end -}} +        {{ with .Site.Params.schemaGitHub -}} +        , {{ . }} +        {{ end -}} +      ], +      {{ if eq .Site.Params.schemaType "Organization" -}} +        "logo": { +          "@type": "ImageObject", +          "@id": {{ print $baseURL "#/schema/image/1"}}, +          "url": {{ print $baseURL .Site.Params.schemaLogo }}, +          "width": {{ .Site.Params.schemaLogoWidth }}, +          "height": {{ .Site.Params.schemaLogoHeight }}, +          "caption": "{{ .Site.Params.schemaName }}" +        }, +        "image": { +          "@id": {{ print $baseURL "#/schema/image/1" }} +        } +      {{ else -}} +        "image": { +          "@type": "ImageObject", +          "@id": {{ print $baseURL "#/schema/image/1"}}, +          "url": {{ print $baseURL .Site.Params.schemaImage }}, +          "width": {{ .Site.Params.schemaImageWidth }}, +          "height": {{ .Site.Params.schemaImageHeight }}, +          "caption": "{{ .Site.Params.schemaName }}" +        } +      {{ end -}} +    }, +    { +      "@type": "WebSite", +      "@id": {{ print $baseURL "#/schema/website/1" }}, +      "url": {{ print $baseURL }}, +      "name": "{{ .Site.Params.title }}", +      "description": "{{ .Site.Params.description }}", +      {{ if eq .Site.Params.schemaType "Organization" -}} +        "publisher": { +          "@id": {{ print $baseURL "#/schema/organization/1" }} +        } +      {{ else -}} +        "publisher": { +          "@id": {{ print $baseURL "#/schema/person/1" }} +        } +      {{ end -}} +    }, +    { +      {{ if and (ne .Kind "taxonomy") (ne .Kind "term") -}} +        "@type": "WebPage", +      {{ else -}} +        "@type": "CollectionPage", +      {{ end -}} +      "@id": {{ .Permalink }}, +      "url": {{ .Permalink }}, +      "name": "{{ .Title }}", +      "description": "{{ .Description }}", +      "isPartOf": { +        "@id": {{ print $baseURL "#/schema/website/1" }} +      }, +      {{ if eq .Site.Params.schemaType "Organization" -}} +        "about": { +          "@id": {{ print $baseURL "#/schema/organization/1" }} +        }, +      {{ else -}} +        "about": { +          "@id": {{ print $baseURL "#/schema/person/1" }} +        }, +      {{ end -}} +      "datePublished": "{{ .PublishDate.Format "2006-01-02T15:04:05CET" }}", +      "dateModified": "{{ .Lastmod.Format "2006-01-02T15:04:05CET" }}", +      "breadcrumb": { +        "@id": {{ print .Permalink "#/schema/breadcrumb/1" }} +      }, +      "primaryImageOfPage": { +        "@id": {{ print .Permalink "#/schema/image/2" }} +      }, +      "inLanguage": "{{ .Site.Params.schemaLocale }}", +      "potentialAction": [{ +        "@type": "ReadAction", "target": [{{ .Permalink }}] +      }] +    }, +    { +      "@type": "BreadcrumbList", +      "@id": {{ print .Permalink "#/schema/breadcrumb/1" }}, +      "name": "Breadcrumbs", +      "itemListElement": [{{ $list := $.Scratch.Get "breadcrumb" }}{{ $len := (len $list) }}{{ range $index, $element := $list }}{{ if ne .position 1 }},{{ end }}{ +        "@type": "ListItem", +        "position": {{ .position }}, +        "item": { +          {{ if ne (add $index 1) $len -}} +          "@type": "WebPage", +          "@id": {{ .url }}, +          "url": {{ .url }}, +          "name": "{{ .name | humanize | title }}" +          {{ else -}} +          "@id": {{ .url }} +          {{ end -}} +        } +        }{{ end }}] +    }, + +    {{ if and (eq .Kind "page") (or (eq .Section "blog") (eq .Section "docs") (eq .Section "tutorial") (eq .Section "showcase")) -}} +    { +      "@context": "https://schema.org", +      "@graph": [ +        { +          "@type": "Article", +          "@id": {{ print $baseURL "#/schema/article/1" }}, +          "headline": "{{ .Title }}", +          "description": "{{ .Description }}", +          "isPartOf": { +            "@id": {{ .Permalink }} +          }, +          "mainEntityOfPage": { +            "@id": {{ .Permalink }} +          }, +          "datePublished": "{{ .PublishDate.Format "2006-01-02T15:04:05CET" }}", +          "dateModified": "{{ .Lastmod.Format "2006-01-02T15:04:05CET" }}", +          "author": { +            "@id": {{ print $baseURL "#/schema/person/2" }} +          }, +          {{ if eq .Site.Params.schemaType "Organization" -}} +            "publisher": { +              "@id": {{ print $baseURL "#/schema/organization/1" }} +            }, +          {{ else -}} +            "publisher": { +              "@id": {{ print $baseURL "#/schema/person/1" }} +            }, +          {{ end -}} +          "image": { +            "@id": {{ print .Permalink "#/schema/image/2" }} +          } +        } +      ] +    }, +    { +      "@context": "https://schema.org", +      "@graph": [ +        { +          "@type": "Person", +          "@id": {{ print $baseURL "#/schema/person/2" }}, +          "name": {{ .Site.Params.schemaAuthor }}, +          "sameAs": [ +            {{ with .Site.Params.schemaAuthorTwitter -}} +            {{ . }} +            {{ end -}} +            {{ with .Site.Params.schemaAuthorLinkedIn -}} +            , {{ . }} +            {{ end -}} +            {{ with .Site.Params.schemaAuthorGitHub -}} +            , {{ . }} +            {{ end -}} +          ] +        } +      ] +    }, +    {{ end -}} +    { +      "@context": "https://schema.org", +      "@graph": [ +        { +          "@type": "ImageObject", +          "@id": {{ print .Permalink "#/schema/image/2" }}, +          "url": {{ $.Scratch.Get "primaryImage" }}, +          "contentUrl": {{ $.Scratch.Get "primaryImage" }}, +          "caption": "{{ .Title }}" +        } +      ] +    } + +  ] +} +</script>
\ No newline at end of file diff --git a/docs/layouts/partials/head/stylesheet.html b/docs/layouts/partials/head/stylesheet.html new file mode 100644 index 000000000..4dc25c01a --- /dev/null +++ b/docs/layouts/partials/head/stylesheet.html @@ -0,0 +1,11 @@ +{{ if eq (hugo.Environment) "development" -}} +  {{ $options := (dict "targetPath" "main.css" "enableSourceMap" true "includePaths" (slice "node_modules")) -}} +  {{ $css := resources.Get "scss/app.scss" | toCSS $options -}} +  <link rel="stylesheet" href="{{ $css.Permalink | relURL }}"> +{{ else -}} +  {{ $options := (dict "targetPath" "main.css" "outputStyle" "compressed" "includePaths" (slice "node_modules")) -}} +  {{ $css := resources.Get "scss/app.scss" | toCSS $options | postCSS (dict "config" "config/postcss.config.js") -}} +  {{ $secureCSS := $css | resources.Fingerprint "sha512" -}} +  <link rel="stylesheet" href="{{ $secureCSS.Permalink }}" integrity="{{ $secureCSS.Data.Integrity }}" crossorigin="anonymous"> +{{ end -}} +<noscript><style>img.lazyload { display: none; }</style></noscript>
\ No newline at end of file diff --git a/docs/layouts/partials/head/twitter_cards.html b/docs/layouts/partials/head/twitter_cards.html new file mode 100644 index 000000000..fdf581c48 --- /dev/null +++ b/docs/layouts/partials/head/twitter_cards.html @@ -0,0 +1,24 @@ +<meta name="twitter:card" content="summary_large_image"> +<meta name="twitter:site" content="{{ .Site.Params.twitterSite }}"> +<meta name="twitter:creator" content="{{ .Site.Params.twitterCreator }}"> +<meta name="twitter:title" content="{{ .Title }}"> +<meta name="twitter:description" content="{{ .Description }}"> +{{ with $.Params.images -}} +  <meta name="twitter:image" content="{{ $.Permalink }}{{ index . 0 }}"> +{{ else -}} +  {{ $images := $.Resources.ByType "image" -}} +  {{ $featured := $images.GetMatch "*feature*" -}} +  {{ if not $featured -}} +    {{ $featured = $images.GetMatch "{*cover*,*thumbnail*}" -}} +  {{ end -}} +  {{ with $featured -}} +    <meta name="twitter:image" content="{{ $featured.Permalink }}"> +  {{ else -}} +    {{ with $.Site.Params.images -}} +      <meta name="twitter:image" content="{{ index . 0 | absURL }}"> +    {{ else -}} +      <meta name="twitter:card" content="summary"> +    {{ end -}} +  {{ end -}} +{{ end -}} +<meta name="twitter:image:alt" content="{{ .Title }}">
\ No newline at end of file diff --git a/docs/layouts/partials/header/alert.html b/docs/layouts/partials/header/alert.html new file mode 100644 index 000000000..7944ae96b --- /dev/null +++ b/docs/layouts/partials/header/alert.html @@ -0,0 +1,10 @@ +{{ if .Site.Params.alertDismissable -}} +  <div id="announcement" data-id="global-alert-{{ md5 .Site.Params.alertText }}" class="alert alert-primary alert-dismissible fade show text-lg-center" role="alert"> +    {{ .Site.Params.alertText | safeHTML }} +    <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button> +  </div> +{{ else -}} +  <div class="alert alert-primary text-lg-center" role="alert"> +    {{ .Site.Params.alertText | safeHTML }} +  </div> +{{ end -}}
\ No newline at end of file diff --git a/docs/layouts/partials/header/header.html b/docs/layouts/partials/header/header.html new file mode 100644 index 000000000..0c4d30aec --- /dev/null +++ b/docs/layouts/partials/header/header.html @@ -0,0 +1,175 @@ +{{ if .Site.Params.alert -}} +  {{ partial "header/alert.html" . }} +{{ end -}} + +{{ if eq .Site.Params.options.flexSearch false -}} +<div class="sticky-lg-top"> +{{ end -}} + +<div class="header-bar"></div> + +<header class="navbar navbar-expand-md navbar-light doks-navbar"> +  <nav class="container-{{ if .Site.Params.options.fullWidth }}fluid{{ else }}xxl{{ end }} flex-wrap flex-md-nowrap" aria-label="Main navigation"> +    <a class="navbar-brand p-0 me-auto" href="{{ "/" | relLangURL }}" aria-label="{{ .Site.Params.Title }}"> +      {{ .Site.Params.Title }} +    </a> + +    <button class="btn btn-menu d-block d-md-none order-5" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasDoks" aria-controls="offcanvasDoks" aria-label="Open main menu"> +      <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-menu"><line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="18" x2="21" y2="18"></line></svg> +    </button> + +    <div class="offcanvas offcanvas-end border-0 py-md-1" tabindex="-1" id="offcanvasDoks" data-bs-backdrop="true" aria-labelledby="offcanvasDoksLabel"> +      <div class="header-bar d-md-none"></div> +      <div class="offcanvas-header d-md-none"> +        <h2 class="h5 offcanvas-title ps-2" id="offcanvasDoksLabel"><a class="text-dark" href="{{ "/" | relLangURL }}">{{ .Site.Params.Title }}</a></h2> +        <button type="button" class="btn-close text-reset me-2" data-bs-dismiss="offcanvas" aria-label="Close main menu"></button> +      </div> +      <div class="offcanvas-body px-4"> +        <h3 class="h6 text-uppercase mb-3 d-md-none">Main</h3> +        <ul class="nav flex-column flex-md-row ms-md-n3"> +          {{- $current := . -}} +          {{- $section := $current.Section -}} +          {{ range .Site.Menus.main -}} +            {{- $active := or ($current.IsMenuCurrent "main" .) ($current.HasMenuCurrent "main" .) -}} +            {{- $active = or $active (eq .Name $current.Title) -}} +            {{- $active = or $active (and (eq .Name ($section | humanize)) (eq $current.Section $section)) -}} +            {{- $active = or $active (and (eq .Name "Blog") (eq $current.Section "blog" "contributors")) -}} +            {{ if .HasChildren }} +              <li class="nav-item dropdown"> +                <a class="nav-link dropdown-toggle ps-0 py-1" href="#" id="navbarDropdownMenuLink" role="button" data-bs-toggle="dropdown" aria-expanded="false"> +                  {{ .Name }} +                  <span class="dropdown-caret"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-down"><polyline points="6 9 12 15 18 9"></polyline></svg></span> +                </a> +                <ul class="dropdown-menu dropdown-menu-main shadow rounded border-0" aria-labelledby="navbarDropdownMenuLink"> +                  {{ range .Children -}} +                  {{- $active = eq .Name $current.Title -}} +                    <li> +                      <a class="dropdown-item{{ if $active }} active{{ end }}" href="{{ .URL | relLangURL }}"{{ if $active }} aria-current="true"{{ end }}>{{ .Name }}</a> +                    </li> +                  {{ end -}} +                </ul> +              </li> +            {{ else }} +              <li class="nav-item"> +                <a class="nav-link ps-0 py-1{{ if $active }} active{{ end }}" href="{{ .URL | relLangURL }}">{{ .Name }}</a> +              </li> +            {{ end }} +          {{ end -}} +        </ul> +        <hr class="text-black-50 my-4 d-md-none"> +        <h3 class="h6 text-uppercase mb-3 d-md-none">Socials</h3> +        <ul class="nav flex-column flex-md-row ms-md-auto me-md-n5 pe-md-2"> +          {{ range .Site.Menus.social -}} +            <li class="nav-item"> +              <a class="nav-link ps-0 py-1" href="{{ .URL | relURL }}">{{ .Pre | safeHTML }}<small class="ms-2 d-md-none">{{ .Name | safeHTML }}</small></a> +            </li> +          {{ end -}} +        </ul> +      </div> +    </div> +    {{ if .Site.Params.options.darkMode -}} +    <button id="mode" class="btn btn-link order-md-1" type="button" aria-label="Toggle user interface mode"> +      <span class="toggle-dark"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-moon"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path></svg></span> +      <span class="toggle-light"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-sun"><circle cx="12" cy="12" r="5"></circle><line x1="12" y1="1" x2="12" y2="3"></line><line x1="12" y1="21" x2="12" y2="23"></line><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line><line x1="1" y1="12" x2="3" y2="12"></line><line x1="21" y1="12" x2="23" y2="12"></line><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line></svg></span> +    </button> +    {{ end -}} + +    {{ if eq .Site.Params.options.multilingualMode true -}} +    <div class="dropdown order-md-2"> +      <button class="btn btn-doks-light dropdown-toggle" id="doks-languages" data-bs-toggle="dropdown" aria-expanded="false" data-bs-display="static"> +        {{ .Site.Params.languageISO }} +        <span class="dropdown-caret"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-down"><polyline points="6 9 12 15 18 9"></polyline></svg></span> +      </button> +      <ul class="dropdown-menu dropdown-menu-end shadow rounded border-0" aria-labelledby="doks-languages"> + +        <li><a class="dropdown-item current" aria-current="true" href="{{ .RelPermalink }}">{{ .Site.Language.LanguageName }}</a></li> + +        <li><hr class="dropdown-divider"></li> + +      {{ if .IsTranslated -}} +        {{ range .Translations }} +          <li><a class="dropdown-item" rel="alternate" href="{{ .RelPermalink }}" hreflang="{{ .Lang }}" lang="{{ .Lang }}">{{ .Language.LanguageName }}</a></li> +        {{ end -}} +      {{ else -}} +        {{ range .Site.Languages -}} +          {{ if ne $.Site.Language.Lang .Lang }} +            <li><a class="dropdown-item" rel="alternate" href="{{ .Lang | relLangURL }}" hreflang="{{ .Lang }}" lang="{{ .Lang }}">{{ .LanguageName }}</a></li> +          {{ end -}} +        {{ end -}} +      {{ end -}} +        <!-- +        <li><hr class="dropdown-divider"></li> +        <li><a class="dropdown-item" href="/docs/contributing/how-to-contribute/">Help Translate</a></li> +        --> +      </ul> +    </div> +    {{ end -}} +  </nav> +</header> + +{{ if eq .Site.Params.options.flexSearch false }} +</div> +{{ end -}} + +{{ if in .Site.Params.Sections.Search .Section -}} +<nav class="doks-subnavbar py-2 sticky-lg-top{{ if eq .Site.Params.options.flexSearch false }} d-lg-none{{ end }}" aria-label="Secondary navigation"> +  <div class="container-{{ if .Site.Params.options.fullWidth }}fluid{{ else }}xxl{{ end }} d-flex align-items-md-center"> + +    {{ if .Site.Params.options.flexSearch -}} +    <form class="doks-search position-relative flex-grow-1 me-auto"> +      <input id="search" class="form-control is-search" type="search" placeholder="Search..." aria-label="Search..." autocomplete="off"> +      <div id="suggestions" class="shadow bg-white rounded d-none"></div> +    </form> +    {{ end -}} + +    {{ if eq .Site.Params.options.docsVersioning true -}} +    <div class="dropdown ms-3"> +      <button class="btn btn-doks-light dropdown-toggle" id="doks-versions" data-bs-toggle="dropdown" aria-expanded="false" data-bs-display="static" aria-label="Toggle version menu"> +        <span class="d-none d-lg-inline">Doks</span> v{{ .Site.Params.docsVersion }} +      </button> +      <ul class="dropdown-menu dropdown-menu-end shadow rounded border-0" aria-labelledby="doks-versions"> +        <li><a class="dropdown-item current" aria-current="true" href="/docs/{{ .Site.Params.docsVersion }}/prologue/introduction/">Latest ({{ .Site.Params.docsVersion }}.x)</a></li> +        <li><hr class="dropdown-divider"></li> +        <li><a class="dropdown-item" href="/docs/0.2/prologue/introduction/">v0.2.x</a></li> +        <li><a class="dropdown-item" href="/docs/0.1/prologue/introduction/">v0.1.x</a></li> +        <li><hr class="dropdown-divider"></li> +        <li><a class="dropdown-item" href="/docs/versions/">All versions</a></li> +      </ul> +    </div> +    {{ end -}} + +    <button class="btn doks-sidebar-toggle d-lg-none ms-3 order-3 collapsed{{ if eq .Site.Params.options.flexSearch false }} ms-auto{{ end }}" type="button" data-bs-toggle="collapse" data-bs-target="#doks-docs-nav" aria-controls="doks-docs-nav" aria-expanded="false" aria-label="Toggle documentation navigation"> +      <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" class="doks doks-expand" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><title>Expand</title><polyline points="7 13 12 18 17 13"></polyline><polyline points="7 6 12 11 17 6"></polyline></svg> +      <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" class="doks doks-collapse" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><title>Collapse</title><polyline points="17 11 12 6 7 11"></polyline><polyline points="17 18 12 13 7 18"></polyline></svg> +    </button> + +  </div> +</nav> + +<div class="container-{{ if .Site.Params.options.fullWidth }}fluid{{ else }}xxl{{ end }}"> +  <aside class="doks-sidebar"> +    <nav id="doks-docs-nav" class="collapse d-lg-none" aria-label="Tertiary navigation"> +      {{ partial "sidebar/docs-menu.html" . }} +    </nav> +  </aside> +</div> + +{{ else if ne .CurrentSection .FirstSection -}} +<nav class="doks-subnavbar py-2 sticky-lg-top d-lg-none" aria-label="Secondary navigation"> +  <div class="container-{{ if .Site.Params.options.fullWidth }}fluid{{ else }}xxl{{ end }} d-flex align-items-md-center"> +    <span class="navbar-text ms-0">{{ .Section | humanize }}</span> +    <button class="btn doks-sidebar-toggle d-lg-none ms-auto order-3 collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#doks-docs-nav" aria-controls="doks-docs-nav" aria-expanded="false" aria-label="Toggle documentation navigation"> +      <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" class="doks doks-expand" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><title>Expand</title><polyline points="7 13 12 18 17 13"></polyline><polyline points="7 6 12 11 17 6"></polyline></svg> +      <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" class="doks doks-collapse" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><title>Collapse</title><polyline points="17 11 12 6 7 11"></polyline><polyline points="17 18 12 13 7 18"></polyline></svg> +    </button> +  </div> +</nav> + +<div class="container-{{ if .Site.Params.options.fullWidth }}fluid{{ else }}xxl{{ end }}"> +  <aside class="doks-sidebar"> +    <nav id="doks-docs-nav" class="collapse d-lg-none" aria-label="Tertiary navigation"> +      {{ partial "sidebar/docs-menu.html" . }} +    </nav> +  </aside> +</div> +{{ end -}} diff --git a/docs/layouts/partials/main/blog-meta.html b/docs/layouts/partials/main/blog-meta.html new file mode 100644 index 000000000..d3cc3b7a3 --- /dev/null +++ b/docs/layouts/partials/main/blog-meta.html @@ -0,0 +1,2 @@ +{{ $last := sub (len .Params.contributors) 1 }} +<p><small>Posted {{ .PublishDate.Format "January 2, 2006" }} by {{ if .Params.contributors -}}{{ range $index, $contributor := .Params.contributors }}{{ if gt $index 0 }}{{ if eq $index $last }} and {{ else }}, {{ end }}{{ end }}<a class="stretched-link position-relative" href="{{ "/contributors/" | relURL }}{{ . | urlize }}/">{{ . }}</a>{{ end -}}{{ end -}} ‐ <strong>{{ .ReadingTime -}} min read</strong></small><p> diff --git a/docs/layouts/partials/main/breadcrumb.html b/docs/layouts/partials/main/breadcrumb.html new file mode 100644 index 000000000..666450ea9 --- /dev/null +++ b/docs/layouts/partials/main/breadcrumb.html @@ -0,0 +1,4 @@ +{{ with .Parent -}} +  {{ partial "main/breadcrumb.html" . -}} +  <li class="breadcrumb-item"><a href="{{ .RelPermalink }}">{{ if .IsHome }}Home{{ else if eq .CurrentSection .FirstSection }}{{ .Section | humanize }}{{ else }}{{ .Title }}{{ end }}</a></li> +{{ end -}} diff --git a/docs/layouts/partials/main/community.html b/docs/layouts/partials/main/community.html new file mode 100644 index 000000000..f6fb23b41 --- /dev/null +++ b/docs/layouts/partials/main/community.html @@ -0,0 +1,8 @@ +<div class="alert alert-danger d-flex" role="alert"> +  <div class="flex-shrink-1 alert-icon">⚠️</div> +  <div class="w-100"> +    This documentation is maintained by the community, it is not guaranteed to be complete or up-to-date. +    We always recommend users read the third-party documentation as part of the integration process to ensure the configuration matches their needs and as such we always link the documentation if available. +    If you find an error in this documentation please either make a GitHub Pull Request or start a GitHub Discussion. +  </div> +</div> diff --git a/docs/layouts/partials/main/date.html b/docs/layouts/partials/main/date.html new file mode 100644 index 000000000..4b41ddb3a --- /dev/null +++ b/docs/layouts/partials/main/date.html @@ -0,0 +1,6 @@ +<!-- +  Returns formatted date. +  Usage: partial "docs/date" (dict "Date" .Date "Format" .Site.Params.BookDateFormat) +--> +{{ $format := default "January 2, 2006" .Format -}} +{{ return (.Date.Format $format) -}}
\ No newline at end of file diff --git a/docs/layouts/partials/main/docs-navigation.html b/docs/layouts/partials/main/docs-navigation.html new file mode 100644 index 000000000..b620dc736 --- /dev/null +++ b/docs/layouts/partials/main/docs-navigation.html @@ -0,0 +1,25 @@ +{{ if or .Prev .Next -}} +	<div class="docs-navigation d-flex justify-content-between"> +	<!-- https://www.feliciano.tech/blog/custom-sort-hugo-single-pages/ --> +	{{ $pages := where site.RegularPages "Section" .Section -}} +  {{ $pages = ($pages.ByParam "Title").ByParam "Weight" -}} +	{{ with $pages.Next . -}} +		<a href="{{ .RelPermalink }}"> +			<div class="card my-1"> +				<div class="card-body py-2"> +					← {{ .Title }} +				</div> +			</div> +		</a> +	{{ end -}} +	{{ with $pages.Prev . -}} +		<a class="ms-auto" href="{{ .RelPermalink }}"> +			<div class="card my-1"> +				<div class="card-body py-2"> +					{{ .Title }} → +				</div> +			</div> +		</a> +	{{ end -}} +	</div> +{{ end -}} diff --git a/docs/layouts/partials/main/edit-page.html b/docs/layouts/partials/main/edit-page.html new file mode 100644 index 000000000..b69ed3622 --- /dev/null +++ b/docs/layouts/partials/main/edit-page.html @@ -0,0 +1,34 @@ +{{ $parts := slice .Site.Params.docsRepo }} + +{{ if (eq .Site.Params.repoHost "GitHub") }} +  {{ $parts = $parts | append "blob" .Site.Params.docsRepoBranch }} +{{ else if (eq .Site.Params.repoHost "Gitea") }} +  {{ $parts = $parts | append "_edit" .Site.Params.docsRepoBranch }} +{{ else if (eq .Site.Params.repoHost "GitLab") }} +  {{ $parts = $parts | append "-/blob" .Site.Params.docsRepoBranch }} +{{ else if (eq .Site.Params.repoHost "Bitbucket") }} +  {{ $parts = $parts | append "src" .Site.Params.docsRepoBranch }} +{{ else if (eq .Site.Params.repoHost "BitbucketServer") }} +  {{ $parts = $parts | append "browse" .Site.Params.docsRepoBranch }} +{{ end }} + +{{ if isset .Site.Params "docsreposubpath" }} +  {{ if not (eq .Site.Params.docsRepoSubPath "") }} +    {{ $parts = $parts | append .Site.Params.docsRepoSubPath }} +  {{ end }} +{{ end }} + +{{ $filePath := replace .File.Path "\\" "/" }} + +{{ $parts = $parts | append "content" .Lang $filePath }} + +{{ $url := delimit $parts "/" }} + +<div class="edit-page"> +  <a href="{{ $url }}"> +    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-edit-2"> +      <path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"></path> +    </svg> +    Edit this page on {{ .Site.Params.repoHost }} +  </a> +</div> diff --git a/docs/layouts/partials/main/last-modified.html b/docs/layouts/partials/main/last-modified.html new file mode 100644 index 000000000..ea782aed4 --- /dev/null +++ b/docs/layouts/partials/main/last-modified.html @@ -0,0 +1,10 @@ +{{ if and .GitInfo .Site.Params.docsRepo -}} +  {{- $date := partial "main/date" (dict "Date" .GitInfo.AuthorDate.Local "Format" .Site.Params.BookDateFormat) -}} +  {{- $commitPath := default "commit" .Site.Params.BookCommitPath -}} +  <div class="last-modified"> +    <a href="{{ .Site.Params.docsRepo }}/{{ $commitPath }}/{{ .GitInfo.Hash }}"> +      <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-calendar"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect><line x1="16" y1="2" x2="16" y2="6"></line><line x1="8" y1="2" x2="8" y2="6"></line><line x1="3" y1="10" x2="21" y2="10"></line></svg> +      Last modified on {{ $date }} +    </a> +  </div> +{{ end -}} diff --git a/docs/layouts/partials/main/support.html b/docs/layouts/partials/main/support.html new file mode 100644 index 000000000..86d2ff424 --- /dev/null +++ b/docs/layouts/partials/main/support.html @@ -0,0 +1,7 @@ +<section class="section section-open-collective mt-3 bg-light py-5"> +  <div class="container"> +    <h2 class="h3 mt-0 text-center">Support Authelia</h2> +    <p class="text-center">Help support the team developing Authelia by <a href="{{ "contributing/prologue/financial/" | relURL }}">becoming a financial contributor</a>.</p> +    <p class="text-center mb-0 mt-4"><a class="btn btn-primary px-4 mb-2" href="https://opencollective.com/authelia-sponsors" role="button">Contribute</a></p> +  </div> +</section> diff --git a/docs/layouts/partials/sidebar/auto-collapsible-menu.html b/docs/layouts/partials/sidebar/auto-collapsible-menu.html new file mode 100644 index 000000000..e3fa9ff5d --- /dev/null +++ b/docs/layouts/partials/sidebar/auto-collapsible-menu.html @@ -0,0 +1,57 @@ +<!-- Auto collapsible section menu --> +<ul class="list-unstyled collapsible-sidebar"> +  {{ $currentPage := . -}} +  {{ $section := $currentPage.Section -}} +  {{ range (where .Site.Sections "Section" "in" $section) }} +  {{ range .Sections.ByWeight }} +      {{ $active := in $currentPage.RelPermalink .RelPermalink }} +      <li class="mb-1"> +        <button class="btn btn-toggle align-items-center rounded collapsed" data-bs-toggle="collapse" data-bs-target="#section-{{ md5 .Title }}" aria-expanded="{{ if $active }}true{{ else }}false{{ end }}"> +          {{ .Title }} +        </button> +        <div class="collapse{{ if $active }} show{{ end }}" id="section-{{ md5 .Title }}"> +          <ul class="btn-toggle-nav list-unstyled fw-normal pb-1 small"> +            {{ range (.Pages.ByParam "Title").ByParam "Weight" }} +              {{ if .IsNode }} +                {{ $active := in $currentPage.RelPermalink .RelPermalink }} +                <li class="my-1 ms-3"> +                  <button class="btn btn-toggle align-items-center rounded collapsed" data-bs-toggle="collapse" data-bs-target="#section-{{ md5 .Title }}" aria-expanded="{{ if $active }}true{{ else }}false{{ end }}"> +                    {{ .Title }} +                  </button> +                  <div class="collapse{{ if $active }} show{{ end }}" id="section-{{ md5 .Title }}"> +                    <ul class="btn-toggle-nav list-unstyled fw-normal pb-1 small"> +                      {{ range (.Pages.ByParam "Title").ByParam "Weight" }} +                        {{ if .IsNode }} +                          {{ $active := in $currentPage.RelPermalink .RelPermalink }} +                          <li class="my-1 ms-3"> +                            <button class="btn btn-toggle align-items-center rounded collapsed" data-bs-toggle="collapse" data-bs-target="#section-{{ md5 .Title }}" aria-expanded="{{ if $active }}true{{ else }}false{{ end }}"> +                              {{ .Title }} +                            </button> +                            <div class="collapse{{ if $active }} show{{ end }}" id="section-{{ md5 .Title }}"> +                              <ul class="btn-toggle-nav list-unstyled fw-normal pb-1 small"> +                                {{ range (.Pages.ByParam "Title").ByParam "Weight" }} +                                  {{ $active := in $currentPage.RelPermalink .RelPermalink }} +                                  <li><a class="docs-link rounded{{ if $active }} active{{ end }}" href="{{ .Permalink }}">{{ .Title }}</a></li> +                                {{ end }} +                              </ul> +                            </div> +                          </li> +                        {{ else }} +                          {{ $active := in $currentPage.RelPermalink .RelPermalink }} +                          <li><a class="docs-link rounded{{ if $active }} active{{ end }}" href="{{ .Permalink }}">{{ .Title }}</a></li> +                        {{ end }} +                      {{ end }} +                    </ul> +                  </div> +                </li> +              {{ else }} +                {{ $active := in $currentPage.RelPermalink .RelPermalink }} +                <li><a class="docs-link rounded{{ if $active }} active{{ end }}" href="{{ .Permalink }}">{{ if (eq .CurrentSection.Title .Title) }}Introduction{{ else }}{{ .Title }}{{ end }}</a></li> +              {{ end }} +            {{ end }} +          </ul> +        </div> +      </li> +    {{ end }} +  {{ end }} +</ul> diff --git a/docs/layouts/partials/sidebar/auto-default-menu.html b/docs/layouts/partials/sidebar/auto-default-menu.html new file mode 100644 index 000000000..361d890ab --- /dev/null +++ b/docs/layouts/partials/sidebar/auto-default-menu.html @@ -0,0 +1,37 @@ +<!-- Auto default section menu --> +{{ $currentPage := . -}} +{{ $section := $currentPage.Section -}} +{{ range (where .Site.Sections "Section" "in" $section) }} +{{ range .Sections.ByWeight }} +    {{ $active := in $currentPage.RelPermalink .RelPermalink }} +    <h3 class="h6 text-uppercase mb-2">{{ .Title }}</h3> +    <ul class="list-unstyled"> +      {{ range .Pages }} +        {{ if .IsNode }} +          {{ $active := in $currentPage.RelPermalink .RelPermalink }} +          <h4 class="h6 text-uppercase ms-3 mt-3 mb-2">{{ .Title }}</h4> +          <ul class="list-unstyled ms-3"> +            {{ range (.Pages.ByParam "Title").ByParam "Weight" }} +              {{ if .IsNode }} +                {{ $active := in $currentPage.RelPermalink .RelPermalink }} +                <h5 class="h6 text-uppercase mt-2 mb-2">{{ .Title }}</h5> +                <ul class="list-unstyled ms-3"> +                  {{ range (.Pages.ByParam "Title").ByParam "Weight" }} +                    {{ $active := in $currentPage.RelPermalink .RelPermalink }} +                    <li><a class="docs-link{{ if $active }} active{{ end }}" href="{{ .Permalink }}">{{ .Name }}</a></li> +                  {{ end }} +                </ul> +              {{ else }} +                {{ $active := in $currentPage.RelPermalink .RelPermalink }} +                <li><a class="docs-link{{ if $active }} active{{ end }}" href="{{ .Permalink }}">{{ .Name }}</a></li> +              {{ end }} +            {{ end }} +          </ul> +        {{ else }} +          {{ $active := in $currentPage.RelPermalink .RelPermalink }} +          <li><a class="docs-link{{ if $active }} active{{ end }}" href="{{ .Permalink }}">{{ if (eq .CurrentSection.Title .Title) }}Introduction{{ else }}{{ .Name }}{{ end }}</a></li> +        {{ end }} +      {{ end }} +    </ul> +  {{ end }} +{{ end }} diff --git a/docs/layouts/partials/sidebar/docs-menu.html b/docs/layouts/partials/sidebar/docs-menu.html new file mode 100644 index 000000000..93093f763 --- /dev/null +++ b/docs/layouts/partials/sidebar/docs-menu.html @@ -0,0 +1,9 @@ +{{ if and .Site.Params.menu.section.auto .Site.Params.menu.section.collapsibleSidebar -}} +  {{ partial "sidebar/auto-collapsible-menu.html" . -}} +{{ else if and .Site.Params.menu.section.auto (not .Site.Params.menu.section.collapsibleSidebar) -}} +  {{ partial "sidebar/auto-default-menu.html" . -}} +{{ else if and (not .Site.Params.menu.section.auto) .Site.Params.menu.section.collapsibleSidebar -}} +  {{ partial "sidebar/manual-collapsible-menu.html" . -}} +{{ else if and (not .Site.Params.menu.section.auto) (not .Site.Params.menu.section.collapsibleSidebar) -}} +  {{ partial "sidebar/manual-default-menu.html" . -}} +{{ end -}} diff --git a/docs/layouts/partials/sidebar/docs-toc.html b/docs/layouts/partials/sidebar/docs-toc.html new file mode 100644 index 000000000..a0de898eb --- /dev/null +++ b/docs/layouts/partials/sidebar/docs-toc.html @@ -0,0 +1,6 @@ +{{ if and (ne .Params.toc false) (ne .TableOfContents "<nav id=\"TableOfContents\"></nav>") -}} +  <div class="page-links"> +    <h3>On this page</h3> +    {{ .TableOfContents }} +  </div> +{{ end -}} diff --git a/docs/layouts/partials/sidebar/manual-collapsible-menu.html b/docs/layouts/partials/sidebar/manual-collapsible-menu.html new file mode 100644 index 000000000..f8b512ea9 --- /dev/null +++ b/docs/layouts/partials/sidebar/manual-collapsible-menu.html @@ -0,0 +1,63 @@ +<!-- Manual collapsible section menu --> +<ul class="list-unstyled collapsible-sidebar"> +  {{ $currentPage := . -}} +  {{ $section := $currentPage.Section -}} +  {{ range (index .Site.Menus $section) -}} +    {{- $active := or ($currentPage.IsMenuCurrent $section .) ($currentPage.HasMenuCurrent $section .) -}} +    {{- $active = or $active (eq $currentPage.Section .Identifier) -}} +    <li class="mb-1"> +      <button class="btn btn-toggle align-items-center rounded collapsed" data-bs-toggle="collapse" data-bs-target="#section-{{ .Identifier }}" aria-expanded="{{ if $active }}true{{ else }}false{{ end }}"> +        {{ .Name }} +      </button> +      {{ if .HasChildren -}} +        <div class="collapse{{ if $active }} show{{ end }}" id="section-{{ .Identifier }}"> +          <ul class="btn-toggle-nav list-unstyled fw-normal pb-1 small"> +            {{ range .Children -}} +              {{ if .HasChildren -}} +                <li class="my-1 ms-3"> +                  <button class="btn btn-toggle align-items-center rounded collapsed" data-bs-toggle="collapse" data-bs-target="#section-{{ .Identifier }}" aria-expanded="{{ if $active }}true{{ else }}false{{ end }}"> +                    {{ .Name }} +                  </button> +                  {{ if .HasChildren -}} +                    <div class="collapse{{ if $active }} show{{ end }}" id="section-{{ .Identifier }}"> +                      <ul class="btn-toggle-nav list-unstyled fw-normal pb-1 small"> +                        {{ range .Children -}} +                          {{ if .HasChildren -}} +                            <li class="my-1 ms-3"> +                              <button class="btn btn-toggle align-items-center rounded collapsed" data-bs-toggle="collapse" data-bs-target="#section-{{ .Identifier }}" aria-expanded="{{ if $active }}true{{ else }}false{{ end }}"> +                                {{ .Name }} +                              </button> +                              {{ if .HasChildren -}} +                                <div class="collapse{{ if $active }} show{{ end }}" id="section-{{ .Identifier }}"> +                                  <ul class="btn-toggle-nav list-unstyled fw-normal pb-1 small"> +                                  {{ range .Children -}} +                                    {{- $active := or ($currentPage.IsMenuCurrent $section .) ($currentPage.HasMenuCurrent $section .) -}} +                                    {{- $active = or $active (eq $currentPage.Section .Identifier) -}} +                                    <li><a class="docs-link rounded{{ if $active }} active{{ end }}" href="{{ .URL | relURL }}">{{ .Title }}</a></li> +                                  {{ end -}} +                                  </ul> +                                </div> +                              {{ end -}} +                            </li> +                          {{ else -}} +                            {{- $active := or ($currentPage.IsMenuCurrent $section .) ($currentPage.HasMenuCurrent $section .) -}} +                            {{- $active = or $active (eq $currentPage.Section .Identifier) -}} +                            <li><a class="docs-link rounded{{ if $active }} active{{ end }}" href="{{ .URL | relURL }}">{{ .Title }}</a></li> +                          {{ end -}} +                        {{ end -}} +                      </ul> +                    </div> +                  {{ end -}} +                </li> +              {{ else -}} +                {{- $active := or ($currentPage.IsMenuCurrent $section .) ($currentPage.HasMenuCurrent $section .) -}} +                {{- $active = or $active (eq $currentPage.Section .Identifier) -}} +                <li><a class="docs-link rounded{{ if $active }} active{{ end }}" href="{{ .URL | relURL }}">{{ .Title }}</a></li> +              {{ end -}} +            {{ end -}} +          </ul> +        </div> +      {{ end -}} +    </li> +  {{ end -}} +</ul> diff --git a/docs/layouts/partials/sidebar/manual-default-menu.html b/docs/layouts/partials/sidebar/manual-default-menu.html new file mode 100644 index 000000000..6a2e2c2b0 --- /dev/null +++ b/docs/layouts/partials/sidebar/manual-default-menu.html @@ -0,0 +1,41 @@ +<!-- Manual default section menu --> +{{ $currentPage := . -}} +{{ $section := $currentPage.Section -}} +{{ range (index .Site.Menus $section) -}} +  <h3 class="h6 text-uppercase mb-2">{{ .Name }}</h3> +  {{ if .HasChildren -}} +    <ul class="list-unstyled"> +      {{ range .Children -}} +        {{ if .HasChildren -}} +          <h4 class="h6 text-uppercase ms-3 mt-3 mb-2">{{ .Name }}</h4> +          {{ if .HasChildren -}} +            <ul class="list-unstyled ms-3"> +              {{ range .Children -}} +                {{ if .HasChildren -}} +                  <h5 class="h6 text-uppercase mt-2 mb-2">{{ .Name }}</h5> +                  {{ if .HasChildren -}} +                    <ul class="list-unstyled ms-3"> +                      {{ range .Children -}} +                        {{- $active := or ($currentPage.IsMenuCurrent $section .) ($currentPage.HasMenuCurrent $section .) -}} +                        {{- $active = or $active (eq $currentPage.Section .Identifier) -}} +                        <li><a class="docs-link{{ if $active }} active{{ end }}" href="{{ .URL | relURL }}">{{ .Title }}</a></li> +                      {{ end -}} +                    </ul> +                  {{ end -}} +                {{ else -}} +                  {{- $active := or ($currentPage.IsMenuCurrent $section .) ($currentPage.HasMenuCurrent $section .) -}} +                  {{- $active = or $active (eq $currentPage.Section .Identifier) -}} +                  <li><a class="docs-link{{ if $active }} active{{ end }}" href="{{ .URL | relURL }}">{{ .Title }}</a></li> +                {{ end -}} +              {{ end -}} +            </ul> +          {{ end -}} +        {{ else -}} +          {{- $active := or ($currentPage.IsMenuCurrent $section .) ($currentPage.HasMenuCurrent $section .) -}} +          {{- $active = or $active (eq $currentPage.Section .Identifier) -}} +          <li><a class="docs-link{{ if $active }} active{{ end }}" href="{{ .URL | relURL }}">{{ .Title }}</a></li> +        {{ end -}} +      {{ end -}} +    </ul> +  {{ end -}} +{{ end -}} diff --git a/docs/layouts/reference/list.html b/docs/layouts/reference/list.html new file mode 100644 index 000000000..41b36f8c7 --- /dev/null +++ b/docs/layouts/reference/list.html @@ -0,0 +1,22 @@ +{{ define "main" }} +<div class="row justify-content-center"> +  <div class="col-md-12 col-lg-10 col-xl-8"> +    <article> +      <h1 class="text-center">{{ if eq .CurrentSection .FirstSection }}{{ .Section | humanize }}{{ else }}{{ .Title }}{{ end }}</h1> +      <div class="text-center">{{ .Content }}</div> +			<div class="card-list"> +				{{ $currentSection := .CurrentSection }} +				{{ range where .Site.RegularPages.ByWeight "Section" .Section }} +					{{ if in (.RelPermalink | string) $currentSection.RelPermalink }} +						<div class="card my-3"> +							<div class="card-body"> +								<a class="stretched-link" href="{{ .RelPermalink }}">{{ if (eq $currentSection.Title .Title) }}Introduction{{ else }}{{ .Params.title | title }}{{ end }} →</a> +							</div> +						</div> +					{{ end }} +				{{ end }} +			</div> +    </article> +  </div> +</div> +{{ end }} diff --git a/docs/layouts/reference/single.html b/docs/layouts/reference/single.html new file mode 100644 index 000000000..3c996056a --- /dev/null +++ b/docs/layouts/reference/single.html @@ -0,0 +1,53 @@ +{{ define "main" }} +	<div class="row flex-xl-nowrap"> +		<div class="col-lg-5 col-xl-4 docs-sidebar d-none d-lg-block"> +			<nav {{ if eq .Site.Params.menu.section.collapsibleSidebar false }}id="sidebar-default" {{ end }}class="docs-links" aria-label="Main navigation"> +        {{ partial "sidebar/docs-menu.html" . }} +			</nav> +		</div> +		{{ if ne .Params.toc false -}} +		<nav class="docs-toc d-none d-xl-block col-xl-3" aria-label="Secondary navigation"> +      {{ partial "sidebar/docs-toc.html" . }} +		</nav> +		{{ end -}} +		{{ if .Params.toc -}} +		<main class="docs-content col-lg-11 col-xl{{ if eq .Site.Params.options.fullWidth false }}-9{{ end }}"> +		{{ else -}} +		<main class="docs-content col-lg-11 col-xl-9 mx-xl-auto"> +		{{ end -}} +			{{ if .Site.Params.options.breadCrumb -}} +				<!-- https://discourse.gohugo.io/t/breadcrumb-navigation-for-highly-nested-content/27359/6 --> +				<nav aria-label="breadcrumb"> +					<ol class="breadcrumb"> +						{{ partial "main/breadcrumb" . -}} +						<li class="breadcrumb-item active" aria-current="page">{{ if (eq .CurrentSection.Title .Title) }}Introduction{{ else }}{{ .Title }}{{ end }}</li> +					</ol> +				</nav> +			{{ end }} +			<h1>{{ .Title }}</h1> +			<p class="lead">{{ .Params.lead | safeHTML }}</p> +			{{ if ne .Params.toc false -}} +			<nav class="d-xl-none" aria-label="Quaternary navigation"> +        {{ partial "sidebar/docs-toc.html" . }} +			</nav> +			{{ end -}} +			{{ .Content }} +			<div class="page-footer-meta d-flex flex-column flex-md-row justify-content-between"> +				{{ if .Site.Params.lastMod -}} +					{{ partial "main/last-modified.html" . }} +				{{ end -}} +				{{ if .Site.Params.editPage -}} +					{{ partial "main/edit-page.html" . }} +				{{ end -}} +			</div> +      {{ partial "main/docs-navigation.html" . }} +			<!-- +			{{ if not .Site.Params.options.collapsibleSidebar -}} +				{{ partial "main/docs-navigation.html" . }} +			{{ else -}} +				<div class="my-n3"></div> +			{{ end -}} +			--> +		</main> +	</div> +{{ end }} diff --git a/docs/layouts/roadmap/list.html b/docs/layouts/roadmap/list.html new file mode 100644 index 000000000..e4dd15937 --- /dev/null +++ b/docs/layouts/roadmap/list.html @@ -0,0 +1,26 @@ +{{ define "main" }} +<div class="row justify-content-center"> +  <div class="col-md-12 col-lg-10 col-xl-8"> +    <article> +      <h1 class="text-center">{{ if eq .CurrentSection .FirstSection }}{{ .Section | humanize }}{{ else }}{{ .Title }}{{ end }}</h1> +      <div class="text-center">{{ .Content }}</div> +			<div class="card-list"> +				{{ $currentSection := .CurrentSection }} +				{{ range where .Site.RegularPages.ByWeight "Section" .Section }} +					{{ if in (.RelPermalink | string) $currentSection.RelPermalink }} +						<div class="card my-3"> +							<div class="card-body"> +                {{ if (eq .Parent.Title "Complete") }} +                <a class="stretched-link" href="{{ .RelPermalink }}"><em>(Complete)</em> {{ if (eq $currentSection.Title .Title) }}Introduction{{ else }}{{ .Params.title | title }}{{ end }} →</a> +                {{ else }} +								<a class="stretched-link" href="{{ .RelPermalink }}">{{ if (eq $currentSection.Title .Title) }}Introduction{{ else }}{{ .Params.title | title }}{{ end }} →</a> +                {{ end }} +							</div> +						</div> +					{{ end }} +				{{ end }} +			</div> +    </article> +  </div> +</div> +{{ end }} diff --git a/docs/layouts/roadmap/single.html b/docs/layouts/roadmap/single.html new file mode 100644 index 000000000..3c996056a --- /dev/null +++ b/docs/layouts/roadmap/single.html @@ -0,0 +1,53 @@ +{{ define "main" }} +	<div class="row flex-xl-nowrap"> +		<div class="col-lg-5 col-xl-4 docs-sidebar d-none d-lg-block"> +			<nav {{ if eq .Site.Params.menu.section.collapsibleSidebar false }}id="sidebar-default" {{ end }}class="docs-links" aria-label="Main navigation"> +        {{ partial "sidebar/docs-menu.html" . }} +			</nav> +		</div> +		{{ if ne .Params.toc false -}} +		<nav class="docs-toc d-none d-xl-block col-xl-3" aria-label="Secondary navigation"> +      {{ partial "sidebar/docs-toc.html" . }} +		</nav> +		{{ end -}} +		{{ if .Params.toc -}} +		<main class="docs-content col-lg-11 col-xl{{ if eq .Site.Params.options.fullWidth false }}-9{{ end }}"> +		{{ else -}} +		<main class="docs-content col-lg-11 col-xl-9 mx-xl-auto"> +		{{ end -}} +			{{ if .Site.Params.options.breadCrumb -}} +				<!-- https://discourse.gohugo.io/t/breadcrumb-navigation-for-highly-nested-content/27359/6 --> +				<nav aria-label="breadcrumb"> +					<ol class="breadcrumb"> +						{{ partial "main/breadcrumb" . -}} +						<li class="breadcrumb-item active" aria-current="page">{{ if (eq .CurrentSection.Title .Title) }}Introduction{{ else }}{{ .Title }}{{ end }}</li> +					</ol> +				</nav> +			{{ end }} +			<h1>{{ .Title }}</h1> +			<p class="lead">{{ .Params.lead | safeHTML }}</p> +			{{ if ne .Params.toc false -}} +			<nav class="d-xl-none" aria-label="Quaternary navigation"> +        {{ partial "sidebar/docs-toc.html" . }} +			</nav> +			{{ end -}} +			{{ .Content }} +			<div class="page-footer-meta d-flex flex-column flex-md-row justify-content-between"> +				{{ if .Site.Params.lastMod -}} +					{{ partial "main/last-modified.html" . }} +				{{ end -}} +				{{ if .Site.Params.editPage -}} +					{{ partial "main/edit-page.html" . }} +				{{ end -}} +			</div> +      {{ partial "main/docs-navigation.html" . }} +			<!-- +			{{ if not .Site.Params.options.collapsibleSidebar -}} +				{{ partial "main/docs-navigation.html" . }} +			{{ else -}} +				<div class="my-n3"></div> +			{{ end -}} +			--> +		</main> +	</div> +{{ end }} diff --git a/docs/layouts/robots.txt b/docs/layouts/robots.txt new file mode 100644 index 000000000..3107a650a --- /dev/null +++ b/docs/layouts/robots.txt @@ -0,0 +1,7 @@ +User-agent: * +{{ if eq (hugo.Environment) "production" -}} +Allow: / +{{ else -}} +Disallow: / +{{ end }} +Sitemap: {{ "sitemap.xml" | absURL -}} diff --git a/docs/layouts/rss.xml b/docs/layouts/rss.xml new file mode 100644 index 000000000..80e2fa9a0 --- /dev/null +++ b/docs/layouts/rss.xml @@ -0,0 +1,27 @@ +{{ printf "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>" | safeHTML }} +<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"> +  <channel> +    <title>{{ if eq  .Title  .Site.Title }}{{ .Site.Title }}{{ else }}{{ with .Title }}{{.}} on {{ end }}{{ .Site.Title }}{{ end }}</title> +    <link>{{ .Permalink }}</link> +    <description>Recent content {{ if ne  .Title  .Site.Title }}{{ with .Title }}in {{.}} {{ end }}{{ end }}on {{ .Site.Title }}</description> +    <generator>Hugo -- gohugo.io</generator>{{ with .Site.LanguageCode }} +    <language>{{.}}</language>{{end}}{{ with .Site.Author.email }} +    <managingEditor>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</managingEditor>{{end}}{{ with .Site.Author.email }} +    <webMaster>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</webMaster>{{end}}{{ with .Site.Params.copyRight }} +    <copyright>{{ (printf . (now.Format "2006")) | safeHTML }}</copyright>{{end}}{{ if not .Date.IsZero }} +    <lastBuildDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</lastBuildDate>{{ end }} +    {{ with .OutputFormats.Get "RSS" }} +        {{ printf "<atom:link href=%q rel=\"self\" type=%q />" .Permalink .MediaType | safeHTML }} +    {{ end }} +    {{ range .Pages }}{{ if ne .Params.feed_exclude true }} +    <item> +      <title>{{ .Title }}</title> +      <link>{{ .Permalink }}</link> +      <pubDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</pubDate> +      {{ with .Site.Author.email }}<author>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</author>{{end}} +      <guid>{{ .Permalink }}</guid> +      <description>{{ .Summary | html }}</description> +    </item> +    {{ end }}{{ end }} +  </channel> +</rss> diff --git a/docs/layouts/shortcodes/alert.html b/docs/layouts/shortcodes/alert.html new file mode 100644 index 000000000..e2abe8ed3 --- /dev/null +++ b/docs/layouts/shortcodes/alert.html @@ -0,0 +1,12 @@ +<div class="alert alert-{{ with .Get "context" }}{{.}}{{ else }}doks{{ end }} d-flex" role="alert"> +  <div class="flex-shrink-1 alert-icon">{{ with .Get "icon" }}{{.}} {{ end }}</div> +  {{ with .Get "text"}} +    <div class="w-100">{{ . | safeHTML }} </div> +  {{ else }} +    {{ with .Inner}} +      <div class="w-100"> {{ . | markdownify}}</div> +    {{ else }} +      {{ errorf "No valid text variable or Inner content given"}} +    {{ end }} +  {{ end}} +</div> diff --git a/docs/layouts/shortcodes/confkey.html b/docs/layouts/shortcodes/confkey.html new file mode 100644 index 000000000..efba515f6 --- /dev/null +++ b/docs/layouts/shortcodes/confkey.html @@ -0,0 +1,12 @@ +{{ $requiredClass := "confkey-required" }}{{ $requiredText := "required" }} +{{ with .Get "required" }} +{{ if (eq . "no") }}{{ $requiredClass = "confkey-notrequired" }}{{ $requiredText = "not required" }} +{{ else if (eq . "situational") }}{{ $requiredClass = "confkey-situational" }}{{ $requiredText = "situational" }} +{{ end }}{{ end }} +<div class="mb-3"> +  <span class="badge confkey-type" data-bs-toggle="tooltip" data-bs-placement="top" title="The value type">{{ with .Get "type" }}{{ . }}{{ else }}string{{ end }}</span> +  {{ with .Get "default" }} +  <span class="badge confkey-default" data-bs-toggle="tooltip" title="The default value">{{ . }}</span> +  {{ end }} +  <span class="badge {{ $requiredClass }}" data-bs-toggle="tooltip" title="If this option is required or not">{{ $requiredText }}</span> +</div> diff --git a/docs/layouts/shortcodes/details.html b/docs/layouts/shortcodes/details.html new file mode 100644 index 000000000..61a71837d --- /dev/null +++ b/docs/layouts/shortcodes/details.html @@ -0,0 +1,4 @@ +<details{{ with .Get 1 }} {{ . | safeHTML }}{{ end -}}> +  <summary>{{ with .Get 0 -}}{{ . | safeHTML }}{{ else -}}{{ errorf "No summary provided"}}{{ end -}}</summary> +  {{ with .Inner -}}{{ . | markdownify}}{{ else -}}{{ errorf "No details provided"}}{{ end -}} +</details>
\ No newline at end of file diff --git a/docs/layouts/shortcodes/email.html b/docs/layouts/shortcodes/email.html new file mode 100644 index 000000000..88674fcc3 --- /dev/null +++ b/docs/layouts/shortcodes/email.html @@ -0,0 +1 @@ +<script type="text/javascript" nonce="dXNlcj0iaGVsbG8iLGRvbWFpbj0iaGVua3ZlcmxpbmRlLmNvbSIsZG9jdW1lbnQud3JpdGUodXNlcisiQCIrZG9tYWluKTs=">user="{{ with .Get "user" }}{{.}}{{ end }}",domain="{{ with .Get "domain" }}{{.}}{{ end }}",document.write(user+"@"+domain);</script><noscript>{{ with .Get "user" }}{{.}}{{ end }} at {{ with .Get "domain" }}{{.}}{{ end }}</noscript>
\ No newline at end of file diff --git a/docs/layouts/shortcodes/mermaid.html b/docs/layouts/shortcodes/mermaid.html new file mode 100644 index 000000000..aeecad535 --- /dev/null +++ b/docs/layouts/shortcodes/mermaid.html @@ -0,0 +1,8 @@ +{{ if .Page.Params.mermaid -}} +  <div class="mermaid{{ with .Get "class" }} {{ . }}{{ end }}"> +    {{ $data := replaceRE "(^\\s+```)" "" .Inner -}} +    {{ replaceRE "(```\\s+$)" "" $data -}} +  </div> +{{ else -}} +  {{ errorf "Failed to process mermaid shortcode: %s. Set mermaid to true in page front matter." .Position }} +{{ end -}} diff --git a/docs/layouts/shortcodes/print.html b/docs/layouts/shortcodes/print.html new file mode 100644 index 000000000..9c8bd546d --- /dev/null +++ b/docs/layouts/shortcodes/print.html @@ -0,0 +1 @@ +{{ index .Params 0 -}} diff --git a/docs/layouts/shortcodes/roadmap-status.html b/docs/layouts/shortcodes/roadmap-status.html new file mode 100644 index 000000000..2517a0485 --- /dev/null +++ b/docs/layouts/shortcodes/roadmap-status.html @@ -0,0 +1,12 @@ +{{ $class := "rs-not-started" }}{{ $text := "not started" }} +{{ with .Get "stage" }} +{{ if (eq . "in-progress") }}{{ $class = "rs-started" }}{{ $text = "in progress" }} +{{ else if (eq . "waiting") }}{{ $class = "rs-waiting" }}{{ $text = "waiting" }} +{{ else if (eq . "complete") }}{{ $class = "rs-complete" }}{{ $text = "complete" }} +{{ end }}{{ end }} +<div class="m-2"> +  <span class="badge {{ $class }}" data-bs-toggle="tooltip" data-bs-placement="top" title="The status of this roadmap item">{{ $text }}</span> +  {{ with .Get "version" }} +  <span class="badge rs-version" data-bs-toggle="tooltip" data-bs-placement="top" title="The version this stage was implemented in">{{ . }}</span> +  {{ end }} +</div> diff --git a/docs/layouts/shortcodes/video.html b/docs/layouts/shortcodes/video.html new file mode 100644 index 000000000..784c3a72a --- /dev/null +++ b/docs/layouts/shortcodes/video.html @@ -0,0 +1,11 @@ +<div class="ratio ratio-{{ with .Get "ratio" }}{{.}}{{ end }}"> +  <video{{ with .Get "attributes" }} {{ . | safeHTMLAttr }}{{ end }}> +    {{ with .Get "webm-src" -}} +    <source src="{{ . | relURL }}" type="video/webm"> +    {{ end -}} +    {{ with .Get "mp4-src" -}} +    <source src="{{ . | relURL }}" type="video/mp4"> +    {{ end -}} +    Sorry, your browser doesn't support embedded videos. +  </video> +</div> diff --git a/docs/layouts/sitemap.xml b/docs/layouts/sitemap.xml new file mode 100644 index 000000000..a3fcf7ac4 --- /dev/null +++ b/docs/layouts/sitemap.xml @@ -0,0 +1,22 @@ +{{ printf "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>" | safeHTML }} +<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" +  xmlns:xhtml="http://www.w3.org/1999/xhtml"> +  {{ range .Data.Pages }}{{ if ne .Params.sitemap_exclude true }} +  <url> +    <loc>{{ .Permalink }}</loc>{{ if not .Lastmod.IsZero }} +    <lastmod>{{ safeHTML ( .Lastmod.Format "2006-01-02T15:04:05-07:00" ) }}</lastmod>{{ end }}{{ with .Sitemap.ChangeFreq }} +    <changefreq>{{ . }}</changefreq>{{ end }}{{ if ge .Sitemap.Priority 0.0 }} +    <priority>{{ .Sitemap.Priority }}</priority>{{ end }}{{ if .IsTranslated }}{{ range .Translations }} +    <xhtml:link +                rel="alternate" +                hreflang="{{ .Lang }}" +                href="{{ .Permalink }}" +                />{{ end }} +    <xhtml:link +                rel="alternate" +                hreflang="{{ .Lang }}" +                href="{{ .Permalink }}" +                />{{ end }} +  </url> +  {{ end }}{{ end }} +</urlset> diff --git a/docs/netlify.toml b/docs/netlify.toml new file mode 100644 index 000000000..092a0f1e1 --- /dev/null +++ b/docs/netlify.toml @@ -0,0 +1,43 @@ +[build] +  publish = "public" +  functions = "functions" + +[build.environment] +  NODE_VERSION = "17.8.0" +  NPM_VERSION = "8.5.5" + +[context.production] +  command = "npm run build" + +[context.deploy-preview] +  command = "npm run build -- -b $DEPLOY_PRIME_URL" + +[context.branch-deploy] +  command = "npm run build -- -b $DEPLOY_PRIME_URL" + +[context.next] +  command = "npm run build" + +[context.next.environment] +  HUGO_ENV = "next" + +[[plugins]] +  package = "netlify-plugin-submit-sitemap" + +	[plugins.inputs] +    baseUrl = "https://www.authelia.com/" +    sitemapPath = "/sitemap.xml" +    ignorePeriod = 0 +    providers = [ +      "google", +      "bing", +      "yandex" +    ] + +[dev] +  framework = "#custom" +  command = "npm run start" +  targetPort = 1313 +  port = 8888 +  publish = "public" +  autoLaunch = false diff --git a/docs/package.json b/docs/package.json new file mode 100644 index 000000000..f7cf995c2 --- /dev/null +++ b/docs/package.json @@ -0,0 +1,68 @@ +{ +  "name": "@hyas/doks", +  "description": "Doks theme", +  "version": "0.4.2", +  "browserslist": [ +    "defaults" +  ], +  "repository": "https://github.com/h-enk/doks", +  "license": "MIT", +  "publishConfig": { +    "access": "public" +  }, +  "scripts": { +    "init": "shx rm -rf .git && git init -b main", +    "create": "exec-bin node_modules/.bin/hugo/hugo new", +    "prestart": "npm run clean", +    "start": "exec-bin node_modules/.bin/hugo/hugo server --bind=0.0.0.0 --disableFastRender", +    "prebuild": "npm run clean", +    "build": "exec-bin node_modules/.bin/hugo/hugo --gc --minify", +    "build:preview": "npm run build -D -F", +    "clean": "shx rm -rf public resources", +    "clean:install": "shx rm -rf package-lock.json node_modules ", +    "lint": "npm run -s lint:scripts && npm run -s lint:styles && npm run -s lint:markdown", +    "lint:scripts": "eslint assets/js config functions", +    "lint:styles": "stylelint \"assets/scss/**/*.{css,sass,scss,sss,less}\"", +    "lint:markdown": "markdownlint-cli2 \"*.md\" \"content/**/*.md\"", +    "lint:markdown-fix": "markdownlint-cli2-fix \"*.md\" \"content/**/*.md\"", +    "server": "exec-bin node_modules/.bin/hugo/hugo server", +    "test": "npm run -s lint", +    "env": "env", +    "precheck": "npm version", +    "check": "exec-bin node_modules/.bin/hugo/hugo version", +    "copy:katex-fonts": "shx cp ./node_modules/katex/dist/fonts/* ./static/fonts/", +    "postinstall": "hugo-installer --version otherDependencies.hugo --extended --destination node_modules/.bin/hugo", +    "version": "auto-changelog -p && git add CHANGELOG.md" +  }, +  "devDependencies": { +    "@babel/cli": "7.17.10", +    "@babel/core": "7.18.2", +    "@babel/preset-env": "^7.16", +    "@fullhuman/postcss-purgecss": "4.1.3", +    "auto-changelog": "2.4.0", +    "autoprefixer": "10.4.7", +    "bootstrap": "5.1.3", +    "bootstrap-icons": "1.8.3", +    "clipboard": "2.0.11", +    "eslint": "8.17.0", +    "exec-bin": "1.0.0", +    "flexsearch": "0.7.21", +    "highlight.js": "11.5.1", +    "hugo-installer": "3.1.0", +    "instant.page": "5.1.0", +    "katex": "0.16.0", +    "lazysizes": "5.3.2", +    "markdownlint-cli2": "0.4.0", +    "netlify-plugin-submit-sitemap": "0.3.0", +    "node-fetch": "3.2.5", +    "postcss": "8.4.14", +    "postcss-cli": "9.1.0", +    "purgecss-whitelister": "2.4.0", +    "shx": "0.3.4", +    "stylelint": "14.9.0", +    "stylelint-config-standard-scss": "3.0.0" +  }, +  "otherDependencies": { +    "hugo": "0.96.0" +  } +} diff --git a/docs/pnpm-lock.yaml b/docs/pnpm-lock.yaml new file mode 100644 index 000000000..c8b2bcc69 --- /dev/null +++ b/docs/pnpm-lock.yaml @@ -0,0 +1,4259 @@ +lockfileVersion: 5.4 + +specifiers: +  '@babel/cli': 7.17.10 +  '@babel/core': 7.18.2 +  '@babel/preset-env': ^7.16 +  '@fullhuman/postcss-purgecss': 4.1.3 +  auto-changelog: 2.4.0 +  autoprefixer: 10.4.7 +  bootstrap: 5.1.3 +  bootstrap-icons: 1.8.3 +  clipboard: 2.0.11 +  eslint: 8.17.0 +  exec-bin: 1.0.0 +  flexsearch: 0.7.21 +  highlight.js: 11.5.1 +  hugo-installer: 3.1.0 +  instant.page: 5.1.0 +  katex: 0.16.0 +  lazysizes: 5.3.2 +  markdownlint-cli2: 0.4.0 +  netlify-plugin-submit-sitemap: 0.3.0 +  node-fetch: 3.2.5 +  postcss: 8.4.14 +  postcss-cli: 9.1.0 +  purgecss-whitelister: 2.4.0 +  shx: 0.3.4 +  stylelint: 14.9.0 +  stylelint-config-standard-scss: 3.0.0 + +devDependencies: +  '@babel/cli': 7.17.10_@babel+core@7.18.2 +  '@babel/core': 7.18.2 +  '@babel/preset-env': 7.18.2_@babel+core@7.18.2 +  '@fullhuman/postcss-purgecss': 4.1.3_postcss@8.4.14 +  auto-changelog: 2.4.0 +  autoprefixer: 10.4.7_postcss@8.4.14 +  bootstrap: 5.1.3 +  bootstrap-icons: 1.8.3 +  clipboard: 2.0.11 +  eslint: 8.17.0 +  exec-bin: 1.0.0 +  flexsearch: 0.7.21 +  highlight.js: 11.5.1 +  hugo-installer: 3.1.0 +  instant.page: 5.1.0 +  katex: 0.16.0 +  lazysizes: 5.3.2 +  markdownlint-cli2: 0.4.0 +  netlify-plugin-submit-sitemap: 0.3.0 +  node-fetch: 3.2.5 +  postcss: 8.4.14 +  postcss-cli: 9.1.0_postcss@8.4.14 +  purgecss-whitelister: 2.4.0 +  shx: 0.3.4 +  stylelint: 14.9.0 +  stylelint-config-standard-scss: 3.0.0_7ic4eknhyyc4ey2sk6vxipflva + +packages: + +  /@ampproject/remapping/2.2.0: +    resolution: {integrity: sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==} +    engines: {node: '>=6.0.0'} +    dependencies: +      '@jridgewell/gen-mapping': 0.1.1 +      '@jridgewell/trace-mapping': 0.3.13 +    dev: true + +  /@babel/cli/7.17.10_@babel+core@7.18.2: +    resolution: {integrity: sha512-OygVO1M2J4yPMNOW9pb+I6kFGpQK77HmG44Oz3hg8xQIl5L/2zq+ZohwAdSaqYgVwM0SfmPHZHphH4wR8qzVYw==} +    engines: {node: '>=6.9.0'} +    hasBin: true +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@jridgewell/trace-mapping': 0.3.13 +      commander: 4.1.1 +      convert-source-map: 1.8.0 +      fs-readdir-recursive: 1.1.0 +      glob: 7.2.3 +      make-dir: 2.1.0 +      slash: 2.0.0 +    optionalDependencies: +      '@nicolo-ribaudo/chokidar-2': 2.1.8-no-fsevents.3 +      chokidar: 3.5.3 +    dev: true + +  /@babel/code-frame/7.16.7: +    resolution: {integrity: sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==} +    engines: {node: '>=6.9.0'} +    dependencies: +      '@babel/highlight': 7.17.12 +    dev: true + +  /@babel/compat-data/7.17.10: +    resolution: {integrity: sha512-GZt/TCsG70Ms19gfZO1tM4CVnXsPgEPBCpJu+Qz3L0LUDsY5nZqFZglIoPC1kIYOtNBZlrnFT+klg12vFGZXrw==} +    engines: {node: '>=6.9.0'} +    dev: true + +  /@babel/core/7.18.2: +    resolution: {integrity: sha512-A8pri1YJiC5UnkdrWcmfZTJTV85b4UXTAfImGmCfYmax4TR9Cw8sDS0MOk++Gp2mE/BefVJ5nwy5yzqNJbP/DQ==} +    engines: {node: '>=6.9.0'} +    dependencies: +      '@ampproject/remapping': 2.2.0 +      '@babel/code-frame': 7.16.7 +      '@babel/generator': 7.18.2 +      '@babel/helper-compilation-targets': 7.18.2_@babel+core@7.18.2 +      '@babel/helper-module-transforms': 7.18.0 +      '@babel/helpers': 7.18.2 +      '@babel/parser': 7.18.4 +      '@babel/template': 7.16.7 +      '@babel/traverse': 7.18.2 +      '@babel/types': 7.18.4 +      convert-source-map: 1.8.0 +      debug: 4.3.4 +      gensync: 1.0.0-beta.2 +      json5: 2.2.1 +      semver: 6.3.0 +    transitivePeerDependencies: +      - supports-color +    dev: true + +  /@babel/generator/7.18.2: +    resolution: {integrity: sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw==} +    engines: {node: '>=6.9.0'} +    dependencies: +      '@babel/types': 7.18.4 +      '@jridgewell/gen-mapping': 0.3.1 +      jsesc: 2.5.2 +    dev: true + +  /@babel/helper-annotate-as-pure/7.16.7: +    resolution: {integrity: sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==} +    engines: {node: '>=6.9.0'} +    dependencies: +      '@babel/types': 7.18.4 +    dev: true + +  /@babel/helper-builder-binary-assignment-operator-visitor/7.16.7: +    resolution: {integrity: sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA==} +    engines: {node: '>=6.9.0'} +    dependencies: +      '@babel/helper-explode-assignable-expression': 7.16.7 +      '@babel/types': 7.18.4 +    dev: true + +  /@babel/helper-compilation-targets/7.18.2_@babel+core@7.18.2: +    resolution: {integrity: sha512-s1jnPotJS9uQnzFtiZVBUxe67CuBa679oWFHpxYYnTpRL/1ffhyX44R9uYiXoa/pLXcY9H2moJta0iaanlk/rQ==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0 +    dependencies: +      '@babel/compat-data': 7.17.10 +      '@babel/core': 7.18.2 +      '@babel/helper-validator-option': 7.16.7 +      browserslist: 4.20.3 +      semver: 6.3.0 +    dev: true + +  /@babel/helper-create-class-features-plugin/7.18.0_@babel+core@7.18.2: +    resolution: {integrity: sha512-Kh8zTGR9de3J63e5nS0rQUdRs/kbtwoeQQ0sriS0lItjC96u8XXZN6lKpuyWd2coKSU13py/y+LTmThLuVX0Pg==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-annotate-as-pure': 7.16.7 +      '@babel/helper-environment-visitor': 7.18.2 +      '@babel/helper-function-name': 7.17.9 +      '@babel/helper-member-expression-to-functions': 7.17.7 +      '@babel/helper-optimise-call-expression': 7.16.7 +      '@babel/helper-replace-supers': 7.18.2 +      '@babel/helper-split-export-declaration': 7.16.7 +    transitivePeerDependencies: +      - supports-color +    dev: true + +  /@babel/helper-create-regexp-features-plugin/7.17.12_@babel+core@7.18.2: +    resolution: {integrity: sha512-b2aZrV4zvutr9AIa6/gA3wsZKRwTKYoDxYiFKcESS3Ug2GTXzwBEvMuuFLhCQpEnRXs1zng4ISAXSUxxKBIcxw==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-annotate-as-pure': 7.16.7 +      regexpu-core: 5.0.1 +    dev: true + +  /@babel/helper-define-polyfill-provider/0.3.1_@babel+core@7.18.2: +    resolution: {integrity: sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==} +    peerDependencies: +      '@babel/core': ^7.4.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-compilation-targets': 7.18.2_@babel+core@7.18.2 +      '@babel/helper-module-imports': 7.16.7 +      '@babel/helper-plugin-utils': 7.17.12 +      '@babel/traverse': 7.18.2 +      debug: 4.3.4 +      lodash.debounce: 4.0.8 +      resolve: 1.22.0 +      semver: 6.3.0 +    transitivePeerDependencies: +      - supports-color +    dev: true + +  /@babel/helper-environment-visitor/7.18.2: +    resolution: {integrity: sha512-14GQKWkX9oJzPiQQ7/J36FTXcD4kSp8egKjO9nINlSKiHITRA9q/R74qu8S9xlc/b/yjsJItQUeeh3xnGN0voQ==} +    engines: {node: '>=6.9.0'} +    dev: true + +  /@babel/helper-explode-assignable-expression/7.16.7: +    resolution: {integrity: sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ==} +    engines: {node: '>=6.9.0'} +    dependencies: +      '@babel/types': 7.18.4 +    dev: true + +  /@babel/helper-function-name/7.17.9: +    resolution: {integrity: sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==} +    engines: {node: '>=6.9.0'} +    dependencies: +      '@babel/template': 7.16.7 +      '@babel/types': 7.18.4 +    dev: true + +  /@babel/helper-hoist-variables/7.16.7: +    resolution: {integrity: sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==} +    engines: {node: '>=6.9.0'} +    dependencies: +      '@babel/types': 7.18.4 +    dev: true + +  /@babel/helper-member-expression-to-functions/7.17.7: +    resolution: {integrity: sha512-thxXgnQ8qQ11W2wVUObIqDL4p148VMxkt5T/qpN5k2fboRyzFGFmKsTGViquyM5QHKUy48OZoca8kw4ajaDPyw==} +    engines: {node: '>=6.9.0'} +    dependencies: +      '@babel/types': 7.18.4 +    dev: true + +  /@babel/helper-module-imports/7.16.7: +    resolution: {integrity: sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==} +    engines: {node: '>=6.9.0'} +    dependencies: +      '@babel/types': 7.18.4 +    dev: true + +  /@babel/helper-module-transforms/7.18.0: +    resolution: {integrity: sha512-kclUYSUBIjlvnzN2++K9f2qzYKFgjmnmjwL4zlmU5f8ZtzgWe8s0rUPSTGy2HmK4P8T52MQsS+HTQAgZd3dMEA==} +    engines: {node: '>=6.9.0'} +    dependencies: +      '@babel/helper-environment-visitor': 7.18.2 +      '@babel/helper-module-imports': 7.16.7 +      '@babel/helper-simple-access': 7.18.2 +      '@babel/helper-split-export-declaration': 7.16.7 +      '@babel/helper-validator-identifier': 7.16.7 +      '@babel/template': 7.16.7 +      '@babel/traverse': 7.18.2 +      '@babel/types': 7.18.4 +    transitivePeerDependencies: +      - supports-color +    dev: true + +  /@babel/helper-optimise-call-expression/7.16.7: +    resolution: {integrity: sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==} +    engines: {node: '>=6.9.0'} +    dependencies: +      '@babel/types': 7.18.4 +    dev: true + +  /@babel/helper-plugin-utils/7.17.12: +    resolution: {integrity: sha512-JDkf04mqtN3y4iAbO1hv9U2ARpPyPL1zqyWs/2WG1pgSq9llHFjStX5jdxb84himgJm+8Ng+x0oiWF/nw/XQKA==} +    engines: {node: '>=6.9.0'} +    dev: true + +  /@babel/helper-remap-async-to-generator/7.16.8: +    resolution: {integrity: sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw==} +    engines: {node: '>=6.9.0'} +    dependencies: +      '@babel/helper-annotate-as-pure': 7.16.7 +      '@babel/helper-wrap-function': 7.16.8 +      '@babel/types': 7.18.4 +    transitivePeerDependencies: +      - supports-color +    dev: true + +  /@babel/helper-replace-supers/7.18.2: +    resolution: {integrity: sha512-XzAIyxx+vFnrOxiQrToSUOzUOn0e1J2Li40ntddek1Y69AXUTXoDJ40/D5RdjFu7s7qHiaeoTiempZcbuVXh2Q==} +    engines: {node: '>=6.9.0'} +    dependencies: +      '@babel/helper-environment-visitor': 7.18.2 +      '@babel/helper-member-expression-to-functions': 7.17.7 +      '@babel/helper-optimise-call-expression': 7.16.7 +      '@babel/traverse': 7.18.2 +      '@babel/types': 7.18.4 +    transitivePeerDependencies: +      - supports-color +    dev: true + +  /@babel/helper-simple-access/7.18.2: +    resolution: {integrity: sha512-7LIrjYzndorDY88MycupkpQLKS1AFfsVRm2k/9PtKScSy5tZq0McZTj+DiMRynboZfIqOKvo03pmhTaUgiD6fQ==} +    engines: {node: '>=6.9.0'} +    dependencies: +      '@babel/types': 7.18.4 +    dev: true + +  /@babel/helper-skip-transparent-expression-wrappers/7.16.0: +    resolution: {integrity: sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==} +    engines: {node: '>=6.9.0'} +    dependencies: +      '@babel/types': 7.18.4 +    dev: true + +  /@babel/helper-split-export-declaration/7.16.7: +    resolution: {integrity: sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==} +    engines: {node: '>=6.9.0'} +    dependencies: +      '@babel/types': 7.18.4 +    dev: true + +  /@babel/helper-validator-identifier/7.16.7: +    resolution: {integrity: sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==} +    engines: {node: '>=6.9.0'} +    dev: true + +  /@babel/helper-validator-option/7.16.7: +    resolution: {integrity: sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==} +    engines: {node: '>=6.9.0'} +    dev: true + +  /@babel/helper-wrap-function/7.16.8: +    resolution: {integrity: sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw==} +    engines: {node: '>=6.9.0'} +    dependencies: +      '@babel/helper-function-name': 7.17.9 +      '@babel/template': 7.16.7 +      '@babel/traverse': 7.18.2 +      '@babel/types': 7.18.4 +    transitivePeerDependencies: +      - supports-color +    dev: true + +  /@babel/helpers/7.18.2: +    resolution: {integrity: sha512-j+d+u5xT5utcQSzrh9p+PaJX94h++KN+ng9b9WEJq7pkUPAd61FGqhjuUEdfknb3E/uDBb7ruwEeKkIxNJPIrg==} +    engines: {node: '>=6.9.0'} +    dependencies: +      '@babel/template': 7.16.7 +      '@babel/traverse': 7.18.2 +      '@babel/types': 7.18.4 +    transitivePeerDependencies: +      - supports-color +    dev: true + +  /@babel/highlight/7.17.12: +    resolution: {integrity: sha512-7yykMVF3hfZY2jsHZEEgLc+3x4o1O+fYyULu11GynEUQNwB6lua+IIQn1FiJxNucd5UlyJryrwsOh8PL9Sn8Qg==} +    engines: {node: '>=6.9.0'} +    dependencies: +      '@babel/helper-validator-identifier': 7.16.7 +      chalk: 2.4.2 +      js-tokens: 4.0.0 +    dev: true + +  /@babel/parser/7.18.4: +    resolution: {integrity: sha512-FDge0dFazETFcxGw/EXzOkN8uJp0PC7Qbm+Pe9T+av2zlBpOgunFHkQPPn+eRuClU73JF+98D531UgayY89tow==} +    engines: {node: '>=6.0.0'} +    hasBin: true +    dependencies: +      '@babel/types': 7.18.4 +    dev: true + +  /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/7.17.12_@babel+core@7.18.2: +    resolution: {integrity: sha512-xCJQXl4EeQ3J9C4yOmpTrtVGmzpm2iSzyxbkZHw7UCnZBftHpF/hpII80uWVyVrc40ytIClHjgWGTG1g/yB+aw==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +    dev: true + +  /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/7.17.12_@babel+core@7.18.2: +    resolution: {integrity: sha512-/vt0hpIw0x4b6BLKUkwlvEoiGZYYLNZ96CzyHYPbtG2jZGz6LBe7/V+drYrc/d+ovrF9NBi0pmtvmNb/FsWtRQ==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.13.0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +      '@babel/helper-skip-transparent-expression-wrappers': 7.16.0 +      '@babel/plugin-proposal-optional-chaining': 7.17.12_@babel+core@7.18.2 +    dev: true + +  /@babel/plugin-proposal-async-generator-functions/7.17.12_@babel+core@7.18.2: +    resolution: {integrity: sha512-RWVvqD1ooLKP6IqWTA5GyFVX2isGEgC5iFxKzfYOIy/QEFdxYyCybBDtIGjipHpb9bDWHzcqGqFakf+mVmBTdQ==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +      '@babel/helper-remap-async-to-generator': 7.16.8 +      '@babel/plugin-syntax-async-generators': 7.8.4_@babel+core@7.18.2 +    transitivePeerDependencies: +      - supports-color +    dev: true + +  /@babel/plugin-proposal-class-properties/7.17.12_@babel+core@7.18.2: +    resolution: {integrity: sha512-U0mI9q8pW5Q9EaTHFPwSVusPMV/DV9Mm8p7csqROFLtIE9rBF5piLqyrBGigftALrBcsBGu4m38JneAe7ZDLXw==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-create-class-features-plugin': 7.18.0_@babel+core@7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +    transitivePeerDependencies: +      - supports-color +    dev: true + +  /@babel/plugin-proposal-class-static-block/7.18.0_@babel+core@7.18.2: +    resolution: {integrity: sha512-t+8LsRMMDE74c6sV7KShIw13sqbqd58tlqNrsWoWBTIMw7SVQ0cZ905wLNS/FBCy/3PyooRHLFFlfrUNyyz5lA==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.12.0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-create-class-features-plugin': 7.18.0_@babel+core@7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +      '@babel/plugin-syntax-class-static-block': 7.14.5_@babel+core@7.18.2 +    transitivePeerDependencies: +      - supports-color +    dev: true + +  /@babel/plugin-proposal-dynamic-import/7.16.7_@babel+core@7.18.2: +    resolution: {integrity: sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +      '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.18.2 +    dev: true + +  /@babel/plugin-proposal-export-namespace-from/7.17.12_@babel+core@7.18.2: +    resolution: {integrity: sha512-j7Ye5EWdwoXOpRmo5QmRyHPsDIe6+u70ZYZrd7uz+ebPYFKfRcLcNu3Ro0vOlJ5zuv8rU7xa+GttNiRzX56snQ==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +      '@babel/plugin-syntax-export-namespace-from': 7.8.3_@babel+core@7.18.2 +    dev: true + +  /@babel/plugin-proposal-json-strings/7.17.12_@babel+core@7.18.2: +    resolution: {integrity: sha512-rKJ+rKBoXwLnIn7n6o6fulViHMrOThz99ybH+hKHcOZbnN14VuMnH9fo2eHE69C8pO4uX1Q7t2HYYIDmv8VYkg==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +      '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.18.2 +    dev: true + +  /@babel/plugin-proposal-logical-assignment-operators/7.17.12_@babel+core@7.18.2: +    resolution: {integrity: sha512-EqFo2s1Z5yy+JeJu7SFfbIUtToJTVlC61/C7WLKDntSw4Sz6JNAIfL7zQ74VvirxpjB5kz/kIx0gCcb+5OEo2Q==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +      '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.18.2 +    dev: true + +  /@babel/plugin-proposal-nullish-coalescing-operator/7.17.12_@babel+core@7.18.2: +    resolution: {integrity: sha512-ws/g3FSGVzv+VH86+QvgtuJL/kR67xaEIF2x0iPqdDfYW6ra6JF3lKVBkWynRLcNtIC1oCTfDRVxmm2mKzy+ag==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +      '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3_@babel+core@7.18.2 +    dev: true + +  /@babel/plugin-proposal-numeric-separator/7.16.7_@babel+core@7.18.2: +    resolution: {integrity: sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +      '@babel/plugin-syntax-numeric-separator': 7.10.4_@babel+core@7.18.2 +    dev: true + +  /@babel/plugin-proposal-object-rest-spread/7.18.0_@babel+core@7.18.2: +    resolution: {integrity: sha512-nbTv371eTrFabDfHLElkn9oyf9VG+VKK6WMzhY2o4eHKaG19BToD9947zzGMO6I/Irstx9d8CwX6njPNIAR/yw==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/compat-data': 7.17.10 +      '@babel/core': 7.18.2 +      '@babel/helper-compilation-targets': 7.18.2_@babel+core@7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +      '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.18.2 +      '@babel/plugin-transform-parameters': 7.17.12_@babel+core@7.18.2 +    dev: true + +  /@babel/plugin-proposal-optional-catch-binding/7.16.7_@babel+core@7.18.2: +    resolution: {integrity: sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +      '@babel/plugin-syntax-optional-catch-binding': 7.8.3_@babel+core@7.18.2 +    dev: true + +  /@babel/plugin-proposal-optional-chaining/7.17.12_@babel+core@7.18.2: +    resolution: {integrity: sha512-7wigcOs/Z4YWlK7xxjkvaIw84vGhDv/P1dFGQap0nHkc8gFKY/r+hXc8Qzf5k1gY7CvGIcHqAnOagVKJJ1wVOQ==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +      '@babel/helper-skip-transparent-expression-wrappers': 7.16.0 +      '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.18.2 +    dev: true + +  /@babel/plugin-proposal-private-methods/7.17.12_@babel+core@7.18.2: +    resolution: {integrity: sha512-SllXoxo19HmxhDWm3luPz+cPhtoTSKLJE9PXshsfrOzBqs60QP0r8OaJItrPhAj0d7mZMnNF0Y1UUggCDgMz1A==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-create-class-features-plugin': 7.18.0_@babel+core@7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +    transitivePeerDependencies: +      - supports-color +    dev: true + +  /@babel/plugin-proposal-private-property-in-object/7.17.12_@babel+core@7.18.2: +    resolution: {integrity: sha512-/6BtVi57CJfrtDNKfK5b66ydK2J5pXUKBKSPD2G1whamMuEnZWgoOIfO8Vf9F/DoD4izBLD/Au4NMQfruzzykg==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-annotate-as-pure': 7.16.7 +      '@babel/helper-create-class-features-plugin': 7.18.0_@babel+core@7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +      '@babel/plugin-syntax-private-property-in-object': 7.14.5_@babel+core@7.18.2 +    transitivePeerDependencies: +      - supports-color +    dev: true + +  /@babel/plugin-proposal-unicode-property-regex/7.17.12_@babel+core@7.18.2: +    resolution: {integrity: sha512-Wb9qLjXf3ZazqXA7IvI7ozqRIXIGPtSo+L5coFmEkhTQK18ao4UDDD0zdTGAarmbLj2urpRwrc6893cu5Bfh0A==} +    engines: {node: '>=4'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-create-regexp-features-plugin': 7.17.12_@babel+core@7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +    dev: true + +  /@babel/plugin-syntax-async-generators/7.8.4_@babel+core@7.18.2: +    resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +    dev: true + +  /@babel/plugin-syntax-class-properties/7.12.13_@babel+core@7.18.2: +    resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +    dev: true + +  /@babel/plugin-syntax-class-static-block/7.14.5_@babel+core@7.18.2: +    resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +    dev: true + +  /@babel/plugin-syntax-dynamic-import/7.8.3_@babel+core@7.18.2: +    resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +    dev: true + +  /@babel/plugin-syntax-export-namespace-from/7.8.3_@babel+core@7.18.2: +    resolution: {integrity: sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +    dev: true + +  /@babel/plugin-syntax-import-assertions/7.17.12_@babel+core@7.18.2: +    resolution: {integrity: sha512-n/loy2zkq9ZEM8tEOwON9wTQSTNDTDEz6NujPtJGLU7qObzT1N4c4YZZf8E6ATB2AjNQg/Ib2AIpO03EZaCehw==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +    dev: true + +  /@babel/plugin-syntax-json-strings/7.8.3_@babel+core@7.18.2: +    resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +    dev: true + +  /@babel/plugin-syntax-logical-assignment-operators/7.10.4_@babel+core@7.18.2: +    resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +    dev: true + +  /@babel/plugin-syntax-nullish-coalescing-operator/7.8.3_@babel+core@7.18.2: +    resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +    dev: true + +  /@babel/plugin-syntax-numeric-separator/7.10.4_@babel+core@7.18.2: +    resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +    dev: true + +  /@babel/plugin-syntax-object-rest-spread/7.8.3_@babel+core@7.18.2: +    resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +    dev: true + +  /@babel/plugin-syntax-optional-catch-binding/7.8.3_@babel+core@7.18.2: +    resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +    dev: true + +  /@babel/plugin-syntax-optional-chaining/7.8.3_@babel+core@7.18.2: +    resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +    dev: true + +  /@babel/plugin-syntax-private-property-in-object/7.14.5_@babel+core@7.18.2: +    resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +    dev: true + +  /@babel/plugin-syntax-top-level-await/7.14.5_@babel+core@7.18.2: +    resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +    dev: true + +  /@babel/plugin-transform-arrow-functions/7.17.12_@babel+core@7.18.2: +    resolution: {integrity: sha512-PHln3CNi/49V+mza4xMwrg+WGYevSF1oaiXaC2EQfdp4HWlSjRsrDXWJiQBKpP7749u6vQ9mcry2uuFOv5CXvA==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +    dev: true + +  /@babel/plugin-transform-async-to-generator/7.17.12_@babel+core@7.18.2: +    resolution: {integrity: sha512-J8dbrWIOO3orDzir57NRsjg4uxucvhby0L/KZuGsWDj0g7twWK3g7JhJhOrXtuXiw8MeiSdJ3E0OW9H8LYEzLQ==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-module-imports': 7.16.7 +      '@babel/helper-plugin-utils': 7.17.12 +      '@babel/helper-remap-async-to-generator': 7.16.8 +    transitivePeerDependencies: +      - supports-color +    dev: true + +  /@babel/plugin-transform-block-scoped-functions/7.16.7_@babel+core@7.18.2: +    resolution: {integrity: sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +    dev: true + +  /@babel/plugin-transform-block-scoping/7.18.4_@babel+core@7.18.2: +    resolution: {integrity: sha512-+Hq10ye+jlvLEogSOtq4mKvtk7qwcUQ1f0Mrueai866C82f844Yom2cttfJdMdqRLTxWpsbfbkIkOIfovyUQXw==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +    dev: true + +  /@babel/plugin-transform-classes/7.18.4_@babel+core@7.18.2: +    resolution: {integrity: sha512-e42NSG2mlKWgxKUAD9EJJSkZxR67+wZqzNxLSpc51T8tRU5SLFHsPmgYR5yr7sdgX4u+iHA1C5VafJ6AyImV3A==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-annotate-as-pure': 7.16.7 +      '@babel/helper-environment-visitor': 7.18.2 +      '@babel/helper-function-name': 7.17.9 +      '@babel/helper-optimise-call-expression': 7.16.7 +      '@babel/helper-plugin-utils': 7.17.12 +      '@babel/helper-replace-supers': 7.18.2 +      '@babel/helper-split-export-declaration': 7.16.7 +      globals: 11.12.0 +    transitivePeerDependencies: +      - supports-color +    dev: true + +  /@babel/plugin-transform-computed-properties/7.17.12_@babel+core@7.18.2: +    resolution: {integrity: sha512-a7XINeplB5cQUWMg1E/GI1tFz3LfK021IjV1rj1ypE+R7jHm+pIHmHl25VNkZxtx9uuYp7ThGk8fur1HHG7PgQ==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +    dev: true + +  /@babel/plugin-transform-destructuring/7.18.0_@babel+core@7.18.2: +    resolution: {integrity: sha512-Mo69klS79z6KEfrLg/1WkmVnB8javh75HX4pi2btjvlIoasuxilEyjtsQW6XPrubNd7AQy0MMaNIaQE4e7+PQw==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +    dev: true + +  /@babel/plugin-transform-dotall-regex/7.16.7_@babel+core@7.18.2: +    resolution: {integrity: sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-create-regexp-features-plugin': 7.17.12_@babel+core@7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +    dev: true + +  /@babel/plugin-transform-duplicate-keys/7.17.12_@babel+core@7.18.2: +    resolution: {integrity: sha512-EA5eYFUG6xeerdabina/xIoB95jJ17mAkR8ivx6ZSu9frKShBjpOGZPn511MTDTkiCO+zXnzNczvUM69YSf3Zw==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +    dev: true + +  /@babel/plugin-transform-exponentiation-operator/7.16.7_@babel+core@7.18.2: +    resolution: {integrity: sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-builder-binary-assignment-operator-visitor': 7.16.7 +      '@babel/helper-plugin-utils': 7.17.12 +    dev: true + +  /@babel/plugin-transform-for-of/7.18.1_@babel+core@7.18.2: +    resolution: {integrity: sha512-+TTB5XwvJ5hZbO8xvl2H4XaMDOAK57zF4miuC9qQJgysPNEAZZ9Z69rdF5LJkozGdZrjBIUAIyKUWRMmebI7vg==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +    dev: true + +  /@babel/plugin-transform-function-name/7.16.7_@babel+core@7.18.2: +    resolution: {integrity: sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-compilation-targets': 7.18.2_@babel+core@7.18.2 +      '@babel/helper-function-name': 7.17.9 +      '@babel/helper-plugin-utils': 7.17.12 +    dev: true + +  /@babel/plugin-transform-literals/7.17.12_@babel+core@7.18.2: +    resolution: {integrity: sha512-8iRkvaTjJciWycPIZ9k9duu663FT7VrBdNqNgxnVXEFwOIp55JWcZd23VBRySYbnS3PwQ3rGiabJBBBGj5APmQ==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +    dev: true + +  /@babel/plugin-transform-member-expression-literals/7.16.7_@babel+core@7.18.2: +    resolution: {integrity: sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +    dev: true + +  /@babel/plugin-transform-modules-amd/7.18.0_@babel+core@7.18.2: +    resolution: {integrity: sha512-h8FjOlYmdZwl7Xm2Ug4iX2j7Qy63NANI+NQVWQzv6r25fqgg7k2dZl03p95kvqNclglHs4FZ+isv4p1uXMA+QA==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-module-transforms': 7.18.0 +      '@babel/helper-plugin-utils': 7.17.12 +      babel-plugin-dynamic-import-node: 2.3.3 +    transitivePeerDependencies: +      - supports-color +    dev: true + +  /@babel/plugin-transform-modules-commonjs/7.18.2_@babel+core@7.18.2: +    resolution: {integrity: sha512-f5A865gFPAJAEE0K7F/+nm5CmAE3y8AWlMBG9unu5j9+tk50UQVK0QS8RNxSp7MJf0wh97uYyLWt3Zvu71zyOQ==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-module-transforms': 7.18.0 +      '@babel/helper-plugin-utils': 7.17.12 +      '@babel/helper-simple-access': 7.18.2 +      babel-plugin-dynamic-import-node: 2.3.3 +    transitivePeerDependencies: +      - supports-color +    dev: true + +  /@babel/plugin-transform-modules-systemjs/7.18.4_@babel+core@7.18.2: +    resolution: {integrity: sha512-lH2UaQaHVOAeYrUUuZ8i38o76J/FnO8vu21OE+tD1MyP9lxdZoSfz+pDbWkq46GogUrdrMz3tiz/FYGB+bVThg==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-hoist-variables': 7.16.7 +      '@babel/helper-module-transforms': 7.18.0 +      '@babel/helper-plugin-utils': 7.17.12 +      '@babel/helper-validator-identifier': 7.16.7 +      babel-plugin-dynamic-import-node: 2.3.3 +    transitivePeerDependencies: +      - supports-color +    dev: true + +  /@babel/plugin-transform-modules-umd/7.18.0_@babel+core@7.18.2: +    resolution: {integrity: sha512-d/zZ8I3BWli1tmROLxXLc9A6YXvGK8egMxHp+E/rRwMh1Kip0AP77VwZae3snEJ33iiWwvNv2+UIIhfalqhzZA==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-module-transforms': 7.18.0 +      '@babel/helper-plugin-utils': 7.17.12 +    transitivePeerDependencies: +      - supports-color +    dev: true + +  /@babel/plugin-transform-named-capturing-groups-regex/7.17.12_@babel+core@7.18.2: +    resolution: {integrity: sha512-vWoWFM5CKaTeHrdUJ/3SIOTRV+MBVGybOC9mhJkaprGNt5demMymDW24yC74avb915/mIRe3TgNb/d8idvnCRA==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-create-regexp-features-plugin': 7.17.12_@babel+core@7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +    dev: true + +  /@babel/plugin-transform-new-target/7.17.12_@babel+core@7.18.2: +    resolution: {integrity: sha512-CaOtzk2fDYisbjAD4Sd1MTKGVIpRtx9bWLyj24Y/k6p4s4gQ3CqDGJauFJxt8M/LEx003d0i3klVqnN73qvK3w==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +    dev: true + +  /@babel/plugin-transform-object-super/7.16.7_@babel+core@7.18.2: +    resolution: {integrity: sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +      '@babel/helper-replace-supers': 7.18.2 +    transitivePeerDependencies: +      - supports-color +    dev: true + +  /@babel/plugin-transform-parameters/7.17.12_@babel+core@7.18.2: +    resolution: {integrity: sha512-6qW4rWo1cyCdq1FkYri7AHpauchbGLXpdwnYsfxFb+KtddHENfsY5JZb35xUwkK5opOLcJ3BNd2l7PhRYGlwIA==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +    dev: true + +  /@babel/plugin-transform-property-literals/7.16.7_@babel+core@7.18.2: +    resolution: {integrity: sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +    dev: true + +  /@babel/plugin-transform-regenerator/7.18.0_@babel+core@7.18.2: +    resolution: {integrity: sha512-C8YdRw9uzx25HSIzwA7EM7YP0FhCe5wNvJbZzjVNHHPGVcDJ3Aie+qGYYdS1oVQgn+B3eAIJbWFLrJ4Jipv7nw==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +      regenerator-transform: 0.15.0 +    dev: true + +  /@babel/plugin-transform-reserved-words/7.17.12_@babel+core@7.18.2: +    resolution: {integrity: sha512-1KYqwbJV3Co03NIi14uEHW8P50Md6KqFgt0FfpHdK6oyAHQVTosgPuPSiWud1HX0oYJ1hGRRlk0fP87jFpqXZA==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +    dev: true + +  /@babel/plugin-transform-shorthand-properties/7.16.7_@babel+core@7.18.2: +    resolution: {integrity: sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +    dev: true + +  /@babel/plugin-transform-spread/7.17.12_@babel+core@7.18.2: +    resolution: {integrity: sha512-9pgmuQAtFi3lpNUstvG9nGfk9DkrdmWNp9KeKPFmuZCpEnxRzYlS8JgwPjYj+1AWDOSvoGN0H30p1cBOmT/Svg==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +      '@babel/helper-skip-transparent-expression-wrappers': 7.16.0 +    dev: true + +  /@babel/plugin-transform-sticky-regex/7.16.7_@babel+core@7.18.2: +    resolution: {integrity: sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +    dev: true + +  /@babel/plugin-transform-template-literals/7.18.2_@babel+core@7.18.2: +    resolution: {integrity: sha512-/cmuBVw9sZBGZVOMkpAEaVLwm4JmK2GZ1dFKOGGpMzEHWFmyZZ59lUU0PdRr8YNYeQdNzTDwuxP2X2gzydTc9g==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +    dev: true + +  /@babel/plugin-transform-typeof-symbol/7.17.12_@babel+core@7.18.2: +    resolution: {integrity: sha512-Q8y+Jp7ZdtSPXCThB6zjQ74N3lj0f6TDh1Hnf5B+sYlzQ8i5Pjp8gW0My79iekSpT4WnI06blqP6DT0OmaXXmw==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +    dev: true + +  /@babel/plugin-transform-unicode-escapes/7.16.7_@babel+core@7.18.2: +    resolution: {integrity: sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +    dev: true + +  /@babel/plugin-transform-unicode-regex/7.16.7_@babel+core@7.18.2: +    resolution: {integrity: sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-create-regexp-features-plugin': 7.17.12_@babel+core@7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +    dev: true + +  /@babel/preset-env/7.18.2_@babel+core@7.18.2: +    resolution: {integrity: sha512-PfpdxotV6afmXMU47S08F9ZKIm2bJIQ0YbAAtDfIENX7G1NUAXigLREh69CWDjtgUy7dYn7bsMzkgdtAlmS68Q==} +    engines: {node: '>=6.9.0'} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/compat-data': 7.17.10 +      '@babel/core': 7.18.2 +      '@babel/helper-compilation-targets': 7.18.2_@babel+core@7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +      '@babel/helper-validator-option': 7.16.7 +      '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.17.12_@babel+core@7.18.2 +      '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.17.12_@babel+core@7.18.2 +      '@babel/plugin-proposal-async-generator-functions': 7.17.12_@babel+core@7.18.2 +      '@babel/plugin-proposal-class-properties': 7.17.12_@babel+core@7.18.2 +      '@babel/plugin-proposal-class-static-block': 7.18.0_@babel+core@7.18.2 +      '@babel/plugin-proposal-dynamic-import': 7.16.7_@babel+core@7.18.2 +      '@babel/plugin-proposal-export-namespace-from': 7.17.12_@babel+core@7.18.2 +      '@babel/plugin-proposal-json-strings': 7.17.12_@babel+core@7.18.2 +      '@babel/plugin-proposal-logical-assignment-operators': 7.17.12_@babel+core@7.18.2 +      '@babel/plugin-proposal-nullish-coalescing-operator': 7.17.12_@babel+core@7.18.2 +      '@babel/plugin-proposal-numeric-separator': 7.16.7_@babel+core@7.18.2 +      '@babel/plugin-proposal-object-rest-spread': 7.18.0_@babel+core@7.18.2 +      '@babel/plugin-proposal-optional-catch-binding': 7.16.7_@babel+core@7.18.2 +      '@babel/plugin-proposal-optional-chaining': 7.17.12_@babel+core@7.18.2 +      '@babel/plugin-proposal-private-methods': 7.17.12_@babel+core@7.18.2 +      '@babel/plugin-proposal-private-property-in-object': 7.17.12_@babel+core@7.18.2 +      '@babel/plugin-proposal-unicode-property-regex': 7.17.12_@babel+core@7.18.2 +      '@babel/plugin-syntax-async-generators': 7.8.4_@babel+core@7.18.2 +      '@babel/plugin-syntax-class-properties': 7.12.13_@babel+core@7.18.2 +      '@babel/plugin-syntax-class-static-block': 7.14.5_@babel+core@7.18.2 +      '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.18.2 +      '@babel/plugin-syntax-export-namespace-from': 7.8.3_@babel+core@7.18.2 +      '@babel/plugin-syntax-import-assertions': 7.17.12_@babel+core@7.18.2 +      '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.18.2 +      '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.18.2 +      '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3_@babel+core@7.18.2 +      '@babel/plugin-syntax-numeric-separator': 7.10.4_@babel+core@7.18.2 +      '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.18.2 +      '@babel/plugin-syntax-optional-catch-binding': 7.8.3_@babel+core@7.18.2 +      '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.18.2 +      '@babel/plugin-syntax-private-property-in-object': 7.14.5_@babel+core@7.18.2 +      '@babel/plugin-syntax-top-level-await': 7.14.5_@babel+core@7.18.2 +      '@babel/plugin-transform-arrow-functions': 7.17.12_@babel+core@7.18.2 +      '@babel/plugin-transform-async-to-generator': 7.17.12_@babel+core@7.18.2 +      '@babel/plugin-transform-block-scoped-functions': 7.16.7_@babel+core@7.18.2 +      '@babel/plugin-transform-block-scoping': 7.18.4_@babel+core@7.18.2 +      '@babel/plugin-transform-classes': 7.18.4_@babel+core@7.18.2 +      '@babel/plugin-transform-computed-properties': 7.17.12_@babel+core@7.18.2 +      '@babel/plugin-transform-destructuring': 7.18.0_@babel+core@7.18.2 +      '@babel/plugin-transform-dotall-regex': 7.16.7_@babel+core@7.18.2 +      '@babel/plugin-transform-duplicate-keys': 7.17.12_@babel+core@7.18.2 +      '@babel/plugin-transform-exponentiation-operator': 7.16.7_@babel+core@7.18.2 +      '@babel/plugin-transform-for-of': 7.18.1_@babel+core@7.18.2 +      '@babel/plugin-transform-function-name': 7.16.7_@babel+core@7.18.2 +      '@babel/plugin-transform-literals': 7.17.12_@babel+core@7.18.2 +      '@babel/plugin-transform-member-expression-literals': 7.16.7_@babel+core@7.18.2 +      '@babel/plugin-transform-modules-amd': 7.18.0_@babel+core@7.18.2 +      '@babel/plugin-transform-modules-commonjs': 7.18.2_@babel+core@7.18.2 +      '@babel/plugin-transform-modules-systemjs': 7.18.4_@babel+core@7.18.2 +      '@babel/plugin-transform-modules-umd': 7.18.0_@babel+core@7.18.2 +      '@babel/plugin-transform-named-capturing-groups-regex': 7.17.12_@babel+core@7.18.2 +      '@babel/plugin-transform-new-target': 7.17.12_@babel+core@7.18.2 +      '@babel/plugin-transform-object-super': 7.16.7_@babel+core@7.18.2 +      '@babel/plugin-transform-parameters': 7.17.12_@babel+core@7.18.2 +      '@babel/plugin-transform-property-literals': 7.16.7_@babel+core@7.18.2 +      '@babel/plugin-transform-regenerator': 7.18.0_@babel+core@7.18.2 +      '@babel/plugin-transform-reserved-words': 7.17.12_@babel+core@7.18.2 +      '@babel/plugin-transform-shorthand-properties': 7.16.7_@babel+core@7.18.2 +      '@babel/plugin-transform-spread': 7.17.12_@babel+core@7.18.2 +      '@babel/plugin-transform-sticky-regex': 7.16.7_@babel+core@7.18.2 +      '@babel/plugin-transform-template-literals': 7.18.2_@babel+core@7.18.2 +      '@babel/plugin-transform-typeof-symbol': 7.17.12_@babel+core@7.18.2 +      '@babel/plugin-transform-unicode-escapes': 7.16.7_@babel+core@7.18.2 +      '@babel/plugin-transform-unicode-regex': 7.16.7_@babel+core@7.18.2 +      '@babel/preset-modules': 0.1.5_@babel+core@7.18.2 +      '@babel/types': 7.18.4 +      babel-plugin-polyfill-corejs2: 0.3.1_@babel+core@7.18.2 +      babel-plugin-polyfill-corejs3: 0.5.2_@babel+core@7.18.2 +      babel-plugin-polyfill-regenerator: 0.3.1_@babel+core@7.18.2 +      core-js-compat: 3.22.8 +      semver: 6.3.0 +    transitivePeerDependencies: +      - supports-color +    dev: true + +  /@babel/preset-modules/0.1.5_@babel+core@7.18.2: +    resolution: {integrity: sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-plugin-utils': 7.17.12 +      '@babel/plugin-proposal-unicode-property-regex': 7.17.12_@babel+core@7.18.2 +      '@babel/plugin-transform-dotall-regex': 7.16.7_@babel+core@7.18.2 +      '@babel/types': 7.18.4 +      esutils: 2.0.3 +    dev: true + +  /@babel/runtime/7.18.3: +    resolution: {integrity: sha512-38Y8f7YUhce/K7RMwTp7m0uCumpv9hZkitCbBClqQIow1qSbCvGkcegKOXpEWCQLfWmevgRiWokZ1GkpfhbZug==} +    engines: {node: '>=6.9.0'} +    dependencies: +      regenerator-runtime: 0.13.9 +    dev: true + +  /@babel/template/7.16.7: +    resolution: {integrity: sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==} +    engines: {node: '>=6.9.0'} +    dependencies: +      '@babel/code-frame': 7.16.7 +      '@babel/parser': 7.18.4 +      '@babel/types': 7.18.4 +    dev: true + +  /@babel/traverse/7.18.2: +    resolution: {integrity: sha512-9eNwoeovJ6KH9zcCNnENY7DMFwTU9JdGCFtqNLfUAqtUHRCOsTOqWoffosP8vKmNYeSBUv3yVJXjfd8ucwOjUA==} +    engines: {node: '>=6.9.0'} +    dependencies: +      '@babel/code-frame': 7.16.7 +      '@babel/generator': 7.18.2 +      '@babel/helper-environment-visitor': 7.18.2 +      '@babel/helper-function-name': 7.17.9 +      '@babel/helper-hoist-variables': 7.16.7 +      '@babel/helper-split-export-declaration': 7.16.7 +      '@babel/parser': 7.18.4 +      '@babel/types': 7.18.4 +      debug: 4.3.4 +      globals: 11.12.0 +    transitivePeerDependencies: +      - supports-color +    dev: true + +  /@babel/types/7.18.4: +    resolution: {integrity: sha512-ThN1mBcMq5pG/Vm2IcBmPPfyPXbd8S02rS+OBIDENdufvqC7Z/jHPCv9IcP01277aKtDI8g/2XysBN4hA8niiw==} +    engines: {node: '>=6.9.0'} +    dependencies: +      '@babel/helper-validator-identifier': 7.16.7 +      to-fast-properties: 2.0.0 +    dev: true + +  /@csstools/selector-specificity/2.0.0_444rcjjorr3kpoqtvoodsr46pu: +    resolution: {integrity: sha512-rZ6vufeY/UjAgtyiJ4WvfF6XP6HizIyOfbZOg0RnecIwjrvH8Am3nN1BpKnnPZunYAkUcPPXDhwbxOtGop8cfQ==} +    engines: {node: ^12 || ^14 || >=16} +    peerDependencies: +      postcss: ^8.3 +      postcss-selector-parser: ^6.0.10 +    dependencies: +      postcss: 8.4.14 +      postcss-selector-parser: 6.0.10 +    dev: true + +  /@eslint/eslintrc/1.3.0: +    resolution: {integrity: sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==} +    engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} +    dependencies: +      ajv: 6.12.6 +      debug: 4.3.4 +      espree: 9.3.2 +      globals: 13.15.0 +      ignore: 5.2.0 +      import-fresh: 3.3.0 +      js-yaml: 4.1.0 +      minimatch: 3.1.2 +      strip-json-comments: 3.1.1 +    transitivePeerDependencies: +      - supports-color +    dev: true + +  /@fullhuman/postcss-purgecss/4.1.3_postcss@8.4.14: +    resolution: {integrity: sha512-jqcsyfvq09VOsMXxJMPLRF6Fhg/NNltzWKnC9qtzva+QKTxerCO4esG6je7hbnmkpZtaDyPTwMBj9bzfWorsrw==} +    peerDependencies: +      postcss: ^8.0.0 +    dependencies: +      postcss: 8.4.14 +      purgecss: 4.1.3 +    dev: true + +  /@humanwhocodes/config-array/0.9.5: +    resolution: {integrity: sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==} +    engines: {node: '>=10.10.0'} +    dependencies: +      '@humanwhocodes/object-schema': 1.2.1 +      debug: 4.3.4 +      minimatch: 3.1.2 +    transitivePeerDependencies: +      - supports-color +    dev: true + +  /@humanwhocodes/object-schema/1.2.1: +    resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} +    dev: true + +  /@jridgewell/gen-mapping/0.1.1: +    resolution: {integrity: sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==} +    engines: {node: '>=6.0.0'} +    dependencies: +      '@jridgewell/set-array': 1.1.1 +      '@jridgewell/sourcemap-codec': 1.4.13 +    dev: true + +  /@jridgewell/gen-mapping/0.3.1: +    resolution: {integrity: sha512-GcHwniMlA2z+WFPWuY8lp3fsza0I8xPFMWL5+n8LYyP6PSvPrXf4+n8stDHZY2DM0zy9sVkRDy1jDI4XGzYVqg==} +    engines: {node: '>=6.0.0'} +    dependencies: +      '@jridgewell/set-array': 1.1.1 +      '@jridgewell/sourcemap-codec': 1.4.13 +      '@jridgewell/trace-mapping': 0.3.13 +    dev: true + +  /@jridgewell/resolve-uri/3.0.7: +    resolution: {integrity: sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA==} +    engines: {node: '>=6.0.0'} +    dev: true + +  /@jridgewell/set-array/1.1.1: +    resolution: {integrity: sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ==} +    engines: {node: '>=6.0.0'} +    dev: true + +  /@jridgewell/sourcemap-codec/1.4.13: +    resolution: {integrity: sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==} +    dev: true + +  /@jridgewell/trace-mapping/0.3.13: +    resolution: {integrity: sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w==} +    dependencies: +      '@jridgewell/resolve-uri': 3.0.7 +      '@jridgewell/sourcemap-codec': 1.4.13 +    dev: true + +  /@nicolo-ribaudo/chokidar-2/2.1.8-no-fsevents.3: +    resolution: {integrity: sha512-s88O1aVtXftvp5bCPB7WnmXc5IwOZZ7YPuwNPt+GtOOXpPvad1LfbmjYv+qII7zP6RU2QGnqve27dnLycEnyEQ==} +    requiresBuild: true +    dev: true +    optional: true + +  /@nodelib/fs.scandir/2.1.5: +    resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} +    engines: {node: '>= 8'} +    dependencies: +      '@nodelib/fs.stat': 2.0.5 +      run-parallel: 1.2.0 +    dev: true + +  /@nodelib/fs.stat/2.0.5: +    resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} +    engines: {node: '>= 8'} +    dev: true + +  /@nodelib/fs.walk/1.2.8: +    resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} +    engines: {node: '>= 8'} +    dependencies: +      '@nodelib/fs.scandir': 2.1.5 +      fastq: 1.13.0 +    dev: true + +  /@sindresorhus/is/4.6.0: +    resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} +    engines: {node: '>=10'} +    dev: true + +  /@szmarczak/http-timer/4.0.6: +    resolution: {integrity: sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==} +    engines: {node: '>=10'} +    dependencies: +      defer-to-connect: 2.0.1 +    dev: true + +  /@types/cacheable-request/6.0.2: +    resolution: {integrity: sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==} +    dependencies: +      '@types/http-cache-semantics': 4.0.1 +      '@types/keyv': 3.1.4 +      '@types/node': 17.0.39 +      '@types/responselike': 1.0.0 +    dev: true + +  /@types/http-cache-semantics/4.0.1: +    resolution: {integrity: sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==} +    dev: true + +  /@types/json-buffer/3.0.0: +    resolution: {integrity: sha512-3YP80IxxFJB4b5tYC2SUPwkg0XQLiu0nWvhRgEatgjf+29IcWO9X1k8xRv5DGssJ/lCrjYTjQPcobJr2yWIVuQ==} +    dev: true + +  /@types/keyv/3.1.4: +    resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} +    dependencies: +      '@types/node': 17.0.39 +    dev: true + +  /@types/minimist/1.2.2: +    resolution: {integrity: sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==} +    dev: true + +  /@types/node/17.0.39: +    resolution: {integrity: sha512-JDU3YLlnPK3WDao6/DlXLOgSNpG13ct+CwIO17V8q0/9fWJyeMJJ/VyZ1lv8kDprihvZMydzVwf0tQOqGiY2Nw==} +    dev: true + +  /@types/normalize-package-data/2.4.1: +    resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} +    dev: true + +  /@types/parse-json/4.0.0: +    resolution: {integrity: sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==} +    dev: true + +  /@types/responselike/1.0.0: +    resolution: {integrity: sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==} +    dependencies: +      '@types/node': 17.0.39 +    dev: true + +  /acorn-jsx/5.3.2_acorn@8.7.1: +    resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} +    peerDependencies: +      acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 +    dependencies: +      acorn: 8.7.1 +    dev: true + +  /acorn/8.7.1: +    resolution: {integrity: sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==} +    engines: {node: '>=0.4.0'} +    hasBin: true +    dev: true + +  /aggregate-error/3.1.0: +    resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} +    engines: {node: '>=8'} +    dependencies: +      clean-stack: 2.2.0 +      indent-string: 4.0.0 +    dev: true + +  /ajv/6.12.6: +    resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} +    dependencies: +      fast-deep-equal: 3.1.3 +      fast-json-stable-stringify: 2.1.0 +      json-schema-traverse: 0.4.1 +      uri-js: 4.4.1 +    dev: true + +  /ajv/8.11.0: +    resolution: {integrity: sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==} +    dependencies: +      fast-deep-equal: 3.1.3 +      json-schema-traverse: 1.0.0 +      require-from-string: 2.0.2 +      uri-js: 4.4.1 +    dev: true + +  /ansi-regex/5.0.1: +    resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} +    engines: {node: '>=8'} +    dev: true + +  /ansi-styles/3.2.1: +    resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} +    engines: {node: '>=4'} +    dependencies: +      color-convert: 1.9.3 +    dev: true + +  /ansi-styles/4.3.0: +    resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} +    engines: {node: '>=8'} +    dependencies: +      color-convert: 2.0.1 +    dev: true + +  /anymatch/3.1.2: +    resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==} +    engines: {node: '>= 8'} +    dependencies: +      normalize-path: 3.0.0 +      picomatch: 2.3.1 +    dev: true + +  /argparse/2.0.1: +    resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} +    dev: true + +  /array-union/2.1.0: +    resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} +    engines: {node: '>=8'} +    dev: true + +  /array-union/3.0.1: +    resolution: {integrity: sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw==} +    engines: {node: '>=12'} +    dev: true + +  /arrify/1.0.1: +    resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} +    engines: {node: '>=0.10.0'} +    dev: true + +  /astral-regex/2.0.0: +    resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} +    engines: {node: '>=8'} +    dev: true + +  /auto-changelog/2.4.0: +    resolution: {integrity: sha512-vh17hko1c0ItsEcw6m7qPRf3m45u+XK5QyCrrBFViElZ8jnKrPC1roSznrd1fIB/0vR/zawdECCRJtTuqIXaJw==} +    engines: {node: '>=8.3'} +    hasBin: true +    dependencies: +      commander: 7.2.0 +      handlebars: 4.7.7 +      node-fetch: 2.6.7 +      parse-github-url: 1.0.2 +      semver: 7.3.7 +    transitivePeerDependencies: +      - encoding +    dev: true + +  /autoprefixer/10.4.7_postcss@8.4.14: +    resolution: {integrity: sha512-ypHju4Y2Oav95SipEcCcI5J7CGPuvz8oat7sUtYj3ClK44bldfvtvcxK6IEK++7rqB7YchDGzweZIBG+SD0ZAA==} +    engines: {node: ^10 || ^12 || >=14} +    hasBin: true +    peerDependencies: +      postcss: ^8.1.0 +    dependencies: +      browserslist: 4.20.3 +      caniuse-lite: 1.0.30001346 +      fraction.js: 4.2.0 +      normalize-range: 0.1.2 +      picocolors: 1.0.0 +      postcss: 8.4.14 +      postcss-value-parser: 4.2.0 +    dev: true + +  /babel-plugin-dynamic-import-node/2.3.3: +    resolution: {integrity: sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==} +    dependencies: +      object.assign: 4.1.2 +    dev: true + +  /babel-plugin-polyfill-corejs2/0.3.1_@babel+core@7.18.2: +    resolution: {integrity: sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w==} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/compat-data': 7.17.10 +      '@babel/core': 7.18.2 +      '@babel/helper-define-polyfill-provider': 0.3.1_@babel+core@7.18.2 +      semver: 6.3.0 +    transitivePeerDependencies: +      - supports-color +    dev: true + +  /babel-plugin-polyfill-corejs3/0.5.2_@babel+core@7.18.2: +    resolution: {integrity: sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ==} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-define-polyfill-provider': 0.3.1_@babel+core@7.18.2 +      core-js-compat: 3.22.8 +    transitivePeerDependencies: +      - supports-color +    dev: true + +  /babel-plugin-polyfill-regenerator/0.3.1_@babel+core@7.18.2: +    resolution: {integrity: sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==} +    peerDependencies: +      '@babel/core': ^7.0.0-0 +    dependencies: +      '@babel/core': 7.18.2 +      '@babel/helper-define-polyfill-provider': 0.3.1_@babel+core@7.18.2 +    transitivePeerDependencies: +      - supports-color +    dev: true + +  /balanced-match/1.0.2: +    resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} +    dev: true + +  /balanced-match/2.0.0: +    resolution: {integrity: sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==} +    dev: true + +  /base64-js/1.5.1: +    resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} +    dev: true + +  /binary-extensions/2.2.0: +    resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} +    engines: {node: '>=8'} +    dev: true + +  /bl/1.2.3: +    resolution: {integrity: sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==} +    dependencies: +      readable-stream: 2.3.7 +      safe-buffer: 5.2.1 +    dev: true + +  /bootstrap-icons/1.8.3: +    resolution: {integrity: sha512-s5kmttnbq4BXbx3Bwnj39y+t7Vc3blTtyD77W3aYQ1LlNoS3lNbbGvSYhIbg26Im8KmjScyFpHEevlPOBcIDdA==} +    dev: true + +  /bootstrap/5.1.3: +    resolution: {integrity: sha512-fcQztozJ8jToQWXxVuEyXWW+dSo8AiXWKwiSSrKWsRB/Qt+Ewwza+JWoLKiTuQLaEPhdNAJ7+Dosc9DOIqNy7Q==} +    peerDependencies: +      '@popperjs/core': ^2.10.2 +    dev: true + +  /brace-expansion/1.1.11: +    resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} +    dependencies: +      balanced-match: 1.0.2 +      concat-map: 0.0.1 +    dev: true + +  /braces/3.0.2: +    resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} +    engines: {node: '>=8'} +    dependencies: +      fill-range: 7.0.1 +    dev: true + +  /browserslist/4.20.3: +    resolution: {integrity: sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg==} +    engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} +    hasBin: true +    dependencies: +      caniuse-lite: 1.0.30001346 +      electron-to-chromium: 1.4.146 +      escalade: 3.1.1 +      node-releases: 2.0.5 +      picocolors: 1.0.0 +    dev: true + +  /buffer-alloc-unsafe/1.1.0: +    resolution: {integrity: sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==} +    dev: true + +  /buffer-alloc/1.2.0: +    resolution: {integrity: sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==} +    dependencies: +      buffer-alloc-unsafe: 1.1.0 +      buffer-fill: 1.0.0 +    dev: true + +  /buffer-crc32/0.2.13: +    resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} +    dev: true + +  /buffer-fill/1.0.0: +    resolution: {integrity: sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==} +    dev: true + +  /buffer/5.7.1: +    resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} +    dependencies: +      base64-js: 1.5.1 +      ieee754: 1.2.1 +    dev: true + +  /cacheable-lookup/5.0.4: +    resolution: {integrity: sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==} +    engines: {node: '>=10.6.0'} +    dev: true + +  /cacheable-request/7.0.2: +    resolution: {integrity: sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==} +    engines: {node: '>=8'} +    dependencies: +      clone-response: 1.0.2 +      get-stream: 5.2.0 +      http-cache-semantics: 4.1.0 +      keyv: 4.3.0 +      lowercase-keys: 2.0.0 +      normalize-url: 6.1.0 +      responselike: 2.0.0 +    dev: true + +  /call-bind/1.0.2: +    resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} +    dependencies: +      function-bind: 1.1.1 +      get-intrinsic: 1.1.1 +    dev: true + +  /callsites/3.1.0: +    resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} +    engines: {node: '>=6'} +    dev: true + +  /camelcase-keys/6.2.2: +    resolution: {integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==} +    engines: {node: '>=8'} +    dependencies: +      camelcase: 5.3.1 +      map-obj: 4.3.0 +      quick-lru: 4.0.1 +    dev: true + +  /camelcase/5.3.1: +    resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} +    engines: {node: '>=6'} +    dev: true + +  /caniuse-lite/1.0.30001346: +    resolution: {integrity: sha512-q6ibZUO2t88QCIPayP/euuDREq+aMAxFE5S70PkrLh0iTDj/zEhgvJRKC2+CvXY6EWc6oQwUR48lL5vCW6jiXQ==} +    dev: true + +  /chalk/2.4.2: +    resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} +    engines: {node: '>=4'} +    dependencies: +      ansi-styles: 3.2.1 +      escape-string-regexp: 1.0.5 +      supports-color: 5.5.0 +    dev: true + +  /chalk/4.1.2: +    resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} +    engines: {node: '>=10'} +    dependencies: +      ansi-styles: 4.3.0 +      supports-color: 7.2.0 +    dev: true + +  /chokidar/3.5.3: +    resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} +    engines: {node: '>= 8.10.0'} +    dependencies: +      anymatch: 3.1.2 +      braces: 3.0.2 +      glob-parent: 5.1.2 +      is-binary-path: 2.1.0 +      is-glob: 4.0.3 +      normalize-path: 3.0.0 +      readdirp: 3.6.0 +    optionalDependencies: +      fsevents: 2.3.2 +    dev: true + +  /clean-stack/2.2.0: +    resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} +    engines: {node: '>=6'} +    dev: true + +  /clipboard/2.0.11: +    resolution: {integrity: sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==} +    dependencies: +      good-listener: 1.2.2 +      select: 1.1.2 +      tiny-emitter: 2.1.0 +    dev: true + +  /cliui/6.0.0: +    resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} +    dependencies: +      string-width: 4.2.3 +      strip-ansi: 6.0.1 +      wrap-ansi: 6.2.0 +    dev: true + +  /cliui/7.0.4: +    resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} +    dependencies: +      string-width: 4.2.3 +      strip-ansi: 6.0.1 +      wrap-ansi: 7.0.0 +    dev: true + +  /clone-regexp/2.2.0: +    resolution: {integrity: sha512-beMpP7BOtTipFuW8hrJvREQ2DrRu3BE7by0ZpibtfBA+qfHYvMGTc2Yb1JMYPKg/JUw0CHYvpg796aNTSW9z7Q==} +    engines: {node: '>=6'} +    dependencies: +      is-regexp: 2.1.0 +    dev: true + +  /clone-response/1.0.2: +    resolution: {integrity: sha512-yjLXh88P599UOyPTFX0POsd7WxnbsVsGohcwzHOLspIhhpalPw1BcqED8NblyZLKcGrL8dTgMlcaZxV2jAD41Q==} +    dependencies: +      mimic-response: 1.0.1 +    dev: true + +  /color-convert/1.9.3: +    resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} +    dependencies: +      color-name: 1.1.3 +    dev: true + +  /color-convert/2.0.1: +    resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} +    engines: {node: '>=7.0.0'} +    dependencies: +      color-name: 1.1.4 +    dev: true + +  /color-name/1.1.3: +    resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} +    dev: true + +  /color-name/1.1.4: +    resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} +    dev: true + +  /colord/2.9.2: +    resolution: {integrity: sha512-Uqbg+J445nc1TKn4FoDPS6ZZqAvEDnwrH42yo8B40JSOgSLxMZ/gt3h4nmCtPLQeXhjJJkqBx7SCY35WnIixaQ==} +    dev: true + +  /commander/2.20.3: +    resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} +    dev: true + +  /commander/4.1.1: +    resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} +    engines: {node: '>= 6'} +    dev: true + +  /commander/7.2.0: +    resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} +    engines: {node: '>= 10'} +    dev: true + +  /commander/8.3.0: +    resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} +    engines: {node: '>= 12'} +    dev: true + +  /compress-brotli/1.3.8: +    resolution: {integrity: sha512-lVcQsjhxhIXsuupfy9fmZUFtAIdBmXA7EGY6GBdgZ++qkM9zG4YFT8iU7FoBxzryNDMOpD1HIFHUSX4D87oqhQ==} +    engines: {node: '>= 12'} +    dependencies: +      '@types/json-buffer': 3.0.0 +      json-buffer: 3.0.1 +    dev: true + +  /concat-map/0.0.1: +    resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} +    dev: true + +  /convert-source-map/1.8.0: +    resolution: {integrity: sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==} +    dependencies: +      safe-buffer: 5.1.2 +    dev: true + +  /core-js-compat/3.22.8: +    resolution: {integrity: sha512-pQnwg4xtuvc2Bs/5zYQPaEYYSuTxsF7LBWF0SvnVhthZo/Qe+rJpcEekrdNK5DWwDJ0gv0oI9NNX5Mppdy0ctg==} +    dependencies: +      browserslist: 4.20.3 +      semver: 7.0.0 +    dev: true + +  /core-util-is/1.0.3: +    resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} +    dev: true + +  /cosmiconfig/7.0.1: +    resolution: {integrity: sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==} +    engines: {node: '>=10'} +    dependencies: +      '@types/parse-json': 4.0.0 +      import-fresh: 3.3.0 +      parse-json: 5.2.0 +      path-type: 4.0.0 +      yaml: 1.10.2 +    dev: true + +  /cross-spawn/7.0.3: +    resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} +    engines: {node: '>= 8'} +    dependencies: +      path-key: 3.1.1 +      shebang-command: 2.0.0 +      which: 2.0.2 +    dev: true + +  /css-functions-list/3.1.0: +    resolution: {integrity: sha512-/9lCvYZaUbBGvYUgYGFJ4dcYiyqdhSjG7IPVluoV8A1ILjkF7ilmhp1OGUz8n+nmBcu0RNrQAzgD8B6FJbrt2w==} +    engines: {node: '>=12.22'} +    dev: true + +  /cssesc/3.0.0: +    resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} +    engines: {node: '>=4'} +    hasBin: true +    dev: true + +  /data-uri-to-buffer/4.0.0: +    resolution: {integrity: sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==} +    engines: {node: '>= 12'} +    dev: true + +  /debug/4.3.4: +    resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} +    engines: {node: '>=6.0'} +    peerDependencies: +      supports-color: '*' +    peerDependenciesMeta: +      supports-color: +        optional: true +    dependencies: +      ms: 2.1.2 +    dev: true + +  /decamelize-keys/1.1.0: +    resolution: {integrity: sha512-ocLWuYzRPoS9bfiSdDd3cxvrzovVMZnRDVEzAs+hWIVXGDbHxWMECij2OBuyB/An0FFW/nLuq6Kv1i/YC5Qfzg==} +    engines: {node: '>=0.10.0'} +    dependencies: +      decamelize: 1.2.0 +      map-obj: 1.0.1 +    dev: true + +  /decamelize/1.2.0: +    resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} +    engines: {node: '>=0.10.0'} +    dev: true + +  /decompress-response/6.0.0: +    resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} +    engines: {node: '>=10'} +    dependencies: +      mimic-response: 3.1.0 +    dev: true + +  /decompress-tar/4.1.1: +    resolution: {integrity: sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==} +    engines: {node: '>=4'} +    dependencies: +      file-type: 5.2.0 +      is-stream: 1.1.0 +      tar-stream: 1.6.2 +    dev: true + +  /decompress-tarbz2/4.1.1: +    resolution: {integrity: sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==} +    engines: {node: '>=4'} +    dependencies: +      decompress-tar: 4.1.1 +      file-type: 6.2.0 +      is-stream: 1.1.0 +      seek-bzip: 1.0.6 +      unbzip2-stream: 1.4.3 +    dev: true + +  /decompress-targz/4.1.1: +    resolution: {integrity: sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==} +    engines: {node: '>=4'} +    dependencies: +      decompress-tar: 4.1.1 +      file-type: 5.2.0 +      is-stream: 1.1.0 +    dev: true + +  /decompress-unzip/4.0.1: +    resolution: {integrity: sha512-1fqeluvxgnn86MOh66u8FjbtJpAFv5wgCT9Iw8rcBqQcCo5tO8eiJw7NNTrvt9n4CRBVq7CstiS922oPgyGLrw==} +    engines: {node: '>=4'} +    dependencies: +      file-type: 3.9.0 +      get-stream: 2.3.1 +      pify: 2.3.0 +      yauzl: 2.10.0 +    dev: true + +  /decompress/4.2.1: +    resolution: {integrity: sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ==} +    engines: {node: '>=4'} +    dependencies: +      decompress-tar: 4.1.1 +      decompress-tarbz2: 4.1.1 +      decompress-targz: 4.1.1 +      decompress-unzip: 4.0.1 +      graceful-fs: 4.2.10 +      make-dir: 1.3.0 +      pify: 2.3.0 +      strip-dirs: 2.1.0 +    dev: true + +  /deep-is/0.1.4: +    resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} +    dev: true + +  /defer-to-connect/2.0.1: +    resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} +    engines: {node: '>=10'} +    dev: true + +  /define-properties/1.1.4: +    resolution: {integrity: sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==} +    engines: {node: '>= 0.4'} +    dependencies: +      has-property-descriptors: 1.0.0 +      object-keys: 1.1.1 +    dev: true + +  /del/6.0.0: +    resolution: {integrity: sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==} +    engines: {node: '>=10'} +    dependencies: +      globby: 11.1.0 +      graceful-fs: 4.2.10 +      is-glob: 4.0.3 +      is-path-cwd: 2.2.0 +      is-path-inside: 3.0.3 +      p-map: 4.0.0 +      rimraf: 3.0.2 +      slash: 3.0.0 +    dev: true + +  /delegate/3.2.0: +    resolution: {integrity: sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==} +    dev: true + +  /dependency-graph/0.11.0: +    resolution: {integrity: sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==} +    engines: {node: '>= 0.6.0'} +    dev: true + +  /dir-glob/3.0.1: +    resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} +    engines: {node: '>=8'} +    dependencies: +      path-type: 4.0.0 +    dev: true + +  /doctrine/3.0.0: +    resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} +    engines: {node: '>=6.0.0'} +    dependencies: +      esutils: 2.0.3 +    dev: true + +  /electron-to-chromium/1.4.146: +    resolution: {integrity: sha512-4eWebzDLd+hYLm4csbyMU2EbBnqhwl8Oe9eF/7CBDPWcRxFmqzx4izxvHH+lofQxzieg8UbB8ZuzNTxeukzfTg==} +    dev: true + +  /emoji-regex/8.0.0: +    resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} +    dev: true + +  /end-of-stream/1.4.4: +    resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} +    dependencies: +      once: 1.4.0 +    dev: true + +  /entities/2.1.0: +    resolution: {integrity: sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==} +    dev: true + +  /error-ex/1.3.2: +    resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} +    dependencies: +      is-arrayish: 0.2.1 +    dev: true + +  /escalade/3.1.1: +    resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} +    engines: {node: '>=6'} +    dev: true + +  /escape-string-regexp/1.0.5: +    resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} +    engines: {node: '>=0.8.0'} +    dev: true + +  /escape-string-regexp/4.0.0: +    resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} +    engines: {node: '>=10'} +    dev: true + +  /eslint-scope/7.1.1: +    resolution: {integrity: sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==} +    engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} +    dependencies: +      esrecurse: 4.3.0 +      estraverse: 5.3.0 +    dev: true + +  /eslint-utils/3.0.0_eslint@8.17.0: +    resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} +    engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} +    peerDependencies: +      eslint: '>=5' +    dependencies: +      eslint: 8.17.0 +      eslint-visitor-keys: 2.1.0 +    dev: true + +  /eslint-visitor-keys/2.1.0: +    resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} +    engines: {node: '>=10'} +    dev: true + +  /eslint-visitor-keys/3.3.0: +    resolution: {integrity: sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==} +    engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} +    dev: true + +  /eslint/8.17.0: +    resolution: {integrity: sha512-gq0m0BTJfci60Fz4nczYxNAlED+sMcihltndR8t9t1evnU/azx53x3t2UHXC/uRjcbvRw/XctpaNygSTcQD+Iw==} +    engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} +    hasBin: true +    dependencies: +      '@eslint/eslintrc': 1.3.0 +      '@humanwhocodes/config-array': 0.9.5 +      ajv: 6.12.6 +      chalk: 4.1.2 +      cross-spawn: 7.0.3 +      debug: 4.3.4 +      doctrine: 3.0.0 +      escape-string-regexp: 4.0.0 +      eslint-scope: 7.1.1 +      eslint-utils: 3.0.0_eslint@8.17.0 +      eslint-visitor-keys: 3.3.0 +      espree: 9.3.2 +      esquery: 1.4.0 +      esutils: 2.0.3 +      fast-deep-equal: 3.1.3 +      file-entry-cache: 6.0.1 +      functional-red-black-tree: 1.0.1 +      glob-parent: 6.0.2 +      globals: 13.15.0 +      ignore: 5.2.0 +      import-fresh: 3.3.0 +      imurmurhash: 0.1.4 +      is-glob: 4.0.3 +      js-yaml: 4.1.0 +      json-stable-stringify-without-jsonify: 1.0.1 +      levn: 0.4.1 +      lodash.merge: 4.6.2 +      minimatch: 3.1.2 +      natural-compare: 1.4.0 +      optionator: 0.9.1 +      regexpp: 3.2.0 +      strip-ansi: 6.0.1 +      strip-json-comments: 3.1.1 +      text-table: 0.2.0 +      v8-compile-cache: 2.3.0 +    transitivePeerDependencies: +      - supports-color +    dev: true + +  /espree/9.3.2: +    resolution: {integrity: sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==} +    engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} +    dependencies: +      acorn: 8.7.1 +      acorn-jsx: 5.3.2_acorn@8.7.1 +      eslint-visitor-keys: 3.3.0 +    dev: true + +  /esquery/1.4.0: +    resolution: {integrity: sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==} +    engines: {node: '>=0.10'} +    dependencies: +      estraverse: 5.3.0 +    dev: true + +  /esrecurse/4.3.0: +    resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} +    engines: {node: '>=4.0'} +    dependencies: +      estraverse: 5.3.0 +    dev: true + +  /estraverse/5.3.0: +    resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} +    engines: {node: '>=4.0'} +    dev: true + +  /esutils/2.0.3: +    resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} +    engines: {node: '>=0.10.0'} +    dev: true + +  /exec-bin/1.0.0: +    resolution: {integrity: sha512-p8f8h8b6op2nR7U5rsd+zACUMfsfB+jW8HNIBD2njOQ/gF2WvBfQRo/OU6Q6f/b34WLAyePZcwMJyrDdEjB/fw==} +    hasBin: true +    dev: true + +  /execall/2.0.0: +    resolution: {integrity: sha512-0FU2hZ5Hh6iQnarpRtQurM/aAvp3RIbfvgLHrcqJYzhXyV2KFruhuChf9NC6waAhiUR7FFtlugkI4p7f2Fqlow==} +    engines: {node: '>=8'} +    dependencies: +      clone-regexp: 2.2.0 +    dev: true + +  /fast-deep-equal/3.1.3: +    resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} +    dev: true + +  /fast-glob/3.2.11: +    resolution: {integrity: sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==} +    engines: {node: '>=8.6.0'} +    dependencies: +      '@nodelib/fs.stat': 2.0.5 +      '@nodelib/fs.walk': 1.2.8 +      glob-parent: 5.1.2 +      merge2: 1.4.1 +      micromatch: 4.0.5 +    dev: true + +  /fast-json-stable-stringify/2.1.0: +    resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} +    dev: true + +  /fast-levenshtein/2.0.6: +    resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} +    dev: true + +  /fastest-levenshtein/1.0.12: +    resolution: {integrity: sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==} +    dev: true + +  /fastq/1.13.0: +    resolution: {integrity: sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==} +    dependencies: +      reusify: 1.0.4 +    dev: true + +  /fd-slicer/1.1.0: +    resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} +    dependencies: +      pend: 1.2.0 +    dev: true + +  /fetch-blob/3.1.5: +    resolution: {integrity: sha512-N64ZpKqoLejlrwkIAnb9iLSA3Vx/kjgzpcDhygcqJ2KKjky8nCgUQ+dzXtbrLaWZGZNmNfQTsiQ0weZ1svglHg==} +    engines: {node: ^12.20 || >= 14.13} +    dependencies: +      node-domexception: 1.0.0 +      web-streams-polyfill: 3.2.1 +    dev: true + +  /file-entry-cache/6.0.1: +    resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} +    engines: {node: ^10.12.0 || >=12.0.0} +    dependencies: +      flat-cache: 3.0.4 +    dev: true + +  /file-type/3.9.0: +    resolution: {integrity: sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==} +    engines: {node: '>=0.10.0'} +    dev: true + +  /file-type/5.2.0: +    resolution: {integrity: sha512-Iq1nJ6D2+yIO4c8HHg4fyVb8mAJieo1Oloy1mLLaB2PvezNedhBVm+QU7g0qM42aiMbRXTxKKwGD17rjKNJYVQ==} +    engines: {node: '>=4'} +    dev: true + +  /file-type/6.2.0: +    resolution: {integrity: sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==} +    engines: {node: '>=4'} +    dev: true + +  /fill-range/7.0.1: +    resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} +    engines: {node: '>=8'} +    dependencies: +      to-regex-range: 5.0.1 +    dev: true + +  /find-up/4.1.0: +    resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} +    engines: {node: '>=8'} +    dependencies: +      locate-path: 5.0.0 +      path-exists: 4.0.0 +    dev: true + +  /flat-cache/3.0.4: +    resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} +    engines: {node: ^10.12.0 || >=12.0.0} +    dependencies: +      flatted: 3.2.5 +      rimraf: 3.0.2 +    dev: true + +  /flatted/3.2.5: +    resolution: {integrity: sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==} +    dev: true + +  /flexsearch/0.7.21: +    resolution: {integrity: sha512-W7cHV7Hrwjid6lWmy0IhsWDFQboWSng25U3VVywpHOTJnnAZNPScog67G+cVpeX9f7yDD21ih0WDrMMT+JoaYg==} +    dev: true + +  /formdata-polyfill/4.0.10: +    resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} +    engines: {node: '>=12.20.0'} +    dependencies: +      fetch-blob: 3.1.5 +    dev: true + +  /fraction.js/4.2.0: +    resolution: {integrity: sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==} +    dev: true + +  /fs-constants/1.0.0: +    resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} +    dev: true + +  /fs-extra/10.1.0: +    resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} +    engines: {node: '>=12'} +    dependencies: +      graceful-fs: 4.2.10 +      jsonfile: 6.1.0 +      universalify: 2.0.0 +    dev: true + +  /fs-readdir-recursive/1.1.0: +    resolution: {integrity: sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==} +    dev: true + +  /fs.realpath/1.0.0: +    resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} +    dev: true + +  /fsevents/2.3.2: +    resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} +    engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} +    os: [darwin] +    requiresBuild: true +    dev: true +    optional: true + +  /function-bind/1.1.1: +    resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} +    dev: true + +  /functional-red-black-tree/1.0.1: +    resolution: {integrity: sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==} +    dev: true + +  /gensync/1.0.0-beta.2: +    resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} +    engines: {node: '>=6.9.0'} +    dev: true + +  /get-caller-file/2.0.5: +    resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} +    engines: {node: 6.* || 8.* || >= 10.*} +    dev: true + +  /get-intrinsic/1.1.1: +    resolution: {integrity: sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==} +    dependencies: +      function-bind: 1.1.1 +      has: 1.0.3 +      has-symbols: 1.0.3 +    dev: true + +  /get-stdin/8.0.0: +    resolution: {integrity: sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==} +    engines: {node: '>=10'} +    dev: true + +  /get-stdin/9.0.0: +    resolution: {integrity: sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==} +    engines: {node: '>=12'} +    dev: true + +  /get-stream/2.3.1: +    resolution: {integrity: sha512-AUGhbbemXxrZJRD5cDvKtQxLuYaIbNtDTK8YqupCI393Q2KSTreEsLUN3ZxAWFGiKTzL6nKuzfcIvieflUX9qA==} +    engines: {node: '>=0.10.0'} +    dependencies: +      object-assign: 4.1.1 +      pinkie-promise: 2.0.1 +    dev: true + +  /get-stream/5.2.0: +    resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} +    engines: {node: '>=8'} +    dependencies: +      pump: 3.0.0 +    dev: true + +  /glob-all/3.3.0: +    resolution: {integrity: sha512-30gCh9beSb+YSAh0vsoIlBRm4bSlyMa+5nayax1EJhjwYrCohX0aDxcxvWVe3heOrJikbHgRs75Af6kPLcumew==} +    hasBin: true +    dependencies: +      glob: 7.2.3 +      yargs: 15.4.1 +    dev: true + +  /glob-parent/5.1.2: +    resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} +    engines: {node: '>= 6'} +    dependencies: +      is-glob: 4.0.3 +    dev: true + +  /glob-parent/6.0.2: +    resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} +    engines: {node: '>=10.13.0'} +    dependencies: +      is-glob: 4.0.3 +    dev: true + +  /glob/7.2.3: +    resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} +    dependencies: +      fs.realpath: 1.0.0 +      inflight: 1.0.6 +      inherits: 2.0.4 +      minimatch: 3.1.2 +      once: 1.4.0 +      path-is-absolute: 1.0.1 +    dev: true + +  /global-modules/2.0.0: +    resolution: {integrity: sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==} +    engines: {node: '>=6'} +    dependencies: +      global-prefix: 3.0.0 +    dev: true + +  /global-prefix/3.0.0: +    resolution: {integrity: sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==} +    engines: {node: '>=6'} +    dependencies: +      ini: 1.3.8 +      kind-of: 6.0.3 +      which: 1.3.1 +    dev: true + +  /globals/11.12.0: +    resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} +    engines: {node: '>=4'} +    dev: true + +  /globals/13.15.0: +    resolution: {integrity: sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog==} +    engines: {node: '>=8'} +    dependencies: +      type-fest: 0.20.2 +    dev: true + +  /globby/11.1.0: +    resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} +    engines: {node: '>=10'} +    dependencies: +      array-union: 2.1.0 +      dir-glob: 3.0.1 +      fast-glob: 3.2.11 +      ignore: 5.2.0 +      merge2: 1.4.1 +      slash: 3.0.0 +    dev: true + +  /globby/12.1.0: +    resolution: {integrity: sha512-YULDaNwsoUZkRy9TWSY/M7Obh0abamTKoKzTfOI3uU+hfpX2FZqOq8LFDxsjYheF1RH7ITdArgbQnsNBFgcdBA==} +    engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} +    dependencies: +      array-union: 3.0.1 +      dir-glob: 3.0.1 +      fast-glob: 3.2.11 +      ignore: 5.2.0 +      merge2: 1.4.1 +      slash: 4.0.0 +    dev: true + +  /globby/12.2.0: +    resolution: {integrity: sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA==} +    engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} +    dependencies: +      array-union: 3.0.1 +      dir-glob: 3.0.1 +      fast-glob: 3.2.11 +      ignore: 5.2.0 +      merge2: 1.4.1 +      slash: 4.0.0 +    dev: true + +  /globjoin/0.1.4: +    resolution: {integrity: sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==} +    dev: true + +  /gonzales-pe/4.3.0: +    resolution: {integrity: sha512-otgSPpUmdWJ43VXyiNgEYE4luzHCL2pz4wQ0OnDluC6Eg4Ko3Vexy/SrSynglw/eR+OhkzmqFCZa/OFa/RgAOQ==} +    engines: {node: '>=0.6.0'} +    hasBin: true +    dependencies: +      minimist: 1.2.6 +    dev: true + +  /good-listener/1.2.2: +    resolution: {integrity: sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==} +    dependencies: +      delegate: 3.2.0 +    dev: true + +  /got/11.8.5: +    resolution: {integrity: sha512-o0Je4NvQObAuZPHLFoRSkdG2lTgtcynqymzg2Vupdx6PorhaT5MCbIyXG6d4D94kk8ZG57QeosgdiqfJWhEhlQ==} +    engines: {node: '>=10.19.0'} +    dependencies: +      '@sindresorhus/is': 4.6.0 +      '@szmarczak/http-timer': 4.0.6 +      '@types/cacheable-request': 6.0.2 +      '@types/responselike': 1.0.0 +      cacheable-lookup: 5.0.4 +      cacheable-request: 7.0.2 +      decompress-response: 6.0.0 +      http2-wrapper: 1.0.3 +      lowercase-keys: 2.0.0 +      p-cancelable: 2.1.1 +      responselike: 2.0.0 +    dev: true + +  /graceful-fs/4.2.10: +    resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} +    dev: true + +  /handlebars/4.7.7: +    resolution: {integrity: sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==} +    engines: {node: '>=0.4.7'} +    hasBin: true +    dependencies: +      minimist: 1.2.6 +      neo-async: 2.6.2 +      source-map: 0.6.1 +      wordwrap: 1.0.0 +    optionalDependencies: +      uglify-js: 3.15.5 +    dev: true + +  /hard-rejection/2.1.0: +    resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} +    engines: {node: '>=6'} +    dev: true + +  /has-flag/3.0.0: +    resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} +    engines: {node: '>=4'} +    dev: true + +  /has-flag/4.0.0: +    resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} +    engines: {node: '>=8'} +    dev: true + +  /has-property-descriptors/1.0.0: +    resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} +    dependencies: +      get-intrinsic: 1.1.1 +    dev: true + +  /has-symbols/1.0.3: +    resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} +    engines: {node: '>= 0.4'} +    dev: true + +  /has/1.0.3: +    resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} +    engines: {node: '>= 0.4.0'} +    dependencies: +      function-bind: 1.1.1 +    dev: true + +  /highlight.js/11.5.1: +    resolution: {integrity: sha512-LKzHqnxr4CrD2YsNoIf/o5nJ09j4yi/GcH5BnYz9UnVpZdS4ucMgvP61TDty5xJcFGRjnH4DpujkS9bHT3hq0Q==} +    engines: {node: '>=12.0.0'} +    dev: true + +  /hosted-git-info/2.8.9: +    resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} +    dev: true + +  /hosted-git-info/4.1.0: +    resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} +    engines: {node: '>=10'} +    dependencies: +      lru-cache: 6.0.0 +    dev: true + +  /hpagent/0.1.2: +    resolution: {integrity: sha512-ePqFXHtSQWAFXYmj+JtOTHr84iNrII4/QRlAAPPE+zqnKy4xJo7Ie1Y4kC7AdB+LxLxSTTzBMASsEcy0q8YyvQ==} +    dev: true + +  /html-tags/3.2.0: +    resolution: {integrity: sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg==} +    engines: {node: '>=8'} +    dev: true + +  /http-cache-semantics/4.1.0: +    resolution: {integrity: sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==} +    dev: true + +  /http2-wrapper/1.0.3: +    resolution: {integrity: sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==} +    engines: {node: '>=10.19.0'} +    dependencies: +      quick-lru: 5.1.1 +      resolve-alpn: 1.2.1 +    dev: true + +  /hugo-installer/3.1.0: +    resolution: {integrity: sha512-E3yc8m1NRZBROOx0tx5WtUfAa9EcBbjbM4YSfy3KLGXQfHXIpbfD3oQ5YIKvih8aKuyyRtKzBZIdiOHfWAvvtg==} +    hasBin: true +    dependencies: +      decompress: 4.2.1 +      del: 6.0.0 +      got: 11.8.5 +      hpagent: 0.1.2 +      object-path: 0.11.8 +      semver: 7.3.7 +      yargs: 16.2.0 +    dev: true + +  /ieee754/1.2.1: +    resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} +    dev: true + +  /ignore/5.2.0: +    resolution: {integrity: sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==} +    engines: {node: '>= 4'} +    dev: true + +  /import-fresh/3.3.0: +    resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} +    engines: {node: '>=6'} +    dependencies: +      parent-module: 1.0.1 +      resolve-from: 4.0.0 +    dev: true + +  /import-lazy/4.0.0: +    resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} +    engines: {node: '>=8'} +    dev: true + +  /imurmurhash/0.1.4: +    resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} +    engines: {node: '>=0.8.19'} +    dev: true + +  /indent-string/4.0.0: +    resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} +    engines: {node: '>=8'} +    dev: true + +  /inflight/1.0.6: +    resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} +    dependencies: +      once: 1.4.0 +      wrappy: 1.0.2 +    dev: true + +  /inherits/2.0.4: +    resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} +    dev: true + +  /ini/1.3.8: +    resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} +    dev: true + +  /instant.page/5.1.0: +    resolution: {integrity: sha512-7tz0vkrbj6rN08+C56UDTs1Z71ATPNjMv2eCFaYnIIn3jlkEF6HZCaUtsigjaN2hVaYiuu06vu1usDMnu+OEFg==} +    dev: true + +  /interpret/1.4.0: +    resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==} +    engines: {node: '>= 0.10'} +    dev: true + +  /invariant/2.2.2: +    resolution: {integrity: sha512-FUiAFCOgp7bBzHfa/fK+Uc/vqywvdN9Wg3CiTprLcE630mrhxjDS5MlBkHzeI6+bC/6bq9VX/hxBt05fPAT5WA==} +    dependencies: +      loose-envify: 1.4.0 +    dev: true + +  /is-arrayish/0.2.1: +    resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} +    dev: true + +  /is-binary-path/2.1.0: +    resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} +    engines: {node: '>=8'} +    dependencies: +      binary-extensions: 2.2.0 +    dev: true + +  /is-core-module/2.9.0: +    resolution: {integrity: sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==} +    dependencies: +      has: 1.0.3 +    dev: true + +  /is-extglob/2.1.1: +    resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} +    engines: {node: '>=0.10.0'} +    dev: true + +  /is-fullwidth-code-point/3.0.0: +    resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} +    engines: {node: '>=8'} +    dev: true + +  /is-glob/4.0.3: +    resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} +    engines: {node: '>=0.10.0'} +    dependencies: +      is-extglob: 2.1.1 +    dev: true + +  /is-natural-number/4.0.1: +    resolution: {integrity: sha512-Y4LTamMe0DDQIIAlaer9eKebAlDSV6huy+TWhJVPlzZh2o4tRP5SQWFlLn5N0To4mDD22/qdOq+veo1cSISLgQ==} +    dev: true + +  /is-number/7.0.0: +    resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} +    engines: {node: '>=0.12.0'} +    dev: true + +  /is-path-cwd/2.2.0: +    resolution: {integrity: sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==} +    engines: {node: '>=6'} +    dev: true + +  /is-path-inside/3.0.3: +    resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} +    engines: {node: '>=8'} +    dev: true + +  /is-plain-obj/1.1.0: +    resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} +    engines: {node: '>=0.10.0'} +    dev: true + +  /is-plain-object/5.0.0: +    resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} +    engines: {node: '>=0.10.0'} +    dev: true + +  /is-regexp/2.1.0: +    resolution: {integrity: sha512-OZ4IlER3zmRIoB9AqNhEggVxqIH4ofDns5nRrPS6yQxXE1TPCUpFznBfRQmQa8uC+pXqjMnukiJBxCisIxiLGA==} +    engines: {node: '>=6'} +    dev: true + +  /is-stream/1.1.0: +    resolution: {integrity: sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==} +    engines: {node: '>=0.10.0'} +    dev: true + +  /isarray/1.0.0: +    resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} +    dev: true + +  /isexe/2.0.0: +    resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} +    dev: true + +  /js-tokens/4.0.0: +    resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} +    dev: true + +  /js-yaml/4.1.0: +    resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} +    hasBin: true +    dependencies: +      argparse: 2.0.1 +    dev: true + +  /jsesc/0.5.0: +    resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} +    hasBin: true +    dev: true + +  /jsesc/2.5.2: +    resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} +    engines: {node: '>=4'} +    hasBin: true +    dev: true + +  /json-buffer/3.0.1: +    resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} +    dev: true + +  /json-parse-even-better-errors/2.3.1: +    resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} +    dev: true + +  /json-schema-traverse/0.4.1: +    resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} +    dev: true + +  /json-schema-traverse/1.0.0: +    resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} +    dev: true + +  /json-stable-stringify-without-jsonify/1.0.1: +    resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} +    dev: true + +  /json5/2.2.1: +    resolution: {integrity: sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==} +    engines: {node: '>=6'} +    hasBin: true +    dev: true + +  /jsonfile/6.1.0: +    resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} +    dependencies: +      universalify: 2.0.0 +    optionalDependencies: +      graceful-fs: 4.2.10 +    dev: true + +  /katex/0.16.0: +    resolution: {integrity: sha512-wPRB4iUPysfH97wTgG5/tRLYxmKVq6Q4jRAWRVOUxXB1dsiv4cvcNjqabHkrOvJHM1Bpk3WrgmllSO1vIvP24w==} +    hasBin: true +    dependencies: +      commander: 8.3.0 +    dev: true + +  /keyv/4.3.0: +    resolution: {integrity: sha512-C30Un9+63J0CsR7Wka5quXKqYZsT6dcRQ2aOwGcSc3RiQ4HGWpTAHlCA+puNfw2jA/s11EsxA1nCXgZRuRKMQQ==} +    dependencies: +      compress-brotli: 1.3.8 +      json-buffer: 3.0.1 +    dev: true + +  /kind-of/6.0.3: +    resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} +    engines: {node: '>=0.10.0'} +    dev: true + +  /known-css-properties/0.25.0: +    resolution: {integrity: sha512-b0/9J1O9Jcyik1GC6KC42hJ41jKwdO/Mq8Mdo5sYN+IuRTXs2YFHZC3kZSx6ueusqa95x3wLYe/ytKjbAfGixA==} +    dev: true + +  /lazysizes/5.3.2: +    resolution: {integrity: sha512-22UzWP+Vedi/sMeOr8O7FWimRVtiNJV2HCa+V8+peZOw6QbswN9k58VUhd7i6iK5bw5QkYrF01LJbeJe0PV8jg==} +    dev: true + +  /levn/0.4.1: +    resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} +    engines: {node: '>= 0.8.0'} +    dependencies: +      prelude-ls: 1.2.1 +      type-check: 0.4.0 +    dev: true + +  /lilconfig/2.0.5: +    resolution: {integrity: sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg==} +    engines: {node: '>=10'} +    dev: true + +  /lines-and-columns/1.2.4: +    resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} +    dev: true + +  /linkify-it/3.0.3: +    resolution: {integrity: sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==} +    dependencies: +      uc.micro: 1.0.6 +    dev: true + +  /locate-path/5.0.0: +    resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} +    engines: {node: '>=8'} +    dependencies: +      p-locate: 4.1.0 +    dev: true + +  /lodash.debounce/4.0.8: +    resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} +    dev: true + +  /lodash.merge/4.6.2: +    resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} +    dev: true + +  /lodash.truncate/4.4.2: +    resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} +    dev: true + +  /lodash/4.17.21: +    resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} +    dev: true + +  /loose-envify/1.4.0: +    resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} +    hasBin: true +    dependencies: +      js-tokens: 4.0.0 +    dev: true + +  /lowercase-keys/2.0.0: +    resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==} +    engines: {node: '>=8'} +    dev: true + +  /lru-cache/6.0.0: +    resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} +    engines: {node: '>=10'} +    dependencies: +      yallist: 4.0.0 +    dev: true + +  /make-dir/1.3.0: +    resolution: {integrity: sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==} +    engines: {node: '>=4'} +    dependencies: +      pify: 3.0.0 +    dev: true + +  /make-dir/2.1.0: +    resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} +    engines: {node: '>=6'} +    dependencies: +      pify: 4.0.1 +      semver: 5.7.1 +    dev: true + +  /map-obj/1.0.1: +    resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} +    engines: {node: '>=0.10.0'} +    dev: true + +  /map-obj/4.3.0: +    resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} +    engines: {node: '>=8'} +    dev: true + +  /markdown-it/12.3.2: +    resolution: {integrity: sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==} +    hasBin: true +    dependencies: +      argparse: 2.0.1 +      entities: 2.1.0 +      linkify-it: 3.0.3 +      mdurl: 1.0.1 +      uc.micro: 1.0.6 +    dev: true + +  /markdownlint-cli2-formatter-default/0.0.3_markdownlint-cli2@0.4.0: +    resolution: {integrity: sha512-QEAJitT5eqX1SNboOD+SO/LNBpu4P4je8JlR02ug2cLQAqmIhh8IJnSK7AcaHBHhNADqdGydnPpQOpsNcEEqCw==} +    peerDependencies: +      markdownlint-cli2: '>=0.0.4' +    dependencies: +      markdownlint-cli2: 0.4.0 +    dev: true + +  /markdownlint-cli2/0.4.0: +    resolution: {integrity: sha512-EcwP5tAbyzzL3ACI0L16LqbNctmh8wNX56T+aVvIxWyTAkwbYNx2V7IheRkXS3mE7R/pnaApZ/RSXcXuzRVPjg==} +    engines: {node: '>=12'} +    hasBin: true +    dependencies: +      globby: 12.1.0 +      markdownlint: 0.25.1 +      markdownlint-cli2-formatter-default: 0.0.3_markdownlint-cli2@0.4.0 +      markdownlint-rule-helpers: 0.16.0 +      micromatch: 4.0.4 +      strip-json-comments: 4.0.0 +      yaml: 1.10.2 +    dev: true + +  /markdownlint-rule-helpers/0.16.0: +    resolution: {integrity: sha512-oEacRUVeTJ5D5hW1UYd2qExYI0oELdYK72k1TKGvIeYJIbqQWAz476NAc7LNixSySUhcNl++d02DvX0ccDk9/w==} +    dev: true + +  /markdownlint/0.25.1: +    resolution: {integrity: sha512-AG7UkLzNa1fxiOv5B+owPsPhtM4D6DoODhsJgiaNg1xowXovrYgOnLqAgOOFQpWOlHFVQUzjMY5ypNNTeov92g==} +    engines: {node: '>=12'} +    dependencies: +      markdown-it: 12.3.2 +    dev: true + +  /mathml-tag-names/2.1.3: +    resolution: {integrity: sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==} +    dev: true + +  /mdurl/1.0.1: +    resolution: {integrity: sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==} +    dev: true + +  /meow/9.0.0: +    resolution: {integrity: sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==} +    engines: {node: '>=10'} +    dependencies: +      '@types/minimist': 1.2.2 +      camelcase-keys: 6.2.2 +      decamelize: 1.2.0 +      decamelize-keys: 1.1.0 +      hard-rejection: 2.1.0 +      minimist-options: 4.1.0 +      normalize-package-data: 3.0.3 +      read-pkg-up: 7.0.1 +      redent: 3.0.0 +      trim-newlines: 3.0.1 +      type-fest: 0.18.1 +      yargs-parser: 20.2.9 +    dev: true + +  /merge2/1.4.1: +    resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} +    engines: {node: '>= 8'} +    dev: true + +  /micromatch/4.0.4: +    resolution: {integrity: sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==} +    engines: {node: '>=8.6'} +    dependencies: +      braces: 3.0.2 +      picomatch: 2.3.1 +    dev: true + +  /micromatch/4.0.5: +    resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} +    engines: {node: '>=8.6'} +    dependencies: +      braces: 3.0.2 +      picomatch: 2.3.1 +    dev: true + +  /mimic-response/1.0.1: +    resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==} +    engines: {node: '>=4'} +    dev: true + +  /mimic-response/3.1.0: +    resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} +    engines: {node: '>=10'} +    dev: true + +  /min-indent/1.0.1: +    resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} +    engines: {node: '>=4'} +    dev: true + +  /minimatch/3.1.2: +    resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} +    dependencies: +      brace-expansion: 1.1.11 +    dev: true + +  /minimist-options/4.1.0: +    resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} +    engines: {node: '>= 6'} +    dependencies: +      arrify: 1.0.1 +      is-plain-obj: 1.1.0 +      kind-of: 6.0.3 +    dev: true + +  /minimist/1.2.6: +    resolution: {integrity: sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==} +    dev: true + +  /ms/2.1.2: +    resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} +    dev: true + +  /nanoid/3.3.4: +    resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==} +    engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} +    hasBin: true +    dev: true + +  /natural-compare/1.4.0: +    resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} +    dev: true + +  /neo-async/2.6.2: +    resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} +    dev: true + +  /netlify-plugin-submit-sitemap/0.3.0: +    resolution: {integrity: sha512-JJH37nG4zjGkPCcBKYngQtwNU89OKFOiKwPnhbdye1CexHc+gvYoTQptmDIGe9AC8GR2LBBxXWA7Vd54AWxELA==} +    dependencies: +      node-fetch: 3.2.5 +    dev: true + +  /node-domexception/1.0.0: +    resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} +    engines: {node: '>=10.5.0'} +    dev: true + +  /node-fetch/2.6.7: +    resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==} +    engines: {node: 4.x || >=6.0.0} +    peerDependencies: +      encoding: ^0.1.0 +    peerDependenciesMeta: +      encoding: +        optional: true +    dependencies: +      whatwg-url: 5.0.0 +    dev: true + +  /node-fetch/3.2.5: +    resolution: {integrity: sha512-u7zCHdJp8JXBwF09mMfo2CL6kp37TslDl1KP3hRGTlCInBtag+UO3LGVy+NF0VzvnL3PVMpA2hXh1EtECFnyhQ==} +    engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} +    dependencies: +      data-uri-to-buffer: 4.0.0 +      fetch-blob: 3.1.5 +      formdata-polyfill: 4.0.10 +    dev: true + +  /node-releases/2.0.5: +    resolution: {integrity: sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==} +    dev: true + +  /normalize-package-data/2.5.0: +    resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} +    dependencies: +      hosted-git-info: 2.8.9 +      resolve: 1.22.0 +      semver: 5.7.1 +      validate-npm-package-license: 3.0.4 +    dev: true + +  /normalize-package-data/3.0.3: +    resolution: {integrity: sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==} +    engines: {node: '>=10'} +    dependencies: +      hosted-git-info: 4.1.0 +      is-core-module: 2.9.0 +      semver: 7.3.7 +      validate-npm-package-license: 3.0.4 +    dev: true + +  /normalize-path/3.0.0: +    resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} +    engines: {node: '>=0.10.0'} +    dev: true + +  /normalize-range/0.1.2: +    resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} +    engines: {node: '>=0.10.0'} +    dev: true + +  /normalize-url/6.1.0: +    resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} +    engines: {node: '>=10'} +    dev: true + +  /object-assign/4.1.1: +    resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} +    engines: {node: '>=0.10.0'} +    dev: true + +  /object-keys/1.1.1: +    resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} +    engines: {node: '>= 0.4'} +    dev: true + +  /object-path/0.11.8: +    resolution: {integrity: sha512-YJjNZrlXJFM42wTBn6zgOJVar9KFJvzx6sTWDte8sWZF//cnjl0BxHNpfZx+ZffXX63A9q0b1zsFiBX4g4X5KA==} +    engines: {node: '>= 10.12.0'} +    dev: true + +  /object.assign/4.1.2: +    resolution: {integrity: sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==} +    engines: {node: '>= 0.4'} +    dependencies: +      call-bind: 1.0.2 +      define-properties: 1.1.4 +      has-symbols: 1.0.3 +      object-keys: 1.1.1 +    dev: true + +  /once/1.4.0: +    resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} +    dependencies: +      wrappy: 1.0.2 +    dev: true + +  /optionator/0.9.1: +    resolution: {integrity: sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==} +    engines: {node: '>= 0.8.0'} +    dependencies: +      deep-is: 0.1.4 +      fast-levenshtein: 2.0.6 +      levn: 0.4.1 +      prelude-ls: 1.2.1 +      type-check: 0.4.0 +      word-wrap: 1.2.3 +    dev: true + +  /p-cancelable/2.1.1: +    resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==} +    engines: {node: '>=8'} +    dev: true + +  /p-limit/2.3.0: +    resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} +    engines: {node: '>=6'} +    dependencies: +      p-try: 2.2.0 +    dev: true + +  /p-locate/4.1.0: +    resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} +    engines: {node: '>=8'} +    dependencies: +      p-limit: 2.3.0 +    dev: true + +  /p-map/4.0.0: +    resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} +    engines: {node: '>=10'} +    dependencies: +      aggregate-error: 3.1.0 +    dev: true + +  /p-try/2.2.0: +    resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} +    engines: {node: '>=6'} +    dev: true + +  /parent-module/1.0.1: +    resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} +    engines: {node: '>=6'} +    dependencies: +      callsites: 3.1.0 +    dev: true + +  /parse-github-url/1.0.2: +    resolution: {integrity: sha512-kgBf6avCbO3Cn6+RnzRGLkUsv4ZVqv/VfAYkRsyBcgkshNvVBkRn1FEZcW0Jb+npXQWm2vHPnnOqFteZxRRGNw==} +    engines: {node: '>=0.10.0'} +    hasBin: true +    dev: true + +  /parse-json/5.2.0: +    resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} +    engines: {node: '>=8'} +    dependencies: +      '@babel/code-frame': 7.16.7 +      error-ex: 1.3.2 +      json-parse-even-better-errors: 2.3.1 +      lines-and-columns: 1.2.4 +    dev: true + +  /path-exists/4.0.0: +    resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} +    engines: {node: '>=8'} +    dev: true + +  /path-is-absolute/1.0.1: +    resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} +    engines: {node: '>=0.10.0'} +    dev: true + +  /path-key/3.1.1: +    resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} +    engines: {node: '>=8'} +    dev: true + +  /path-parse/1.0.7: +    resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} +    dev: true + +  /path-type/4.0.0: +    resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} +    engines: {node: '>=8'} +    dev: true + +  /pend/1.2.0: +    resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} +    dev: true + +  /picocolors/1.0.0: +    resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} +    dev: true + +  /picomatch/2.3.1: +    resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} +    engines: {node: '>=8.6'} +    dev: true + +  /pify/2.3.0: +    resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} +    engines: {node: '>=0.10.0'} +    dev: true + +  /pify/3.0.0: +    resolution: {integrity: sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==} +    engines: {node: '>=4'} +    dev: true + +  /pify/4.0.1: +    resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} +    engines: {node: '>=6'} +    dev: true + +  /pinkie-promise/2.0.1: +    resolution: {integrity: sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==} +    engines: {node: '>=0.10.0'} +    dependencies: +      pinkie: 2.0.4 +    dev: true + +  /pinkie/2.0.4: +    resolution: {integrity: sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==} +    engines: {node: '>=0.10.0'} +    dev: true + +  /postcss-cli/9.1.0_postcss@8.4.14: +    resolution: {integrity: sha512-zvDN2ADbWfza42sAnj+O2uUWyL0eRL1V+6giM2vi4SqTR3gTYy8XzcpfwccayF2szcUif0HMmXiEaDv9iEhcpw==} +    engines: {node: '>=12'} +    hasBin: true +    peerDependencies: +      postcss: ^8.0.0 +    dependencies: +      chokidar: 3.5.3 +      dependency-graph: 0.11.0 +      fs-extra: 10.1.0 +      get-stdin: 9.0.0 +      globby: 12.2.0 +      picocolors: 1.0.0 +      postcss: 8.4.14 +      postcss-load-config: 3.1.4_postcss@8.4.14 +      postcss-reporter: 7.0.5_postcss@8.4.14 +      pretty-hrtime: 1.0.3 +      read-cache: 1.0.0 +      slash: 4.0.0 +      yargs: 17.5.1 +    transitivePeerDependencies: +      - ts-node +    dev: true + +  /postcss-load-config/3.1.4_postcss@8.4.14: +    resolution: {integrity: sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==} +    engines: {node: '>= 10'} +    peerDependencies: +      postcss: '>=8.0.9' +      ts-node: '>=9.0.0' +    peerDependenciesMeta: +      postcss: +        optional: true +      ts-node: +        optional: true +    dependencies: +      lilconfig: 2.0.5 +      postcss: 8.4.14 +      yaml: 1.10.2 +    dev: true + +  /postcss-media-query-parser/0.2.3: +    resolution: {integrity: sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==} +    dev: true + +  /postcss-reporter/7.0.5_postcss@8.4.14: +    resolution: {integrity: sha512-glWg7VZBilooZGOFPhN9msJ3FQs19Hie7l5a/eE6WglzYqVeH3ong3ShFcp9kDWJT1g2Y/wd59cocf9XxBtkWA==} +    engines: {node: '>=10'} +    peerDependencies: +      postcss: ^8.1.0 +    dependencies: +      picocolors: 1.0.0 +      postcss: 8.4.14 +      thenby: 1.3.4 +    dev: true + +  /postcss-resolve-nested-selector/0.1.1: +    resolution: {integrity: sha512-HvExULSwLqHLgUy1rl3ANIqCsvMS0WHss2UOsXhXnQaZ9VCc2oBvIpXrl00IUFT5ZDITME0o6oiXeiHr2SAIfw==} +    dev: true + +  /postcss-safe-parser/6.0.0_postcss@8.4.14: +    resolution: {integrity: sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==} +    engines: {node: '>=12.0'} +    peerDependencies: +      postcss: ^8.3.3 +    dependencies: +      postcss: 8.4.14 +    dev: true + +  /postcss-scss/4.0.4_postcss@8.4.14: +    resolution: {integrity: sha512-aBBbVyzA8b3hUL0MGrpydxxXKXFZc5Eqva0Q3V9qsBOLEMsjb6w49WfpsoWzpEgcqJGW4t7Rio8WXVU9Gd8vWg==} +    engines: {node: '>=12.0'} +    peerDependencies: +      postcss: ^8.3.3 +    dependencies: +      postcss: 8.4.14 +    dev: true + +  /postcss-selector-parser/6.0.10: +    resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==} +    engines: {node: '>=4'} +    dependencies: +      cssesc: 3.0.0 +      util-deprecate: 1.0.2 +    dev: true + +  /postcss-value-parser/4.2.0: +    resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} +    dev: true + +  /postcss/8.4.14: +    resolution: {integrity: sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==} +    engines: {node: ^10 || ^12 || >=14} +    dependencies: +      nanoid: 3.3.4 +      picocolors: 1.0.0 +      source-map-js: 1.0.2 +    dev: true + +  /prelude-ls/1.2.1: +    resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} +    engines: {node: '>= 0.8.0'} +    dev: true + +  /pretty-hrtime/1.0.3: +    resolution: {integrity: sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==} +    engines: {node: '>= 0.8'} +    dev: true + +  /process-nextick-args/2.0.1: +    resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} +    dev: true + +  /pump/3.0.0: +    resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} +    dependencies: +      end-of-stream: 1.4.4 +      once: 1.4.0 +    dev: true + +  /punycode/2.1.1: +    resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} +    engines: {node: '>=6'} +    dev: true + +  /purgecss-whitelister/2.4.0: +    resolution: {integrity: sha512-O0jBUDtY9dU9tUT0vA1FvwFdkKDerxzteYaBV49JCbm+QJLFKMlIsf5Kp5cdbLatHQNjJtV8VB8eXtISoZL2Dg==} +    dependencies: +      glob-all: 3.3.0 +      gonzales-pe: 4.3.0 +      scss-parser: 1.0.3 +    dev: true + +  /purgecss/4.1.3: +    resolution: {integrity: sha512-99cKy4s+VZoXnPxaoM23e5ABcP851nC2y2GROkkjS8eJaJtlciGavd7iYAw2V84WeBqggZ12l8ef44G99HmTaw==} +    hasBin: true +    dependencies: +      commander: 8.3.0 +      glob: 7.2.3 +      postcss: 8.4.14 +      postcss-selector-parser: 6.0.10 +    dev: true + +  /queue-microtask/1.2.3: +    resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} +    dev: true + +  /quick-lru/4.0.1: +    resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==} +    engines: {node: '>=8'} +    dev: true + +  /quick-lru/5.1.1: +    resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} +    engines: {node: '>=10'} +    dev: true + +  /read-cache/1.0.0: +    resolution: {integrity: sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=} +    dependencies: +      pify: 2.3.0 +    dev: true + +  /read-pkg-up/7.0.1: +    resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} +    engines: {node: '>=8'} +    dependencies: +      find-up: 4.1.0 +      read-pkg: 5.2.0 +      type-fest: 0.8.1 +    dev: true + +  /read-pkg/5.2.0: +    resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} +    engines: {node: '>=8'} +    dependencies: +      '@types/normalize-package-data': 2.4.1 +      normalize-package-data: 2.5.0 +      parse-json: 5.2.0 +      type-fest: 0.6.0 +    dev: true + +  /readable-stream/2.3.7: +    resolution: {integrity: sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==} +    dependencies: +      core-util-is: 1.0.3 +      inherits: 2.0.4 +      isarray: 1.0.0 +      process-nextick-args: 2.0.1 +      safe-buffer: 5.1.2 +      string_decoder: 1.1.1 +      util-deprecate: 1.0.2 +    dev: true + +  /readdirp/3.6.0: +    resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} +    engines: {node: '>=8.10.0'} +    dependencies: +      picomatch: 2.3.1 +    dev: true + +  /rechoir/0.6.2: +    resolution: {integrity: sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=} +    engines: {node: '>= 0.10'} +    dependencies: +      resolve: 1.22.0 +    dev: true + +  /redent/3.0.0: +    resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} +    engines: {node: '>=8'} +    dependencies: +      indent-string: 4.0.0 +      strip-indent: 3.0.0 +    dev: true + +  /regenerate-unicode-properties/10.0.1: +    resolution: {integrity: sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw==} +    engines: {node: '>=4'} +    dependencies: +      regenerate: 1.4.2 +    dev: true + +  /regenerate/1.4.2: +    resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==} +    dev: true + +  /regenerator-runtime/0.13.9: +    resolution: {integrity: sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==} +    dev: true + +  /regenerator-transform/0.15.0: +    resolution: {integrity: sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg==} +    dependencies: +      '@babel/runtime': 7.18.3 +    dev: true + +  /regexpp/3.2.0: +    resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==} +    engines: {node: '>=8'} +    dev: true + +  /regexpu-core/5.0.1: +    resolution: {integrity: sha512-CriEZlrKK9VJw/xQGJpQM5rY88BtuL8DM+AEwvcThHilbxiTAy8vq4iJnd2tqq8wLmjbGZzP7ZcKFjbGkmEFrw==} +    engines: {node: '>=4'} +    dependencies: +      regenerate: 1.4.2 +      regenerate-unicode-properties: 10.0.1 +      regjsgen: 0.6.0 +      regjsparser: 0.8.4 +      unicode-match-property-ecmascript: 2.0.0 +      unicode-match-property-value-ecmascript: 2.0.0 +    dev: true + +  /regjsgen/0.6.0: +    resolution: {integrity: sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA==} +    dev: true + +  /regjsparser/0.8.4: +    resolution: {integrity: sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA==} +    hasBin: true +    dependencies: +      jsesc: 0.5.0 +    dev: true + +  /require-directory/2.1.1: +    resolution: {integrity: sha1-jGStX9MNqxyXbiNE/+f3kqam30I=} +    engines: {node: '>=0.10.0'} +    dev: true + +  /require-from-string/2.0.2: +    resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} +    engines: {node: '>=0.10.0'} +    dev: true + +  /require-main-filename/2.0.0: +    resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} +    dev: true + +  /resolve-alpn/1.2.1: +    resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} +    dev: true + +  /resolve-from/4.0.0: +    resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} +    engines: {node: '>=4'} +    dev: true + +  /resolve-from/5.0.0: +    resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} +    engines: {node: '>=8'} +    dev: true + +  /resolve/1.22.0: +    resolution: {integrity: sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==} +    hasBin: true +    dependencies: +      is-core-module: 2.9.0 +      path-parse: 1.0.7 +      supports-preserve-symlinks-flag: 1.0.0 +    dev: true + +  /responselike/2.0.0: +    resolution: {integrity: sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==} +    dependencies: +      lowercase-keys: 2.0.0 +    dev: true + +  /reusify/1.0.4: +    resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} +    engines: {iojs: '>=1.0.0', node: '>=0.10.0'} +    dev: true + +  /rimraf/3.0.2: +    resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} +    hasBin: true +    dependencies: +      glob: 7.2.3 +    dev: true + +  /run-parallel/1.2.0: +    resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} +    dependencies: +      queue-microtask: 1.2.3 +    dev: true + +  /safe-buffer/5.1.2: +    resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} +    dev: true + +  /safe-buffer/5.2.1: +    resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} +    dev: true + +  /scss-parser/1.0.3: +    resolution: {integrity: sha512-XQKCfOJERmhn1yoNRUyxv9wgkf4DIv29Jk0m4FiZforeiCmGxrby8K3not7tQ8GK1yvtd9N0OnNimNetJ8V+zQ==} +    engines: {node: '>=6.0.0'} +    dependencies: +      invariant: 2.2.2 +      lodash: 4.17.21 +    dev: true + +  /seek-bzip/1.0.6: +    resolution: {integrity: sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ==} +    hasBin: true +    dependencies: +      commander: 2.20.3 +    dev: true + +  /select/1.1.2: +    resolution: {integrity: sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=} +    dev: true + +  /semver/5.7.1: +    resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==} +    hasBin: true +    dev: true + +  /semver/6.3.0: +    resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} +    hasBin: true +    dev: true + +  /semver/7.0.0: +    resolution: {integrity: sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==} +    hasBin: true +    dev: true + +  /semver/7.3.7: +    resolution: {integrity: sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==} +    engines: {node: '>=10'} +    hasBin: true +    dependencies: +      lru-cache: 6.0.0 +    dev: true + +  /set-blocking/2.0.0: +    resolution: {integrity: sha1-BF+XgtARrppoA93TgrJDkrPYkPc=} +    dev: true + +  /shebang-command/2.0.0: +    resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} +    engines: {node: '>=8'} +    dependencies: +      shebang-regex: 3.0.0 +    dev: true + +  /shebang-regex/3.0.0: +    resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} +    engines: {node: '>=8'} +    dev: true + +  /shelljs/0.8.5: +    resolution: {integrity: sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==} +    engines: {node: '>=4'} +    hasBin: true +    dependencies: +      glob: 7.2.3 +      interpret: 1.4.0 +      rechoir: 0.6.2 +    dev: true + +  /shx/0.3.4: +    resolution: {integrity: sha512-N6A9MLVqjxZYcVn8hLmtneQWIJtp8IKzMP4eMnx+nqkvXoqinUPCbUFLp2UcWTEIUONhlk0ewxr/jaVGlc+J+g==} +    engines: {node: '>=6'} +    hasBin: true +    dependencies: +      minimist: 1.2.6 +      shelljs: 0.8.5 +    dev: true + +  /signal-exit/3.0.7: +    resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} +    dev: true + +  /slash/2.0.0: +    resolution: {integrity: sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==} +    engines: {node: '>=6'} +    dev: true + +  /slash/3.0.0: +    resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} +    engines: {node: '>=8'} +    dev: true + +  /slash/4.0.0: +    resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} +    engines: {node: '>=12'} +    dev: true + +  /slice-ansi/4.0.0: +    resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} +    engines: {node: '>=10'} +    dependencies: +      ansi-styles: 4.3.0 +      astral-regex: 2.0.0 +      is-fullwidth-code-point: 3.0.0 +    dev: true + +  /source-map-js/1.0.2: +    resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} +    engines: {node: '>=0.10.0'} +    dev: true + +  /source-map/0.6.1: +    resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} +    engines: {node: '>=0.10.0'} +    dev: true + +  /spdx-correct/3.1.1: +    resolution: {integrity: sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==} +    dependencies: +      spdx-expression-parse: 3.0.1 +      spdx-license-ids: 3.0.11 +    dev: true + +  /spdx-exceptions/2.3.0: +    resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==} +    dev: true + +  /spdx-expression-parse/3.0.1: +    resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} +    dependencies: +      spdx-exceptions: 2.3.0 +      spdx-license-ids: 3.0.11 +    dev: true + +  /spdx-license-ids/3.0.11: +    resolution: {integrity: sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==} +    dev: true + +  /string-width/4.2.3: +    resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} +    engines: {node: '>=8'} +    dependencies: +      emoji-regex: 8.0.0 +      is-fullwidth-code-point: 3.0.0 +      strip-ansi: 6.0.1 +    dev: true + +  /string_decoder/1.1.1: +    resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} +    dependencies: +      safe-buffer: 5.1.2 +    dev: true + +  /strip-ansi/6.0.1: +    resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} +    engines: {node: '>=8'} +    dependencies: +      ansi-regex: 5.0.1 +    dev: true + +  /strip-dirs/2.1.0: +    resolution: {integrity: sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==} +    dependencies: +      is-natural-number: 4.0.1 +    dev: true + +  /strip-indent/3.0.0: +    resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} +    engines: {node: '>=8'} +    dependencies: +      min-indent: 1.0.1 +    dev: true + +  /strip-json-comments/3.1.1: +    resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} +    engines: {node: '>=8'} +    dev: true + +  /strip-json-comments/4.0.0: +    resolution: {integrity: sha512-LzWcbfMbAsEDTRmhjWIioe8GcDRl0fa35YMXFoJKDdiD/quGFmjJjdgPjFJJNwCMaLyQqFIDqCdHD2V4HfLgYA==} +    engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} +    dev: true + +  /style-search/0.1.0: +    resolution: {integrity: sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==} +    dev: true + +  /stylelint-config-recommended-scss/5.0.2_7ic4eknhyyc4ey2sk6vxipflva: +    resolution: {integrity: sha512-b14BSZjcwW0hqbzm9b0S/ScN2+3CO3O4vcMNOw2KGf8lfVSwJ4p5TbNEXKwKl1+0FMtgRXZj6DqVUe/7nGnuBg==} +    peerDependencies: +      stylelint: ^14.0.0 +    dependencies: +      postcss-scss: 4.0.4_postcss@8.4.14 +      stylelint: 14.9.0 +      stylelint-config-recommended: 6.0.0_stylelint@14.9.0 +      stylelint-scss: 4.2.0_stylelint@14.9.0 +    transitivePeerDependencies: +      - postcss +    dev: true + +  /stylelint-config-recommended/6.0.0_stylelint@14.9.0: +    resolution: {integrity: sha512-ZorSSdyMcxWpROYUvLEMm0vSZud2uB7tX1hzBZwvVY9SV/uly4AvvJPPhCcymZL3fcQhEQG5AELmrxWqtmzacw==} +    peerDependencies: +      stylelint: ^14.0.0 +    dependencies: +      stylelint: 14.9.0 +    dev: true + +  /stylelint-config-standard-scss/3.0.0_7ic4eknhyyc4ey2sk6vxipflva: +    resolution: {integrity: sha512-zt3ZbzIbllN1iCmc94e4pDxqpkzeR6CJo5DDXzltshuXr+82B8ylHyMMARNnUYrZH80B7wgY7UkKTYCFM0UUyw==} +    peerDependencies: +      stylelint: ^14.0.0 +    dependencies: +      stylelint: 14.9.0 +      stylelint-config-recommended-scss: 5.0.2_7ic4eknhyyc4ey2sk6vxipflva +      stylelint-config-standard: 24.0.0_stylelint@14.9.0 +    transitivePeerDependencies: +      - postcss +    dev: true + +  /stylelint-config-standard/24.0.0_stylelint@14.9.0: +    resolution: {integrity: sha512-+RtU7fbNT+VlNbdXJvnjc3USNPZRiRVp/d2DxOF/vBDDTi0kH5RX2Ny6errdtZJH3boO+bmqIYEllEmok4jiuw==} +    peerDependencies: +      stylelint: ^14.0.0 +    dependencies: +      stylelint: 14.9.0 +      stylelint-config-recommended: 6.0.0_stylelint@14.9.0 +    dev: true + +  /stylelint-scss/4.2.0_stylelint@14.9.0: +    resolution: {integrity: sha512-HHHMVKJJ5RM9pPIbgJ/XA67h9H0407G68Rm69H4fzFbFkyDMcTV1Byep3qdze5+fJ3c0U7mJrbj6S0Fg072uZA==} +    peerDependencies: +      stylelint: ^14.5.1 +    dependencies: +      lodash: 4.17.21 +      postcss-media-query-parser: 0.2.3 +      postcss-resolve-nested-selector: 0.1.1 +      postcss-selector-parser: 6.0.10 +      postcss-value-parser: 4.2.0 +      stylelint: 14.9.0 +    dev: true + +  /stylelint/14.9.0: +    resolution: {integrity: sha512-+xsQ4uKS56RQs8AGYx2CXc9nhWyPR7c/G0RqyiKgWZx2LuE3VJnIhGRQXUfnGQXOqBPHxNjMCHiK5NNQRB52sw==} +    engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} +    hasBin: true +    dependencies: +      '@csstools/selector-specificity': 2.0.0_444rcjjorr3kpoqtvoodsr46pu +      balanced-match: 2.0.0 +      colord: 2.9.2 +      cosmiconfig: 7.0.1 +      css-functions-list: 3.1.0 +      debug: 4.3.4 +      execall: 2.0.0 +      fast-glob: 3.2.11 +      fastest-levenshtein: 1.0.12 +      file-entry-cache: 6.0.1 +      get-stdin: 8.0.0 +      global-modules: 2.0.0 +      globby: 11.1.0 +      globjoin: 0.1.4 +      html-tags: 3.2.0 +      ignore: 5.2.0 +      import-lazy: 4.0.0 +      imurmurhash: 0.1.4 +      is-plain-object: 5.0.0 +      known-css-properties: 0.25.0 +      mathml-tag-names: 2.1.3 +      meow: 9.0.0 +      micromatch: 4.0.5 +      normalize-path: 3.0.0 +      picocolors: 1.0.0 +      postcss: 8.4.14 +      postcss-media-query-parser: 0.2.3 +      postcss-resolve-nested-selector: 0.1.1 +      postcss-safe-parser: 6.0.0_postcss@8.4.14 +      postcss-selector-parser: 6.0.10 +      postcss-value-parser: 4.2.0 +      resolve-from: 5.0.0 +      string-width: 4.2.3 +      strip-ansi: 6.0.1 +      style-search: 0.1.0 +      supports-hyperlinks: 2.2.0 +      svg-tags: 1.0.0 +      table: 6.8.0 +      v8-compile-cache: 2.3.0 +      write-file-atomic: 4.0.1 +    transitivePeerDependencies: +      - supports-color +    dev: true + +  /supports-color/5.5.0: +    resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} +    engines: {node: '>=4'} +    dependencies: +      has-flag: 3.0.0 +    dev: true + +  /supports-color/7.2.0: +    resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} +    engines: {node: '>=8'} +    dependencies: +      has-flag: 4.0.0 +    dev: true + +  /supports-hyperlinks/2.2.0: +    resolution: {integrity: sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==} +    engines: {node: '>=8'} +    dependencies: +      has-flag: 4.0.0 +      supports-color: 7.2.0 +    dev: true + +  /supports-preserve-symlinks-flag/1.0.0: +    resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} +    engines: {node: '>= 0.4'} +    dev: true + +  /svg-tags/1.0.0: +    resolution: {integrity: sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=} +    dev: true + +  /table/6.8.0: +    resolution: {integrity: sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==} +    engines: {node: '>=10.0.0'} +    dependencies: +      ajv: 8.11.0 +      lodash.truncate: 4.4.2 +      slice-ansi: 4.0.0 +      string-width: 4.2.3 +      strip-ansi: 6.0.1 +    dev: true + +  /tar-stream/1.6.2: +    resolution: {integrity: sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==} +    engines: {node: '>= 0.8.0'} +    dependencies: +      bl: 1.2.3 +      buffer-alloc: 1.2.0 +      end-of-stream: 1.4.4 +      fs-constants: 1.0.0 +      readable-stream: 2.3.7 +      to-buffer: 1.1.1 +      xtend: 4.0.2 +    dev: true + +  /text-table/0.2.0: +    resolution: {integrity: sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=} +    dev: true + +  /thenby/1.3.4: +    resolution: {integrity: sha512-89Gi5raiWA3QZ4b2ePcEwswC3me9JIg+ToSgtE0JWeCynLnLxNr/f9G+xfo9K+Oj4AFdom8YNJjibIARTJmapQ==} +    dev: true + +  /through/2.3.8: +    resolution: {integrity: sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=} +    dev: true + +  /tiny-emitter/2.1.0: +    resolution: {integrity: sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==} +    dev: true + +  /to-buffer/1.1.1: +    resolution: {integrity: sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==} +    dev: true + +  /to-fast-properties/2.0.0: +    resolution: {integrity: sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=} +    engines: {node: '>=4'} +    dev: true + +  /to-regex-range/5.0.1: +    resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} +    engines: {node: '>=8.0'} +    dependencies: +      is-number: 7.0.0 +    dev: true + +  /tr46/0.0.3: +    resolution: {integrity: sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=} +    dev: true + +  /trim-newlines/3.0.1: +    resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} +    engines: {node: '>=8'} +    dev: true + +  /type-check/0.4.0: +    resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} +    engines: {node: '>= 0.8.0'} +    dependencies: +      prelude-ls: 1.2.1 +    dev: true + +  /type-fest/0.18.1: +    resolution: {integrity: sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==} +    engines: {node: '>=10'} +    dev: true + +  /type-fest/0.20.2: +    resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} +    engines: {node: '>=10'} +    dev: true + +  /type-fest/0.6.0: +    resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} +    engines: {node: '>=8'} +    dev: true + +  /type-fest/0.8.1: +    resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} +    engines: {node: '>=8'} +    dev: true + +  /uc.micro/1.0.6: +    resolution: {integrity: sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==} +    dev: true + +  /uglify-js/3.15.5: +    resolution: {integrity: sha512-hNM5q5GbBRB5xB+PMqVRcgYe4c8jbyZ1pzZhS6jbq54/4F2gFK869ZheiE5A8/t+W5jtTNpWef/5Q9zk639FNQ==} +    engines: {node: '>=0.8.0'} +    hasBin: true +    requiresBuild: true +    dev: true +    optional: true + +  /unbzip2-stream/1.4.3: +    resolution: {integrity: sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==} +    dependencies: +      buffer: 5.7.1 +      through: 2.3.8 +    dev: true + +  /unicode-canonical-property-names-ecmascript/2.0.0: +    resolution: {integrity: sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==} +    engines: {node: '>=4'} +    dev: true + +  /unicode-match-property-ecmascript/2.0.0: +    resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} +    engines: {node: '>=4'} +    dependencies: +      unicode-canonical-property-names-ecmascript: 2.0.0 +      unicode-property-aliases-ecmascript: 2.0.0 +    dev: true + +  /unicode-match-property-value-ecmascript/2.0.0: +    resolution: {integrity: sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==} +    engines: {node: '>=4'} +    dev: true + +  /unicode-property-aliases-ecmascript/2.0.0: +    resolution: {integrity: sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==} +    engines: {node: '>=4'} +    dev: true + +  /universalify/2.0.0: +    resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==} +    engines: {node: '>= 10.0.0'} +    dev: true + +  /uri-js/4.4.1: +    resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} +    dependencies: +      punycode: 2.1.1 +    dev: true + +  /util-deprecate/1.0.2: +    resolution: {integrity: sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=} +    dev: true + +  /v8-compile-cache/2.3.0: +    resolution: {integrity: sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==} +    dev: true + +  /validate-npm-package-license/3.0.4: +    resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} +    dependencies: +      spdx-correct: 3.1.1 +      spdx-expression-parse: 3.0.1 +    dev: true + +  /web-streams-polyfill/3.2.1: +    resolution: {integrity: sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==} +    engines: {node: '>= 8'} +    dev: true + +  /webidl-conversions/3.0.1: +    resolution: {integrity: sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=} +    dev: true + +  /whatwg-url/5.0.0: +    resolution: {integrity: sha1-lmRU6HZUYuN2RNNib2dCzotwll0=} +    dependencies: +      tr46: 0.0.3 +      webidl-conversions: 3.0.1 +    dev: true + +  /which-module/2.0.0: +    resolution: {integrity: sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=} +    dev: true + +  /which/1.3.1: +    resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} +    hasBin: true +    dependencies: +      isexe: 2.0.0 +    dev: true + +  /which/2.0.2: +    resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} +    engines: {node: '>= 8'} +    hasBin: true +    dependencies: +      isexe: 2.0.0 +    dev: true + +  /word-wrap/1.2.3: +    resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==} +    engines: {node: '>=0.10.0'} +    dev: true + +  /wordwrap/1.0.0: +    resolution: {integrity: sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=} +    dev: true + +  /wrap-ansi/6.2.0: +    resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} +    engines: {node: '>=8'} +    dependencies: +      ansi-styles: 4.3.0 +      string-width: 4.2.3 +      strip-ansi: 6.0.1 +    dev: true + +  /wrap-ansi/7.0.0: +    resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} +    engines: {node: '>=10'} +    dependencies: +      ansi-styles: 4.3.0 +      string-width: 4.2.3 +      strip-ansi: 6.0.1 +    dev: true + +  /wrappy/1.0.2: +    resolution: {integrity: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=} +    dev: true + +  /write-file-atomic/4.0.1: +    resolution: {integrity: sha512-nSKUxgAbyioruk6hU87QzVbY279oYT6uiwgDoujth2ju4mJ+TZau7SQBhtbTmUyuNYTuXnSyRn66FV0+eCgcrQ==} +    engines: {node: ^12.13.0 || ^14.15.0 || >=16} +    dependencies: +      imurmurhash: 0.1.4 +      signal-exit: 3.0.7 +    dev: true + +  /xtend/4.0.2: +    resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} +    engines: {node: '>=0.4'} +    dev: true + +  /y18n/4.0.3: +    resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} +    dev: true + +  /y18n/5.0.8: +    resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} +    engines: {node: '>=10'} +    dev: true + +  /yallist/4.0.0: +    resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} +    dev: true + +  /yaml/1.10.2: +    resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} +    engines: {node: '>= 6'} +    dev: true + +  /yargs-parser/18.1.3: +    resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} +    engines: {node: '>=6'} +    dependencies: +      camelcase: 5.3.1 +      decamelize: 1.2.0 +    dev: true + +  /yargs-parser/20.2.9: +    resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} +    engines: {node: '>=10'} +    dev: true + +  /yargs-parser/21.0.1: +    resolution: {integrity: sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==} +    engines: {node: '>=12'} +    dev: true + +  /yargs/15.4.1: +    resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} +    engines: {node: '>=8'} +    dependencies: +      cliui: 6.0.0 +      decamelize: 1.2.0 +      find-up: 4.1.0 +      get-caller-file: 2.0.5 +      require-directory: 2.1.1 +      require-main-filename: 2.0.0 +      set-blocking: 2.0.0 +      string-width: 4.2.3 +      which-module: 2.0.0 +      y18n: 4.0.3 +      yargs-parser: 18.1.3 +    dev: true + +  /yargs/16.2.0: +    resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} +    engines: {node: '>=10'} +    dependencies: +      cliui: 7.0.4 +      escalade: 3.1.1 +      get-caller-file: 2.0.5 +      require-directory: 2.1.1 +      string-width: 4.2.3 +      y18n: 5.0.8 +      yargs-parser: 20.2.9 +    dev: true + +  /yargs/17.5.1: +    resolution: {integrity: sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==} +    engines: {node: '>=12'} +    dependencies: +      cliui: 7.0.4 +      escalade: 3.1.1 +      get-caller-file: 2.0.5 +      require-directory: 2.1.1 +      string-width: 4.2.3 +      y18n: 5.0.8 +      yargs-parser: 21.0.1 +    dev: true + +  /yauzl/2.10.0: +    resolution: {integrity: sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=} +    dependencies: +      buffer-crc32: 0.2.13 +      fd-slicer: 1.1.0 +    dev: true diff --git a/docs/roadmap/index.md b/docs/roadmap/index.md deleted file mode 100644 index beb3fb3ec..000000000 --- a/docs/roadmap/index.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -layout: default -title: Roadmap -nav_order: 9 -has_children: true ---- - -The Authelia team consists of 3 globally distributed developers working actively on improving Authelia in our spare time -and we define our priorities based on a roadmap that we share here for transparency. We also try to balance features and  -improvements as much as possible with the maintenance tasks we have to perform to keep the backlog of open issues in a -reasonable state. If you're willing to contribute and help us move forward faster, get in touch with us on Matrix. We'll -be glad to share ideas and plans with you. - -Below are the prioritised roadmap items: - -1. Webauthn needs to be implemented because U2F is being deprecated in the browsers. Chrome displays an annoying popup -advertising the deprecation. This is being implemented [here](https://github.com/authelia/authelia/pull/2707). - -2. [Authelia acts as an OpenID Connect Provider](https://github.com/authelia/authelia/issues/189). This is a high -priority because currently the only way to pass authentication information back to the protected app is through the -use of HTTP headers as described -[here](https://www.authelia.com/docs/deployment/supported-proxies/#how-can-the-backend-be-aware-of-the-authenticated-users) -however, many apps either do not support this method or are starting to move away from this in favour of OpenID Connect or OAuth2 -internally or via plugins. **[In Preview](./oidc.md)** *this roadmap item is in preview status since information is not  -yet persisted in the database. More information can be found [here](./oidc.md) in the docs*. - -3. [Multilingual full support](https://github.com/authelia/authelia/issues/625). Support as been added but we heed to study multiple providers like Crowdin or Weblate -to help us translate in more languages and make Authelia available to even more people around the world!  - -4. [Protection of multiple root domains](https://github.com/authelia/authelia/issues/1198). This request has been upvoted many times and we heard you! -Currently, an Authelia setup is only able to protect all subdomains of a given root domain. This situation is challenging for -administrators maintaining services across multiple root domains so we have decided to prioritize this to enable those deployments. - -5. [User/Administrator interface](https://github.com/authelia/authelia/issues/303). Many use cases raised on Github relates to -being able to audit, configure and administrate a given account on Authelia. For instance, a user should be able to reset the password -manage MFA hardware devices and personal security policies, etc... An administrator should be able to unban accounts after a regulation ban, -kill sessions to reduce security risk due to compromised accounts and many other things. This item will be decomposed into multiple -items for implementing the features but there is preparatory work to be done on the permissions (likely role-based) we want to -implement. - -6. [Facilitate setup on Kubernetes](https://github.com/authelia/authelia/issues/575). There are mainly two objectives -here. First, we need to provide the documentation required to setup Authelia on Kubernetes. Even though, some users -already have it working and the feature is even tested in the project, there is a clear lack of documentation. The -second item is to provide a Helm chart to streamline the setup on Kubernetes. diff --git a/docs/roadmap/oidc.md b/docs/roadmap/oidc.md deleted file mode 100644 index 1267ac607..000000000 --- a/docs/roadmap/oidc.md +++ /dev/null @@ -1,154 +0,0 @@ ---- -layout: default -title: OpenID Connect -parent: Roadmap -nav_order: 1 ---- - -We have decided to implement [OpenID Connect] as a beta feature, it's suggested you only utilize it for testing and -providing feedback, and should take caution in relying on it in production as of now. [OpenID Connect] and it's related -endpoints are not enabled by default unless you specifically configure the [OpenID Connect] section. - -As [OpenID Connect] is fairly complex (the [OpenID Connect] Provider role especially so) it's intentional that it is -both a beta and that the implemented features are part of a thoughtful roadmap. Items that are not immediately obvious -as required (i.e. bug fixes or spec features), will likely be discussed in team meetings or on GitHub issues before being -added to the list. We want to implement this feature in a very thoughtful way in order to avoid security issues. - -The beta will be broken up into stages. Each stage will bring additional features. The following table is a *rough* plan -for which stage will have each feature, and may evolve over time: - -<table> -    <thead> -      <tr> -        <th class="tbl-header">Stage</th> -        <th class="tbl-header">Feature Description</th> -      </tr> -    </thead> -    <tbody> -      <tr> -        <td rowspan="8" class="tbl-header tbl-beta-stage">beta1 (4.29.0)</td> -        <td><a href="https://openid.net/specs/openid-connect-core-1_0.html#Consent" target="_blank" rel="noopener noreferrer">User Consent</a></td> -      </tr> -      <tr> -        <td><a href="https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowSteps" target="_blank" rel="noopener noreferrer">Authorization Code Flow</a></td> -      </tr> -      <tr> -        <td><a href="https://openid.net/specs/openid-connect-discovery-1_0.html" target="_blank" rel="noopener noreferrer">OpenID Connect Discovery</a></td> -      </tr> -      <tr> -        <td>RS256 Signature Strategy</td> -      </tr> -      <tr> -        <td>Per Client Scope/Grant Type/Response Type Restriction</td> -      </tr> -      <tr> -        <td>Per Client Authorization Policy (1FA/2FA)</td> -      </tr> -      <tr> -        <td class="tbl-beta-stage">Per Client List of Valid Redirection URI's</td> -      </tr> -      <tr> -        <td class="tbl-beta-stage"><a href="https://datatracker.ietf.org/doc/html/rfc6749#section-2.1" target="_blank" rel="noopener noreferrer">Confidential Client Type</a></td> -      </tr> -      <tr> -        <td rowspan="6" class="tbl-header tbl-beta-stage">beta2 (4.30.0)</td> -        <td class="tbl-beta-stage"><a href="https://openid.net/specs/openid-connect-core-1_0.html#UserInfo" target="_blank" rel="noopener noreferrer">Userinfo Endpoint</a> (missed in beta1)</td> -      </tr> -      <tr> -        <td class="tbl-beta-stage">Parameter Entropy Configuration</td> -      </tr> -      <tr> -        <td class="tbl-beta-stage">Token/Code Lifespan Configuration</td> -      </tr> -      <tr> -        <td class="tbl-beta-stage">Client Debug Messages</td> -      </tr> -      <tr> -        <td class="tbl-beta-stage">Client Audience</td> -      </tr> -      <tr> -        <td class="tbl-beta-stage"><a href="https://datatracker.ietf.org/doc/html/rfc6749#section-2.1" target="_blank" rel="noopener noreferrer">Public Client Type</a></td> -      </tr> -      <tr> -        <td rowspan="1" class="tbl-header tbl-beta-stage">beta3 (4.34.0)</td> -        <td>Proof Key for Code Exchange (PKCE) for Authorization Code Flow</td> -      </tr> -      <tr> -        <td rowspan="8" class="tbl-header tbl-beta-stage">beta5 (4.35.0)</td> -        <td>Token Storage</td> -      </tr> -      <tr> -        <td class="tbl-beta-stage">Audit Storage</td> -      </tr> -      <tr> -        <td class="tbl-beta-stage">Subject Storage</td> -      </tr> -      <tr> -        <td class="tbl-beta-stage"><a href="https://openid.net/specs/openid-connect-core-1_0.html#SubjectIDTypes" target="_blank">Pairwise Subject Identifier Type</a></td> -      </tr> -      <tr> -        <td class="tbl-beta-stage">Per-Client Consent Pre-Configuration</td> -      </tr> -      <tr> -        <td class="tbl-beta-stage">Cross-Origin Resource Sharing Configuration</td> -      </tr> -      <tr> -        <td class="tbl-beta-stage">Authentication Methods References Claim</td> -      </tr> -      <tr> -        <td class="tbl-beta-stage">Opaque Subject Identifiers (<a href="https://datatracker.ietf.org/doc/html/rfc4122" target="_blank">UUID</a> V4) for <code>sub</code> Claim</td> -      </tr> -      <tr> -        <td rowspan="2" class="tbl-header tbl-beta-stage">beta5 <sup>1</sup></td> -        <td class="tbl-beta-stage">Prompt Handling</td> -      </tr> -      <tr> -        <td class="tbl-beta-stage">Display Handling</td> -      </tr> -      <tr> -        <td rowspan="4" class="tbl-header tbl-beta-stage">beta6 <sup>1</sup></td> -        <td><a href="https://openid.net/specs/openid-connect-backchannel-1_0.html" target="_blank" rel="noopener noreferrer">Back-Channel Logout</a></td> -      </tr> -      <tr> -        <td>Deny Refresh on Session Expiration</td> -      </tr> -      <tr> -        <td><a href="https://openid.net/specs/openid-connect-messages-1_0-20.html#rotate.sig.keys" target="_blank" rel="noopener noreferrer">Signing Key Rotation Policy</a></td> -      </tr> -      <tr> -        <td class="tbl-beta-stage">Client Secrets Hashed in Configuration</td> -      </tr> -      <tr> -        <td class="tbl-header tbl-beta-stage">GA <sup>1</sup></td> -        <td class="tbl-beta-stage">General Availability after previous stages are vetted for bug fixes</td> -      </tr> -      <tr> -        <td rowspan="7" class="tbl-header">misc</td> -        <td>List of other features that may be implemented</td> -      </tr> -      <tr> -        <td class="tbl-beta-stage"><a href="https://openid.net/specs/openid-connect-frontchannel-1_0.html" target="_blank" rel="noopener noreferrer">Front-Channel Logout</a> <sup>2</sup></td> -      </tr> -      <tr> -        <td class="tbl-beta-stage"><a href="https://datatracker.ietf.org/doc/html/rfc8414" target="_blank" rel="noopener noreferrer">OAuth 2.0 Authorization Server Metadata</a> <sup>2</sup></td> -      </tr> -      <tr> -        <td class="tbl-beta-stage"><a href="https://openid.net/specs/openid-connect-session-1_0-17.html" target="_blank" rel="noopener noreferrer">OpenID Connect Session Management</a> <sup>2</sup></td> -      </tr> -      <tr> -        <td class="tbl-beta-stage">End-User Scope Grants <sup>2</sup></td> -      </tr> -      <tr> -        <td class="tbl-beta-stage">Client RBAC <sup>2</sup></td> -      </tr> -      <tr> -        <td class="tbl-beta-stage">Add <code>preferred_username</code> claim (4.33.2)</td> -      </tr> -    </tbody> -</table> - -¹ _This stage has not been implemented as of yet_. - -² _This individual feature has not been implemented as of yet_. - -[OpenID Connect]: https://openid.net/connect/ diff --git a/docs/security/index.md b/docs/security/index.md deleted file mode 100644 index 5341c3d68..000000000 --- a/docs/security/index.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -layout: default -title: Security -nav_order: 6 -has_children: true ---- - -# Security - -Authelia takes security very seriously. We follow the rule of  -[responsible disclosure](https://en.wikipedia.org/wiki/Responsible_disclosure), and we encourage the community to as  -well. - -***Important:*** Please see our [security policy](https://github.com/authelia/authelia/security/policy) if you discover -a security vulnerability. Our [security policy](https://github.com/authelia/authelia/security/policy) has several -methods of contact and more details about the processes we follow. - -For details about security measures implemented in Authelia, please follow this  -[link](https://www.authelia.com/docs/security/measures.html) and for reading about the threat model follow this  -[link](https://www.authelia.com/docs/security/threat-model.html).
\ No newline at end of file diff --git a/docs/static/android-chrome-192x192.png b/docs/static/android-chrome-192x192.png Binary files differnew file mode 100644 index 000000000..5aa1077a4 --- /dev/null +++ b/docs/static/android-chrome-192x192.png diff --git a/docs/static/android-chrome-512x512.png b/docs/static/android-chrome-512x512.png Binary files differnew file mode 100644 index 000000000..8f336c22c --- /dev/null +++ b/docs/static/android-chrome-512x512.png diff --git a/docs/static/apple-touch-icon.png b/docs/static/apple-touch-icon.png Binary files differnew file mode 100644 index 000000000..a14732570 --- /dev/null +++ b/docs/static/apple-touch-icon.png diff --git a/docs/static/authelia.png b/docs/static/authelia.png Binary files differnew file mode 100644 index 000000000..6fe024703 --- /dev/null +++ b/docs/static/authelia.png diff --git a/docs/static/css/vendor/.gitkeep b/docs/static/css/vendor/.gitkeep new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/docs/static/css/vendor/.gitkeep diff --git a/docs/static/favicon-16x16.png b/docs/static/favicon-16x16.png Binary files differnew file mode 100644 index 000000000..4d32b1ddb --- /dev/null +++ b/docs/static/favicon-16x16.png diff --git a/docs/static/favicon-32x32.png b/docs/static/favicon-32x32.png Binary files differnew file mode 100644 index 000000000..b864d250a --- /dev/null +++ b/docs/static/favicon-32x32.png diff --git a/docs/favicon.ico b/docs/static/favicon.ico Binary files differindex 46d3d0e2a..46d3d0e2a 100644 --- a/docs/favicon.ico +++ b/docs/static/favicon.ico diff --git a/docs/static/fonts/KaTeX_AMS-Regular.ttf b/docs/static/fonts/KaTeX_AMS-Regular.ttf Binary files differnew file mode 100644 index 000000000..737cf8eb5 --- /dev/null +++ b/docs/static/fonts/KaTeX_AMS-Regular.ttf diff --git a/docs/static/fonts/KaTeX_AMS-Regular.woff b/docs/static/fonts/KaTeX_AMS-Regular.woff Binary files differnew file mode 100644 index 000000000..38378bfba --- /dev/null +++ b/docs/static/fonts/KaTeX_AMS-Regular.woff diff --git a/docs/static/fonts/KaTeX_AMS-Regular.woff2 b/docs/static/fonts/KaTeX_AMS-Regular.woff2 Binary files differnew file mode 100644 index 000000000..a4d1ba641 --- /dev/null +++ b/docs/static/fonts/KaTeX_AMS-Regular.woff2 diff --git a/docs/static/fonts/KaTeX_Caligraphic-Bold.ttf b/docs/static/fonts/KaTeX_Caligraphic-Bold.ttf Binary files differnew file mode 100644 index 000000000..04d28abd9 --- /dev/null +++ b/docs/static/fonts/KaTeX_Caligraphic-Bold.ttf diff --git a/docs/static/fonts/KaTeX_Caligraphic-Bold.woff b/docs/static/fonts/KaTeX_Caligraphic-Bold.woff Binary files differnew file mode 100644 index 000000000..a01ce9060 --- /dev/null +++ b/docs/static/fonts/KaTeX_Caligraphic-Bold.woff diff --git a/docs/static/fonts/KaTeX_Caligraphic-Bold.woff2 b/docs/static/fonts/KaTeX_Caligraphic-Bold.woff2 Binary files differnew file mode 100644 index 000000000..37927274a --- /dev/null +++ b/docs/static/fonts/KaTeX_Caligraphic-Bold.woff2 diff --git a/docs/static/fonts/KaTeX_Caligraphic-Regular.ttf b/docs/static/fonts/KaTeX_Caligraphic-Regular.ttf Binary files differnew file mode 100644 index 000000000..b2ce555fd --- /dev/null +++ b/docs/static/fonts/KaTeX_Caligraphic-Regular.ttf diff --git a/docs/static/fonts/KaTeX_Caligraphic-Regular.woff b/docs/static/fonts/KaTeX_Caligraphic-Regular.woff Binary files differnew file mode 100644 index 000000000..bc169b7cd --- /dev/null +++ b/docs/static/fonts/KaTeX_Caligraphic-Regular.woff diff --git a/docs/static/fonts/KaTeX_Caligraphic-Regular.woff2 b/docs/static/fonts/KaTeX_Caligraphic-Regular.woff2 Binary files differnew file mode 100644 index 000000000..f1e38bba2 --- /dev/null +++ b/docs/static/fonts/KaTeX_Caligraphic-Regular.woff2 diff --git a/docs/static/fonts/KaTeX_Fraktur-Bold.ttf b/docs/static/fonts/KaTeX_Fraktur-Bold.ttf Binary files differnew file mode 100644 index 000000000..c42d16916 --- /dev/null +++ b/docs/static/fonts/KaTeX_Fraktur-Bold.ttf diff --git a/docs/static/fonts/KaTeX_Fraktur-Bold.woff b/docs/static/fonts/KaTeX_Fraktur-Bold.woff Binary files differnew file mode 100644 index 000000000..f30b54b3d --- /dev/null +++ b/docs/static/fonts/KaTeX_Fraktur-Bold.woff diff --git a/docs/static/fonts/KaTeX_Fraktur-Bold.woff2 b/docs/static/fonts/KaTeX_Fraktur-Bold.woff2 Binary files differnew file mode 100644 index 000000000..b7a83593a --- /dev/null +++ b/docs/static/fonts/KaTeX_Fraktur-Bold.woff2 diff --git a/docs/static/fonts/KaTeX_Fraktur-Regular.ttf b/docs/static/fonts/KaTeX_Fraktur-Regular.ttf Binary files differnew file mode 100644 index 000000000..413322824 --- /dev/null +++ b/docs/static/fonts/KaTeX_Fraktur-Regular.ttf diff --git a/docs/static/fonts/KaTeX_Fraktur-Regular.woff b/docs/static/fonts/KaTeX_Fraktur-Regular.woff Binary files differnew file mode 100644 index 000000000..5af51de9e --- /dev/null +++ b/docs/static/fonts/KaTeX_Fraktur-Regular.woff diff --git a/docs/static/fonts/KaTeX_Fraktur-Regular.woff2 b/docs/static/fonts/KaTeX_Fraktur-Regular.woff2 Binary files differnew file mode 100644 index 000000000..3874f93e8 --- /dev/null +++ b/docs/static/fonts/KaTeX_Fraktur-Regular.woff2 diff --git a/docs/static/fonts/KaTeX_Main-Bold.ttf b/docs/static/fonts/KaTeX_Main-Bold.ttf Binary files differnew file mode 100644 index 000000000..14390e012 --- /dev/null +++ b/docs/static/fonts/KaTeX_Main-Bold.ttf diff --git a/docs/static/fonts/KaTeX_Main-Bold.woff b/docs/static/fonts/KaTeX_Main-Bold.woff Binary files differnew file mode 100644 index 000000000..33b41998e --- /dev/null +++ b/docs/static/fonts/KaTeX_Main-Bold.woff diff --git a/docs/static/fonts/KaTeX_Main-Bold.woff2 b/docs/static/fonts/KaTeX_Main-Bold.woff2 Binary files differnew file mode 100644 index 000000000..f9b71cbe7 --- /dev/null +++ b/docs/static/fonts/KaTeX_Main-Bold.woff2 diff --git a/docs/static/fonts/KaTeX_Main-BoldItalic.ttf b/docs/static/fonts/KaTeX_Main-BoldItalic.ttf Binary files differnew file mode 100644 index 000000000..ad0761f43 --- /dev/null +++ b/docs/static/fonts/KaTeX_Main-BoldItalic.ttf diff --git a/docs/static/fonts/KaTeX_Main-BoldItalic.woff b/docs/static/fonts/KaTeX_Main-BoldItalic.woff Binary files differnew file mode 100644 index 000000000..115af4f07 --- /dev/null +++ b/docs/static/fonts/KaTeX_Main-BoldItalic.woff diff --git a/docs/static/fonts/KaTeX_Main-BoldItalic.woff2 b/docs/static/fonts/KaTeX_Main-BoldItalic.woff2 Binary files differnew file mode 100644 index 000000000..5c500c285 --- /dev/null +++ b/docs/static/fonts/KaTeX_Main-BoldItalic.woff2 diff --git a/docs/static/fonts/KaTeX_Main-Italic.ttf b/docs/static/fonts/KaTeX_Main-Italic.ttf Binary files differnew file mode 100644 index 000000000..fc8625c81 --- /dev/null +++ b/docs/static/fonts/KaTeX_Main-Italic.ttf diff --git a/docs/static/fonts/KaTeX_Main-Italic.woff b/docs/static/fonts/KaTeX_Main-Italic.woff Binary files differnew file mode 100644 index 000000000..2d3087ab4 --- /dev/null +++ b/docs/static/fonts/KaTeX_Main-Italic.woff diff --git a/docs/static/fonts/KaTeX_Main-Italic.woff2 b/docs/static/fonts/KaTeX_Main-Italic.woff2 Binary files differnew file mode 100644 index 000000000..08510d85a --- /dev/null +++ b/docs/static/fonts/KaTeX_Main-Italic.woff2 diff --git a/docs/static/fonts/KaTeX_Main-Regular.ttf b/docs/static/fonts/KaTeX_Main-Regular.ttf Binary files differnew file mode 100644 index 000000000..5115a044e --- /dev/null +++ b/docs/static/fonts/KaTeX_Main-Regular.ttf diff --git a/docs/static/fonts/KaTeX_Main-Regular.woff b/docs/static/fonts/KaTeX_Main-Regular.woff Binary files differnew file mode 100644 index 000000000..42b74ab13 --- /dev/null +++ b/docs/static/fonts/KaTeX_Main-Regular.woff diff --git a/docs/static/fonts/KaTeX_Main-Regular.woff2 b/docs/static/fonts/KaTeX_Main-Regular.woff2 Binary files differnew file mode 100644 index 000000000..18647fa6a --- /dev/null +++ b/docs/static/fonts/KaTeX_Main-Regular.woff2 diff --git a/docs/static/fonts/KaTeX_Math-BoldItalic.ttf b/docs/static/fonts/KaTeX_Math-BoldItalic.ttf Binary files differnew file mode 100644 index 000000000..326b523bd --- /dev/null +++ b/docs/static/fonts/KaTeX_Math-BoldItalic.ttf diff --git a/docs/static/fonts/KaTeX_Math-BoldItalic.woff b/docs/static/fonts/KaTeX_Math-BoldItalic.woff Binary files differnew file mode 100644 index 000000000..5b4041aa8 --- /dev/null +++ b/docs/static/fonts/KaTeX_Math-BoldItalic.woff diff --git a/docs/static/fonts/KaTeX_Math-BoldItalic.woff2 b/docs/static/fonts/KaTeX_Math-BoldItalic.woff2 Binary files differnew file mode 100644 index 000000000..ba55276d0 --- /dev/null +++ b/docs/static/fonts/KaTeX_Math-BoldItalic.woff2 diff --git a/docs/static/fonts/KaTeX_Math-Italic.ttf b/docs/static/fonts/KaTeX_Math-Italic.ttf Binary files differnew file mode 100644 index 000000000..f148fceeb --- /dev/null +++ b/docs/static/fonts/KaTeX_Math-Italic.ttf diff --git a/docs/static/fonts/KaTeX_Math-Italic.woff b/docs/static/fonts/KaTeX_Math-Italic.woff Binary files differnew file mode 100644 index 000000000..31d003849 --- /dev/null +++ b/docs/static/fonts/KaTeX_Math-Italic.woff diff --git a/docs/static/fonts/KaTeX_Math-Italic.woff2 b/docs/static/fonts/KaTeX_Math-Italic.woff2 Binary files differnew file mode 100644 index 000000000..9871ab6b8 --- /dev/null +++ b/docs/static/fonts/KaTeX_Math-Italic.woff2 diff --git a/docs/static/fonts/KaTeX_SansSerif-Bold.ttf b/docs/static/fonts/KaTeX_SansSerif-Bold.ttf Binary files differnew file mode 100644 index 000000000..dce35c8fd --- /dev/null +++ b/docs/static/fonts/KaTeX_SansSerif-Bold.ttf diff --git a/docs/static/fonts/KaTeX_SansSerif-Bold.woff b/docs/static/fonts/KaTeX_SansSerif-Bold.woff Binary files differnew file mode 100644 index 000000000..992cb3d6d --- /dev/null +++ b/docs/static/fonts/KaTeX_SansSerif-Bold.woff diff --git a/docs/static/fonts/KaTeX_SansSerif-Bold.woff2 b/docs/static/fonts/KaTeX_SansSerif-Bold.woff2 Binary files differnew file mode 100644 index 000000000..6dd10388a --- /dev/null +++ b/docs/static/fonts/KaTeX_SansSerif-Bold.woff2 diff --git a/docs/static/fonts/KaTeX_SansSerif-Italic.ttf b/docs/static/fonts/KaTeX_SansSerif-Italic.ttf Binary files differnew file mode 100644 index 000000000..a3eb86c38 --- /dev/null +++ b/docs/static/fonts/KaTeX_SansSerif-Italic.ttf diff --git a/docs/static/fonts/KaTeX_SansSerif-Italic.woff b/docs/static/fonts/KaTeX_SansSerif-Italic.woff Binary files differnew file mode 100644 index 000000000..f4fa252a2 --- /dev/null +++ b/docs/static/fonts/KaTeX_SansSerif-Italic.woff diff --git a/docs/static/fonts/KaTeX_SansSerif-Italic.woff2 b/docs/static/fonts/KaTeX_SansSerif-Italic.woff2 Binary files differnew file mode 100644 index 000000000..9f2501a3a --- /dev/null +++ b/docs/static/fonts/KaTeX_SansSerif-Italic.woff2 diff --git a/docs/static/fonts/KaTeX_SansSerif-Regular.ttf b/docs/static/fonts/KaTeX_SansSerif-Regular.ttf Binary files differnew file mode 100644 index 000000000..3be73ce17 --- /dev/null +++ b/docs/static/fonts/KaTeX_SansSerif-Regular.ttf diff --git a/docs/static/fonts/KaTeX_SansSerif-Regular.woff b/docs/static/fonts/KaTeX_SansSerif-Regular.woff Binary files differnew file mode 100644 index 000000000..ec283f418 --- /dev/null +++ b/docs/static/fonts/KaTeX_SansSerif-Regular.woff diff --git a/docs/static/fonts/KaTeX_SansSerif-Regular.woff2 b/docs/static/fonts/KaTeX_SansSerif-Regular.woff2 Binary files differnew file mode 100644 index 000000000..e46094fba --- /dev/null +++ b/docs/static/fonts/KaTeX_SansSerif-Regular.woff2 diff --git a/docs/static/fonts/KaTeX_Script-Regular.ttf b/docs/static/fonts/KaTeX_Script-Regular.ttf Binary files differnew file mode 100644 index 000000000..40c8a997a --- /dev/null +++ b/docs/static/fonts/KaTeX_Script-Regular.ttf diff --git a/docs/static/fonts/KaTeX_Script-Regular.woff b/docs/static/fonts/KaTeX_Script-Regular.woff Binary files differnew file mode 100644 index 000000000..4eafae758 --- /dev/null +++ b/docs/static/fonts/KaTeX_Script-Regular.woff diff --git a/docs/static/fonts/KaTeX_Script-Regular.woff2 b/docs/static/fonts/KaTeX_Script-Regular.woff2 Binary files differnew file mode 100644 index 000000000..69b1754d7 --- /dev/null +++ b/docs/static/fonts/KaTeX_Script-Regular.woff2 diff --git a/docs/static/fonts/KaTeX_Size1-Regular.ttf b/docs/static/fonts/KaTeX_Size1-Regular.ttf Binary files differnew file mode 100644 index 000000000..f0aff83ef --- /dev/null +++ b/docs/static/fonts/KaTeX_Size1-Regular.ttf diff --git a/docs/static/fonts/KaTeX_Size1-Regular.woff b/docs/static/fonts/KaTeX_Size1-Regular.woff Binary files differnew file mode 100644 index 000000000..0358ee4a3 --- /dev/null +++ b/docs/static/fonts/KaTeX_Size1-Regular.woff diff --git a/docs/static/fonts/KaTeX_Size1-Regular.woff2 b/docs/static/fonts/KaTeX_Size1-Regular.woff2 Binary files differnew file mode 100644 index 000000000..f951ed016 --- /dev/null +++ b/docs/static/fonts/KaTeX_Size1-Regular.woff2 diff --git a/docs/static/fonts/KaTeX_Size2-Regular.ttf b/docs/static/fonts/KaTeX_Size2-Regular.ttf Binary files differnew file mode 100644 index 000000000..4f72f1679 --- /dev/null +++ b/docs/static/fonts/KaTeX_Size2-Regular.ttf diff --git a/docs/static/fonts/KaTeX_Size2-Regular.woff b/docs/static/fonts/KaTeX_Size2-Regular.woff Binary files differnew file mode 100644 index 000000000..8a053d23a --- /dev/null +++ b/docs/static/fonts/KaTeX_Size2-Regular.woff diff --git a/docs/static/fonts/KaTeX_Size2-Regular.woff2 b/docs/static/fonts/KaTeX_Size2-Regular.woff2 Binary files differnew file mode 100644 index 000000000..181d9625a --- /dev/null +++ b/docs/static/fonts/KaTeX_Size2-Regular.woff2 diff --git a/docs/static/fonts/KaTeX_Size3-Regular.ttf b/docs/static/fonts/KaTeX_Size3-Regular.ttf Binary files differnew file mode 100644 index 000000000..56d2dc6c5 --- /dev/null +++ b/docs/static/fonts/KaTeX_Size3-Regular.ttf diff --git a/docs/static/fonts/KaTeX_Size3-Regular.woff b/docs/static/fonts/KaTeX_Size3-Regular.woff Binary files differnew file mode 100644 index 000000000..0ec99ad1a --- /dev/null +++ b/docs/static/fonts/KaTeX_Size3-Regular.woff diff --git a/docs/static/fonts/KaTeX_Size3-Regular.woff2 b/docs/static/fonts/KaTeX_Size3-Regular.woff2 Binary files differnew file mode 100644 index 000000000..c2985cd38 --- /dev/null +++ b/docs/static/fonts/KaTeX_Size3-Regular.woff2 diff --git a/docs/static/fonts/KaTeX_Size4-Regular.ttf b/docs/static/fonts/KaTeX_Size4-Regular.ttf Binary files differnew file mode 100644 index 000000000..baf02091a --- /dev/null +++ b/docs/static/fonts/KaTeX_Size4-Regular.ttf diff --git a/docs/static/fonts/KaTeX_Size4-Regular.woff b/docs/static/fonts/KaTeX_Size4-Regular.woff Binary files differnew file mode 100644 index 000000000..ff6731972 --- /dev/null +++ b/docs/static/fonts/KaTeX_Size4-Regular.woff diff --git a/docs/static/fonts/KaTeX_Size4-Regular.woff2 b/docs/static/fonts/KaTeX_Size4-Regular.woff2 Binary files differnew file mode 100644 index 000000000..a4e810da5 --- /dev/null +++ b/docs/static/fonts/KaTeX_Size4-Regular.woff2 diff --git a/docs/static/fonts/KaTeX_Typewriter-Regular.ttf b/docs/static/fonts/KaTeX_Typewriter-Regular.ttf Binary files differnew file mode 100644 index 000000000..e66c218df --- /dev/null +++ b/docs/static/fonts/KaTeX_Typewriter-Regular.ttf diff --git a/docs/static/fonts/KaTeX_Typewriter-Regular.woff b/docs/static/fonts/KaTeX_Typewriter-Regular.woff Binary files differnew file mode 100644 index 000000000..c66d149d5 --- /dev/null +++ b/docs/static/fonts/KaTeX_Typewriter-Regular.woff diff --git a/docs/static/fonts/KaTeX_Typewriter-Regular.woff2 b/docs/static/fonts/KaTeX_Typewriter-Regular.woff2 Binary files differnew file mode 100644 index 000000000..e5bf2ce1f --- /dev/null +++ b/docs/static/fonts/KaTeX_Typewriter-Regular.woff2 diff --git a/docs/static/fonts/bootstrap-icons.woff b/docs/static/fonts/bootstrap-icons.woff Binary files differnew file mode 100644 index 000000000..b26ccd1ac --- /dev/null +++ b/docs/static/fonts/bootstrap-icons.woff diff --git a/docs/static/fonts/bootstrap-icons.woff2 b/docs/static/fonts/bootstrap-icons.woff2 Binary files differnew file mode 100644 index 000000000..f865a4b26 --- /dev/null +++ b/docs/static/fonts/bootstrap-icons.woff2 diff --git a/docs/static/fonts/vendor/.gitkeep b/docs/static/fonts/vendor/.gitkeep new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/docs/static/fonts/vendor/.gitkeep diff --git a/docs/static/fonts/vendor/jost/jost-v4-latin-500.woff b/docs/static/fonts/vendor/jost/jost-v4-latin-500.woff Binary files differnew file mode 100644 index 000000000..eab8d1b68 --- /dev/null +++ b/docs/static/fonts/vendor/jost/jost-v4-latin-500.woff diff --git a/docs/static/fonts/vendor/jost/jost-v4-latin-500.woff2 b/docs/static/fonts/vendor/jost/jost-v4-latin-500.woff2 Binary files differnew file mode 100644 index 000000000..92349d19c --- /dev/null +++ b/docs/static/fonts/vendor/jost/jost-v4-latin-500.woff2 diff --git a/docs/static/fonts/vendor/jost/jost-v4-latin-500italic.woff b/docs/static/fonts/vendor/jost/jost-v4-latin-500italic.woff Binary files differnew file mode 100644 index 000000000..7a8ed959e --- /dev/null +++ b/docs/static/fonts/vendor/jost/jost-v4-latin-500italic.woff diff --git a/docs/static/fonts/vendor/jost/jost-v4-latin-500italic.woff2 b/docs/static/fonts/vendor/jost/jost-v4-latin-500italic.woff2 Binary files differnew file mode 100644 index 000000000..c6b9d56e9 --- /dev/null +++ b/docs/static/fonts/vendor/jost/jost-v4-latin-500italic.woff2 diff --git a/docs/static/fonts/vendor/jost/jost-v4-latin-700.woff b/docs/static/fonts/vendor/jost/jost-v4-latin-700.woff Binary files differnew file mode 100644 index 000000000..57390f51a --- /dev/null +++ b/docs/static/fonts/vendor/jost/jost-v4-latin-700.woff diff --git a/docs/static/fonts/vendor/jost/jost-v4-latin-700.woff2 b/docs/static/fonts/vendor/jost/jost-v4-latin-700.woff2 Binary files differnew file mode 100644 index 000000000..584073a80 --- /dev/null +++ b/docs/static/fonts/vendor/jost/jost-v4-latin-700.woff2 diff --git a/docs/static/fonts/vendor/jost/jost-v4-latin-700italic.woff b/docs/static/fonts/vendor/jost/jost-v4-latin-700italic.woff Binary files differnew file mode 100644 index 000000000..e23eedf07 --- /dev/null +++ b/docs/static/fonts/vendor/jost/jost-v4-latin-700italic.woff diff --git a/docs/static/fonts/vendor/jost/jost-v4-latin-700italic.woff2 b/docs/static/fonts/vendor/jost/jost-v4-latin-700italic.woff2 Binary files differnew file mode 100644 index 000000000..e56d892a6 --- /dev/null +++ b/docs/static/fonts/vendor/jost/jost-v4-latin-700italic.woff2 diff --git a/docs/static/fonts/vendor/jost/jost-v4-latin-italic.woff b/docs/static/fonts/vendor/jost/jost-v4-latin-italic.woff Binary files differnew file mode 100644 index 000000000..5dcd11159 --- /dev/null +++ b/docs/static/fonts/vendor/jost/jost-v4-latin-italic.woff diff --git a/docs/static/fonts/vendor/jost/jost-v4-latin-italic.woff2 b/docs/static/fonts/vendor/jost/jost-v4-latin-italic.woff2 Binary files differnew file mode 100644 index 000000000..9346c1d2a --- /dev/null +++ b/docs/static/fonts/vendor/jost/jost-v4-latin-italic.woff2 diff --git a/docs/static/fonts/vendor/jost/jost-v4-latin-regular.woff b/docs/static/fonts/vendor/jost/jost-v4-latin-regular.woff Binary files differnew file mode 100644 index 000000000..4f24758df --- /dev/null +++ b/docs/static/fonts/vendor/jost/jost-v4-latin-regular.woff diff --git a/docs/static/fonts/vendor/jost/jost-v4-latin-regular.woff2 b/docs/static/fonts/vendor/jost/jost-v4-latin-regular.woff2 Binary files differnew file mode 100644 index 000000000..7f0bf7556 --- /dev/null +++ b/docs/static/fonts/vendor/jost/jost-v4-latin-regular.woff2 diff --git a/docs/static/images/1FA.png b/docs/static/images/1FA.png Binary files differnew file mode 100644 index 000000000..e28a104da --- /dev/null +++ b/docs/static/images/1FA.png diff --git a/docs/images/2FA-METHODS.png b/docs/static/images/2FA-METHODS.png Binary files differindex 24d9e30d5..24d9e30d5 100644 --- a/docs/images/2FA-METHODS.png +++ b/docs/static/images/2FA-METHODS.png diff --git a/docs/static/images/archi.png b/docs/static/images/archi.png Binary files differnew file mode 100644 index 000000000..bda611cfc --- /dev/null +++ b/docs/static/images/archi.png diff --git a/docs/images/archi.svg b/docs/static/images/archi.svg index f0c16b78a..f0c16b78a 100644 --- a/docs/images/archi.svg +++ b/docs/static/images/archi.svg diff --git a/docs/images/authelia-title.png b/docs/static/images/authelia-title.png Binary files differindex 7994682f5..7994682f5 100644 --- a/docs/images/authelia-title.png +++ b/docs/static/images/authelia-title.png diff --git a/docs/images/logos/balto.svg b/docs/static/images/logos/balto.svg index 69b2b2215..69b2b2215 100644 --- a/docs/images/logos/balto.svg +++ b/docs/static/images/logos/balto.svg diff --git a/docs/images/logos/caddy.png b/docs/static/images/logos/caddy.png Binary files differindex d0d33ccf1..d0d33ccf1 100644 --- a/docs/images/logos/caddy.png +++ b/docs/static/images/logos/caddy.png diff --git a/docs/images/logos/docker.logo.png b/docs/static/images/logos/docker.logo.png Binary files differindex dc5b89699..dc5b89699 100644 --- a/docs/images/logos/docker.logo.png +++ b/docs/static/images/logos/docker.logo.png diff --git a/docs/images/logos/envoy.png b/docs/static/images/logos/envoy.png Binary files differindex 16017014c..16017014c 100644 --- a/docs/images/logos/envoy.png +++ b/docs/static/images/logos/envoy.png diff --git a/docs/images/logos/goland.svg b/docs/static/images/logos/goland.svg index 90fca253c..90fca253c 100644 --- a/docs/images/logos/goland.svg +++ b/docs/static/images/logos/goland.svg diff --git a/docs/images/logos/haproxy.png b/docs/static/images/logos/haproxy.png Binary files differindex acb6926e6..acb6926e6 100644 --- a/docs/images/logos/haproxy.png +++ b/docs/static/images/logos/haproxy.png diff --git a/docs/images/logos/intellij-idea.svg b/docs/static/images/logos/intellij-idea.svg index 455ae2146..455ae2146 100644 --- a/docs/images/logos/intellij-idea.svg +++ b/docs/static/images/logos/intellij-idea.svg diff --git a/docs/images/logos/jetbrains.svg b/docs/static/images/logos/jetbrains.svg index 75d4d2177..75d4d2177 100644 --- a/docs/images/logos/jetbrains.svg +++ b/docs/static/images/logos/jetbrains.svg diff --git a/docs/static/images/logos/kubernetes.png b/docs/static/images/logos/kubernetes.png Binary files differnew file mode 100644 index 000000000..5e2b1ab75 --- /dev/null +++ b/docs/static/images/logos/kubernetes.png diff --git a/docs/images/logos/nginx.png b/docs/static/images/logos/nginx.png Binary files differindex e879ce45d..e879ce45d 100644 --- a/docs/images/logos/nginx.png +++ b/docs/static/images/logos/nginx.png diff --git a/docs/images/logos/traefik.png b/docs/static/images/logos/traefik.png Binary files differindex 5c3c9783f..5c3c9783f 100644 --- a/docs/images/logos/traefik.png +++ b/docs/static/images/logos/traefik.png diff --git a/docs/images/logos/webstorm.svg b/docs/static/images/logos/webstorm.svg index 39ab7eb97..39ab7eb97 100644 --- a/docs/images/logos/webstorm.svg +++ b/docs/static/images/logos/webstorm.svg diff --git a/docs/static/images/vendor/.gitkeep b/docs/static/images/vendor/.gitkeep new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/docs/static/images/vendor/.gitkeep diff --git a/docs/static/js/vendor/.gitkeep b/docs/static/js/vendor/.gitkeep new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/docs/static/js/vendor/.gitkeep diff --git a/docs/static/site.webmanifest b/docs/static/site.webmanifest new file mode 100644 index 000000000..b39e0a88d --- /dev/null +++ b/docs/static/site.webmanifest @@ -0,0 +1 @@ +{"name":"Authelia","short_name":"Authelia","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#fff","background_color":"#fff","display":"standalone"} diff --git a/docs/static/videos/.gitkeep b/docs/static/videos/.gitkeep new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/docs/static/videos/.gitkeep diff --git a/docs/theme.toml b/docs/theme.toml new file mode 100644 index 000000000..7ffb6820f --- /dev/null +++ b/docs/theme.toml @@ -0,0 +1,14 @@ +name = "Doks" +license = "MIT" +licenselink = "https://github.com/h-enk/doks/blob/master/LICENSE" +description = "Hugo theme helping you build modern documentation websites that are secure, fast, and SEO-ready — by default." + +homepage = "https://github.com/h-enk/doks" +demosite = "https://doks.netlify.app" + +tags = ["landing page", "documentation", "blog", "minimal", "modern", "customizable", "search", "dark mode", "bootstrap"] +features = ["security aware", "fast by default", "seo-ready", "development tools", "bootstrap framework", "netlify-ready", "full text search", "page layouts", "dark mode"] + +[author] +  name = "Henk Verlinde" +  homepage = "https://henkverlinde.com" diff --git a/examples/compose/lite/README.md b/examples/compose/lite/README.md index be057a228..7494f622e 100644 --- a/examples/compose/lite/README.md +++ b/examples/compose/lite/README.md @@ -1,3 +1,3 @@  # Usage -Please see the [documentation](https://www.authelia.com/docs/deployment/deployment-lite.html) for usage instructions.
\ No newline at end of file +Please see the [documentation](https://www.authelia.com/integration/deployment/docker/#lite) for usage instructions. diff --git a/examples/templates/notifications/README.md b/examples/templates/notifications/README.md index 115332a51..17bf81f89 100644 --- a/examples/templates/notifications/README.md +++ b/examples/templates/notifications/README.md @@ -1,4 +1,4 @@  # Notification Templates  The following folder contains email templates as examples of what can be done with the email template system. See the -[docs](https://www.authelia.com/docs/configuration/notifier/#template_path) for more information.
\ No newline at end of file +[docs](https://www.authelia.com/reference/guides/notification-templates/) for more information. diff --git a/internal/commands/const.go b/internal/commands/const.go index 01b4624cd..008da12ed 100644 --- a/internal/commands/const.go +++ b/internal/commands/const.go @@ -13,7 +13,7 @@ An open-source authentication and authorization server providing  two-factor authentication and single sign-on (SSO) for your  applications via a web portal. -Documentation is available at: https://www.authelia.com/docs` +Documentation is available at: https://www.authelia.com/`  	cmdAutheliaExample = `authelia --config /etc/authelia/config.yml --config /etc/authelia/access-control.yml  authelia --config /etc/authelia/config.yml,/etc/authelia/access-control.yml diff --git a/internal/configuration/config.template.yml b/internal/configuration/config.template.yml index e38dbda84..cb5e13b2f 100644 --- a/internal/configuration/config.template.yml +++ b/internal/configuration/config.template.yml @@ -15,7 +15,7 @@  theme: light  ## The secret used to generate JWT tokens when validating user identity by email confirmation. JWT Secret can also be -## set using a secret: https://www.authelia.com/docs/configuration/secrets.html +## set using a secret: https://www.authelia.com/c/secrets  jwt_secret: a_very_important_secret  ## Default redirection URL @@ -52,7 +52,7 @@ server:    # asset_path: /config/assets/    ## Buffers usually should be configured to be the same value. -  ## Explanation at https://www.authelia.com/docs/configuration/server.html +  ## Explanation at https://www.authelia.com/c/server#buffer-sizes    ## Read buffer size adjusts the server's max incoming request size in bytes.    ## Write buffer size does the same for outgoing responses.    read_buffer_size: 4096 @@ -129,13 +129,13 @@ totp:    ## The TOTP algorithm to use.    ## It is CRITICAL you read the documentation before changing this option: -  ## https://www.authelia.com/docs/configuration/one-time-password.html#algorithm +  ## https://www.authelia.com/c/totp#algorithm    algorithm: sha1    ## The number of digits a user has to input. Must either be 6 or 8.    ## Changing this option only affects newly generated TOTP configurations.    ## It is CRITICAL you read the documentation before changing this option: -  ## https://www.authelia.com/docs/configuration/one-time-password.html#digits +  ## https://www.authelia.com/c/totp#digits    digits: 6    ## The period in seconds a one-time password is valid for. @@ -145,7 +145,8 @@ totp:    ## The skew controls number of one-time passwords either side of the current one that are valid.    ## Warning: before changing skew read the docs link below.    skew: 1 -  ## See: https://www.authelia.com/docs/configuration/one-time-password.html#input-validation to read the documentation. +  ## See: https://www.authelia.com/c/totp#input-validation to read +  ## the documentation.    ## The size of the generated shared secrets. Default is 32 and is sufficient in most use cases, minimum is 20.    secret_size: 32 @@ -181,7 +182,7 @@ duo_api:    disable: false    hostname: api-123456789.example.com    integration_key: ABCDEF -  ## Secret can also be set using a secret: https://www.authelia.com/docs/configuration/secrets.html +  ## Secret can also be set using a secret: https://www.authelia.com/c/secrets    secret_key: 1234567890abcdefghifjkl    enable_self_enrollment: false @@ -230,8 +231,8 @@ authentication_backend:    ## always belong to groups they belonged to at the time of login even if they have been removed from them in LDAP.    ## To force update on every request you can set this to '0' or 'always', this will increase processor demand.    ## See the below documentation for more information. -  ## Duration Notation docs:  https://www.authelia.com/docs/configuration/index.html#duration-notation-format -  ## Refresh Interval docs: https://www.authelia.com/docs/configuration/authentication/ldap.html#refresh-interval +  ## Duration Notation docs:  https://www.authelia.com/c/common#duration-notation-format +  ## Refresh Interval docs: https://www.authelia.com/c/1fa#refresh-interval    refresh_interval: 5m    ## @@ -249,7 +250,7 @@ authentication_backend:      ##      ## Depending on the option here certain other values in this section have a default value, notably all of the      ## attribute mappings have a default value that this config overrides, you can read more about these default values -    ## at https://www.authelia.com/docs/configuration/authentication/ldap.html#defaults +    ## at https://www.authelia.com/c/ldap#defaults      implementation: custom      ## The url to the ldap server. Format: <scheme>://<address>[:<port>]. @@ -294,7 +295,7 @@ authentication_backend:      ## The users filter used in search queries to find the user profile based on input filled in login form.      ## Various placeholders are available in the user filter which you can read about in the documentation which can -    ## be found at: https://www.authelia.com/docs/configuration/authentication/ldap.html#users-filter-replacements +    ## be found at: https://www.authelia.com/c/ldap#users-filter-replacements      ##      ## Recommended settings are as follows:      ## - Microsoft Active Directory: (&({username_attribute}={input})(objectCategory=person)(objectClass=user)) @@ -312,7 +313,7 @@ authentication_backend:      ## The groups filter used in search queries to find the groups based on relevant authenticated user.      ## Various placeholders are available in the groups filter which you can read about in the documentation which can -    ## be found at: https://www.authelia.com/docs/configuration/authentication/ldap.html#groups-filter-replacements +    ## be found at: https://www.authelia.com/c/ldap#groups-filter-replacements      ##      ## If your groups use the `groupOfUniqueNames` structure use this instead:      ##    (&(uniqueMember={dn})(objectClass=groupOfUniqueNames)) @@ -334,7 +335,7 @@ authentication_backend:      ## The username and password of the admin user.      user: cn=admin,dc=example,dc=com -    ## Password can also be set using a secret: https://www.authelia.com/docs/configuration/secrets.html +    ## Password can also be set using a secret: https://www.authelia.com/c/secrets      password: password    ## @@ -345,9 +346,9 @@ authentication_backend:    ## to be scaled to more than one instance. The options under 'password' have sane defaults, and as it has security    ## implications it is highly recommended you leave the default values. Before considering changing these settings    ## please read the docs page below: -  ## https://www.authelia.com/docs/configuration/authentication/file.html#password-hash-algorithm-tuning +  ## https://www.authelia.com/r/passwords#tuning    ## -  ## Important: Kubernetes (or HA) users must read https://www.authelia.com/docs/features/statelessness.html +  ## Important: Kubernetes (or HA) users must read https://www.authelia.com/t/statelessness    ##    # file:    #   path: /config/users_database.yml @@ -524,15 +525,15 @@ session:    domain: example.com    ## Sets the Cookie SameSite value. Possible options are none, lax, or strict. -  ## Please read https://www.authelia.com/docs/configuration/session/#same_site +  ## Please read https://www.authelia.com/c/session#same_site    same_site: lax    ## The secret to encrypt the session data. This is only used with Redis / Redis Sentinel. -  ## Secret can also be set using a secret: https://www.authelia.com/docs/configuration/secrets.html +  ## Secret can also be set using a secret: https://www.authelia.com/c/secrets    secret: insecure_session_secret    ## The value for expiration, inactivity, and remember_me_duration are in seconds or the duration notation format. -  ## See: https://www.authelia.com/docs/configuration/index.html#duration-notation-format +  ## See: https://www.authelia.com/c/common#duration-notation-format    ## All three of these values affect the cookie/session validity period. Longer periods are considered less secure    ## because a stolen cookie will last longer giving attackers more time to spy or attack. @@ -551,7 +552,7 @@ session:    ##    ## Redis Provider    ## -  ## Important: Kubernetes (or HA) users must read https://www.authelia.com/docs/features/statelessness.html +  ## Important: Kubernetes (or HA) users must read https://www.authelia.com/t/statelessness    ##    redis:      host: 127.0.0.1 @@ -562,7 +563,7 @@ session:      ## Username used for redis authentication. This is optional and a new feature in redis 6.0.      # username: authelia -    ## Password can also be set using a secret: https://www.authelia.com/docs/configuration/secrets.html +    ## Password can also be set using a secret: https://www.authelia.com/c/secrets      password: authelia      ## This is the Redis DB Index https://redis.io/commands/select (sometimes referred to as database number, DB, etc). @@ -625,11 +626,11 @@ regulation:    ## The time range during which the user can attempt login before being banned. The user is banned if the    ## authentication failed 'max_retries' times in a 'find_time' seconds window. Find Time accepts duration notation. -  ## See: https://www.authelia.com/docs/configuration/index.html#duration-notation-format +  ## See: https://www.authelia.com/c/common#duration-notation-format    find_time: 2m    ## The length of time before a banned user can login again. Ban Time accepts duration notation. -  ## See: https://www.authelia.com/docs/configuration/index.html#duration-notation-format +  ## See: https://www.authelia.com/c/common#duration-notation-format    ban_time: 5m  ## @@ -647,7 +648,7 @@ storage:    ## This stores the data in a SQLite3 Database.    ## This is only recommended for lightweight non-stateful installations.    ## -  ## Important: Kubernetes (or HA) users must read https://www.authelia.com/docs/features/statelessness.html +  ## Important: Kubernetes (or HA) users must read https://www.authelia.com/t/statelessness    ##    # local:    #   path: /config/db.sqlite3 @@ -660,7 +661,7 @@ storage:      port: 3306      database: authelia      username: authelia -    ## Password can also be set using a secret: https://www.authelia.com/docs/configuration/secrets.html +    ## Password can also be set using a secret: https://www.authelia.com/c/secrets      password: mypassword      timeout: 5s @@ -673,7 +674,7 @@ storage:    #   database: authelia    #   schema: public    #   username: authelia -  #   ## Password can also be set using a secret: https://www.authelia.com/docs/configuration/secrets.html +  #   ## Password can also be set using a secret: https://www.authelia.com/c/secrets    #   password: mypassword    #   timeout: 5s    #   ssl: @@ -694,7 +695,7 @@ notifier:    ##    ## File System (Notification Provider)    ## -  ## Important: Kubernetes (or HA) users must read https://www.authelia.com/docs/features/statelessness.html +  ## Important: Kubernetes (or HA) users must read https://www.authelia.com/t/statelessness    ##    # filesystem:    #   filename: /config/notification.txt @@ -723,7 +724,7 @@ notifier:      username: test      ## The password used for SMTP authentication. -    ## Can also be set using a secret: https://www.authelia.com/docs/configuration/secrets.html +    ## Can also be set using a secret: https://www.authelia.com/c/secrets      password: password      ## The sender is used to is used for the MAIL FROM command and the FROM header. @@ -768,14 +769,14 @@ notifier:    ## OpenID Connect (Identity Provider)    ##    ## It's recommended you read the documentation before configuration of this section: -  ## https://www.authelia.com/docs/configuration/identity-providers/oidc.html +  ## https://www.authelia.com/c/oidc    # oidc:      ## The hmac_secret is used to sign OAuth2 tokens (authorization code, access tokens and refresh tokens). -    ## HMAC Secret can also be set using a secret: https://www.authelia.com/docs/configuration/secrets.html +    ## HMAC Secret can also be set using a secret: https://www.authelia.com/c/secrets      # hmac_secret: this_is_a_secret_abc123abc123abc      ## The issuer_private_key is used to sign the JWT forged by OpenID Connect. -    ## Issuer Private Key can also be set using a secret: https://docs.authelia.com/configuration/secrets.html +    ## Issuer Private Key can also be set using a secret: https://www.authelia.com/c/secrets      # issuer_private_key: |      #   --- KEY START      #   --- KEY END diff --git a/internal/configuration/validator/const.go b/internal/configuration/validator/const.go index dd7cc40e6..adaa2a40b 100644 --- a/internal/configuration/validator/const.go +++ b/internal/configuration/validator/const.go @@ -188,10 +188,10 @@ const (  		"is invalid: must be one of 'deny', 'two_factor', 'one_factor' or 'bypass'"  	errAccessControlRuleBypassPolicyInvalidWithSubjects = "access control: rule %s: 'policy' option 'bypass' is " +  		"not supported when 'subject' option is configured: see " + -		"https://www.authelia.com/docs/configuration/access-control.html#bypass" +		"https://www.authelia.com/c/acl#bypass"  	errAccessControlRuleBypassPolicyInvalidWithSubjectsWithGroupDomainRegex = "access control: rule %s: 'policy' option 'bypass' is " +  		"not supported when 'domain_regex' option contains the user or group named matches. For more information see: " + -		"https://www.authelia.com/docs/configuration/access-control.html#bypass-and-user-identity" +		"https://www.authelia.com/c/acl#bypass-and-user-identity"  	errFmtAccessControlRuleNetworksInvalid = "access control: rule %s: the network '%s' is not a " +  		"valid Group Name, IP, or CIDR notation"  	errFmtAccessControlRuleSubjectInvalid = "access control: rule %s: 'subject' option '%s' is " + diff --git a/internal/handlers/handler_verify.go b/internal/handlers/handler_verify.go index 7bf8d7187..5d4ea3729 100644 --- a/internal/handlers/handler_verify.go +++ b/internal/handlers/handler_verify.go @@ -328,7 +328,7 @@ func generateVerifySessionHasUpToDateProfileTraceLogs(ctx *middlewares.AutheliaC  func verifySessionHasUpToDateProfile(ctx *middlewares.AutheliaCtx, targetURL *url.URL, userSession *session.UserSession,  	refreshProfile bool, refreshProfileInterval time.Duration) error {  	// TODO: Add a check for LDAP password changes based on a time format attribute. -	// See https://www.authelia.com/docs/security/threat-model.html#potential-future-guarantees +	// See https://www.authelia.com/o/threatmodel#potential-future-guarantees  	ctx.Logger.Tracef("Checking if we need check the authentication backend for an updated profile for %s.", userSession.Username)  	if !refreshProfile || userSession.Username == "" || targetURL == nil { diff --git a/web/.commitlintrc.js b/web/.commitlintrc.js index 7b4eeb7f0..a97f14f2f 100644 --- a/web/.commitlintrc.js +++ b/web/.commitlintrc.js @@ -54,5 +54,5 @@ module.exports = {          ],      },      defaultIgnores: true, -    helpUrl: "https://www.authelia.com/docs/contributing/commitmsg-guidelines.html", +    helpUrl: "https://www.authelia.com/contributing/development/guidelines-commit-message/",  };  | 
