def run_proxy(): parser = argparse.ArgumentParser() parser.add_argument('-p', '--port', help='The port the dispatcher runs on') parser.add_argument('-m', '--manager', help="hostname:port of the manager") parser.add_argument('--bind', help="bind to interface. Default 127.0.0.1", default='127.0.0.1') parser.add_argument('--sslcert', help='The SSL certficate to use', default=None) parser.add_argument('--sslkey', help='The SSL key to use', default=None) parser.add_argument('--fingerprint', help='Pin certifcate to fingerprint', default=None) parser.add_argument('--disable-verifyhostname', help='Disable hostname verification. If fingerprint is specified it gets precedence', dest="verify_hostname", action='store_false', default=None) parser.add_argument('--debug', help='Set log level to debug', default=False, action='store_true') parser.add_argument('--log-config', help='Provide a python logging config file', default=None) args = parser.parse_args(args=filter_args()) manager_hostname, manager_port = args.manager.split(':') certfile = args.sslcert if args.sslcert else None keyfile = args.sslkey if args.sslcert else None log_level = logging.DEBUG if args.debug else logging.INFO log_config = args.log_config init_logging('dipatcher', level=log_level, config_file=log_config) client = PixelatedDispatcherClient(manager_hostname, manager_port, cacert=certfile, fingerprint=args.fingerprint, assert_hostname=args.verify_hostname) client.validate_connection() dispatcher = DispatcherProxy(client, bindaddr=args.bind, keyfile=keyfile, certfile=certfile) dispatcher.serve_forever()
def test_that_503_raises_an_not_available_error(self): self.client = PixelatedDispatcherClient('localhost', 12345, ssl=False) @urlmatch(path='/agents') def list_agents(url, request): return {'status_code': 503, 'reason': 'some reason'} with HTTMock(list_agents, not_found_handler): self.assertRaises(PixelatedNotAvailableHTTPError, self.client.list)
def test_hostname_gets_checkt_by_default(self, session_mock): some_ca = 'some cert' self.client = PixelatedDispatcherClient('localhost', 12345, cacert=some_ca) session = session_mock.return_value self.client.validate_connection() session.mount.assert_called_once_with('https://', ANY) adapter = session.mount.call_args[0][1] self.assertEqual(VERIFY_HOSTNAME, adapter._assert_hostname)
def test_assert_hostname_gets_past_to_tlsv1_adapter(self, session_mock): some_ca = 'some cert' self.client = PixelatedDispatcherClient('localhost', 12345, cacert=some_ca, assert_hostname=False) session = session_mock.return_value self.client.validate_connection() session.mount.assert_called_once_with('https://', ANY) adapter = session.mount.call_args[0][1] self.assertEqual(False, adapter._assert_hostname)
def _verify_enforce_tls(self, session, func): some_ca = 'some cert' fingerprint = 'fingerprint' self.client = PixelatedDispatcherClient('localhost', 12345, cacert=some_ca, assert_hostname=False, fingerprint=fingerprint) func(self.client) session.mount.assert_called_once_with('https://', ANY) adapter = session.mount.call_args[0][1] self.assertEqual(False, adapter._assert_hostname) self.assertEqual(fingerprint, adapter._assert_fingerprint)
def test_validate_connection(self, session_mock): some_ca = 'some cert' some_fingerprint = 'some Fingerprint' self.client = PixelatedDispatcherClient('localhost', 12345, cacert=some_ca, fingerprint=some_fingerprint) session = session_mock.return_value self.client.validate_connection() session.mount.assert_called_once_with('https://', ANY) session.get.assert_called_once_with('https://localhost:12345/agents', verify=some_ca) adapter = session.mount.call_args[0][1] self.assertEqual(some_fingerprint, adapter._assert_fingerprint)
def test_that_call_without_ssl_is_possible(self): self.client = PixelatedDispatcherClient('localhost', 12345, ssl=False) @urlmatch(path='/agents') def list_agents(url, request): if url.scheme == 'https': return {'status_code': 500} else: return { 'status_code': 200, 'content': {'agents': []} } with HTTMock(list_agents, not_found_handler): self.client.list()
def _dispatcher_proxy(self): dispatcher = DispatcherProxy(PixelatedDispatcherClient( 'localhost', DEFAULT_PORT, cacert=cafile(), assert_hostname=False), port=12345, certfile=certfile(), keyfile=keyfile()) return SmokeTest.Server(dispatcher.serve_forever, dispatcher.shutdown, thread_name='PixelatedDispatcherProxy')
def run_proxy(): parser = argparse.ArgumentParser() parser.add_argument('-m', '--manager', help='hostname:port of the manager') parser.add_argument('--banner', help='banner file to show on login screen', default='_login_screen_message.html') parser.add_argument('--bind', help="interface to bind to (default: 127.0.0.1)", default='127.0.0.1') parser.add_argument('--sslcert', help='proxy HTTP server SSL certificate', default=None) parser.add_argument('--sslkey', help='proxy HTTP server SSL key', default=None) parser.add_argument('--fingerprint', help='pin certificate to fingerprint', default=None) parser.add_argument('--disable-verifyhostname', help='disable hostname verification; if fingerprint is specified it gets precedence', dest="verify_hostname", action='store_false', default=None) parser.add_argument('--debug', help='set log level to debug and auto reload files', default=False, action='store_true') parser.add_argument('--log-config', help='provide a python logging config file', default=None) parser.add_argument('--daemon', help='start in daemon mode and put process into background', default=False, action='store_true') parser.add_argument('--pidfile', help='path for pid file. By default none is created', default=None) args = parser.parse_args(args=filter_args()) manager_hostname, manager_port = args.manager.split(':') certfile = args.sslcert if args.sslcert else None keyfile = args.sslkey if args.sslcert else None manager_cafile = certfile if args.fingerprint is None else False log_level = logging.DEBUG if args.debug else logging.INFO log_config = args.log_config client = PixelatedDispatcherClient(manager_hostname, manager_port, cacert=manager_cafile, fingerprint=args.fingerprint, assert_hostname=args.verify_hostname) client.validate_connection() dispatcher = DispatcherProxy(client, bindaddr=args.bind, keyfile=keyfile, certfile=certfile, banner=args.banner, debug=args.debug) if args.daemon: pidfile = TimeoutPIDLockFile(args.pidfile, acquire_timeout=PID_ACQUIRE_TIMEOUT_IN_S) if args.pidfile else None can_use_pidfile(pidfile) with daemon.DaemonContext(pidfile=pidfile): # init logging only after we have spawned the sub process. Otherwise there might be some hickups init_logging('proxy', level=log_level, config_file=log_config) dispatcher.serve_forever() else: init_logging('proxy', level=log_level, config_file=log_config) dispatcher.serve_forever()
class MultipileClientTest(unittest.TestCase): def setUp(self): self.client = PixelatedDispatcherClient('localhost', 12345) def test_exception_raised_if_not_available(self): with HTTMock(not_found_handler): self.assertRaises(PixelatedHTTPError, self.client.get_agent, 'test') self.assertRaises(PixelatedHTTPError, self.client.list) self.assertRaises(PixelatedHTTPError, self.client.get_agent_runtime, 'test') self.assertRaises(PixelatedHTTPError, self.client.start, 'test') self.assertFalse(self.client.agent_exists('test')) def test_list(self): expected = [ {'name': 'first', 'state': 'stopped', 'uri': 'https://*****:*****@urlmatch(path='/agents') def list_agents(url, request): return { 'status_code': 200, 'content': {'agents': expected} } with HTTMock(list_agents, not_found_handler): agents = self.client.list() self.assertEqual(expected, agents) def test_running(self): expected = [ {'name': 'first', 'state': 'stopped', 'uri': 'https://*****:*****@urlmatch(path='/agents') def list_agents(url, request): return { 'status_code': 200, 'content': {'agents': expected} } with HTTMock(list_agents, not_found_handler): agents = self.client.list() self.assertEqual(expected, agents) def test_get_agent(self): expected = {'name': 'first', 'state': 'stopped', 'uri': 'https://*****:*****@urlmatch(path='^/agents/first$') def fetch_agent(url, request): return { 'status_code': 200, 'content': expected } with HTTMock(fetch_agent, not_found_handler): agent = self.client.get_agent('first') self.assertEqual(expected, agent) def test_agent_exists(self): @urlmatch(path=r'^/agents/first$') def first_agent(url, request): return {'status_code': 200, 'content': {}} with HTTMock(first_agent, not_found_handler): self.assertTrue(self.client.agent_exists('first')) def test_agent_runtime(self): @urlmatch(path=r'^/agents/first/runtime$') def first_agent_runtime(url, request): return {'status_code': 200, 'content': {'port': 5000}} with HTTMock(first_agent_runtime, not_found_handler): runtime = self.client.get_agent_runtime('first') self.assertEqual({'port': 5000}, runtime) def test_start(self): expected = {'name': 'first', 'state': 'running', 'uri': 'https://*****:*****@urlmatch(path=r'^/agents/first/state$') def start_agent(url, request): if request.body == '{"state": "running"}': return {'status_code': 200, 'content': expected} else: return {'status_code': 400} with HTTMock(start_agent, not_found_handler): actual = self.client.start('first') self.assertEqual(expected, actual) def test_stop(self): expected = {'name': 'first', 'state': 'stopped', 'uri': 'https://*****:*****@urlmatch(path=r'^/agents/first/state$') def stop_agent(url, request): return {'status_code': 200, 'content': expected} with HTTMock(stop_agent, not_found_handler): actual = self.client.stop('first') self.assertEqual(expected, actual) def test_authenticate(self): @urlmatch(path=r'^/agents/first/authenticate', method='POST') def auth_agent(url, request): if request.headers['Content-Type'] != 'application/json': return {'status_code': 403} if request.body == '{"password": "******"}': return {'status_code': 200, 'content': {}} else: return {'status_code': 403} with HTTMock(auth_agent, not_found_handler): self.client.authenticate('first', 'password') def test_add(self): @urlmatch(path=r'^/agents', method='POST') def add_agent(url, request): return {'status_code': 201} with HTTMock(add_agent, not_found_handler): self.client.add('first', 'password') def test_reset_data(self): expected = {'name': 'first', 'state': 'stopped', 'uri': 'https://*****:*****@urlmatch(path=r'^/agents/first/reset_data', method='PUT') def reset_agent_data(url, request): return {'status_code': 200, 'content': expected} with HTTMock(reset_agent_data, not_found_handler): response = self.client.reset_data('first') return self.assertEqual(expected, response) def test_memory_usage(self): expected = {'total_usage': 1234, 'average_usage': 1234, 'agents': [{'name': 'test', 'memory_usage': 1234}]} @urlmatch(path=r'^/stats/memory_usage', method='GET') def memory_usage(url, request): return {'status_code': 200, 'content': expected} with HTTMock(memory_usage, not_found_handler): usage = self.client.memory_usage() self.assertEqual(expected, usage) @patch('requests.Session') def test_that_certificates_are_verified_by_default(self, requests_mock): session = requests_mock.return_value verify_certificate = True self._assert_cacert_used(session, verify_certificate) @patch('requests.Session') def test_that_cacert_gets_used(self, requests_mock): some_ca = 'some cert' self.client = PixelatedDispatcherClient('localhost', 12345, cacert=some_ca) session = requests_mock.return_value self._assert_cacert_used(session, some_ca) def _assert_cacert_used(self, session, cacert): self.client.list() session.get.assert_called_once_with('https://*****:*****@urlmatch(path='/agents') def list_agents(url, request): if url.scheme == 'https': return {'status_code': 500} else: return { 'status_code': 200, 'content': {'agents': []} } with HTTMock(list_agents, not_found_handler): self.client.list() def test_that_503_raises_an_not_available_error(self): self.client = PixelatedDispatcherClient('localhost', 12345, ssl=False) @urlmatch(path='/agents') def list_agents(url, request): return {'status_code': 503, 'reason': 'some reason'} with HTTMock(list_agents, not_found_handler): self.assertRaises(PixelatedNotAvailableHTTPError, self.client.list) @patch('requests.Session') def test_validate_connection(self, session_mock): some_ca = 'some cert' some_fingerprint = 'some Fingerprint' self.client = PixelatedDispatcherClient('localhost', 12345, cacert=some_ca, fingerprint=some_fingerprint) session = session_mock.return_value self.client.validate_connection() session.mount.assert_called_once_with('https://', ANY) session.get.assert_called_once_with('https://*****:*****@urlmatch(path='/agents') def list_agents(url, request): return {'status_code': 503, 'reason': 'some reason'} with HTTMock(list_agents, not_found_handler): self.client.validate_connection() def test_validate_connection_allows_timeout(self): self.count = 0 @urlmatch(path='/agents') def list_agents(url, request): self.count = self.count + 1 if self.count < 2: raise ConnectionError('Test Error') else: return {'status_code': 503, 'reason': 'some reason'} with HTTMock(list_agents, not_found_handler): self.client.validate_connection(timeout_in_s=5) @patch('requests.Session') def test_assert_hostname_gets_past_to_tlsv1_adapter(self, session_mock): some_ca = 'some cert' self.client = PixelatedDispatcherClient('localhost', 12345, cacert=some_ca, assert_hostname=False) session = session_mock.return_value self.client.validate_connection() session.mount.assert_called_once_with('https://', ANY) adapter = session.mount.call_args[0][1] self.assertEqual(False, adapter._assert_hostname) @patch('requests.Session') def test_hostname_gets_checkt_by_default(self, session_mock): some_ca = 'some cert' self.client = PixelatedDispatcherClient('localhost', 12345, cacert=some_ca) session = session_mock.return_value self.client.validate_connection() session.mount.assert_called_once_with('https://', ANY) adapter = session.mount.call_args[0][1] self.assertEqual(VERIFY_HOSTNAME, adapter._assert_hostname) @patch('requests.Session') def test_that_post_uses_tls_adapter_with_params(self, session_mock): session = session_mock.return_value def call_post(client): client._post('http://localhost/some/path') self._verify_enforce_tls(session, call_post) @patch('requests.Session') def test_that_put_uses_tls_adapter_with_params(self, session_mock): session = session_mock.return_value def call_put(client): client._put('http://localhost/some/path') self._verify_enforce_tls(session, call_put) def _verify_enforce_tls(self, session, func): some_ca = 'some cert' fingerprint = 'fingerprint' self.client = PixelatedDispatcherClient('localhost', 12345, cacert=some_ca, assert_hostname=False, fingerprint=fingerprint) func(self.client) session.mount.assert_called_once_with('https://', ANY) adapter = session.mount.call_args[0][1] self.assertEqual(False, adapter._assert_hostname) self.assertEqual(fingerprint, adapter._assert_fingerprint)
def test_initialize_without_ssl(self): PixelatedDispatcherClient('hostname', 1234, ssl=False)
def test_initialize_with_ssl_ca(self): PixelatedDispatcherClient('hostname', 1234, cacert=True)
def test_that_cacert_gets_used(self, requests_mock): some_ca = 'some cert' self.client = PixelatedDispatcherClient('localhost', 12345, cacert=some_ca) session = requests_mock.return_value self._assert_cacert_used(session, some_ca)
def run_proxy(): parser = argparse.ArgumentParser() parser.add_argument('-m', '--manager', help='hostname:port of the manager') parser.add_argument('--banner', help='banner file to show on login screen', default='_login_screen_message.html') parser.add_argument('--bind', help="interface to bind to (default: 127.0.0.1)", default='127.0.0.1') parser.add_argument('--sslcert', help='proxy HTTP server SSL certificate', default=None) parser.add_argument('--sslkey', help='proxy HTTP server SSL key', default=None) parser.add_argument('--fingerprint', help='pin certificate to fingerprint', default=None) parser.add_argument( '--disable-verifyhostname', help= 'disable hostname verification; if fingerprint is specified it gets precedence', dest="verify_hostname", action='store_false', default=None) parser.add_argument('--debug', help='set log level to debug and auto reload files', default=False, action='store_true') parser.add_argument('--log-config', help='provide a python logging config file', default=None) parser.add_argument( '--daemon', help='start in daemon mode and put process into background', default=False, action='store_true') parser.add_argument('--pidfile', help='path for pid file. By default none is created', default=None) args = parser.parse_args(args=filter_args()) manager_hostname, manager_port = args.manager.split(':') certfile = args.sslcert if args.sslcert else None keyfile = args.sslkey if args.sslcert else None manager_cafile = certfile if args.fingerprint is None else False log_level = logging.DEBUG if args.debug else logging.INFO log_config = args.log_config client = PixelatedDispatcherClient(manager_hostname, manager_port, cacert=manager_cafile, fingerprint=args.fingerprint, assert_hostname=args.verify_hostname) client.validate_connection() dispatcher = DispatcherProxy(client, bindaddr=args.bind, keyfile=keyfile, certfile=certfile, banner=args.banner, debug=args.debug) if args.daemon: pidfile = TimeoutPIDLockFile( args.pidfile, acquire_timeout=PID_ACQUIRE_TIMEOUT_IN_S) if args.pidfile else None can_use_pidfile(pidfile) with daemon.DaemonContext(pidfile=pidfile): # init logging only after we have spawned the sub process. Otherwise there might be some hickups init_logging('proxy', level=log_level, config_file=log_config) dispatcher.serve_forever() else: init_logging('proxy', level=log_level, config_file=log_config) dispatcher.serve_forever()
def setUp(self): self.client = PixelatedDispatcherClient('localhost', 12345)
def test_initialized_with_host_and_port(self): PixelatedDispatcherClient('hostname', 1234)
def _create_cli(self, host, port, cacert, ssl, fingerprint): return PixelatedDispatcherClient(host, port, cacert=cacert, ssl=ssl, fingerprint=fingerprint)