Esempio n. 1
0
def _tools_migrations_run_before_app_restore(backup_version, app_id):

    all_migrations = _get_migrations_list()

    current_version = version.parse(
        ynh_packages_version()["yunohost"]["version"])
    backup_version = version.parse(backup_version)

    if backup_version == current_version:
        return

    for migration in all_migrations:
        if (hasattr(migration, "introduced_in_version") and
                version.parse(migration.introduced_in_version) > backup_version
                and hasattr(migration, "run_before_app_restore")):
            try:
                logger.info(
                    m18n.n("migrations_running_forward", id=migration.id))
                migration.run_before_app_restore(app_id)
            except Exception as e:
                msg = m18n.n("migrations_migration_has_failed",
                             exception=e,
                             id=migration.id)
                logger.error(msg, exc_info=1)
                raise
    def disclaimer(self):

        # Avoid having a super long disclaimer + uncessary check if we ain't
        # on stretch / yunohost 3.x anymore
        # NB : we do both check to cover situations where the upgrade crashed
        # in the middle and debian version could be >= 10.x but yunohost package
        # would still be in 3.x...
        if not self.debian_major_version() == 9 \
           and not self.yunohost_major_version() == 3:
            return None

        # Get list of problematic apps ? I.e. not official or community+working
        problematic_apps = unstable_apps()
        problematic_apps = "".join(
            ["\n    - " + app for app in problematic_apps])

        # Manually modified files ? (c.f. yunohost service regen-conf)
        modified_files = manually_modified_files()
        modified_files = "".join(["\n    - " + f for f in modified_files])

        message = m18n.n("migration_0015_general_warning")

        message = "N.B.: This migration has been tested by the community over the last few months but has only been declared stable recently. If your server hosts critical services and if you are not too confident with debugging possible issues, we recommend you to wait a little bit more while we gather more feedback and polish things up. If on the other hand you are relatively confident with debugging small issues that may arise, you are encouraged to run this migration ;)! You can read about remaining known issues and feedback from the community here: https://forum.yunohost.org/t/12195\n\n" + message

        if problematic_apps:
            message += "\n\n" + m18n.n(
                "migration_0015_problematic_apps_warning",
                problematic_apps=problematic_apps)

        if modified_files:
            message += "\n\n" + m18n.n("migration_0015_modified_files",
                                       manually_modified_files=modified_files)

        return message
Esempio n. 3
0
def user_permission_reset(operation_logger, permission, sync_perm=True):
    """
    Reset a given permission to just 'all_users'

    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"

    # Fetch existing permission

    existing_permission = user_permission_info(permission)

    if existing_permission["allowed"] == ["all_users"]:
        logger.warning(m18n.n("permission_already_up_to_date"))
        return

    # Update permission with default (all_users)

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

    new_permission = _update_ldap_group_permission(permission=permission,
                                                   allowed="all_users",
                                                   sync_perm=sync_perm)

    logger.debug(m18n.n("permission_updated", permission=permission))

    return new_permission
    def add_new_ldap_attributes(self):

        from yunohost.utils.ldap import _get_ldap_interface
        from yunohost.regenconf import regen_conf, BACKUP_CONF_DIR

        # Check if the migration can be processed
        ldap_regen_conf_status = regen_conf(names=["slapd"], dry_run=True)
        # By this we check if the have been customized
        if ldap_regen_conf_status and ldap_regen_conf_status["slapd"][
                "pending"]:
            logger.warning(
                m18n.n(
                    "migration_0019_slapd_config_will_be_overwritten",
                    conf_backup_folder=BACKUP_CONF_DIR,
                ))

        # Update LDAP schema restart slapd
        logger.info(m18n.n("migration_0011_update_LDAP_schema"))
        regen_conf(names=["slapd"], force=True)

        logger.info(m18n.n("migration_0019_add_new_attributes_in_ldap"))
        ldap = _get_ldap_interface()
        permission_list = user_permission_list(full=True)["permissions"]

        for permission in permission_list:
            system_perms = {
                "mail": "E-mail",
                "xmpp": "XMPP",
                "ssh": "SSH",
                "sftp": "STFP",
            }
            if permission.split(".")[0] in system_perms:
                update = {
                    "authHeader": ["FALSE"],
                    "label": [system_perms[permission.split(".")[0]]],
                    "showTile": ["FALSE"],
                    "isProtected": ["TRUE"],
                }
            else:
                app, subperm_name = permission.split(".")
                if permission.endswith(".main"):
                    update = {
                        "authHeader": ["TRUE"],
                        "label": [
                            app
                        ],  # Note that this is later re-changed during the call to migrate_legacy_permission_settings() if a 'label' setting exists
                        "showTile": ["TRUE"],
                        "isProtected": ["FALSE"],
                    }
                else:
                    update = {
                        "authHeader": ["TRUE"],
                        "label": [subperm_name.title()],
                        "showTile": ["FALSE"],
                        "isProtected": ["TRUE"],
                    }

            ldap.update("cn=%s,ou=permission" % permission, update)
Esempio n. 5
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 YunohostValidationError("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"))
Esempio n. 6
0
    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)
Esempio n. 7
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 YunohostValidationError(
                "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"))
    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)
Esempio n. 9
0
def _run_service_command(action, service):
    """
    Run services management command (start, stop, enable, disable, restart, reload)

    Keyword argument:
        action -- Action to perform
        service -- Service name

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

    possible_actions = ['start', 'stop', 'restart', 'reload', 'reload-or-restart', 'enable', 'disable']
    if action not in possible_actions:
        raise ValueError("Unknown action '%s', available actions are: %s" % (action, ", ".join(possible_actions)))

    cmd = 'systemctl %s %s' % (action, service)

    need_lock = services[service].get('need_lock', False) \
        and action in ['start', 'stop', 'restart', 'reload', 'reload-or-restart']

    if action in ["enable", "disable"]:
        cmd += " --quiet"

    try:
        # Launch the command
        logger.debug("Running '%s'" % cmd)
        p = subprocess.Popen(cmd.split(), stderr=subprocess.STDOUT)
        # If this command needs a lock (because the service uses yunohost
        # commands inside), find the PID and add a lock for it
        if need_lock:
            PID = _give_lock(action, service, p)
        # Wait for the command to complete
        p.communicate()

        if p.returncode != 0:
            logger.warning(m18n.n('service_cmd_exec_failed', command=cmd))
            return False

    except Exception as e:
        logger.warning(m18n.n("unexpected_error", error=str(e)))
        return False

    finally:
        # Remove the lock if one was given
        if need_lock and PID != 0:
            _remove_lock(PID)

    return True
