Ejemplo n.º 1
0
 def test_01_create_realm(self):
     rid = save_resolver({"resolver": self.resolvername1,
                            "type": "passwdresolver",
                            "fileName": "/etc/passwd"})
     self.assertTrue(rid > 0, rid)
     
     rid = save_resolver({"resolver": self.resolvername2,
                            "type": "passwdresolver",
                            "fileName": "/etc/secrets"})
     self.assertTrue(rid > 0, rid)
     
     (added, failed) = set_realm(self.realm1,
                                 [self.resolvername1,
                                  self.resolvername2])
     self.assertTrue(len(failed) == 0)
     self.assertTrue(len(added) == 2)
     
     # test the realms
     realms = get_realms()
     self.assertTrue(self.realm1 in realms, realms)
     self.assertTrue(realms.get("realm1").get("default"), realms)
     
     # try to create realm with invalid name
     self.assertRaises(Exception, set_realm, "#####")
     
     # update the resolver list:
     (added, failed) = set_realm(self.realm1,
                                 [self.resolvername1,
                                  "non exiting"])
     self.assertTrue(len(failed) == 1)
     self.assertTrue(len(added) == 1)
     
     self.assertTrue(realm_is_defined(self.realm1))
     self.assertTrue(realm_is_defined("non exist") is False)
Ejemplo n.º 2
0
 def test_10_delete_realm(self):
     delete_realm(self.realm1)
     delete_realm("realm2")
     delete_resolver(self.resolvername1)
     delete_resolver(self.resolvername2)
     realms = get_realms()
     self.assertTrue(len(realms) == 0, realms)
Ejemplo n.º 3
0
def get_config_documentation():
    """
    returns an restructured text document, that describes the complete
    configuration.
    """
    P = PolicyClass()

    config = get_from_config()
    resolvers = get_resolver_list()
    realms = get_realms()
    policies = P.list_policies()
    admins = get_db_admins()
    context = {
        "system": socket.getfqdn(socket.gethostname()),
        "date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M"),
        "systemconfig": config,
        "appconfig": current_app.config,
        "resolverconfig": resolvers,
        "realmconfig": realms,
        "policyconfig": policies,
        "admins": admins
    }

    g.audit_object.log({"success": True})
    # Three or more line breaks will be changed to two.
    return re.sub("\n{3,}", "\n\n",
                  render_template("documentation.rst", context=context))
Ejemplo n.º 4
0
 def test_10_delete_realm(self):
     delete_realm(self.realm1)
     delete_realm("realm2")
     delete_resolver(self.resolvername1)
     delete_resolver(self.resolvername2)
     realms = get_realms()
     self.assertTrue(len(realms) == 0, realms)
Ejemplo n.º 5
0
def get_config_documentation():
    """
    returns an restructured text document, that describes the complete
    configuration.
    """
    P = PolicyClass()

    config = get_from_config()
    resolvers = get_resolver_list()
    realms = get_realms()
    policies = P.get_policies()
    admins = get_db_admins()
    context = {"system": socket.getfqdn(socket.gethostname()),
               "date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M"),
               "systemconfig": config,
               "appconfig": current_app.config,
               "resolverconfig": resolvers,
               "realmconfig": realms,
               "policyconfig": policies,
               "admins": admins}

    g.audit_object.log({"success": True})
    # Three or more line breaks will be changed to two.
    return re.sub("\n{3,}", "\n\n", render_template("documentation.rst",
                                               context=context))
Ejemplo n.º 6
0
def list():
    """
    list the available realms
    """
    from privacyidea.lib.realm import get_realms
    realm_list = get_realms()
    for name, realm_data in realm_list.iteritems():
        resolvernames = [x.get("name") for x in realm_data.get("resolver")]
        print "%16s: %s" % (name, resolvernames)
Ejemplo n.º 7
0
def single_page_application():
    instance = request.script_root
    if instance == "/":
        instance = ""
    # The backend URL should come from the configuration of the system.
    backend_url = ""

    # The default theme. We can change this later
    theme = current_app.config.get("PI_CSS", DEFAULT_THEME)
    # Get further customizations
    customization = current_app.config.get("PI_CUSTOMIZATION",
                                           "/static/customize/")
    customization = customization.strip('/')
    # TODO: we should add the CSS into PI_CUSTOMZATION/css
    # Enrollment-Wizard:
    #    PI_CUSTOMIZATION/views/includes/token.enroll.pre.top.html
    #    PI_CUSTOMIZATION/views/includes/token.enroll.pre.bottom.html
    #    PI_CUSTOMIZATION/views/includes/token.enroll.post.top.html
    #    PI_CUSTOMIZATION/views/includes/token.enroll.post.bottom.html
    browser_lang = request.accept_languages.best_match(["en", "de"])
    # check if login with REMOTE_USER is allowed.
    remote_user = ""
    password_reset = False
    if not hasattr(request, "all_data"):
        request.all_data = {}
    # Depending on displaying the realm dropdown, we fill realms or not.
    policy_object = PolicyClass()
    realms = ""
    client_ip = request.access_route[0] if request.access_route else \
        request.remote_addr
    realm_dropdown = policy_object.get_policies(action=ACTION.REALMDROPDOWN,
                                                scope=SCOPE.WEBUI,
                                                client=client_ip)
    if realm_dropdown:
        realms = ",".join(get_realms().keys())

    try:
        if is_remote_user_allowed(request):
            remote_user = request.remote_user
        password_reset = is_password_reset()
        hsm_ready = True
    except HSMException:
        hsm_ready = False

    return render_template("index.html",
                           instance=instance,
                           backendUrl=backend_url,
                           browser_lang=browser_lang,
                           remote_user=remote_user,
                           theme=theme,
                           password_reset=password_reset,
                           hsm_ready=hsm_ready,
                           customization=customization,
                           realms=realms)
Ejemplo n.º 8
0
    def conditions(cls):
        """
        The UserNotification can filter for conditions like
        * type of logged in user and
        * successful or failed value.success

        allowed types are str, multi, text, regexp

        :return: dict
        """
        realms = get_realms()
        cond = {
            "realm": {
                "type": "str",
                "desc": _("The user realm, for which this event should apply."),
                "value": realms.keys()
            },
            "tokenrealm": {
                "type": "multi",
                "desc": _("The token realm, for which this event should "
                          "apply."),
                "value": [{"name": r} for r in realms.keys()]
            },
            "tokentype": {
                "type": "multi",
                "desc": _("The type of the token."),
                "value": [{"name": r} for r in get_token_types()]
            },
            "logged_in_user": {
                "type": "str",
                "desc": _("The logged in user is of the following type."),
                "value": (ROLE.ADMIN, ROLE.USER)
            },
            "result_value": {
                "type": "str",
                "desc": _("The result.value within the response is "
                          "True or False."),
                "value": ("True", "False")
            },
            "token_locked": {
                "type": "str",
                "desc": _("Check if the max failcounter of the token is "
                          "reached."),
                "value": ("True", "False")
            },
            "serial": {
                "type": "regexp",
                "desc": _("Action is triggered, if the serial matches this "
                          "regular expression.")
            }
        }
        return cond
Ejemplo n.º 9
0
def single_page_application():
    instance = request.script_root
    if instance == "/":
        instance = ""
    # The backend URL should come from the configuration of the system.
    backend_url = ""

    # The default theme. We can change this later
    theme = current_app.config.get("PI_CSS", DEFAULT_THEME)
    # Get further customizations
    customization = current_app.config.get("PI_CUSTOMIZATION",
                                           "/static/customize/")
    customization = customization.strip('/')
    # TODO: we should add the CSS into PI_CUSTOMZATION/css
    # Enrollment-Wizard:
    #    PI_CUSTOMIZATION/views/includes/token.enroll.pre.top.html
    #    PI_CUSTOMIZATION/views/includes/token.enroll.pre.bottom.html
    #    PI_CUSTOMIZATION/views/includes/token.enroll.post.top.html
    #    PI_CUSTOMIZATION/views/includes/token.enroll.post.bottom.html
    browser_lang = request.accept_languages.best_match(["en", "de"])
    # check if login with REMOTE_USER is allowed.
    remote_user = ""
    password_reset = False
    # Depending on displaying the realm dropdown, we fill realms or not.
    policy_object = PolicyClass()
    realms = ""
    client_ip = request.access_route[0] if request.access_route else \
        request.remote_addr
    realm_dropdown = policy_object.get_policies(action=ACTION.REALMDROPDOWN,
                                                scope=SCOPE.WEBUI,
                                                client=client_ip)
    if realm_dropdown:
        realms = ",".join(get_realms().keys())

    try:
        if is_remote_user_allowed(request):
            remote_user = request.remote_user
        password_reset = is_password_reset()
        hsm_ready = True
    except HSMException:
        hsm_ready = False

    return render_template("index.html", instance=instance,
                           backendUrl=backend_url,
                           browser_lang=browser_lang,
                           remote_user=remote_user,
                           theme=theme,
                           password_reset=password_reset,
                           hsm_ready=hsm_ready,
                           customization=customization,
                           realms=realms)
