def test_02_get_resolver_list(self): reso_list = get_resolver_list(filter_resolver_name=self.resolvername1) self.assertTrue(self.resolvername1 in reso_list, reso_list) self.assertTrue(self.resolvername2 not in reso_list, reso_list) reso_list = get_resolver_list(editable=True) self.assertTrue(len(reso_list) == 0)
def test_13_update_resolver(self): ldap3mock.setLDAPDirectory(LDAPDirectory) # -------------------------------- # First we create an LDAP resolver rid = save_resolver( { "resolver": "myLDAPres", "type": "ldapresolver", "LDAPURI": "ldap://localhost", "LDAPBASE": "o=test", "BINDDN": "cn=manager,ou=example,o=test", "BINDPW": "ldaptest", "LOGINNAMEATTRIBUTE": "cn", "LDAPSEARCHFILTER": "(cn=*)", "LDAPFILTER": "(&(cn=%s))", "USERINFO": '{ "username": "******",' '"phone" : "telephoneNumber", ' '"mobile" : "mobile"' ', "email" : "mail", ' '"surname" : "sn", ' '"givenname" : "givenName" }', "UIDTYPE": "DN", } ) self.assertTrue(rid > 0, rid) reso_list = get_resolver_list() self.assertTrue("myLDAPres" in reso_list, reso_list) ui = ResolverConfig.query.filter(ResolverConfig.Key == "USERINFO").first().Value # Check that the email is contained in the UI self.assertTrue("email" in ui, ui) # -------------------------------- # Then we update the LDAP resolver rid = save_resolver( { "resolver": "myLDAPres", "type": "ldapresolver", "LDAPURI": "ldap://localhost", "LDAPBASE": "o=test", "BINDDN": "cn=manager,ou=example,o=test", "BINDPW": "ldaptest", "LOGINNAMEATTRIBUTE": "cn", "LDAPSEARCHFILTER": "(cn=*)", "LDAPFILTER": "(&(cn=%s))", "USERINFO": '{ "username": "******",' '"phone" : "telephoneNumber", ' '"surname" : "sn", ' '"givenname" : "givenName" }', "UIDTYPE": "DN", } ) self.assertTrue(rid > 0, rid) reso_list = get_resolver_list(filter_resolver_name="myLDAPres") # TODO check the data ui = ResolverConfig.query.filter(ResolverConfig.Key == "USERINFO").first().Value # Check that the email is NOT contained in the UI self.assertTrue("email" not in ui, ui)
def test_01_create_resolver(self): rid = save_resolver( { "resolver": self.resolvername1, "type": "passwdresolver", "fileName": "/etc/passwd", "type.fileName": "string", "desc.fileName": "The name of the file", } ) self.assertTrue(rid > 0, rid) # description with missing main key params = {"resolver": "reso2", "type": "passwdresolver", "type.fileName": "string"} self.assertRaises(Exception, save_resolver, params) # type with missing main key params = {"resolver": "reso2", "type": "passwdresolver", "desc.fileName": "The file name"} self.assertRaises(Exception, save_resolver, params) # not allowed resolver name params = {"resolver": "res with blank", "type": "passwdresolver"} self.assertRaises(Exception, save_resolver, params) # unknown type params = {"resolver": "validname", "type": "unknown_type"} self.assertRaises(Exception, save_resolver, params) # same name with different type params = {"resolver": self.resolvername1, "type": "ldapresolver", "fileName": "/etc/secrets"} self.assertRaises(Exception, save_resolver, params) # similar name with different type params = {"resolver": "Resolver1", "type": "ldapresolver", "fileName": "/etc/secrets"} self.assertRaises(Exception, save_resolver, params) # check that the resolver was successfully created reso_list = get_resolver_list() self.assertTrue(self.resolvername1 in reso_list) # test error: type without data params = {"resolver": self.resolvername2, "type": "ldapresolver", "type.BindPW": "topsecret"} self.assertRaises(Exception, save_resolver, params) # test error: description without data params = {"resolver": self.resolvername2, "type": "ldapresolver", "desc.BindPW": "something else"} self.assertRaises(Exception, save_resolver, params) # key not supported by the resolver # The resolver is created anyway params = {"resolver": self.resolvername2, "type": "passwdresolver", "UnknownKey": "something else"} rid = save_resolver(params) self.assertTrue(rid > 0) # check that the resolver was successfully created reso_list = get_resolver_list() self.assertTrue(self.resolvername2 in reso_list)
def test_10_delete_resolver(self): # get the list of the resolvers reso_list = get_resolver_list() self.assertTrue(self.resolvername1 in reso_list, reso_list) self.assertTrue(self.resolvername2 in reso_list, reso_list) # delete the resolvers delete_resolver(self.resolvername1) delete_resolver(self.resolvername2) # check list empty reso_list = get_resolver_list() self.assertTrue(self.resolvername1 not in reso_list, reso_list) self.assertTrue(self.resolvername2 not in reso_list, reso_list) self.assertTrue(len(reso_list) == 0, reso_list)
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))
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))
def list(): """ list the available resolvers and the type """ from privacyidea.lib.resolver import get_resolver_list resolver_list = get_resolver_list() for name, resolver in resolver_list.iteritems(): print "%16s - (%s)" % (name, resolver.get("type"))
def is_password_reset(g): """ Check if password reset is allowed. We need to check, if a user policy with password_reset exists AND if an editable resolver exists. Otherwise password_reset does not make any sense. :return: True or False """ rlist = get_resolver_list(editable=True) log.debug("Number of editable resolvers: {0!s}".format(len(rlist))) pwreset = Match.generic( g, scope=SCOPE.USER, action=ACTION.PASSWORDRESET).allowed(write_to_audit_log=False) log.debug("Password reset allowed via policies: {0!s}".format(pwreset)) return bool(rlist and pwreset)
def is_password_reset(): """ Check if password reset is allowed. We need to check, if a user policy with password_reset exists AND if an editable resolver exists. Otherwise password_reset does not make any sense. :return: True or False """ rlist = get_resolver_list(editable=True) log.debug("Number of editable resolvers: %s" % len(rlist)) Policy = PolicyClass() policy_at_all = Policy.get_policies(scope=SCOPE.USER, active=True) log.debug("Policy at all: %s" % policy_at_all) policy_reset_pw = Policy.get_policies(scope=SCOPE.USER, action=ACTION.PASSWORDRESET) log.debug("Password reset policy: %s" % policy_reset_pw) pwreset = (policy_at_all and policy_reset_pw) or not policy_at_all log.debug("Password reset allowed via policy: %s" % pwreset) return bool(rlist and pwreset)
def is_password_reset(): """ Check if password reset is allowed. We need to check, if a user policy with password_reset exists AND if an editable resolver exists. Otherwise password_reset does not make any sense. :return: True or False """ rlist = get_resolver_list(editable=True) log.debug("Number of editable resolvers: {0!s}".format(len(rlist))) Policy = PolicyClass() policy_at_all = Policy.get_policies(scope=SCOPE.USER, active=True) log.debug("Policy at all: {0!s}".format(policy_at_all)) policy_reset_pw = Policy.get_policies(scope=SCOPE.USER, action=ACTION.PASSWORDRESET) log.debug("Password reset policy: {0!s}".format(policy_reset_pw)) pwreset = (policy_at_all and policy_reset_pw) or not policy_at_all log.debug("Password reset allowed via policy: {0!s}".format(pwreset)) return bool(rlist and pwreset)
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)
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.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
def test_13_update_resolver(self): ldap3mock.setLDAPDirectory(LDAPDirectory) # -------------------------------- # First we create an LDAP resolver rid = save_resolver({ "resolver": "myLDAPres", "type": "ldapresolver", 'LDAPURI': 'ldap://localhost', 'LDAPBASE': 'o=test', 'BINDDN': 'cn=manager,ou=example,o=test', 'BINDPW': 'ldaptest', 'LOGINNAMEATTRIBUTE': 'cn', 'LDAPSEARCHFILTER': '(cn=*)', 'LDAPFILTER': '(&(cn=%s))', 'USERINFO': '{ "username": "******",' '"phone" : "telephoneNumber", ' '"mobile" : "mobile"' ', "email" : "mail", ' '"surname" : "sn", ' '"givenname" : "givenName" }', 'UIDTYPE': 'DN' }) self.assertTrue(rid > 0, rid) reso_list = get_resolver_list() self.assertTrue("myLDAPres" in reso_list, reso_list) ui = ResolverConfig.query.filter( ResolverConfig.Key == 'USERINFO').first().Value # Check that the email is contained in the UI self.assertTrue("email" in ui, ui) # -------------------------------- # Then we update the LDAP resolver rid = save_resolver({ "resolver": "myLDAPres", "type": "ldapresolver", 'LDAPURI': 'ldap://localhost', 'LDAPBASE': 'o=test', 'BINDDN': 'cn=manager,ou=example,o=test', 'BINDPW': 'ldaptest', 'LOGINNAMEATTRIBUTE': 'cn', 'LDAPSEARCHFILTER': '(cn=*)', 'LDAPFILTER': '(&(cn=%s))', 'USERINFO': '{ "username": "******",' '"phone" : "telephoneNumber", ' '"surname" : "sn", ' '"givenname" : "givenName" }', 'UIDTYPE': 'DN' }) self.assertTrue(rid > 0, rid) reso_list = get_resolver_list(filter_resolver_name="myLDAPres") # TODO check the data ui = ResolverConfig.query.filter( ResolverConfig.Key == 'USERINFO').first().Value # Check that the email is NOT contained in the UI self.assertTrue("email" not in ui, ui)
def test_04_if_a_resolver_exists(self): reso_list = get_resolver_list() self.assertTrue(self.resolvername1 in reso_list) self.assertTrue("some other" not in reso_list)
def test_01_create_resolver(self): rid = save_resolver({ "resolver": self.resolvername1, "type": "passwdresolver", "fileName": "/etc/passwd", "type.fileName": "string", "desc.fileName": "The name of the file" }) self.assertTrue(rid > 0, rid) # description with missing main key params = { "resolver": "reso2", "type": "passwdresolver", "type.fileName": "string" } self.assertRaises(Exception, save_resolver, params) # type with missing main key params = { "resolver": "reso2", "type": "passwdresolver", "desc.fileName": "The file name" } self.assertRaises(Exception, save_resolver, params) # not allowed resolver name params = {"resolver": "res with blank", "type": "passwdresolver"} self.assertRaises(Exception, save_resolver, params) # unknown type params = {"resolver": "validname", "type": "unknown_type"} self.assertRaises(Exception, save_resolver, params) # same name with different type params = { "resolver": self.resolvername1, "type": "ldapresolver", "fileName": "/etc/secrets" } self.assertRaises(Exception, save_resolver, params) # similar name with different type params = { "resolver": "Resolver1", "type": "ldapresolver", "fileName": "/etc/secrets" } self.assertRaises(Exception, save_resolver, params) # check that the resolver was successfully created reso_list = get_resolver_list() self.assertTrue(self.resolvername1 in reso_list) # test error: type without data params = { "resolver": self.resolvername2, "type": "ldapresolver", "type.BindPW": "topsecret" } self.assertRaises(Exception, save_resolver, params) # test error: description without data params = { "resolver": self.resolvername2, "type": "ldapresolver", "desc.BindPW": "something else" } self.assertRaises(Exception, save_resolver, params) # key not supported by the resolver # The resolver is created anyway params = { "resolver": self.resolvername2, "type": "passwdresolver", "UnknownKey": "something else" } rid = save_resolver(params) self.assertTrue(rid > 0) # check that the resolver was successfully created reso_list = get_resolver_list() self.assertTrue(self.resolvername2 in reso_list)
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)
def test_02_get_resolver_list(self): reso_list = get_resolver_list(filter_resolver_name=self.resolvername1) self.assertTrue(self.resolvername1 in reso_list, reso_list) self.assertTrue(self.resolvername2 not in reso_list, reso_list)