def test_17_auth_timelimit_success(self): user = User("timelimituser", realm=self.realm2) pin = "spass" # create a token token = init_token({"type": "spass", "pin": pin}, user=user) # set policy for timelimit set_policy(name="pol_time1", scope=SCOPE.AUTHZ, action="%s=2/20s" % ACTION.AUTHMAXSUCCESS) for i in [1, 2]: with self.app.test_request_context('/validate/check', method='POST', data={"user": "******", "realm": self.realm2, "pass": pin}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data).get("result") self.assertEqual(result.get("value"), True) with self.app.test_request_context('/validate/check', method='POST', data={"user": "******", "realm": self.realm2, "pass": pin}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data).get("result") self.assertEqual(result.get("value"), False) delete_policy("pol_time1") remove_token(token.token.serial)
def test_18_auth_timelimit_fail(self): user = User("timelimituser", realm=self.realm2) pin = "spass" # create a token token = init_token({"type": "spass", "pin": pin}, user=user) # set policy for timelimit set_policy(name="pol_time1", scope=SCOPE.AUTHZ, action="%s=2/20s" % ACTION.AUTHMAXFAIL) for i in [1, 2]: with self.app.test_request_context( "/validate/check", method="POST", data={"user": "******", "realm": self.realm2, "pass": "******"}, ): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data).get("result") self.assertEqual(result.get("value"), False) # Now we do the correct authentication, but # as already two authentications failed, this will fail, too with self.app.test_request_context( "/validate/check", method="POST", data={"user": "******", "realm": self.realm2, "pass": pin} ): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data).get("result") self.assertEqual(result.get("value"), False) details = json.loads(res.data).get("detail") self.assertEqual(details.get("message"), "Only 2 failed authentications per 0:00:20") delete_policy("pol_time1") remove_token(token.token.serial)
def test_16_init_token_defaults(self): g.logged_in_user = {"username": "******", "role": "user"} builder = EnvironBuilder(method='POST', data={'type': "totp", "genkey": "1"}, headers={}) env = builder.get_environ() # Set the remote address so that we can filter for it env["REMOTE_ADDR"] = "10.0.0.1" g.client_ip = env["REMOTE_ADDR"] req = Request(env) # Set a policy that defines the default totp settings set_policy(name="pol1", scope=SCOPE.USER, action="totp_otplen=8,totp_hashlib=sha256,totp_timestep=60") g.policy_object = PolicyClass() # request, that matches the policy req.all_data = { "type": "totp", "genkey": "1"} init_token_defaults(req) # Check, if the token defaults were added self.assertEqual(req.all_data.get("totp.hashlib"), "sha256") self.assertEqual(req.all_data.get("otplen"), "8") self.assertEqual(req.all_data.get("timeStep"), "60") # finally delete policy delete_policy("pol1")
def test_14_required_email(self): g.logged_in_user = {"username": "******", "role": "admin"} builder = EnvironBuilder(method='POST', data={'serial': "OATH123456"}, headers={}) env = builder.get_environ() # Set the remote address so that we can filter for it env["REMOTE_ADDR"] = "10.0.0.1" req = Request(env) # Set a mangle policy to change the username # and only use the last 4 characters of the username set_policy(name="email1", scope=SCOPE.REGISTER, action="%s=/.*@mydomain\..*" % ACTION.REQUIREDEMAIL) g.policy_object = PolicyClass() # request, that matches the policy req.all_data = {"email": "*****@*****.**"} # This emails is allowed r = required_email(req) self.assertTrue(r) # This email is not allowed req.all_data = {"email": "*****@*****.**"} # This emails is allowed self.assertRaises(RegistrationError, required_email, req) delete_policy("email1") g.policy_object = PolicyClass() # Without a policy, this email can register req.all_data = {"email": "*****@*****.**"} # This emails is allowed r = required_email(req) self.assertTrue(r)
def test_01_otppin(self): my_user = User("cornelius", realm="r1") set_policy(name="pol1", scope=SCOPE.AUTH, action="%s=%s" % (ACTION.OTPPIN, ACTIONVALUE.NONE)) g = FakeFlaskG() P = PolicyClass() g.policy_object = P options = {"g": g} # NONE with empty PIN -> success r = auth_otppin(self.fake_check_otp, None, "", options=options, user=my_user) self.assertTrue(r) # NONE with empty PIN -> success, even if the authentication is done # for a serial and not a user, since the policy holds for all realms token = init_token({"type": "HOTP", "otpkey": "1234"}) r = auth_otppin(self.fake_check_otp, token, "", options=options, user=None) self.assertTrue(r) # NONE with some pin -> fail r = auth_otppin(self.fake_check_otp, None, "some pin", options=options, user=my_user) self.assertFalse(r) delete_policy("pol1") set_policy(name="pol1", scope=SCOPE.AUTH, action="%s=%s" % (ACTION.OTPPIN, ACTIONVALUE.TOKENPIN)) g = FakeFlaskG() P = PolicyClass() g.policy_object = P options = {"g": g} r = auth_otppin(self.fake_check_otp, None, "FAKE", options=options, user=my_user) self.assertTrue(r) r = auth_otppin(self.fake_check_otp, None, "Wrong Pin", options=options, user=my_user) self.assertFalse(r) delete_policy("pol1")
def test_05_user_has_no_tokens(self): user = User("cornelius", realm="r1") passw = "test" options = {} # A user with no tokens will fail to authenticate rv = auth_user_has_no_token(check_user_pass, user, passw, options) self.assertFalse(rv[0]) self.assertEqual(rv[1].get("message"), "The user has no tokens assigned") # Now we set a policy, that a non existing user will authenticate set_policy(name="pol1", scope=SCOPE.AUTH, action=ACTION.PASSNOTOKEN) g = FakeFlaskG() g.policy_object = PolicyClass() g.audit_object = FakeAudit() options = {"g": g} rv = auth_user_has_no_token(check_user_pass, user, passw, options=options) self.assertTrue(rv[0]) self.assertEqual(rv[1].get("message"), u"user has no token, accepted due to " u"'pol1'") delete_policy("pol1")
def test_07_client_policies(self): delete_policy(name="pol2a") set_policy(name="pol1", scope="s", client="172.16.0.3, 172.16.0.4/24") set_policy(name="pol2", scope="s", client="192.168.0.0/16, " "-192.168.1.1") set_policy(name="pol3", scope="s", client="10.0.0.1, 10.0.0.2, " "10.0.0.3") set_policy(name="pol4", scope="s") # One policy with matching client, one without any clients P = PolicyClass() p = P.get_policies(client="10.0.0.1") self.assertTrue(_check_policy_name("pol3", p), p) self.assertTrue(_check_policy_name("pol4", p), p) self.assertTrue(len(p) == 2, p) # client matches pol4 and pol2 p = P.get_policies(client="192.168.2.3") self.assertTrue(_check_policy_name("pol2", p), p) self.assertTrue(_check_policy_name("pol4", p), p) self.assertTrue(len(p) == 2, p) # client only matches pol4, since it is excluded in pol2 p = P.get_policies(client="192.168.1.1") self.assertTrue(_check_policy_name("pol4", p), p) self.assertTrue(len(p) == 1, p)
def test_04a_user_does_not_exist_without_resolver(self): user = User("MisterX", realm=self.realm1) passw = "somePW" # Now we set a policy, that a non existing user will authenticate set_policy(name="pol1", scope=SCOPE.AUTH, action="{0}, {1}, {2}, {3}=none".format( ACTION.RESETALLTOKENS, ACTION.PASSNOUSER, ACTION.PASSNOTOKEN, ACTION.OTPPIN ), realm=self.realm1) g = FakeFlaskG() g.policy_object = PolicyClass() g.audit_object = FakeAudit() options = {"g": g} rv = auth_user_does_not_exist(check_user_pass, user, passw, options=options) self.assertTrue(rv[0]) self.assertEqual(rv[1].get("message"), u"user does not exist, accepted due " u"to 'pol1'") delete_policy("pol1")
def test_08_encrypt_pin(self): g.logged_in_user = {"username": "******", "role": "admin"} builder = EnvironBuilder(method='POST', data={'serial': "OATH123456"}, headers={}) env = builder.get_environ() # Set the remote address so that we can filter for it env["REMOTE_ADDR"] = "10.0.0.1" req = Request(env) # Set a policy that defines the PIN to be encrypted set_policy(name="pol1", scope=SCOPE.ENROLL, action=ACTION.ENCRYPTPIN) g.policy_object = PolicyClass() # request, that matches the policy req.all_data = { "user": "******", "realm": "home"} encrypt_pin(req) # Check, if the tokenlabel was added self.assertEqual(req.all_data.get("encryptpin"), "True") # finally delete policy delete_policy("pol1")
def test_13_remote_user(self): g.logged_in_user = {"username": "******", "role": "admin"} builder = EnvironBuilder(method='POST', data={'serial': "OATH123456"}, headers={}) env = builder.get_environ() # Set the remote address so that we can filter for it env["REMOTE_ADDR"] = "10.0.0.1" env["REMOTE_USER"] = "******" req = Request(env) # A user, for whom the login via REMOTE_USER is allowed. set_policy(name="ruser", scope=SCOPE.WEBUI, action="%s=%s" % (ACTION.REMOTE_USER, REMOTE_USER.ACTIVE)) g.policy_object = PolicyClass() r = is_remote_user_allowed(req) self.assertEqual(r, [REMOTE_USER.ACTIVE]) # Login for the REMOTE_USER is not allowed. # Only allowed for user "super", but REMOTE_USER=admin set_policy(name="ruser", scope=SCOPE.WEBUI, action="%s=%s" % (ACTION.REMOTE_USER, REMOTE_USER.ACTIVE), user="******") g.policy_object = PolicyClass() r = is_remote_user_allowed(req) self.assertEqual(r, []) delete_policy("ruser")
def test_03_otppin_for_serial(self): # now create a policy with userstore PW set_policy(name="pol1", scope=SCOPE.AUTH, action="%s=%s" % (ACTION.OTPPIN, ACTIONVALUE.USERSTORE)) g = FakeFlaskG() P = PolicyClass() g.policy_object = P options = {"g": g, "serial": "T001"} # create a token and assign to user cornelius token = init_token({"serial": "T001", "type": "hotp", "genkey": 1}, user=User("cornelius", realm="r1")) self.assertTrue(token) # Wrong password # Not identified by the user but by the token owner r = auth_otppin(self.fake_check_otp, token, "WrongPW", options=options, user=None) self.assertFalse(r) # Correct password from userstore: "test" # Not identified by the user but by the token owner r = auth_otppin(self.fake_check_otp, token, "test", options=options, user=None) self.assertTrue(r) delete_policy("pol1") remove_token("T001")
def test_02_userstore_password(self): # create a realm, where cornelius has a password test rid = save_resolver({"resolver": "myreso", "type": "passwdresolver", "fileName": PWFILE2}) self.assertTrue(rid > 0, rid) (added, failed) = set_realm("r1", ["myreso"]) self.assertTrue(len(failed) == 0) self.assertTrue(len(added) == 1) # now create a policy with userstore PW set_policy(name="pol1", scope=SCOPE.AUTH, action="%s=%s" % (ACTION.OTPPIN, ACTIONVALUE.USERSTORE)) g = FakeFlaskG() P = PolicyClass() g.policy_object = P options = {"g": g} # Wrong password r = auth_otppin(self.fake_check_otp, None, "WrongPW", options=options, user=User("cornelius", realm="r1")) self.assertFalse(r) # Correct password from userstore: "test" r = auth_otppin(self.fake_check_otp, None, "test", options=options, user=User("cornelius", realm="r1")) self.assertTrue(r) delete_policy("pol1")
def test_09_challenge_response_allowed(self): user = User("cornelius", realm="r1") pin = "test" g = FakeFlaskG() g.policy_object = PolicyClass() options = {"g": g} token = init_token({"type": "hotp", "otpkey": "1234", "pin": pin}, user=user) # With no policy, it will be no chal resp rv = token.is_challenge_request(pin, user=user, options=options) self.assertEqual(rv, False) # Now we set a policy with several tokentypes set_policy(name="pol_chal_resp_1", scope=SCOPE.AUTH, action="%s=hotp tiqr totp" % ACTION.CHALLENGERESPONSE) set_policy(name="pol_chal_resp_2", scope=SCOPE.AUTH, action="%s=hotp motp" % ACTION.CHALLENGERESPONSE) g = FakeFlaskG() g.policy_object = PolicyClass() options = {"g": g} rv = token.is_challenge_request(pin, user=user, options=options) self.assertEqual(rv, True) delete_policy("pol_chal_resp_1")
def test_01a_admin_realms(self): admin1 = {"username": "******", "role": "admin", "realm": "realm1"} admin2 = {"username": "******", "role": "admin", "realm": "realm2"} set_policy(name="pol", scope=SCOPE.ADMIN, action="*", adminrealm="realm1") g.policy_object = PolicyClass() builder = EnvironBuilder(method='POST', data={'serial': "OATH123456"}, headers={}) env = builder.get_environ() # Set the remote address so that we can filter for it env["REMOTE_ADDR"] = "10.0.0.1" req = Request(env) req.all_data = {} # admin1 is allowed to do everything g.logged_in_user = admin1 r = check_base_action(req, action="delete") self.assertTrue(r) # admin2 is not allowed. g.logged_in_user = admin2 self.assertRaises(PolicyError, check_base_action, req, action="delete") delete_policy("pol")
def test_19_validate_passthru(self): # user passthru, realm: self.realm2, passwd: pthru set_policy(name="pthru", scope=SCOPE.AUTH, action=ACTION.PASSTHRU) # Passthru with GET request with self.app.test_request_context( '/validate/check', method='GET', query_string=urlencode({"user": "******", "realm": self.realm2, "pass": "******"})): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data).get("result") self.assertEqual(result.get("value"), True) # Passthru with POST Request with self.app.test_request_context('/validate/check', method='POST', data={"user": "******", "realm": self.realm2, "pass": "******"}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data).get("result") self.assertEqual(result.get("value"), True) delete_policy("pthru")
def test_06_set_tokenlabel(self): g.logged_in_user = {"username": "******", "role": "admin"} builder = EnvironBuilder(method='POST', data={'serial': "OATH123456"}, headers={}) env = builder.get_environ() # Set the remote address so that we can filter for it env["REMOTE_ADDR"] = "10.0.0.1" req = Request(env) # Set a policy that defines the tokenlabel set_policy(name="pol1", scope=SCOPE.ENROLL, action="%s=%s" % (ACTION.TOKENLABEL, "<u>@<r>")) set_policy(name="pol2", scope=SCOPE.ENROLL, action="%s=%s" % (ACTION.TOKENISSUER, "myPI")) g.policy_object = PolicyClass() # request, that matches the policy req.all_data = { "user": "******", "realm": "home"} init_tokenlabel(req) # Check, if the tokenlabel was added self.assertEqual(req.all_data.get("tokenlabel"), "<u>@<r>") # Check, if the tokenissuer was added self.assertEqual(req.all_data.get("tokenissuer"), "myPI") # finally delete policy delete_policy("pol1") delete_policy("pol2")
def test_03_check_token_upload(self): g.logged_in_user = {"username": "******", "role": "admin"} builder = EnvironBuilder(method='POST', data={'serial': "OATH123456"}, headers={}) env = builder.get_environ() # Set the remote address so that we can filter for it env["REMOTE_ADDR"] = "10.0.0.1" req = Request(env) req.all_data = {"filename": "token.xml"} # Set a policy, that does allow the action set_policy(name="pol1", scope=SCOPE.ADMIN, action="enrollTOTP, enrollHOTP, %s" % ACTION.IMPORT, client="10.0.0.0/8") g.policy_object = PolicyClass() # Try to import tokens r = check_token_upload(req) self.assertTrue(r) # The admin can not upload from another IP address # An exception is raised env["REMOTE_ADDR"] = "192.168.0.1" req = Request(env) req.all_data = {"filename": "token.xml"} self.assertRaises(PolicyError, check_token_upload, req) # finally delete policy delete_policy("pol1")
def test_22_validate_locked(self): # test a user with two tokens # One token is locked/revoked. # But the user must be able to login with the 2nd token # user lockeduser, realm: self.realm2 # enroll two tokens user = "******" set_policy(name="locked", scope=SCOPE.AUTH, action="{0!s}={1!s}".format(ACTION.OTPPIN, "tokenpin")) r = init_token({"type": "spass", "serial": "spass1l", "pin": "locked"}, user=User(user, self.realm2)) r = init_token({"type": "spass", "serial": "spass2l", "pin": "locked"}, user=User(user, self.realm2)) # disable first token r = revoke_token("spass1l") self.assertEqual(r, True) # Check that the user still can authenticate with the 2nd token with self.app.test_request_context('/validate/check', method='POST', data={"user": user, "realm": self.realm2, "pass": "******"}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data).get("result") self.assertEqual(result.get("value"), True) remove_token("spass1l") remove_token("spass2l") delete_policy("locked")
def test_07_set_random_pin(self): g.logged_in_user = {"username": "******", "role": "admin"} builder = EnvironBuilder(method='POST', data={'serial': "OATH123456"}, headers={}) env = builder.get_environ() # Set the remote address so that we can filter for it env["REMOTE_ADDR"] = "10.0.0.1" req = Request(env) # Set a policy that defines the tokenlabel set_policy(name="pol1", scope=SCOPE.ENROLL, action="%s=%s" % (ACTION.OTPPINRANDOM, "12")) set_policy(name="pinhandling", scope=SCOPE.ENROLL, action="%s=privacyidea.lib.pinhandling.base.PinHandler" % ACTION.PINHANDLING) g.policy_object = PolicyClass() # request, that matches the policy req.all_data = { "user": "******", "realm": "home"} init_random_pin(req) # Check, if the tokenlabel was added self.assertEqual(len(req.all_data.get("pin")), 12) # finally delete policy delete_policy("pol1") delete_policy("pinhandling")
def test_06_passthru(self): user = User("cornelius", realm="r1") passw = "test" options = {} # A user with no tokens will fail to authenticate self.assertEqual(get_tokens(user=user, count=True), 0) rv = auth_user_passthru(check_user_pass, user, passw, options) self.assertFalse(rv[0]) self.assertEqual(rv[1].get("message"), "The user has no tokens assigned") # Now we set a PASSTHRU policy, so that the user may authenticate # against his userstore set_policy(name="pol1", scope=SCOPE.AUTH, action=ACTION.PASSTHRU) g = FakeFlaskG() g.policy_object = PolicyClass() options = {"g": g} rv = auth_user_passthru(check_user_pass, user, passw, options=options) self.assertTrue(rv[0]) self.assertEqual( rv[1].get("message"), u"The user authenticated against his userstore " u"according to policy 'pol1'." ) # Now assign a token to the user. If the user has a token and the # passthru policy is set, the user must not be able to authenticate # with his userstore password. init_token({"serial": "PTHRU", "type": "spass", "pin": "Hallo"}, user=user) rv = auth_user_passthru(check_user_pass, user, passw, options=options) self.assertFalse(rv[0]) self.assertEqual(rv[1].get("message"), "wrong otp pin") remove_token("PTHRU") delete_policy("pol1")
def test_03_no_detail_on_success(self): builder = EnvironBuilder(method='POST', data={'serial': "HOTP123435"}, headers={}) env = builder.get_environ() # Set the remote address so that we can filter for it env["REMOTE_ADDR"] = "10.0.0.1" req = Request(env) # The response contains the token type SPASS res = {"jsonrpc": "2.0", "result": {"status": True, "value": True}, "version": "privacyIDEA test", "id": 1, "detail": {"message": "matching 1 tokens", "serial": "HOTP123456", "type": "hotp"}} resp = Response(json.dumps(res)) # Set a policy, that does not allow the detail on success set_policy(name="pol2", scope=SCOPE.AUTHZ, action="no_detail_on_success", client="10.0.0.0/8") g.policy_object = PolicyClass() new_response = no_detail_on_success(req, resp) jresult = json.loads(new_response.data) self.assertTrue("detail" not in jresult, jresult) delete_policy("pol2")
def test_01_challenge(self): set_policy("chalresp", scope=SCOPE.AUTHZ, action="{0!s}=hotp".format(ACTION.CHALLENGERESPONSE)) token = init_token({"genkey": 1, "serial": "CHAL1", "pin": "pin"}) from privacyidea.lib.token import check_serial_pass r = check_serial_pass(token.token.serial, "pin") # The OTP PIN is correct self.assertEqual(r[0], False) self.assertEqual(r[1].get("message"), "please enter otp: ") transaction_id = r[1].get("transaction_id") chals = get_challenges() self.assertEqual(len(chals), 1) self.assertEqual(chals[0].transaction_id, transaction_id) # get challenge for this serial chals = get_challenges(serial="CHAL1") self.assertEqual(len(chals), 1) self.assertEqual(chals[0].transaction_id, transaction_id) # get challenge for another seial chals = get_challenges(serial="CHAL2") self.assertEqual(len(chals), 0) delete_policy("chalresp")
def test_04_check_max_token_user(self): g.logged_in_user = {"username": "******", "role": "admin"} builder = EnvironBuilder(method='POST', data={'serial': "OATH123456"}, headers={}) env = builder.get_environ() # Set the remote address so that we can filter for it env["REMOTE_ADDR"] = "10.0.0.1" g.client_ip = env["REMOTE_ADDR"] req = Request(env) req.all_data = {"user": "******", "realm": self.realm1} # Set a policy, that allows two tokens per user set_policy(name="pol1", scope=SCOPE.ENROLL, action="{0!s}={1!s}".format(ACTION.MAXTOKENUSER, 2)) g.policy_object = PolicyClass() # The user has one token, everything is fine. self.setUp_user_realms() tokenobject = init_token({"serial": "NEW001", "type": "hotp", "otpkey": "1234567890123456"}, user=User(login="******", realm=self.realm1)) tokenobject_list = get_tokens(user=User(login="******", realm=self.realm1)) self.assertTrue(len(tokenobject_list) == 1) self.assertTrue(check_max_token_user(req)) # Now the user gets his second token tokenobject = init_token({"serial": "NEW002", "type": "hotp", "otpkey": "1234567890123456"}, user=User(login="******", realm=self.realm1)) tokenobject_list = get_tokens(user=User(login="******", realm=self.realm1)) self.assertTrue(len(tokenobject_list) == 2) # The user has two tokens. The check that will run in this case, # before the user would be assigned the 3rd token, will raise a # PolicyError self.assertRaises(PolicyError, check_max_token_user, req) # The check for a token, that has no username in it, must not # succeed. I.e. in the realm new tokens must be enrollable. req.all_data = {} self.assertTrue(check_max_token_user(req)) req.all_data = {"realm": self.realm1} self.assertTrue(check_max_token_user(req)) # finally delete policy delete_policy("pol1") remove_token("NEW001") remove_token("NEW002")
def test_05_autoassign_any_pin(self): # init a token, that does has no uwser self.setUp_user_realms() tokenobject = init_token({"serial": "UASSIGN1", "type": "hotp", "otpkey": "3132333435363738393031" "323334353637383930"}, tokenrealms=[self.realm1]) user_obj = User("autoassignuser", self.realm1) # unassign all tokens from the user autoassignuser try: unassign_token(None, user=user_obj) except Exception: print("no need to unassign token") # The request with an OTP value and a PIN of a user, who has not # token assigned builder = EnvironBuilder(method='POST', data={}, headers={}) env = builder.get_environ() env["REMOTE_ADDR"] = "10.0.0.1" g.client_ip = env["REMOTE_ADDR"] req = Request(env) req.all_data = {"user": "******", "realm": self.realm1, "pass": "******"} # The response with a failed request res = {"jsonrpc": "2.0", "result": {"status": True, "value": False}, "version": "privacyIDEA test", "id": 1} resp = Response(json.dumps(res)) # Set the autoassign policy # to "any_pin" set_policy(name="pol2", scope=SCOPE.ENROLL, action="{0!s}={1!s}".format(ACTION.AUTOASSIGN, AUTOASSIGNVALUE.NONE), client="10.0.0.0/8") g.policy_object = PolicyClass() new_response = autoassign(req, resp) jresult = json.loads(new_response.data) self.assertTrue(jresult.get("result").get("value"), jresult) self.assertEqual(jresult.get("detail").get("serial"), "UASSIGN1") # test the token with test287082 will fail res, dict = check_user_pass(User("autoassignuser", self.realm1), "test287082") self.assertFalse(res) # test the token with test359152 will succeed res, dict = check_user_pass(User("autoassignuser", self.realm1), "test359152") self.assertTrue(res) delete_policy("pol2")
def test_14_otppin_priority(self): my_user = User("cornelius", realm="r1") set_policy(name="pol1", scope=SCOPE.AUTH, action="{0!s}={1!s}".format(ACTION.OTPPIN, ACTIONVALUE.NONE), priority=2) set_policy(name="pol2", scope=SCOPE.AUTH, action="{0!s}={1!s}".format(ACTION.OTPPIN, ACTIONVALUE.TOKENPIN), priority=2) g = FakeFlaskG() P = PolicyClass() g.policy_object = P g.audit_object = FakeAudit() options = {"g": g} # error because of conflicting policies with self.assertRaises(PolicyError): auth_otppin(self.fake_check_otp, None, "", options=options, user=my_user) # lower pol2 priority set_policy(name="pol2", priority=3) g.policy_object.reload_from_db() # NONE with empty PIN -> success r = auth_otppin(self.fake_check_otp, None, "", options=options, user=my_user) self.assertTrue(r) # NONE with empty PIN -> success, even if the authentication is done # for a serial and not a user, since the policy holds for all realms token = init_token({"type": "HOTP", "otpkey": "1234"}) r = auth_otppin(self.fake_check_otp, token, "", options=options, user=None) self.assertTrue(r) # NONE with some pin -> fail r = auth_otppin(self.fake_check_otp, None, "some pin", options=options, user=my_user) self.assertFalse(r) # increase pol2 priority set_policy(name="pol2", priority=1) g.policy_object.reload_from_db() r = auth_otppin(self.fake_check_otp, None, "FAKE", options=options, user=my_user) self.assertTrue(r) r = auth_otppin(self.fake_check_otp, None, "Wrong Pin", options=options, user=my_user) self.assertFalse(r) delete_policy("pol1") delete_policy("pol2")
def test_08_get_webui_settings(self): # Test that a machine definition will return offline hashes self.setUp_user_realms() serial = "offline01" tokenobject = init_token({"serial": serial, "type": "hotp", "otpkey": "3132333435363738393031" "323334353637383930", "pin": "offline", "user": "******"}) # Set the Machine and MachineToken resolver1 = save_resolver({"name": "reso1", "type": "hosts", "filename": HOSTSFILE}) mt = attach_token(serial, "offline", hostname="gandalf") self.assertEqual(mt.token.serial, serial) self.assertEqual(mt.token.machine_list[0].machine_id, "192.168.0.1") # The request with an OTP value and a PIN of a user, who has not # token assigned builder = EnvironBuilder(method='POST', data={}, headers={}) env = builder.get_environ() env["REMOTE_ADDR"] = "192.168.0.1" g.client_ip = env["REMOTE_ADDR"] req = Request(env) req.all_data = {"user": "******", "pass": "******"} res = {"jsonrpc": "2.0", "result": {"status": True, "value": {"role": "user", "username": "******"}}, "version": "privacyIDEA test", "detail": {"serial": serial}, "id": 1} resp = Response(json.dumps(res)) new_response = get_webui_settings(req, resp) jresult = json.loads(new_response.data) self.assertEqual(jresult.get("result").get("value").get( "token_wizard"), False) # Set a policy. User has not token, so "token_wizard" will be True set_policy(name="pol_wizard", scope=SCOPE.WEBUI, action=ACTION.TOKENWIZARD) g.policy_object = PolicyClass() new_response = get_webui_settings(req, resp) jresult = json.loads(new_response.data) self.assertEqual(jresult.get("result").get("value").get( "token_wizard"), True) delete_policy("pol_wizard")
def test_16_admin_realm(self): P = PolicyClass() logged_in_user = {"username": "******", "role": "admin", "realm": "realm1"} # Without policies, the admin gets all tt = P.ui_get_enroll_tokentypes("127.0.0.1", logged_in_user) self.assertTrue("hotp" in tt) self.assertTrue("totp" in tt) self.assertTrue("motp" in tt) self.assertTrue("sms" in tt) self.assertTrue("spass" in tt) self.assertTrue("sshkey" in tt) self.assertTrue("email" in tt) self.assertTrue("certificate" in tt) self.assertTrue("yubico" in tt) self.assertTrue("yubikey" in tt) self.assertTrue("radius" in tt) # An admin in realm1 may only enroll Yubikeys set_policy(name="tokenEnroll", scope=SCOPE.ADMIN, adminrealm="realm1", action="enrollYUBIKEY") P = PolicyClass() tt = P.ui_get_enroll_tokentypes("127.0.0.1", logged_in_user) self.assertFalse("hotp" in tt) self.assertFalse("totp" in tt) self.assertFalse("motp" in tt) self.assertFalse("sms" in tt) self.assertFalse("spass" in tt) self.assertFalse("sshkey" in tt) self.assertFalse("email" in tt) self.assertFalse("certificate" in tt) self.assertFalse("yubico" in tt) self.assertTrue("yubikey" in tt) self.assertFalse("radius" in tt) # An admin in another admin realm may enroll nothing. logged_in_user = {"username": "******", "role": "admin", "realm": "OtherRealm"} tt = P.ui_get_enroll_tokentypes("127.0.0.1", logged_in_user) self.assertFalse("hotp" in tt) self.assertFalse("totp" in tt) self.assertFalse("motp" in tt) self.assertFalse("sms" in tt) self.assertFalse("spass" in tt) self.assertFalse("sshkey" in tt) self.assertFalse("email" in tt) self.assertFalse("certificate" in tt) self.assertFalse("yubico" in tt) self.assertFalse("yubikey" in tt) self.assertFalse("radius" in tt) delete_policy("tokenEnroll")
def test_06_u2f_enrollment_fails_wrong_issuer(self): # test data taken from # https://fidoalliance.org/specs/fido-u2f-v1.0-ps-20141009/fido-u2f-raw-message-formats-ps-20141009.html#examples serial = "U2F0010BF6F" set_privacyidea_config("u2f.appId", "https://puck.az.intern") pin = "test" # Registration data client_data = "eyJ0eXAiOiJuYXZpZ2F0b3IuaWQuZmluaXNoRW5yb2xsbWVudCIsImNoYWxsZW5nZSI6ImpIakIxaEM2VjA3dDl4ZnNNaDRfOEQ3U1JuSHRFY1BqUTdsaVl3cWxkX009Iiwib3JpZ2luIjoiaHR0cHM6Ly9wdWNrLmF6LmludGVybiIsImNpZF9wdWJrZXkiOiJ1bnVzZWQifQ" reg_data = "BQRHjwxEYFCkLHz3xdrmifKOHl2h17BmRJQ_S1Y9PRAhS2R186T391YE-ryqWis9HSmdp0XpRqUaKk9L8lxJTPpTQF_xFJ_LAsKkPTzKIwUlPIjGZDsLmv0en2Iya17Yz8X8OS89fuxwZOvEok-NQOKUTJP3att_RVe3dEAbq_iOtyAwggJEMIIBLqADAgECAgRVYr6gMAsGCSqGSIb3DQEBCzAuMSwwKgYDVQQDEyNZdWJpY28gVTJGIFJvb3QgQ0EgU2VyaWFsIDQ1NzIwMDYzMTAgFw0xNDA4MDEwMDAwMDBaGA8yMDUwMDkwNDAwMDAwMFowKjEoMCYGA1UEAwwfWXViaWNvIFUyRiBFRSBTZXJpYWwgMTQzMjUzNDY4ODBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABEszH3c9gUS5mVy-RYVRfhdYOqR2I2lcvoWsSCyAGfLJuUZ64EWw5m8TGy6jJDyR_aYC4xjz_F2NKnq65yvRQwmjOzA5MCIGCSsGAQQBgsQKAgQVMS4zLjYuMS40LjEuNDE0ODIuMS41MBMGCysGAQQBguUcAgEBBAQDAgUgMAsGCSqGSIb3DQEBCwOCAQEArBbZs262s6m3bXWUs09Z9Pc-28n96yk162tFHKv0HSXT5xYU10cmBMpypXjjI-23YARoXwXn0bm-BdtulED6xc_JMqbK-uhSmXcu2wJ4ICA81BQdPutvaizpnjlXgDJjq6uNbsSAp98IStLLp7fW13yUw-vAsWb5YFfK9f46Yx6iakM3YqNvvs9M9EUJYl_VrxBJqnyLx2iaZlnpr13o8NcsKIJRdMUOBqt_ageQg3ttsyq_3LyoNcu7CQ7x8NmeCGm_6eVnZMQjDmwFdymwEN4OxfnM5MkcKCYhjqgIGruWkVHsFnJa8qjZXneVvKoiepuUQyDEJ2GcqvhU2YKY1zBFAiEA4ZkIXXyjEPExcMGtW6kJXqYv7UHgjxJR5h3H9w9FV7gCIFGdhxZDqwCQKplDi-LU4WJ45OyCpNK6lGa72eZqUR_k" # Authentication data transaction_id = "05871369157706202013" challenge = "1616515928c389ba9e028d83eb5f63782cbf351ca6abbc81aeb0dddd4895b609" # challenge = "FhZRWSjDibqeAo2D619jeCy_NRymq7yBrrDd3UiVtgk" key_handle = "X_EUn8sCwqQ9PMojBSU8iMZkOwua_R6fYjJrXtjPxfw5Lz1-7HBk68SiT41A4pRMk_dq239FV7d0QBur-I63IA" client_data_auth = "eyJ0eXAiOiJuYXZpZ2F0b3IuaWQuZ2V0QXNzZXJ0aW9uIiwiY2hhbGxlbmdlIjoiRmhaUldTakRpYnFlQW8yRDYxOWplQ3lfTlJ5bXE3eUJyckRkM1VpVnRnayIsIm9yaWdpbiI6Imh0dHBzOi8vcHVjay5hei5pbnRlcm4iLCJjaWRfcHVia2V5IjoidW51c2VkIn0" signature_data = "AQAAAAMwRQIgU8d6waOIRVVydg_AXxediEZGkfFioUjd6FG3OxH2wUMCIQDpxzavJyxRlMwgNmD1Kw-iw_oP2egdshU9hrpxFHTRzQ" # step 1 with self.app.test_request_context('/token/init', method='POST', data={"type": "u2f", "user": "******", "realm": self.realm1, "serial": serial}, headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertEqual(res.status_code, 200) result = json.loads(res.data).get("result") detail = json.loads(res.data).get("detail") self.assertEqual(result.get("status"), True) self.assertEqual(result.get("value"), True) set_policy(name="u2f01", scope=SCOPE.ENROLL, action="{0!s}=issuer/.*Plugup.*/".format(U2FACTION.REQ)) # Init step 2 with self.app.test_request_context('/token/init', method='POST', data={"type": "u2f", "serial": serial, "regdata": reg_data, "clientdata": client_data}, headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertEqual(res.status_code, 403) result = json.loads(res.data).get("result") detail = json.loads(res.data).get("detail") self.assertEqual(result.get("status"), False) self.assertEqual(result.get("error").get("message"), u'The U2F device is not allowed to be registered ' u'due to policy restriction.') delete_policy("u2f01") remove_token(serial)
def test_07_login_mode(self): # a realm: cornelius@r1: PW: test def check_webui_user_userstore(user_obj, password, options=None, superuser_realms=None, check_otp=False): self.assertEqual(check_otp, False) def check_webui_user_privacyidea(user_obj, password, options=None, superuser_realms=None, check_otp=False): self.assertEqual(check_otp, True) user_obj = User("cornelius", "r1") g = FakeFlaskG() P = PolicyClass() g.policy_object = P g.audit_object = FakeAudit() options = {"g": g} # No policy, the function is called with check_otp=False login_mode(check_webui_user_userstore, user_obj, "", options=options, superuser_realms="", check_otp=False) set_policy(name="pol2", scope=SCOPE.WEBUI, action="{0!s}={1!s}".format(ACTION.LOGINMODE, LOGINMODE.PRIVACYIDEA)) g = FakeFlaskG() P = PolicyClass() g.policy_object = P g.audit_object = FakeAudit() options = {"g": g} # Policy is set, the function is called with check_otp=True login_mode(check_webui_user_privacyidea, user_obj, "", options=options, superuser_realms="", check_otp=False) # Set policy, so that the user is not allowed to login at all set_policy(name="pol2", scope=SCOPE.WEBUI, action="{0!s}={1!s}".format(ACTION.LOGINMODE, LOGINMODE.DISABLE)) g = FakeFlaskG() P = PolicyClass() g.policy_object = P g.audit_object = FakeAudit() options = {"g": g} # Policy is set. Trying to login raises a policy error self.assertRaises(PolicyError, login_mode, check_webui_user_privacyidea, user_obj, "", options=options, superuser_realms="", check_otp=False) delete_policy("pol2")
def test_02_REMOTE_USER(self): # Allow remote user set_policy(name="remote", scope=SCOPE.WEBUI, action="%s=allowed" % ACTION.REMOTE_USER) # Admin remote user with self.app.test_request_context('/auth', method='POST', data={"username": "******"}, environ_base={"REMOTE_USER": "******"}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data).get("result") self.assertTrue("token" in result.get("value")) self.assertTrue("username" in result.get("value")) self.assertEqual(result.get("value").get("role"), "admin") self.assertTrue(result.get("status"), res.data) self.setUp_user_realms() # User "cornelius" from the default realm as normale user with self.app.test_request_context('/auth', method='POST', data={"username": "******"}, environ_base={"REMOTE_USER": "******"}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data).get("result") self.assertTrue("token" in result.get("value")) self.assertTrue("username" in result.get("value")) self.assertEqual(result.get("value").get("role"), "user") self.assertTrue(result.get("status"), res.data) # Define the superuser_realm: "adminrealm" (added, failed) = set_realm("adminrealm", [self.resolvername1]) self.assertTrue(len(failed) == 0) self.assertTrue(len(added) == 1) # user cornelius is a member of the superuser_realm... with self.app.test_request_context('/auth', method='POST', data={"username": "******"}, environ_base={"REMOTE_USER": "******"}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data).get("result") self.assertTrue("token" in result.get("value")) self.assertTrue("username" in result.get("value")) # ...and will have the role admin self.assertEqual(result.get("value").get("role"), "admin") self.assertTrue(result.get("status"), res.data) delete_policy("remote")
def test_03_api_enroll_push_poll_only(self): """Enroll a poll-only push token""" self.authenticate() # Set policy for poll only set_policy("push1", scope=SCOPE.ENROLL, action="{0!s}={1!s},{2!s}={3!s},{4!s}={5!s}".format( PUSH_ACTION.FIREBASE_CONFIG, POLL_ONLY, PUSH_ACTION.REGISTRATION_URL, REGISTRATION_URL, PUSH_ACTION.TTL, TTL)) # 1st step with self.app.test_request_context('/token/init', method='POST', data={ "type": "push", "genkey": 1 }, headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertEqual(res.status_code, 200) detail = res.json.get("detail") serial = detail.get("serial") self.assertEqual(detail.get("rollout_state"), "clientwait") self.assertIn("pushurl", detail) # check that the new URL contains the serial number self.assertIn("&serial=PIPU", detail.get("pushurl").get("value")) # The firebase settings are NOT contained in the QR Code, since we do poll_only # poll_only self.assertNotIn("appid=", detail.get("pushurl").get("value")) self.assertNotIn("appidios=", detail.get("pushurl").get("value")) self.assertNotIn("apikeyios=", detail.get("pushurl").get("value")) self.assertNotIn("otpkey", detail) enrollment_credential = detail.get("enrollment_credential") # 2nd step: as performed by the smartphone. Also in POLL_ONLY the smartphone needs to send # an empty "fbtoken" with self.app.test_request_context( '/ttype/push', method='POST', data={ "enrollment_credential": enrollment_credential, "serial": serial, "pubkey": self.smartphone_public_key_pem_urlsafe, "fbtoken": "" }): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) detail = res.json.get("detail") # still the same serial number self.assertEqual(serial, detail.get("serial")) self.assertEqual(detail.get("rollout_state"), "enrolled") # Now the smartphone gets a public key from the server augmented_pubkey = "-----BEGIN RSA PUBLIC KEY-----\n{}\n-----END RSA PUBLIC KEY-----\n".format( detail.get("public_key")) parsed_server_pubkey = serialization.load_pem_public_key( to_bytes(augmented_pubkey), default_backend()) self.assertIsInstance(parsed_server_pubkey, rsa.RSAPublicKey) pubkey = detail.get("public_key") # Now check, what is in the token in the database toks = get_tokens(serial=serial) self.assertEqual(len(toks), 1) token_obj = toks[0] self.assertEqual(token_obj.token.rollout_state, u"enrolled") self.assertTrue(token_obj.token.active) tokeninfo = token_obj.get_tokeninfo() self.assertEqual(tokeninfo.get("public_key_smartphone"), self.smartphone_public_key_pem_urlsafe) self.assertEqual(tokeninfo.get("firebase_token"), u"") self.assertEqual( tokeninfo.get("public_key_server").strip().strip( "-BEGIN END RSA PUBLIC KEY-").strip(), pubkey) # The token should also contain the firebase config self.assertEqual(tokeninfo.get(PUSH_ACTION.FIREBASE_CONFIG), POLL_ONLY) # remove the token remove_token(serial) # remove the policy delete_policy("push1")
def test_04_remote_user_auth(self): self.setUp_user_realms() # first check that without a remote_user policy the login fails with self.app.test_request_context( '/auth', method='POST', data={"username": "******"}, environ_base={"REMOTE_USER": "******"}): res = self.app.full_dispatch_request() self.assertEqual(res.status_code, 401, res) result = res.json.get("result") self.assertFalse(result.get("status"), result) self.assertEqual(result.get("error").get('code'), 4031, result) self.assertEqual( result.get("error").get('message'), 'Authentication failure. Wrong credentials', result) aentry = self.find_most_recent_audit_entry(action='POST /auth') self.assertEqual(aentry['action'], 'POST /auth', aentry) self.assertEqual(aentry['success'], 0, aentry) # now check that with a disabled remote_user policy the login fails set_policy(name="remote", scope=SCOPE.WEBUI, action="{0!s}={1!s}".format(ACTION.REMOTE_USER, REMOTE_USER.DISABLE)) with self.app.test_request_context( '/auth', method='POST', data={"username": "******"}, environ_base={"REMOTE_USER": "******"}): res = self.app.full_dispatch_request() self.assertEqual(res.status_code, 401, res) result = res.json.get("result") self.assertFalse(result.get("status"), result) self.assertEqual(result.get("error").get('code'), 4031, result) self.assertEqual( result.get("error").get('message'), 'Authentication failure. Wrong credentials', result) aentry = self.find_most_recent_audit_entry(action='POST /auth') self.assertEqual(aentry['action'], 'POST /auth', aentry) self.assertEqual(aentry['success'], 0, aentry) self.assertEqual(aentry['policies'], 'remote', aentry) # And now check that with an enabled remote_user policy the login succeeds set_policy(name="remote", scope=SCOPE.WEBUI, action="{0!s}={1!s}".format(ACTION.REMOTE_USER, REMOTE_USER.ACTIVE)) with self.app.test_request_context( '/auth', method='POST', data={"username": "******"}, environ_base={"REMOTE_USER": "******"}): res = self.app.full_dispatch_request() self.assertEqual(res.status_code, 200, res) result = res.json.get("result") self.assertTrue(result.get("status"), result) self.assertEqual(result.get("value").get('role'), 'user', result) aentry = self.find_most_recent_audit_entry(action='POST /auth') self.assertEqual(aentry['action'], 'POST /auth', aentry) self.assertEqual(aentry['success'], 1, aentry) self.assertEqual(aentry['policies'], 'remote', aentry) # check that a remote user with "@" works as well set_policy(name="remote", scope=SCOPE.WEBUI, realm=self.realm1, action="{0!s}={1!s}".format(ACTION.REMOTE_USER, REMOTE_USER.ACTIVE)) with self.app.test_request_context( '/auth', method='POST', data={"username": "******"}, environ_base={"REMOTE_USER": "******"}): res = self.app.full_dispatch_request() self.assertEqual(res.status_code, 200, res) result = res.json.get("result") self.assertTrue(result.get("status"), result) self.assertEqual(result.get("value").get('role'), 'user', result) aentry = self.find_most_recent_audit_entry(action='POST /auth') self.assertEqual(aentry['action'], 'POST /auth', aentry) self.assertEqual(aentry['success'], 1, aentry) self.assertEqual(aentry['policies'], 'remote', aentry) # check that the policy remote_user=force passes the necessary hidden tag to the # login window set_policy(name="remote", scope=SCOPE.WEBUI, realm=self.realm1, action="{0!s}={1!s}".format(ACTION.REMOTE_USER, REMOTE_USER.FORCE)) with self.app.test_request_context( '/', method='GET', environ_base={"REMOTE_USER": "******"}): res = self.app.full_dispatch_request() self.assertEqual(res.status_code, 200, res) # The login page contains the info about force remote_user, which will hide the # "login with credentials" button. self.assertIn( u'input type=hidden id=FORCE_REMOTE_USER value="True"', to_unicode(res.data)) # bind the remote user policy to an unknown realm set_policy(name="remote", scope=SCOPE.WEBUI, realm='unknown', action="{0!s}={1!s}".format(ACTION.REMOTE_USER, REMOTE_USER.ACTIVE)) with self.app.test_request_context( '/auth', method='POST', data={"username": "******"}, environ_base={"REMOTE_USER": "******"}): res = self.app.full_dispatch_request() self.assertEqual(res.status_code, 401, res) result = res.json.get("result") self.assertFalse(result.get("status"), result) aentry = self.find_most_recent_audit_entry(action='POST /auth') self.assertEqual(aentry['action'], 'POST /auth', aentry) self.assertEqual(aentry['success'], 0, aentry) self.assertEqual(aentry['policies'], '', aentry) # check split@sign is working correctly set_policy(name="remote", scope=SCOPE.WEBUI, realm=self.realm1, action="{0!s}={1!s}".format(ACTION.REMOTE_USER, REMOTE_USER.ACTIVE)) set_privacyidea_config(SYSCONF.SPLITATSIGN, False) with self.app.test_request_context( '/auth', method='POST', data={"username": "******"}, environ_base={"REMOTE_USER": "******"}): res = self.app.full_dispatch_request() self.assertEqual(res.status_code, 200, res) result = res.json.get("result") self.assertTrue(result.get("status"), result) self.assertEqual(result.get("value").get('role'), 'user', result) aentry = self.find_most_recent_audit_entry(action='POST /auth') self.assertEqual(aentry['action'], 'POST /auth', aentry) self.assertEqual(aentry['success'], 1, aentry) self.assertEqual(aentry['policies'], 'remote', aentry) delete_policy(name='remote') set_privacyidea_config(SYSCONF.SPLITATSIGN, True)
def test_15_ui_tokentypes(self): P = PolicyClass() logged_in_user = { "username": "******", "role": "admin", "realm": "realm1" } # Without policies, the admin gets all tt = P.ui_get_enroll_tokentypes("127.0.0.1", logged_in_user) self.assertTrue("hotp" in tt) self.assertTrue("totp" in tt) self.assertTrue("motp" in tt) self.assertTrue("sms" in tt) self.assertTrue("spass" in tt) self.assertTrue("sshkey" in tt) self.assertTrue("email" in tt) self.assertTrue("certificate" in tt) self.assertTrue("yubico" in tt) self.assertTrue("yubikey" in tt) self.assertTrue("radius" in tt) # An admin may only enroll Yubikeys set_policy(name="tokenEnroll", scope=SCOPE.ADMIN, action="enrollYUBIKEY") P = PolicyClass() tt = P.ui_get_enroll_tokentypes("127.0.0.1", logged_in_user) self.assertFalse("hotp" in tt) self.assertFalse("totp" in tt) self.assertFalse("motp" in tt) self.assertFalse("sms" in tt) self.assertFalse("spass" in tt) self.assertFalse("sshkey" in tt) self.assertFalse("email" in tt) self.assertFalse("certificate" in tt) self.assertFalse("yubico" in tt) self.assertTrue("yubikey" in tt) self.assertFalse("radius" in tt) # A user may enroll nothing set_policy(name="someUserAction", scope=SCOPE.USER, action="disable") P = PolicyClass() tt = P.ui_get_enroll_tokentypes("127.0.0.1", { "username": "******", "realm": "realm", "role": "user" }) self.assertEqual(len(tt), 0) delete_policy("tokenEnroll") # Two admins: # adminA is allowed to enroll tokens in all realms # adminB is allowed to enroll tokens only in realmB set_policy(name="polAdminA", scope=SCOPE.ADMIN, user="******", action="enrollHOTP, enrollTOTP") set_policy(name="polAdminB", scope=SCOPE.ADMIN, user="******", realm="realmB", action="enrollHOTP") P = PolicyClass() # realm is empty, since in case of an admin, this is the admin realm rights = P.ui_get_enroll_tokentypes(None, { "role": SCOPE.ADMIN, "realm": None, "username": "******" }) self.assertTrue("hotp" in rights) self.assertTrue("totp" in rights) rights = P.ui_get_enroll_tokentypes(None, { "role": SCOPE.ADMIN, "realm": "", "username": "******" }) self.assertTrue("totp" not in rights) self.assertTrue("hotp" in rights) rights = P.ui_get_enroll_tokentypes(None, { "role": SCOPE.ADMIN, "realm": "", "username": "******" }) self.assertEqual(rights, {}) delete_policy("polAdminA") delete_policy("polAdminB")
def test_01_set_policy(self): with self.app.test_request_context('/policy/pol1', method='POST', data={ "action": ACTION.NODETAILFAIL, "client": "10.1.2.3", "scope": SCOPE.AUTHZ, "check_all_resolvers": "true", "realm": "realm1", "priority": 3 }, headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) data = res.json result = data.get("result") self.assertTrue("setPolicy pol1" in result.get("value"), result.get("value")) # get the policies and see if check_all_resolvers and priority are set with self.app.test_request_context('/policy/', method='GET', headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) self.assertTrue(res.json['result']['status'], res.json) value = res.json['result']['value'] self.assertEqual(len(value), 1) pol1 = value[0] self.assertEqual(pol1.get("check_all_resolvers"), True) self.assertEqual(pol1.get("priority"), 3) # get active policies with self.app.test_request_context('/policy/?active=true', method='GET', headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) self.assertTrue(res.json['result']['status'], res.json) self.assertEqual(len(value), 1) pol1 = value[0] self.assertEqual(pol1.get("check_all_resolvers"), True) self.assertEqual(pol1.get("priority"), 3) # Update policy to check_all_resolvers = false and priority = 5 with self.app.test_request_context('/policy/pol1', method='POST', data={ "action": ACTION.NODETAILFAIL, "client": "10.1.2.3", "scope": SCOPE.AUTHZ, "check_all_resolvers": "false", "priority": 5, "realm": "realm1" }, headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) data = res.json result = data.get("result") self.assertTrue("setPolicy pol1" in result.get("value"), result.get("value")) # get the policies and see if check_all_resolvers and priority are set with self.app.test_request_context('/policy/', method='GET', headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) self.assertTrue(res.json['result']['status'], res.json) value = res.json['result']['value'] self.assertEqual(len(value), 1) pol1 = value[0] self.assertEqual(pol1.get("check_all_resolvers"), False) self.assertEqual(pol1.get("priority"), 5) delete_policy("pol1") with self.app.test_request_context('/policy/polpinode', method='POST', data={ "action": ACTION.NODETAILFAIL, "client": "10.1.2.3", "scope": SCOPE.AUTHZ, "pinode": "Node1", "priority": 1, "realm": "realm1" }, headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) data = res.json result = data.get("result") self.assertTrue("setPolicy polpinode" in result.get("value"), result.get("value")) # get the policies and see if the pinode was set with self.app.test_request_context('/policy/', method='GET', headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) self.assertTrue(res.json['result']['status'], res.json) value = res.json['result']['value'] self.assertEqual(len(value), 1) pol1 = value[0] self.assertEqual(pol1.get("pinode"), ["Node1"]) delete_policy("polpinode")
def test_02_check_httpenvironment_condition(self): self.setUp_user_realms() # enroll a simple pass token with self.app.test_request_context( '/token/init', method='POST', json={ "type": "spass", "pin": "1234", "serial": "sp1", "user": "******", "realm": "realm1", "client": "10.1.2.3" }, headers={'PI-Authorization': self.at}): res = self.app.full_dispatch_request() self.assertEqual(res.status_code, 200) # test an auth request with self.app.test_request_context('/validate/check', method='POST', json={ "pass": "******", "user": "******", "realm": "realm1", "client": "10.1.2.3" }): res = self.app.full_dispatch_request() self.assertEqual(res.status_code, 200) result = res.json self.assertTrue("detail" in result) self.assertEqual( result.get("detail").get("message"), u"matching 1 tokens") # set a policy with conditions # Request with a certain request method will not see the user details with self.app.test_request_context( '/policy/cond1', method='POST', json={ "action": ACTION.NODETAILSUCCESS, "realm": "realm1", "client": "10.1.2.3", "conditions": [[ CONDITION_SECTION.HTTP_ENVIRONMENT, "REQUEST_METHOD", "equals", "POST", True ]], "scope": SCOPE.AUTHZ }, headers={'PI-Authorization': self.at}): res = self.app.full_dispatch_request() self.assertEqual(res.status_code, 200) # A GET request will contain the details! with self.app.test_request_context('/validate/check', method='GET', json={ "pass": "******", "user": "******", "realm": "realm1", "client": "10.1.2.3" }): res = self.app.full_dispatch_request() self.assertEqual(res.status_code, 200) result = res.json self.assertTrue("detail" in result) self.assertEqual( result.get("detail").get("message"), u"matching 1 tokens") # A POST request will NOT contain the details! with self.app.test_request_context('/validate/check', method='POST', json={ "pass": "******", "user": "******", "realm": "realm1", "client": "10.1.2.3" }): res = self.app.full_dispatch_request() self.assertEqual(res.status_code, 200) result = res.json self.assertFalse("detail" in result) delete_policy("cond1") # Now we run a test with a non-existing environment key with self.app.test_request_context( '/policy/cond1', method='POST', json={ "action": ACTION.NODETAILSUCCESS, "realm": "realm1", "client": "10.1.2.3", "conditions": [[ CONDITION_SECTION.HTTP_ENVIRONMENT, "NON_EXISTING", "equals", "POST", True ]], "scope": SCOPE.AUTHZ }, headers={'PI-Authorization': self.at}): res = self.app.full_dispatch_request() self.assertEqual(res.status_code, 200) with self.app.test_request_context('/validate/check', method='POST', json={ "pass": "******", "user": "******", "realm": "realm1", "client": "10.1.2.3" }): res = self.app.full_dispatch_request() self.assertEqual(res.status_code, 403) result = res.json self.assertIn( u"Unknown HTTP environment key referenced in condition of policy", result["result"]["error"]["message"]) self.assertIn(u"NON_EXISTING", result["result"]["error"]["message"]) delete_policy("cond1") remove_token("sp1")
def test_08_get_webui_settings(self): # Test that a machine definition will return offline hashes self.setUp_user_realms() serial = "offline01" tokenobject = init_token({ "serial": serial, "type": "hotp", "otpkey": "3132333435363738393031" "323334353637383930", "pin": "offline", "user": "******" }) # Set the Machine and MachineToken resolver1 = save_resolver({ "name": "reso1", "type": "hosts", "filename": HOSTSFILE }) mt = attach_token(serial, "offline", hostname="gandalf") self.assertEqual(mt.token.serial, serial) self.assertEqual(mt.token.machine_list[0].machine_id, "192.168.0.1") # The request with an OTP value and a PIN of a user, who has not # token assigned builder = EnvironBuilder(method='POST', data={}, headers={}) env = builder.get_environ() env["REMOTE_ADDR"] = "192.168.0.1" g.client_ip = env["REMOTE_ADDR"] req = Request(env) req.all_data = {"user": "******", "pass": "******"} res = { "jsonrpc": "2.0", "result": { "status": True, "value": { "role": "user", "username": "******" } }, "version": "privacyIDEA test", "detail": { "serial": serial }, "id": 1 } resp = Response(json.dumps(res)) new_response = get_webui_settings(req, resp) jresult = json.loads(new_response.data) self.assertEqual( jresult.get("result").get("value").get("token_wizard"), False) # Set a policy. User has not token, so "token_wizard" will be True set_policy(name="pol_wizard", scope=SCOPE.WEBUI, action=ACTION.TOKENWIZARD) g.policy_object = PolicyClass() new_response = get_webui_settings(req, resp) jresult = json.loads(new_response.data) self.assertEqual( jresult.get("result").get("value").get("token_wizard"), True) delete_policy("pol_wizard")
def test_06_passthru(self): user = User("cornelius", realm="r1") passw = "test" options = {} # A user with no tokens will fail to authenticate self.assertEqual(get_tokens(user=user, count=True), 0) rv = auth_user_passthru(check_user_pass, user, passw, options) self.assertFalse(rv[0]) self.assertEqual(rv[1].get("message"), "The user has no tokens assigned") # Now we set a PASSTHRU policy, so that the user may authenticate # against his userstore (old style) set_policy(name="pol1", scope=SCOPE.AUTH, action=ACTION.PASSTHRU) g = FakeFlaskG() g.policy_object = PolicyClass() g.audit_object = FakeAudit() options = {"g": g} rv = auth_user_passthru(check_user_pass, user, passw, options=options) self.assertTrue(rv[0]) self.assertEqual(rv[1].get("message"), u"against userstore due to 'pol1'") # Now set a PASSTHRU policy to the userstore (new style) set_policy(name="pol1", scope=SCOPE.AUTH, action="{0!s}=userstore".format(ACTION.PASSTHRU)) g = FakeFlaskG() g.policy_object = PolicyClass() g.audit_object = FakeAudit() options = {"g": g} rv = auth_user_passthru(check_user_pass, user, passw, options=options) self.assertTrue(rv[0]) self.assertEqual(rv[1].get("message"), u"against userstore due to 'pol1'") # Now set a PASSTHRU policy to a RADIUS config (new style) radiusmock.setdata(success=True) set_policy(name="pol1", scope=SCOPE.AUTH, action="{0!s}=radiusconfig1".format(ACTION.PASSTHRU)) r = add_radius("radiusconfig1", "1.2.3.4", "testing123", dictionary=DICT_FILE) self.assertTrue(r > 0) g = FakeFlaskG() g.policy_object = PolicyClass() g.audit_object = FakeAudit() options = {"g": g} rv = auth_user_passthru(check_user_pass, user, passw, options=options) self.assertTrue(rv[0]) self.assertEqual(rv[1].get("message"), u"against RADIUS server radiusconfig1 due to 'pol1'") # Now assign a token to the user. If the user has a token and the # passthru policy is set, the user must not be able to authenticate # with his userstore password. init_token({ "serial": "PTHRU", "type": "spass", "pin": "Hallo" }, user=user) rv = auth_user_passthru(check_user_pass, user, passw, options=options) self.assertFalse(rv[0]) self.assertEqual(rv[1].get("message"), "wrong otp pin") remove_token("PTHRU") delete_policy("pol1")
def test_02_get_allowed_audit_realm(self): # Check that an administrator is only allowed to see log entries of # the defined realms. # fill some audit entries Audit(action="enroll", success=1, realm="realm1a").save() Audit(action="enroll", success=1, realm="realm1a").save() Audit(action="enroll", success=1, realm="realm2b").save() Audit(action="enroll", success=1, realm="realm2b").save() Audit(action="enroll", success=1, realm="realm2b").save() # check, that we see all audit entries with self.app.test_request_context('/audit/', method='GET', data={"realm": "realm1a"}, headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) json_response = json.loads(res.data.decode('utf8')) self.assertTrue(json_response.get("result").get("status"), res) self.assertEqual( json_response.get("result").get("value").get("count"), 2) with self.app.test_request_context('/audit/', method='GET', headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) json_response = json.loads(res.data.decode('utf8')) self.assertTrue(json_response.get("result").get("status"), res) self.assertEqual( json_response.get("result").get("value").get("count"), 8) audit_list = json_response.get("result").get("value").get( "auditdata") audit_actions = [ a for a in audit_list if a.get("action") == "GET /audit/" ] self.assertEqual(len(audit_actions), 2) with self.app.test_request_context('/audit/', method='GET', data={"realm": "realm2b"}, headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) json_response = json.loads(res.data.decode('utf8')) self.assertTrue(json_response.get("result").get("status"), res) self.assertEqual( json_response.get("result").get("value").get("count"), 3) # set policy for audit realms set_policy("audit01", scope=SCOPE.ADMIN, action=ACTION.AUDIT, realm="realm1a") # check, that we only see allowed audit realms with self.app.test_request_context('/audit/', method='GET', headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) json_response = json.loads(res.data.decode('utf8')) self.assertTrue(json_response.get("result").get("status"), res) # We now have 3 entries, as we added one by the search in line #43 audit_list = json_response.get("result").get("value").get( "auditdata") audit_realms = [ a for a in audit_list if a.get("realm") == "realm1a" ] self.assertEqual(len(audit_realms), 3) self.assertEqual( json_response.get("result").get("value").get("count"), 3) # delete policy delete_policy("audit01")
def test_03_get_allowed_audit_realm(self): # Check than an internal admin is allowed to see all realms # A helpdesk user in "adminrealm" is only allowerd to see realm1A Audit(action="enroll", success=1, realm="realm1a").save() Audit(action="enroll", success=1, realm="realm1a").save() Audit(action="enroll", success=1, realm="realm2b").save() Audit(action="enroll", success=1, realm="realm2b").save() Audit(action="enroll", success=1, realm="realm2b").save() # check, that we see all audit entries with self.app.test_request_context('/audit/', method='GET', data={"realm": "realm1a"}, headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) json_response = json.loads(res.data.decode('utf8')) self.assertTrue(json_response.get("result").get("status"), res) self.assertEqual( json_response.get("result").get("value").get("count"), 5) with self.app.test_request_context('/audit/', method='GET', data={"realm": "realm2b"}, headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) json_response = json.loads(res.data.decode('utf8')) self.assertTrue(json_response.get("result").get("status"), res) self.assertEqual( json_response.get("result").get("value").get("count"), 7) # set policy: helpdesk users in adminrealm are only allowed to # view "realm1A". set_policy("audit01", scope=SCOPE.ADMIN, action=ACTION.AUDIT, adminrealm="adminrealm", realm="realm1a") # Test admin is allowed to view unrestricted logs! set_policy("audit02", scope=SCOPE.ADMIN, action=ACTION.AUDIT, user="******") rid = save_resolver({ "resolver": self.resolvername1, "type": "passwdresolver", "fileName": PWFILE }) self.assertTrue(rid > 0, rid) (added, failed) = set_realm("adminrealm", [self.resolvername1]) self.assertTrue(len(failed) == 0) self.assertTrue(len(added) == 1) helpdesk_authorization = None with self.app.test_request_context('/auth', method='POST', data={ 'username': '******', 'password': '******' }): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) json_response = json.loads(res.data.decode('utf8')) value = json_response.get("result").get("value") # Helpdesk user is allowed to view the audit log. self.assertTrue("auditlog" in value.get("rights")) helpdesk_authorization = value.get("token") # check, that we only see allowed audit realms with self.app.test_request_context( '/audit/', method='GET', headers={'Authorization': helpdesk_authorization}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) json_response = json.loads(res.data.decode('utf8')) self.assertTrue(json_response.get("result").get("status"), res) # We now have 3 entries, as we added one by the search in line #43 count = json_response.get("result").get("value").get("count") auditdata = json_response.get("result").get("value").get( "auditdata") self.assertEqual(count, 6) # All entries are in realm1A! for ad in auditdata: self.assertEqual(ad.get("realm"), "realm1a") # Now check, that the testadmin (self.at) sees all entries! with self.app.test_request_context('/audit/', method='GET', headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) json_response = json.loads(res.data.decode('utf8')) self.assertTrue(json_response.get("result").get("status"), res) # We now have 3 entries, as we added one by the search in line #43 count = json_response.get("result").get("value").get("count") auditdata = json_response.get("result").get("value").get( "auditdata") self.assertEqual(count, 20) # delete policy delete_policy("audit01") delete_policy("audit02")
def test_06_api_auth(self): self.setUp_user_realms() # get enrolled push token toks = get_tokens(tokentype="push") self.assertEqual(len(toks), 1) tokenobj = toks[0] # set PIN tokenobj.set_pin("pushpin") tokenobj.add_user(User("cornelius", self.realm1)) # Set a loginmode policy set_policy("webui", scope=SCOPE.WEBUI, action="{}={}".format(ACTION.LOGINMODE, LOGINMODE.PRIVACYIDEA)) # Set a PUSH_WAIT action which will be ignored by privacyIDEA set_policy("push1", scope=SCOPE.AUTH, action="{0!s}=20".format(PUSH_ACTION.WAIT)) with mock.patch('privacyidea.lib.smsprovider.FirebaseProvider.ServiceAccountCredentials') as mySA: # alternative: side_effect instead of return_value mySA.from_json_keyfile_name.return_value = myCredentials(myAccessTokenInfo("my_bearer_token")) # add responses, to simulate the communication to firebase responses.add(responses.POST, 'https://fcm.googleapis.com/v1/projects/test-123456/messages:send', body="""{}""", content_type="application/json") with self.app.test_request_context('/auth', method='POST', data={"username": "******", "realm": self.realm1, # this will be overwritted by pushtoken_disable_wait PUSH_ACTION.WAIT: "10", "password": "******"}): res = self.app.full_dispatch_request() self.assertEqual(res.status_code, 401) jsonresp = res.json self.assertFalse(jsonresp.get("result").get("value")) self.assertFalse(jsonresp.get("result").get("status")) self.assertEqual(jsonresp.get("detail").get("serial"), tokenobj.token.serial) self.assertIn("transaction_id", jsonresp.get("detail")) transaction_id = jsonresp.get("detail").get("transaction_id") self.assertEqual(jsonresp.get("detail").get("message"), DEFAULT_CHALLENGE_TEXT) # Get the challenge from the database challengeobject_list = get_challenges(serial=tokenobj.token.serial, transaction_id=transaction_id) challenge = challengeobject_list[0].challenge # This is what the smartphone answers. # create the signature: sign_data = "{0!s}|{1!s}".format(challenge, tokenobj.token.serial) signature = b32encode_and_unicode( self.smartphone_private_key.sign(sign_data.encode("utf-8"), padding.PKCS1v15(), hashes.SHA256())) # We still cannot log in with self.app.test_request_context('/auth', method='POST', data={"username": "******", "realm": self.realm1, "pass": "", "transaction_id": transaction_id}): res = self.app.full_dispatch_request() self.assertEqual(res.status_code, 401) self.assertFalse(res.json['result']['status']) # Answer the challenge with self.app.test_request_context('/ttype/push', method='POST', data={"serial": tokenobj.token.serial, "nonce": challenge, "signature": signature}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) self.assertTrue(res.json['result']['status']) self.assertTrue(res.json['result']['value']) # We can now log in with self.app.test_request_context('/auth', method='POST', data={"username": "******", "realm": self.realm1, "pass": "", "transaction_id": transaction_id}): res = self.app.full_dispatch_request() self.assertEqual(res.status_code, 200) self.assertTrue(res.json['result']['status']) delete_policy("push1") delete_policy("webui")
def test_04_delete_policy(self): delete_policy(name="pol4") P = PolicyClass() pol4 = P.get_policies(name="pol4") self.assertTrue(pol4 == [], pol4)
def test_10_auth_items_ssh(self): # create an SSH token token_obj = init_token({"serial": self.serial2, "type": "sshkey", "sshkey": SSHKEY}) self.assertEqual(token_obj.type, "sshkey") # Attach the token to the machine "gandalf" with the application SSH r = attach_token(hostname="gandalf", serial=self.serial2, application="ssh", options={"user": "******"}) self.assertEqual(r.machine_id, "192.168.0.1") # fetch the auth_items for application SSH on machine gandalf with self.app.test_request_context( '/machine/authitem/ssh?hostname=gandalf', method='GET', headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = res.json.get("result") self.assertEqual(result["status"], True) sshkey = result["value"].get("ssh")[0].get("sshkey") self.assertTrue(sshkey.startswith("ssh-rsa"), sshkey) # fetch the auth_items for user testuser with self.app.test_request_context( '/machine/authitem/ssh?hostname=gandalf&user=testuser', method='GET', headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = res.json.get("result") self.assertEqual(result["status"], True) sshkey = result["value"].get("ssh")[0].get("sshkey") self.assertTrue(sshkey.startswith("ssh-rsa"), sshkey) # fetch auth_items for testuser, but with mangle policy # Remove everything that sounds like "SOMETHING\" in front of # the username set_policy(name="mangle1", scope=SCOPE.AUTH, action="{0!s}=user/.*\\\\(.*)/\\1/".format(ACTION.MANGLE)) with self.app.test_request_context( '/machine/authitem/ssh?hostname=gandalf&user=DOMAIN\\testuser', method='GET', headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = res.json.get("result") self.assertEqual(result["status"], True) sshkey = result["value"].get("ssh")[0].get("sshkey") self.assertTrue(sshkey.startswith("ssh-rsa"), sshkey) delete_policy("mangle1") # Now that the policy is deleted, we will not get the auth_items # anymore, since the username is not mangled. with self.app.test_request_context( '/machine/authitem/ssh?hostname=gandalf&user=DOMAIN\\testuser', method='GET', headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = res.json.get("result") self.assertEqual(result["status"], True) sshkeys = result["value"].get("ssh") # No user DOMAIN\\testuser and no SSH keys self.assertFalse(sshkeys) # fetch the auth_items on machine gandalf for all applications with self.app.test_request_context( '/machine/authitem?hostname=gandalf', method='GET', headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = res.json.get("result") sshkey = result["value"].get("ssh")[0].get("sshkey") self.assertTrue(sshkey.startswith("ssh-rsa"), sshkey)
def test_05_autoassign_userstore(self): # init a token, that does has no user self.setUp_user_realms() tokenobject = init_token( { "serial": "UASSIGN2", "type": "hotp", "otpkey": "3132333435363738393031" "323334353637383930" }, tokenrealms=[self.realm1]) user_obj = User("autoassignuser", self.realm1) # unassign all tokens from the user autoassignuser try: unassign_token(None, user=user_obj) except Exception: print("no need to unassign token") # The request with an OTP value and a PIN of a user, who has not # token assigned builder = EnvironBuilder(method='POST', data={}, headers={}) env = builder.get_environ() env["REMOTE_ADDR"] = "10.0.0.1" req = Request(env) req.all_data = { "user": "******", "realm": self.realm1, "pass": "******" } # The response with a failed request res = { "jsonrpc": "2.0", "result": { "status": True, "value": False }, "version": "privacyIDEA test", "id": 1 } resp = Response(json.dumps(res)) # Set the autoassign policy # to "userstore" set_policy(name="pol2", scope=SCOPE.ENROLL, action="%s=%s" % (ACTION.AUTOASSIGN, AUTOASSIGNVALUE.USERSTORE), client="10.0.0.0/8") g.policy_object = PolicyClass() new_response = autoassign(req, resp) jresult = json.loads(new_response.data) self.assertEqual(jresult.get("result").get("value"), True) self.assertEqual(jresult.get("detail").get("serial"), "UASSIGN2") # authenticate with 287082 a second time will fail res, dict = check_user_pass(User("autoassignuser", self.realm1), "password287082") self.assertFalse(res) # authenticate with the next OTP 359152 will succeed res, dict = check_user_pass(User("autoassignuser", self.realm1), "password359152") self.assertTrue(res) delete_policy("pol2")
def test_03_custom_parameters(self): set_policy( name="enrollhotp", action=["enrollHOTP=1", "delete", "hotp_2step=allow"], scope=SCOPE.ADMIN, ) with self.app.test_request_context( '/token/init', method='POST', data={ "type": "hotp", "genkey": "1", "2stepinit": "1", "2step_serversize": "5", "2step_clientsize": "16", "2step_difficulty": "17898", "hashlib": "sha512", # force 64-byte secret "otplen": "8", }, headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data).get("result") self.assertTrue(result.get("status") is True, result) self.assertTrue(result.get("value") is True, result) detail = json.loads(res.data).get("detail") serial = detail.get("serial") otpkey_url = detail.get("otpkey", {}).get("value") server_component = binascii.unhexlify(otpkey_url.split("/")[2]) client_component = "wrongsize0" # 10 bytes hex_client_component = binascii.hexlify(client_component) # Supply a client secret of incorrect size with self.app.test_request_context('/token/init', method='POST', data={ "type": "hotp", "serial": serial, "otpkey": hex_client_component, }, headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 400, res) result = json.loads(res.data).get("result") self.assertFalse(result.get("status")) client_component = "correctsizeABCDE" # 16 bytes hex_client_component = binascii.hexlify(client_component) # Now doing the correct 2nd step with self.app.test_request_context( '/token/init', method='POST', data={ "type": "hotp", "serial": serial, "otpkey": hex_client_component, "2step_serversize": "3", # will have no effect "2step_clientsize": "4", "2step_difficulty": "33333" }, headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data).get("result") self.assertTrue(result.get("status") is True, result) self.assertTrue(result.get("value") is True, result) detail = json.loads(res.data).get("detail") otpkey_url = detail.get("otpkey", {}).get("value") otpkey = otpkey_url.split("/")[2] # Now try to authenticate otpkey_bin = binascii.unhexlify(otpkey) otp_value = HmacOtp(digits=8, hashfunc=hashlib.sha512).generate(key=otpkey_bin, counter=1) with self.app.test_request_context('/validate/check', method='POST', data={ "serial": serial, "pass": otp_value }): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data).get("result") self.assertEqual(result.get("status"), True) self.assertEqual(result.get("value"), True) # Check serversize self.assertEqual(len(server_component), 5) # Check that the OTP key is what we expected it to be expected_secret = pbkdf2(binascii.hexlify(server_component), client_component, 17898, 64) self.assertEqual(otpkey_bin, expected_secret) with self.app.test_request_context('/token/' + serial, method='DELETE', headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) delete_policy("enrollhotp")
def test_11_otppin_with_resolvers(self): # This tests, if the otppin policy differentiates between users in # the same realm but in different resolvers. r = save_resolver({ "resolver": "reso001", "type": "passwdresolver", "fileName": "tests/testdata/passwords" }) # user "cornelius" is in resolver reso001 self.assertTrue(r > 0) r = save_resolver({ "resolver": "reso002", "type": "passwdresolver", "fileName": "tests/testdata/pw-2nd-resolver" }) # user "userresolver2" is in resolver reso002 self.assertTrue(r > 0) (added, failed) = set_realm("myrealm", ["reso001", "reso002"]) self.assertEqual(len(added), 2) self.assertEqual(len(failed), 0) my_user_1 = User("cornelius", realm="myrealm") my_user_2 = User("userresolver2", realm="myrealm") # We set a policy only for resolver reso002 set_policy(name="pol1", scope=SCOPE.AUTH, realm="myrealm", resolver="reso002", action="{0!s}={1!s}".format(ACTION.OTPPIN, ACTIONVALUE.NONE)) g = FakeFlaskG() P = PolicyClass() g.policy_object = P g.audit_object = FakeAudit() options = {"g": g} # user in reso001 fails with empty PIN, since the policy does not # match for him r = auth_otppin(self.fake_check_otp, None, "", options=options, user=my_user_1) self.assertFalse(r) # user in reso002 succeeds with empty PIN, since policy pol1 matches # for him r = auth_otppin(self.fake_check_otp, None, "", options=options, user=my_user_2) self.assertTrue(r) # user in reso002 fails with any PIN, since policy pol1 matches # for him r = auth_otppin(self.fake_check_otp, None, "anyPIN", options=options, user=my_user_2) self.assertFalse(r) delete_policy("pol1") delete_realm("myrealm") delete_resolver("reso001") delete_resolver("reso002")
def test_06_offline_auth(self): # Test that a machine definition will return offline hashes self.setUp_user_realms() serial = "offline01" tokenobject = init_token({ "serial": serial, "type": "hotp", "otpkey": "3132333435363738393031" "323334353637383930", "pin": "offline", "user": "******" }) # Set the Machine and MachineToken resolver1 = save_resolver({ "name": "reso1", "type": "hosts", "filename": HOSTSFILE }) mt = attach_token(serial, "offline", hostname="gandalf") self.assertEqual(mt.token.serial, serial) self.assertEqual(mt.token.machine_list[0].machine_id, "192.168.0.1") # The request with an OTP value and a PIN of a user, who has not # token assigned builder = EnvironBuilder(method='POST', data={}, headers={}) env = builder.get_environ() env["REMOTE_ADDR"] = "192.168.0.1" g.client_ip = env["REMOTE_ADDR"] req = Request(env) req.all_data = {"user": "******", "pass": "******"} res = { "jsonrpc": "2.0", "result": { "status": True, "value": True }, "version": "privacyIDEA test", "detail": { "serial": serial }, "id": 1 } resp = Response(json.dumps(res)) new_response = offline_info(req, resp) jresult = json.loads(new_response.data) self.assertTrue(jresult.get("result").get("value"), jresult) self.assertEqual(jresult.get("detail").get("serial"), serial) # Check the hashvalues in the offline tree auth_items = jresult.get("auth_items") self.assertEqual(len(auth_items), 1) response = auth_items.get("offline")[0].get("response") self.assertEqual(len(response), 100) # check if the counter of the token was increased to 100 tokenobject = get_tokens(serial=serial)[0] self.assertEqual(tokenobject.token.count, 101) delete_policy("pol2")
def test_01_otppin(self): my_user = User("cornelius", realm="r1") set_policy(name="pol1", scope=SCOPE.AUTH, action="{0!s}={1!s}".format(ACTION.OTPPIN, ACTIONVALUE.NONE)) g = FakeFlaskG() P = PolicyClass() g.policy_object = P g.audit_object = FakeAudit() options = {"g": g} # NONE with empty PIN -> success r = auth_otppin(self.fake_check_otp, None, "", options=options, user=my_user) self.assertTrue(r) # NONE with empty PIN -> success, even if the authentication is done # for a serial and not a user, since the policy holds for all realms token = init_token({"type": "HOTP", "otpkey": "1234"}) r = auth_otppin(self.fake_check_otp, token, "", options=options, user=None) self.assertTrue(r) # NONE with some pin -> fail r = auth_otppin(self.fake_check_otp, None, "some pin", options=options, user=my_user) self.assertFalse(r) delete_policy("pol1") set_policy(name="pol1", scope=SCOPE.AUTH, action="{0!s}={1!s}".format(ACTION.OTPPIN, ACTIONVALUE.TOKENPIN)) g = FakeFlaskG() P = PolicyClass() g.policy_object = P g.audit_object = FakeAudit() options = {"g": g} r = auth_otppin(self.fake_check_otp, None, "FAKE", options=options, user=my_user) self.assertTrue(r) r = auth_otppin(self.fake_check_otp, None, "Wrong Pin", options=options, user=my_user) self.assertFalse(r) delete_policy("pol1")
def test_01_check_httpheader_condition(self): self.setUp_user_realms() # enroll a simple pass token with self.app.test_request_context( '/token/init', method='POST', json={ "type": "spass", "pin": "1234", "serial": "sp1", "user": "******", "realm": "realm1", "client": "10.1.2.3" }, headers={'PI-Authorization': self.at}): res = self.app.full_dispatch_request() self.assertEqual(res.status_code, 200) # test an auth request with self.app.test_request_context('/validate/check', method='POST', json={ "pass": "******", "user": "******", "realm": "realm1", "client": "10.1.2.3" }): res = self.app.full_dispatch_request() self.assertEqual(res.status_code, 200) result = res.json self.assertTrue("detail" in result) self.assertEqual( result.get("detail").get("message"), u"matching 1 tokens") # set a policy with conditions # Request from a certain user agent will not see the detail with self.app.test_request_context( '/policy/cond1', method='POST', json={ "action": ACTION.NODETAILSUCCESS, "client": "10.1.2.3", "realm": "realm1", "conditions": [[ CONDITION_SECTION.HTTP_REQUEST_HEADER, "User-Agent", "equals", "SpecialApp", True ]], "scope": SCOPE.AUTHZ }, headers={'PI-Authorization': self.at}): res = self.app.full_dispatch_request() self.assertEqual(res.status_code, 200) # A request with another header will display the details with self.app.test_request_context( '/validate/check', method='POST', headers={"User-Agent": "somethingelse"}, json={ "pass": "******", "user": "******", "realm": "realm1", "client": "10.1.2.3" }): res = self.app.full_dispatch_request() self.assertEqual(res.status_code, 200) result = res.json self.assertTrue("detail" in result) self.assertEqual( result.get("detail").get("message"), u"matching 1 tokens") # A request with the dedicated header will not display the details with self.app.test_request_context( '/validate/check', method='POST', headers={'User-Agent': 'SpecialApp'}, json={ "pass": "******", "user": "******", "realm": "realm1", "client": "10.1.2.3" }): res = self.app.full_dispatch_request() self.assertEqual(res.status_code, 200) result = res.json self.assertFalse("detail" in result) # A request without such a header with self.app.test_request_context('/validate/check', method='POST', headers={"Another": "header"}, json={ "pass": "******", "user": "******", "realm": "realm1", "client": "10.1.2.3" }): res = self.app.full_dispatch_request() self.assertEqual(res.status_code, 403) result = res.json self.assertIn( u"Unknown HTTP header key referenced in condition of policy", result["result"]["error"]["message"]) self.assertIn(u"User-Agent", result["result"]["error"]["message"]) # A request without such a specific header - always has a header with self.app.test_request_context('/validate/check', method='POST', json={ "pass": "******", "user": "******", "realm": "realm1", "client": "10.1.2.3" }): res = self.app.full_dispatch_request() self.assertEqual(res.status_code, 403) result = res.json self.assertIn( u"Unknown HTTP header key referenced in condition of policy", result["result"]["error"]["message"]) self.assertIn(u"User-Agent", result["result"]["error"]["message"]) # Test http header policy with broken matching # update the policy with self.app.test_request_context( '/policy/cond1', method='POST', json={ "action": ACTION.NODETAILSUCCESS, "client": "10.1.2.3", "realm": "realm1", "conditions": [[ CONDITION_SECTION.HTTP_REQUEST_HEADER, "User-Agent", "broken", "SpecialApp", True ]], "scope": SCOPE.AUTHZ }, headers={'PI-Authorization': self.at}): res = self.app.full_dispatch_request() self.assertEqual(res.status_code, 200) # now test the policy with self.app.test_request_context( '/validate/check', method='POST', headers={"User-Agent": "SpecialApp"}, json={ "pass": "******", "user": "******", "realm": "realm1", "client": "10.1.2.3" }): res = self.app.full_dispatch_request() self.assertEqual(res.status_code, 403) result = res.json self.assertIn( u"Invalid comparison in the HTTP header conditions of policy", result["result"]["error"]["message"]) # Also check for an unknown section # update the policy with self.app.test_request_context( '/policy/cond1', method='POST', json={ "action": ACTION.NODETAILSUCCESS, "client": "10.1.2.3", "realm": "realm1", "conditions": [['blabla', "User-Agent", "equals", "SpecialApp", True]], "scope": SCOPE.AUTHZ }, headers={'PI-Authorization': self.at}): res = self.app.full_dispatch_request() self.assertEqual(res.status_code, 200) # now test the policy with self.app.test_request_context( '/validate/check', method='POST', headers={"User-Agent": "SpecialApp"}, json={ "pass": "******", "user": "******", "realm": "realm1", "client": "10.1.2.3" }): res = self.app.full_dispatch_request() self.assertEqual(res.status_code, 403) result = res.json # The text can be "Policy u'cond1' has condition with unknown section" # or "Policy 'cond1' has condition with unknown section" # so we only match for a substring self.assertIn("has condition with unknown section", result["result"]["error"]["message"], result) delete_policy("cond1") remove_token("sp1")
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_16_passthru_assign(self): user = User("cornelius", realm="r1") passw = "{0!s}test".format(self.valid_otp_values[1]) options = {} # remove all tokens of cornelius remove_token(user=user) # create unassigned tokens in realm r1 init_token({ "type": "hotp", "otpkey": "00" * 20, "serial": "TOKFAIL" }, tokenrealms=["r1"]) init_token( { "type": "hotp", "otpkey": self.otpkey, "serial": "TOKMATCH" }, tokenrealms=["r1"]) # A user with no tokens will fail to authenticate self.assertEqual(get_tokens(user=user, count=True), 0) rv = auth_user_passthru(check_user_pass, user, passw, options) self.assertFalse(rv[0]) self.assertEqual(rv[1].get("message"), "The user has no tokens assigned") # Now add a PASSTHRU policy to a RADIUS config radiusmock.setdata(success=True) set_policy(name="pol1", scope=SCOPE.AUTH, action="{0!s}=radiusconfig1".format(ACTION.PASSTHRU)) r = add_radius("radiusconfig1", "1.2.3.4", "testing123", dictionary=DICT_FILE) self.assertTrue(r > 0) set_policy(name="pol2", scope=SCOPE.AUTH, action="{0!s}=6:pin:1234".format(ACTION.PASSTHRU_ASSIGN)) g = FakeFlaskG() g.policy_object = PolicyClass() g.audit_object = FakeAudit() options = {"g": g} rv = auth_user_passthru(check_user_pass, user, passw, options=options) self.assertTrue(rv[0]) self.assertTrue(u"against RADIUS server radiusconfig1 due to 'pol1'" in rv[1].get("message")) self.assertTrue(u"autoassigned TOKMATCH" in rv[1].get("message")) # Check if the token is assigned and can authenticate r = check_user_pass(User("cornelius", "r1"), "test{0!s}".format(self.valid_otp_values[2])) self.assertTrue(r[0]) self.assertEqual(r[1].get("serial"), "TOKMATCH") remove_token("TOKFAIL") remove_token("TOKMATCH") delete_policy("pol1") delete_policy("pol2")
def test_01_setup_eventhandlers(self): # This test create an HOTP token with C/R with a pre-event handler # and the user uses this HOTP token to directly login to /auth # Setup realm rid = save_resolver({ "resolver": self.resolvername1, "type": "passwdresolver", "fileName": PWFILE }) self.assertTrue(rid > 0, rid) (added, failed) = set_realm(self.realm1, [self.resolvername1]) self.assertTrue(len(failed) == 0) self.assertTrue(len(added) == 1) set_default_realm(self.realm1) # set a policy to authenticate against privacyIDEA set_policy("piLogin", scope=SCOPE.WEBUI, action="{0!s}=privacyIDEA".format(ACTION.LOGINMODE)) # set a policy to for otppin=userstore set_policy("otppin", scope=SCOPE.AUTH, action="{0!s}=userstore".format(ACTION.OTPPIN)) # Set a policy to do C/R with HOTP tokens set_policy("crhotp", scope=SCOPE.AUTH, action="{0!s}=hotp".format(ACTION.CHALLENGERESPONSE)) # Create an event handler, that creates HOTP token on /auth with default OTP key eid = set_event( "createtoken", event=["auth"], handlermodule="Token", action="enroll", position="pre", conditions={CONDITION.USER_TOKEN_NUMBER: 0}, options={ "tokentype": "hotp", "user": "******", "additional_params": { 'otpkey': self.otpkey, # We need to set gekey=0, otherwise the Tokenhandler will # generate a random otpkey 'genkey': 0 } }) # cleanup tokens remove_token(user=User("someuser", self.realm1)) # user tries to log in with his userstore password and gets a transaction_id with self.app.test_request_context('/auth', method='POST', data={ "username": "******", "password": "******" }): res = self.app.full_dispatch_request() self.assertEqual(401, res.status_code, res) result = res.json.get("result") self.assertFalse(result.get("status"), result) detail = res.json.get("detail") self.assertEqual("please enter otp: ", detail.get("message")) transaction_id = detail.get("transaction_id") # Check if the token was enrolled toks = get_tokens(user=User("someuser", self.realm1)) self.assertEqual(len(toks), 1) self.assertEqual(toks[0].token.tokentype, "hotp") serial = toks[0].token.serial # Check if the correct otpkey was used hotptoken = toks[0] r = hotptoken.check_otp(self.valid_otp_values[1]) self.assertTrue(r >= 0) # Now the user logs in with the second step of C/R with OTP value of new token with self.app.test_request_context('/auth', method='POST', data={ "username": "******", "transaction_id": transaction_id, "password": self.valid_otp_values[2] }): res = self.app.full_dispatch_request() self.assertEqual(200, res.status_code, res) result = res.json.get("result") self.assertTrue(result.get("status")) self.assertTrue(result.get("value")) # Check that there is still only one token toks = get_tokens(user=User("someuser", self.realm1)) self.assertEqual(len(toks), 1) self.assertEqual(toks[0].token.tokentype, "hotp") self.assertEqual(serial, toks[0].token.serial) # cleanup delete_policy("piLogin") delete_policy("otppin") delete_policy("crhotp") delete_event(eid) remove_token(hotptoken.token.serial)
def test_12_authcache(self): password = "******" username = "******" realm = "myrealm" resolver = "reso001" r = save_resolver({"resolver": "reso001", "type": "passwdresolver", "fileName": "tests/testdata/passwords"}) (added, failed) = set_realm("myrealm", ["reso001"]) def fake_check_user_pass(user, passw, options=None): return True, {"message": "Fake Authentication"} set_policy(name="pol1", scope=SCOPE.AUTH, realm=realm, resolver=resolver, action="{0!s}={1!s}".format(ACTION.AUTH_CACHE, "4h/5m")) g = FakeFlaskG() P = PolicyClass() g.policy_object = P g.audit_object = FakeAudit() options = {"g": g} # This successfully authenticates against the authcache # We have an authentication, that is within the policy timeout AuthCache(username, realm, resolver, _hash_password(password), first_auth=datetime.datetime.utcnow() - timedelta(hours=3), last_auth=datetime.datetime.utcnow() - timedelta(minutes=1)).save() r = auth_cache(fake_check_user_pass, User("cornelius", "myrealm"), password, options=options) self.assertTrue(r[0]) self.assertEqual(r[1].get("message"), "Authenticated by AuthCache." ) # We have an authentication, that is not read from the authcache, # since the authcache first_auth is too old. delete_from_cache(username, realm, resolver, password) AuthCache(username, realm, resolver, _hash_password(password), first_auth=datetime.datetime.utcnow() - timedelta(hours=5), last_auth=datetime.datetime.utcnow() - timedelta( minutes=1)).save() r = auth_cache(fake_check_user_pass, User("cornelius", "myrealm"), password, options=options) self.assertTrue(r[0]) self.assertEqual(r[1].get("message"), "Fake Authentication") # We have an authentication, that is not read from authcache, since # the last_auth is too old = 10 minutes. delete_from_cache(username, realm, resolver, password) AuthCache(username, realm, resolver, _hash_password(password), first_auth=datetime.datetime.utcnow() - timedelta(hours=1), last_auth=datetime.datetime.utcnow() - timedelta( minutes=10)).save() r = auth_cache(fake_check_user_pass, User("cornelius", "myrealm"), password, options=options) self.assertTrue(r[0]) self.assertEqual(r[1].get("message"), "Fake Authentication") # We have a policy, with no special last_auth delete_policy("pol1") set_policy(name="pol1", scope=SCOPE.AUTH, realm=realm, resolver=resolver, action="{0!s}={1!s}".format(ACTION.AUTH_CACHE, "4h")) g = FakeFlaskG() P = PolicyClass() g.policy_object = P g.audit_object = FakeAudit() options = {"g": g} delete_from_cache(username, realm, resolver, password) AuthCache(username, realm, resolver, _hash_password(password), first_auth=datetime.datetime.utcnow() - timedelta(hours=2), last_auth=datetime.datetime.utcnow() - timedelta( hours=1)).save() r = auth_cache(fake_check_user_pass, User("cornelius", "myrealm"), password, options=options) self.assertTrue(r[0]) self.assertEqual(r[1].get("message"), "Authenticated by AuthCache.") # Clean up delete_policy("pol1") delete_realm("myrealm") delete_resolver("reso001")
def test_05_u2f_auth_fails_wrong_issuer(self): # test data taken from # https://fidoalliance.org/specs/fido-u2f-v1.0-ps-20141009/fido-u2f-raw-message-formats-ps-20141009.html#examples serial = "U2F0010BF6F" set_privacyidea_config("u2f.appId", "https://puck.az.intern") pin = "test" # Registration data client_data = "eyJ0eXAiOiJuYXZpZ2F0b3IuaWQuZmluaXNoRW5yb2xsbWVudCIsImNoYWxsZW5nZSI6ImpIakIxaEM2VjA3dDl4ZnNNaDRfOEQ3U1JuSHRFY1BqUTdsaVl3cWxkX009Iiwib3JpZ2luIjoiaHR0cHM6Ly9wdWNrLmF6LmludGVybiIsImNpZF9wdWJrZXkiOiJ1bnVzZWQifQ" reg_data = "BQRHjwxEYFCkLHz3xdrmifKOHl2h17BmRJQ_S1Y9PRAhS2R186T391YE-ryqWis9HSmdp0XpRqUaKk9L8lxJTPpTQF_xFJ_LAsKkPTzKIwUlPIjGZDsLmv0en2Iya17Yz8X8OS89fuxwZOvEok-NQOKUTJP3att_RVe3dEAbq_iOtyAwggJEMIIBLqADAgECAgRVYr6gMAsGCSqGSIb3DQEBCzAuMSwwKgYDVQQDEyNZdWJpY28gVTJGIFJvb3QgQ0EgU2VyaWFsIDQ1NzIwMDYzMTAgFw0xNDA4MDEwMDAwMDBaGA8yMDUwMDkwNDAwMDAwMFowKjEoMCYGA1UEAwwfWXViaWNvIFUyRiBFRSBTZXJpYWwgMTQzMjUzNDY4ODBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABEszH3c9gUS5mVy-RYVRfhdYOqR2I2lcvoWsSCyAGfLJuUZ64EWw5m8TGy6jJDyR_aYC4xjz_F2NKnq65yvRQwmjOzA5MCIGCSsGAQQBgsQKAgQVMS4zLjYuMS40LjEuNDE0ODIuMS41MBMGCysGAQQBguUcAgEBBAQDAgUgMAsGCSqGSIb3DQEBCwOCAQEArBbZs262s6m3bXWUs09Z9Pc-28n96yk162tFHKv0HSXT5xYU10cmBMpypXjjI-23YARoXwXn0bm-BdtulED6xc_JMqbK-uhSmXcu2wJ4ICA81BQdPutvaizpnjlXgDJjq6uNbsSAp98IStLLp7fW13yUw-vAsWb5YFfK9f46Yx6iakM3YqNvvs9M9EUJYl_VrxBJqnyLx2iaZlnpr13o8NcsKIJRdMUOBqt_ageQg3ttsyq_3LyoNcu7CQ7x8NmeCGm_6eVnZMQjDmwFdymwEN4OxfnM5MkcKCYhjqgIGruWkVHsFnJa8qjZXneVvKoiepuUQyDEJ2GcqvhU2YKY1zBFAiEA4ZkIXXyjEPExcMGtW6kJXqYv7UHgjxJR5h3H9w9FV7gCIFGdhxZDqwCQKplDi-LU4WJ45OyCpNK6lGa72eZqUR_k" # Authentication data transaction_id = "05871369157706202013" challenge = "1616515928c389ba9e028d83eb5f63782cbf351ca6abbc81aeb0dddd4895b609" # challenge = "FhZRWSjDibqeAo2D619jeCy_NRymq7yBrrDd3UiVtgk" key_handle = "X_EUn8sCwqQ9PMojBSU8iMZkOwua_R6fYjJrXtjPxfw5Lz1-7HBk68SiT41A4pRMk_dq239FV7d0QBur-I63IA" client_data_auth = "eyJ0eXAiOiJuYXZpZ2F0b3IuaWQuZ2V0QXNzZXJ0aW9uIiwiY2hhbGxlbmdlIjoiRmhaUldTakRpYnFlQW8yRDYxOWplQ3lfTlJ5bXE3eUJyckRkM1VpVnRnayIsIm9yaWdpbiI6Imh0dHBzOi8vcHVjay5hei5pbnRlcm4iLCJjaWRfcHVia2V5IjoidW51c2VkIn0" signature_data = "AQAAAAMwRQIgU8d6waOIRVVydg_AXxediEZGkfFioUjd6FG3OxH2wUMCIQDpxzavJyxRlMwgNmD1Kw-iw_oP2egdshU9hrpxFHTRzQ" # step 1 with self.app.test_request_context('/token/init', method='POST', data={ "type": "u2f", "user": "******", "realm": self.realm1, "serial": serial }, headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertEqual(res.status_code, 200) result = json.loads(res.data.decode('utf8')).get("result") detail = json.loads(res.data.decode('utf8')).get("detail") self.assertEqual(result.get("status"), True) self.assertEqual(result.get("value"), True) # Init step 2 with self.app.test_request_context('/token/init', method='POST', data={ "type": "u2f", "serial": serial, "regdata": reg_data, "clientdata": client_data }, headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertEqual(res.status_code, 200) result = json.loads(res.data.decode('utf8')).get("result") detail = json.loads(res.data.decode('utf8')).get("detail") self.assertEqual(result.get("status"), True) self.assertEqual(result.get("value"), True) # create a challenge in the database db_challenge = Challenge(serial, transaction_id=transaction_id, challenge=challenge, data=None) db_challenge.save() set_policy(name="u2f01", scope=SCOPE.AUTHZ, action="{0!s}=issuer/.*Plugup.*/".format(U2FACTION.REQ)) # Successful C/R authentication with self.app.test_request_context('/validate/check', method='POST', data={ "serial": serial, "pass": "", "transaction_id": transaction_id, "clientdata": client_data_auth, "signaturedata": signature_data }): res = self.app.full_dispatch_request() self.assertEqual(res.status_code, 403) result = json.loads(res.data.decode('utf8')).get("result") self.assertEqual(result.get("status"), False) self.assertEqual(result.get("error").get("code"), ERROR.POLICY) self.assertEqual( result.get("error").get("message"), u'The U2F device is not allowed to authenticate due to policy restriction.' ) delete_policy("u2f01") remove_token(serial)
def test_13_passthru_priorities(self): user = User("cornelius", realm="r1") passw = "test" options = {} # remove all tokens of cornelius remove_token(user=user) # A user with no tokens will fail to authenticate self.assertEqual(get_tokens(user=user, count=True), 0) rv = auth_user_passthru(check_user_pass, user, passw, options) self.assertFalse(rv[0]) self.assertEqual(rv[1].get("message"), "The user has no tokens assigned") # Now set a PASSTHRU policy to the userstore set_policy(name="pol1", scope=SCOPE.AUTH, action="{0!s}=userstore".format(ACTION.PASSTHRU)) g = FakeFlaskG() g.policy_object = PolicyClass() g.audit_object = FakeAudit() options = {"g": g} rv = auth_user_passthru(check_user_pass, user, passw, options=options) self.assertTrue(rv[0]) self.assertEqual(rv[1].get("message"), u"against userstore due to 'pol1'") # Now add a PASSTHRU policy to a RADIUS config radiusmock.setdata(response=radiusmock.AccessAccept) set_policy(name="pol2", scope=SCOPE.AUTH, action="{0!s}=radiusconfig1".format(ACTION.PASSTHRU)) r = add_radius("radiusconfig1", "1.2.3.4", "testing123", dictionary=DICT_FILE) self.assertTrue(r > 0) g = FakeFlaskG() g.policy_object = PolicyClass() g.audit_object = FakeAudit() options = {"g": g} # They will conflict, because they use the same priority with self.assertRaises(PolicyError): auth_user_passthru(check_user_pass, user, passw, options=options) # Lower pol1 priority set_policy(name="pol1", priority=2) rv = auth_user_passthru(check_user_pass, user, passw, options=options) self.assertTrue(rv[0]) self.assertEqual(rv[1].get("message"), u"against RADIUS server radiusconfig1 due to 'pol2'") # Lower pol2 priority set_policy(name="pol2", priority=3) rv = auth_user_passthru(check_user_pass, user, passw, options=options) self.assertTrue(rv[0]) self.assertEqual(rv[1].get("message"), u"against userstore due to 'pol1'") # Add old style priority set_policy(name="pol3", scope=SCOPE.AUTH, action=ACTION.PASSTHRU) rv = auth_user_passthru(check_user_pass, user, passw, options=options) self.assertTrue(rv[0]) self.assertEqual(rv[1].get("message"), u"against userstore due to 'pol3'") set_policy(name="pol3", priority=2) # They will conflict, because they use the same priority with self.assertRaises(PolicyError): auth_user_passthru(check_user_pass, user, passw, options=options) delete_policy("pol3") # Now assign a token to the user. If the user has a token and the # passthru policy is set, the user must not be able to authenticate # with his userstore password. init_token({"serial": "PTHRU", "type": "spass", "pin": "Hallo"}, user=user) rv = auth_user_passthru(check_user_pass, user, passw, options=options) self.assertFalse(rv[0]) self.assertEqual(rv[1].get("message"), "wrong otp pin") remove_token("PTHRU") delete_policy("pol1") delete_policy("pol2")
def test_06_force_totp_parameters(self): set_policy( name="force_2step", action=["totp_2step=force", "enrollTOTP=1", "delete"], scope=SCOPE.ADMIN, ) set_policy( name="2step_params", action=[ "totp_2step_difficulty=12345", "totp_2step_serversize=33", "totp_2step_clientsize=11" ], scope=SCOPE.ENROLL, ) with self.app.test_request_context( '/token/init', method='POST', data={ "type": "totp", "genkey": "1", "2stepinit": "0", # will be forced nevertheless "2step_serversize": "3", "2step_clientsize": "4", "2step_difficulty": "33333", "timeStep": "60", "hashlib": "sha512", "otplen": "8", }, headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data).get("result") self.assertTrue(result.get("status") is True, result) self.assertTrue(result.get("value") is True, result) detail = json.loads(res.data).get("detail") serial = detail.get("serial") otpkey_url = detail.get("otpkey", {}).get("value") server_component = binascii.unhexlify(otpkey_url.split("/")[2]) google_url = detail["googleurl"]["value"] self.assertIn('2step_difficulty=12345', google_url) self.assertIn('2step_salt=11', google_url) self.assertIn('2step_output=64', google_url) # Authentication does not work yet! wrong_otp_value = HmacOtp(digits=8, hashfunc=hashlib.sha512).generate( key=server_component, counter=int(time.time() / 60)) with self.app.test_request_context('/validate/check', method='POST', data={ "serial": serial, "pass": wrong_otp_value }): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data) self.assertTrue(result.get("result").get("status")) self.assertFalse(result.get("result").get("value")) self.assertEqual( result.get("detail").get("message"), u'matching 1 tokens, Token is disabled') client_component = "wrongsize" # 9 bytes hex_client_component = binascii.hexlify(client_component) # Supply a client secret of incorrect size with self.app.test_request_context('/token/init', method='POST', data={ "type": "totp", "serial": serial, "otpkey": hex_client_component, }, headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 400, res) result = json.loads(res.data).get("result") self.assertFalse(result.get("status")) client_component = "correctsize" # 11 bytes hex_client_component = binascii.hexlify(client_component) # Now doing the correct 2nd step with self.app.test_request_context( '/token/init', method='POST', data={ "type": "totp", "serial": serial, "otpkey": hex_client_component, "2step_serversize": "3", # will have no effect "2step_clientsize": "4", "2step_difficulty": "33333" }, headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data).get("result") self.assertTrue(result.get("status") is True, result) self.assertTrue(result.get("value") is True, result) detail = json.loads(res.data).get("detail") otpkey_url = detail.get("otpkey", {}).get("value") otpkey = otpkey_url.split("/")[2] # Now try to authenticate otpkey_bin = binascii.unhexlify(otpkey) otp_value = HmacOtp(digits=8, hashfunc=hashlib.sha512).generate( key=otpkey_bin, counter=int(time.time() / 60)) with self.app.test_request_context('/validate/check', method='POST', data={ "serial": serial, "pass": otp_value }): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data).get("result") self.assertEqual(result.get("status"), True) self.assertEqual(result.get("value"), True) # Check serversize self.assertEqual(len(server_component), 33) # Check that the OTP key is what we expected it to be expected_secret = pbkdf2(binascii.hexlify(server_component), client_component, 12345, 64) self.assertEqual(otpkey_bin, expected_secret) with self.app.test_request_context('/token/' + serial, method='DELETE', headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) delete_policy("force_2step") delete_policy("2step_params")
def test_05_init_totp_token(self): set_policy( name="allow_2step", action=["totp_2step=allow", "enrollTOTP=1", "delete"], scope=SCOPE.ADMIN, ) with self.app.test_request_context('/token/init', method='POST', data={ "type": "totp", "genkey": "1", "2stepinit": "1" }, headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data).get("result") self.assertTrue(result.get("status") is True, result) self.assertTrue(result.get("value") is True, result) detail = json.loads(res.data).get("detail") serial = detail.get("serial") otpkey_url = detail.get("otpkey", {}).get("value") server_component = binascii.unhexlify(otpkey_url.split("/")[2]) google_url = detail["googleurl"]["value"] self.assertIn('2step_difficulty=10000', google_url) self.assertIn('2step_salt=8', google_url) self.assertIn('2step_output=20', google_url) self.assertEqual(detail['2step_difficulty'], 10000) self.assertEqual(detail['2step_salt'], 8) self.assertEqual(detail['2step_output'], 20) client_component = "VRYSECRT" checksum = hashlib.sha1(client_component).digest()[:4] base32check_client_component = base64.b32encode( checksum + client_component).strip("=") # Try to do a 2stepinit on a second step will raise an error with self.app.test_request_context('/token/init', method='POST', data={ "type": "totp", "2stepinit": "1", "serial": serial, "otpkey": base32check_client_component, "otpkeyformat": "base32check" }, headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertEqual(res.status_code, 400) result = json.loads(res.data).get("result") self.assertIn( '2stepinit is only to be used in the first initialization step', result.get("error").get("message")) # Invalid base32check will raise an error with self.app.test_request_context( '/token/init', method='POST', data={ "type": "totp", "2stepinit": "1", "serial": serial, "otpkey": "A" + base32check_client_component[1:], "otpkeyformat": "base32check" }, headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertEqual(res.status_code, 400) result = json.loads(res.data).get("result") self.assertIn('Malformed base32check data: Incorrect checksum', result.get("error").get("message")) # Authentication does not work yet! wrong_otp_value = HmacOtp().generate(key=server_component, counter=int(time.time() / 30)) with self.app.test_request_context('/validate/check', method='POST', data={ "serial": serial, "pass": wrong_otp_value }): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data) self.assertTrue(result.get("result").get("status")) self.assertFalse(result.get("result").get("value")) self.assertEqual( result.get("detail").get("message"), u'matching 1 tokens, Token is disabled') # Now doing the correct 2nd step with self.app.test_request_context('/token/init', method='POST', data={ "type": "totp", "serial": serial, "otpkey": base32check_client_component, "otpkeyformat": "base32check" }, headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data).get("result") self.assertTrue(result.get("status") is True, result) self.assertTrue(result.get("value") is True, result) detail = json.loads(res.data).get("detail") otpkey_url = detail.get("otpkey", {}).get("value") otpkey = otpkey_url.split("/")[2] self.assertNotIn('2step', detail) # Now try to authenticate otpkey_bin = binascii.unhexlify(otpkey) otp_value = HmacOtp().generate(key=otpkey_bin, counter=int(time.time() / 30)) with self.app.test_request_context('/validate/check', method='POST', data={ "serial": serial, "pass": otp_value }): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data).get("result") self.assertEqual(result.get("status"), True) self.assertEqual(result.get("value"), True) # Check that the OTP key is what we expected it to be expected_secret = pbkdf2(binascii.hexlify(server_component), client_component, 10000, 20) self.assertEqual(otpkey_bin, expected_secret) with self.app.test_request_context('/token/' + serial, method='DELETE', headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) delete_policy("allow_2step")
def test_03b_api_authenticate_client(self): # Test the /validate/check endpoints without the smartphone endpoint /ttype/push self.setUp_user_realms() # get enrolled push token toks = get_tokens(tokentype="push") self.assertEqual(len(toks), 1) tokenobj = toks[0] # set PIN tokenobj.set_pin("pushpin") tokenobj.add_user(User("cornelius", self.realm1)) # We mock the ServiceAccountCredentials, since we can not directly contact the Google API with mock.patch('privacyidea.lib.smsprovider.FirebaseProvider.ServiceAccountCredentials') as mySA: # alternative: side_effect instead of return_value mySA.from_json_keyfile_name.return_value = myCredentials(myAccessTokenInfo("my_bearer_token")) # add responses, to simulate the communication to firebase responses.add(responses.POST, 'https://fcm.googleapis.com/v1/projects/test-123456/messages:send', body="""{}""", content_type="application/json") # Send the first authentication request to trigger the challenge with self.app.test_request_context('/validate/check', method='POST', data={"user": "******", "realm": self.realm1, "pass": "******"}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) jsonresp = res.json self.assertFalse(jsonresp.get("result").get("value")) self.assertTrue(jsonresp.get("result").get("status")) self.assertEqual(jsonresp.get("detail").get("serial"), tokenobj.token.serial) self.assertTrue("transaction_id" in jsonresp.get("detail")) transaction_id = jsonresp.get("detail").get("transaction_id") self.assertEqual(jsonresp.get("detail").get("message"), DEFAULT_CHALLENGE_TEXT) # Our ServiceAccountCredentials mock has not been called because we use a cached token self.assertEqual(len(mySA.from_json_keyfile_name.mock_calls), 0) self.assertIn(FIREBASE_FILE, get_app_local_store()["firebase_token"]) # The mobile device has not communicated with the backend, yet. # The user is not authenticated! with self.app.test_request_context('/validate/check', method='POST', data={"user": "******", "realm": self.realm1, "pass": "", "transaction_id": transaction_id}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) jsonresp = res.json # Result-Value is false, the user has not answered the challenge, yet self.assertFalse(jsonresp.get("result").get("value")) # Now the smartphone communicates with the backend and the challenge in the database table # is marked as answered successfully. challengeobject_list = get_challenges(serial=tokenobj.token.serial, transaction_id=transaction_id) challengeobject_list[0].set_otp_status(True) with self.app.test_request_context('/validate/check', method='POST', data={"user": "******", "realm": self.realm1, "pass": "", "state": transaction_id}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) jsonresp = res.json # Result-Value is True, since the challenge is marked resolved in the DB self.assertTrue(jsonresp.get("result").get("value")) # We mock the ServiceAccountCredentials, since we can not directly contact the Google API # Do single shot auth with waiting # Also mock time.time to be 4000 seconds in the future (exceeding the validity of myAccessTokenInfo), # so that we fetch a new auth token with mock.patch('privacyidea.lib.smsprovider.FirebaseProvider.time') as mock_time: mock_time.time.return_value = time.time() + 4000 with mock.patch('privacyidea.lib.smsprovider.FirebaseProvider.ServiceAccountCredentials') as mySA: # alternative: side_effect instead of return_value mySA.from_json_keyfile_name.return_value = myCredentials(myAccessTokenInfo("my_new_bearer_token")) # add responses, to simulate the communication to firebase responses.add(responses.POST, 'https://fcm.googleapis.com/v1/projects/test-123456/messages:send', body="""{}""", content_type="application/json") # In two seconds we need to run an update on the challenge table. Timer(2, self.mark_challenge_as_accepted).start() set_policy("push1", scope=SCOPE.AUTH, action="{0!s}=20".format(PUSH_ACTION.WAIT)) # Send the first authentication request to trigger the challenge with self.app.test_request_context('/validate/check', method='POST', data={"user": "******", "realm": self.realm1, "pass": "******"}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) jsonresp = res.json # We successfully authenticated! YEAH! self.assertTrue(jsonresp.get("result").get("value")) self.assertTrue(jsonresp.get("result").get("status")) self.assertEqual(jsonresp.get("detail").get("serial"), tokenobj.token.serial) delete_policy("push1") # Our ServiceAccountCredentials mock has been called once because we fetched a new token self.assertEqual(len(mySA.from_json_keyfile_name.mock_calls), 1) self.assertIn(FIREBASE_FILE, get_app_local_store()["firebase_token"]) self.assertEqual(get_app_local_store()["firebase_token"][FIREBASE_FILE].access_token, "my_new_bearer_token") # Authentication fails, if the push notification is not accepted within the configured time with mock.patch('privacyidea.lib.smsprovider.FirebaseProvider.ServiceAccountCredentials') as mySA: # alternative: side_effect instead of return_value mySA.from_json_keyfile_name.return_value = myCredentials(myAccessTokenInfo("my_bearer_token")) # add responses, to simulate the communication to firebase responses.add(responses.POST, 'https://fcm.googleapis.com/v1/projects/test-123456/messages:send', body="""{}""", content_type="application/json") set_policy("push1", scope=SCOPE.AUTH, action="{0!s}=1".format(PUSH_ACTION.WAIT)) # Send the first authentication request to trigger the challenge with self.app.test_request_context('/validate/check', method='POST', data={"user": "******", "realm": self.realm1, "pass": "******"}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) jsonresp = res.json # We fail to authenticate! Oh No! self.assertFalse(jsonresp.get("result").get("value")) self.assertTrue(jsonresp.get("result").get("status")) self.assertEqual(jsonresp.get("detail").get("serial"), tokenobj.token.serial) delete_policy("push1")
def test_01_check_token_action(self): g.logged_in_user = {"username": "******", "role": "admin"} builder = EnvironBuilder(method='POST', data={'serial': "OATH123456"}, headers={}) env = builder.get_environ() # Set the remote address so that we can filter for it env["REMOTE_ADDR"] = "10.0.0.1" req = Request(env) req.all_data = {"serial": "SomeSerial"} # Set a policy, that does allow the action set_policy(name="pol1", scope=SCOPE.ADMIN, action="enable", client="10.0.0.0/8") g.policy_object = PolicyClass() # Action enable is cool r = check_base_action(request=req, action="enable") self.assertTrue(r) # Another action - like "disable" - is not allowed # An exception is self.assertRaises(PolicyError, check_base_action, req, "disable") # Action delete is not allowed self.assertRaises(PolicyError, check_base_action, req, "delete") # check action with a token realm set_policy(name="pol1", scope=SCOPE.ADMIN, action="enable", client="10.0.0.0/8", realm="realm1") set_policy(name="pol2", scope=SCOPE.ADMIN, action="*", client="10.0.0.0/8", realm="realm2") g.policy_object = PolicyClass() # set a polrealm1 and a polrealm2 # setup realm1 self.setUp_user_realms() # setup realm2 self.setUp_user_realm2() tokenobject = init_token({ "serial": "POL001", "type": "hotp", "otpkey": "1234567890123456" }) r = set_realms("POL001", [self.realm1]) tokenobject = init_token({ "serial": "POL002", "type": "hotp", "otpkey": "1234567890123456" }) r = set_realms("POL002", [self.realm2]) # Token in realm1 can not be deleted req.all_data = {"serial": "POL001"} self.assertRaises(PolicyError, check_base_action, req, "delete") # while token in realm2 can be deleted req.all_data = {"serial": "POL002"} r = check_base_action(req, action="delete") self.assertTrue(r) # A normal user can "disable", since no user policies are defined. g.logged_in_user = {"username": "******", "role": "user"} r = check_base_action(req, "disable") self.assertTrue(r) delete_policy("pol1") delete_policy("pol2") remove_token("POL001") remove_token("POL002")