Ejemplo n.º 10
0
    def actions(cls):
        """
        This method returns a dictionary of allowed actions and possible
        options in this handler module.

        :return: dict with actions
        """
        realm_list = get_realms().keys()
        actions = {ACTION_TYPE.SET_TOKENREALM:
                       {"realm":
                            {"type": "str",
                             "required": True,
                             "description": _("set a new realm of the token"),
                             "value": realm_list},
                        "only_realm":
                            {"type": "bool",
                             "description": _("The new realm will be the only "
                                              "realm of the token. I.e. all "
                                              "other realms will be removed "
                                              "from this token. Otherwise the "
                                              "realm will be added to the token.")
                            }
                        },
                   ACTION_TYPE.DELETE: {},
                   ACTION_TYPE.UNASSIGN: {},
                   ACTION_TYPE.DISABLE: {},
                   ACTION_TYPE.ENABLE: {},
                   #"assign": {},
                   ACTION_TYPE.INIT:
                       {"tokentype":
                            {"type": "str",
                             "required": True,
                             "description": _("Token type to create"),
                             "value": get_token_types()
                             },
                        #"user": {},
                        "realm":
                            {"type": "str",
                             "required": False,
                             "description": _("Set the realm of the newly "
                                              "created token."),
                             "value": realm_list},
                        }
                   }
        return actions
Ejemplo n.º 11
0
    def test_01_create_realm(self):
        rid = save_resolver({
            "resolver": self.resolvername1,
            "type": "passwdresolver",
            "fileName": "/etc/passwd"
        })
        self.assertTrue(rid > 0, rid)

        rid = save_resolver({
            "resolver": self.resolvername2,
            "type": "passwdresolver",
            "fileName": "/etc/secrets"
        })
        self.assertTrue(rid > 0, rid)

        (added, failed) = set_realm(self.realm1,
                                    [self.resolvername1, self.resolvername2])
        self.assertTrue(len(failed) == 0)
        self.assertTrue(len(added) == 2)

        (added, failed) = set_realm(self.realm_dot,
                                    [self.resolvername1, self.resolvername2])
        self.assertTrue(len(failed) == 0)
        self.assertTrue(len(added) == 2)

        # test the realms
        realms = get_realms()
        self.assertTrue(self.realm1 in realms, realms)
        self.assertTrue(realms.get("realm1").get("default"), realms)
        self.assertTrue(self.realm_dot in realms, realms)

        # delete dot realm
        delete_realm(self.realm_dot)

        # try to create realm with invalid name
        self.assertRaises(Exception, set_realm, "#####")

        # update the resolver list:
        (added, failed) = set_realm(self.realm1,
                                    [self.resolvername1, "non exiting"])
        self.assertTrue(len(failed) == 1)
        self.assertTrue(len(added) == 1)

        self.assertTrue(realm_is_defined(self.realm1))
        self.assertTrue(realm_is_defined("non exist") is False)
Ejemplo n.º 12
0
    def conditions(cls):
        """
        The UserNotification can filter for conditions like
        * type of logged in user and
        * successful or failed value.success

        :return: dict
        """
        realms = get_realms()
        cond = {
            "realm": {
                "type": "str",
                "desc": _("The user realm, for which this event should aply."),
                "value": realms.keys()
            },
            "logged_in_user": {
                "type": "str",
                "desc": _("The logged in user is of the following type."),
                "value": (ROLE.ADMIN, ROLE.USER)
            },
            "result_value": {
                "type":
                "str",
                "desc":
                _("The result.value within the response is "
                  "True or False."),
                "value": ("True", "False")
            },
            "token_locked": {
                "type":
                "str",
                "desc":
                _("Check if the max failcounter of the token is "
                  "reached."),
                "value": ("True", "False")
            }
        }
        return cond
Ejemplo n.º 13
0
 def test_03_get_specific_realm(self):
     realm = get_realms(self.realm1)
     self.assertTrue(self.realm1 in realm, realm)
     self.assertTrue(len(realm) == 1, realm)
Ejemplo n.º 14
0
def single_page_application():
    instance = request.script_root
    if instance == "/":
        instance = ""
    # The backend URL should come from the configuration of the system.
    backend_url = ""

    if current_app.config.get("PI_UI_DEACTIVATED"):
        # Do not provide the UI
        return render_template("deactivated.html")

    # The default theme. We can change this later
    theme = current_app.config.get("PI_CSS", DEFAULT_THEME)
    # Get further customizations
    customization = current_app.config.get("PI_CUSTOMIZATION",
                                           "/static/customize/")
    customization = customization.strip('/')
    # TODO: we should add the CSS into PI_CUSTOMZATION/css
    # Enrollment-Wizard:
    #    PI_CUSTOMIZATION/views/includes/token.enroll.pre.top.html
    #    PI_CUSTOMIZATION/views/includes/token.enroll.pre.bottom.html
    #    PI_CUSTOMIZATION/views/includes/token.enroll.post.top.html
    #    PI_CUSTOMIZATION/views/includes/token.enroll.post.bottom.html
    # Get the hidden external links
    external_links = current_app.config.get("PI_EXTERNAL_LINKS", True)
    # Get the logo file
    logo = current_app.config.get("PI_LOGO", "privacyIDEA1.png")
    browser_lang = request.accept_languages.best_match(["en", "de"])
    # check if login with REMOTE_USER is allowed.
    remote_user = ""
    password_reset = False
    if not hasattr(request, "all_data"):
        request.all_data = {}
    # Depending on displaying the realm dropdown, we fill realms or not.
    policy_object = PolicyClass()
    realms = ""
    client_ip = request.access_route[0] if request.access_route else \
        request.remote_addr
    realm_dropdown = policy_object.get_policies(action=ACTION.REALMDROPDOWN,
                                                scope=SCOPE.WEBUI,
                                                client=client_ip,
                                                active=True)
    if realm_dropdown:
        try:
            realm_dropdown_values = policy_object.get_action_values(
                action=ACTION.REALMDROPDOWN,
                scope=SCOPE.WEBUI,
                client=client_ip)
            # Use the realms from the policy.
            realms = ",".join(realm_dropdown_values)
        except AttributeError as ex:
            # The policy is still a boolean realm_dropdown action
            # Thus we display ALL realms
            realms = ",".join(get_realms().keys())
        if realms:
            realms = "," + realms

    try:
        if is_remote_user_allowed(request):
            remote_user = request.remote_user
        password_reset = is_password_reset()
        hsm_ready = True
    except HSMException:
        hsm_ready = False

    # Use policies to determine the customization of menu
    # and baseline. get_action_values returns an array!
    sub_state  = subscription_status()
    customization_menu_file = policy_object.get_action_values(
        allow_white_space_in_action=True,
        action=ACTION.CUSTOM_MENU,
        scope=SCOPE.WEBUI,
        client=client_ip, unique=True)
    if len(customization_menu_file) and customization_menu_file[0] \
            and sub_state not in [1, 2]:
        customization_menu_file = customization_menu_file[0]
    else:
        customization_menu_file = "templates/menu.html"
    customization_baseline_file = policy_object.get_action_values(
        allow_white_space_in_action=True,
        action=ACTION.CUSTOM_BASELINE,
        scope=SCOPE.WEBUI,
        client=client_ip, unique=True)
    if len(customization_baseline_file) and customization_baseline_file[0] \
            and sub_state not in [1, 2]:
        customization_baseline_file = customization_baseline_file[0]
    else:
        customization_baseline_file = "templates/baseline.html"

    return render_template("index.html", instance=instance,
                           backendUrl=backend_url,
                           browser_lang=browser_lang,
                           remote_user=remote_user,
                           theme=theme,
                           password_reset=password_reset,
                           hsm_ready=hsm_ready,
                           customization=customization,
                           customization_menu_file=customization_menu_file,
                           customization_baseline_file=customization_baseline_file,
                           realms=realms,
                           external_links=external_links,
                           logo=logo)
