예제 #1
0
    def run(self):

        if not self.package_is_installed("postgresql-9.6"):
            logger.warning(
                m18n.n("migration_0017_postgresql_96_not_installed"))
            return

        if not self.package_is_installed("postgresql-11"):
            raise YunohostError("migration_0017_postgresql_11_not_installed")

        # Make sure there's a 9.6 cluster
        try:
            self.runcmd("pg_lsclusters | grep -q '^9.6 '")
        except Exception:
            logger.warning(
                "It looks like there's not active 9.6 cluster, so probably don't need to run this migration"
            )
            return

        if not space_used_by_directory(
                "/var/lib/postgresql/9.6") > free_space_in_directory(
                    "/var/lib/postgresql"):
            raise YunohostError("migration_0017_not_enough_space",
                                path="/var/lib/postgresql/")

        self.runcmd("systemctl stop postgresql")
        self.runcmd(
            "LC_ALL=C pg_dropcluster --stop 11 main || true"
        )  # We do not trigger an exception if the command fails because that probably means cluster 11 doesn't exists, which is fine because it's created during the pg_upgradecluster)
        self.runcmd("LC_ALL=C pg_upgradecluster -m upgrade 9.6 main")
        self.runcmd("LC_ALL=C pg_dropcluster --stop 9.6 main")
        self.runcmd("systemctl start postgresql")
예제 #2
0
def _check_domain_is_ready_for_ACME(domain):

    dnsrecords = Diagnoser.get_cached_report("dnsrecords",
                                             item={
                                                 "domain": domain,
                                                 "category": "basic"
                                             },
                                             warn_if_no_cache=False) or {}
    httpreachable = Diagnoser.get_cached_report(
        "web", item={"domain": domain}, warn_if_no_cache=False) or {}

    if not dnsrecords or not httpreachable:
        raise YunohostError('certmanager_domain_not_diagnosed_yet',
                            domain=domain)

    # Check if IP from DNS matches public IP
    if not dnsrecords.get("status") in [
            "SUCCESS", "WARNING"
    ]:  # Warning is for missing IPv6 record which ain't critical for ACME
        raise YunohostError('certmanager_domain_dns_ip_differs_from_public_ip',
                            domain=domain)

    # Check if domain seems to be accessible through HTTP?
    if not httpreachable.get("status") == "SUCCESS":
        raise YunohostError('certmanager_domain_http_not_working',
                            domain=domain)
예제 #3
0
    def resolve_domain(domain, rdtype):

        # FIXME make this work for IPv6-only hosts too..
        ok, result = dig(dyn_host, "A")
        dyn_host_ip = result[0] if ok == "ok" and len(result) else None
        if not dyn_host_ip:
            raise YunohostError("Failed to resolve %s" % dyn_host)

        ok, result = dig(domain, rdtype, resolvers=[dyn_host_ip])
        if ok == "ok":
            return result[0] if len(result) else None
        elif result[0] == "Timeout":
            logger.debug(
                "Timed-out while trying to resolve %s record for %s using %s" %
                (rdtype, domain, dyn_host))
        else:
            return None

        logger.debug("Falling back to external resolvers")
        ok, result = dig(domain, rdtype, resolvers="force_external")
        if ok == "ok":
            return result[0] if len(result) else None
        elif result[0] == "Timeout":
            logger.debug(
                "Timed-out while trying to resolve %s record for %s using external resolvers : %s"
                % (rdtype, domain, result))
        else:
            return None

        raise YunohostError("Failed to resolve %s for %s" % (rdtype, domain),
                            raw_msg=True)
