From f79b0ff0a3954b9d29c9b93e5146c9d56b8b6201 Mon Sep 17 00:00:00 2001 From: ljf Date: Wed, 23 Sep 2020 05:00:09 +0200 Subject: [PATCH] [enh] SFTP and SSH permissions --- data/actionsmap/yunohost.yml | 16 ----- data/hooks/conf_regen/03-ssh | 1 - data/other/ldap_scheme.yml | 21 ++++++ data/templates/ssh/sshd_config | 1 - locales/en.json | 2 +- .../0019_ssh_sftp_permissions.py | 56 +++++++++++++++ src/yunohost/ssh.py | 70 ------------------- src/yunohost/user.py | 6 -- 8 files changed, 78 insertions(+), 95 deletions(-) create mode 100644 src/yunohost/data_migrations/0019_ssh_sftp_permissions.py diff --git a/data/actionsmap/yunohost.yml b/data/actionsmap/yunohost.yml index 4f9f608bb..afe595723 100644 --- a/data/actionsmap/yunohost.yml +++ b/data/actionsmap/yunohost.yml @@ -408,22 +408,6 @@ user: key: help: The key to be removed - ### user_ssh_enable_permission() - enable-permission: - action_help: Enable sftp permission - api: POST /users/ssh/sftp/enable - configuration: - authenticate: all - authenticator: as-root - - ### user_ssh_disable_permission() - disable-permission: - action_help: Disable sftp permission - api: POST /users/ssh/sftp/disable - configuration: - authenticate: all - authenticator: as-root - ############################# # Domain # ############################# diff --git a/data/hooks/conf_regen/03-ssh b/data/hooks/conf_regen/03-ssh index 76a894ccf..54b7c55b7 100755 --- a/data/hooks/conf_regen/03-ssh +++ b/data/hooks/conf_regen/03-ssh @@ -28,7 +28,6 @@ do_pre_regen() { export ssh_keys export ipv6_enabled - export sftp_secure ynh_render_template "sshd_config" "${pending_dir}/etc/ssh/sshd_config" } diff --git a/data/other/ldap_scheme.yml b/data/other/ldap_scheme.yml index aa2b46ad3..ba678f1f8 100644 --- a/data/other/ldap_scheme.yml +++ b/data/other/ldap_scheme.yml @@ -89,3 +89,24 @@ depends_children: label: "XMPP" showTile: "FALSE" isProtected: "TRUE" + cn=ssh.main,ou=permission: + cn: ssh.main + gidNumber: "5003" + objectClass: + - posixGroup + - permissionYnh + groupPermission: [] + cn=ssh.tunnel,ou=permission: + cn: ssh.tunnel + gidNumber: "5004" + objectClass: + - posixGroup + - permissionYnh + groupPermission: [] + cn=sftp.main,ou=permission: + cn: sftp.main + gidNumber: "5005" + objectClass: + - posixGroup + - permissionYnh + groupPermission: [] diff --git a/data/templates/ssh/sshd_config b/data/templates/ssh/sshd_config index bb6520e64..709483728 100644 --- a/data/templates/ssh/sshd_config +++ b/data/templates/ssh/sshd_config @@ -91,7 +91,6 @@ PermitTunnel no # Disable .ssh/rc, which could be edited (e.g. from Nextcloud or whatever) by users to execute arbitrary commands even if SSH login is disabled PermitUserRC no - # root login is allowed on local networks # It's meant to be a backup solution in case LDAP is down and # user admin can't be used... diff --git a/locales/en.json b/locales/en.json index a08855ce2..a23441382 100644 --- a/locales/en.json +++ b/locales/en.json @@ -587,7 +587,7 @@ "show_tile_cant_be_enabled_for_regex": "You cannot enable 'show_tile' right no, because the URL for the permission '{permission}' is a regex", "sftp_permission_already_disabled": "SFTP permission already disabled", "sftp_permission_already_enabled": "SFTP permission already enabled", - "ssowat_conf_generated": "SSOwat configuration regenerated", + "ssowat_conf_generated": "SSOwat configuration generated", "ssowat_conf_updated": "SSOwat configuration updated", "system_upgraded": "System upgraded", "system_username_exists": "Username already exists in the list of system users", diff --git a/src/yunohost/data_migrations/0019_ssh_sftp_permissions.py b/src/yunohost/data_migrations/0019_ssh_sftp_permissions.py new file mode 100644 index 000000000..fc970bd56 --- /dev/null +++ b/src/yunohost/data_migrations/0019_ssh_sftp_permissions.py @@ -0,0 +1,56 @@ +import time +import subprocess + +from moulinette import m18n +from yunohost.utils.error import YunohostError +from moulinette.utils.log import getActionLogger +from moulinette.utils.filesystem import read_yaml + +from yunohost.tools import Migration +from yunohost.permission import user_permission_update + +logger = getActionLogger('yunohost.migration') + +################################################### +# Tools used also for restoration +################################################### + + +class MyMigration(Migration): + """ + Add new permissions around SSH/SFTP features + """ + + required = True + + def run(self): + logger.info(m18n.n("migration_0019_ssh_sftp_permissions")) + + from yunohost.utils.ldap import _get_ldap_interface + ldap = _get_ldap_interface() + + add_perm_to_users = False + + # Add SSH and SFTP permissions + ldap_map = read_yaml('/usr/share/yunohost/yunohost-config/moulinette/ldap_scheme.yml') + for rdn, attr_dict in ldap_map['depends_children'].items(): + try: + objects = ldap.search(rdn + ",dc=yunohost,dc=org") + # ldap search will raise an exception if no corresponding object is found >.> ... + except Exception as e: + if rdn == "cn=ssh.main,ou=permission": + add_perm_to_users = True + ldap.add(rdn, attr_dict) + + # Add a bash terminal to each users + users = ldap.search('ou=users,dc=yunohost,dc=org', filter="(loginShell=*)", attrs=["dn", "uid", "loginShell"]) + for user in users: + if user['loginShell'][0] == '/bin/false': + dn=user['dn'][0].replace(',dc=yunohost,dc=org', '') + ldap.update(dn, {'loginShell': ['/bin/bash']}) + elif add_perm_to_users: + user_permission_update("ssh.main", add=user["uid"][0], sync_perm=False) + + # Somehow this is needed otherwise the PAM thing doesn't forget about the + # old loginShell value ? + subprocess.call(['nscd', '-i', 'passwd']) diff --git a/src/yunohost/ssh.py b/src/yunohost/ssh.py index eb4cc2702..9122cf1d6 100644 --- a/src/yunohost/ssh.py +++ b/src/yunohost/ssh.py @@ -6,55 +6,10 @@ import pwd import subprocess from yunohost.utils.error import YunohostError -from moulinette import m18n -from moulinette.utils.log import getActionLogger from moulinette.utils.filesystem import read_file, write_to_file, chown, chmod, mkdir SSHD_CONFIG_PATH = "/etc/ssh/sshd_config" -logger = getActionLogger('yunohost.user') - -def user_ssh_allow(username): - """ - Allow YunoHost user connect as ssh. - - Keyword argument: - username -- User username - """ - # TODO it would be good to support different kind of shells - - if not _get_user_for_ssh(username): - raise YunohostError('user_unknown', user=username) - - from yunohost.utils.ldap import _get_ldap_interface - ldap = _get_ldap_interface() - ldap.update('uid=%s,ou=users' % username, {'loginShell': ['/bin/bash']}) - - # Somehow this is needed otherwise the PAM thing doesn't forget about the - # old loginShell value ? - subprocess.call(['nscd', '-i', 'passwd']) - - -def user_ssh_disallow(username): - """ - Disallow YunoHost user connect as ssh. - - Keyword argument: - username -- User username - """ - # TODO it would be good to support different kind of shells - - if not _get_user_for_ssh(username): - raise YunohostError('user_unknown', user=username) - - from yunohost.utils.ldap import _get_ldap_interface - ldap = _get_ldap_interface() - ldap.update('uid=%s,ou=users' % username, {'loginShell': ['/bin/false']}) - - # Somehow this is needed otherwise the PAM thing doesn't forget about the - # old loginShell value ? - subprocess.call(['nscd', '-i', 'passwd']) - def user_ssh_list_keys(username): user = _get_user_for_ssh(username, ["homeDirectory"]) @@ -150,31 +105,6 @@ def user_ssh_remove_key(username, key): write_to_file(authorized_keys_file, authorized_keys_content) - -def user_ssh_enable_permission(auth): - """ - Enable the permission for sftp. When disabled all user are allowed to access by sftp. - - """ - from permission import permission_add, user_permission_list - - if user_permission_list(auth, app="sftp", permission="main")['permissions']: - logger.warning(m18n.n('sftp_permission_already_enabled')) - else: - permission_add(auth, "sftp", "main") - -def user_ssh_disable_permission(auth): - """ - Diable the permission for sftp. When disabled all user are allowed to access by sftp. - - """ - from permission import permission_remove, user_permission_list - - if user_permission_list(auth, app="sftp", permission="main")['permissions']: - permission_remove(auth, "sftp", "main", force=True) - else: - logger.warning(m18n.n('sftp_permission_already_disabled')) - # # Helpers # diff --git a/src/yunohost/user.py b/src/yunohost/user.py index 50b352d61..67fd43a03 100644 --- a/src/yunohost/user.py +++ b/src/yunohost/user.py @@ -816,12 +816,6 @@ def user_ssh_add_key(username, key, comment): def user_ssh_remove_key(username, key): return yunohost.ssh.user_ssh_remove_key(username, key) -def user_ssh_enable_permission(auth): - return yunohost.ssh.user_ssh_enable_permission(auth) - -def user_ssh_disable_permission(auth): - return yunohost.ssh.user_ssh_disable_permission(auth) - # # End SSH subcategory #