Ejemplo n.º 15
0
def single_page_application():
    instance = request.script_root
    if instance == "/":
        instance = ""
    # The backend URL should come from the configuration of the system.
    backend_url = ""

    if current_app.config.get("PI_UI_DEACTIVATED"):
        # Do not provide the UI
        return send_html(render_template("deactivated.html"))

    # The default theme. We can change this later
    theme = current_app.config.get("PI_CSS", DEFAULT_THEME)
    theme = theme.strip('/')
    # Get further customizations
    customization = current_app.config.get("PI_CUSTOMIZATION",
                                           "/static/customize/")
    customization = customization.strip('/')
    custom_css = customization + "/css/custom.css" if current_app.config.get("PI_CUSTOM_CSS") else ""
    # Enrollment-Wizard:
    #    PI_CUSTOMIZATION/views/includes/token.enroll.pre.top.html
    #    PI_CUSTOMIZATION/views/includes/token.enroll.pre.bottom.html
    #    PI_CUSTOMIZATION/views/includes/token.enroll.post.top.html
    #    PI_CUSTOMIZATION/views/includes/token.enroll.post.bottom.html
    # Get the hidden external links
    external_links = current_app.config.get("PI_EXTERNAL_LINKS", True)
    # Read the UI translation warning
    translation_warning = current_app.config.get("PI_TRANSLATION_WARNING", False)
    # Get the logo file
    logo = current_app.config.get("PI_LOGO", "privacyIDEA1.png")
    browser_lang = request.accept_languages.best_match(["en", "de", "de-DE", "nl"], default="en").split("-")[0]
    # The page title can be configured in pi.cfg
    page_title = current_app.config.get("PI_PAGE_TITLE", "privacyIDEA Authentication System")
    # check if login with REMOTE_USER is allowed.
    remote_user = ""
    password_reset = False
    if not hasattr(request, "all_data"):
        request.all_data = {}
    # Depending on displaying the realm dropdown, we fill realms or not.
    realms = ""
    realm_dropdown = Match.action_only(g, scope=SCOPE.WEBUI, action=ACTION.REALMDROPDOWN)\
        .policies(write_to_audit_log=False)
    if realm_dropdown:
        try:
            realm_dropdown_values = Match.action_only(g, scope=SCOPE.WEBUI, action=ACTION.REALMDROPDOWN) \
                .action_values(unique=False, write_to_audit_log=False)
            # Use the realms from the policy.
            realms = ",".join(realm_dropdown_values)
        except AttributeError as _e:
            # The policy is still a boolean realm_dropdown action
            # Thus we display ALL realms
            realms = ",".join(get_realms())

    try:
        if is_remote_user_allowed(request):
            remote_user = request.remote_user
        password_reset = is_password_reset(g)
        hsm_ready = True
    except HSMException:
        hsm_ready = False

    # Use policies to determine the customization of menu
    # and baseline. get_action_values returns an array!
    sub_state = subscription_status()
    customization_menu_file = Match.action_only(g, action=ACTION.CUSTOM_MENU,
                                                scope=SCOPE.WEBUI)\
        .action_values(unique=True, allow_white_space_in_action=True, write_to_audit_log=False)
    if len(customization_menu_file) and list(customization_menu_file)[0] \
            and sub_state not in [1, 2]:
        customization_menu_file = list(customization_menu_file)[0]
    else:
        customization_menu_file = "templates/menu.html"
    customization_baseline_file = Match.action_only(g, action=ACTION.CUSTOM_BASELINE,
                                                    scope=SCOPE.WEBUI) \
        .action_values(unique=True, allow_white_space_in_action=True, write_to_audit_log=False)
    if len(customization_baseline_file) and list(customization_baseline_file)[0] \
            and sub_state not in [1, 2]:
        customization_baseline_file = list(customization_baseline_file)[0]
    else:
        customization_baseline_file = "templates/baseline.html"

    login_text = Match.action_only(g, action=ACTION.LOGIN_TEXT, scope=SCOPE.WEBUI) \
        .action_values(unique=True, allow_white_space_in_action=True, write_to_audit_log=False)
    if len(login_text) and list(login_text)[0] and sub_state not in [1, 2]:
        login_text = list(login_text)[0]
    else:
        login_text = ""

    render_context = {
        'instance': instance,
        'backendUrl': backend_url,
        'browser_lang': browser_lang,
        'remote_user': remote_user,
        'theme': theme,
        'translation_warning': translation_warning,
        'password_reset': password_reset,
        'hsm_ready': hsm_ready,
        'has_job_queue': str(has_job_queue()),
        'customization': customization,
        'custom_css': custom_css,
        'customization_menu_file': customization_menu_file,
        'customization_baseline_file': customization_baseline_file,
        'realms': realms,
        'external_links': external_links,
        'login_text': login_text,
        'logo': logo,
        'page_title': page_title
    }

    return send_html(render_template("index.html", **render_context))
Ejemplo n.º 16
0
    def test_21_check_all_resolver(self):
        # check_all_resolver allows to find a policy for a secondary user
        # resolver.
        # We create one realm "realm1" with the resolvers
        # reso1 (prio 1)
        # reso2 (prio 2)
        # reso3 (prio 3)
        # A user user@realm1 will be identified as user.reso1@realm1.
        # But we will also match policies for reso2.

        # no realm and resolver
        r = get_realms()
        self.assertEqual(r, {})

        r = get_resolver_list()
        self.assertEqual(r, {})

        # create user realm
        for reso in ["reso1", "resoX", "resoA"]:
            rid = save_resolver({
                "resolver": reso,
                "type": "passwdresolver",
                "fileName": PWFILE
            })
            self.assertTrue(rid > 0, rid)

        # create a realm with reso1 being the resolver with the highest priority
        (added, failed) = set_realm("realm1", ["reso1", "resoX", "resoA"],
                                    priority={
                                        "reso1": 1,
                                        "resoX": 2,
                                        "resoA": 3
                                    })
        self.assertTrue(len(failed) == 0)
        self.assertTrue(len(added) == 3)

        user = User(login="******", realm="realm1")
        # The user, that is created, is cornelius.reso1@realm1
        user_str = "{0!s}".format(user)
        self.assertEqual(user_str, "<cornelius.reso1@realm1>")
        # But the user "cornelius" is also contained in other resolves in
        # this realm
        r = user.get_ordererd_resolvers()
        self.assertEqual(r, ["reso1", "resoX", "resoA"])
        self.assertFalse(user.is_empty())
        self.assertTrue(User().is_empty())

        # define a policy with the wrong resolver
        p = set_policy(name="checkAll",
                       scope=SCOPE.AUTHZ,
                       realm="realm1",
                       resolver="resoX",
                       action="{0}=totp".format(ACTION.TOKENTYPE))
        self.assertTrue(p > 0)
        p = set_policy(name="catchAll",
                       scope=SCOPE.AUTHZ,
                       realm="realm1",
                       action="{0}=totp".format(ACTION.TOKENTYPE))
        self.assertTrue(p > 0)
        P = PolicyClass()
        pols = P.get_policies(scope=SCOPE.AUTHZ,
                              realm=user.realm,
                              resolver=user.resolver,
                              user=user.login)
        self.assertEqual(len(pols), 1)

        # Now we change the policy, so that it uses check_all_resolver, i.e.
        p = set_policy(name="checkAll",
                       scope=SCOPE.AUTHZ,
                       realm="realm1",
                       resolver="resoX",
                       check_all_resolvers=True,
                       action="{0}=totp".format(ACTION.TOKENTYPE))
        self.assertTrue(p > 0)
        P = PolicyClass()
        pols = P.get_policies(scope=SCOPE.AUTHZ,
                              realm=user.realm,
                              resolver=user.resolver,
                              user=user.login)
        self.assertEqual(len(pols), 2)

        # delete policy
        delete_policy("checkAll")
        delete_policy("catchAll")
        # delete resolvers and realm
        delete_realm("realm1")
        for reso in ["reso1", "resoX", "resoA"]:
            rid = delete_resolver(reso)
            self.assertTrue(rid > 0, rid)
Ejemplo n.º 17
0
    def conditions(cls):
        """
        The UserNotification can filter for conditions like
        * type of logged in user and
        * successful or failed value.success

        allowed types are str, multi, text, regexp

        :return: dict
        """
        realms = get_realms()
        cond = {
            "realm": {
                "type": "str",
                "desc":
                _("The user realm, for which this event should apply."),
                "value": realms.keys()
            },
            "tokenrealm": {
                "type": "multi",
                "desc": _("The token realm, for which this event should "
                          "apply."),
                "value": [{
                    "name": r
                } for r in realms.keys()]
            },
            CONDITION.TOKENTYPE: {
                "type": "multi",
                "desc": _("The type of the token."),
                "value": [{
                    "name": r
                } for r in get_token_types()]
            },
            "logged_in_user": {
                "type": "str",
                "desc": _("The logged in user is of the following type."),
                "value": (ROLE.ADMIN, ROLE.USER)
            },
            "result_value": {
                "type":
                "str",
                "desc":
                _("The result.value within the response is "
                  "True or False."),
                "value": ("True", "False")
            },
            "token_locked": {
                "type":
                "str",
                "desc":
                _("Check if the max failcounter of the token is "
                  "reached."),
                "value": ("True", "False")
            },
            CONDITION.TOKEN_HAS_OWNER: {
                "type": "str",
                "desc": _("The token has a user assigned."),
                "value": ("True", "False")
            },
            CONDITION.TOKEN_IS_ORPHANED: {
                "type":
                "str",
                "desc":
                _("The token has a user assigned, but the user does "
                  "not exist in the userstore anymore."),
                "value": ("True", "False")
            },
            CONDITION.TOKEN_VALIDITY_PERIOD: {
                "type": "str",
                "desc": _("Check if the token is within its validity period."),
                "value": ("True", "False")
            },
            "serial": {
                "type":
                "regexp",
                "desc":
                _("Action is triggered, if the serial matches this "
                  "regular expression.")
            },
            CONDITION.USER_TOKEN_NUMBER: {
                "type":
                "str",
                "desc":
                _("Action is triggered, if the user has this number "
                  "of tokens assigned.")
            },
            CONDITION.OTP_COUNTER: {
                "type":
                "str",
                "desc":
                _("Action is triggered, if the counter of the token "
                  "equals this setting.")
            },
            CONDITION.LAST_AUTH: {
                "type":
                "str",
                "desc":
                _("Action is triggered, if the last authentication of "
                  "the token is older than 7h, 10d or 1y.")
            },
            CONDITION.COUNT_AUTH: {
                "type":
                "str",
                "desc":
                _("This can be '>100', '<99', or '=100', to trigger "
                  "the action, if the tokeninfo field 'count_auth' is "
                  "bigger than 100, less than 99 or exactly 100.")
            },
            CONDITION.COUNT_AUTH_SUCCESS: {
                "type":
                "str",
                "desc":
                _("This can be '>100', '<99', or '=100', to trigger "
                  "the action, if the tokeninfo field "
                  "'count_auth_success' is "
                  "bigger than 100, less than 99 or exactly 100.")
            },
            CONDITION.COUNT_AUTH_FAIL: {
                "type":
                "str",
                "desc":
                _("This can be '>100', '<99', or '=100', to trigger "
                  "the action, if the difference between the tokeninfo "
                  "field 'count_auth' and 'count_auth_success is "
                  "bigger than 100, less than 99 or exactly 100.")
            },
            CONDITION.TOKENINFO: {
                "type":
                "str",
                "desc":
                _("This condition can check any arbitrary tokeninfo "
                  "field. You need to enter something like "
                  "'<fieldname> == <fieldvalue>', '<fieldname> > "
                  "<fieldvalue>' or '<fieldname> < <fieldvalue>'")
            }
        }
        return cond