예제 #4
0
def tools_adminpw(new_password, check_strength=True):
    """
    Change admin password

    Keyword argument:
        new_password

    """
    from yunohost.user import _hash_user_password
    from yunohost.utils.password import assert_password_is_strong_enough
    import spwd

    if check_strength:
        assert_password_is_strong_enough("admin", new_password)

    # UNIX seems to not like password longer than 127 chars ...
    # e.g. SSH login gets broken (or even 'su admin' when entering the password)
    if len(new_password) >= 127:
        raise YunohostError("admin_password_too_long")

    new_hash = _hash_user_password(new_password)

    from yunohost.utils.ldap import _get_ldap_interface

    ldap = _get_ldap_interface()

    try:
        ldap.update(
            "cn=admin",
            {
                "userPassword": [new_hash],
            },
        )
    except Exception:
        logger.error("unable to change admin password")
        raise YunohostError("admin_password_change_failed")
    else:
        # Write as root password
        try:
            hash_root = spwd.getspnam("root").sp_pwd

            with open("/etc/shadow", "r") as before_file:
                before = before_file.read()

            with open("/etc/shadow", "w") as after_file:
                after_file.write(
                    before.replace("root:" + hash_root,
                                   "root:" + new_hash.replace("{CRYPT}", "")))
        # An IOError may be thrown if for some reason we can't read/write /etc/passwd
        # A KeyError could also be thrown if 'root' is not in /etc/passwd in the first place (for example because no password defined ?)
        # (c.f. the line about getspnam)
        except (IOError, KeyError):
            logger.warning(m18n.n("root_password_desynchronized"))
            return

        logger.info(m18n.n("root_password_replaced_by_admin_password"))
        logger.success(m18n.n("admin_password_changed"))
예제 #5
0
def domain_main_domain(operation_logger, new_main_domain=None):
    """
    Check the current main domain, or change it

    Keyword argument:
        new_main_domain -- The new domain to be set as the main domain

    """
    from yunohost.tools import _set_hostname

    # If no new domain specified, we return the current main domain
    if not new_main_domain:
        return {'current_main_domain': _get_maindomain()}

    # Check domain exists
    if new_main_domain not in domain_list()['domains']:
        raise YunohostError('domain_name_unknown', domain=new_main_domain)

    operation_logger.related_to.append(('domain', new_main_domain))
    operation_logger.start()

    # Apply changes to ssl certs
    ssl_key = "/etc/ssl/private/yunohost_key.pem"
    ssl_crt = "/etc/ssl/private/yunohost_crt.pem"
    new_ssl_key = "/etc/yunohost/certs/%s/key.pem" % new_main_domain
    new_ssl_crt = "/etc/yunohost/certs/%s/crt.pem" % new_main_domain

    try:
        if os.path.exists(ssl_key) or os.path.lexists(ssl_key):
            os.remove(ssl_key)
        if os.path.exists(ssl_crt) or os.path.lexists(ssl_crt):
            os.remove(ssl_crt)

        os.symlink(new_ssl_key, ssl_key)
        os.symlink(new_ssl_crt, ssl_crt)

        _set_maindomain(new_main_domain)
    except Exception as e:
        logger.warning("%s" % e, exc_info=1)
        raise YunohostError('main_domain_change_failed')

    _set_hostname(new_main_domain)

    # Generate SSOwat configuration file
    app_ssowatconf()

    # Regen configurations
    try:
        with open('/etc/yunohost/installed', 'r'):
            regen_conf()
    except IOError:
        pass

    logger.success(m18n.n('main_domain_changed'))
예제 #6
0
def user_delete(operation_logger, username, purge=False):
    """
    Delete user

    Keyword argument:
        username -- Username to delete
        purge

    """
    from yunohost.hook import hook_callback
    from yunohost.utils.ldap import _get_ldap_interface

    if username not in user_list()["users"]:
        raise YunohostError('user_unknown', user=username)

    operation_logger.start()

    user_group_update("all_users",
                      remove=username,
                      force=True,
                      sync_perm=False)
    for group, infos in user_group_list()["groups"].items():
        if group == "all_users":
            continue
        # If the user is in this group (and it's not the primary group),
        # remove the member from the group
        if username != group and username in infos["members"]:
            user_group_update(group, remove=username, sync_perm=False)

    # Delete primary group if it exists (why wouldnt it exists ?  because some
    # epic bug happened somewhere else and only a partial removal was
    # performed...)
    if username in user_group_list()['groups'].keys():
        user_group_delete(username, force=True, sync_perm=True)

    ldap = _get_ldap_interface()
    try:
        ldap.remove('uid=%s,ou=users' % username)
    except Exception as e:
        raise YunohostError('user_deletion_failed', user=username, error=e)

    # Invalidate passwd to take user deletion into account
    subprocess.call(['nscd', '-i', 'passwd'])

    if purge:
        subprocess.call(['rm', '-rf', '/home/{0}'.format(username)])
        subprocess.call(['rm', '-rf', '/var/mail/{0}'.format(username)])

    hook_callback('post_user_delete', args=[username, purge])

    logger.success(m18n.n('user_deleted'))
