Add support for Authelia

This commit is contained in:
Slavi Pantaleev 2023-09-12 13:26:38 +03:00
parent e48f6964e0
commit 6f980e5d93
6 changed files with 310 additions and 5 deletions

198
docs/services/authelia.md Normal file
View file

@ -0,0 +1,198 @@
# Authelia
[Authelia](https://www.authelia.com/) is an open-source [authentication](https://www.authelia.com/overview/authentication/introduction/) and [authorization](https://www.authelia.com/overview/authorization/access-control/) server and portal fulfilling the identity and access management (IAM) role of information security in providing [multi-factor authentication](https://www.authelia.com/overview/authentication/introduction/) and single sign-on (SSO) for your applications via a web portal.
Authelia has 2 [modes of operation](#modes-of-operation) (Forward-Auth and OpenID Connect). Read below for more information.
**Warning**: this service is a new addition to the playbook. It may not fully work or be configured in a suboptimal manner.
## Dependencies
This service requires the following other services:
- a database
- (optional) a [Postgres](postgres.md) database - if enabled for your Ansible inventory host, Authelia will be connected to the Postgres server automatically
- (optional) a MySQL / [MariaDB](mariadb.md) database - if enabled for your Ansible inventory host (and you don't also enable Postgres), Authelia will be connected to the MariaDB server automatically
- or SQLite, used by default when none of the above database choices is enabled for your Ansible inventory host
- (optional, but recommended) [Redis](redis.md)
- for storing session information in a persistent manner
- if Redis is not enabled, session information is stored in-memory and restarting Authelia destroys user sessions
- a [Traefik](traefik.md) reverse-proxy server
- for serving the Authelia portal website
- for protecting other Traefik-based services by adding the Authelia forward-auth middleware to them when [Protecting services with Authelia's forward-auth](#protecting-a-service-with-authelias-forward-auth)
## Configuration
To enable this service, add the following configuration to your `vars.yml` file and re-run the [installation](../installing.md) process:
```yaml
########################################################################
# #
# authelia #
# #
########################################################################
authelia_enabled: true
authelia_hostname: authelia.example.com
# The base domain that session cookies related to authentication will be set on.
#
# Forward-auth services that you will protect need to be hosted on subdomains under this base domain.
# (e.g. service1.example.com, service2.example.com)
#
# For OpenID Connect-protected services, this value does not matter.
#
# In any case, `authelia_config_session_domain` needs to be a subdomain of `authelia_hostname`.
authelia_config_session_domain: example.com
# The database encryption password.
# Changing this subsequently will cause trouble unless you use the CLI to migrate.
# Generating a strong password (e.g. `pwgen -s 64 1`) is recommended.
authelia_config_storage_encryption_key: ''
# Authelia supports either LDAP or a file-based authentication (user) database.
#
# Using the file-based database is easiest and it's what we do by default here
# by defining `authelia_config_authentication_backend_file_content`.
#
# To use LDAP, remove `authelia_config_authentication_backend_file_content` and define various
# `authelia_config_authentication_backend_ldap_*` variables.
authelia_config_authentication_backend_file_content: |
---
users:
john:
disabled: false
displayname: John Doe
password: PASSWORD_HASH_HERE
email: john@example.com
groups:
- admins
- dev
peter:
disabled: false
displayname: Peter Johnson
password: PASSWORD_HASH_HERE
email: peter@example.com
groups:
- dev
...
# You can define various authentication rules for each protected service here.
authelia_config_access_control_rules:
- domain: 'service1.example.com'
policy: one_factor
# The configuration below connects Authelia to the Redis instance, for session storage purposes.
# You may wish to run a separate Redis instance for Authelia, because Redis is not multi-tenant.
# Read more in docs/services/redis.md.
# If Redis is not available, session data will be stored in memory and will be lost on container restart.
authelia_config_session_redis_host: "{{ redis_identifier if redis_enabled else '' }}"
########################################################################
# #
# /authelia #
# #
########################################################################
```
### URL
In the example configuration above, we configure the service to be hosted at `https://authelia.example.com`.
While the Authelia Ansible role provides an `authelia_path_prefix` variable, Authelia does not support being hosted at a subpath right now.
On the Authelia base URL, there's a portal website where you can log in and manage your user account.
### Session storage
As mentioned in the default configuration above (see `authelia_config_session_redis_host`), you may wish to run [Redis](redis.md) for storing session data.
You may wish to run a separate Redis instance for Authelia, because Redis is not multi-tenant. See [our Redis documentation page](redis.md) for additional details. When running a separate instance of Redis, you may need to connect Authelia to the Redis instance's container network via the `authelia_container_additional_networks_custom` variable.
### Authentication storage providers
Authelia supports [LDAP](https://www.authelia.com/configuration/first-factor/ldap/) and [file-based](https://www.authelia.com/configuration/first-factor/file/) storage providers for the user database.
The default configuration above enables the file-based provider with the `authelia_config_authentication_backend_file_content` variable.
To use LDAP, remove the `authelia_config_authentication_backend_file_content` variable and define a bunch of `authelia_config_authentication_backend_ldap_*` variables.
### Modes of operation
Authelia has 2 [modes of operation](#modes-of-operation) which can be enabled simultaneously:
- **Forward-Auth**: [Forward-Auth](https://doc.traefik.io/traefik/middlewares/http/forwardauth/) is useful for protecting services which are not aware of authentication at all or which can receive authentication/authorization data via [HTTP headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers). Forward-Auth can act as a replacement for [HTTP Basic Authentication](https://en.wikipedia.org/wiki/Basic_access_authentication). It does this by acting as a companion to [common reverse proxies](https://www.authelia.com/overview/prologue/supported-proxies/), like [Traefik](traefik.md) which is frequently used by this playbook. To learn more, see [Protecting a service with Authelia's forward-auth](#protecting-a-service-with-authelias-forward-auth)
- **OpenID Connect**: experimental OpenID Connect support support, so that services which are OpenID Connect-compatible can use Authelia as an identity provider. To learn more, see [Protecting a service with OpenID Connect](#protecting-a-service-with-openid-connect)
#### Protecting a service with Authelia's forward-auth
If you're using [Traefik](traefik.md), you can easily protect services running on the same host by adding additional Traefik labels to them.
[Forward-Auth](https://doc.traefik.io/traefik/middlewares/http/forwardauth/) is useful for protecting services which are not aware of authentication at all or which can receive authentication/authorization data via [HTTP headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers).
Here's an example configuration for [Hubsite](hubsite.md) (a service which does not support authentication at all):
```yaml
hubsite_container_labels_additional_labels: |
traefik.http.routers.{{ hubsite_identifier }}.middlewares={{ authelia_identifier }}@docker
```
The Hubsite component does not use any Traefik middlewares, so defining a `.middlewares` configuration key and pointing it to the Authelia middleware works well.
For most other components, middlewares are in use in their default Traefik labels, so adding an additional `.middlewares` key will not work. You may need to inject additional middlewares on top of the default ones. Not all components may (yet) have a variable for doing so. Consider contributing to various roles to allow additional middlewares to be injected dynamically!
#### Protecting a service with OpenID Connect
For services which support OpenID Connect, you can enable the [experimental OpenID Connect identity provider](https://www.authelia.com/configuration/identity-providers/open-id-connect/) in Authelia.
You will need some additional configuration like this:
```yaml
authelia_config_identity_providers_oidc_clients:
- id: grafana
description: Grafana
secret: HASH_OF_THE_SHARED_SECRET
public: false
authorization_policy: one_factor
redirect_uris:
- https://mash.example.com/grafana/login/generic_oauth
scopes:
- openid
- profile
- groups
- email
userinfo_signing_algorithm: none
authelia_config_identity_providers_oidc_issuer_private_key: |
KEY CONTENT GOES HERE.
TO GENERATE A KEY, USE: `openssl genpkey -algorithm RSA -out FILE_NAME`
```
The example configuration above configures a single OpenID Connect client (application) called `grafana` (see the [Grafana](grafana.md) service supported by this playbook), which supposedly lives at the base URL of `https://mash.example.com/grafana`.
You will need to create a shared secret and hash its value (e.g. `php -r 'echo password_hash("PASSWORD_HERE", PASSWORD_ARGON2ID);'`). Feel free to use another language (or tool) for creating a hash as well. A few different hash algorithms are supported besides Argon2id.
Finally, configure your application, hooking it to Authelia's OpenID Connect identity provider.
You can get inspired by the [sample configuration](grafana.md#single-sign-on--authelia) we have created for [Grafana](grafana.md).
## Extending the Authelia configuration
The Authelia Ansible role provides various variables for configuring Authelia. You can see their default values in the [`defaults/main.yml` file](https://github.com/mother-of-all-self-hosting/ansible-role-authelia/blob/main/defaults/main.yml) of the Authelia role.
If a dedicated variable is not available for you to use or if you wish to override some hardcoded default, you can always use the `authelia_configuration_extension_yaml` Ansible variable for extending/overriding the default configuration.
## Related services
- [authentik](authentik.md) - An open-source Identity Provider focused on flexibility and versatility.
- [Keycloak](keycloak.md) - An open source identity and access management solution

View file

@ -81,11 +81,15 @@ grafana_dashboard_download_urls: |
}} }}
``` ```
### Single-Sign-On
Grafana supports Single-Sign-On (SSO) via OAUTH. To make use of this you'll need a Identity Provider like [authentik](./authentik.md), [Keycloak](./keycloak.md) or [Authelia](./authelia.md).
Below, you can find some examples for Grafana configuration.
#### Single-Sign-On / Authentik #### Single-Sign-On / Authentik
Grafana supports Single-Sign-On (SSO) via OAUTH. To make use of this you'll need a Identity Provider like [authentik](./authentik.md) or [Keycloak](./keycloak.md). Using authentik you can connect and Authentik like this:
* Create a new OAUTH provider in authentik called `grafana` * Create a new OAUTH provider in authentik called `grafana`
* Create an application also named `grafana` in authentik using this provider * Create an application also named `grafana` in authentik using this provider
* Add the following configuration to your `vars.yml` file and re-run the [installation](../installing.md) process (make sure to adjust `authentik.example.com`) * Add the following configuration to your `vars.yml` file and re-run the [installation](../installing.md) process (make sure to adjust `authentik.example.com`)
@ -114,6 +118,35 @@ grafana_environment_variables_additional_variables: |
Make sure the user you want to login as has an email address in authentik, otherwise there will be an error. Make sure the user you want to login as has an email address in authentik, otherwise there will be an error.
#### Single-Sign-On / Authelia
The configuration flow below assumes [Authelia](authelia.md) configured via the playbook, but you can run Authelia in another way too.
- Come up with a client ID you'd like to use. Example: `grafana`
- Generate a shared secret for the OpenID Connect application: `pwgen -s 64 1`. This is to be used in `GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET` below
- Hash the shared secret for use in Authelia's configuration (`authelia_config_identity_providers_oidc_clients`): `php -r 'echo password_hash("PASSWORD_HERE", PASSWORD_ARGON2ID);'`. Feel free to use another language (or tool) for creating a hash as well. A few different hash algorithms are supported besides Argon2id.
- Define this `grafana` client in Authelia via `authelia_config_identity_providers_oidc_clients`. See [example configuration](authelia.md#protecting-a-service-with-openid-connect) on the Authelia documentation page.
```yaml
# To make Grafana honor the expiration time of JWT tokens, enable this experimental feature below.
# grafana_feature_toggles_enable: accessTokenExpirationCheck
grafana_environment_variables_additional_variables: |
GF_AUTH_GENERIC_OAUTH_ENABLED=true
GF_AUTH_GENERIC_OAUTH_NAME=Authelia
GF_AUTH_GENERIC_OAUTH_CLIENT_ID=grafana
GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET=PLAIN_TEXT_SHARED_SECRET
GF_AUTH_GENERIC_OAUTH_SCOPES=openid profile email groups
GF_AUTH_GENERIC_OAUTH_EMPTY_SCOPES=false
GF_AUTH_GENERIC_OAUTH_AUTH_URL=https://authelia.example.com/api/oidc/authorization
GF_AUTH_GENERIC_OAUTH_TOKEN_URL=https://authelia.example.com/api/oidc/token
GF_AUTH_GENERIC_OAUTH_API_URL=https://authelia.example.com/api/oidc/userinfo
GF_AUTH_GENERIC_OAUTH_LOGIN_ATTRIBUTE_PATH=preferred_username
GF_AUTH_GENERIC_OAUTH_GROUPS_ATTRIBUTE_PATH=groups
GF_AUTH_GENERIC_OAUTH_NAME_ATTRIBUTE_PATH=name
GF_AUTH_GENERIC_OAUTH_USE_PKCE=true
```
## Usage ## Usage
After installation, you should be able to access your new Grafana instance at the configured URL (see above). After installation, you should be able to access your new Grafana instance at the configured URL (see above).

View file

@ -5,6 +5,7 @@
| [AUX](https://github.com/mother-of-all-self-hosting/ansible-role-aux) | Auxiliary file/directory management on your server via Ansible | [Link](services/auxiliary.md) | | [AUX](https://github.com/mother-of-all-self-hosting/ansible-role-aux) | Auxiliary file/directory management on your server via Ansible | [Link](services/auxiliary.md) |
| [AdGuard Home](https://adguard.com/en/adguard-home/overview.html/) | A network-wide DNS software for blocking ads & tracking | [Link](services/adguard-home.md) | | [AdGuard Home](https://adguard.com/en/adguard-home/overview.html/) | A network-wide DNS software for blocking ads & tracking | [Link](services/adguard-home.md) |
| [Appsmith](https://www.appsmith.com/) | Platform for building and deploying custom internal tools and applications without writing code | [Link](services/appsmith.md) | | [Appsmith](https://www.appsmith.com/) | Platform for building and deploying custom internal tools and applications without writing code | [Link](services/appsmith.md) |
| [Authelia](https://www.authelia.com/) | An open-source authentication and authorization server that can work as a companion to [common reverse proxies](https://www.authelia.com/overview/prologue/supported-proxies/) (like [Traefik](traefik.md) frequently used by this playbook) | [Link](services/authelia.md) |
| [authentik](https://goauthentik.io/) | An open-source Identity Provider focused on flexibility and versatility. | [Link](services/authentik.md) | | [authentik](https://goauthentik.io/) | An open-source Identity Provider focused on flexibility and versatility. | [Link](services/authentik.md) |
| [borgbackup](https://www.borgbackup.org/) (via [borgmatic](https://torsion.org/borgmatic/)) | A deduplicating backup program with optional compression and encryption| [Link](services/backup-borg.md) | | [borgbackup](https://www.borgbackup.org/) (via [borgmatic](https://torsion.org/borgmatic/)) | A deduplicating backup program with optional compression and encryption| [Link](services/backup-borg.md) |
| [Changedetection.io](https://github.com/dgtlmoon/changedetection.io) | A simple website change detection and restock monitoring solution. | [Link](services/changedetection.md) | | [Changedetection.io](https://github.com/dgtlmoon/changedetection.io) | A simple website change detection and restock monitoring solution. | [Link](services/changedetection.md) |

View file

@ -19,6 +19,61 @@ aux_file_default_group: "{{ mash_playbook_user_groupname }}"
######################################################################## ########################################################################
########################################################################
# #
# authelia #
# #
########################################################################
authelia_enabled: false
authelia_identifier: "{{ mash_playbook_service_identifier_prefix }}authelia"
authelia_uid: "{{ mash_playbook_uid }}"
authelia_gid: "{{ mash_playbook_gid }}"
authelia_base_path: "{{ mash_playbook_base_path }}/{{ mash_playbook_service_base_directory_name_prefix }}authelia"
authelia_systemd_required_services_list_auto: |
{{
([devture_postgres_identifier ~ '.service'] if devture_postgres_enabled and authelia_config_storage_postgres_host == devture_postgres_identifier else [])
}}
authelia_container_additional_networks_auto: |
{{
([mash_playbook_reverse_proxyable_services_additional_network] if mash_playbook_reverse_proxyable_services_additional_network else [])
+
([devture_postgres_container_network] if devture_postgres_enabled and authelia_config_storage_postgres_host == devture_postgres_identifier and authelia_container_network != devture_postgres_container_network else [])
}}
authelia_container_labels_traefik_enabled: "{{ mash_playbook_traefik_labels_enabled }}"
authelia_container_labels_traefik_docker_network: "{{ mash_playbook_reverse_proxyable_services_additional_network }}"
authelia_container_labels_traefik_entrypoints: "{{ devture_traefik_entrypoint_primary }}"
authelia_container_labels_traefik_tls_certResolver: "{{ devture_traefik_certResolver_primary }}"
authelia_config_jwt_secret: "{{ '%s' | format(mash_playbook_generic_secret_key) | password_hash('sha512', 'jwt.authelia', rounds=655555) | to_uuid }}"
authelia_config_session_secret: "{{ '%s' | format(mash_playbook_generic_secret_key) | password_hash('sha512', 'ses.authelia', rounds=655555) | to_uuid }}"
authelia_config_identity_providers_oidc_hmac_secret: "{{ '%s' | format(mash_playbook_generic_secret_key) | password_hash('sha512', 'hm.authelia', rounds=655555) | to_uuid }}"
authelia_config_storage_postgres_host: "{{ devture_postgres_identifier if devture_postgres_enabled else '' }}"
authelia_config_storage_postgres_port: "{{ '5432' if devture_postgres_enabled else '' }}"
authelia_config_storage_postgres_password: "{{ '%s' | format(mash_playbook_generic_secret_key) | password_hash('sha512', 'db.authelia', rounds=655555) | to_uuid }}"
# If Postgres and MariaDB are bot enabled, we favor Postgres.
# We only enable MySQL if it's the only enabled component (that is, if Postgres is not enabled at the same time).
authelia_config_storage_mysql_host: "{{ mariadb_identifier if mariadb_enabled and not devture_postgres_enabled else '' }}"
authelia_config_storage_mysql_port: "{{ '3306' if mariadb_enabled else '' }}"
authelia_config_storage_mysql_password: "{{ '%s' | format(mash_playbook_generic_secret_key) | password_hash('sha512', 'db.authelia', rounds=655555) | to_uuid }}"
########################################################################
# #
# /authelia #
# #
########################################################################
######################################################################## ########################################################################
# # # #
@ -73,6 +128,8 @@ devture_systemd_service_manager_services_list_auto: |
+ +
([{'name': (authentik_worker_identifier + '.service'), 'priority': 2000, 'groups': ['mash', 'authentik']}] if authentik_enabled else []) ([{'name': (authentik_worker_identifier + '.service'), 'priority': 2000, 'groups': ['mash', 'authentik']}] if authentik_enabled else [])
+ +
([{'name': (authelia_identifier + '.service'), 'priority': 2000, 'groups': ['mash', 'authelia']}] if authelia_enabled else [])
+
([{'name': (changedetection_identifier + '.service'), 'priority': 2100, 'groups': ['mash', 'changedetection']}] if changedetection_enabled else []) ([{'name': (changedetection_identifier + '.service'), 'priority': 2100, 'groups': ['mash', 'changedetection']}] if changedetection_enabled else [])
+ +
([{'name': (changedetection_playwright_driver_identifier + '.service'), 'priority': 2000, 'groups': ['mash', 'changedetection']}] if changedetection_playwright_driver_enabled else []) ([{'name': (changedetection_playwright_driver_identifier + '.service'), 'priority': 2000, 'groups': ['mash', 'changedetection']}] if changedetection_playwright_driver_enabled else [])
@ -258,6 +315,12 @@ devture_postgres_systemd_services_to_stop_for_maintenance_list: |
devture_postgres_managed_databases_auto: | devture_postgres_managed_databases_auto: |
{{ {{
([{
'name': authelia_config_storage_postgres_database,
'username': authelia_config_storage_postgres_username,
'password': authelia_config_storage_postgres_password,
}] if authelia_enabled and authelia_config_storage_postgres_host == devture_postgres_identifier else [])
+
([{ ([{
'name': authentik_database_name, 'name': authentik_database_name,
'username': authentik_database_username, 'username': authentik_database_username,
@ -2234,9 +2297,14 @@ mariadb_base_path: "{{ mash_playbook_base_path }}/{{ mash_playbook_service_base_
mariadb_uid: "{{ mash_playbook_uid }}" mariadb_uid: "{{ mash_playbook_uid }}"
mariadb_gid: "{{ mash_playbook_gid }}" mariadb_gid: "{{ mash_playbook_gid }}"
# This will be extended in the future, to auto-create databases for services which depend on MariaDB. mariadb_managed_databases_auto: |
# See `devture_postgres_managed_databases_auto` {{
mariadb_managed_databases_auto: [] ([{
'name': authelia_config_storage_mysql_database,
'username': authelia_config_storage_mysql_username,
'password': authelia_config_storage_mysql_password,
}] if authelia_enabled and authelia_config_storage_mysql_host == mariadb_identifier else [])
}}
######################################################################## ########################################################################
# # # #

View file

@ -6,6 +6,9 @@
- src: git+https://github.com/mother-of-all-self-hosting/ansible-role-appsmith.git - src: git+https://github.com/mother-of-all-self-hosting/ansible-role-appsmith.git
version: v1.9.35-0 version: v1.9.35-0
name: appsmith name: appsmith
- src: git+https://github.com/mother-of-all-self-hosting/ansible-role-authelia.git
version: v4.37.5-0
name: authelia
- src: git+https://github.com/mother-of-all-self-hosting/ansible-role-authentik.git - src: git+https://github.com/mother-of-all-self-hosting/ansible-role-authentik.git
version: v2023.8.2-0 version: v2023.8.2-0
name: authentik name: authentik

View file

@ -60,6 +60,8 @@
- role: galaxy/appsmith - role: galaxy/appsmith
- role: galaxy/authelia
- role: galaxy/authentik - role: galaxy/authentik
- role: galaxy/backup_borg - role: galaxy/backup_borg