Ejemplo n.º 18
0
    def actions(cls):
        """
        This method returns a dictionary of allowed actions and possible
        options in this handler module.

        :return: dict with actions
        """
        realm_list = get_realms().keys()
        actions = {
            ACTION_TYPE.SET_TOKENREALM: {
                "realm": {
                    "type": "str",
                    "required": True,
                    "description": _("set a new realm of the token"),
                    "value": realm_list
                },
                "only_realm": {
                    "type":
                    "bool",
                    "description":
                    _("The new realm will be the only "
                      "realm of the token. I.e. all "
                      "other realms will be removed "
                      "from this token. Otherwise the "
                      "realm will be added to the token.")
                }
            },
            ACTION_TYPE.DELETE: {},
            ACTION_TYPE.UNASSIGN: {},
            ACTION_TYPE.DISABLE: {},
            ACTION_TYPE.ENABLE: {},
            ACTION_TYPE.INIT: {
                "tokentype": {
                    "type": "str",
                    "required": True,
                    "description": _("Token type to create"),
                    "value": get_token_types()
                },
                "user": {
                    "type":
                    "bool",
                    "description":
                    _("Assign token to user in "
                      "request or to tokenowner.")
                },
                "realm": {
                    "type":
                    "str",
                    "required":
                    False,
                    "description":
                    _("Set the realm of the newly "
                      "created token."),
                    "value":
                    realm_list
                },
                "motppin": {
                    "type":
                    "str",
                    "visibleIf":
                    "tokentype",
                    "visibleValue":
                    "motp",
                    "description":
                    _("Set the MOTP PIN of the MOTP "
                      "token during enrollment. This "
                      "is a required value for "
                      "enrolling MOTP tokens.")
                }
            },
            ACTION_TYPE.SET_DESCRIPTION: {
                "description": {
                    "type": "str",
                    "description": _("The new description of the "
                                     "token.")
                }
            },
            ACTION_TYPE.SET_VALIDITY: {
                VALIDITY.START: {
                    "type":
                    "str",
                    "description":
                    _("The token will be valid starting "
                      "at the given date. Can be a fixed "
                      "date or an offset like +10m, "
                      "+24h, +7d.")
                },
                VALIDITY.END: {
                    "type":
                    "str",
                    "description":
                    _("The token will be valid until "
                      "the given date. Can be a fixed "
                      "date or an offset like +10m, "
                      "+24h, +7d.")
                }
            },
            ACTION_TYPE.SET_COUNTWINDOW: {
                "count window": {
                    # TODO: should be "int" but we do not support
                    #  this at the moment.
                    "type": "str",
                    "required": True,
                    "description": _("Set the new count window of "
                                     "the token.")
                }
            },
            ACTION_TYPE.SET_TOKENINFO: {
                "key": {
                    "type": "str",
                    "required": True,
                    "description": _("Set this tokeninfo key.")
                },
                "value": {
                    "type": "str",
                    "description": _("Set the above key the this "
                                     "value.")
                }
            }
        }
        return actions
Ejemplo n.º 19
0
def single_page_application():
    instance = request.script_root
    if instance == "/":
        instance = ""
    # The backend URL should come from the configuration of the system.
    backend_url = ""

    if current_app.config.get("PI_UI_DEACTIVATED"):
        # Do not provide the UI
        return render_template("deactivated.html")

    # The default theme. We can change this later
    theme = current_app.config.get("PI_CSS", DEFAULT_THEME)
    # Get further customizations
    customization = current_app.config.get("PI_CUSTOMIZATION",
                                           "/static/customize/")
    customization = customization.strip('/')
    # TODO: we should add the CSS into PI_CUSTOMZATION/css
    # Enrollment-Wizard:
    #    PI_CUSTOMIZATION/views/includes/token.enroll.pre.top.html
    #    PI_CUSTOMIZATION/views/includes/token.enroll.pre.bottom.html
    #    PI_CUSTOMIZATION/views/includes/token.enroll.post.top.html
    #    PI_CUSTOMIZATION/views/includes/token.enroll.post.bottom.html
    # Get the hidden external links
    external_links = current_app.config.get("PI_EXTERNAL_LINKS", True)
    # Get the logo file
    logo = current_app.config.get("PI_LOGO", "privacyIDEA1.png")
    browser_lang = request.accept_languages.best_match(
        ["en", "de", "de-DE"], default="en").split("-")[0]
    # The page title can be configured in pi.cfg
    page_title = current_app.config.get("PI_PAGE_TITLE",
                                        "privacyIDEA Authentication System")
    # check if login with REMOTE_USER is allowed.
    remote_user = ""
    password_reset = False
    if not hasattr(request, "all_data"):
        request.all_data = {}
    # Depending on displaying the realm dropdown, we fill realms or not.
    policy_object = PolicyClass()
    realms = ""
    client_ip = get_client_ip(request, get_from_config(SYSCONF.OVERRIDECLIENT))
    realm_dropdown = policy_object.get_policies(action=ACTION.REALMDROPDOWN,
                                                scope=SCOPE.WEBUI,
                                                client=client_ip,
                                                active=True)
    if realm_dropdown:
        try:
            realm_dropdown_values = policy_object.get_action_values(
                action=ACTION.REALMDROPDOWN,
                scope=SCOPE.WEBUI,
                client=client_ip)
            # Use the realms from the policy.
            realms = ",".join(realm_dropdown_values)
        except AttributeError as ex:
            # The policy is still a boolean realm_dropdown action
            # Thus we display ALL realms
            realms = ",".join(get_realms())

    try:
        if is_remote_user_allowed(request):
            remote_user = request.remote_user
        password_reset = is_password_reset()
        hsm_ready = True
    except HSMException:
        hsm_ready = False

    # Use policies to determine the customization of menu
    # and baseline. get_action_values returns an array!
    sub_state = subscription_status()
    customization_menu_file = policy_object.get_action_values(
        allow_white_space_in_action=True,
        action=ACTION.CUSTOM_MENU,
        scope=SCOPE.WEBUI,
        client=client_ip,
        unique=True)
    if len(customization_menu_file) and list(customization_menu_file)[0] \
            and sub_state not in [1, 2]:
        customization_menu_file = list(customization_menu_file)[0]
    else:
        customization_menu_file = "templates/menu.html"
    customization_baseline_file = policy_object.get_action_values(
        allow_white_space_in_action=True,
        action=ACTION.CUSTOM_BASELINE,
        scope=SCOPE.WEBUI,
        client=client_ip,
        unique=True)
    if len(customization_baseline_file) and list(customization_baseline_file)[0] \
            and sub_state not in [1, 2]:
        customization_baseline_file = list(customization_baseline_file)[0]
    else:
        customization_baseline_file = "templates/baseline.html"

    login_text = policy_object.get_action_values(
        allow_white_space_in_action=True,
        action=ACTION.LOGIN_TEXT,
        scope=SCOPE.WEBUI,
        client=client_ip,
        unique=True)
    if len(login_text) and list(login_text)[0] and sub_state not in [1, 2]:
        login_text = list(login_text)[0]
    else:
        login_text = ""

    return render_template(
        "index.html",
        instance=instance,
        backendUrl=backend_url,
        browser_lang=browser_lang,
        remote_user=remote_user,
        theme=theme,
        password_reset=password_reset,
        hsm_ready=hsm_ready,
        has_job_queue=str(has_job_queue()),
        customization=customization,
        customization_menu_file=customization_menu_file,
        customization_baseline_file=customization_baseline_file,
        realms=realms,
        external_links=external_links,
        login_text=login_text,
        logo=logo,
        page_title=page_title)
