Пример #1
0
def _clear_dummy_app_settings():
    # Clean dummy app settings
    for app in _installed_apps():
        if _get_app_settings(app).get('dummy_permission_app', False):
            app_setting_path = os.path.join(APPS_SETTING_PATH, app)
            if os.path.exists(app_setting_path):
                shutil.rmtree(app_setting_path)
Пример #2
0
def _permission_create_with_dummy_app(
    permission,
    allowed=None,
    url=None,
    additional_urls=None,
    auth_header=True,
    label=None,
    show_tile=False,
    protected=True,
    sync_perm=True,
    domain=None,
    path=None,
):
    app = permission.split(".")[0]
    if app not in _installed_apps():
        app_setting_path = os.path.join(APPS_SETTING_PATH, app)
        if not os.path.exists(app_setting_path):
            os.makedirs(app_setting_path)
        settings = {"id": app, "dummy_permission_app": True}
        if domain:
            settings["domain"] = domain
        if path:
            settings["path"] = path
        _set_app_settings(app, settings)

        with open(os.path.join(APPS_SETTING_PATH, app, "manifest.json"),
                  "w") as f:
            json.dump(
                {
                    "name": app,
                    "id": app,
                    "description": {
                        "en": "Dummy app to test permissions"
                    },
                },
                f,
            )
    permission_create(
        permission=permission,
        allowed=allowed,
        url=url,
        additional_urls=additional_urls,
        auth_header=auth_header,
        label=label,
        show_tile=show_tile,
        protected=protected,
        sync_perm=sync_perm,
    )
Пример #3
0
    def migrate_app_permission(app=None):
        logger.info(m18n.n("migration_0011_migrate_permission"))

        apps = _installed_apps()

        if app:
            if app not in apps:
                logger.error(
                    "Can't migrate permission for app %s because it ain't installed..."
                    % app
                )
                apps = []
            else:
                apps = [app]

        for app in apps:
            permission = app_setting(app, "allowed_users")
            path = app_setting(app, "path")
            domain = app_setting(app, "domain")

            url = "/" if domain and path else None
            if permission:
                known_users = list(user_list()["users"].keys())
                allowed = [
                    user for user in permission.split(",") if user in known_users
                ]
            else:
                allowed = ["all_users"]
            permission_create(
                app + ".main",
                url=url,
                allowed=allowed,
                show_tile=True,
                protected=False,
                sync_perm=False,
            )

            app_setting(app, "allowed_users", delete=True)

            # Migrate classic public app still using the legacy unprotected_uris
            if (
                app_setting(app, "unprotected_uris") == "/"
                or app_setting(app, "skipped_uris") == "/"
            ):
                user_permission_update(app + ".main", add="visitors", sync_perm=False)

        permission_sync_to_user()
Пример #4
0
def check_permission_for_apps():
    # We check that the for each installed apps we have at last the "main" permission
    # and we don't have any permission linked to no apps. The only exception who is not liked to an app
    # is mail, xmpp, and sftp

    app_perms = user_permission_list(
        ignore_system_perms=True)["permissions"].keys()

    # Keep only the prefix so that
    # ["foo.main", "foo.pwet", "bar.main"]
    # becomes
    # {"bar", "foo"}
    # and compare this to the list of installed apps ...

    app_perms_prefix = set(p.split(".")[0] for p in app_perms)

    assert set(_installed_apps()) == app_perms_prefix
