diff --git a/roles/authelia-for-hedgedoc/cfg.schema.json b/roles/authelia-for-hedgedoc/cfg.schema.json index b2da9bf..c8bf2cb 100644 --- a/roles/authelia-for-hedgedoc/cfg.schema.json +++ b/roles/authelia-for-hedgedoc/cfg.schema.json @@ -19,6 +19,7 @@ "additionalProperties": false, "required": [ "hedgedoc_url_base", + "client_id", "client_secret" ] } diff --git a/roles/authelia-for-owncloud/cfg.schema.json b/roles/authelia-for-owncloud/cfg.schema.json index 8df9dca..4532214 100644 --- a/roles/authelia-for-owncloud/cfg.schema.json +++ b/roles/authelia-for-owncloud/cfg.schema.json @@ -68,12 +68,12 @@ "nullable": true, "type": "object", "properties": { - "ios_client_id": { + "client_id": { "nullable": false, "type": "string", "default": "mxd5OQDk6es5LzOzRvidJNfXLUZS2oN3oUFeXPP8LpPrhx3UroJFduGEYIBOxkY1" }, - "ios_client_secret": { + "client_secret": { "nullable": false, "type": "string", "default": "KFeFWWEZO9TkisIQzR3fo7hfiMXlOpaqP8CFuTbSHzV1TUuGECglPxpiVKJfOXIx" @@ -88,6 +88,10 @@ }, "additionalProperties": false, "required": [ - "owncloud_url_base" + "owncloud_url_base", + "web", + "desktop", + "android", + "ios" ] } diff --git a/roles/authelia-for-owncloud/templates/authelia-client-conf-android.json.j2 b/roles/authelia-for-owncloud/templates/authelia-client-conf-android.json.j2 index d21c360..7c39744 100644 --- a/roles/authelia-for-owncloud/templates/authelia-client-conf-android.json.j2 +++ b/roles/authelia-for-owncloud/templates/authelia-client-conf-android.json.j2 @@ -2,7 +2,7 @@ "client_id": "{{cfg_authelia_for_owncloud.android.client_id}}", "client_secret": "{{temp_authelia_for_owncloud_android_client_secret_hashed.stdout}}", "client_name": "ownCloud | Android Client", - + "public": false, "authorization_policy": "one_factor", "require_pkce": true, diff --git a/roles/authelia-for-owncloud/templates/authelia-client-conf-desktop.json.j2 b/roles/authelia-for-owncloud/templates/authelia-client-conf-desktop.json.j2 index e314bf2..2b33bf2 100644 --- a/roles/authelia-for-owncloud/templates/authelia-client-conf-desktop.json.j2 +++ b/roles/authelia-for-owncloud/templates/authelia-client-conf-desktop.json.j2 @@ -2,7 +2,7 @@ "client_id": "{{cfg_authelia_for_owncloud.desktop.client_id}}", "client_secret": "{{temp_authelia_for_owncloud_desktop_client_secret_hashed.stdout}}", "client_name": "ownCloud | Desktop Client", - + "public": false, "authorization_policy": "one_factor", "require_pkce": true, diff --git a/roles/authelia/cfg.schema.json b/roles/authelia/cfg.schema.json index 8efff86..30ca12f 100644 --- a/roles/authelia/cfg.schema.json +++ b/roles/authelia/cfg.schema.json @@ -7,10 +7,30 @@ "type": "string", "default": "0.0.0.0" }, + "domain": { + "nullable": false, + "type": "string" + }, + "session_domain": { + "nullable": false, + "type": "string" + }, + "redirect_url": { + "nullable": false, + "type": "string" + }, "jwt_secret": { "nullable": false, "type": "string" }, + "session_secret": { + "nullable": false, + "type": "string" + }, + "storage_encryption_key": { + "nullable": false, + "type": "string" + }, "users_file_path": { "nullable": false, "type": "string", @@ -21,29 +41,6 @@ "type": "string", "default": "/var/authelia/log.jsonl" }, - "domain": { - "nullable": false, - "type": "string", - "default": "authelia.example.org" - }, - "redirect_url": { - "nullable": false, - "type": "string", - "default": "https://example.org" - }, - "session_domain": { - "nullable": false, - "type": "string", - "default": "example.org" - }, - "session_secret": { - "nullable": false, - "type": "string" - }, - "storage_encryption_key": { - "nullable": false, - "type": "string" - }, "storage": { "anyOf": [ { @@ -53,7 +50,8 @@ "kind": { "nullable": false, "type": "string", - "enum": ["sqlite"] + "enum": ["sqlite"], + "default": "sqlite" }, "data": { "nullable": false, @@ -67,6 +65,7 @@ }, "additionalProperties": false, "required": [ + "path" ], "default": { } @@ -74,8 +73,11 @@ }, "additionalProperties": false, "required": [ - "kind" - ] + "kind", + "data" + ], + "default": { + } }, { "nullable": false, @@ -117,15 +119,23 @@ }, "additionalProperties": false, "required": [ - "password" - ] + "host", + "port", + "username", + "password", + "schema" + ], + "default": { + } } }, "additionalProperties": false, "required": [ "kind", "data" - ] + ], + "default": { + } }, { "nullable": false, @@ -167,22 +177,30 @@ }, "additionalProperties": false, "required": [ - "password" - ] + "host", + "port", + "username", + "password", + "schema" + ], + "default": { + } } }, "additionalProperties": false, "required": [ "kind", "data" - ] + ], + "default": { + } } ] }, "ntp_server": { "nullable": false, "type": "string", - "mandatory": false + "default": "time.cloudflare.com:123" }, "password_reset": { "nullable": false, @@ -201,6 +219,8 @@ }, "additionalProperties": false, "required": [ + "enabled", + "custom_url" ], "default": { } @@ -214,15 +234,22 @@ "kind": { "nullable": false, "type": "string", - "enum": ["file"] + "enum": ["file"], + "default": "file" }, "data": { "nullable": false, "type": "object", "properties": { + "path": { + "nullable": false, + "type": "string", + "default": "/var/authelia/notifications" + } }, "additionalProperties": false, "required": [ + "path" ], "default": { } @@ -230,8 +257,11 @@ }, "additionalProperties": false, "required": [ - "kind" - ] + "kind", + "data" + ], + "default": { + } }, { "nullable": false, @@ -240,7 +270,8 @@ "kind": { "nullable": false, "type": "string", - "enum": ["smtp"] + "enum": ["smtp"], + "default": "smtp" }, "data": { "nullable": false, @@ -248,8 +279,7 @@ "properties": { "host": { "nullable": false, - "type": "string", - "default": "smtp.example.org" + "type": "string" }, "port": { "nullable": false, @@ -273,7 +303,11 @@ }, "additionalProperties": false, "required": [ - "password" + "host", + "port", + "username", + "password", + "sender" ] } }, @@ -281,7 +315,9 @@ "required": [ "kind", "data" - ] + ], + "default": { + } } ] }, @@ -338,7 +374,7 @@ }, "additionalProperties": false, "required": [ - "acces_token", + "access_token", "refresh_token" ] }, @@ -384,15 +420,30 @@ }, "additionalProperties": false, "required": [ - "hmac_secret" - ] + "hmac_secret", + "lifespan", + "cors_endpoints" + ], + "default": { + } } }, "additionalProperties": false, "required": [ + "listen_address", + "domain", + "session_domain", + "redirect_url", "jwt_secret", "session_secret", "storage_encryption_key", + "users_file_path", + "log_file_path", + "storage", + "ntp_server", + "notification", "oidc" - ] + ], + "default": { + } } diff --git a/roles/authelia/defaults/main.json b/roles/authelia/defaults/main.json index cf65251..6b9e1f9 100644 --- a/roles/authelia/defaults/main.json +++ b/roles/authelia/defaults/main.json @@ -3,9 +3,6 @@ "listen_address": "0.0.0.0", "users_file_path": "/var/authelia/users.yml", "log_file_path": "/var/authelia/log.jsonl", - "domain": "authelia.example.org", - "redirect_url": "https://example.org", - "session_domain": "example.org", "storage": { "kind": "sqlite", "data": { diff --git a/roles/dokuwiki/tasks/main.json b/roles/dokuwiki/tasks/main.json index 6baa11e..f404c5b 100644 --- a/roles/dokuwiki/tasks/main.json +++ b/roles/dokuwiki/tasks/main.json @@ -5,8 +5,8 @@ "ansible.builtin.apt": { "pkg": [ "unzip", - "php-fpm", - "php-xml" + "php8.2-fpm", + "php8.2-xml" ] } }, diff --git a/roles/hedgedoc-and-nginx/vardef.json b/roles/hedgedoc-and-nginx/vardef.json new file mode 100644 index 0000000..b78ac7a --- /dev/null +++ b/roles/hedgedoc-and-nginx/vardef.json @@ -0,0 +1,15 @@ +{ + "domain": { + "type": "string", + "mandatory": false + }, + "tls_mode": { + "type": "string", + "options": [ + "disable", + "enable", + "force" + ], + "mandatory": false + } +} diff --git a/roles/hedgedoc/cfg.schema.json b/roles/hedgedoc/cfg.schema.json index b6cc54b..d2dc549 100644 --- a/roles/hedgedoc/cfg.schema.json +++ b/roles/hedgedoc/cfg.schema.json @@ -15,207 +15,189 @@ "version": { "nullable": false, "type": "string", - "version": "1.10.3" + "default": "1.10.3" + }, + "domain": { + "nullable": false, + "type": "string" }, "session_secret": { "nullable": false, "type": "string" }, - "domain": { - "nullable": false, - "type": "string", - "default": "hedgedoc.example.org" - }, "database": { - "nullable": false, - "type": "object", - "properties": { - "kind": { + "anyOf": [ + { "nullable": false, - "type": "string", - "enum": [ - "sqlite", - "postgresql" - ], - "default": "sqlite" - }, - "data": { - "anyOf": [ - { + "type": "object", + "properties": { + "kind": { "nullable": false, - "type": "object", - "properties": { - "sqlite": { - "nullable": false, - "type": "object", - "properties": { - "path": { - "nullable": false, - "type": "string", - "default": "/var/hedgedoc/data.sqlite" - } - }, - "additionalProperties": false, - "required": [ - ], - "default": { - } - } - }, - "additionalProperties": false, - "required": [ - "sqlite" - ] + "type": "string", + "enum": ["sqlite"], + "default": "sqlite" }, - { + "data": { "nullable": false, "type": "object", "properties": { - "postgresql": { + "path": { "nullable": false, - "type": "object", - "properties": { - "host": { - "nullable": false, - "type": "string", - "default": "localhost" - }, - "port": { - "nullable": false, - "type": "integer", - "default": 5432 - }, - "username": { - "nullable": false, - "type": "string", - "default": "hedgedoc_user" - }, - "password": { - "nullable": false, - "type": "string" - }, - "schema": { - "nullable": false, - "type": "string", - "default": "hedgedoc" - } - }, - "additionalProperties": false, - "required": [ - "password" - ] + "type": "string", + "default": "/var/hedgedoc/data.sqlite" } }, "additionalProperties": false, "required": [ - "postgresql" + "path" + ], + "default": { + } + } + }, + "additionalProperties": false, + "required": [ + "kind", + "data" + ] + }, + { + "nullable": false, + "type": "object", + "properties": { + "kind": { + "nullable": false, + "type": "string", + "enum": ["postgresql"], + "default": "postgresql" + }, + "data": { + "nullable": false, + "type": "object", + "properties": { + "host": { + "nullable": false, + "type": "string", + "default": "localhost" + }, + "port": { + "nullable": false, + "type": "integer", + "default": 5432 + }, + "username": { + "nullable": false, + "type": "string", + "default": "hedgedoc_user" + }, + "password": { + "nullable": false, + "type": "string" + }, + "schema": { + "nullable": false, + "type": "string", + "default": "hedgedoc" + } + }, + "additionalProperties": false, + "required": [ + "host", + "port", + "username", + "password", + "schema" ] } + }, + "additionalProperties": false, + "required": [ + "kind", + "data" ] } - }, - "additionalProperties": false, - "required": [ - "kind", - "data" ] }, "authentication": { - "nullable": false, - "type": "object", - "properties": { - "kind": { + "anyOf": [ + { "nullable": false, - "type": "string", - "enum": [ - "internal", - "authelia" - ], - "default": "internal" - }, - "data": { - "anyOf": [ - { + "type": "object", + "properties": { + "kind": { "nullable": false, - "type": "object", - "properties": { - "internal": { - "nullable": false, - "type": "object", - "properties": { - }, - "additionalProperties": false, - "required": [ - ], - "default": { - } - } - }, - "additionalProperties": false, - "required": [ - "internal" - ] + "type": "string", + "enum": ["internal"], + "default": "internal" }, - { + "data": { "nullable": false, "type": "object", "properties": { - "authelia": { + }, + "additionalProperties": false, + "required": [ + ], + "default": { + } + } + }, + "additionalProperties": false, + "required": [ + "kind", + "data" + ] + }, + { + "nullable": false, + "type": "object", + "properties": { + "kind": { + "nullable": false, + "type": "string", + "enum": ["authelia"], + "default": "authelia" + }, + "data": { + "nullable": false, + "type": "object", + "properties": { + "url_base": { "nullable": false, - "type": "object", - "properties": { - "url_base": { - "nullable": false, - "type": "string" - }, - "client_id": { - "nullable": false, - "type": "string", - "default": "hedgedoc" - }, - "client_secret": { - "nullable": false, - "type": "string" - }, - "provider_name": { - "nullable": false, - "type": "string", - "default": "Authelia" - } - }, - "additionalProperties": false, - "required": [ - "url_base", - "client_secret" - ] + "type": "string" + }, + "client_id": { + "nullable": false, + "type": "string", + "default": "hedgedoc" + }, + "client_secret": { + "nullable": false, + "type": "string" + }, + "provider_name": { + "nullable": false, + "type": "string", + "default": "Authelia" } }, "additionalProperties": false, "required": [ - "authelia" - ] + "url_base", + "client_id", + "client_secret", + "provider_name" + ] } + }, + "additionalProperties": false, + "required": [ + "kind", + "data" ] } - }, - "additionalProperties": false, - "required": [ - "kind", - "data" ] }, - "log_level": { - "nullable": false, - "type": "string", - "enum": [ - "debug", - "verbose", - "info", - "warn", - "error" - ], - "default": "error" - }, "guest_allow_create": { "nullable": false, "type": "boolean", @@ -229,12 +211,38 @@ "free_names_mode": { "nullable": false, "type": "string", + "enum": [ + "never", + "authed", + "always" + ], "default": "authed" + }, + "log_level": { + "nullable": false, + "type": "string", + "enum": [ + "debug", + "verbose", + "info", + "warn", + "error" + ], + "default": "error" } }, "additionalProperties": false, "required": [ + "user_name", + "directory", + "version", "domain", - "session_secret" + "session_secret", + "database", + "authentication", + "guest_allow_create", + "guest_allow_change", + "free_names_mode", + "log_level" ] } diff --git a/roles/hedgedoc/defaults/main.json b/roles/hedgedoc/defaults/main.json index 8f0fd47..9f2da1f 100644 --- a/roles/hedgedoc/defaults/main.json +++ b/roles/hedgedoc/defaults/main.json @@ -6,33 +6,17 @@ "database": { "kind": "sqlite", "data": { - "sqlite": { - "path": "/var/hedgedoc/data.sqlite" - }, - "postgresql": { - "host": "localhost", - "port": 5432, - "username": "hedgedoc_user", - "password": "hedgedoc", - "schema": "hedgedoc" - } + "path": "/var/hedgedoc/data.sqlite" } }, "authentication": { "kind": "internal", "data": { - "internal": { - }, - "authelia": { - "client_id": "hedgedoc", - "client_secret": "hedgedoc", - "provider_name": "Authelia" - } } }, - "log_level": "error", "guest_allow_create": false, "guest_allow_change": false, - "free_names_mode": "authed" + "free_names_mode": "authed", + "log_level": "error" } } diff --git a/roles/nginx/cfg.schema.json b/roles/nginx/cfg.schema.json index b04f70f..13a8fcb 100644 --- a/roles/nginx/cfg.schema.json +++ b/roles/nginx/cfg.schema.json @@ -9,7 +9,7 @@ "default": null }, "dhparam_size": { - "nullable": false, + "nullable": true, "type": "integer", "default": null }, @@ -21,5 +21,8 @@ }, "additionalProperties": false, "required": [ + "auto_reload_interval", + "dhparam_size", + "improved_security" ] } diff --git a/roles/nginx/defaults/main.json b/roles/nginx/defaults/main.json index 21dfe39..e59898d 100644 --- a/roles/nginx/defaults/main.json +++ b/roles/nginx/defaults/main.json @@ -1,6 +1,7 @@ { "cfg_nginx_defaults": { "auto_reload_interval": null, - "dhparam_size": 2048 + "dhparam_size": null, + "improved_security": false } } diff --git a/roles/owncloud-and-nginx/cfg.schema.json b/roles/owncloud-and-nginx/cfg.schema.json index 974342b..070ca31 100644 --- a/roles/owncloud-and-nginx/cfg.schema.json +++ b/roles/owncloud-and-nginx/cfg.schema.json @@ -17,12 +17,15 @@ "default": "force" }, "maximum_upload_size": { + "nullable": false, "type": "string", "default": "1G" } }, "additionalProperties": false, "required": [ - "domain" + "domain", + "tls_mode", + "maximum_upload_size" ] } diff --git a/roles/owncloud/cfg.schema.json b/roles/owncloud/cfg.schema.json index 1dde09d..6c3c59d 100644 --- a/roles/owncloud/cfg.schema.json +++ b/roles/owncloud/cfg.schema.json @@ -24,8 +24,7 @@ }, "domain": { "nullable": false, - "type": "string", - "default": "owncloud.example.org" + "type": "string" }, "admin_password": { "nullable": false, @@ -39,7 +38,8 @@ "properties": { "kind": { "type": "string", - "enum": ["internal"] + "enum": ["internal"], + "default": "internal" }, "data": { "nullable": false, @@ -55,7 +55,8 @@ }, "additionalProperties": false, "required": [ - "kind" + "kind", + "data" ] }, { @@ -64,7 +65,8 @@ "properties": { "kind": { "type": "string", - "enum": ["authelia"] + "enum": ["authelia"], + "default": "authelia" }, "data": { "nullable": false, @@ -86,6 +88,7 @@ }, "additionalProperties": false, "required": [ + "client_id" ], "default": { } @@ -93,7 +96,8 @@ }, "additionalProperties": false, "required": [ - "url_base" + "url_base", + "web" ] } }, @@ -127,6 +131,8 @@ }, "additionalProperties": false, "required": [ + "password_necessity", + "password_policy_active" ], "default": { } @@ -134,6 +140,13 @@ }, "additionalProperties": false, "required": [ - "admin_password" + "user", + "directory", + "version", + "platform", + "domain", + "admin_password", + "authentication", + "public_share" ] } diff --git a/tools/cfg-man b/tools/cfg-man new file mode 100755 index 0000000..6aa543b --- /dev/null +++ b/tools/cfg-man @@ -0,0 +1,179 @@ +#!/usr/bin/env python3 + +import os as _os +import sys as _sys +import json as _json +import argparse as _argparse + + +def convey( + x, + fs +): + y = x + for f in fs: + y = f(y) + return y + + +def file_read( + path +): + handle = open(path, "r") + content = handle.read() + handle.close() + return content + + +class interface_option(object): + def is_filled(self): + raise NotImplementedError() + def cull(self): + raise NotImplementedError() + def propagate(self, function): + raise NotImplementedError() + + +class class_option_empty(interface_option): + def __init__(self): + pass + def is_filled(self): + return False + def cull(self): + raise ValueError("cull from empty") + def propagate(self, function): + return class_option_empty() + + +class class_option_filled(interface_option): + def __init__(self, value): + self.value = value + def is_filled(self): + return True + def cull(self): + return self.value + def propagate(self, function): + return function(self.value) + + +def generate_defaults( + schema_node +): + if ("anyOf" in schema_node): + ## todo: o'rly? + return generate_defaults(schema_node["anyOf"][0]) + else: + if (not ("type" in schema_node)): + raise ValueError(":?") + else: + if (not (schema_node["type"] == "object")): + if (not ("default" in schema_node)): + return class_option_empty() + else: + return class_option_filled(schema_node["default"]) + else: + result = {} + for (key, value, ) in schema_node["properties"].items(): + sub_result = generate_defaults(value) + if (not sub_result.is_filled()): + pass + else: + result[key] = sub_result.cull() + return class_option_filled(result) + + +def generate_overrides( + schema_node +): + if ("anyOf" in schema_node): + ## todo: o'rly? + return generate_overrides(schema_node["anyOf"][0]) + else: + if (not ("type" in schema_node)): + raise ValueError(":?") + else: + if (not (schema_node["type"] == "object")): + if ("default" in schema_node): + return class_option_empty() + else: + if ("enum" in schema_node): + return class_option_filled(schema_node["enum"][0]) + else: + if (schema_node.get("nullable", False)): + return class_option_filled(None) + else: + if (schema_node["type"] == "boolean"): + return class_option_filled(False) + elif (schema_node["type"] == "integer"): + return class_option_filled(0) + elif (schema_node["type"] == "number"): + return class_option_filled(0) + elif (schema_node["type"] == "string"): + return class_option_filled("") + else: + raise ValueError("unhandled type: %s" % schema_node["type"]) + else: + result = {} + for (key, value, ) in schema_node["properties"].items(): + sub_result = generate_overrides(value) + if (not sub_result.is_filled()): + pass + else: + result[key] = sub_result.cull() + return ( + class_option_empty() + if (len(result) <= 0) else + class_option_filled(result) + ) + + +def role_name_derive( + role_name +): + return role_name.replace("-", "_") + + +def main( +): + ## args + argument_parser = _argparse.ArgumentParser() + argument_parser.add_argument( + "action", + type = str, + choices = [ + "defaults", + "overrides", + ], + metavar = "", + ) + argument_parser.add_argument( + "role", + type = str, + metavar = "", + ) + args = argument_parser.parse_args() + + ## exec + cfg_schema = convey( + args.role, + [ + lambda x: _os.path.join("roles", x, "cfg.schema.json"), + file_read, + _json.loads, + ] + ) + if args.action == "defaults": + raw = generate_defaults(cfg_schema) + key = ("cfg_%s_defaults" % (role_name_derive(args.role))) + result = {key: (raw.cull() if raw.is_filled() else {})} + _sys.stdout.write(_json.dumps(result, indent = "\t") + "\n") + elif args.action == "overrides": + raw = generate_overrides(cfg_schema) + key = ("cfg_%s_overrides" % (role_name_derive(args.role))) + result = {key: (raw.cull() if raw.is_filled() else {})} + _sys.stdout.write(_json.dumps(result, indent = "\t") + "\n") + else: + raise ValueError("invalid action: %s" % args.action) + + +main()