Ejemplo n.º 20
0
    def test_21_check_all_resolver(self):
        # check_all_resolver allows to find a policy for a secondary user
        # resolver.
        # We create one realm "realm1" with the resolvers
        # reso1 (prio 1)
        # reso2 (prio 2)
        # reso3 (prio 3)
        # A user user@realm1 will be identified as user.reso1@realm1.
        # But we will also match policies for reso2.

        # no realm and resolver
        r = get_realms()
        self.assertEqual(r, {})

        r = get_resolver_list()
        self.assertEqual(r, {})

        # create user realm
        for reso in ["reso1", "resoX", "resoA"]:
            rid = save_resolver({"resolver": reso,
                                 "type": "passwdresolver",
                                 "fileName": PWFILE})
            self.assertTrue(rid > 0, rid)

        # create a realm with reso1 being the resolver with the highest priority
        (added, failed) = set_realm("realm1",
                                    ["reso1", "resoX", "resoA"],
                                    priority={"reso1": 1,
                                              "resoX": 2,
                                              "resoA": 3})
        self.assertTrue(len(failed) == 0)
        self.assertTrue(len(added) == 3)

        user = User(login="******",
                    realm="realm1")
        # The user, that is created, is cornelius.reso1@realm1
        user_str = "{0!s}".format(user)
        self.assertEqual(user_str, "<cornelius.reso1@realm1>")
        # But the user "cornelius" is also contained in other resolves in
        # this realm
        r = user.get_ordererd_resolvers()
        self.assertEqual(r, ["reso1", "resoX", "resoA"])
        self.assertFalse(user.is_empty())
        self.assertTrue(User().is_empty())

        # define a policy with the wrong resolver
        p = set_policy(name="checkAll", scope=SCOPE.AUTHZ, realm="realm1",
                       resolver="resoX",
                       action="{0}=totp".format(ACTION.TOKENTYPE))
        self.assertTrue(p > 0)
        p = set_policy(name="catchAll", scope=SCOPE.AUTHZ, realm="realm1",
                       action="{0}=totp".format(ACTION.TOKENTYPE))
        self.assertTrue(p > 0)
        P = PolicyClass()
        pols = P.get_policies(scope=SCOPE.AUTHZ, realm=user.realm,
                              resolver=user.resolver, user=user.login)
        self.assertEqual(len(pols), 1)

        # Now we change the policy, so that it uses check_all_resolver, i.e.
        p = set_policy(name="checkAll", scope=SCOPE.AUTHZ, realm="realm1",
                       resolver="resoX", check_all_resolvers=True,
                       action="{0}=totp".format(ACTION.TOKENTYPE))
        self.assertTrue(p > 0)
        P = PolicyClass()
        pols = P.get_policies(scope=SCOPE.AUTHZ, realm=user.realm,
                              resolver=user.resolver, user=user.login)
        self.assertEqual(len(pols), 2)

        # delete policy
        delete_policy("checkAll")
        delete_policy("catchAll")
        # delete resolvers and realm
        delete_realm("realm1")
        for reso in ["reso1", "resoX", "resoA"]:
            rid = delete_resolver(reso)
            self.assertTrue(rid > 0, rid)
Ejemplo n.º 21
0
    def conditions(cls):
        """
        The UserNotification can filter for conditions like
        * type of logged in user and
        * successful or failed value.success

        allowed types are str, multi, text, regexp

        :return: dict
        """
        realms = get_realms()
        resolvers = get_resolver_list()
        cond = {
            CONDITION.ROLLOUT_STATE: {
                "type": "str",
                "desc": _("The rollout_state of the token has a certain value like 'clientwait' or 'enrolled'.")
            },
            CONDITION.REALM: {
                "type": "str",
                "desc": _("The realm of the user, for which this event should apply."),
                "value": list(realms)
            },
            CONDITION.RESOLVER: {
                "type": "str",
                "desc": _("The resolver of the user, for which this event should apply."),
                "value": list(resolvers)
            },
            CONDITION.TOKENREALM: {
                "type": "multi",
                "desc": _("The realm of the token, for which this event should "
                          "apply."),
                "value": [{"name": r} for r in realms]
            },
            CONDITION.TOKENRESOLVER: {
                "type": "multi",
                "desc": _("The resolver of the token, for which this event should "
                          "apply."),
                "value": [{"name": r} for r in resolvers]
            },
            CONDITION.TOKENTYPE: {
                "type": "multi",
                "desc": _("The type of the token."),
                "value": [{"name": r} for r in get_token_types()]
            },
            "logged_in_user": {
                "type": "str",
                "desc": _("The logged in user is of the following type."),
                "value": (ROLE.ADMIN, ROLE.USER)
            },
            CONDITION.RESULT_VALUE: {
                "type": "str",
                "desc": _("The result.value within the response is "
                          "True or False."),
                "value": ("True", "False")
            },
            CONDITION.RESULT_STATUS: {
                "type": "str",
                "desc": _("The result.status within the response is "
                          "True or False."),
                "value": ("True", "False")
            },
            "token_locked": {
                "type": "str",
                "desc": _("Check if the max failcounter of the token is "
                          "reached."),
                "value": ("True", "False")
            },
            CONDITION.TOKEN_HAS_OWNER: {
                "type": "str",
                "desc": _("The token has a user assigned."),
                "value": ("True", "False")
            },
            CONDITION.TOKEN_IS_ORPHANED: {
                "type": "str",
                "desc": _("The token has a user assigned, but the user does "
                          "not exist in the userstore anymore."),
                "value": ("True", "False")
            },
            CONDITION.TOKEN_VALIDITY_PERIOD: {
                "type": "str",
                "desc": _("Check if the token is within its validity period."),
                "value": ("True", "False")
            },
            "serial": {
                "type": "regexp",
                "desc": _("Action is triggered, if the serial matches this "
                          "regular expression.")
            },
            CONDITION.USER_TOKEN_NUMBER: {
                "type": "str",
                "desc": _("Action is triggered, if the user has this number "
                          "of tokens assigned.")
            },
            CONDITION.OTP_COUNTER: {
                "type": "str",
                "desc": _("Action is triggered, if the counter of the token "
                          "equals this setting. Can also be "
                          "'>100' or '<99' for no exact match.")
            },
            CONDITION.LAST_AUTH: {
                "type": "str",
                "desc": _("Action is triggered, if the last authentication of "
                          "the token is older than 7h, 10d or 1y.")
            },
            CONDITION.COUNT_AUTH: {
                "type": "str",
                "desc": _("This can be '>100', '<99', or '=100', to trigger "
                          "the action, if the tokeninfo field 'count_auth' is "
                          "bigger than 100, less than 99 or exactly 100.")
            },
            CONDITION.COUNT_AUTH_SUCCESS: {
                "type": "str",
                "desc": _("This can be '>100', '<99', or '=100', to trigger "
                          "the action, if the tokeninfo field "
                          "'count_auth_success' is "
                          "bigger than 100, less than 99 or exactly 100.")
            },
            CONDITION.COUNT_AUTH_FAIL: {
                "type": "str",
                "desc": _("This can be '>100', '<99', or '=100', to trigger "
                          "the action, if the difference between the tokeninfo "
                          "field 'count_auth' and 'count_auth_success is "
                          "bigger than 100, less than 99 or exactly 100.")
            },
            CONDITION.TOKENINFO: {
                "type": "str",
                "desc": _("This condition can check any arbitrary tokeninfo "
                          "field. You need to enter something like "
                          "'<fieldname> == <fieldvalue>', '<fieldname> > "
                          "<fieldvalue>' or '<fieldname> < <fieldvalue>'")
            },
            CONDITION.DETAIL_ERROR_MESSAGE: {
                "type": "str",
                "desc": _("Here you can enter a regular expression. The "
                          "condition only applies if the regular expression "
                          "matches the detail->error->message in the response.")
            },
            CONDITION.DETAIL_MESSAGE: {
                "type": "str",
                "desc": _("Here you can enter a regular expression. The "
                          "condition only applies if the regular expression "
                          "matches the detail->message in the response.")
            },
            CONDITION.CLIENT_IP: {
                "type": "str",
                "desc": _("Trigger the action, if the client IP matches.")
            }
        }
        return cond