예제 #7
0
def tools_migrations_list(pending=False, done=False):
    """
    List existing migrations
    """

    # Check for option conflict
    if pending and done:
        raise YunohostError("migrations_list_conflict_pending_done")

    # Get all migrations
    migrations = _get_migrations_list()

    # Reduce to dictionnaries
    migrations = [{
        "id": migration.id,
        "number": migration.number,
        "name": migration.name,
        "mode": migration.mode,
        "state": migration.state,
        "description": migration.description,
        "disclaimer": migration.disclaimer
    } for migration in migrations]

    # If asked, filter pending or done migrations
    if pending or done:
        if done:
            migrations = [m for m in migrations if m["state"] != "pending"]
        if pending:
            migrations = [m for m in migrations if m["state"] == "pending"]

    return {"migrations": migrations}
예제 #8
0
def user_group_info(groupname):
    """
    Get user informations

    Keyword argument:
        groupname -- Groupname to get informations

    """

    from yunohost.utils.ldap import _get_ldap_interface, _ldap_path_extract
    ldap = _get_ldap_interface()

    # Fetch info for this group
    result = ldap.search('ou=groups,dc=yunohost,dc=org', "cn=" + groupname,
                         ["cn", "member", "permission"])

    if not result:
        raise YunohostError('group_unknown', group=groupname)

    infos = result[0]

    # Format data

    return {
        'members':
        [_ldap_path_extract(p, "uid") for p in infos.get("member", [])],
        'permissions':
        [_ldap_path_extract(p, "cn") for p in infos.get("permission", [])]
    }
예제 #9
0
파일: ldap.py 프로젝트: trogeat/yunohost
def assert_slapd_is_running():

    # Assert slapd is running...
    if not os.system("pgrep slapd >/dev/null") == 0:
        raise YunohostError(
            "Service slapd is not running but is required to perform this action ... You can try to investigate what's happening with 'systemctl status slapd'"
        )
예제 #10
0
    def get_matching_migration(target):
        for m in all_migrations:
            if m.id == target or m.name == target or m.id.split(
                    "_")[0] == target:
                return m

        raise YunohostError("migrations_no_such_migration", id=target)
예제 #11
0
파일: service.py 프로젝트: d3v53c/yunohost
def service_log(name, number=50):
    """
    Log every log files of a service

    Keyword argument:
        name -- Service name to log
        number -- Number of lines to display

    """
    services = _get_services()
    number = int(number)

    if name not in services.keys():
        raise YunohostError("service_unknown", service=name)

    log_list = services[name].get("log", [])

    if not isinstance(log_list, list):
        log_list = [log_list]

    # Legacy stuff related to --log_type where we'll typically have the service
    # name in the log list but it's not an actual logfile. Nowadays journalctl
    # is automatically fetch as well as regular log files.
    if name in log_list:
        log_list.remove(name)

    result = {}

    # First we always add the logs from journalctl / systemd
    result["journalctl"] = _get_journalctl_logs(name, number).splitlines()

    for log_path in log_list:

        if not os.path.exists(log_path):
            continue

        # Make sure to resolve symlinks
        log_path = os.path.realpath(log_path)

        # log is a file, read it
        if os.path.isfile(log_path):
            result[log_path] = _tail(log_path, number)
            continue
        elif not os.path.isdir(log_path):
            result[log_path] = []
            continue

        for log_file in os.listdir(log_path):
            log_file_path = os.path.join(log_path, log_file)
            # not a file : skip
            if not os.path.isfile(log_file_path):
                continue

            if not log_file.endswith(".log"):
                continue

            result[log_file_path] = (_tail(log_file_path, number)
                                     if os.path.exists(log_file_path) else [])

    return result