Пример #5
0
def user_permission_list(short=False,
                         full=False,
                         ignore_system_perms=False,
                         absolute_urls=False):
    """
    List permissions and corresponding accesses
    """

    # Fetch relevant informations
    from yunohost.app import app_setting, _installed_apps
    from yunohost.utils.ldap import _get_ldap_interface, _ldap_path_extract

    ldap = _get_ldap_interface()
    permissions_infos = ldap.search(
        "ou=permission,dc=yunohost,dc=org",
        "(objectclass=permissionYnh)",
        [
            "cn",
            "groupPermission",
            "inheritPermission",
            "URL",
            "additionalUrls",
            "authHeader",
            "label",
            "showTile",
            "isProtected",
        ],
    )

    # Parse / organize information to be outputed
    apps = sorted(_installed_apps())
    apps_base_path = {
        app: app_setting(app, "domain") + app_setting(app, "path")
        for app in apps
        if app_setting(app, "domain") and app_setting(app, "path")
    }

    permissions = {}
    for infos in permissions_infos:

        name = infos["cn"][0]
        if ignore_system_perms and name.split(".")[0] in SYSTEM_PERMS:
            continue

        app = name.split(".")[0]

        perm = {}
        perm["allowed"] = [
            _ldap_path_extract(p, "cn")
            for p in infos.get("groupPermission", [])
        ]

        if full:
            perm["corresponding_users"] = [
                _ldap_path_extract(p, "uid")
                for p in infos.get("inheritPermission", [])
            ]
            perm["auth_header"] = infos.get("authHeader", [False])[0] == "TRUE"
            perm["label"] = infos.get("label", [None])[0]
            perm["show_tile"] = infos.get("showTile", [False])[0] == "TRUE"
            perm["protected"] = infos.get("isProtected", [False])[0] == "TRUE"
            perm["url"] = infos.get("URL", [None])[0]
            perm["additional_urls"] = infos.get("additionalUrls", [])

            if absolute_urls:
                app_base_path = (
                    apps_base_path[app] if app in apps_base_path else ""
                )  # Meh in some situation where the app is currently installed/removed, this function may be called and we still need to act as if the corresponding permission indeed exists ... dunno if that's really the right way to proceed but okay.
                perm["url"] = _get_absolute_url(perm["url"], app_base_path)
                perm["additional_urls"] = [
                    _get_absolute_url(url, app_base_path)
                    for url in perm["additional_urls"]
                ]

        permissions[name] = perm

    # Make sure labels for sub-permissions are the form " Applabel (Sublabel) "
    if full:
        subpermissions = {
            k: v
            for k, v in permissions.items() if not k.endswith(".main")
        }
        for name, infos in subpermissions.items():
            main_perm_name = name.split(".")[0] + ".main"
            if main_perm_name not in permissions:
                logger.debug(
                    "Uhoh, unknown permission %s ? (Maybe we're in the process or deleting the perm for this app...)"
                    % main_perm_name)
                continue
            main_perm_label = permissions[main_perm_name]["label"]
            infos["sublabel"] = infos["label"]
            infos["label"] = "%s (%s)" % (main_perm_label, infos["label"])

    if short:
        permissions = list(permissions.keys())

    return {"permissions": permissions}