Ejemplo n.º 22
0
    def conditions(cls):
        """
        The UserNotification can filter for conditions like
        * type of logged in user and
        * successful or failed value.success

        allowed types are str, multi, text, regexp

        :return: dict
        """
        realms = get_realms()
        cond = {
            "realm": {
                "type": "str",
                "desc": _("The user realm, for which this event should apply."),
                "value": list(realms)
            },
            "tokenrealm": {
                "type": "multi",
                "desc": _("The token realm, for which this event should "
                          "apply."),
                "value": [{"name": r} for r in realms.keys()]
            },
            CONDITION.TOKENTYPE: {
                "type": "multi",
                "desc": _("The type of the token."),
                "value": [{"name": r} for r in get_token_types()]
            },
            "logged_in_user": {
                "type": "str",
                "desc": _("The logged in user is of the following type."),
                "value": (ROLE.ADMIN, ROLE.USER)
            },
            CONDITION.RESULT_VALUE: {
                "type": "str",
                "desc": _("The result.value within the response is "
                          "True or False."),
                "value": ("True", "False")
            },
            CONDITION.RESULT_STATUS: {
                "type": "str",
                "desc": _("The result.status within the response is "
                          "True or False."),
                "value": ("True", "False")
            },
            "token_locked": {
                "type": "str",
                "desc": _("Check if the max failcounter of the token is "
                          "reached."),
                "value": ("True", "False")
            },
            CONDITION.TOKEN_HAS_OWNER: {
                "type": "str",
                "desc": _("The token has a user assigned."),
                "value": ("True", "False")
            },
            CONDITION.TOKEN_IS_ORPHANED: {
                "type": "str",
                "desc": _("The token has a user assigned, but the user does "
                          "not exist in the userstore anymore."),
                "value": ("True", "False")
            },
            CONDITION.TOKEN_VALIDITY_PERIOD: {
                "type": "str",
                "desc": _("Check if the token is within its validity period."),
                "value": ("True", "False")
            },
            "serial": {
                "type": "regexp",
                "desc": _("Action is triggered, if the serial matches this "
                          "regular expression.")
            },
            CONDITION.USER_TOKEN_NUMBER: {
                "type": "str",
                "desc": _("Action is triggered, if the user has this number "
                          "of tokens assigned.")
            },
            CONDITION.OTP_COUNTER: {
                "type": "str",
                "desc": _("Action is triggered, if the counter of the token "
                          "equals this setting.")
            },
            CONDITION.LAST_AUTH: {
                "type": "str",
                "desc": _("Action is triggered, if the last authentication of "
                          "the token is older than 7h, 10d or 1y.")
            },
            CONDITION.COUNT_AUTH: {
                "type": "str",
                "desc": _("This can be '>100', '<99', or '=100', to trigger "
                          "the action, if the tokeninfo field 'count_auth' is "
                          "bigger than 100, less than 99 or exactly 100.")
            },
            CONDITION.COUNT_AUTH_SUCCESS: {
                "type": "str",
                "desc": _("This can be '>100', '<99', or '=100', to trigger "
                          "the action, if the tokeninfo field "
                          "'count_auth_success' is "
                          "bigger than 100, less than 99 or exactly 100.")
            },
            CONDITION.COUNT_AUTH_FAIL: {
                "type": "str",
                "desc": _("This can be '>100', '<99', or '=100', to trigger "
                          "the action, if the difference between the tokeninfo "
                          "field 'count_auth' and 'count_auth_success is "
                          "bigger than 100, less than 99 or exactly 100.")
            },
            CONDITION.TOKENINFO: {
                "type": "str",
                "desc": _("This condition can check any arbitrary tokeninfo "
                          "field. You need to enter something like "
                          "'<fieldname> == <fieldvalue>', '<fieldname> > "
                          "<fieldvalue>' or '<fieldname> < <fieldvalue>'")
            },
            CONDITION.DETAIL_ERROR_MESSAGE: {
                "type": "str",
                "desc": _("Here you can enter a regular expression. The "
                          "condition only applies if the regular expression "
                          "matches the detail->error->message in the response.")
            },
            CONDITION.DETAIL_MESSAGE: {
                "type": "str",
                "desc": _("Here you can enter a regular expression. The "
                          "condition only applies if the regular expression "
                          "matches the detail->message in the response.")
            }
        }
        return cond
Ejemplo n.º 23
0
 def test_03_get_specific_realm(self):
     realm = get_realms(self.realm1)
     self.assertTrue(self.realm1 in realm, realm)
     self.assertTrue(len(realm) == 1, realm)
Ejemplo n.º 24
0
    def actions(cls):
        """
        This method returns a dictionary of allowed actions and possible
        options in this handler module.

        :return: dict with actions
        """
        realm_list = list(get_realms())
        actions = {ACTION_TYPE.SET_TOKENREALM:
                       {"realm":
                            {"type": "str",
                             "required": True,
                             "description": _("set a new realm of the token"),
                             "value": realm_list},
                        "only_realm":
                            {"type": "bool",
                             "description": _("The new realm will be the only "
                                              "realm of the token. I.e. all "
                                              "other realms will be removed "
                                              "from this token. Otherwise the "
                                              "realm will be added to the token.")
                            }
                        },
                   ACTION_TYPE.DELETE: {},
                   ACTION_TYPE.UNASSIGN: {},
                   ACTION_TYPE.DISABLE: {},
                   ACTION_TYPE.ENABLE: {},
                   ACTION_TYPE.SET_RANDOM_PIN: {
                       "length":
                           {"type": "int",
                            "required": True,
                            "description": _("set the PIN of the token to a random PIN of this length."),
                            "value": list(range(1,32))}
                   },
                   ACTION_TYPE.INIT:
                       {"tokentype":
                            {"type": "str",
                             "required": True,
                             "description": _("Token type to create"),
                             "value": get_token_types()
                             },
                        "user":
                            {"type": "bool",
                             "description": _("Assign token to user in "
                                              "request or to tokenowner.")},
                        "realm":
                            {"type": "str",
                             "required": False,
                             "description": _("Set the realm of the newly "
                                              "created token."),
                             "value": realm_list},
                        "dynamic_phone": {
                            "type": "bool",
                            "visibleIf": "tokentype",
                            "visibleValue": "sms",
                            "description": _("Dynamically read the mobile number "
                                             "from the user store.")
                        },
                        "dynamic_email": {
                            "type": "bool",
                            "visibleIf": "tokentype",
                            "visibleValue": "email",
                            "description": _("Dynamically read the email address "
                                             "from the user store.")
                        },
                        "smtp_identifier": {
                            "type": "str",
                            "visibleIf": "tokentype",
                            "visibleValue": "email",
                            "description": _("Use a specific SMTP server configuration for this token."),
                            "value": [server.config.identifier for server in get_smtpservers()]
                        },
                        "sms_identifier": {
                            "type": "str",
                            "visibleIf": "tokentype",
                            "visibleValue": "sms",
                            "description": _("Use a specific SMS gateway configuration for this token."),
                            "value": [gateway.identifier for gateway in get_smsgateway()]
                        },
                        "additional_params": {
                            "type": "str",
                            "description": _("A dictionary of additional init parameters.")
                        },
                        "motppin": {
                            "type": "str",
                            "visibleIf": "tokentype",
                            "visibleValue": "motp",
                            "description": _("Set the MOTP PIN of the MOTP "
                                             "token during enrollment. This "
                                             "is a required value for "
                                             "enrolling MOTP tokens.")}
                        },
                   ACTION_TYPE.SET_DESCRIPTION:
                       {"description":
                            {
                                "type": "str",
                                "description": _("The new description of the "
                                                 "token.")
                            }
                       },
                   ACTION_TYPE.SET_VALIDITY:
                       {VALIDITY.START: {
                           "type": "str",
                           "description": _("The token will be valid starting "
                                            "at the given date. Can be a fixed "
                                            "date or an offset like +10m, "
                                            "+24h, +7d.")
                       },
                        VALIDITY.END: {
                            "type": "str",
                            "description": _("The token will be valid until "
                                             "the given date. Can be a fixed "
                                             "date or an offset like +10m, "
                                             "+24h, +7d.")
                        }
                       },
                   ACTION_TYPE.SET_COUNTWINDOW:
                       {"count window":
                            {
                                # TODO: should be "int" but we do not support
                                #  this at the moment.
                                "type": "str",
                                "required": True,
                                "description": _("Set the new count window of "
                                                 "the token.")
                            }
                       },
                   ACTION_TYPE.SET_FAILCOUNTER:
                       {
                           "fail counter":
                               {
                                   "type": "str",
                                   "required": True,
                                   "description": _("Set the failcounter of "
                                                    "the token.")
                               }
                       },
                   ACTION_TYPE.CHANGE_FAILCOUNTER:
                       {
                           "change fail counter":
                               {
                                   "type": "str",
                                   "required": True,
                                   "description": _("Increase or decrease the fail counter of the token. "
                                                    "Values of +n, -n with n being an integer are accepted.")
                               }
                       },
                   ACTION_TYPE.SET_TOKENINFO:
                       {"key":
                           {
                               "type": "str",
                               "required": True,
                               "description": _("Set this tokeninfo key.")
                           },
                        "value":
                            {
                                "type": "str",
                                "description": _("Set the above key the this "
                                                 "value.")
                            }
                       },
                   ACTION_TYPE.DELETE_TOKENINFO:
                       {"key":
                            {
                                "type": "str",
                                "required": True,
                                "description": _("Delete this tokeninfo key.")
                            }
                       }
                   }
        return actions