예제 #12
0
def _dyndns_provides(provider, domain):
    """
    Checks if a provider provide/manage a given domain.

    Keyword arguments:
        provider -- The url of the provider, e.g. "dyndns.yunohost.org"
        domain -- The full domain that you'd like.. e.g. "foo.nohost.me"

    Returns:
        True if the provider provide/manages the domain. False otherwise.
    """

    logger.debug("Checking if %s is managed by %s ..." % (domain, provider))

    try:
        # Dyndomains will be a list of domains supported by the provider
        # e.g. [ "nohost.me", "noho.st" ]
        dyndomains = download_json("https://%s/domains" % provider, timeout=30)
    except MoulinetteError as e:
        logger.error(str(e))
        raise YunohostError("dyndns_could_not_check_provide",
                            domain=domain,
                            provider=provider)

    # Extract 'dyndomain' from 'domain', e.g. 'nohost.me' from 'foo.nohost.me'
    dyndomain = ".".join(domain.split(".")[1:])

    return dyndomain in dyndomains
예제 #13
0
def _guess_current_dyndns_domain(dyn_host):
    """
    This function tries to guess which domain should be updated by
    "dyndns_update()" because there's not proper management of the current
    dyndns domain :/ (and at the moment the code doesn't support having several
    dyndns domain, which is sort of a feature so that people don't abuse the
    dynette...)
    """

    # Retrieve the first registered domain
    paths = list(glob.iglob("/etc/yunohost/dyndns/K*.private"))
    for path in paths:
        match = RE_DYNDNS_PRIVATE_KEY_MD5.match(path)
        if not match:
            match = RE_DYNDNS_PRIVATE_KEY_SHA512.match(path)
            if not match:
                continue
        _domain = match.group("domain")

        # Verify if domain is registered (i.e., if it's available, skip
        # current domain beause that's not the one we want to update..)
        # If there's only 1 such key found, then avoid doing the request
        # for nothing (that's very probably the one we want to find ...)
        if len(paths) > 1 and _dyndns_available(dyn_host, _domain):
            continue
        else:
            return (_domain, path)

    raise YunohostError("dyndns_no_domain_registered")
예제 #14
0
파일: ldap.py 프로젝트: trogeat/yunohost
def _get_ldap_interface():

    global _ldap_interface

    if _ldap_interface is None:

        conf = {
            "vendor": "ldap",
            "name": "as-root",
            "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",
            },
            "extra": {},
        }

        try:
            _ldap_interface = ldap.Authenticator(**conf)
        except MoulinetteLdapIsDownError:
            raise YunohostError(
                "Service slapd is not running but is required to perform this action ... You can try to investigate what's happening with 'systemctl status slapd'"
            )

        assert_slapd_is_running()

    return _ldap_interface
예제 #15
0
def _save_settings(settings, location=SETTINGS_PATH):
    settings_without_description = {}
    for key, value in settings.items():
        settings_without_description[key] = value
        if "description" in value:
            del settings_without_description[key]["description"]

    try:
        result = json.dumps(settings_without_description, indent=4)
    except Exception as e:
        raise YunohostError("global_settings_cant_serialize_settings", reason=e)

    try:
        with open(location, "w") as settings_fd:
            settings_fd.write(result)
    except Exception as e:
        raise YunohostError("global_settings_cant_write_settings", reason=e)