Esempio n. 10
0
def tools_reboot(operation_logger, force=False):
    reboot = force
    if not reboot:
        try:
            # Ask confirmation for restoring
            i = msignals.prompt(m18n.n('server_reboot_confirm', answers='y/N'))
        except NotImplemented:
            pass
        else:
            if i.lower() == 'y' or i.lower() == 'yes':
                reboot = True
    if reboot:
        operation_logger.start()
        logger.warn(m18n.n('server_reboot'))
        subprocess.check_call(['systemctl', 'reboot'])
Esempio n. 11
0
def tools_reboot(operation_logger, force=False):
    reboot = force
    if not reboot:
        try:
            # Ask confirmation for restoring
            i = msignals.prompt(m18n.n("server_reboot_confirm", answers="y/N"))
        except NotImplemented:
            pass
        else:
            if i.lower() == "y" or i.lower() == "yes":
                reboot = True
    if reboot:
        operation_logger.start()
        logger.warn(m18n.n("server_reboot"))
        subprocess.check_call(["systemctl", "reboot"])
Esempio n. 12
0
def firewall_allow(
    protocol, port, ipv4_only=False, ipv6_only=False, no_upnp=False, no_reload=False
):
    """
    Allow connections on a port

    Keyword arguments:
        protocol -- Protocol type to allow (TCP/UDP/Both)
        port -- Port or range of ports to open
        ipv4_only -- Only add a rule for IPv4 connections
        ipv6_only -- Only add a rule for IPv6 connections
        no_upnp -- Do not add forwarding of this port with UPnP
        no_reload -- Do not reload firewall rules

    """
    firewall = firewall_list(raw=True)

    # Validate port
    if not isinstance(port, int) and ":" not in port:
        port = int(port)

    # Validate protocols
    protocols = ["TCP", "UDP"]
    if protocol != "Both" and protocol in protocols:
        protocols = [
            protocol,
        ]

    # Validate IP versions
    ipvs = ["ipv4", "ipv6"]
    if ipv4_only and not ipv6_only:
        ipvs = [
            "ipv4",
        ]
    elif ipv6_only and not ipv4_only:
        ipvs = [
            "ipv6",
        ]

    for p in protocols:
        # Iterate over IP versions to add port
        for i in ipvs:
            if port not in firewall[i][p]:
                firewall[i][p].append(port)
            else:
                ipv = "IPv%s" % i[3]
                logger.warning(m18n.n("port_already_opened", port=port, ip_version=ipv))
        # Add port forwarding with UPnP
        if not no_upnp and port not in firewall["uPnP"][p]:
            firewall["uPnP"][p].append(port)
            if (
                p + "_TO_CLOSE" in firewall["uPnP"]
                and port in firewall["uPnP"][p + "_TO_CLOSE"]
            ):
                firewall["uPnP"][p + "_TO_CLOSE"].remove(port)

    # Update and reload firewall
    _update_firewall_file(firewall)
    if not no_reload:
        return firewall_reload()
