From 2f18fc9570edc70f35cddb3973dfc7ac33402d31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Fra=C3=9F?= Date: Sat, 16 Dec 2023 11:33:38 +0100 Subject: [PATCH] [mod] role:authelia --- ansible/roles/authelia/defaults/main.json | 2 +- ansible/roles/authelia/files/conf-compose.py | 132 ++++++++++++++ ansible/roles/authelia/info.md | 7 +- ansible/roles/authelia/tasks/main.json | 90 ++++------ .../templates/conf-client-dummy.json.j2 | 7 + .../authelia/templates/conf-main.json.j2 | 166 ++++++++++++++++++ .../authelia/templates/configuration.yml.j2 | 141 --------------- .../roles/authelia/templates/systemd-unit.j2 | 11 -- 8 files changed, 349 insertions(+), 207 deletions(-) create mode 100644 ansible/roles/authelia/files/conf-compose.py create mode 100644 ansible/roles/authelia/templates/conf-client-dummy.json.j2 create mode 100644 ansible/roles/authelia/templates/conf-main.json.j2 delete mode 100644 ansible/roles/authelia/templates/configuration.yml.j2 delete mode 100644 ansible/roles/authelia/templates/systemd-unit.j2 diff --git a/ansible/roles/authelia/defaults/main.json b/ansible/roles/authelia/defaults/main.json index 7c00228..44809f8 100644 --- a/ansible/roles/authelia/defaults/main.json +++ b/ansible/roles/authelia/defaults/main.json @@ -1,6 +1,6 @@ { "var_authelia_version": "4.37.5", - "var_authelia_variant": "amd64", + "var_authelia_architecture": "amd64", "var_authelia_listen_address": "0.0.0.0", "var_authelia_jwt_secret": "authelia_jwt_secret", "var_authelia_users_file_path": "/var/authelia/users.yml", diff --git a/ansible/roles/authelia/files/conf-compose.py b/ansible/roles/authelia/files/conf-compose.py new file mode 100644 index 0000000..92a76b8 --- /dev/null +++ b/ansible/roles/authelia/files/conf-compose.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python3 + +import sys as _sys +import os as _os +import yaml as _yaml +import json as _json +import argparse as _argparse + + +def file_read(path): + handle = open(path, "r") + content = handle.read() + handle.close() + return content + + +def file_write(path, content): + directory = _os.path.dirname(path) + if (not _os.path.exists(directory)): + _os.makedirs(directory, exist_ok = True) + else: + pass + handle = open(path, "w") + handle.write(content) + handle.close() + return content + + +def dict_merge(core, mantle, path = None): + if (path is None): + path = [] + result = {} + for source in [core, mantle]: + for (key, value_new, ) in source.items(): + path_ = (path + [key]) + type_new = type(value_new) + if (not (key in result)): + result[key] = value_new + else: + value_old = result[key] + type_old = type(value_old) + if (value_old is None): + result[key] = value_new + else: + if (not (type_old == type_new)): + raise ValueError( + "type mismatch at path %s: %s vs. %s" + % ( + ".".join(path), + str(type_old), + str(type_new), + ) + ) + else: + if (type_old == dict): + result[key] = dict_merge(value_old, value_new, path_) + elif (type_old == list): + result[key] = (value_old + value_new) + else: + result[key] = value_new + return result + + +def main(): + ## args + argument_parser = _argparse.ArgumentParser() + argument_parser.add_argument( + "-m", + "--main-file-path", + type = str, + dest = "main_file_path", + default = "/etc/authelia/conf.d/main.json", + metavar = "", + ) + argument_parser.add_argument( + "-c", + "--clients-directory-path", + type = str, + dest = "clients_directory_path", + default = "/etc/authelia/conf.d/clients", + metavar = "", + ) + argument_parser.add_argument( + "-f", + "--output-format", + type = str, + choices = ["json", "yaml"], + dest = "output_format", + default = "yaml", + metavar = "", + ) + argument_parser.add_argument( + "-o", + "--output-path", + type = str, + dest = "output_path", + default = "/etc/authelia/configuration.yml", + metavar = "", + ) + args = argument_parser.parse_args() + + ## exec + data = {} + ### main + if True: + data_ = _json.loads(file_read(args.main_file_path)) + data = dict_merge(data, data_) + ### clients + if True: + for name in _os.listdir(args.clients_directory_path): + data__ = _json.loads(file_read(_os.path.join(args.clients_directory_path, name))) + data_ = { + "identity_providers": { + "oidc": { + "clients": [data__] + } + } + } + data = dict_merge(data, data_) + + ## output + if True: + if (args.output_format == "json"): + output_content = _json.dumps(data, indent = "\t") + elif (args.output_format == "yaml"): + output_content = _yaml.dump(data) + else: + raise ValueError("invalid output format") + file_write(args.output_path, output_content) + + +main() diff --git a/ansible/roles/authelia/info.md b/ansible/roles/authelia/info.md index a980bea..f025edb 100644 --- a/ansible/roles/authelia/info.md +++ b/ansible/roles/authelia/info.md @@ -1,6 +1,11 @@ +## Beschreibung + +- zum Aufsetzen des Authentifizierungs-Dienstes [Authelia](https://www.authelia.com/) +- um einen Clients hinzuzfügen, erstellt man eine entsprechende JSON-Datei in `/etc/authelia/conf.d/clients` und führt aus `/usr/bin/authelia-conf-compose` + + ## Verweise -- [Projekt-Website](https://www.authelia.com/) - [GitHub-Seite](https://github.com/authelia/authelia) - [Installations-Anleitung](https://www.authelia.com/integration/deployment/bare-metal/) - [Dokumentation | Konfiguration](https://www.authelia.com/configuration/) diff --git a/ansible/roles/authelia/tasks/main.json b/ansible/roles/authelia/tasks/main.json index fe83c24..945d9cf 100644 --- a/ansible/roles/authelia/tasks/main.json +++ b/ansible/roles/authelia/tasks/main.json @@ -1,7 +1,6 @@ [ { -"when": false, - "name": "prepare package installation 1", + "name": "packages | prerequisites", "become": true, "ansible.builtin.apt": { "pkg": [ @@ -11,16 +10,14 @@ } }, { -"when": false, - "name": "prepare package installation 2", + "name": "packages | keys", "become": true, "ansible.builtin.apt_key": { "url": "https://apt.authelia.com/organization/signing.asc" } }, { -"when": false, - "name": "prepare package installation 3", + "name": "packages | repository", "become": true, "ansible.builtin.apt_repository": { "repo": "deb https://apt.authelia.com/stable/debian/debian/ all main" @@ -28,59 +25,18 @@ }, { -"when": false, - "name": "install packages", + "name": "packages | installation", "become": true, "ansible.builtin.apt": { "update_cache": true, "pkg": [ "openssl", "python3-cryptography", + "python3-yaml", "authelia" ] } }, - { - "name": "download", - "delegate_to": "localhost", - "ansible.builtin.get_url": { - "url": "https://github.com/authelia/authelia/releases/download/v{{var_authelia_version}}/authelia-v{{var_authelia_version}}-linux-{{var_authelia_variant}}.tar.gz", - "dest": "/tmp/authelia.tar.gz" - } - }, - { - "name": "unpack | preparation", - "delegate_to": "localhost", - "ansible.builtin.file": { - "state": "directory", - "dest": "/tmp/authelia" - } - }, - { - "name": "unpack | execution", - "delegate_to": "localhost", - "ansible.builtin.unarchive": { - "src": "/tmp/authelia.tar.gz", - "dest": "/tmp/authelia" - } - }, - { - "name": "setup binary", - "become": true, - "ansible.builtin.copy": { - "src": "/tmp/authelia/authelia-linux-{{var_authelia_variant}}", - "dest": "/usr/bin/authelia", - "mode": "0744" - } - }, - { - "name": "systemd unit", - "become": true, - "ansible.builtin.template": { - "src": "systemd-unit.j2", - "dest": "/etc/systemd/system/authelia.service" - } - }, { "name": "generate private key for signing OIDC JWTs", "become": true, @@ -93,11 +49,40 @@ "register": "temp_tls_result" }, { - "name": "emplace configuration", + "name": "configuration | compose script", + "become": true, + "ansible.builtin.copy": { + "src": "conf-compose.py", + "dest": "/usr/bin/authelia-conf-compose", + "mode": "0700" + } + }, + { + "name": "configuration | directories", + "become": true, + "loop": [ + "/etc/authelia/conf.d", + "/etc/authelia/conf.d/clients" + ], + "ansible.builtin.file": { + "state": "directory", + "path": "{{item}}" + } + }, + { + "name": "configuration | main", "become": true, "ansible.builtin.template": { - "src": "configuration.yml.j2", - "dest": "/etc/authelia/configuration.yml" + "src": "conf-main.json.j2", + "dest": "/etc/authelia/conf.d/main.json" + } + }, + { + "name": "configuration | client | dummy", + "become": true, + "ansible.builtin.template": { + "src": "conf-client-dummy.json.j2", + "dest": "/etc/authelia/conf.d/clients/dummy.json" } }, { @@ -128,7 +113,6 @@ "name": "apply", "become": true, "ansible.builtin.systemd_service": { - "enabled": true, "state": "restarted", "name": "authelia" } diff --git a/ansible/roles/authelia/templates/conf-client-dummy.json.j2 b/ansible/roles/authelia/templates/conf-client-dummy.json.j2 new file mode 100644 index 0000000..88dcf25 --- /dev/null +++ b/ansible/roles/authelia/templates/conf-client-dummy.json.j2 @@ -0,0 +1,7 @@ +{ + "public": false, + "id": "dummy", + "secret": "d1424b378e4fbbc153f330f33b74ab192525b98cc2dd58b2e8d01c2737be00c6", + "redirect_uris": [ + ] +} diff --git a/ansible/roles/authelia/templates/conf-main.json.j2 b/ansible/roles/authelia/templates/conf-main.json.j2 new file mode 100644 index 0000000..5fa6b6d --- /dev/null +++ b/ansible/roles/authelia/templates/conf-main.json.j2 @@ -0,0 +1,166 @@ +{ + "theme": "auto", + "jwt_secret": "{{var_authelia_jwt_secret}}", + "default_2fa_method": "totp", + "server": { + "host": "{{var_authelia_listen_address}}", + "port": 9091, + "path": "", + "enable_pprof": false, + "enable_expvars": false, + "disable_healthcheck": false + }, + "log": { + "level": "info", + "format": "json", + "file_path": "{{var_authelia_log_file_path}}", + "keep_stdout": false + }, + "telemetry": { + "metrics": { + "enabled": false, + "address": "tcp://0.0.0.0:9959" + } + }, + "totp": { + "disable": false, + "issuer": "authelia.com", + "algorithm": "sha1", + "digits": 6, + "period": 30, + "skew": 1, + "secret_size": 32 + }, + "webauthn": { + "disable": true, + "timeout": "60s", + "display_name": "Authelia", + "attestation_conveyance_preference": "indirect", + "user_verification": "preferred" + }, + "ntp": { + "address": "{{var_authelia_ntp_server}}", + "version": 4, + "max_desync": "3s", + "disable_startup_check": false, + "disable_failure": false + }, + "authentication_backend": { + "password_reset": { + "disable": true, + "custom_url": "" + }, + "refresh_interval": "5m", + "file": { + "path": "{{var_authelia_users_file_path}}", + "watch": true, + "search": { + "email": false, + "case_insensitive": false + }, + "password": { + "algorithm": "argon2", + "argon2": { + "variant": "argon2id", + "iterations": 3, + "memory": 65536, + "parallelism": 4, + "key_length": 32, + "salt_length": 16 + }, + "scrypt": { + "iterations": 16, + "block_size": 8, + "parallelism": 1, + "key_length": 32, + "salt_length": 16 + }, + "pbkdf2": { + "variant": "sha512", + "iterations": 310000, + "salt_length": 16 + }, + "sha2crypt": { + "variant": "sha512", + "iterations": 50000, + "salt_length": 16 + }, + "bcrypt": { + "variant": "standard", + "cost": 12 + } + } + } + }, + "password_policy": { + "standard": { + "enabled": false, + "min_length": 8, + "max_length": 0, + "require_uppercase": true, + "require_lowercase": true, + "require_number": true, + "require_special": true + }, + "zxcvbn": { + "enabled": false, + "min_score": 3 + } + }, + "access_control": { + "default_policy": "one_factor" + }, + "session": { + "name": "authelia_session", + "domain": "{{var_authelia_session_domain}}", + "same_site": "lax", + "secret": "{{var_authelia_session_secret}}", + "expiration": "1h", + "inactivity": "5m", + "remember_me_duration": "1M" + }, + "regulation": { + "max_retries": 3, + "find_time": "2m", + "ban_time": "5m" + }, + "storage": { + "encryption_key": "{{var_authelia_storage_encryption_key}}", + "local": { + "path": "{{var_authelia_storage_path}}" + } + }, + "notifier": { + "disable_startup_check": true, +{% if var_authelia_notification_mode == "file" %} + "filesystem": { + "filename": "{{var_authelia_notification_file_path}}" + } +{% endif %} +{% if var_authelia_notification_mode == "smtp" %} + "smtp": { + "host": "{{var_authelia_notification_smtp_host}}", + "port": {{var_authelia_notification_smtp_port}}, + "username": "{{var_authelia_notification_smtp_username}}", + "password": "{{var_authelia_notification_smtp_password}}", + "sender": "{{var_authelia_notification_smtp_sender}}", + "disable_require_tls": false, + "disable_html_emails": false, + "tls": { + "skip_verify": false + } + } +{% endif %} + }, + "identity_providers": { + "oidc": { + "hmac_secret": "{{var_authelia_oidc_hmac_secret}}", + "issuer_private_key": "{{temp_tls_result.privatekey | replace('\n', '\\n')}}", + "cors": { + "allowed_origins_from_client_redirect_uris": true + }, + "clients": [ + ] + } + } +} diff --git a/ansible/roles/authelia/templates/configuration.yml.j2 b/ansible/roles/authelia/templates/configuration.yml.j2 deleted file mode 100644 index 8fc19ad..0000000 --- a/ansible/roles/authelia/templates/configuration.yml.j2 +++ /dev/null @@ -1,141 +0,0 @@ -theme: auto -jwt_secret: "{{var_authelia_jwt_secret}}" -default_2fa_method: totp -server: - host: "{{var_authelia_listen_address}}" - port: 9091 - path: "" - enable_pprof: false - enable_expvars: false - disable_healthcheck: false -log: - level: info - format: json - file_path: {{var_authelia_log_file_path}} - keep_stdout: false -telemetry: - metrics: - enabled: false - address: tcp://0.0.0.0:9959 -totp: - disable: false - issuer: authelia.com - algorithm: sha1 - digits: 6 - period: 30 - skew: 1 - secret_size: 32 -webauthn: - disable: true - timeout: 60s - display_name: Authelia - attestation_conveyance_preference: indirect - user_verification: preferred -ntp: - address: "{{var_authelia_ntp_server}}" - version: 4 - max_desync: 3s - disable_startup_check: false - disable_failure: false -authentication_backend: - password_reset: - disable: true - custom_url: "" - refresh_interval: 5m - file: - path: "{{var_authelia_users_file_path}}" - watch: true - search: - email: false - case_insensitive: false - password: - algorithm: argon2 - argon2: - variant: argon2id - iterations: 3 - memory: 65536 - parallelism: 4 - key_length: 32 - salt_length: 16 - scrypt: - iterations: 16 - block_size: 8 - parallelism: 1 - key_length: 32 - salt_length: 16 - pbkdf2: - variant: sha512 - iterations: 310000 - salt_length: 16 - sha2crypt: - variant: sha512 - iterations: 50000 - salt_length: 16 - bcrypt: - variant: standard - cost: 12 -password_policy: - standard: - enabled: false - min_length: 8 - max_length: 0 - require_uppercase: true - require_lowercase: true - require_number: true - require_special: true - zxcvbn: - enabled: false - min_score: 3 -access_control: - default_policy: one_factor -session: - name: authelia_session - domain: "{{var_authelia_session_domain}}" - same_site: lax - secret: "{{var_authelia_session_secret}}" - expiration: 1h - inactivity: 5m - remember_me_duration: 1M -regulation: - max_retries: 3 - find_time: 2m - ban_time: 5m -storage: - encryption_key: "{{var_authelia_storage_encryption_key}}" - local: - path: "{{var_authelia_storage_path}}" -notifier: - disable_startup_check: true -{% if var_authelia_notification_mode == "file" %} - filesystem: - filename: {{var_authelia_notification_file_path}} -{% endif %} -{% if var_authelia_notification_mode == "smtp" %} - smtp: - host: "{{var_authelia_notification_smtp_host}}" - port: {{var_authelia_notification_smtp_port}} - username: "{{var_authelia_notification_smtp_username}}" - password: "{{var_authelia_notification_smtp_password}}" - sender: "{{var_authelia_notification_smtp_sender}}" - disable_require_tls: false - disable_html_emails: false - tls: - skip_verify: false -{% endif %} -identity_providers: - oidc: - hmac_secret: "{{var_authelia_oidc_hmac_secret}}" - issuer_private_key: | -{% filter indent(width=6) %} - {{temp_tls_result.privatekey}} -{% endfilter %} - cors: - allowed_origins_from_client_redirect_uris: true - clients: - - - public: false - id: "dummy" - secret: "d1424b378e4fbbc153f330f33b74ab192525b98cc2dd58b2e8d01c2737be00c6" - redirect_uris: [] - -... diff --git a/ansible/roles/authelia/templates/systemd-unit.j2 b/ansible/roles/authelia/templates/systemd-unit.j2 deleted file mode 100644 index 48b2065..0000000 --- a/ansible/roles/authelia/templates/systemd-unit.j2 +++ /dev/null @@ -1,11 +0,0 @@ -[Unit] -Description=Authelia authentication and authorization server -After=multi-user.target - -[Service] -Environment=AUTHELIA_SERVER_DISABLE_HEALTHCHECK=true -ExecStart=/usr/bin/authelia --config /etc/authelia/configuration.yml -SyslogIdentifier=authelia - -[Install] -WantedBy=multi-user.target