예제 #16
0
def permission_sync_to_user():
    """
    Sychronise the inheritPermission attribut in the permission object from the
    user<->group link and the group<->permission link
    """
    import os
    from yunohost.app import app_ssowatconf
    from yunohost.user import user_group_list
    from yunohost.utils.ldap import _get_ldap_interface

    ldap = _get_ldap_interface()

    groups = user_group_list(full=True)["groups"]
    permissions = user_permission_list(full=True)["permissions"]

    for permission_name, permission_infos in permissions.items():

        # These are the users currently allowed because there's an 'inheritPermission' object corresponding to it
        currently_allowed_users = set(permission_infos["corresponding_users"])

        # These are the users that should be allowed because they are member of a group that is allowed for this permission ...
        should_be_allowed_users = set([
            user for group in permission_infos["allowed"]
            for user in groups[group]["members"]
        ])

        # Note that a LDAP operation with the same value that is in LDAP crash SLAP.
        # So we need to check before each ldap operation that we really change something in LDAP
        if currently_allowed_users == should_be_allowed_users:
            # We're all good, this permission is already correctly synchronized !
            continue

        new_inherited_perms = {
            "inheritPermission": [
                "uid=%s,ou=users,dc=yunohost,dc=org" % u
                for u in should_be_allowed_users
            ],
            "memberUid":
            should_be_allowed_users,
        }

        # Commit the change with the new inherited stuff
        try:
            ldap.update("cn=%s,ou=permission" % permission_name,
                        new_inherited_perms)
        except Exception as e:
            raise YunohostError("permission_update_failed",
                                permission=permission_name,
                                error=e)

    logger.debug("The permission database has been resynchronized")

    app_ssowatconf()

    # Reload unscd, otherwise the group ain't propagated to the LDAP database
    os.system("nscd --invalidate=passwd")
    os.system("nscd --invalidate=group")
예제 #17
0
파일: legacy.py 프로젝트: grenagit/yunohost
    def migrate_LDAP_db():

        logger.info(m18n.n("migration_0011_update_LDAP_database"))

        from yunohost.utils.ldap import _get_ldap_interface
        ldap = _get_ldap_interface()

        ldap_map = read_yaml(
            '/usr/share/yunohost/yunohost-config/moulinette/ldap_scheme.yml')

        try:
            SetupGroupPermissions.remove_if_exists("ou=permission")
            SetupGroupPermissions.remove_if_exists('ou=groups')

            attr_dict = ldap_map['parents']['ou=permission']
            ldap.add('ou=permission', attr_dict)

            attr_dict = ldap_map['parents']['ou=groups']
            ldap.add('ou=groups', attr_dict)

            attr_dict = ldap_map['children']['cn=all_users,ou=groups']
            ldap.add('cn=all_users,ou=groups', attr_dict)

            attr_dict = ldap_map['children']['cn=visitors,ou=groups']
            ldap.add('cn=visitors,ou=groups', attr_dict)

            for rdn, attr_dict in ldap_map['depends_children'].items():
                ldap.add(rdn, attr_dict)
        except Exception as e:
            raise YunohostError("migration_0011_LDAP_update_failed", error=e)

        logger.info(m18n.n("migration_0011_create_group"))

        # Create a group for each yunohost user
        user_list = ldap.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]
            ldap.update(
                'uid=%s,ou=users' % username, {
                    'objectClass': [
                        'mailAccount', 'inetOrgPerson', 'posixAccount',
                        'userPermissionYnh'
                    ]
                })
            user_group_create(username,
                              gid=user_info['uidNumber'][0],
                              primary_group=True,
                              sync_perm=False)
            user_group_update(groupname='all_users',
                              add=username,
                              force=True,
                              sync_perm=False)
예제 #18
0
def diagnosis_run(categories=[],
                  force=False,
                  except_if_never_ran_yet=False,
                  email=False):

    if (email or
            except_if_never_ran_yet) and not os.path.exists(DIAGNOSIS_CACHE):
        return

    # Get all the categories
    all_categories = _list_diagnosis_categories()
    all_categories_names = [category for category, _ in all_categories]

    # Check the requested category makes sense
    if categories == []:
        categories = all_categories_names
    else:
        unknown_categories = [
            c for c in categories if c not in all_categories_names
        ]
        if unknown_categories:
            raise YunohostError("diagnosis_unknown_categories",
                                categories=", ".join(unknown_categories))

    issues = []
    # Call the hook ...
    diagnosed_categories = []
    for category in categories:
        logger.debug("Running diagnosis for %s ..." % category)
        path = [p for n, p in all_categories if n == category][0]

        try:
            code, report = hook_exec(path, args={"force": force}, env=None)
        except Exception:
            import traceback

            logger.error(
                m18n.n(
                    "diagnosis_failed_for_category",
                    category=category,
                    error="\n" + traceback.format_exc(),
                ))
        else:
            diagnosed_categories.append(category)
            if report != {}:
                issues.extend([
                    item for item in report["items"]
                    if item["status"] in ["WARNING", "ERROR"]
                ])

    if email:
        _email_diagnosis_issues()
    if issues and msettings.get("interface") == "cli":
        logger.warning(m18n.n("diagnosis_display_tip"))
