import unittest import sys import os import pytest import pyotp sys.path.append( os.path.dirname( os.path.dirname(os.path.abspath(__file__)) ) ) import app import config class TestUOTP(unittest.TestCase): app_client = None admin_name = 'admin' admin_seed = None admin_realm = 'ungleich-admin' auth_realm = 'ungleich-auth' etcd_client = config.etcd_client @classmethod def setUpClass(cls): app.app.config['TESTING'] = True os.environ['BASE_PREFIX'] = '/test/uotp/' os.environ['ADMIN_REALM'] = TestUOTP.admin_realm os.environ['AUTH_REALM'] = TestUOTP.auth_realm with app.app.test_client() as client: with app.app.app_context(): app.create_admin_if_dont_exists(TestUOTP.etcd_client) entry = TestUOTP.etcd_client.get( os.path.join( os.environ['BASE_PREFIX'], os.environ['ADMIN_REALM'], 'admin' ), value_in_json=True ) assert entry is not None TestUOTP.app_client = client TestUOTP.admin_seed = entry.value['seed'] return super().setUpClass() @classmethod def tearDownClass(cls): TestUOTP.etcd_client.client.delete_prefix(os.environ['BASE_PREFIX']) del os.environ['BASE_PREFIX'] del os.environ['ADMIN_REALM'] del os.environ['AUTH_REALM'] return super().tearDownClass() def get_otp_list(self): r = self.app_client.get('/list', json={ 'admin-name': self.admin_name, 'admin-realm': self.admin_realm, 'admin-token': pyotp.TOTP(self.admin_seed).now() } ) return r def create_otp(self, _name, _realm, _admin_name, _admin_realm, _admin_seed): r = self.app_client.post('/create', json={ "name": _name, "realm": _realm, "admin-name": _admin_name, "admin-realm": _admin_realm, "admin-token": pyotp.TOTP(_admin_seed).now() }) return r def verify_otp(self, _name, _realm, _seed, _auth_name, _auth_realm, _auth_seed): r = self.app_client.get('/verify', json={ "name": _name, "realm": _realm, "token": pyotp.TOTP(_seed).now(), "auth-name": _auth_name, "auth-realm": _auth_realm, "auth-token": pyotp.TOTP(_auth_seed).now() }) return r def test_list(self): r = self.get_otp_list() self.assertEqual(r.status_code, 200) self.assertIn( '{}/{}'.format(self.admin_realm, self.admin_name), r.json ) def test_create(self): _name = 'auth' _realm = 'ungleich-auth' # Test Successful case i.e Admin creating OTP Account r = self.create_otp(_name, _realm, self.admin_name, self.admin_realm, self.admin_seed) self.assertEqual(r.status_code, 200) r = self.get_otp_list() self.assertIn( '{}/{}'.format(_realm, _name), r.json ) # Test Unsuccesful Creation i.e User from non-admin realm # tries to create OTP account # Get Auth Account entry = self.etcd_client.get( os.path.join( os.environ['BASE_PREFIX'], _realm, _name ), value_in_json=True ) _adversery_name = 'adversery' _adversery_realm = 'ungleich-admin' r = self.create_otp(_adversery_name, _adversery_realm, _name, _realm, entry.value['seed']) self.assertEqual(r.status_code, 400) r = self.get_otp_list() self.assertNotIn( '{}/{}'.format(_adversery_realm, _adversery_name), r.json ) def test_verify(self): _auth_name = 'verification-auth' _auth_realm = 'ungleich-auth' _auth_seed = None r = self.create_otp(_auth_name, _auth_realm, self.admin_name, self.admin_realm, self.admin_seed) self.assertEqual(r.status_code, 200) entry = self.etcd_client.get( os.path.join( os.environ['BASE_PREFIX'], _auth_realm, _auth_name ), value_in_json=True ) self.assertIsNotNone(entry) _auth_seed = entry.value['seed'] # This should work r = self.verify_otp(self.admin_name, self.admin_realm, self.admin_seed, _auth_name, _auth_realm, _auth_seed) self.assertEqual(r.status_code, 200) # This should not work i.e should rerturn 400 # because the auth_seed is not correct r = self.verify_otp(self.admin_name, self.admin_realm, self.admin_seed, _auth_name, _auth_realm, 'meowmeowmeow') self.assertEqual(r.status_code, 400) # This should not work i.e should rerturn 400 # because the auth user is not from ungleich-auth realm r = self.verify_otp(self.admin_name, self.admin_realm, self.admin_seed, self.admin_name, self.admin_realm, self.admin_seed) self.assertEqual(r.status_code, 400) if __name__ == '__main__': unittest.main()