From f839ec51537fc0fd4292b3bff75d1419e47787d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josu=C3=A9=20Tille?= Date: Sun, 26 May 2019 00:54:57 +0200 Subject: [PATCH] Improve restoration mecanisme for LDAP integrity --- data/hooks/backup/05-conf_ldap | 6 ++-- locales/en.json | 2 ++ src/yunohost/backup.py | 65 ++++++++++++++++++++++++++++------ 3 files changed, 58 insertions(+), 15 deletions(-) diff --git a/data/hooks/backup/05-conf_ldap b/data/hooks/backup/05-conf_ldap index 5b91bb5b2..9ae22095e 100755 --- a/data/hooks/backup/05-conf_ldap +++ b/data/hooks/backup/05-conf_ldap @@ -13,7 +13,5 @@ backup_dir="${1}/conf/ldap" ynh_backup "/etc/ldap/slapd.conf" "${backup_dir}/slapd.conf" sudo slapcat -b cn=config -l "${backup_dir}/cn=config.master.ldif" -# Backup the database (all but not the permission except the permission for mail, metronome and sftp -sudo slapcat -b dc=yunohost,dc=org \ - -H 'ldap:///dc=yunohost,dc=org???(|(!(objectClass=permissionYnh))(cn=main.mail)(cn=main.metronome)(cn=main.sftp))' \ - -l "${backup_dir}/dc=yunohost-dc=org.ldif" +# Backup the database +sudo slapcat -b dc=yunohost,dc=org -l "${backup_dir}/dc=yunohost-dc=org.ldif" diff --git a/locales/en.json b/locales/en.json index 31513a546..fc3f8fe69 100644 --- a/locales/en.json +++ b/locales/en.json @@ -48,6 +48,8 @@ "app_upgrade_failed": "Unable to upgrade {app:s}", "app_upgrade_some_app_failed": "Unable to upgrade some applications", "app_upgraded": "{app:s} has been upgraded", + "apps_permission_not_found": "No permission found for the installed apps", + "apps_permission_restoration_failed": "Permission '{permission:s}' for app {app:s} restoration has failed", "appslist_corrupted_json": "Could not load the application lists. It looks like {filename:s} is corrupted.", "appslist_could_not_migrate": "Could not migrate app list {appslist:s}! Unable to parse the url… The old cron job has been kept in {bkp_file:s}.", "appslist_fetched": "The application list {appslist:s} has been fetched", diff --git a/src/yunohost/backup.py b/src/yunohost/backup.py index 879798099..3087a15e9 100644 --- a/src/yunohost/backup.py +++ b/src/yunohost/backup.py @@ -919,7 +919,7 @@ class RestoreManager(): successfull_apps = self.targets.list("apps", include=["Success", "Warning"]) - permission_sync_to_user(auth, force=True) + permission_sync_to_user(auth, force=False) if os.path.ismount(self.work_dir): ret = subprocess.call(["umount", self.work_dir]) @@ -1183,6 +1183,16 @@ class RestoreManager(): if system_targets == []: return + # Backup old permission for apps + # We need to do that because in case of an app is installed we can't remove the permission for this app + old_apps_permission = [] + try: + old_apps_permission = auth.search('ou=permission,dc=yunohost,dc=org', + '(&(objectClass=permissionYnh)(!(cn=main.mail))(!(cn=main.metronome))(!(cn=main.sftp)))', + ['cn', 'objectClass', 'groupPermission', 'URL', 'gidNumber']) + except: + logger.info(m18n.n('apps_permission_not_found')) + # Start register change on system operation_logger = OperationLogger('backup_restore_system') operation_logger.start() @@ -1228,10 +1238,27 @@ class RestoreManager(): from yunohost.tools import _get_migration_by_name setup_group_permission = _get_migration_by_name("setup_group_permission") # Update LDAP schema restart slapd - logger.info(m18n.n("migration_0009_update_LDAP_schema")) - service_regen_conf(names=['slapd'], force=True) + logger.info(m18n.n("migration_0011_update_LDAP_schema")) + regen_conf(names=['slapd'], force=True) setup_group_permission.migrate_LDAP_db(auth) + # Remove all permission for all app which sill in the LDAP + for per in auth.search('ou=permission,dc=yunohost,dc=org', + '(&(objectClass=permissionYnh)(!(cn=main.mail))(!(cn=main.metronome))(!(cn=main.sftp)))', + ['cn']): + if not auth.remove('cn=%s,ou=permission' % per['cn'][0]): + raise YunohostError('permission_deletion_failed', permission=permission, app=app) + + # Restore permission for the app which is installed + for per in old_apps_permission: + try: + permission_name, app_name = per['cn'][0].split('.') + except: + logger.warning(m18n.n('permission_name_not_valid', permission=per['cn'][0])) + if _is_installed(app_name): + if not auth.add('cn=%s,ou=permission' % per['cn'][0], per): + raise YunohostError('apps_permission_restoration_failed', permission=permission_name, app=app_name) + def _restore_apps(self, auth): """Restore all apps targeted""" @@ -1239,6 +1266,7 @@ class RestoreManager(): apps_targets = self.targets.list("apps", exclude=["Skipped"]) for app in apps_targets: + print(app) self._restore_app(auth, app) def _restore_app(self, auth, app_instance_name): @@ -1268,6 +1296,9 @@ class RestoreManager(): name already exists restore_app_failed -- Raised if the restore bash script failed """ + from moulinette.utils.filesystem import read_ldif + from yunohost.user import user_group_list + def copytree(src, dst, symlinks=False, ignore=None): for item in os.listdir(src): s = os.path.join(src, item) @@ -1321,14 +1352,6 @@ class RestoreManager(): filesystem.chmod(app_settings_new_path, 0o400, 0o400, True) filesystem.chown(app_scripts_new_path, 'admin', None, True) - # Restore permissions - if os.path.isfile(app_settings_in_archive + '/permission.ldif'): - os.system("slapadd -l '%s/permission.ldif'" % app_settings_in_archive) - else: - from yunohost.tools import _get_migration_by_name - setup_group_permission = _get_migration_by_name("setup_group_permission") - setup_group_permission.migrate_app_permission(auth, app=app_instance_name) - # Copy the app scripts to a writable temporary folder # FIXME : use 'install -Dm555' or something similar to what's done # in the backup method ? @@ -1338,6 +1361,26 @@ class RestoreManager(): filesystem.chown(tmp_folder_for_app_restore, 'admin', None, True) restore_script = os.path.join(tmp_folder_for_app_restore, 'restore') + # Restore permissions + if os.path.isfile(app_settings_in_archive + '/permission.ldif'): + filtred_entries = ['entryUUID', 'creatorsName', 'createTimestamp', 'entryCSN', 'structuralObjectClass', + 'modifiersName', 'modifyTimestamp', 'inheritPermission', 'memberUid'] + entries = read_ldif('%s/permission.ldif' % app_settings_in_archive, filtred_entries) + group_list = user_group_list(auth, ['cn'])['groups'] + for dn, entry in entries: + # Remove the group which has been removed + for group in entry['groupPermission']: + group_name = group.split(',')[0].split('=')[1] + if group_name not in group_list: + entry['groupPermission'].remove(group) + print(entry) + if not auth.add('cn=%s,ou=permission' % entry['cn'][0], entry): + raise YunohostError('apps_permission_restoration_failed', permission=permission_name, app=app_name) + else: + from yunohost.tools import _get_migration_by_name + setup_group_permission = _get_migration_by_name("setup_group_permission") + setup_group_permission.migrate_app_permission(auth, app=app_instance_name) + # Prepare env. var. to pass to script env_dict = self._get_env_var(app_instance_name)