diff --git a/data/hooks/backup/05-conf_ldap b/data/hooks/backup/05-conf_ldap index e3e8e455d..b28ea39ca 100644 --- a/data/hooks/backup/05-conf_ldap +++ b/data/hooks/backup/05-conf_ldap @@ -11,7 +11,6 @@ backup_dir="${1}/conf/ldap" # Backup the configuration ynh_backup "/etc/ldap/ldap.conf" "${backup_dir}/ldap.conf" -ynh_backup "/etc/ldap/slapd.ldif" "${backup_dir}/slapd.ldif" slapcat -b cn=config -l "${backup_dir}/cn=config.master.ldif" # Backup the database diff --git a/data/hooks/conf_regen/06-slapd b/data/hooks/conf_regen/06-slapd index e7524184c..16aaab9c7 100755 --- a/data/hooks/conf_regen/06-slapd +++ b/data/hooks/conf_regen/06-slapd @@ -4,6 +4,9 @@ set -e tmp_backup_dir_file="/tmp/slapd-backup-dir.txt" +config="/usr/share/yunohost/templates/slapd/config.ldif" +db_init="/usr/share/yunohost/templates/slapd/db_init.ldif" + do_init_regen() { if [[ $EUID -ne 0 ]]; then echo "You must be root to run this script" 1>&2 @@ -12,16 +15,12 @@ do_init_regen() { do_pre_regen "" - systemctl daemon-reload - - systemctl restart slapd - # Drop current existing slapd data rm -rf /var/backups/*.ldapdb rm -rf /var/backups/slapd-* -debconf-set-selections << EOF + debconf-set-selections << EOF slapd slapd/password1 password yunohost slapd slapd/password2 password yunohost slapd slapd/domain string yunohost.org @@ -36,20 +35,38 @@ EOF DEBIAN_FRONTEND=noninteractive dpkg-reconfigure slapd -u - # Regen conf - - _regenerate_slapd_conf - - # Enforce permissions - chown root:openldap /etc/ldap/slapd.ldif + # Enforce permissions chown -R openldap:openldap /etc/ldap/schema/ usermod -aG ssl-cert openldap + # (Re-)init data according to default ldap entries + echo ' Initializing LDAP with Yunohost DB structure' + + rm -rf /etc/ldap/slapd.d + mkdir -p /etc/ldap/slapd.d + slapadd -F /etc/ldap/slapd.d -b cn=config -l "$config" 2>&1 \ + | grep -v "none elapsed\|Closing DB" || true + chown -R openldap: /etc/ldap/slapd.d + + rm -rf /var/lib/ldap + mkdir -p /var/lib/ldap + slapadd -F /etc/ldap/slapd.d -b dc=yunohost,dc=org -l "$db_init" 2>&1 \ + | grep -v "none elapsed\|Closing DB" || true + chown -R openldap: /var/lib/ldap + + nscd -i groups + nscd -i passwd + systemctl restart slapd - # (Re-)init data according to ldap_scheme.yaml - - yunohost tools shell -c "from yunohost.tools import tools_ldapinit; tools_ldapinit()" + # We don't use mkhomedir_helper because 'admin' may not be recognized + # when this script is ran in a chroot (e.g. ISO install) + # We also refer to admin as uid 1007 for the same reason + if [ ! -d /home/admin ] + then + cp -r /etc/skel /home/admin + chown -R 1007:1007 /home/admin + fi } _regenerate_slapd_conf() { @@ -59,7 +76,7 @@ _regenerate_slapd_conf() { # so we use a temporary directory slapd_new.d rm -Rf /etc/ldap/slapd_new.d mkdir /etc/ldap/slapd_new.d - slapadd -n0 -l /etc/ldap/slapd.ldif -F /etc/ldap/slapd_new.d/ 2>&1 \ + slapadd -b cn=config -l "$config" -F /etc/ldap/slapd_new.d/ 2>&1 \ | grep -v "none elapsed\|Closing DB" || true # Actual validation (-Q is for quiet, -u is for dry-run) slaptest -Q -u -F /etc/ldap/slapd_new.d @@ -101,7 +118,7 @@ do_pre_regen() { cd /usr/share/yunohost/templates/slapd # copy configuration files - cp -a ldap.conf slapd.ldif "$ldap_dir" + cp -a ldap.conf "$ldap_dir" cp -a sudo.ldif mailserver.ldif permission.ldif "$schema_dir" mkdir -p ${pending_dir}/etc/systemd/system/slapd.service.d/ @@ -117,7 +134,6 @@ do_post_regen() { echo "Enforce permissions on ldap/slapd directories and certs ..." # penldap user should be in the ssl-cert group to let it access the certificate for TLS usermod -aG ssl-cert openldap - chown root:openldap /etc/ldap/slapd.ldif chown -R openldap:openldap /etc/ldap/schema/ chown -R openldap:openldap /etc/ldap/slapd.d/ @@ -139,13 +155,15 @@ gidNumber: 4001 memberUid: admin objectClass: posixGroup objectClass: top" + chown -R openldap: /var/lib/ldap + systemctl restart slapd nscd -i groups fi [ -z "$regen_conf_files" ] && exit 0 # regenerate LDAP config directory from slapd.conf - echo "Regenerate LDAP config directory from slapd.ldif" + echo "Regenerate LDAP config directory from config.ldif" _regenerate_slapd_conf # If there's a backup, re-import its data @@ -194,9 +212,6 @@ case "$1" in init) do_init_regen ;; - apply_config) - do_post_regen /etc/ldap/slapd.ldif - ;; *) echo "hook called with unknown argument \`$1'" >&2 exit 1 diff --git a/data/hooks/restore/05-conf_ldap b/data/hooks/restore/05-conf_ldap index 8dc511695..c2debe018 100644 --- a/data/hooks/restore/05-conf_ldap +++ b/data/hooks/restore/05-conf_ldap @@ -33,7 +33,6 @@ die() { mv /etc/ldap/slapd.d "$TMPDIR" mkdir -p /etc/ldap/slapd.d cp -a "${backup_dir}/ldap.conf" /etc/ldap/ldap.conf -cp -a "${backup_dir}/slapd.ldif" /etc/ldap/slapd.ldif # Legacy thing but we need it to force the regen-conf in case of it exist [ ! -e "${backup_dir}/slapd.conf" ] \ || cp -a "${backup_dir}/slapd.conf" /etc/ldap/slapd.conf diff --git a/data/other/ldap_scheme.yml b/data/other/ldap_scheme.yml deleted file mode 100644 index b45b3ac3a..000000000 --- a/data/other/ldap_scheme.yml +++ /dev/null @@ -1,113 +0,0 @@ -parents: - ou=users: - ou: users - objectClass: - - organizationalUnit - - top - - ou=domains: - ou: domains - objectClass: - - organizationalUnit - - top - - ou=apps: - ou: apps - objectClass: - - organizationalUnit - - top - - ou=permission: - ou: permission - objectClass: - - organizationalUnit - - top - - ou=groups: - ou: groups - objectClass: - - organizationalUnit - - top - ou=sudo: - ou: sudo - objectClass: - - organizationalUnit - - top - -children: - cn=admin,ou=sudo: - cn: admin - sudoUser: admin - sudoHost: ALL - sudoCommand: ALL - sudoOption: "!authenticate" - objectClass: - - sudoRole - - top - cn=admins,ou=groups: - cn: admins - gidNumber: "4001" - memberUid: admin - objectClass: - - posixGroup - - top - cn=all_users,ou=groups: - cn: all_users - gidNumber: "4002" - objectClass: - - posixGroup - - groupOfNamesYnh - cn=visitors,ou=groups: - cn: visitors - gidNumber: "4003" - objectClass: - - posixGroup - - groupOfNamesYnh - -depends_children: - cn=mail.main,ou=permission: - cn: mail.main - gidNumber: "5001" - objectClass: - - posixGroup - - permissionYnh - groupPermission: - - "cn=all_users,ou=groups,dc=yunohost,dc=org" - authHeader: "FALSE" - label: "E-mail" - showTile: "FALSE" - isProtected: "TRUE" - cn=xmpp.main,ou=permission: - cn: xmpp.main - gidNumber: "5002" - objectClass: - - posixGroup - - permissionYnh - groupPermission: - - "cn=all_users,ou=groups,dc=yunohost,dc=org" - authHeader: "FALSE" - label: "XMPP" - showTile: "FALSE" - isProtected: "TRUE" - cn=ssh.main,ou=permission: - cn: ssh.main - gidNumber: "5003" - objectClass: - - posixGroup - - permissionYnh - groupPermission: [] - authHeader: "FALSE" - label: "SSH" - showTile: "FALSE" - isProtected: "TRUE" - cn=sftp.main,ou=permission: - cn: sftp.main - gidNumber: "5004" - objectClass: - - posixGroup - - permissionYnh - groupPermission: [] - authHeader: "FALSE" - label: "SFTP" - showTile: "FALSE" - isProtected: "TRUE" diff --git a/data/templates/slapd/slapd.ldif b/data/templates/slapd/config.ldif similarity index 100% rename from data/templates/slapd/slapd.ldif rename to data/templates/slapd/config.ldif diff --git a/data/templates/slapd/db_init.ldif b/data/templates/slapd/db_init.ldif new file mode 100644 index 000000000..be0181dfe --- /dev/null +++ b/data/templates/slapd/db_init.ldif @@ -0,0 +1,120 @@ +dn: dc=yunohost,dc=org +objectClass: top +objectClass: dcObject +objectClass: organization +o: yunohost.org +dc: yunohost + +dn: cn=admin,ou=sudo,dc=yunohost,dc=org +cn: admin +objectClass: sudoRole +objectClass: top +sudoCommand: ALL +sudoUser: admin +sudoOption: !authenticate +sudoHost: ALL + +dn: ou=users,dc=yunohost,dc=org +objectClass: organizationalUnit +objectClass: top +ou: users + +dn: ou=domains,dc=yunohost,dc=org +objectClass: organizationalUnit +objectClass: top +ou: domains + +dn: ou=apps,dc=yunohost,dc=org +objectClass: organizationalUnit +objectClass: top +ou: apps + +dn: ou=permission,dc=yunohost,dc=org +objectClass: organizationalUnit +objectClass: top +ou: permission + +dn: ou=groups,dc=yunohost,dc=org +objectClass: organizationalUnit +objectClass: top +ou: groups + +dn: ou=sudo,dc=yunohost,dc=org +objectClass: organizationalUnit +objectClass: top +ou: sudo + +dn: cn=admin,dc=yunohost,dc=org +objectClass: organizationalRole +objectClass: posixAccount +objectClass: simpleSecurityObject +cn: admin +uid: admin +uidNumber: 1007 +gidNumber: 1007 +homeDirectory: /home/admin +loginShell: /bin/bash +userPassword: yunohost + +dn: cn=admins,ou=groups,dc=yunohost,dc=org +objectClass: posixGroup +objectClass: top +memberUid: admin +gidNumber: 4001 +cn: admins + +dn: cn=all_users,ou=groups,dc=yunohost,dc=org +objectClass: posixGroup +objectClass: groupOfNamesYnh +gidNumber: 4002 +cn: all_users +permission: cn=mail.main,ou=permission,dc=yunohost,dc=org +permission: cn=xmpp.main,ou=permission,dc=yunohost,dc=org + +dn: cn=visitors,ou=groups,dc=yunohost,dc=org +objectClass: posixGroup +objectClass: groupOfNamesYnh +gidNumber: 4003 +cn: visitors + +dn: cn=mail.main,ou=permission,dc=yunohost,dc=org +groupPermission: cn=all_users,ou=groups,dc=yunohost,dc=org +cn: mail.main +objectClass: posixGroup +objectClass: permissionYnh +isProtected: TRUE +label: E-mail +gidNumber: 5001 +showTile: FALSE +authHeader: FALSE + +dn: cn=xmpp.main,ou=permission,dc=yunohost,dc=org +groupPermission: cn=all_users,ou=groups,dc=yunohost,dc=org +cn: xmpp.main +objectClass: posixGroup +objectClass: permissionYnh +isProtected: TRUE +label: XMPP +gidNumber: 5002 +showTile: FALSE +authHeader: FALSE + +dn: cn=ssh.main,ou=permission,dc=yunohost,dc=org +cn: ssh.main +objectClass: posixGroup +objectClass: permissionYnh +isProtected: TRUE +label: SSH +gidNumber: 5003 +showTile: FALSE +authHeader: FALSE + +dn: cn=sftp.main,ou=permission,dc=yunohost,dc=org +cn: sftp.main +objectClass: posixGroup +objectClass: permissionYnh +isProtected: TRUE +label: SFTP +gidNumber: 5004 +showTile: FALSE +authHeader: FALSE diff --git a/locales/en.json b/locales/en.json index 7d1c67ee5..cde7aab11 100644 --- a/locales/en.json +++ b/locales/en.json @@ -362,7 +362,6 @@ "hook_list_by_invalid": "This property can not be used to list hooks", "hook_name_unknown": "Unknown hook name '{name:s}'", "installation_complete": "Installation completed", - "installation_failed": "Something went wrong with the installation", "invalid_regex": "Invalid regex:'{regex:s}'", "ip6tables_unavailable": "You cannot play with ip6tables here. You are either in a container or your kernel does not support it", "iptables_unavailable": "You cannot play with iptables here. You are either in a container or your kernel does not support it", @@ -412,8 +411,6 @@ "log_tools_upgrade": "Upgrade system packages", "log_tools_shutdown": "Shutdown your server", "log_tools_reboot": "Reboot your server", - "ldap_init_failed_to_create_admin": "LDAP initialization could not create admin user", - "ldap_initialized": "LDAP initialized", "mail_alias_remove_failed": "Could not remove e-mail alias '{mail:s}'", "mail_domain_unknown": "Invalid e-mail address for domain '{domain:s}'. Please, use a domain administrated by this server.", "mail_forward_remove_failed": "Could not remove e-mail forwarding '{mail:s}'", diff --git a/src/yunohost/data_migrations/0020_ssh_sftp_permissions.py b/src/yunohost/data_migrations/0020_ssh_sftp_permissions.py index ba8a2b663..681d0cd9d 100644 --- a/src/yunohost/data_migrations/0020_ssh_sftp_permissions.py +++ b/src/yunohost/data_migrations/0020_ssh_sftp_permissions.py @@ -3,7 +3,6 @@ import os from moulinette import m18n 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, permission_sync_to_user @@ -37,20 +36,34 @@ class MyMigration(Migration): existing_perms = [perm["cn"][0] for perm in existing_perms_raw] # Add SSH and SFTP permissions - ldap_map = read_yaml( - "/usr/share/yunohost/yunohost-config/moulinette/ldap_scheme.yml" - ) - if "sftp.main" not in existing_perms: ldap.add( "cn=sftp.main,ou=permission", - ldap_map["depends_children"]["cn=sftp.main,ou=permission"], + { + "cn": "sftp.main", + "gidNumber": "5004", + "objectClass": ["posixGroup", "permissionYnh"], + "groupPermission": [], + "authHeader": "FALSE", + "label": "SFTP", + "showTile": "FALSE", + "isProtected": "TRUE", + } ) if "ssh.main" not in existing_perms: ldap.add( "cn=ssh.main,ou=permission", - ldap_map["depends_children"]["cn=ssh.main,ou=permission"], + { + "cn": "ssh.main", + "gidNumber": "5003", + "objectClass": ["posixGroup", "permissionYnh"], + "groupPermission": [], + "authHeader": "FALSE", + "label": "SSH", + "showTile": "FALSE", + "isProtected": "TRUE", + } ) # Add a bash terminal to each users diff --git a/src/yunohost/tools.py b/src/yunohost/tools.py index ada43edaa..1bce1b2cb 100644 --- a/src/yunohost/tools.py +++ b/src/yunohost/tools.py @@ -25,9 +25,7 @@ """ import re import os -import yaml import subprocess -import pwd import time from importlib import import_module from packaging import version @@ -67,79 +65,6 @@ def tools_versions(): return ynh_packages_version() -def tools_ldapinit(): - """ - YunoHost LDAP initialization - """ - - with open("/usr/share/yunohost/yunohost-config/moulinette/ldap_scheme.yml") as f: - ldap_map = yaml.load(f) - - from yunohost.utils.ldap import _get_ldap_interface - - ldap = _get_ldap_interface() - - for rdn, attr_dict in ldap_map["parents"].items(): - try: - ldap.add(rdn, attr_dict) - except Exception as e: - logger.warn( - "Error when trying to inject '%s' -> '%s' into ldap: %s" - % (rdn, attr_dict, e) - ) - - for rdn, attr_dict in ldap_map["children"].items(): - try: - ldap.add(rdn, attr_dict) - except Exception as e: - logger.warn( - "Error when trying to inject '%s' -> '%s' into ldap: %s" - % (rdn, attr_dict, e) - ) - - for rdn, attr_dict in ldap_map["depends_children"].items(): - try: - ldap.add(rdn, attr_dict) - except Exception as e: - logger.warn( - "Error when trying to inject '%s' -> '%s' into ldap: %s" - % (rdn, attr_dict, e) - ) - - admin_dict = { - "cn": ["admin"], - "uid": ["admin"], - "description": ["LDAP Administrator"], - "gidNumber": ["1007"], - "uidNumber": ["1007"], - "homeDirectory": ["/home/admin"], - "loginShell": ["/bin/bash"], - "objectClass": ["organizationalRole", "posixAccount", "simpleSecurityObject"], - "userPassword": ["yunohost"], - } - - ldap.update("cn=admin", admin_dict) - - # Force nscd to refresh cache to take admin creation into account - subprocess.call(["nscd", "-i", "passwd"]) - - # Check admin actually exists now - try: - pwd.getpwnam("admin") - except KeyError: - logger.error(m18n.n("ldap_init_failed_to_create_admin")) - raise YunohostError("installation_failed") - - try: - # Attempt to create user home folder - subprocess.check_call(["mkhomedir_helper", "admin"]) - except subprocess.CalledProcessError: - if not os.path.isdir("/home/{0}".format("admin")): - logger.warning(m18n.n("user_home_creation_failed"), exc_info=1) - - logger.success(m18n.n("ldap_initialized")) - - def tools_adminpw(new_password, check_strength=True): """ Change admin password @@ -170,11 +95,11 @@ def tools_adminpw(new_password, check_strength=True): ldap.update( "cn=admin", { - "userPassword": [new_hash], + "userPassword": [new_hash] }, ) - except Exception: - logger.error("unable to change admin password") + except Exception as e: + logger.error("unable to change admin password : %s" % e) raise YunohostError("admin_password_change_failed") else: # Write as root password @@ -352,7 +277,7 @@ def tools_postinstall( domain_add(domain, dyndns) domain_main_domain(domain) - # Change LDAP admin password + # Update LDAP admin and create home dir tools_adminpw(password, check_strength=not force_password) # Enable UPnP silently and reload firewall