diff --git a/data/hooks/conf_regen/15-nginx b/data/hooks/conf_regen/15-nginx index 8875693c6..e2d12df0f 100755 --- a/data/hooks/conf_regen/15-nginx +++ b/data/hooks/conf_regen/15-nginx @@ -83,6 +83,13 @@ do_pre_regen() { done + export webadmin_allowlist_enabled=$(yunohost settings get security.webadmin.allowlist.enabled) + if [ "$webadmin_allowlist_enabled" == "True" ] + then + export webadmin_allowlist=$(yunohost settings get security.webadmin.allowlist) + fi + ynh_render_template "yunohost_admin.conf.inc" "${nginx_conf_dir}/yunohost_admin.conf.inc" + ynh_render_template "yunohost_api.conf.inc" "${nginx_conf_dir}/yunohost_api.conf.inc" ynh_render_template "yunohost_admin.conf" "${nginx_conf_dir}/yunohost_admin.conf" mkdir -p $nginx_conf_dir/default.d/ cp "redirect_to_admin.conf" $nginx_conf_dir/default.d/ diff --git a/data/templates/nginx/plain/yunohost_admin.conf.inc b/data/templates/nginx/yunohost_admin.conf.inc similarity index 76% rename from data/templates/nginx/plain/yunohost_admin.conf.inc rename to data/templates/nginx/yunohost_admin.conf.inc index 4b9938eac..150fce6f6 100644 --- a/data/templates/nginx/plain/yunohost_admin.conf.inc +++ b/data/templates/nginx/yunohost_admin.conf.inc @@ -6,6 +6,13 @@ location /yunohost/admin/ { default_type text/html; index index.html; + {% if webadmin_allowlist_enabled == "True" %} + {% for ip in webadmin_allowlist.split(',') %} + allow {{ ip }}; + {% endfor %} + deny all; + {% endif %} + more_set_headers "Content-Security-Policy: upgrade-insecure-requests; default-src 'self'; connect-src 'self' https://paste.yunohost.org wss://$host; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-eval'; object-src 'none'; img-src 'self' data:;"; more_set_headers "Content-Security-Policy-Report-Only:"; } diff --git a/data/templates/nginx/plain/yunohost_api.conf.inc b/data/templates/nginx/yunohost_api.conf.inc similarity index 75% rename from data/templates/nginx/plain/yunohost_api.conf.inc rename to data/templates/nginx/yunohost_api.conf.inc index 4d7887cc6..c9ae34f82 100644 --- a/data/templates/nginx/plain/yunohost_api.conf.inc +++ b/data/templates/nginx/yunohost_api.conf.inc @@ -6,6 +6,13 @@ location /yunohost/api/ { proxy_set_header Connection "upgrade"; proxy_set_header Host $http_host; + {% if webadmin_allowlist_enabled == "True" %} + {% for ip in webadmin_allowlist.split(',') %} + allow {{ ip }}; + {% endfor %} + deny all; + {% endif %} + # Custom 502 error page error_page 502 /yunohost/api/error/502; } diff --git a/locales/en.json b/locales/en.json index a20abb4b6..1511bed0a 100644 --- a/locales/en.json +++ b/locales/en.json @@ -338,6 +338,8 @@ "global_settings_setting_smtp_relay_port": "SMTP relay port", "global_settings_setting_smtp_relay_user": "SMTP relay user account", "global_settings_setting_smtp_relay_password": "SMTP relay host password", + "global_settings_setting_security_webadmin_allowlist_enabled": "Allow only some IPs to access the webadmin.", + "global_settings_setting_security_webadmin_allowlist": "IP adresses allowed to access the webadmin. Comma-separated.", "global_settings_setting_backup_compress_tar_archives": "When creating new backups, compress the archives (.tar.gz) instead of uncompressed archives (.tar). N.B. : enabling this option means create lighter backup archives, but the initial backup procedure will be significantly longer and heavy on CPU.", "global_settings_unknown_type": "Unexpected situation, the setting {setting} appears to have the type {unknown_type} but it is not a type supported by the system.", "good_practices_about_admin_password": "You are now about to define a new administration password. The password should be at least 8 characters long—though it is good practice to use a longer password (i.e. a passphrase) and/or to use a variation of characters (uppercase, lowercase, digits and special characters).", diff --git a/src/yunohost/settings.py b/src/yunohost/settings.py index 28f5bc687..ec0e7566c 100644 --- a/src/yunohost/settings.py +++ b/src/yunohost/settings.py @@ -100,6 +100,8 @@ DEFAULTS = OrderedDict( ("smtp.relay.password", {"type": "string", "default": ""}), ("backup.compress_tar_archives", {"type": "bool", "default": False}), ("ssowat.panel_overlay.enabled", {"type": "bool", "default": True}), + ("security.webadmin.allowlist.enabled", {"type": "bool", "default": False}), + ("security.webadmin.allowlist", {"type": "string", "default": ""}), ] ) @@ -390,6 +392,8 @@ def trigger_post_change_hook(setting_name, old_value, new_value): @post_change_hook("ssowat.panel_overlay.enabled") @post_change_hook("security.nginx.compatibility") +@post_change_hook("security.webadmin.allowlist.enabled") +@post_change_hook("security.webadmin.allowlist") def reconfigure_nginx(setting_name, old_value, new_value): if old_value != new_value: regen_conf(names=["nginx"])