From 463112de12485be123dc1716a066085e5606266b Mon Sep 17 00:00:00 2001 From: Kay0u Date: Fri, 8 Nov 2019 21:22:28 +0900 Subject: [PATCH 01/29] add subcategories --- data/actionsmap/yunohost_completion.py | 83 +++++++++++++++++++------- 1 file changed, 61 insertions(+), 22 deletions(-) diff --git a/data/actionsmap/yunohost_completion.py b/data/actionsmap/yunohost_completion.py index a4c17c4d6..45d15f16c 100644 --- a/data/actionsmap/yunohost_completion.py +++ b/data/actionsmap/yunohost_completion.py @@ -3,7 +3,7 @@ Simple automated generation of a bash_completion file for yunohost command from the actionsmap. Generates a bash completion file assuming the structure -`yunohost domain action` +`yunohost category action` adds `--help` at the end if one presses [tab] again. author: Christophe Vuillot @@ -15,18 +15,39 @@ THIS_SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) ACTIONSMAP_FILE = THIS_SCRIPT_DIR + '/yunohost.yml' BASH_COMPLETION_FILE = THIS_SCRIPT_DIR + '/../bash-completion.d/yunohost' +def get_dict_actions(OPTION_SUBTREE, category): + ACTIONS = [action for action in OPTION_SUBTREE[category]["actions"].keys() + if not action.startswith('_')] + ACTIONS_STR = '{}'.format(' '.join(ACTIONS)) + + DICT = { "actions_str": ACTIONS_STR } + + return DICT + with open(ACTIONSMAP_FILE, 'r') as stream: - # Getting the dictionary containning what actions are possible per domain + # Getting the dictionary containning what actions are possible per category OPTION_TREE = yaml.load(stream) - DOMAINS = [str for str in OPTION_TREE.keys() if not str.startswith('_')] - DOMAINS_STR = '"{}"'.format(' '.join(DOMAINS)) + + CATEGORY = [category for category in OPTION_TREE.keys() if not category.startswith('_')] + + CATEGORY_STR = '{}'.format(' '.join(CATEGORY)) ACTIONS_DICT = {} - for domain in DOMAINS: - ACTIONS = [str for str in OPTION_TREE[domain]['actions'].keys() - if not str.startswith('_')] - ACTIONS_STR = '"{}"'.format(' '.join(ACTIONS)) - ACTIONS_DICT[domain] = ACTIONS_STR + for category in CATEGORY: + ACTIONS_DICT[category] = get_dict_actions(OPTION_TREE, category) + + ACTIONS_DICT[category]["subcategories"] = {} + ACTIONS_DICT[category]["subcategories_str"] = "" + + if "subcategories" in OPTION_TREE[category].keys(): + SUBCATEGORIES = [ subcategory for subcategory in OPTION_TREE[category]["subcategories"].keys() ] + + SUBCATEGORIES_STR = '{}'.format(' '.join(SUBCATEGORIES)) + + ACTIONS_DICT[category]["subcategories_str"] = SUBCATEGORIES_STR + + for subcategory in SUBCATEGORIES: + ACTIONS_DICT[category]["subcategories"][subcategory] = get_dict_actions(OPTION_TREE[category]["subcategories"], subcategory) with open(BASH_COMPLETION_FILE, 'w') as generated_file: @@ -47,31 +68,49 @@ with open(ACTIONSMAP_FILE, 'r') as stream: generated_file.write('\tnarg=${#COMP_WORDS[@]}\n\n') generated_file.write('\t# the current word being typed\n') generated_file.write('\tcur="${COMP_WORDS[COMP_CWORD]}"\n\n') - generated_file.write('\t# the last typed word\n') - generated_file.write('\tprev="${COMP_WORDS[COMP_CWORD-1]}"\n\n') - # If one is currently typing a domain then match with the domain list - generated_file.write('\t# If one is currently typing a domain,\n') - generated_file.write('\t# match with domains\n') + # If one is currently typing a category then match with the category list + generated_file.write('\t# If one is currently typing a category,\n') + generated_file.write('\t# match with categorys\n') generated_file.write('\tif [[ $narg == 2 ]]; then\n') - generated_file.write('\t\topts={}\n'.format(DOMAINS_STR)) + generated_file.write('\t\topts="{}"\n'.format(CATEGORY_STR)) generated_file.write('\tfi\n\n') # If one is currently typing an action then match with the action list - # of the previously typed domain - generated_file.write('\t# If one already typed a domain,\n') - generated_file.write('\t# match the actions of that domain\n') + # of the previously typed category + generated_file.write('\t# If one already typed a category,\n') + generated_file.write('\t# match the actions or the subcategories of that category\n') generated_file.write('\tif [[ $narg == 3 ]]; then\n') - for domain in DOMAINS: - generated_file.write('\t\tif [[ $prev == "{}" ]]; then\n'.format(domain)) - generated_file.write('\t\t\topts={}\n'.format(ACTIONS_DICT[domain])) + generated_file.write('\t\t# the category typed\n') + generated_file.write('\t\tcategory="${COMP_WORDS[1]}"\n\n') + for category in CATEGORY: + generated_file.write('\t\tif [[ $category == "{}" ]]; then\n'.format(category)) + generated_file.write('\t\t\topts="{} {}"\n'.format(ACTIONS_DICT[category]["actions_str"], ACTIONS_DICT[category]["subcategories_str"])) generated_file.write('\t\tfi\n') generated_file.write('\tfi\n\n') - # If both domain and action have been typed or the domain + generated_file.write('\t# If one already typed an action or a subcategory,\n') + generated_file.write('\t# match the actions of that subcategory\n') + generated_file.write('\tif [[ $narg == 4 ]]; then\n') + generated_file.write('\t\t# the category typed\n') + generated_file.write('\t\tcategory="${COMP_WORDS[1]}"\n\n') + generated_file.write('\t\t# the action or the subcategory typed\n') + generated_file.write('\t\taction_or_subcategory="${COMP_WORDS[2]}"\n\n') + for category in CATEGORY: + if len(ACTIONS_DICT[category]["subcategories"]): + generated_file.write('\t\tif [[ $category == "{}" ]]; then\n'.format(category)) + for subcategory in ACTIONS_DICT[category]["subcategories"]: + generated_file.write('\t\t\tif [[ $action_or_subcategory == "{}" ]]; then\n'.format(subcategory)) + generated_file.write('\t\t\t\topts="{}"\n'.format(ACTIONS_DICT[category]["subcategories"][subcategory]["actions_str"])) + generated_file.write('\t\t\tfi\n') + generated_file.write('\t\tfi\n') + generated_file.write('\tfi\n\n') + + # If both category and action have been typed or the category # was not recognized propose --help (only once) generated_file.write('\t# If no options were found propose --help\n') generated_file.write('\tif [ -z "$opts" ]; then\n') + generated_file.write('\t\tprev="${COMP_WORDS[COMP_CWORD-1]}"\n\n') generated_file.write('\t\tif [[ $prev != "--help" ]]; then\n') generated_file.write('\t\t\topts=( --help )\n') generated_file.write('\t\tfi\n') From e0fa39ad01abd0b58c6db7c43c4081dcb934c2d6 Mon Sep 17 00:00:00 2001 From: Augustin Trancart Date: Sat, 30 Nov 2019 15:52:00 +0100 Subject: [PATCH 02/29] =?UTF-8?q?[fix]=20prevent=20firefox=20to=20mix=20CA?= =?UTF-8?q?=C2=A0and=20server=20certificate?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #1479: yunohost was using the exact same Distinguished Name for the CA certificate and the main domain server certificate. When creating alternate domain name, firefox thought the CA for this second domain was the server certificate for the first domain. As the key mismatches, Firefox raised a bad key usage error, which is not bypassable. To fix this, we "simply" need to make sure the DN for the CA is distinct for any other DN. I did so by adding a Organization to it, and I decided to just remove the last part of the domain and use that as an organization name. It is certainly possible to do something else, as long as we end up having a distinct DN. So yolo.test gives a yolo organization for instance. More info here https://bugzilla.mozilla.org/show_bug.cgi?id=1590217 --- src/yunohost/tools.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/yunohost/tools.py b/src/yunohost/tools.py index c05933dc0..ce219c4bc 100644 --- a/src/yunohost/tools.py +++ b/src/yunohost/tools.py @@ -321,7 +321,7 @@ def tools_postinstall(operation_logger, domain, password, ignore_dyndns=False, 'touch %s/index.txt' % ssl_dir, 'cp %s/openssl.cnf %s/openssl.ca.cnf' % (ssl_dir, ssl_dir), 'sed -i s/yunohost.org/%s/g %s/openssl.ca.cnf ' % (domain, ssl_dir), - 'openssl req -x509 -new -config %s/openssl.ca.cnf -days 3650 -out %s/ca/cacert.pem -keyout %s/ca/cakey.pem -nodes -batch' % (ssl_dir, ssl_dir, ssl_dir), + 'openssl req -x509 -new -config %s/openssl.ca.cnf -days 3650 -out %s/ca/cacert.pem -keyout %s/ca/cakey.pem -nodes -batch -subj /CN=%s/O=%s' % (ssl_dir, ssl_dir, ssl_dir, domain, os.path.splitext(domain)[0]), 'cp %s/ca/cacert.pem /etc/ssl/certs/ca-yunohost_crt.pem' % ssl_dir, 'update-ca-certificates' ] From ff4f644cd073d63ad8bb03b3de671f98039a07e2 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Sat, 28 Mar 2020 21:17:28 +0100 Subject: [PATCH 03/29] Fix possible security issue with these cookie files --- data/helpers.d/utils | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/data/helpers.d/utils b/data/helpers.d/utils index 50671dba0..133a47247 100644 --- a/data/helpers.d/utils +++ b/data/helpers.d/utils @@ -237,9 +237,14 @@ ynh_local_curl () { # Wait untils nginx has fully reloaded (avoid curl fail with http2) sleep 2 + + local cookiefile=/tmp/ynh-$app-cookie.txt + touch $cookiefile + chown root $cookiefile + chmod 700 $cookiefile # Curl the URL - curl --silent --show-error -kL -H "Host: $domain" --resolve $domain:443:127.0.0.1 $POST_data "$full_page_url" --cookie-jar /tmp/ynh-$app-cookie.txt --cookie /tmp/ynh-$app-cookie.txt + curl --silent --show-error -kL -H "Host: $domain" --resolve $domain:443:127.0.0.1 $POST_data "$full_page_url" --cookie-jar $cookiefile --cookie $cookiefile } # Render templates with Jinja2 From 51a0502e9100b10356eb62b6d148a41c79d00f44 Mon Sep 17 00:00:00 2001 From: Kay0u Date: Mon, 30 Mar 2020 19:36:41 +0200 Subject: [PATCH 04/29] add ynh_permission_has_user --- data/actionsmap/yunohost.yml | 9 +++++++++ data/helpers.d/setting | 19 +++++++++++++++++++ src/yunohost/permission.py | 22 ++++++++++++++++++++++ src/yunohost/user.py | 6 ++++++ 4 files changed, 56 insertions(+) diff --git a/data/actionsmap/yunohost.yml b/data/actionsmap/yunohost.yml index 3a4c9db97..c0eca3d03 100644 --- a/data/actionsmap/yunohost.yml +++ b/data/actionsmap/yunohost.yml @@ -296,6 +296,15 @@ user: help: Display all info known about each permission, including the full user list of each group it is granted to. action: store_true + ### user_permission_info() + info: + action_help: Get information about a specific permission + api: GET /users/permissions/ + arguments: + permission: + help: Name of the permission to fetch info about + extra: + pattern: *pattern_username ### user_permission_update() update: diff --git a/data/helpers.d/setting b/data/helpers.d/setting index 384fdc399..1c1139442 100644 --- a/data/helpers.d/setting +++ b/data/helpers.d/setting @@ -367,3 +367,22 @@ ynh_permission_update() { yunohost user permission update "$app.$permission" ${add:-} ${remove:-} } + +# Check if a permission exists +# +# usage: ynh_permission_has_user --permission=permission --user=user +# | arg: -p, --permission - the permission to check +# | arg: -u, --user - the user seek in the permission +# +# Requires YunoHost version 3.7.1 or higher. +ynh_permission_has_user() { + declare -Ar args_array=( [p]=permission= [u]=user) + local permission + ynh_handle_getopts_args "$@" + + if ! ynh_permission_exists --permission $permission + return 1 + fi + + yunohost user permission info $permission | grep -w -q "$user" +} \ No newline at end of file diff --git a/src/yunohost/permission.py b/src/yunohost/permission.py index 2aea6f4c4..05def2101 100644 --- a/src/yunohost/permission.py +++ b/src/yunohost/permission.py @@ -196,6 +196,28 @@ def user_permission_reset(operation_logger, permission, sync_perm=True): return new_permission + +def user_permission_info(permission, sync_perm=True): + """ + Return informations about a specific permission + + Keyword argument: + permission -- Name of the permission (e.g. mail or nextcloud or wordpress.editors) + """ + + # By default, manipulate main permission + if "." not in permission: + permission = permission + ".main" + + # Fetch existing permission + + existing_permission = user_permission_list(full=True)["permissions"].get(permission, None) + if existing_permission is None: + raise YunohostError('permission_not_found', permission=permission) + + return existing_permission + + # # # The followings methods are *not* directly exposed. diff --git a/src/yunohost/user.py b/src/yunohost/user.py index 39a2d8f15..74ad9f977 100644 --- a/src/yunohost/user.py +++ b/src/yunohost/user.py @@ -780,6 +780,12 @@ def user_permission_reset(permission, sync_perm=True): sync_perm=sync_perm) +def user_permission_info(permission, sync_perm=True): + import yunohost.permission + return yunohost.permission.user_permission_info(permission, + sync_perm=sync_perm) + + # # SSH subcategory # From 288a617975cbe06321fcddb5bbf558989925cf6a Mon Sep 17 00:00:00 2001 From: Maniack Crudelis Date: Mon, 30 Mar 2020 19:58:06 +0200 Subject: [PATCH 05/29] Let's have a working helper --- data/helpers.d/setting | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/data/helpers.d/setting b/data/helpers.d/setting index 1c1139442..5e88bf259 100644 --- a/data/helpers.d/setting +++ b/data/helpers.d/setting @@ -374,15 +374,22 @@ ynh_permission_update() { # | arg: -p, --permission - the permission to check # | arg: -u, --user - the user seek in the permission # +# example: ynh_permission_has_user --permission=nextcloud.main --user=visitors +# # Requires YunoHost version 3.7.1 or higher. ynh_permission_has_user() { - declare -Ar args_array=( [p]=permission= [u]=user) + local legacy_args=pu + # Declare an array to define the options of this helper. + declare -Ar args_array=( [p]=permission= [u]=user= ) local permission + local user + # Manage arguments with getopts ynh_handle_getopts_args "$@" - if ! ynh_permission_exists --permission $permission + if ! ynh_permission_exists --permission=$permission + then return 1 fi yunohost user permission info $permission | grep -w -q "$user" -} \ No newline at end of file +} From ad22677994399065785b0ffa889a842c284b2f9f Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Mon, 30 Mar 2020 20:09:26 +0200 Subject: [PATCH 06/29] Attempt to simplify permission migration --- data/helpers.d/setting | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/helpers.d/setting b/data/helpers.d/setting index 384fdc399..557afb332 100644 --- a/data/helpers.d/setting +++ b/data/helpers.d/setting @@ -197,7 +197,7 @@ EOF if [[ "$1" == "set" ]] && [[ "${4:-}" == "/" ]] then ynh_permission_update --permission "main" --add "visitors" - elif [[ "$1" == "delete" ]] && [[ "${current_value:-}" == "/" ]] + elif [[ "$1" == "delete" ]] && [[ "${current_value:-}" == "/" ]] && [[ -n "$(ynh_app_setting_get --app=$2 --key='is_public' )" ]] then ynh_permission_update --permission "main" --remove "visitors" fi From 90459e7ae6a4af5d7a6c532e8d53ccef3a6e8c50 Mon Sep 17 00:00:00 2001 From: Kay0u Date: Mon, 30 Mar 2020 21:32:29 +0200 Subject: [PATCH 07/29] Add legacy_args, fix the helper --- data/actionsmap/yunohost.yml | 2 -- data/helpers.d/setting | 18 ++++++++++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/data/actionsmap/yunohost.yml b/data/actionsmap/yunohost.yml index c0eca3d03..b0bb7f9dc 100644 --- a/data/actionsmap/yunohost.yml +++ b/data/actionsmap/yunohost.yml @@ -303,8 +303,6 @@ user: arguments: permission: help: Name of the permission to fetch info about - extra: - pattern: *pattern_username ### user_permission_update() update: diff --git a/data/helpers.d/setting b/data/helpers.d/setting index 1c1139442..4782afd84 100644 --- a/data/helpers.d/setting +++ b/data/helpers.d/setting @@ -270,6 +270,8 @@ ynh_webpath_register () { # # Requires YunoHost version 3.7.0 or higher. ynh_permission_create() { + # Declare an array to define the options of this helper. + local legacy_args=pua declare -Ar args_array=( [p]=permission= [u]=url= [a]=allowed= ) local permission local url @@ -298,6 +300,8 @@ ynh_permission_create() { # # Requires YunoHost version 3.7.0 or higher. ynh_permission_delete() { + # Declare an array to define the options of this helper. + local legacy_args=p declare -Ar args_array=( [p]=permission= ) local permission ynh_handle_getopts_args "$@" @@ -312,6 +316,8 @@ ynh_permission_delete() { # # Requires YunoHost version 3.7.0 or higher. ynh_permission_exists() { + # Declare an array to define the options of this helper. + local legacy_args=p declare -Ar args_array=( [p]=permission= ) local permission ynh_handle_getopts_args "$@" @@ -327,6 +333,8 @@ ynh_permission_exists() { # # Requires YunoHost version 3.7.0 or higher. ynh_permission_url() { + # Declare an array to define the options of this helper. + local legacy_args=pu declare -Ar args_array=([p]=permission= [u]=url=) local permission local url @@ -352,6 +360,8 @@ ynh_permission_url() { # example: ynh_permission_update --permission admin --add samdoe --remove all_users # Requires YunoHost version 3.7.0 or higher. ynh_permission_update() { + # Declare an array to define the options of this helper. + local legacy_args=par declare -Ar args_array=( [p]=permission= [a]=add= [r]=remove= ) local permission local add @@ -376,13 +386,17 @@ ynh_permission_update() { # # Requires YunoHost version 3.7.1 or higher. ynh_permission_has_user() { + # Declare an array to define the options of this helper. + local legacy_args=pu declare -Ar args_array=( [p]=permission= [u]=user) local permission + local user ynh_handle_getopts_args "$@" - if ! ynh_permission_exists --permission $permission + if ! ynh_permission_exists --permission "$permission" + then return 1 fi - yunohost user permission info $permission | grep -w -q "$user" + yunohost user permission info "$app.$permission" | grep -w -q "$user" } \ No newline at end of file From 9dd6d799f4e241bf70a9efb737788795297d6068 Mon Sep 17 00:00:00 2001 From: Kay0u Date: Mon, 30 Mar 2020 21:37:25 +0200 Subject: [PATCH 08/29] fix example --- data/helpers.d/setting | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/helpers.d/setting b/data/helpers.d/setting index ec9404d5f..9466c5631 100644 --- a/data/helpers.d/setting +++ b/data/helpers.d/setting @@ -384,7 +384,7 @@ ynh_permission_update() { # | arg: -p, --permission - the permission to check # | arg: -u, --user - the user seek in the permission # -# example: ynh_permission_has_user --permission=nextcloud.main --user=visitors +# example: ynh_permission_has_user --permission=main --user=visitors # # Requires YunoHost version 3.7.1 or higher. ynh_permission_has_user() { From ec13f77852360b3f62656ee3ffd5ca7ebe99a6a0 Mon Sep 17 00:00:00 2001 From: romain raynaud Date: Mon, 30 Mar 2020 18:55:48 +0000 Subject: [PATCH 09/29] Translated using Weblate (Spanish) Currently translated at 94.6% (581 of 614 strings) Translation: YunoHost/core Translate-URL: https://translate.yunohost.org/projects/yunohost/core/es/ --- locales/es.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/locales/es.json b/locales/es.json index 51daddf32..865254cf4 100644 --- a/locales/es.json +++ b/locales/es.json @@ -174,7 +174,7 @@ "restore_complete": "Restaurada", "restore_confirm_yunohost_installed": "¿Realmente desea restaurar un sistema ya instalado? [{answers:s}]", "restore_failed": "No se pudo restaurar el sistema", - "restore_hook_unavailable": "El guión de restauración para «{part:s}» no está disponible en su sistema y tampoco en el archivo", + "restore_hook_unavailable": "El script de restauración para «{part:s}» no está disponible en su sistema y tampoco en el archivo", "restore_nothings_done": "No se ha restaurado nada", "restore_running_app_script": "Restaurando la aplicación «{app:s}»…", "restore_running_hooks": "Ejecutando los ganchos de restauración…", @@ -377,13 +377,13 @@ "restore_removing_tmp_dir_failed": "No se pudo eliminar un directorio temporal antiguo", "restore_not_enough_disk_space": "Espacio insuficiente (espacio: {free_space:d} B, espacio necesario: {needed_space:d} B, margen de seguridad: {margin:d} B)", "restore_mounting_archive": "Montando archivo en «{path:s}»", - "restore_may_be_not_enough_disk_space": "Parece que su sistema no tiene suficiente espacio (libre: {free_space:d} B, espacio necesario: {needed_space:d} B, margen de seguridad: {margin:d} B)", + "restore_may_be_not_enough_disk_space": "Parece que su sistema no tiene suficiente espacio libre (libre: {free_space:d} B, espacio necesario: {needed_space:d} B, margen de seguridad: {margin:d} B)", "restore_extracting": "Extrayendo los archivos necesarios para el archivo…", "regenconf_pending_applying": "Aplicando la configuración pendiente para la categoría «{category}»…", "regenconf_failed": "No se pudo regenerar la configuración para la(s) categoría(s): {categories}", "regenconf_dry_pending_applying": "Comprobando la configuración pendiente que habría sido aplicada para la categoría «{category}»…", "regenconf_would_be_updated": "La configuración habría sido actualizada para la categoría «{category}»", - "regenconf_updated": "Actualizada la configuración para la categoría «{category}»", + "regenconf_updated": "Actualizada la configuración para la categoría '{category}'", "regenconf_up_to_date": "Ya está actualizada la configuración para la categoría «{category}»", "regenconf_now_managed_by_yunohost": "El archivo de configuración «{conf}» está gestionado ahora por YunoHost (categoría {category}).", "regenconf_file_updated": "Actualizado el archivo de configuración «{conf}»", @@ -400,7 +400,7 @@ "permission_update_nothing_to_do": "No hay permisos para actualizar", "permission_updated": "Actualizado el permiso «{permission:s}»", "permission_generated": "Actualizada la base de datos de permisos", - "permission_update_failed": "No se pudo actualizar el permiso «{permission}» : {error}", + "permission_update_failed": "No se pudo actualizar el permiso '{permission}': {error}", "permission_name_not_valid": "Elija un nombre de permiso permitido para «{permission:s}", "permission_not_found": "No se encontró el permiso «{permission:s}»", "permission_deletion_failed": "No se pudo eliminar el permiso «{permission}»: {error}", @@ -441,7 +441,7 @@ "migration_0011_can_not_backup_before_migration": "El respaldo del sistema no se pudo completar antes de que la migración fallase. Error: {error:s}", "migration_0011_backup_before_migration": "Creando un respaldo de la base de datos de LDAP y de la configuración de las aplicaciones antes de la migración real.", "migration_0009_not_needed": "La migración ya ocurrió de algún modo… (?) Omitiendo.", - "migration_0008_no_warning": "Ignorar su configuración SSH debería ser seguro ¡aunque esto no se puede prometer! Ejecute la migración para ignorarla. Por otra parte puede omitir la migración, aunque no se recomienda.", + "migration_0008_no_warning": "Sobre escribir su configuración SSH debería ser seguro ¡aunque esto no se puede prometer! Ejecute la migración para ignorarla. Por otra parte puede omitir la migración, aunque no se recomienda.", "migration_0008_warning": "Si entiende esos avisos y quiere que YunoHost ignore su configuración actual, ejecute la migración. Por otra parte puede omitir la migración, aunque no se recomienda.", "migration_0008_dsa": "• Se desactivará la clave DSA. Así que podría tener que anular un aviso espeluznante de su cliente SSH y volver a comprobar la huella de su servidor;", "migration_0008_root": "• No podrá conectarse como «root» a través de SSH. En su lugar debe usar el usuario «admin»;", @@ -451,7 +451,7 @@ "migration_0007_cancelled": "No se pudo mejorar el modo en el que se gestiona su configuración de SSH.", "migration_0006_disclaimer": "YunoHost espera ahora que las contraseñas de «admin» y «root» estén sincronizadas. Esta migración reemplaza su contraseña de «root» por la contraseña de «admin».", "migration_0005_not_enough_space": "Tenga suficiente espacio libre disponible en {path} para ejecutar la migración.", - "migration_0005_postgresql_96_not_installed": "⸘PostgreSQL 9.4 está instalado pero no PostgreSQL 9.6‽ Algo raro podría haber ocurrido en su sistema:(…", + "migration_0005_postgresql_96_not_installed": "PostgreSQL 9.4 está instalado pero no PostgreSQL 9.6. Algo raro podría haber ocurrido en su sistema:(…", "migration_0005_postgresql_94_not_installed": "PostgreSQL no estaba instalado en su sistema. Nada que hacer.", "migration_0003_modified_files": "Tenga en cuenta que se encontró que los siguientes archivos fueron modificados manualmente y podrían ser sobrescritos después de la actualización: {manually_modified_files}", "migration_0003_problematic_apps_warning": "Tenga en cuenta que las aplicaciones listadas mas abajo fueron detectadas como 'posiblemente problemáticas'. Parece que no fueron instaladas desde una lista de aplicaciones o no estaban etiquetadas como 'funcional'. Así que no hay garantía de que aún funcionen después de la actualización: {problematic_apps}", From 97e83337d4eec37c178a4254bcd02ca106c4f92f Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Tue, 31 Mar 2020 03:10:30 +0200 Subject: [PATCH 10/29] Update network --- data/helpers.d/network | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/helpers.d/network b/data/helpers.d/network index 5d20b22ac..2dff82108 100644 --- a/data/helpers.d/network +++ b/data/helpers.d/network @@ -17,7 +17,7 @@ ynh_find_port () { ynh_handle_getopts_args "$@" test -n "$port" || ynh_die --message="The argument of ynh_find_port must be a valid port." - while ss -nltu | grep -q -w :$port # Check if the port is free + while ss -nltu | grep -q -w "*:$port" # Check if the port is free do port=$((port+1)) # Else, pass to next port done From be303f3e443d3352118f1e221fb65ce9efc2d062 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Wed, 1 Apr 2020 02:20:02 +0200 Subject: [PATCH 11/29] Fix ynh_find_port grep Co-Authored-By: Kayou --- data/helpers.d/network | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/helpers.d/network b/data/helpers.d/network index 2dff82108..330aa5383 100644 --- a/data/helpers.d/network +++ b/data/helpers.d/network @@ -17,7 +17,7 @@ ynh_find_port () { ynh_handle_getopts_args "$@" test -n "$port" || ynh_die --message="The argument of ynh_find_port must be a valid port." - while ss -nltu | grep -q -w "*:$port" # Check if the port is free + while ss -nltu | awk '{print$5}' | grep -q -E ":$port$" # Check if the port is free do port=$((port+1)) # Else, pass to next port done From eaaa6be6e80d4aa00b29d0d218b3530fa816babc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A9lanie=20Chauvel?= Date: Mon, 30 Mar 2020 23:40:56 +0000 Subject: [PATCH 12/29] Translated using Weblate (French) Currently translated at 100.0% (614 of 614 strings) Translation: YunoHost/core Translate-URL: https://translate.yunohost.org/projects/yunohost/core/fr/ --- locales/fr.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/locales/fr.json b/locales/fr.json index adeeada3b..3b387876f 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -513,7 +513,7 @@ "migration_0008_warning": "Si vous comprenez ces avertissements et souhaitez que YunoHost écrase votre configuration actuelle, exécutez la migration. Sinon, vous pouvez également ignorer la migration, bien que cela ne soit pas recommandé.", "migration_0008_no_warning": "Remplacer votre configuration SSH devrait être sûr, bien que cela ne puisse être promis! Exécutez la migration pour la remplacer. Sinon, vous pouvez également ignorer la migration, bien que cela ne soit pas recommandé.", "migrations_success": "Migration {number} {name} réussie !", - "pattern_password_app": "Désolé, les mots de passe ne doivent pas contenir les caractères suivants : {forbidden_chars}", + "pattern_password_app": "Désolé, les mots de passe ne peuvent pas contenir les caractères suivants : {forbidden_chars}", "root_password_replaced_by_admin_password": "Votre mot de passe root a été remplacé par votre mot de passe administrateur.", "service_conf_now_managed_by_yunohost": "Le fichier de configuration '{conf}' est maintenant géré par YunoHost.", "service_reload_failed": "Impossible de recharger le service '{service:s}'.\n\nJournaux historisés récents de ce service : {logs:s}", @@ -764,5 +764,8 @@ "diagnosis_never_ran_yet": "Il apparaît que le serveur a été installé récemment et qu'il n'y a pas encore eu de diagnostic. Vous devriez en lancer un depuis le webmin ou en utilisant 'yunohost diagnosis run' depuis la ligne de commande.", "diagnosis_description_web": "Web", "diagnosis_basesystem_hardware_board": "Le modèle de carte du serveur est {model}", - "diagnosis_basesystem_hardware": "L'architecture du serveur est {virt} {arch}" + "diagnosis_basesystem_hardware": "L'architecture du serveur est {virt} {arch}", + "group_already_exist_on_system_but_removing_it": "Le groupe {group} est déjà présent dans les groupes du système, mais Yuhonost va le supprimer…", + "certmanager_warning_subdomain_dns_record": "Le sous-domaine '{subdomain:s}' ne résout pas vers la même adresse IP que '{domain:s}'. Certaines fonctionnalités seront indisponibles tant que vous n’aurez pas corrigé cela et regénéré le certificat.", + "domain_cannot_add_xmpp_upload": "Vous ne pouvez pas ajouter de domaine commençant par 'xmpp-upload.'. Ce type de nom est réservé à la fonctionnalité d’upload XMPP intégrée dans Yunohost." } From b0e67460dff0a40713a3c80d6eee91d4faa5ee7e Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Wed, 1 Apr 2020 17:24:08 +0200 Subject: [PATCH 13/29] Add conflict rule against apache2 and bind9 --- debian/control | 1 + 1 file changed, 1 insertion(+) diff --git a/debian/control b/debian/control index 42bafc16c..aed123246 100644 --- a/debian/control +++ b/debian/control @@ -43,6 +43,7 @@ Conflicts: iptables-persistent , yunohost-config-dovecot, yunohost-config-slapd , yunohost-config-nginx, yunohost-config-amavis , yunohost-config-mysql, yunohost-predepends + , apache2, bind9 Replaces: moulinette-yunohost, yunohost-config , yunohost-config-others, yunohost-config-postfix , yunohost-config-dovecot, yunohost-config-slapd From 6c9b5379415701adf1e3b35532ccadd6b39483f8 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Thu, 2 Apr 2020 19:30:40 +0200 Subject: [PATCH 14/29] Drop unused helpers ynh_add_skipped/(un)protected_uris --- data/helpers.d/setting | 92 ------------------------------------------ 1 file changed, 92 deletions(-) diff --git a/data/helpers.d/setting b/data/helpers.d/setting index 384fdc399..f3692cf96 100644 --- a/data/helpers.d/setting +++ b/data/helpers.d/setting @@ -59,98 +59,6 @@ ynh_app_setting_delete() { ynh_app_setting "delete" "$app" "$key" } -# Add skipped_uris urls into the config -# -# usage: ynh_add_skipped_uris [--appid=app] --url=url1,url2 [--regex] -# | arg: -a, --appid - the application id -# | arg: -u, --url - the urls to add to the sso for this app -# | arg: -r, --regex - Use the key 'skipped_regex' instead of 'skipped_uris' -# -# An URL set with 'skipped_uris' key will be totally ignored by the SSO, -# which means that the access will be public and the logged-in user information will not be passed to the app. -# -# Requires YunoHost version 3.6.0 or higher. -ynh_add_skipped_uris() { - # Declare an array to define the options of this helper. - local legacy_args=aur - declare -Ar args_array=( [a]=appid= [u]=url= [r]=regex ) - local appid - local url - local regex - # Manage arguments with getopts - ynh_handle_getopts_args "$@" - appid={appid:-$app} - regex={regex:-0} - - local key=skipped_uris - if [ $regex -eq 1 ]; then - key=skipped_regex - fi - - ynh_app_setting_set --app=$appid --key=$key --value="$url" -} - -# Add unprotected_uris urls into the config -# -# usage: ynh_add_unprotected_uris [--appid=app] --url=url1,url2 [--regex] -# | arg: -a, --appid - the application id -# | arg: -u, --url - the urls to add to the sso for this app -# | arg: -r, --regex - Use the key 'unprotected_regex' instead of 'unprotected_uris' -# -# An URL set with unprotected_uris key will be accessible publicly, but if an user is logged in, -# his information will be accessible (through HTTP headers) to the app. -# -# Requires YunoHost version 3.6.0 or higher. -ynh_add_unprotected_uris() { - # Declare an array to define the options of this helper. - local legacy_args=aur - declare -Ar args_array=( [a]=appid= [u]=url= [r]=regex ) - local appid - local url - local regex - # Manage arguments with getopts - ynh_handle_getopts_args "$@" - appid={appid:-$app} - regex={regex:-0} - - local key=unprotected_uris - if [ $regex -eq 1 ]; then - key=unprotected_regex - fi - - ynh_app_setting_set --app=$appid --key=$key --value="$url" -} - -# Add protected_uris urls into the config -# -# usage: ynh_add_protected_uris [--appid=app] --url=url1,url2 [--regex] -# | arg: -a, --appid - the application id -# | arg: -u, --url - the urls to add to the sso for this app -# | arg: -r, --regex - Use the key 'protected_regex' instead of 'protected_uris' -# -# An URL set with protected_uris will be blocked by the SSO and accessible only to authenticated and authorized users. -# -# Requires YunoHost version 3.6.0 or higher. -ynh_add_protected_uris() { - # Declare an array to define the options of this helper. - local legacy_args=aur - declare -Ar args_array=( [a]=appid= [u]=url= [r]=regex ) - local appid - local url - local regex - # Manage arguments with getopts - ynh_handle_getopts_args "$@" - appid={appid:-$app} - regex={regex:-0} - - local key=protected_uris - if [ $regex -eq 1 ]; then - key=protected_regex - fi - - ynh_app_setting_set --app=$appid --key=$key --value="$url" -} - # Small "hard-coded" interface to avoid calling "yunohost app" directly each # time dealing with a setting is needed (which may be so slow on ARM boards) # From 2c9f1f89e052e6cc1d8adcdded8105417b2f1f53 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Thu, 2 Apr 2020 23:05:54 +0200 Subject: [PATCH 15/29] Simplify indentation in ynh_psql_test_if_first_run --- data/helpers.d/postgresql | 49 ++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/data/helpers.d/postgresql b/data/helpers.d/postgresql index e5df73654..4f51f434d 100644 --- a/data/helpers.d/postgresql +++ b/data/helpers.d/postgresql @@ -265,34 +265,35 @@ ynh_psql_remove_db() { ynh_psql_test_if_first_run() { if [ -f "$PSQL_ROOT_PWD_FILE" ]; then echo "PostgreSQL is already installed, no need to create master password" - else - local psql_root_password="$(ynh_string_random)" - echo "$psql_root_password" >$PSQL_ROOT_PWD_FILE + return + fi - if [ -e /etc/postgresql/9.4/ ]; then - local pg_hba=/etc/postgresql/9.4/main/pg_hba.conf - local logfile=/var/log/postgresql/postgresql-9.4-main.log - elif [ -e /etc/postgresql/9.6/ ]; then - local pg_hba=/etc/postgresql/9.6/main/pg_hba.conf - local logfile=/var/log/postgresql/postgresql-9.6-main.log - else - ynh_die "postgresql shoud be 9.4 or 9.6" - fi + local psql_root_password="$(ynh_string_random)" + echo "$psql_root_password" >$PSQL_ROOT_PWD_FILE - ynh_systemd_action --service_name=postgresql --action=start + if [ -e /etc/postgresql/9.4/ ]; then + local pg_hba=/etc/postgresql/9.4/main/pg_hba.conf + local logfile=/var/log/postgresql/postgresql-9.4-main.log + elif [ -e /etc/postgresql/9.6/ ]; then + local pg_hba=/etc/postgresql/9.6/main/pg_hba.conf + local logfile=/var/log/postgresql/postgresql-9.6-main.log + else + ynh_die "postgresql shoud be 9.4 or 9.6" + fi - sudo --login --user=postgres psql -c"ALTER user postgres WITH PASSWORD '$psql_root_password'" postgres + ynh_systemd_action --service_name=postgresql --action=start - # force all user to connect to local databases using hashed passwords - # https://www.postgresql.org/docs/current/static/auth-pg-hba-conf.html#EXAMPLE-PG-HBA.CONF - # Note: we can't use peer since YunoHost create users with nologin - # See: https://github.com/YunoHost/yunohost/blob/unstable/data/helpers.d/user - ynh_replace_string --match_string="local\(\s*\)all\(\s*\)all\(\s*\)peer" --replace_string="local\1all\2all\3md5" --target_file="$pg_hba" + sudo --login --user=postgres psql -c"ALTER user postgres WITH PASSWORD '$psql_root_password'" postgres - # Advertise service in admin panel - yunohost service add postgresql --log "$logfile" + # force all user to connect to local databases using hashed passwords + # https://www.postgresql.org/docs/current/static/auth-pg-hba-conf.html#EXAMPLE-PG-HBA.CONF + # Note: we can't use peer since YunoHost create users with nologin + # See: https://github.com/YunoHost/yunohost/blob/unstable/data/helpers.d/user + ynh_replace_string --match_string="local\(\s*\)all\(\s*\)all\(\s*\)peer" --replace_string="local\1all\2all\3md5" --target_file="$pg_hba" - systemctl enable postgresql - ynh_systemd_action --service_name=postgresql --action=reload - fi + # Advertise service in admin panel + yunohost service add postgresql --log "$logfile" + + systemctl enable postgresql + ynh_systemd_action --service_name=postgresql --action=reload } From 83a1d6dec53b93a7fcc4e194c5b92b11256b956d Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Thu, 2 Apr 2020 23:13:25 +0200 Subject: [PATCH 16/29] This is not needed --- data/helpers.d/postgresql | 1 - 1 file changed, 1 deletion(-) diff --git a/data/helpers.d/postgresql b/data/helpers.d/postgresql index 4f51f434d..03c713afd 100644 --- a/data/helpers.d/postgresql +++ b/data/helpers.d/postgresql @@ -243,7 +243,6 @@ ynh_psql_remove_db() { # Manage arguments with getopts ynh_handle_getopts_args "$@" - local psql_root_password=$(cat $PSQL_ROOT_PWD_FILE) if ynh_psql_database_exists --database=$db_name; then # Check if the database exists ynh_psql_drop_db $db_name # Remove the database else From fb5dac80d5316f8b8776fff1d57df31ef6a67ac1 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Fri, 3 Apr 2020 00:12:58 +0200 Subject: [PATCH 17/29] Force locale to C/en to avoid perl whining and flooding logs about the damn missing locale --- data/helpers.d/apt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/helpers.d/apt b/data/helpers.d/apt index b2c781faf..7859d44c5 100644 --- a/data/helpers.d/apt +++ b/data/helpers.d/apt @@ -94,7 +94,7 @@ ynh_package_version() { # Requires YunoHost version 2.4.0.3 or higher. ynh_apt() { ynh_wait_dpkg_free - DEBIAN_FRONTEND=noninteractive apt-get -y $@ + LC_ALL=C DEBIAN_FRONTEND=noninteractive apt-get -y $@ } # Update package index files @@ -184,7 +184,7 @@ ynh_package_install_from_equivs () { ynh_wait_dpkg_free cp "$controlfile" "${TMPDIR}/control" (cd "$TMPDIR" - equivs-build ./control 1> /dev/null + LC_ALL=C equivs-build ./control 1> /dev/null dpkg --force-depends -i "./${pkgname}_${pkgversion}_all.deb" 2>&1) # If install fails we use "apt-get check" to try to debug and diagnose possible unmet dependencies # Note the use of { } which allows to group commands without starting a subshell (otherwise the ynh_die wouldn't exit the current shell). From eb4586c244c1af7dc22763a55b67a062fcccdbc7 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Fri, 3 Apr 2020 01:32:05 +0200 Subject: [PATCH 18/29] Do not redact stuff corresponding to --manifest_key --- src/yunohost/log.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/yunohost/log.py b/src/yunohost/log.py index 72e497b5d..cd08bdfe0 100644 --- a/src/yunohost/log.py +++ b/src/yunohost/log.py @@ -315,9 +315,9 @@ class RedactingFormatter(Formatter): try: # This matches stuff like db_pwd=the_secret or admin_password=other_secret # (the secret part being at least 3 chars to avoid catching some lines like just "db_pwd=") - # For 'key', we require to at least have one word char [a-zA-Z0-9_] before it to avoid catching "--key" used in many helpers - match = re.search(r'(pwd|pass|password|secret|\wkey|token)=(\S{3,})$', record.strip()) - if match and match.group(2) not in self.data_to_redact: + # Some names like "key" or "manifest_key" are ignored, used in helpers like ynh_app_setting_set or ynh_read_manifest + match = re.search(r'(pwd|pass|password|secret|\w+key|token)=(\S{3,})$', record.strip()) + if match and match.group(2) not in self.data_to_redact and match.group(1) not in ["key", "manifest_key"]: self.data_to_redact.append(match.group(2)) except Exception as e: logger.warning("Failed to parse line to try to identify data to redact ... : %s" % e) From 128577686a5df3920ba8169c28a5ecf1b62a9987 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Fri, 3 Apr 2020 03:09:46 +0200 Subject: [PATCH 19/29] Forgot to make yunohost_admin.conf to also use the common securit.conf.inc --- data/templates/nginx/yunohost_admin.conf | 42 ++---------------------- 1 file changed, 2 insertions(+), 40 deletions(-) diff --git a/data/templates/nginx/yunohost_admin.conf b/data/templates/nginx/yunohost_admin.conf index e0d9f6bb1..63d466ecd 100644 --- a/data/templates/nginx/yunohost_admin.conf +++ b/data/templates/nginx/yunohost_admin.conf @@ -15,48 +15,10 @@ server { listen 443 ssl http2 default_server; listen [::]:443 ssl http2 default_server; + include /etc/nginx/conf.d/security.conf.inc; + ssl_certificate /etc/yunohost/certs/yunohost.org/crt.pem; ssl_certificate_key /etc/yunohost/certs/yunohost.org/key.pem; - ssl_session_timeout 5m; - ssl_session_cache shared:SSL:50m; - - {% if compatibility == "modern" %} - # Ciphers with modern compatibility - # https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=nginx-1.6.2&openssl=1.0.1t&hsts=yes&profile=modern - # Uncomment the following to use modern ciphers, but remove compatibility with some old clients (android < 5.0, Internet Explorer < 10, ...) - ssl_protocols TLSv1.2; - ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256'; - ssl_prefer_server_ciphers on; - {% else %} - # As suggested by Mozilla : https://wiki.mozilla.org/Security/Server_Side_TLS and https://en.wikipedia.org/wiki/Curve25519 - ssl_ecdh_curve secp521r1:secp384r1:prime256v1; - ssl_prefer_server_ciphers on; - - # Ciphers with intermediate compatibility - # https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=nginx-1.6.2&openssl=1.0.1t&hsts=yes&profile=intermediate - ssl_protocols TLSv1 TLSv1.1 TLSv1.2; - ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS'; - - # Uncomment the following directive after DH generation - # > openssl dhparam -out /etc/ssl/private/dh2048.pem -outform PEM -2 2048 - #ssl_dhparam /etc/ssl/private/dh2048.pem; - {% endif %} - - # Follows the Web Security Directives from the Mozilla Dev Lab and the Mozilla Obervatory + Partners - # https://wiki.mozilla.org/Security/Guidelines/Web_Security - # https://observatory.mozilla.org/ - more_set_headers "Strict-Transport-Security : max-age=63072000; includeSubDomains; preload"; - more_set_headers "Referrer-Policy : 'same-origin'"; - more_set_headers "Content-Security-Policy : upgrade-insecure-requests; object-src 'none'; script-src https: 'unsafe-eval'"; - more_set_headers "X-Content-Type-Options : nosniff"; - more_set_headers "X-XSS-Protection : 1; mode=block"; - more_set_headers "X-Download-Options : noopen"; - more_set_headers "X-Permitted-Cross-Domain-Policies : none"; - more_set_headers "X-Frame-Options : SAMEORIGIN"; - - # Disable gzip to protect against BREACH - # Read https://trac.nginx.org/nginx/ticket/1720 (text/html cannot be disabled!) - gzip off; location / { return 302 https://$http_host/yunohost/admin; From 6813a64cf6e17c23515786de4618456c966c9eb4 Mon Sep 17 00:00:00 2001 From: Kay0u Date: Fri, 3 Apr 2020 20:28:13 +0200 Subject: [PATCH 20/29] remove sync_perm argument --- src/yunohost/permission.py | 2 +- src/yunohost/user.py | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/yunohost/permission.py b/src/yunohost/permission.py index 05def2101..b5ef0884f 100644 --- a/src/yunohost/permission.py +++ b/src/yunohost/permission.py @@ -197,7 +197,7 @@ def user_permission_reset(operation_logger, permission, sync_perm=True): return new_permission -def user_permission_info(permission, sync_perm=True): +def user_permission_info(permission): """ Return informations about a specific permission diff --git a/src/yunohost/user.py b/src/yunohost/user.py index 74ad9f977..4afcc4e72 100644 --- a/src/yunohost/user.py +++ b/src/yunohost/user.py @@ -780,10 +780,9 @@ def user_permission_reset(permission, sync_perm=True): sync_perm=sync_perm) -def user_permission_info(permission, sync_perm=True): +def user_permission_info(permission): import yunohost.permission - return yunohost.permission.user_permission_info(permission, - sync_perm=sync_perm) + return yunohost.permission.user_permission_info(permission) # From ecdb30aab234ebef95dd4e54e4847623327178e8 Mon Sep 17 00:00:00 2001 From: Kay0u Date: Sun, 5 Apr 2020 19:44:39 +0200 Subject: [PATCH 21/29] [fix] config_appy return link --- src/yunohost/app.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/yunohost/app.py b/src/yunohost/app.py index de2a74c9c..39793ec1a 100644 --- a/src/yunohost/app.py +++ b/src/yunohost/app.py @@ -1574,6 +1574,7 @@ def app_config_apply(operation_logger, app, args): logger.success("Config updated as expected") return { + "app": app, "logs": operation_logger.success(), } From ecce6f11cc467d4745aa7e94fa3cbb4184e30f32 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Sun, 5 Apr 2020 20:22:17 +0200 Subject: [PATCH 22/29] Move wildcard DNS record to 'extra' category --- src/yunohost/domain.py | 78 ++++++++++++++++++++++++++---------------- src/yunohost/dyndns.py | 12 ++++++- 2 files changed, 59 insertions(+), 31 deletions(-) diff --git a/src/yunohost/domain.py b/src/yunohost/domain.py index 456dfa4bf..23b5a4179 100644 --- a/src/yunohost/domain.py +++ b/src/yunohost/domain.py @@ -236,8 +236,7 @@ def domain_dns_conf(domain, ttl=None): for record in record_list: result += "\n{name} {ttl} IN {type} {value}".format(**record) - is_cli = True if msettings.get('interface') == 'cli' else False - if is_cli: + if msettings.get('interface') == 'cli': logger.info(m18n.n("domain_dns_conf_is_just_a_recommendation")) return result @@ -406,10 +405,8 @@ def _build_dns_conf(domain, ttl=3600): "basic": [ # if ipv4 available {"type": "A", "name": "@", "value": "123.123.123.123", "ttl": 3600}, - {"type": "A", "name": "*", "value": "123.123.123.123", "ttl": 3600}, # if ipv6 available {"type": "AAAA", "name": "@", "value": "valid-ipv6", "ttl": 3600}, - {"type": "AAAA", "name": "*", "value": "valid-ipv6", "ttl": 3600}, ], "xmpp": [ {"type": "SRV", "name": "_xmpp-client._tcp", "value": "0 5 5222 domain.tld.", "ttl": 3600}, @@ -426,6 +423,10 @@ def _build_dns_conf(domain, ttl=3600): {"type": "TXT", "name": "_dmarc", "value": "\"v=DMARC1; p=none\"", "ttl": 3600} ], "extra": [ + # if ipv4 available + {"type": "A", "name": "*", "value": "123.123.123.123", "ttl": 3600}, + # if ipv6 available + {"type": "AAAA", "name": "*", "value": "valid-ipv6", "ttl": 3600}, {"type": "CAA", "name": "@", "value": "128 issue \"letsencrypt.org\"", "ttl": 3600}, ], "example_of_a_custom_rule": [ @@ -437,32 +438,21 @@ def _build_dns_conf(domain, ttl=3600): ipv4 = get_public_ip() ipv6 = get_public_ip(6) - basic = [] + ########################### + # Basic ipv4/ipv6 records # + ########################### - # Basic ipv4/ipv6 records + basic = [] if ipv4: - basic += [ - ["@", ttl, "A", ipv4], - ["*", ttl, "A", ipv4], - ] + basic.append(["@", ttl, "A", ipv4]) if ipv6: - basic += [ - ["@", ttl, "AAAA", ipv6], - ["*", ttl, "AAAA", ipv6], - ] + basic.append(["@", ttl, "AAAA", ipv6]) - # XMPP - xmpp = [ - ["_xmpp-client._tcp", ttl, "SRV", "0 5 5222 %s." % domain], - ["_xmpp-server._tcp", ttl, "SRV", "0 5 5269 %s." % domain], - ["muc", ttl, "CNAME", "@"], - ["pubsub", ttl, "CNAME", "@"], - ["vjud", ttl, "CNAME", "@"], - ["xmpp-upload", ttl, "CNAME", "@"], - ] + ######### + # Email # + ######### - # SPF record spf_record = '"v=spf1 a mx' if ipv4: spf_record += ' ip4:{ip4}'.format(ip4=ipv4) @@ -470,7 +460,6 @@ def _build_dns_conf(domain, ttl=3600): spf_record += ' ip6:{ip6}'.format(ip6=ipv6) spf_record += ' -all"' - # Email mail = [ ["@", ttl, "MX", "10 %s." % domain], ["@", ttl, "TXT", spf_record], @@ -485,12 +474,36 @@ def _build_dns_conf(domain, ttl=3600): ["_dmarc", ttl, "TXT", '"v=DMARC1; p=none"'], ] - # Extra - extra = [ - ["@", ttl, "CAA", '128 issue "letsencrypt.org"'] + ######## + # XMPP # + ######## + + xmpp = [ + ["_xmpp-client._tcp", ttl, "SRV", "0 5 5222 %s." % domain], + ["_xmpp-server._tcp", ttl, "SRV", "0 5 5269 %s." % domain], + ["muc", ttl, "CNAME", "@"], + ["pubsub", ttl, "CNAME", "@"], + ["vjud", ttl, "CNAME", "@"], + ["xmpp-upload", ttl, "CNAME", "@"], ] - # Official record + ######### + # Extra # + ######### + + extra = [] + + if ipv4: + extra.append(["*", ttl, "A", ipv4]) + if ipv6: + extra.append(["*", ttl, "AAAA", ipv6]) + + extra.append(["@", ttl, "CAA", '128 issue "letsencrypt.org"']) + + #################### + # Standard records # + #################### + records = { "basic": [{"name": name, "ttl": ttl, "type": type_, "value": value} for name, ttl, type_, value in basic], "xmpp": [{"name": name, "ttl": ttl, "type": type_, "value": value} for name, ttl, type_, value in xmpp], @@ -498,7 +511,12 @@ def _build_dns_conf(domain, ttl=3600): "extra": [{"name": name, "ttl": ttl, "type": type_, "value": value} for name, ttl, type_, value in extra], } - # Custom records + ################## + # Custom records # + ################## + + # Defined by custom hooks ships in apps for example ... + hook_results = hook_callback('custom_dns_rules', args=[domain]) for hook_name, results in hook_results.items(): # diff --git a/src/yunohost/dyndns.py b/src/yunohost/dyndns.py index 70817b3fe..6e597fbbf 100644 --- a/src/yunohost/dyndns.py +++ b/src/yunohost/dyndns.py @@ -258,7 +258,17 @@ def dyndns_update(operation_logger, dyn_host="dyndns.yunohost.org", domain=None, logger.info("Updated needed, going on...") dns_conf = _build_dns_conf(domain) - del dns_conf["extra"] # Ignore records from the 'extra' category + + for i, record in enumerate(dns_conf["extra"]): + # Ignore CAA record ... not sure why, we could probably enforce it... + if record[3] == "CAA": + del dns_conf["extra"][i] + + # Delete custom DNS records, we don't support them (have to explicitly + # authorize them on dynette) + for category in dns_conf.keys(): + if category not in ["basic", "mail", "xmpp", "extra"]: + del dns_conf[category] # Delete the old records for all domain/subdomains From f032ba16cc5b6778e18a7042943f45e212fab6f0 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Sun, 5 Apr 2020 20:23:32 +0200 Subject: [PATCH 23/29] Only diagnose basic records for subdomains --- data/hooks/diagnosis/12-dnsrecords.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/data/hooks/diagnosis/12-dnsrecords.py b/data/hooks/diagnosis/12-dnsrecords.py index 96ac31d55..a889201b9 100644 --- a/data/hooks/diagnosis/12-dnsrecords.py +++ b/data/hooks/diagnosis/12-dnsrecords.py @@ -28,21 +28,24 @@ class DNSRecordsDiagnoser(Diagnoser): all_domains = domain_list()["domains"] for domain in all_domains: self.logger_debug("Diagnosing DNS conf for %s" % domain) - for report in self.check_domain(domain, domain == main_domain): + is_subdomain = domain.split(".",1)[1] in all_domains + for report in self.check_domain(domain, domain == main_domain, is_subdomain=is_subdomain): yield report # FIXME : somewhere, should implement a check for reverse DNS ... # FIXME / TODO : somewhere, could also implement a check for domain expiring soon - def check_domain(self, domain, is_main_domain): + def check_domain(self, domain, is_main_domain, is_subdomain): expected_configuration = _build_dns_conf(domain) - # Here if there are no AAAA record, we should add something to expect "no" AAAA record + # FIXME: Here if there are no AAAA record, we should add something to expect "no" AAAA record # to properly diagnose situations where people have a AAAA record but no IPv6 - categories = ["basic", "mail", "xmpp", "extra"] + if is_subdomain: + categories = ["basic"] + for category in categories: records = expected_configuration[category] From 3bd6a7aa2983f19237939ade661ebee1780461ed Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Mon, 6 Apr 2020 15:39:40 +0200 Subject: [PATCH 24/29] Explicitly depends on lsb-release --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index aed123246..4b3837c1b 100644 --- a/debian/control +++ b/debian/control @@ -15,7 +15,7 @@ Depends: ${python:Depends}, ${misc:Depends} , python-psutil, python-requests, python-dnspython, python-openssl , python-apt, python-miniupnpc, python-dbus, python-jinja2 , python-toml - , apt-transport-https + , apt, apt-transport-https, lsb-release , dnsutils, bind9utils, unzip, git, curl, cron, wget, jq , ca-certificates, netcat-openbsd, iproute2 , mariadb-server, php-mysql | php-mysqlnd From 4d99cbe87075fc9180b49f12ef45d51db2d3892d Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Mon, 6 Apr 2020 16:54:25 +0200 Subject: [PATCH 25/29] Add ref for security headers --- data/templates/nginx/security.conf.inc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/data/templates/nginx/security.conf.inc b/data/templates/nginx/security.conf.inc index 272a29e26..28d12055b 100644 --- a/data/templates/nginx/security.conf.inc +++ b/data/templates/nginx/security.conf.inc @@ -20,6 +20,9 @@ ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECD #ssl_dhparam /etc/ssl/private/dh2048.pem; {% endif %} +# Follows the Web Security Directives from the Mozilla Dev Lab and the Mozilla Obervatory + Partners +# https://wiki.mozilla.org/Security/Guidelines/Web_Security +# https://observatory.mozilla.org/ more_set_headers "Content-Security-Policy : upgrade-insecure-requests"; more_set_headers "Content-Security-Policy-Report-Only : default-src https: data: 'unsafe-inline' 'unsafe-eval'"; more_set_headers "X-Content-Type-Options : nosniff"; From 22b9565eb72161e1a66db5980aad8ad56d220a3c Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Mon, 6 Apr 2020 16:56:53 +0200 Subject: [PATCH 26/29] Forgot to check that these headers are different from the default in security.conf ... maybe we want to keep them as is? Not clear why they have different values tan the domain configs... --- data/templates/nginx/yunohost_admin.conf | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/data/templates/nginx/yunohost_admin.conf b/data/templates/nginx/yunohost_admin.conf index 63d466ecd..3df838c4a 100644 --- a/data/templates/nginx/yunohost_admin.conf +++ b/data/templates/nginx/yunohost_admin.conf @@ -20,6 +20,10 @@ server { ssl_certificate /etc/yunohost/certs/yunohost.org/crt.pem; ssl_certificate_key /etc/yunohost/certs/yunohost.org/key.pem; + more_set_headers "Strict-Transport-Security : max-age=63072000; includeSubDomains; preload"; + more_set_headers "Referrer-Policy : 'same-origin'"; + more_set_headers "Content-Security-Policy : upgrade-insecure-requests; object-src 'none'; script-src https: 'unsafe-eval'"; + location / { return 302 https://$http_host/yunohost/admin; } From be8427d5a117fd34ade956d8b67f0ad42533e2e6 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Wed, 8 Apr 2020 12:15:01 +0200 Subject: [PATCH 27/29] Gotta generate security.conf.inc during .deb deployment because it's needed by yunohost_admin.conf --- data/hooks/conf_regen/15-nginx | 1 + 1 file changed, 1 insertion(+) diff --git a/data/hooks/conf_regen/15-nginx b/data/hooks/conf_regen/15-nginx index 11e5f596c..412320e0b 100755 --- a/data/hooks/conf_regen/15-nginx +++ b/data/hooks/conf_regen/15-nginx @@ -23,6 +23,7 @@ do_init_regen() { rm -f "${nginx_dir}/sites-enabled/default" export compatibility="intermediate" + ynh_render_template "security.conf.inc" "${nginx_conf_dir}/security.conf.inc" ynh_render_template "yunohost_admin.conf" "${nginx_conf_dir}/yunohost_admin.conf" # Restart nginx if conf looks good, otherwise display error and exit unhappy From 0a482fd879ce721c3e362e2b0ae876515051b75d Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Wed, 8 Apr 2020 12:56:47 +0200 Subject: [PATCH 28/29] Move openssh-server to Depends, reorganize Depends list --- debian/control | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/debian/control b/debian/control index 4b3837c1b..5bcd78491 100644 --- a/debian/control +++ b/debian/control @@ -15,22 +15,23 @@ Depends: ${python:Depends}, ${misc:Depends} , python-psutil, python-requests, python-dnspython, python-openssl , python-apt, python-miniupnpc, python-dbus, python-jinja2 , python-toml - , apt, apt-transport-https, lsb-release - , dnsutils, bind9utils, unzip, git, curl, cron, wget, jq - , ca-certificates, netcat-openbsd, iproute2 + , apt, apt-transport-https + , nginx, nginx-extras (>=1.6.2) + , php-fpm, php-ldap, php-intl , mariadb-server, php-mysql | php-mysqlnd + , openssh-server, iptables, fail2ban, dnsutils, bind9utils + , openssl, ca-certificates, netcat-openbsd, iproute2 , slapd, ldap-utils, sudo-ldap, libnss-ldapd, unscd, libpam-ldapd - , postfix-ldap, postfix-policyd-spf-perl, postfix-pcre, procmail, mailutils, postsrsd - , dovecot-ldap, dovecot-lmtpd, dovecot-managesieved - , dovecot-antispam, fail2ban, iptables - , nginx-extras (>=1.6.2), php-fpm, php-ldap, php-intl - , dnsmasq, openssl, avahi-daemon, libnss-mdns, resolvconf, libnss-myhostname + , dnsmasq, avahi-daemon, libnss-mdns, resolvconf, libnss-myhostname + , postfix, postfix-ldap, postfix-policyd-spf-perl, postfix-pcre + , dovecot-core, dovecot-ldap, dovecot-lmtpd, dovecot-managesieved, dovecot-antispam + , rspamd (>= 1.6.0), opendkim-tools, postsrsd, procmail, mailutils + , redis-server , metronome - , rspamd (>= 1.6.0), redis-server, opendkim-tools - , haveged, fake-hwclock - , equivs, lsof + , git, curl, wget, cron, unzip, jq + , lsb-release, haveged, fake-hwclock, equivs, lsof Recommends: yunohost-admin - , openssh-server, ntp, inetutils-ping | iputils-ping + , ntp, inetutils-ping | iputils-ping , bash-completion, rsyslog , php-gd, php-curl, php-gettext, php-mcrypt , python-pip From c0f94ba98ae3b8e64a5b7254144e3f4a65ef1bb9 Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Thu, 9 Apr 2020 12:29:44 +0200 Subject: [PATCH 29/29] [fix] uid will be tested as a string --- src/yunohost/user.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/yunohost/user.py b/src/yunohost/user.py index 39a2d8f15..fd67314d8 100644 --- a/src/yunohost/user.py +++ b/src/yunohost/user.py @@ -165,8 +165,8 @@ def user_create(operation_logger, username, firstname, lastname, mail, password, operation_logger.start() # Get random UID/GID - all_uid = {x.pw_uid for x in pwd.getpwall()} - all_gid = {x.gr_gid for x in grp.getgrall()} + all_uid = {str(x.pw_uid) for x in pwd.getpwall()} + all_gid = {str(x.gr_gid) for x in grp.getgrall()} uid_guid_found = False while not uid_guid_found: