diff --git a/locales/en.json b/locales/en.json index 3a629ea0e..23b9c5751 100644 --- a/locales/en.json +++ b/locales/en.json @@ -307,6 +307,7 @@ "migration_description_0006_sync_admin_and_root_passwords": "Synchronize admin and root passwords", "migration_description_0007_ssh_conf_managed_by_yunohost_step1": "Let the SSH configuration be managed by YunoHost (step 1, automatic)", "migration_description_0008_ssh_conf_managed_by_yunohost_step2": "Let the SSH configuration be managed by YunoHost (step 2, manual)", + "migration_description_0009_setup_group_permission": "Setup user group and setup permission for apps and services", "migration_0003_backward_impossible": "The stretch migration cannot be reverted.", "migration_0003_start": "Starting migration to Stretch. The logs will be available in {logfile}.", "migration_0003_patching_sources_list": "Patching the sources.lists…", @@ -332,6 +333,12 @@ "migration_0008_dsa": " - the DSA key will be disabled. Hence, you might need to invalidate a spooky warning from your SSH client, and recheck the fingerprint of your server;", "migration_0008_warning": "If you understand those warnings and agree to let YunoHost override your current configuration, run the migration. Otherwise, you can also skip the migration - though it is not recommended.", "migration_0008_no_warning": "No major risk has been indentified about overriding your SSH configuration - but we can't be absolutely sure ;)! If you agree to let YunoHost override your current configuration, run the migration. Otherwise, you can also skip the migration - though it is not recommended.", + "migration_0009_create_group": "Create group for each user.", + "migration_0009_disclaimer": "Your LDAP schema will be updated and your LDAP database will be updated", + "migration_0009_done": "Migration sucess. You are now able to use groups of user.", + "migration_0009_migrate_permission": "Migrate permission from apps settings to LDAP", + "migration_0009_update_LDAP_database": "Update LDAP database for groups and permission support", + "migration_0009_update_LDAP_schema": "Update LDAP schema", "migrations_backward": "Migrating backward.", "migrations_bad_value_for_target": "Invalid number for target argument, available migrations numbers are 0 or {}", "migrations_cant_reach_migration_file": "Can't access migrations files at path %s", diff --git a/src/yunohost/data_migrations/0009_setup_group_permission.py b/src/yunohost/data_migrations/0009_setup_group_permission.py new file mode 100644 index 000000000..2b88388eb --- /dev/null +++ b/src/yunohost/data_migrations/0009_setup_group_permission.py @@ -0,0 +1,108 @@ +import yaml +import errno + +from moulinette import m18n +from moulinette.core import MoulinetteError, init_authenticator +from moulinette.utils.log import getActionLogger + +from yunohost.tools import Migration +from yunohost.utils.filesystem import free_space_in_directory, space_used_by_directory +from yunohost.user import user_list, user_group_add, user_group_update +from yunohost.app import app_setting, app_list +from yunohost.service import service_regen_conf +from yunohost.permission import permission_add, permission_sync_to_user +from yunohost.user import user_permission_add + +logger = getActionLogger('yunohost.migration') + +################################################### +# Tools used also for restoration +################################################### + +def migrate_LDAP_db(auth): + logger.info(m18n.n("migration_0009_update_LDAP_database")) + try: + auth.remove('cn=sftpusers,ou=groups') + except Exception as e: + logger.warn("Error when trying remove sftpusers group") + + with open('/usr/share/yunohost/yunohost-config/moulinette/ldap_scheme.yml') as f: + ldap_map = yaml.load(f) + + try: + attr_dict = ldap_map['parents']['ou=permission'] + auth.add('ou=permission', attr_dict) + + attr_dict = ldap_map['children']['cn=all_users,ou=groups'] + auth.add('cn=all_users,ou=groups', attr_dict) + + for rdn, attr_dict in ldap_map['depends_children'].items(): + auth.add(rdn, attr_dict) + except Exception as e: + raise MoulinetteError(errno.EINVAL, m18n.n(("LDAP_update_failled"))) + + logger.info(m18n.n("migration_0009_create_group")) + + #Create group for each yunohost user + user_list = auth.search('ou=users,dc=yunohost,dc=org', + '(&(objectclass=person)(!(uid=root))(!(uid=nobody)))', + ['uid', 'uidNumber']) + for user_info in user_list: + username = user_info['uid'][0] + user_group_add(auth, username, gid=user_info['uidNumber'][0], sync_perm=False) + user_group_update(auth, groupname=username, add_user=username, force=True, sync_perm=False) + user_group_update(auth, 'all_users', add_user=username, force=True, sync_perm=False) + + +def migrate_app_permission(auth): + logger.info(m18n.n("migration_0009_migrate_permission")) + + for app_info in app_list(installed=True)['apps']: + app = app_info['id'] + permission = app_setting(app, 'allowed_users') + path = app_setting(app, 'path') + domain = app_setting(app, 'domain') + + url = None + if domain and path: + url = domain + path + permission_add(auth, app, 'main', url=url, default_allow=True, sync_perm=False) + if permission: + allowed_group = permission.split(',') + user_permission_add(auth, [app], 'main', group=allowed_group, sync_perm=False) + app_setting(app, 'allowed_users', delete=True) + + +class MyMigration(Migration): + """ + Update the LDAP DB to be able to store the permission + Create a group for each yunohost user + Migrate app permission from apps setting to LDAP + """ + + required = True + + def migrate(self): + # Update LDAP schema restart slapd + logger.info(m18n.n("migration_0009_update_LDAP_schema")) + service_regen_conf(names=['slapd'], force=True) + + # Do the authentication to LDAP after LDAP as been updated + AUTH_IDENTIFIER = ('ldap', 'as-root') + AUTH_PARAMETERS = {'uri': 'ldapi://%2Fvar%2Frun%2Fslapd%2Fldapi', + 'base_dn': 'dc=yunohost,dc=org', + 'user_rdn': 'gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth'} + auth = init_authenticator(AUTH_IDENTIFIER, AUTH_PARAMETERS) + + #Update LDAP database + migrate_LDAP_db(auth) + + # Migrate permission + migrate_app_permission(auth) + + permission_sync_to_user(auth) + logger.info(m18n.n("migration_0009_done")) + + @property + def disclaimer(self): + return m18n.n("migration_0009_disclaimer") diff --git a/src/yunohost/permission.py b/src/yunohost/permission.py index 6b77118c5..0cf77745a 100644 --- a/src/yunohost/permission.py +++ b/src/yunohost/permission.py @@ -114,7 +114,7 @@ def user_permission_list(auth, app=None, permission=None, username=None, group=N return {'permissions': permissions} -def user_permission_update(operation_logger, auth, app=[], permission=None, add_username=None, add_group=None, del_username=None, del_group=None): +def user_permission_update(operation_logger, auth, app=[], permission=None, add_username=None, add_group=None, del_username=None, del_group=None, sync_perm=True): """ Allow or Disallow a user or group to a permission for a specific application @@ -231,7 +231,8 @@ def user_permission_update(operation_logger, auth, app=[], permission=None, add_ else: raise MoulinetteError(169, m18n.n('permission_update_failed')) - permission_sync_to_user(auth) + if sync_perm: + permission_sync_to_user(auth) for a in app: allowed_users = set()