Ejemplo n.º 25
0
def single_page_application():
    instance = request.script_root
    if instance == "/":
        instance = ""
    # The backend URL should come from the configuration of the system.
    backend_url = ""

    if current_app.config.get("PI_UI_DEACTIVATED"):
        # Do not provide the UI
        return render_template("deactivated.html")

    # The default theme. We can change this later
    theme = current_app.config.get("PI_CSS", DEFAULT_THEME)
    # Get further customizations
    customization = current_app.config.get("PI_CUSTOMIZATION",
                                           "/static/customize/")
    customization = customization.strip('/')
    # TODO: we should add the CSS into PI_CUSTOMZATION/css
    # Enrollment-Wizard:
    #    PI_CUSTOMIZATION/views/includes/token.enroll.pre.top.html
    #    PI_CUSTOMIZATION/views/includes/token.enroll.pre.bottom.html
    #    PI_CUSTOMIZATION/views/includes/token.enroll.post.top.html
    #    PI_CUSTOMIZATION/views/includes/token.enroll.post.bottom.html
    # Get the hidden external links
    external_links = current_app.config.get("PI_EXTERNAL_LINKS", True)
    # Get the logo file
    logo = current_app.config.get("PI_LOGO", "privacyIDEA1.png")
    browser_lang = request.accept_languages.best_match(["en", "de"])
    # check if login with REMOTE_USER is allowed.
    remote_user = ""
    password_reset = False
    if not hasattr(request, "all_data"):
        request.all_data = {}
    # Depending on displaying the realm dropdown, we fill realms or not.
    policy_object = PolicyClass()
    realms = ""
    client_ip = request.access_route[0] if request.access_route else \
        request.remote_addr
    realm_dropdown = policy_object.get_policies(action=ACTION.REALMDROPDOWN,
                                                scope=SCOPE.WEBUI,
                                                client=client_ip,
                                                active=True)
    if realm_dropdown:
        try:
            realm_dropdown_values = policy_object.get_action_values(
                action=ACTION.REALMDROPDOWN,
                scope=SCOPE.WEBUI,
                client=client_ip)
            # Use the realms from the policy.
            realms = ",".join(realm_dropdown_values)
        except AttributeError as ex:
            # The policy is still a boolean realm_dropdown action
            # Thus we display ALL realms
            realms = ",".join(get_realms().keys())
        if realms:
            realms = "," + realms

    try:
        if is_remote_user_allowed(request):
            remote_user = request.remote_user
        password_reset = is_password_reset()
        hsm_ready = True
    except HSMException:
        hsm_ready = False

    return render_template("index.html", instance=instance,
                           backendUrl=backend_url,
                           browser_lang=browser_lang,
                           remote_user=remote_user,
                           theme=theme,
                           password_reset=password_reset,
                           hsm_ready=hsm_ready,
                           customization=customization,
                           realms=realms,
                           external_links=external_links,
                           logo=logo)
Ejemplo n.º 26
0
    def actions(cls):
        """
        This method returns a dictionary of allowed actions and possible
        options in this handler module.

        :return: dict with actions
        """
        realm_list = get_realms().keys()
        actions = {ACTION_TYPE.SET_TOKENREALM:
                       {"realm":
                            {"type": "str",
                             "required": True,
                             "description": _("set a new realm of the token"),
                             "value": realm_list},
                        "only_realm":
                            {"type": "bool",
                             "description": _("The new realm will be the only "
                                              "realm of the token. I.e. all "
                                              "other realms will be removed "
                                              "from this token. Otherwise the "
                                              "realm will be added to the token.")
                            }
                        },
                   ACTION_TYPE.DELETE: {},
                   ACTION_TYPE.UNASSIGN: {},
                   ACTION_TYPE.DISABLE: {},
                   ACTION_TYPE.ENABLE: {},
                   ACTION_TYPE.INIT:
                       {"tokentype":
                            {"type": "str",
                             "required": True,
                             "description": _("Token type to create"),
                             "value": get_token_types()
                             },
                        "user":
                            {"type": "bool",
                             "description": _("Assign token to user in "
                                              "request or to tokenowner.")},
                        "realm":
                            {"type": "str",
                             "required": False,
                             "description": _("Set the realm of the newly "
                                              "created token."),
                             "value": realm_list},
                        "motppin": {
                            "type": "str",
                            "visibleIf": "tokentype",
                            "visibleValue": "motp",
                            "description": _("Set the MOTP PIN of the MOTP "
                                             "token during enrollment. This "
                                             "is a required value for "
                                             "enrolling MOTP tokens.")}
                        },
                   ACTION_TYPE.SET_DESCRIPTION:
                       {"description":
                            {
                                "type": "str",
                                "description": _("The new description of the "
                                                 "token.")
                            }
                       },
                   ACTION_TYPE.SET_VALIDITY:
                       {VALIDITY.START: {
                           "type": "str",
                           "description": _("The token will be valid starting "
                                            "at the given date. Can be a fixed "
                                            "date or an offset like +10m, "
                                            "+24h, +7d.")
                       },
                        VALIDITY.END: {
                            "type": "str",
                            "description": _("The token will be valid until "
                                             "the given date. Can be a fixed "
                                             "date or an offset like +10m, "
                                             "+24h, +7d.")
                        }
                       },
                   ACTION_TYPE.SET_COUNTWINDOW:
                       {"count window":
                            {
                                # TODO: should be "int" but we do not support
                                #  this at the moment.
                                "type": "str",
                                "required": True,
                                "description": _("Set the new count window of "
                                                 "the token.")
                            }
                       },
                   ACTION_TYPE.SET_TOKENINFO:
                       {"key":
                           {
                               "type": "str",
                               "required": True,
                               "description": _("Set this tokeninfo key.")
                           },
                        "value":
                            {
                                "type": "str",
                                "description": _("Set the above key the this "
                                                 "value.")
                            }
                       }
                   }
        return actions