Пример #6
0
def domain_remove(operation_logger, domain, remove_apps=False, force=False):
    """
    Delete domains

    Keyword argument:
        domain -- Domain to delete
        remove_apps -- Remove applications installed on the domain
        force -- Force the domain removal and don't not ask confirmation to
                 remove apps if remove_apps is specified

    """
    from yunohost.hook import hook_callback
    from yunohost.app import app_ssowatconf, app_info, app_remove
    from yunohost.utils.ldap import _get_ldap_interface

    # the 'force' here is related to the exception happening in domain_add ...
    # we don't want to check the domain exists because the ldap add may have
    # failed
    if not force and domain not in domain_list()['domains']:
        raise YunohostError('domain_name_unknown', domain=domain)

    # Check domain is not the main domain
    if domain == _get_maindomain():
        other_domains = domain_list()["domains"]
        other_domains.remove(domain)

        if other_domains:
            raise YunohostError(
                "domain_cannot_remove_main",
                domain=domain,
                other_domains="\n * " + ("\n * ".join(other_domains)),
            )
        else:
            raise YunohostError("domain_cannot_remove_main_add_new_one",
                                domain=domain)

    # Check if apps are installed on the domain
    apps_on_that_domain = []

    for app in _installed_apps():
        settings = _get_app_settings(app)
        label = app_info(app)["name"]
        if settings.get("domain") == domain:
            apps_on_that_domain.append(
                (app, "    - %s \"%s\" on https://%s%s" %
                 (app, label, domain, settings["path"])
                 if "path" in settings else app))

    if apps_on_that_domain:
        if remove_apps:
            if msettings.get('interface') == "cli" and not force:
                answer = msignals.prompt(m18n.n(
                    'domain_remove_confirm_apps_removal',
                    apps="\n".join([x[1] for x in apps_on_that_domain]),
                    answers='y/N'),
                                         color="yellow")
                if answer.upper() != "Y":
                    raise YunohostError("aborting")

            for app, _ in apps_on_that_domain:
                app_remove(app)
        else:
            raise YunohostError('domain_uninstall_app_first',
                                apps="\n".join(
                                    [x[1] for x in apps_on_that_domain]))

    operation_logger.start()
    ldap = _get_ldap_interface()
    try:
        ldap.remove("virtualdomain=" + domain + ",ou=domains")
    except Exception as e:
        raise YunohostError("domain_deletion_failed", domain=domain, error=e)

    os.system("rm -rf /etc/yunohost/certs/%s" % domain)

    # Sometime we have weird issues with the regenconf where some files
    # appears as manually modified even though they weren't touched ...
    # There are a few ideas why this happens (like backup/restore nginx
    # conf ... which we shouldnt do ...). This in turns creates funky
    # situation where the regenconf may refuse to re-create the conf
    # (when re-creating a domain..)
    #
    # So here we force-clear the has out of the regenconf if it exists.
    # This is a pretty ad hoc solution and only applied to nginx
    # because it's one of the major service, but in the long term we
    # should identify the root of this bug...
    _force_clear_hashes(["/etc/nginx/conf.d/%s.conf" % domain])
    # And in addition we even force-delete the file Otherwise, if the file was
    # manually modified, it may not get removed by the regenconf which leads to
    # catastrophic consequences of nginx breaking because it can't load the
    # cert file which disappeared etc..
    if os.path.exists("/etc/nginx/conf.d/%s.conf" % domain):
        _process_regen_conf("/etc/nginx/conf.d/%s.conf" % domain,
                            new_conf=None,
                            save=True)

    regen_conf(names=["nginx", "metronome", "dnsmasq", "postfix"])
    app_ssowatconf()

    hook_callback("post_domain_remove", args=[domain])

    logger.success(m18n.n("domain_deleted"))
Пример #7
0
def migrate_legacy_permission_settings(app=None):

    logger.info(m18n.n("migrating_legacy_permission_settings"))
    apps = _installed_apps()

    if app:
        if app not in apps:
            logger.error(
                "Can't migrate permission for app %s because it ain't installed..."
                % app)
            apps = []
        else:
            apps = [app]

    for app in apps:

        settings = _get_app_settings(app) or {}
        if settings.get("label"):
            user_permission_update(app + ".main",
                                   label=settings["label"],
                                   sync_perm=False)
            del settings["label"]

        def _setting(name):
            s = settings.get(name)
            return s.split(',') if s else []

        skipped_urls = [uri for uri in _setting('skipped_uris') if uri != '/']
        skipped_urls += ['re:' + regex for regex in _setting('skipped_regex')]
        unprotected_urls = [
            uri for uri in _setting('unprotected_uris') if uri != '/'
        ]
        unprotected_urls += [
            're:' + regex for regex in _setting('unprotected_regex')
        ]
        protected_urls = [
            uri for uri in _setting('protected_uris') if uri != '/'
        ]
        protected_urls += [
            're:' + regex for regex in _setting('protected_regex')
        ]

        if skipped_urls != []:
            permission_create(app + ".legacy_skipped_uris",
                              additional_urls=skipped_urls,
                              auth_header=False,
                              label=legacy_permission_label(app, "skipped"),
                              show_tile=False,
                              allowed='visitors',
                              protected=True,
                              sync_perm=False)
        if unprotected_urls != []:
            permission_create(app + ".legacy_unprotected_uris",
                              additional_urls=unprotected_urls,
                              auth_header=True,
                              label=legacy_permission_label(
                                  app, "unprotected"),
                              show_tile=False,
                              allowed='visitors',
                              protected=True,
                              sync_perm=False)
        if protected_urls != []:
            permission_create(app + ".legacy_protected_uris",
                              additional_urls=protected_urls,
                              auth_header=True,
                              label=legacy_permission_label(app, "protected"),
                              show_tile=False,
                              allowed=user_permission_list()['permissions'][
                                  app + ".main"]['allowed'],
                              protected=True,
                              sync_perm=False)

        legacy_permission_settings = [
            "skipped_uris", "unprotected_uris", "protected_uris",
            "skipped_regex", "unprotected_regex", "protected_regex"
        ]
        for key in legacy_permission_settings:
            if key in settings:
                del settings[key]

        _set_app_settings(app, settings)

        permission_sync_to_user()
