[enh] SFTP and SSH permissions

This commit is contained in:
ljf 2020-09-23 05:00:09 +02:00
parent 5e6bcb2346
commit f79b0ff0a3
8 changed files with 78 additions and 95 deletions

View file

@ -408,22 +408,6 @@ user:
key: key:
help: The key to be removed 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 # # Domain #
############################# #############################

View file

@ -28,7 +28,6 @@ do_pre_regen() {
export ssh_keys export ssh_keys
export ipv6_enabled export ipv6_enabled
export sftp_secure
ynh_render_template "sshd_config" "${pending_dir}/etc/ssh/sshd_config" ynh_render_template "sshd_config" "${pending_dir}/etc/ssh/sshd_config"
} }

View file

@ -89,3 +89,24 @@ depends_children:
label: "XMPP" label: "XMPP"
showTile: "FALSE" showTile: "FALSE"
isProtected: "TRUE" 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: []

View file

@ -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 # 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 PermitUserRC no
# root login is allowed on local networks # root login is allowed on local networks
# It's meant to be a backup solution in case LDAP is down and # It's meant to be a backup solution in case LDAP is down and
# user admin can't be used... # user admin can't be used...

View file

@ -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", "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_disabled": "SFTP permission already disabled",
"sftp_permission_already_enabled": "SFTP permission already enabled", "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", "ssowat_conf_updated": "SSOwat configuration updated",
"system_upgraded": "System upgraded", "system_upgraded": "System upgraded",
"system_username_exists": "Username already exists in the list of system users", "system_username_exists": "Username already exists in the list of system users",

View file

@ -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'])

View file

@ -6,55 +6,10 @@ import pwd
import subprocess import subprocess
from yunohost.utils.error import YunohostError 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 from moulinette.utils.filesystem import read_file, write_to_file, chown, chmod, mkdir
SSHD_CONFIG_PATH = "/etc/ssh/sshd_config" 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): def user_ssh_list_keys(username):
user = _get_user_for_ssh(username, ["homeDirectory"]) 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) 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 # Helpers
# #

View file

@ -816,12 +816,6 @@ def user_ssh_add_key(username, key, comment):
def user_ssh_remove_key(username, key): def user_ssh_remove_key(username, key):
return yunohost.ssh.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 # End SSH subcategory
# #