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()
Exemple #8
0
 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)
Exemple #17
0
 def _create_cli(self, host, port, cacert, ssl, fingerprint):
     return PixelatedDispatcherClient(host, port, cacert=cacert, ssl=ssl, fingerprint=fingerprint)