Ejemplo n.º 27
0
    def check_condition(self, options):
        """
        Check if all conditions are met and if the action should be executed.
        The the conditions are met, we return "True"
        :return: True
        """
        g = options.get("g")
        request = options.get("request")
        response = options.get("response")
        e_handler_def = options.get("handler_def")
        if not e_handler_def:
            # options is the handler definition
            return True
        # conditions can be corresponding to the property conditions
        conditions = e_handler_def.get("conditions")
        content = self._get_response_content(response)
        user = self._get_tokenowner(request)

        serial = request.all_data.get("serial") or \
                 content.get("detail", {}).get("serial")
        tokenrealms = []
        tokenresolvers = []
        tokentype = None
        token_obj = None
        if serial:
            # We have determined the serial number from the request.
            token_obj_list = get_tokens(serial=serial)
        else:
            # We have to determine the token via the user object. But only if
            #  the user has only one token
            token_obj_list = get_tokens(user=user)
        if len(token_obj_list) == 1:
            # There is a token involved, so we determine it's resolvers and realms
            token_obj = token_obj_list[0]
            tokenrealms = token_obj.get_realms()
            tokentype = token_obj.get_tokentype()

            all_realms = get_realms()
            for tokenrealm in tokenrealms:
                resolvers = all_realms.get(tokenrealm, {}).get("resolver", {})
                tokenresolvers.extend([r.get("name") for r in resolvers])
            tokenresolvers = list(set(tokenresolvers))

        if CONDITION.CLIENT_IP in conditions:
            if g and g.client_ip:
                ip_policy = [
                    ip.strip()
                    for ip in conditions.get(CONDITION.CLIENT_IP).split(",")
                ]
                found, excluded = check_ip_in_policy(g.client_ip, ip_policy)
                if not found or excluded:
                    return False

        if CONDITION.REALM in conditions:
            if user.realm != conditions.get(CONDITION.REALM):
                return False

        if CONDITION.RESOLVER in conditions:
            if user.resolver != conditions.get(CONDITION.RESOLVER):
                return False

        if "logged_in_user" in conditions:
            # Determine the role of the user
            try:
                logged_in_user = g.logged_in_user
                user_role = logged_in_user.get("role")
            except Exception:
                # A non-logged-in-user is a User, not an admin
                user_role = ROLE.USER
            if user_role != conditions.get("logged_in_user"):
                return False

        if CONDITION.RESULT_VALUE in conditions:
            condition_value = conditions.get(CONDITION.RESULT_VALUE)
            result_value = content.get("result", {}).get("value")
            if is_true(condition_value) != is_true(result_value):
                return False

        if CONDITION.RESULT_STATUS in conditions:
            condition_value = conditions.get(CONDITION.RESULT_STATUS)
            result_status = content.get("result", {}).get("status")
            if is_true(condition_value) != is_true(result_status):
                return False

        # checking of max-failcounter state of the token
        if "token_locked" in conditions:
            if token_obj:
                locked = token_obj.get_failcount() >= \
                         token_obj.get_max_failcount()
                if (conditions.get("token_locked") in ["True", True]) != \
                      locked:
                    return False
            else:
                # check all tokens of the user, if any token is maxfail
                token_objects = get_tokens(user=user, maxfail=True)
                if not ','.join([tok.get_serial() for tok in token_objects]):
                    return False

        if CONDITION.TOKENREALM in conditions and tokenrealms:
            res = False
            for trealm in tokenrealms:
                if trealm in conditions.get(CONDITION.TOKENREALM).split(","):
                    res = True
                    break
            if not res:
                return False

        if CONDITION.TOKENRESOLVER in conditions and tokenresolvers:
            res = False
            for tres in tokenresolvers:
                if tres in conditions.get(CONDITION.TOKENRESOLVER).split(","):
                    res = True
                    break
            if not res:
                return False

        if "serial" in conditions and serial:
            serial_match = conditions.get("serial")
            if not bool(re.match(serial_match, serial)):
                return False

        if CONDITION.USER_TOKEN_NUMBER in conditions and user:
            num_tokens = get_tokens(user=user, count=True)
            if num_tokens != int(conditions.get(CONDITION.USER_TOKEN_NUMBER)):
                return False

        if CONDITION.DETAIL_ERROR_MESSAGE in conditions:
            message = content.get("detail", {}).get("error", {}).get("message")
            search_exp = conditions.get(CONDITION.DETAIL_ERROR_MESSAGE)
            m = re.search(search_exp, message)
            if not bool(m):
                return False

        if CONDITION.DETAIL_MESSAGE in conditions:
            message = content.get("detail", {}).get("message")
            search_exp = conditions.get(CONDITION.DETAIL_MESSAGE)
            m = re.search(search_exp, message)
            if not bool(m):
                return False

        # Token specific conditions
        if token_obj:
            if CONDITION.TOKENTYPE in conditions:
                if tokentype not in conditions.get(
                        CONDITION.TOKENTYPE).split(","):
                    return False

            if CONDITION.TOKEN_HAS_OWNER in conditions:
                uid = token_obj.get_user_id()
                check = conditions.get(CONDITION.TOKEN_HAS_OWNER)
                if uid and check in ["True", True]:
                    res = True
                elif not uid and check in ["False", False]:
                    res = True
                else:
                    log.debug("Condition token_has_owner for token {0!r} "
                              "not fulfilled.".format(token_obj))
                    return False

            if CONDITION.TOKEN_IS_ORPHANED in conditions:
                orphaned = token_obj.is_orphaned()
                check = conditions.get(CONDITION.TOKEN_IS_ORPHANED)
                if orphaned and check in ["True", True]:
                    res = True
                elif not orphaned and check in ["False", False]:
                    res = True
                else:
                    log.debug(
                        "Condition token_is_orphaned for token {0!r} not "
                        "fulfilled.".format(token_obj))
                    return False

            if CONDITION.TOKEN_VALIDITY_PERIOD in conditions:
                valid = token_obj.check_validity_period()
                if (conditions.get(CONDITION.TOKEN_VALIDITY_PERIOD)
                        in ["True", True]) != valid:
                    return False

            if CONDITION.OTP_COUNTER in conditions:
                cond = conditions.get(CONDITION.OTP_COUNTER)
                if not compare_condition(cond, token_obj.token.count):
                    return False

            if CONDITION.LAST_AUTH in conditions:
                if token_obj.check_last_auth_newer(
                        conditions.get(CONDITION.LAST_AUTH)):
                    return False

            if CONDITION.COUNT_AUTH in conditions:
                count = token_obj.get_count_auth()
                cond = conditions.get(CONDITION.COUNT_AUTH)
                if not compare_condition(cond, count):
                    return False

            if CONDITION.COUNT_AUTH_SUCCESS in conditions:
                count = token_obj.get_count_auth_success()
                cond = conditions.get(CONDITION.COUNT_AUTH_SUCCESS)
                if not compare_condition(cond, count):
                    return False

            if CONDITION.COUNT_AUTH_FAIL in conditions:
                count = token_obj.get_count_auth()
                c_success = token_obj.get_count_auth_success()
                c_fail = count - c_success
                cond = conditions.get(CONDITION.COUNT_AUTH_FAIL)
                if not compare_condition(cond, c_fail):
                    return False

            if CONDITION.TOKENINFO in conditions:
                cond = conditions.get(CONDITION.TOKENINFO)
                # replace {now} in condition
                cond, td = parse_time_offset_from_now(cond)
                s_now = (datetime.datetime.now(tzlocal()) +
                         td).strftime(DATE_FORMAT)
                cond = cond.format(now=s_now)
                if len(cond.split("==")) == 2:
                    key, value = [x.strip() for x in cond.split("==")]
                    if not compare_value_value(token_obj.get_tokeninfo(key),
                                               "==", value):
                        return False
                elif len(cond.split(">")) == 2:
                    key, value = [x.strip() for x in cond.split(">")]
                    if not compare_value_value(token_obj.get_tokeninfo(key),
                                               ">", value):
                        return False
                elif len(cond.split("<")) == 2:
                    key, value = [x.strip() for x in cond.split("<")]
                    if not compare_value_value(token_obj.get_tokeninfo(key),
                                               "<", value):
                        return False
                else:
                    # There is a condition, but we do not know it!
                    log.warning("Misconfiguration in your tokeninfo "
                                "condition: {0!s}".format(cond))
                    return False

        return True
Ejemplo n.º 28
0
    def conditions(cls):
        """
        The UserNotification can filter for conditions like
        * type of logged in user and
        * successful or failed value.success

        allowed types are str, multi, text, regexp

        :return: dict
        """
        realms = get_realms()
        cond = {
            "realm": {
                "type": "str",
                "desc":
                _("The user realm, for which this event should apply."),
                "value": realms.keys()
            },
            "tokenrealm": {
                "type": "multi",
                "desc": _("The token realm, for which this event should "
                          "apply."),
                "value": [{
                    "name": r
                } for r in realms.keys()]
            },
            CONDITION.TOKENTYPE: {
                "type": "multi",
                "desc": _("The type of the token."),
                "value": [{
                    "name": r
                } for r in get_token_types()]
            },
            "logged_in_user": {
                "type": "str",
                "desc": _("The logged in user is of the following type."),
                "value": (ROLE.ADMIN, ROLE.USER)
            },
            "result_value": {
                "type":
                "str",
                "desc":
                _("The result.value within the response is "
                  "True or False."),
                "value": ("True", "False")
            },
            "token_locked": {
                "type":
                "str",
                "desc":
                _("Check if the max failcounter of the token is "
                  "reached."),
                "value": ("True", "False")
            },
            CONDITION.TOKEN_HAS_OWNER: {
                "type": "str",
                "desc": _("The token has a user assigned."),
                "value": ("True", "False")
            },
            CONDITION.TOKEN_IS_ORPHANED: {
                "type":
                "str",
                "desc":
                _("The token has a user assigned, but the user does "
                  "not exist in the userstore anymore."),
                "value": ("True", "False")
            },
            "serial": {
                "type":
                "regexp",
                "desc":
                _("Action is triggered, if the serial matches this "
                  "regular expression.")
            },
            CONDITION.USER_TOKEN_NUMBER: {
                "type":
                "str",
                "desc":
                _("Action is triggered, if the user has this number "
                  "of tokens assigned.")
            },
            CONDITION.OTP_COUNTER: {
                "type":
                "str",
                "desc":
                _("Action is triggered, if the counter of the token "
                  "equals this setting.")
            }
        }
        return cond
Ejemplo n.º 29
0
    def actions(cls):
        """
        This method returns a dictionary of allowed actions and possible
        options in this handler module.

        :return: dict with actions
        """
        realm_list = get_realms().keys()
        actions = {ACTION_TYPE.SET_TOKENREALM:
                       {"realm":
                            {"type": "str",
                             "required": True,
                             "description": _("set a new realm of the token"),
                             "value": realm_list},
                        "only_realm":
                            {"type": "bool",
                             "description": _("The new realm will be the only "
                                              "realm of the token. I.e. all "
                                              "other realms will be removed "
                                              "from this token. Otherwise the "
                                              "realm will be added to the token.")
                            }
                        },
                   ACTION_TYPE.DELETE: {},
                   ACTION_TYPE.UNASSIGN: {},
                   ACTION_TYPE.DISABLE: {},
                   ACTION_TYPE.ENABLE: {},
                   ACTION_TYPE.INIT:
                       {"tokentype":
                            {"type": "str",
                             "required": True,
                             "description": _("Token type to create"),
                             "value": get_token_types()
                             },
                        "user":
                            {"type": "bool",
                             "description": _("Assign token to user in "
                                              "request or tokenowner.")},
                        "realm":
                            {"type": "str",
                             "required": False,
                             "description": _("Set the realm of the newly "
                                              "created token."),
                             "value": realm_list},
                        },
                   ACTION_TYPE.SET_DESCRIPTION:
                       {"description":
                            {
                                "type": "str",
                                "description": _("The new description of the "
                                                 "token.")
                            }
                       },
                   ACTION_TYPE.SET_VALIDITY:
                       {VALIDITY.START: {
                           "type": "str",
                           "description": _("The token will be valid starting "
                                            "at the given date. Can be a fixed "
                                            "date or an offset like +10m, "
                                            "+24h, +7d.")
                       },
                        VALIDITY.END: {
                            "type": "str",
                            "description": _("The token will be valid until "
                                             "the given date. Can be a fixed "
                                             "date or an offset like +10m, "
                                             "+24h, +7d.")
                        }

                       }
                   }
        return actions