예제 #19
0
    def validate_regex(regex):
        if '%' in regex:
            logger.warning(
                "/!\\ Packagers! You are probably using a lua regex. You should use a PCRE regex instead."
            )
            return

        try:
            re.compile(regex)
        except Exception:
            raise YunohostError('invalid_regex', regex=regex)
예제 #20
0
def diagnosis_get(category, item):

    # Get all the categories
    all_categories = _list_diagnosis_categories()
    all_categories_names = [c for c, _ in all_categories]

    if category not in all_categories_names:
        raise YunohostError('diagnosis_unknown_categories',
                            categories=category)

    if isinstance(item, list):
        if any("=" not in criteria for criteria in item):
            raise YunohostError(
                "Criterias should be of the form key=value (e.g. domain=yolo.test)"
            )

        # Convert the provided criteria into a nice dict
        item = {c.split("=")[0]: c.split("=")[1] for c in item}

    return Diagnoser.get_cached_report(category, item=item)
예제 #21
0
def permission_delete(operation_logger,
                      permission,
                      force=False,
                      sync_perm=True):
    """
    Delete a permission

    Keyword argument:
        permission -- Name of the permission (e.g. mail or nextcloud or wordpress.editors)
    """

    # By default, manipulate main permission
    if "." not in permission:
        permission = permission + ".main"

    if permission.endswith(".main") and not force:
        raise YunohostError("permission_cannot_remove_main")

    from yunohost.utils.ldap import _get_ldap_interface

    ldap = _get_ldap_interface()

    # Make sure this permission exists

    _ = user_permission_info(permission)

    # Actually delete the permission

    operation_logger.related_to.append(("app", permission.split(".")[0]))
    operation_logger.start()

    try:
        ldap.remove("cn=%s,ou=permission" % permission)
    except Exception as e:
        raise YunohostError("permission_deletion_failed",
                            permission=permission,
                            error=e)

    if sync_perm:
        permission_sync_to_user()
    logger.debug(m18n.n("permission_deleted", permission=permission))
예제 #22
0
def user_group_delete(operation_logger,
                      groupname,
                      force=False,
                      sync_perm=True):
    """
    Delete user

    Keyword argument:
        groupname -- Groupname to delete

    """
    from yunohost.permission import permission_sync_to_user
    from yunohost.utils.ldap import _get_ldap_interface

    existing_groups = list(user_group_list()['groups'].keys())
    if groupname not in existing_groups:
        raise YunohostError('group_unknown', group=groupname)

    # Refuse to delete primary groups of a user (e.g. group 'sam' related to user 'sam')
    # without the force option...
    #
    # We also can't delete "all_users" because that's a special group...
    existing_users = list(user_list()['users'].keys())
    undeletable_groups = existing_users + ["all_users", "visitors"]
    if groupname in undeletable_groups and not force:
        raise YunohostError('group_cannot_be_deleted', group=groupname)

    operation_logger.start()
    ldap = _get_ldap_interface()
    try:
        ldap.remove('cn=%s,ou=groups' % groupname)
    except Exception as e:
        raise YunohostError('group_deletion_failed', group=groupname, error=e)

    if sync_perm:
        permission_sync_to_user()

    if groupname not in existing_users:
        logger.success(m18n.n('group_deleted', group=groupname))
    else:
        logger.debug(m18n.n('group_deleted', group=groupname))
