def test_12_access_timeout(self): """ When Duo is down, handle it well. """ os.environ['auth_control_file'] = '/tmp/foo' def too_slow_authentication(): ''' This function is waiting 5 seconds and the responding true. The idea here is that 5s is "too long" (we use a 2s alarm below) but then pretend the check passed. This True should be ignored since we're going to timeout and thus fail, but it's here to be True in case the test breaks down and lets someone in. ''' time.sleep(5) # The return statement should never be reached:because of the alarm. return True # pragma: no cover with mock.patch('duo_openvpn.DuoOpenVPN') as mock_duo: duo_instance = mock_duo.return_value duo_instance.duo_timeout = 2 duo_instance.failopen = False with self.assertRaises(SystemExit) as exiting, \ mock.patch('duo_openvpn.open', create=True, return_value=mock.MagicMock(spec=StringIO())) as mock_open, \ mock.patch.object(duo_instance, 'main_authentication', side_effect=too_slow_authentication): # our timeout is 2s, beating the 5s delay. Actual times are irrelevant, # so long as we alarm, and alarm before a response comes back. # We fail closed, meaning that we should deny the user. duo_openvpn.main() file_handle = mock_open.return_value.__enter__.return_value file_handle.write.assert_called_with('0') self.assertEqual(exiting.exception.code, 0)
def test_05_write_failed(self): """ When we can't write out auth_control_file, we must die """ os.environ['auth_control_file'] = '/tmp/foo' with mock.patch('duo_openvpn.DuoOpenVPN'), \ self.assertRaises(SystemExit) as exiting, \ mock.patch('duo_openvpn.open', create=True, side_effect=IOError): duo_openvpn.main() self.assertEqual(exiting.exception.code, 1)
def test_01_no_control_file(self): """ When there's no auth_control_file, we must die. """ with mock.patch('sys.stdout', new=StringIO()) as fake_out, \ self.assertRaises(SystemExit) as exiting: duo_openvpn.main() self.assertEqual(exiting.exception.code, 1) self.assertEqual('No auth_control_file env variable provided.\n', fake_out.getvalue())
def test_11_access_granted(self): """ When auth is allowed, let someone in. """ os.environ['auth_control_file'] = '/tmp/foo' with mock.patch('duo_openvpn.DuoOpenVPN') as mock_duo, \ self.assertRaises(SystemExit) as exiting, \ mock.patch('duo_openvpn.open', create=True, return_value=mock.MagicMock(spec=StringIO())) as mock_open, \ mock.patch.object(mock_duo.return_value, 'main_authentication', return_value=True): duo_openvpn.main() file_handle = mock_open.return_value.__enter__.return_value file_handle.write.assert_called_with('1') self.assertEqual(exiting.exception.code, 0)
def assert_auth(self, environ, expected_control, send_control=True): self.mox.ReplayAll() with tempfile.NamedTemporaryFile() as control: if send_control: environ['control'] = control.name with self.assertRaises(SystemExit) as cm: duo_openvpn.main( environ=environ, Client=mock_client_factory(self.expected_calls), ) self.mox.VerifyAll() control.seek(0, os.SEEK_SET) output = control.read() self.assertEqual(expected_control, output) if expected_control == '1': self.assertEqual(0, cm.exception.args[0]) else: self.assertEqual(1, cm.exception.args[0])