Esempio n. 13
0
    def __call__(self, arguments, arg_name, arg_value):
        pattern, message = (arguments[0], arguments[1])

        # Use temporarly utf-8 encoded value
        try:
            v = str(arg_value, "utf-8")
        except Exception:
            v = arg_value

        if v and not re.match(pattern, v or "", re.UNICODE):
            logger.warning(
                "argument value '%s' for '%s' doesn't match pattern '%s'",
                v,
                arg_name,
                pattern,
            )

            # Attempt to retrieve message translation
            msg = m18n.n(message)
            if msg == message:
                msg = m18n.g(message)

            raise MoulinetteValidationError(
                "invalid_argument", argument=arg_name, error=msg
            )
        return arg_value
Esempio n. 14
0
def settings_reset_all():
    """
    Reset all settings to their default value

    Keyword argument:
        yes -- Yes I'm sure I want to do that

    """
    settings = _get_settings()

    # For now on, we backup the previous settings in case of but we don't have
    # any mecanism to take advantage of those backups. It could be a nice
    # addition but we'll see if this is a common need.
    # Another solution would be to use etckeeper and integrate those
    # modification inside of it and take advantage of its git history
    old_settings_backup_path = (
        SETTINGS_PATH_OTHER_LOCATION % datetime.utcnow().strftime("%F_%X")
    )
    _save_settings(settings, location=old_settings_backup_path)

    for value in settings.values():
        value["value"] = value["default"]

    _save_settings(settings)

    return {
        "old_settings_backup_path": old_settings_backup_path,
        "message": m18n.n(
            "global_settings_reset_success", path=old_settings_backup_path
        ),
    }
Esempio n. 15
0
def _set_hostname(hostname, pretty_hostname=None):
    """
    Change the machine hostname using hostnamectl
    """

    if not pretty_hostname:
        pretty_hostname = "(YunoHost/%s)" % hostname

    # First clear nsswitch cache for hosts to make sure hostname is resolved...
    subprocess.call(["nscd", "-i", "hosts"])

    # Then call hostnamectl
    commands = [
        "hostnamectl --static    set-hostname".split() + [hostname],
        "hostnamectl --transient set-hostname".split() + [hostname],
        "hostnamectl --pretty    set-hostname".split() + [pretty_hostname],
    ]

    for command in commands:
        p = subprocess.Popen(command,
                             stdout=subprocess.PIPE,
                             stderr=subprocess.STDOUT)

        out, _ = p.communicate()

        if p.returncode != 0:
            logger.warning(command)
            logger.warning(out)
            logger.error(m18n.n("domain_hostname_failed"))
        else:
            logger.debug(out)
Esempio n. 16
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")
Esempio n. 17
0
def _name_self_CA():
    ca_conf = os.path.join(SSL_DIR, "openssl.ca.cnf")

    if not os.path.exists(ca_conf):
        logger.warning(m18n.n("certmanager_self_ca_conf_file_not_found", file=ca_conf))
        return ""

    with open(ca_conf) as f:
        lines = f.readlines()

    for line in lines:
        if line.startswith("commonName_default"):
            return line.split()[2]

    logger.warning(m18n.n("certmanager_unable_to_parse_self_CA_name", file=ca_conf))
    return ""