예제 #23
0
def service_remove(name):
    """
    Remove a custom service

    Keyword argument:
        name -- Service name to remove

    """
    services = _get_services()

    if name not in services:
        raise YunohostError('service_unknown', service=name)

    del services[name]
    try:
        _save_services(services)
    except Exception:
        # we'll get a logger.warning with more details in _save_services
        raise YunohostError('service_remove_failed', service=name)

    logger.success(m18n.n('service_removed', service=name))
예제 #24
0
def dyndns_removecron():
    """
    Remove IP update cron


    """
    try:
        os.remove("/etc/cron.d/yunohost-dyndns")
    except Exception as e:
        raise YunohostError("dyndns_cron_remove_failed", error=e)

    logger.success(m18n.n("dyndns_cron_removed"))
    def run(self):

        # FIXME : what do we really want to do here ...
        # Imho we should just force-regen the conf in all case, and maybe
        # just display a warning if we detect that the conf was manually modified

        # Backup LDAP and the apps settings before to do the migration
        logger.info(m18n.n("migration_0019_backup_before_migration"))
        try:
            backup_folder = "/home/yunohost.backup/premigration/" + time.strftime(
                "%Y%m%d-%H%M%S", time.gmtime())
            os.makedirs(backup_folder, 0o750)
            os.system("systemctl stop slapd")
            os.system("cp -r --preserve /etc/ldap %s/ldap_config" %
                      backup_folder)
            os.system("cp -r --preserve /var/lib/ldap %s/ldap_db" %
                      backup_folder)
            os.system("cp -r --preserve /etc/yunohost/apps %s/apps_settings" %
                      backup_folder)
        except Exception as e:
            raise YunohostError(
                "migration_0019_can_not_backup_before_migration", error=e)
        finally:
            os.system("systemctl start slapd")

        try:
            # Update LDAP database
            self.add_new_ldap_attributes()

            # Migrate old settings
            migrate_legacy_permission_settings()

        except Exception:
            logger.warn(
                m18n.n("migration_0019_migration_failed_trying_to_rollback"))
            os.system("systemctl stop slapd")
            os.system(
                "rm -r /etc/ldap/slapd.d"
            )  # To be sure that we don't keep some part of the old config
            os.system("cp -r --preserve %s/ldap_config/. /etc/ldap/" %
                      backup_folder)
            os.system("cp -r --preserve %s/ldap_db/. /var/lib/ldap/" %
                      backup_folder)
            os.system(
                "cp -r --preserve %s/apps_settings/. /etc/yunohost/apps/" %
                backup_folder)
            os.system("systemctl start slapd")
            os.system("rm -r " + backup_folder)
            logger.info(m18n.n("migration_0019_rollback_success"))
            raise
        else:
            os.system("rm -r " + backup_folder)
예제 #26
0
def yunopaste(data):

    paste_server = "https://paste.yunohost.org"

    try:
        data = anonymize(data)
    except Exception as e:
        logger.warning(
            "For some reason, YunoHost was not able to anonymize the pasted data. Sorry about that. Be careful about sharing the link, as it may contain somewhat private infos like domain names or IP addresses. Error: %s"
            % e)

    data = data.encode()

    try:
        r = requests.post("%s/documents" % paste_server, data=data, timeout=30)
    except Exception as e:
        raise YunohostError(
            "Something wrong happened while trying to paste data on paste.yunohost.org : %s"
            % str(e),
            raw_msg=True,
        )

    if r.status_code != 200:
        raise YunohostError(
            "Something wrong happened while trying to paste data on paste.yunohost.org : %s, %s"
            % (r.status_code, r.text),
            raw_msg=True,
        )

    try:
        url = json.loads(r.text)["key"]
    except Exception:
        raise YunohostError(
            "Uhoh, couldn't parse the answer from paste.yunohost.org : %s" %
            r.text,
            raw_msg=True,
        )

    return "%s/raw/%s" % (paste_server, url)