Пример #8
0
def domain_remove(operation_logger, domain, force=False):
    """
    Delete domains

    Keyword argument:
        domain -- Domain to delete
        force -- Force the domain removal

    """
    from yunohost.hook import hook_callback
    from yunohost.app import app_ssowatconf, app_info
    from yunohost.utils.ldap import _get_ldap_interface

    if not force and domain not in domain_list()['domains']:
        raise YunohostError('domain_name_unknown', domain=domain)

    # Check domain is not the main domain
    if domain == _get_maindomain():
        other_domains = domain_list()["domains"]
        other_domains.remove(domain)

        if other_domains:
            raise YunohostError('domain_cannot_remove_main',
                                domain=domain,
                                other_domains="\n * " +
                                ("\n * ".join(other_domains)))
        else:
            raise YunohostError('domain_cannot_remove_main_add_new_one',
                                domain=domain)

    # Check if apps are installed on the domain
    apps_on_that_domain = []

    for app in _installed_apps():
        settings = _get_app_settings(app)
        label = app_info(app)["name"]
        if settings.get("domain") == domain:
            apps_on_that_domain.append("    - %s \"%s\" on https://%s%s" %
                                       (app, label, domain, settings["path"])
                                       if "path" in settings else app)

    if apps_on_that_domain:
        raise YunohostError('domain_uninstall_app_first',
                            apps="\n".join(apps_on_that_domain))

    operation_logger.start()
    ldap = _get_ldap_interface()
    try:
        ldap.remove('virtualdomain=' + domain + ',ou=domains')
    except Exception as e:
        raise YunohostError('domain_deletion_failed', domain=domain, error=e)

    os.system('rm -rf /etc/yunohost/certs/%s' % domain)

    # Sometime we have weird issues with the regenconf where some files
    # appears as manually modified even though they weren't touched ...
    # There are a few ideas why this happens (like backup/restore nginx
    # conf ... which we shouldnt do ...). This in turns creates funky
    # situation where the regenconf may refuse to re-create the conf
    # (when re-creating a domain..)
    #
    # So here we force-clear the has out of the regenconf if it exists.
    # This is a pretty ad hoc solution and only applied to nginx
    # because it's one of the major service, but in the long term we
    # should identify the root of this bug...
    _force_clear_hashes(["/etc/nginx/conf.d/%s.conf" % domain])
    # And in addition we even force-delete the file Otherwise, if the file was
    # manually modified, it may not get removed by the regenconf which leads to
    # catastrophic consequences of nginx breaking because it can't load the
    # cert file which disappeared etc..
    if os.path.exists("/etc/nginx/conf.d/%s.conf" % domain):
        _process_regen_conf("/etc/nginx/conf.d/%s.conf" % domain,
                            new_conf=None,
                            save=True)

    regen_conf(names=['nginx', 'metronome', 'dnsmasq', 'postfix'])
    app_ssowatconf()

    hook_callback('post_domain_remove', args=[domain])

    logger.success(m18n.n('domain_deleted'))