Esempio n. 18
0
        def func(self):

            # Backup LDAP before the migration
            logger.info(m18n.n("migration_ldap_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(
                    f"cp -r --preserve /etc/ldap {backup_folder}/ldap_config")
                os.system(
                    f"cp -r --preserve /var/lib/ldap {backup_folder}/ldap_db")
                os.system(
                    f"cp -r --preserve /etc/yunohost/apps {backup_folder}/apps_settings"
                )
            except Exception as e:
                raise YunohostError(
                    "migration_ldap_can_not_backup_before_migration",
                    error=str(e))
            finally:
                os.system("systemctl start slapd")

            try:
                run(self, backup_folder)
            except Exception:
                logger.warning(
                    m18n.n(
                        "migration_ldap_migration_failed_trying_to_rollback"))
                os.system("systemctl stop slapd")
                # To be sure that we don't keep some part of the old config
                os.system("rm -r /etc/ldap/slapd.d")
                os.system(
                    f"cp -r --preserve {backup_folder}/ldap_config/. /etc/ldap/"
                )
                os.system(
                    f"cp -r --preserve {backup_folder}/ldap_db/. /var/lib/ldap/"
                )
                os.system(
                    f"cp -r --preserve {backup_folder}/apps_settings/. /etc/yunohost/apps/"
                )
                os.system("systemctl start slapd")
                os.system(f"rm -r {backup_folder}")
                logger.info(m18n.n("migration_ldap_rollback_success"))
                raise
            else:
                os.system(f"rm -r {backup_folder}")
Esempio n. 19
0
def tools_shutdown(operation_logger, force=False):
    shutdown = force
    if not shutdown:
        try:
            # Ask confirmation for server shutdown
            i = msignals.prompt(
                m18n.n("server_shutdown_confirm", answers="y/N"))
        except NotImplemented:
            pass
        else:
            if i.lower() == "y" or i.lower() == "yes":
                shutdown = True

    if shutdown:
        operation_logger.start()
        logger.warn(m18n.n("server_shutdown"))
        subprocess.check_call(["systemctl", "poweroff"])
Esempio n. 20
0
def service_stop(names):
    """
    Stop one or more services

    Keyword argument:
        name -- Services name to stop

    """
    if isinstance(names, str):
        names = [names]
    for name in names:
        if _run_service_command('stop', name):
            logger.success(m18n.n('service_stopped', service=name))
        else:
            if service_status(name)['status'] != 'inactive':
                raise YunohostError('service_stop_failed', service=name, logs=_get_journalctl_logs(name))
            logger.debug(m18n.n('service_already_stopped', service=name))
Esempio n. 21
0
def tools_shutdown(operation_logger, force=False):
    shutdown = force
    if not shutdown:
        try:
            # Ask confirmation for server shutdown
            i = msignals.prompt(
                m18n.n('server_shutdown_confirm', answers='y/N'))
        except NotImplemented:
            pass
        else:
            if i.lower() == 'y' or i.lower() == 'yes':
                shutdown = True

    if shutdown:
        operation_logger.start()
        logger.warn(m18n.n('server_shutdown'))
        subprocess.check_call(['systemctl', 'poweroff'])
Esempio n. 22
0
    def close(self, error=None):
        """
        Close properly the unit operation
        """

        # When the error happen's in the is_unit_operation try/except,
        # we want to inject the log ref in the exception, such that it may be
        # transmitted to the webadmin which can then redirect to the appropriate
        # log page
        if isinstance(error, Exception) and not isinstance(
                error, YunohostValidationError):
            error.log_ref = self.name

        if self.ended_at is not None or self.started_at is None:
            return
        if error is not None and not isinstance(error, str):
            error = str(error)

        self.ended_at = datetime.utcnow()
        self._error = error
        self._success = error is None

        if self.logger is not None:
            self.logger.removeHandler(self.file_handler)
            self.file_handler.close()

        is_api = msettings.get("interface") == "api"
        desc = _get_description_from_name(self.name)
        if error is None:
            if is_api:
                msg = m18n.n("log_link_to_log", name=self.name, desc=desc)
            else:
                msg = m18n.n("log_help_to_get_log", name=self.name, desc=desc)
            logger.debug(msg)
        else:
            if is_api:
                msg = ("<strong>" + m18n.n(
                    "log_link_to_failed_log", name=self.name, desc=desc) +
                       "</strong>")
            else:
                msg = m18n.n("log_help_to_get_failed_log",
                             name=self.name,
                             desc=desc)
            logger.info(msg)
        self.flush()
        return msg
Esempio n. 23
0
    def __call__(self, message, arg_name, arg_value):
        if arg_value:
            return arg_value

        try:
            # Ask for the password
            return Moulinette.prompt(m18n.n(message), True, True)
        except NotImplementedError:
            return arg_value
    def run(self, *args):

        from yunohost.utils.ldap import _get_ldap_interface

        ldap = _get_ldap_interface()

        existing_perms_raw = ldap.search(
            "ou=permission,dc=yunohost,dc=org", "(objectclass=permissionYnh)", ["cn"]
        )
        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"],
            )

        if "ssh.main" not in existing_perms:
            ldap.add(
                "cn=ssh.main,ou=permission",
                ldap_map["depends_children"]["cn=ssh.main,ou=permission"],
            )

            # 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"]})
                else:
                    user_permission_update(
                        "ssh.main", add=user["uid"][0], sync_perm=False
                    )

            permission_sync_to_user()

            # Somehow this is needed otherwise the PAM thing doesn't forget about the
            # old loginShell value ?
            subprocess.call(["nscd", "-i", "passwd"])

        if (
            "/etc/ssh/sshd_config" in manually_modified_files()
            and os.system(
                "grep -q '^ *AllowGroups\\|^ *AllowUsers' /etc/ssh/sshd_config"
            )
            != 0
        ):
            logger.error(m18n.n("diagnosis_sshd_config_insecure"))