예제 #27
0
def domain_main_domain(operation_logger, new_main_domain=None):
    """
    Check the current main domain, or change it

    Keyword argument:
        new_main_domain -- The new domain to be set as the main domain

    """
    from yunohost.tools import _set_hostname

    # If no new domain specified, we return the current main domain
    if not new_main_domain:
        return {"current_main_domain": _get_maindomain()}

    # Check domain exists
    if new_main_domain not in domain_list()["domains"]:
        raise YunohostError("domain_name_unknown", domain=new_main_domain)

    operation_logger.related_to.append(("domain", new_main_domain))
    operation_logger.start()

    # Apply changes to ssl certs
    try:
        write_to_file("/etc/yunohost/current_host", new_main_domain)

        _set_hostname(new_main_domain)
    except Exception as e:
        logger.warning("%s" % e, exc_info=1)
        raise YunohostError("main_domain_change_failed")

    # Generate SSOwat configuration file
    app_ssowatconf()

    # Regen configurations
    if os.path.exists("/etc/yunohost/installed"):
        regen_conf()

    logger.success(m18n.n("main_domain_changed"))
예제 #28
0
    def check_assertions(self):

        # Be on stretch (9.x) and yunohost 3.x
        # NB : we do both check to cover situations where the upgrade crashed
        # in the middle and debian version could be > 9.x but yunohost package
        # would still be in 3.x...
        if not self.debian_major_version() == 9 \
           and not self.yunohost_major_version() == 3:
            raise YunohostError("migration_0015_not_stretch")

        # Have > 1 Go free space on /var/ ?
        if free_space_in_directory("/var/") / (1024**3) < 1.0:
            raise YunohostError("migration_0015_not_enough_free_space")

        # Check system is up to date
        # (but we don't if 'stretch' is already in the sources.list ...
        # which means maybe a previous upgrade crashed and we're re-running it)
        if " buster " not in read_file("/etc/apt/sources.list"):
            tools_update(system=True)
            upgradable_system_packages = list(_list_upgradable_apt_packages())
            if upgradable_system_packages:
                raise YunohostError(
                    "migration_0015_system_not_fully_up_to_date")
예제 #29
0
    def validate_filter_criterias(filter_):

        # Get all the categories
        all_categories = _list_diagnosis_categories()
        all_categories_names = [category for category, _ in all_categories]

        # Sanity checks for the provided arguments
        if len(filter_) == 0:
            raise YunohostError(
                "You should provide at least one criteria being the diagnosis category to ignore"
            )
        category = filter_[0]
        if category not in all_categories_names:
            raise YunohostError("%s is not a diagnosis category" % category)
        if any("=" not in criteria for criteria in filter_[1:]):
            raise YunohostError(
                "Criterias should be of the form key=value (e.g. domain=yolo.test)"
            )

        # Convert the provided criteria into a nice dict
        criterias = {c.split("=")[0]: c.split("=")[1] for c in filter_[1:]}

        return category, criterias
예제 #30
0
파일: user.py 프로젝트: trogeat/yunohost
def user_list(fields=None):

    from yunohost.utils.ldap import _get_ldap_interface

    user_attrs = {
        "uid": "username",
        "cn": "fullname",
        "mail": "mail",
        "maildrop": "mail-forward",
        "loginShell": "shell",
        "homeDirectory": "home_path",
        "mailuserquota": "mailbox-quota",
    }

    attrs = ["uid"]
    users = {}

    if fields:
        keys = user_attrs.keys()
        for attr in fields:
            if attr in keys:
                attrs.append(attr)
            else:
                raise YunohostError("field_invalid", attr)
    else:
        attrs = ["uid", "cn", "mail", "mailuserquota", "loginShell"]

    ldap = _get_ldap_interface()
    result = ldap.search(
        "ou=users,dc=yunohost,dc=org",
        "(&(objectclass=person)(!(uid=root))(!(uid=nobody)))",
        attrs,
    )

    for user in result:
        entry = {}
        for attr, values in user.items():
            if values:
                if attr == "loginShell":
                    if values[0].strip() == "/bin/false":
                        entry["ssh_allowed"] = False
                    else:
                        entry["ssh_allowed"] = True

                entry[user_attrs[attr]] = values[0]

        uid = entry[user_attrs["uid"]]
        users[uid] = entry

    return {"users": users}