Esempio n. 25
0
def _tools_migrations_run_before_app_restore(backup_version, app_id):

    all_migrations = _get_migrations_list()

    for migration in all_migrations:
        if hasattr(migration, "introduced_in_version") \
           and version.parse(migration.introduced_in_version) > version.parse(backup_version) \
           and hasattr(migration, "run_before_app_restore"):
            try:
                logger.info(
                    m18n.n("migrations_running_forward", id=migration.id))
                migration.run_before_app_restore(app_id)
            except Exception as e:
                msg = m18n.n("migrations_migration_has_failed",
                             exception=e,
                             id=migration.id)
                logger.error(msg, exc_info=1)
                raise
Esempio n. 26
0
def dyndns_installcron():
    """
    Install IP update cron


    """
    with open("/etc/cron.d/yunohost-dyndns", "w+") as f:
        f.write("*/2 * * * * root yunohost dyndns update >> /dev/null\n")

    logger.success(m18n.n("dyndns_cron_installed"))
Esempio n. 27
0
    def __init__(self, key, raw_msg=False, log_ref=None, *args, **kwargs):
        self.key = key  # Saving the key is useful for unit testing
        self.kwargs = kwargs  # Saving the key is useful for unit testing
        self.log_ref = log_ref
        if raw_msg:
            msg = key
        else:
            msg = m18n.n(key, *args, **kwargs)

        super(YunohostError, self).__init__(msg, raw_msg=True)
Esempio n. 28
0
 def __del__(self):
     """
     Try to close the unit operation, if it's missing.
     The missing of the message below could help to see an electrical
     shortage.
     """
     if self.ended_at is not None or self.started_at is None:
         return
     else:
         self.error(m18n.n("log_operation_unit_unclosed_properly"))
Esempio n. 29
0
def dyndns_installcron():
    """
    Install IP update cron


    """
    with open('/etc/cron.d/yunohost-dyndns', 'w+') as f:
        f.write('*/2 * * * * root yunohost dyndns update >> /dev/null\n')

    logger.success(m18n.n('dyndns_cron_installed'))
Esempio n. 30
0
def firewall_disallow(protocol, port, ipv4_only=False, ipv6_only=False,
                      upnp_only=False, no_reload=False):
    """
    Disallow connections on a port

    Keyword arguments:
        protocol -- Protocol type to disallow (TCP/UDP/Both)
        port -- Port or range of ports to close
        ipv4_only -- Only remove the rule for IPv4 connections
        ipv6_only -- Only remove the rule for IPv6 connections
        upnp_only -- Only remove forwarding of this port with UPnP
        no_reload -- Do not reload firewall rules

    """
    firewall = firewall_list(raw=True)

    # Validate port
    if not isinstance(port, int) and ':' not in port:
        port = int(port)

    # Validate protocols
    protocols = ['TCP', 'UDP']
    if protocol != 'Both' and protocol in protocols:
        protocols = [protocol, ]

    # Validate IP versions and UPnP
    ipvs = ['ipv4', 'ipv6']
    upnp = True
    if ipv4_only and ipv6_only:
        upnp = True  # automatically disallow UPnP
    elif ipv4_only:
        ipvs = ['ipv4', ]
        upnp = upnp_only
    elif ipv6_only:
        ipvs = ['ipv6', ]
        upnp = upnp_only
    elif upnp_only:
        ipvs = []

    for p in protocols:
        # Iterate over IP versions to remove port
        for i in ipvs:
            if port in firewall[i][p]:
                firewall[i][p].remove(port)
            else:
                ipv = "IPv%s" % i[3]
                logger.warning(m18n.n('port_already_closed', port=port, ip_version=ipv))
        # Remove port forwarding with UPnP
        if upnp and port in firewall['uPnP'][p]:
            firewall['uPnP'][p].remove(port)

    # Update and reload firewall
    _update_firewall_file(firewall)
    if not no_reload:
        return firewall_reload()