class EzThriftServerTestHarness(KazooTestCase):
    """The EzThriftServerTestHarness extends KazooTestCase to provide service discovery for clients in tests

    The thrift server is started using a TSimpleServer and registered with EzBake service discovery
    """

    def setUp(self):
        super(EzThriftServerTestHarness, self).setUp()
        self.sd_client = ServiceDiscoveryClient(self.hosts)
        self.server_processes = []

    @staticmethod
    def __thrift_server(processor, host="localhost", port=8449, use_simple_server=True,
                        use_ssl=False, ca_certs=None, cert=None, key=None):
        if use_ssl:
            transport = TSSLServerSocket(host=host, port=port,
                                         ca_certs=ca_certs, cert=cert, key=key)
        else:
            transport = TSocket.TServerSocket(host=host, port=port)
        t_factory = TTransport.TBufferedTransportFactory()
        p_factory = TBinaryProtocol.TBinaryProtocolFactory()

        if use_simple_server:
            server = TServer.TSimpleServer(processor, transport, t_factory, p_factory)
        else:
            server = TServer.TThreadedServer(processor, transport, t_factory, p_factory)

        try:
            server.serve()
            print 'server started!'
        except (Exception, AttributeError, TTransportException) as e:
            print e
            logger.error("Server error: %s", e)

    def add_server(self, app_name, service_name, host, port, processor, use_simple_server=True, wait=1,
                   use_ssl=False, ca_certs=None, cert=None, key=None):
        self.sd_client.register_endpoint(app_name, service_name, host, port)
        server_process = Process(target=self.__thrift_server,
                                 args=(processor, host, port, use_simple_server, use_ssl, ca_certs, cert, key))
        server_process.start()
        time.sleep(wait)
        self.server_processes.append(server_process)

    def tearDown(self):
        super(EzThriftServerTestHarness, self).tearDown()
        for server_process in self.server_processes:
            if server_process.is_alive():
                server_process.terminate()
    def __init__(self, ez_props):
        if ez_props is None:
            raise Exception("Invalid EzProperties.")

        zk_con_str = ZookeeperConfiguration(ez_props).getZookeeperConnectionString()
        self.ezd_client = ServiceDiscoveryClient(zk_con_str)

        self.__applicationConfiguration = ApplicationConfiguration(ez_props)
        self.__applicationName = self.__applicationConfiguration.getApplicationName()
        self.__securityConfiguration = SecurityConfiguration(ez_props)
        self.__thriftConfiguration = ThriftConfiguration(ez_props)

        self.__rLock = threading.RLock()
        self.__serviceMap = {}
        self.__clientMap = {}

        self.__log = logging.getLogger(__name__)

        if self.__applicationName is None:
            self.__log.warn("No application name was found. Only common services will be discoverable.")
        else:
            self.__log.info("Application name: " + self.__applicationName)

        try:
            self.__common_services = list(self.ezd_client.get_common_services())
        except Exception:
            self.__log.error("Unable to get common services")
            raise

        self.__refresh_end_points()
        self.__refresh_common_endpoints()

        thread = threading.Thread(target=self._evict_daemon)
        thread.setDaemon(True)
        thread.start()
Example #3
0
    def fetch_derived_token(self, ezSecurityToken, targetApp,
                            excludedAuths=None, skipCache=False):
        """
        Used when an application receives an EzSecurityToken as part of it's
        API but needs to call another service that itself takes an
        EzSecurityToken.

        :param ezSecurityToken:
        :param targetApp:
        :param excludedAuths:
        :return:
        """

        # get the security id for target app (depending on if its a common
        # service or an application)
        dc = ServiceDiscoveryClient(self.zk_con_str)
        targetSecurityId = dc.get_security_id(targetApp)
        token_request = TokenRequest(
            self.appConfig.getSecurityID(),
            util.current_time_millis()
        )
        token_request.tokenPrincipal = ezSecurityToken
        token_request.targetSecurityId = targetSecurityId
        token_request.excludeAuthorizations = excludedAuths

        # look in the cache (and return immediately if in cache)
        dn = ezSecurityToken.tokenPrincipal.principal
        request_chain = ezSecurityToken.tokenPrincipal.requestChain
        cache_key = self._get_cache_key(ezSecurityToken.type, dn, excludedAuths, request_chain, targetSecurityId)
        if not skipCache:
            token = self.__get_from_cache(cache_key)
            if token:
                return token

        # get token (since it wasn't found in the cache)
        headers = {
            HTTP_HEADER_USER_INFO: dn,
            HTTP_HEADER_SIGNATURE: self._sign(dn)
        }
        request, signature = self.build_request(headers, targetApp, exclude_authorizations=excludedAuths)
        return self._request_token_and_store(request, signature, "derived", dn, cache_key)
    def clientServiceGreenlet(self):
        ezd = ServiceDiscoveryClient(gConfig.zk)
        ezd.register_endpoint(gConfig.appName, EzFrontendServiceName,
                              gConfig.internal_hostname, gConfig.thriftPort)
        ezd.set_security_id_for_application(gConfig.appName, '_Ez_EFE')

        while gConfig.run:
            try:
                handler = ezRPKazookeeper.EzReverseProxyHandler(
                    self._logger, self._sfh)
                processor = EzFrontendService.Processor(handler)
                transport = TSSLServerSocket(
                    host=gConfig.internal_hostname,
                    port=gConfig.thriftPort,
                    verify_pattern=gConfig.ez_frontend_access,
                    ca_certs=gConfig.ez_cafile,
                    cert=gConfig.ez_certfile,
                    key=gConfig.ez_keyfile)
                tfactory = TTransport.TBufferedTransportFactory()
                pfactory = TBinaryProtocol.TBinaryProtocolFactory()
                #server = TServer.TSimpleServer(processor,transport,tfactory,pfactory)
                server = TGeventServer(self._logger, processor, transport,
                                       tfactory, pfactory)
                gevent.sleep()
                server.serve()
            except Exception as e:
                self._logger.exception("Error in Thrift server: %s" % e)
        self._logger.info("exiting clientServiceGreenlet")
    def clientServiceGreenlet(self):
      ezd = ServiceDiscoveryClient(gConfig.zk)
      ezd.register_endpoint(gConfig.appName, EzFrontendServiceName, gConfig.internal_hostname, gConfig.thriftPort)
      ezd.set_security_id_for_application(gConfig.appName, '_Ez_EFE')

      while gConfig.run:
        try:
          handler = ezRPKazookeeper.EzReverseProxyHandler(self._logger, self._sfh)
          processor = EzFrontendService.Processor(handler)
          transport = TSSLServerSocket(host=gConfig.internal_hostname,
                                       port=gConfig.thriftPort,
                                       ca_certs=gConfig.ez_cafile,
                                       cert=gConfig.ez_certfile,
                                       key=gConfig.ez_keyfile)
          tfactory = TTransport.TBufferedTransportFactory()
          pfactory = TBinaryProtocol.TBinaryProtocolFactory()
          #server = TServer.TSimpleServer(processor,transport,tfactory,pfactory)
          server = TGeventServer(self._logger, processor, transport, tfactory, pfactory)
          gevent.sleep()
          server.serve()
        except Exception as e:
          self._logger.exception("Error in Thrift server: %s" % e)
      self._logger.info("exiting clientServiceGreenlet")
Example #6
0
    def run(self):
        glt = ezRPGreenlet.EzReverseProxyGreenlet(self._logger, self._sfh)
        self._logger.info("starting greenlet for thrift service...")
        clientGreenlet = gevent.spawn(glt.clientServiceGreenlet)
        self._logger.info("started")

        self._logger.info("starting greenlet to monitor zookeeper...")
        kzGreenlet = gevent.spawn(glt.kzMonitorGreenlet)
        self._logger.info("started")

        self._logger.info(
            "starting greenlet to write out nginx configuration changes...")
        cfgProcessorGreenlet = gevent.spawn(
            glt.configurationChangeQueueGreenlet)
        self._logger.info("started")

        self._logger.info("starting greenlet to monitor for shutdown...")
        fd = gevent_inotifyx.init()
        wd = gevent_inotifyx.add_watch(fd, gConfig.shutdownFile,
                                       gevent_inotifyx.IN_DELETE)
        wGreenlet = gevent.spawn(glt.watchGreenlet, fd)
        self._logger.info("started")

        gConfig.addGreenlets(clientGreenlet, kzGreenlet, cfgProcessorGreenlet,
                             wGreenlet)

        gevent.joinall([clientGreenlet])
        self._logger.warn("joined thrift service greenlet")
        gevent.joinall([kzGreenlet])
        self._logger.warn("joined zookeeper monitoring greenlet")
        gConfig.run = False
        while not gConfig.configurationChangeQueue.empty():
            print "queue not empty"
            gConfig.configurationChangeQueue.get()
            print "got"
            gConfig.configurationChangeQueue.task_done()
        print "joining conf queue"
        gConfig.configurationChangeQueue.join()
        self._logger.warn("joined configuration queue")
        gevent.joinall([cfgProcessorGreenlet])
        self._logger.warn("joined configuration change greenlet")
        gConfig.wGreenlet.join()
        self._logger.warn("joined shutdown monitor greenlet")
        ServiceDiscoveryClient(gConfig.zk).unregister_endpoint(
            gConfig.appName, EzFrontendServiceName, gConfig.internal_hostname,
            gConfig.thriftPort)
        self._logger.warn("unregistered from discovery service")
Example #7
0
 def setUp(self):
     """Replace the Zookeeper client on the module."""
     super(ServiceDiscoveryClientTest, self).setUp()
     self.ezDiscovery = ServiceDiscoveryClient(self.hosts)
Example #8
0
class ServiceDiscoveryClientTest(KazooTestCase):
    """Basic set of tests for ServiceDiscoveryClient."""

    def setUp(self):
        """Replace the Zookeeper client on the module."""
        super(ServiceDiscoveryClientTest, self).setUp()
        self.ezDiscovery = ServiceDiscoveryClient(self.hosts)

    def tearDown(self):
        """Clean up the Zookeeper entries."""
        super(ServiceDiscoveryClientTest, self).tearDown()

    def test_register_endpoint(self):
        """Register an endpoint and make sure it ends up in Zookeeper."""
        self.ezDiscovery.register_endpoint('foo', 'bar', 'localhost', 8080)
        endpoints = self.ezDiscovery.get_endpoints("foo", "bar")
        self.assertEqual(endpoints[0], "localhost:8080")

    def test_register_common_endpoint(self):
        """Register a common endpoint and make sure it ends up in Zookeeper."""
        self.ezDiscovery.register_common_endpoint('bar', 'localhost', 8080)
        endpoints = self.ezDiscovery.get_common_endpoints("bar")
        self.assertEqual(endpoints[0], "localhost:8080")

    def test_unregister_endpoint(self):
        """Register and unregister an endpoint and make sure it is gone."""
        self.ezDiscovery.register_endpoint('foo', 'bar', 'localhost', 8080)
        self.ezDiscovery.unregister_endpoint('foo', 'bar', 'localhost', 8080)
        endpoints = self.ezDiscovery.get_endpoints("foo", "bar")
        self.assertEqual(len(endpoints), 0)

    def test_unregister_common_endpoint(self):
        """Register and unregister a common endpoint and make sure it is gone. """
        self.ezDiscovery.register_common_endpoint('bar', 'localhost', 8080)
        self.ezDiscovery.unregister_common_endpoint('bar', 'localhost', 8080)
        endpoints = self.ezDiscovery.get_common_endpoints("bar")
        self.assertEqual(len(endpoints), 0)

    def test_unregister_none_exist_endpoint(self):
        """ make sure no exception is raised """
        self.ezDiscovery.unregister_endpoint('foo', 'bar', 'localhost', 8000)

    def test_unregister_multiple_endpoints(self):
        """Test that when multiple endpoints get made and some removed the tree
        of endpoints stays correct.
        """
        self.ezDiscovery.register_endpoint('foo', 'bar', 'localhost', 8000)
        self.ezDiscovery.register_endpoint('foo', 'bar', 'localhost', 8888)

        # Unregister the first endpoint.
        self.ezDiscovery.unregister_endpoint('foo', 'bar', 'localhost', 8000)
        endpoints = self.ezDiscovery.get_endpoints('foo', 'bar')
        self.assertEqual(len(endpoints), 1)
        self.assertEqual(endpoints[0], 'localhost:8888')

        # Unregister the second endpoint.
        self.ezDiscovery.unregister_endpoint('foo', 'bar', 'localhost', 8888)
        endpoints = self.ezDiscovery.get_endpoints('foo', 'bar')
        self.assertEqual(len(endpoints), 0)

        base_path = '/'.join([
            ServiceDiscoveryClient.NAMESPACE,
            'foo',
            'bar',
            ServiceDiscoveryClient.ENDPOINTS
        ])
        self.assertTrue(self.client.exists(base_path))

    def test_get_applications(self):
        """Test application list."""
        # Create a few application endpoints.
        self.ezDiscovery.register_endpoint('foo', 'bar', 'localhost', 8000)
        self.ezDiscovery.register_endpoint('harry', 'sally', 'localhost', 8080)
        self.assertEqual(2, len(self.ezDiscovery.get_applications()))

    def test_get_services(self):
        """Test the application services list."""
        # Create a few application endpoints.
        self.ezDiscovery.register_endpoint('foo', 'bar', 'localhost', 8000)
        self.ezDiscovery.register_endpoint('foo', 'baz', 'localhost', 8001)
        self.ezDiscovery.register_endpoint('harry', 'sally', 'localhost', 8080)

        # Make sure it returns the right count for a single service.
        self.assertEqual(2, len(self.ezDiscovery.get_services('foo')))

        self.assertEqual(1, len(self.ezDiscovery.get_services('harry')))
        self.assertEqual('sally', self.ezDiscovery.get_services('harry')[0])

    def test_get_common_services(self):
        """Test fetching common services."""
        # Make a few common services and and an external, ensure they return
        # properly.
        self.ezDiscovery.register_common_endpoint('foo', 'localhost', 8000)
        self.ezDiscovery.register_common_endpoint('bar', 'localhost', 8001)
        self.ezDiscovery.register_endpoint('harry', 'sally', 'localhost', 8080)
        self.assertEqual(2, len(self.ezDiscovery.get_common_services()))

    def test_get_endpoints(self):
        """Test endpoint list fetching."""
        # Create a few application endpoints.
        self.ezDiscovery.register_endpoint('foo', 'bar', 'localhost', 8000)
        self.ezDiscovery.register_endpoint('foo', 'bar', 'localhost', 8001)
        self.ezDiscovery.register_endpoint('harry', 'sally', 'localhost', 8080)
        self.assertEqual(2, len(self.ezDiscovery.get_endpoints('foo', 'bar')))

    def test_get_common_endpoints(self):
        """Test fetching common endpoints."""
        # Create a few common endpoints and one not, test results.
        self.ezDiscovery.register_common_endpoint('foo', 'localhost', 8000)
        self.ezDiscovery.register_common_endpoint('foo', 'localhost', 8001)
        self.ezDiscovery.register_endpoint('harry', 'sally', 'localhost', 8080)
        self.assertEqual(2, len(self.ezDiscovery.get_common_endpoints('foo')))
        self.assertEquals(0, len(self.ezDiscovery.get_common_endpoints('sally')))

    def test_is_service_common(self):
        """Ensure only common services return true."""
        # Test one that does not exist.
        self.assertFalse(self.ezDiscovery.is_service_common('foo'))
        self.ezDiscovery.register_common_endpoint('foo', 'localhost', 8000)
        self.assertTrue(self.ezDiscovery.is_service_common('foo'))
        self.ezDiscovery.register_endpoint('harry', 'sally', 'localhost', 8080)
        self.assertFalse(self.ezDiscovery.is_service_common('sally'))

    def test_set_security_id_for_application(self):
        """Ensure security id's get set for applications."""
        self.ezDiscovery.register_endpoint('foo', 'bar', 'localhost', 8000)
        self.ezDiscovery.set_security_id_for_application('foo', 'sid')

        path = '/'.join([
            ServiceDiscoveryClient.NAMESPACE,
            'foo',
            ServiceDiscoveryClient.SECURITY,
            ServiceDiscoveryClient.SECURITY_ID
        ])
        self.assertTrue(self.client.exists(path))
        self.assertEquals('sid', self.client.get(path)[0])

    def test_set_security_id_for_common_service(self):
        """Ensure security id's get set for common services."""
        self.ezDiscovery.register_common_endpoint('foo', 'localhost', 8000)
        self.ezDiscovery.set_security_id_for_common_service('foo', 'sid')
        path = '/'.join([
            ServiceDiscoveryClient.NAMESPACE,
            '/'.join([ServiceDiscoveryClient.COMMON_APP_NAME, 'foo']),
            ServiceDiscoveryClient.SECURITY,
            ServiceDiscoveryClient.SECURITY_ID
        ])
        self.assertTrue(self.client.exists(path))
        self.assertEquals('sid', self.client.get(path)[0])

    def test_get_security_id_for_application(self):
        """Ensure fetching application security id's returns properly."""
        # Fetch one that does not exist.
        self.assertEquals(
            None,
            self.ezDiscovery.get_security_id('foo')
        )
        self.ezDiscovery.register_endpoint('foo', 'bar', 'localhost', 8000)
        self.ezDiscovery.set_security_id_for_application('foo', 'sid')
        self.assertEquals(
            'sid',
            self.ezDiscovery.get_security_id('foo')
        )

    def test_get_security_id_for_common_service(self):
        """Ensure fetching application security id's returns properly."""

        # clear the cache
        self.ezDiscovery.securityIdCache.clear()

        # Fetch one does not exist.
        self.assertEquals(
            None,
            self.ezDiscovery.get_security_id('foo')
        )
        self.ezDiscovery.register_common_endpoint('foo', 'localhost', 8000)
        self.ezDiscovery.set_security_id_for_common_service('foo', 'sid')
        self.assertEquals(
            'sid',
            self.ezDiscovery.get_security_id('foo')
        )
 def setUp(self):
     super(EzThriftServerTestHarness, self).setUp()
     self.sd_client = ServiceDiscoveryClient(self.hosts)
     self.server_processes = []
    def setUp(self):
        """
        """
        super(ThriftClientPoolTest, self).setUp()
        ezd_client = ServiceDiscoveryClient(self.hosts)

        ez_props = EzConfiguration().getProperties()
        ez_props["thrift.use.ssl"] = "false"
        ez_props["zookeeper.connection.string"] = self.hosts
        application_name = ApplicationConfiguration(ez_props).getApplicationName()

        self.serverProcesses = []
        for endpoint in ENDPOINTS:
            host, port = endpoint.split(':')
            port = int(port)
            server_process = Process(target=start_ezpz, args=(EzPzHandler(), port,))
            server_process.start()
            time.sleep(1)
            self.serverProcesses.append(server_process)
            ezd_client.register_endpoint(application_name, "ezpz", host, port)

        ezd_client.register_endpoint(application_name, "service_one", 'localhost', 8083)
        ezd_client.register_endpoint(application_name, "service_two", 'localhost', 8084)
        ezd_client.register_endpoint(application_name, "service_three", 'localhost', 8085)

        ezd_client.register_common_endpoint('common_service_one', 'localhost', 8080)
        ezd_client.register_common_endpoint('common_service_two', 'localhost', 8081)
        ezd_client.register_common_endpoint('common_service_three', 'localhost', 8082)
        ezd_client.register_common_endpoint('common_service_multi', '192.168.1.1', 6060)
        ezd_client.register_common_endpoint('common_service_multi', '192.168.1.2', 6161)

        ezd_client.register_endpoint("NotThriftClientPool", "unknown_service_three", 'localhost', 8091)
        ezd_client.register_endpoint("NotThriftClientPool", "unknown_service_three", 'localhost', 8092)
        ezd_client.register_endpoint("NotThriftClientPool", "unknown_service_three", 'localhost', 8093)

        self.clientPool = ThriftClientPool(ez_props)
class ThriftClientPool(object):
    """
    """
    def __init__(self, ez_props):
        if ez_props is None:
            raise Exception("Invalid EzProperties.")

        zk_con_str = ZookeeperConfiguration(ez_props).getZookeeperConnectionString()
        self.ezd_client = ServiceDiscoveryClient(zk_con_str)

        self.__applicationConfiguration = ApplicationConfiguration(ez_props)
        self.__applicationName = self.__applicationConfiguration.getApplicationName()
        self.__securityConfiguration = SecurityConfiguration(ez_props)
        self.__thriftConfiguration = ThriftConfiguration(ez_props)

        self.__rLock = threading.RLock()
        self.__serviceMap = {}
        self.__clientMap = {}

        self.__log = logging.getLogger(__name__)

        if self.__applicationName is None:
            self.__log.warn("No application name was found. Only common services will be discoverable.")
        else:
            self.__log.info("Application name: " + self.__applicationName)

        try:
            self.__common_services = list(self.ezd_client.get_common_services())
        except Exception:
            self.__log.error("Unable to get common services")
            raise

        self.__refresh_end_points()
        self.__refresh_common_endpoints()

        thread = threading.Thread(target=self._evict_daemon)
        thread.setDaemon(True)
        thread.start()

    def _evict_daemon(self):
        check_interval_millis = self.__thriftConfiguration.getMillisBetweenClientEvictionChecks()
        idle_threshold_millis = self.__thriftConfiguration.getMillisIdleBeforeEviction()
        while True:
            time.sleep(check_interval_millis * 0.001)
            with self.__rLock:
                for client in self.__clientMap.itervalues():
                    client._pool.evict_check(idle_threshold_millis)

    def _get_service_map(self):
        return self.__serviceMap

    def _get_client_map(self):
        return self.__clientMap

    def __refresh_end_points(self):
        if (self.__applicationName is not None) and (self.__applicationName != ''):
            try:
                for service in self.ezd_client.get_services(self.__applicationName):
                    try:
                        endpoints = self.ezd_client.get_endpoints(self.__applicationName, service)
                        self._add_endpoints(service, endpoints)
                    except Exception:
                        self.__log.warn("No " + service + " for application " + self.__applicationName + " was found")
            except Exception:
                self.__log.warn(
                    "Failed to get application services. "
                    "This might be okay if the application hasn't registered any services."
                )

    def __refresh_common_endpoints(self):
        try:
            for service in self.ezd_client.get_common_services():
                try:
                    endpoints = self.ezd_client.get_common_endpoints(service)
                    self._add_endpoints(service, endpoints)
                except Exception:
                    self.__log.warn("No common service " + service + " was found.")
        except Exception:
            self.__log.warn("Failed to get common services. This might be okay if no common service has been defined.")

    def _add_endpoints(self, service, endpoints):
        with self.__rLock:
            if service in self.__serviceMap:
                del self.__serviceMap[service]
            self.__serviceMap[service] = []
            for endpoint in endpoints:
                self.__serviceMap[service].append(endpoint)

    @staticmethod
    def __get_thrift_connection_key(service_name, client_class):
        return service_name + "|" + str(client_class)

    def __get_endpoints(self, service_name, retry=True):
        with self.__rLock:
            if service_name in self.__serviceMap:
                return self.__serviceMap[service_name]
        if retry:
            self.__refresh_end_points()
            self.__refresh_common_endpoints()
            return self.__get_endpoints(service_name, retry=False)
        return None

    def get_client(self, app_name=None, service_name=None, clazz=None):

        if not service_name:
            raise ValueError("'service_name' does not have a valid value (%s)." % service_name)

        if not clazz:
            raise ValueError("'clazz' does not have a valid value (%s)." % clazz)

        try:
            key = self.__get_thrift_connection_key(service_name, clazz)
            with self.__rLock:

                if app_name:
                    service = self.__applicationConfiguration.getApplicationServiceName(app_name, service_name)
                    if service not in self.__serviceMap:
                        endpoints = self.ezd_client.get_endpoints(app_name, service_name)
                        self._add_endpoints(service, endpoints)

                # get client from client pool, or initialize client
                if key in self.__clientMap:
                    client = self.__clientMap[key]
                else:
                    endpoints = self.__get_endpoints(service_name)
                    if endpoints is None:
                        return None

                    pool_size = self.__thriftConfiguration.getMaxIdleClients()
                    if self.__thriftConfiguration.useSSL():
                        sc = self.__securityConfiguration
                        ca_certs = sc.getTrustedSslCerts()
                        key_file = sc.getPrivateKey()
                        cert = sc.getSslCertificate()
                        client = PoolingThriftClient(endpoints, clazz, pool_size=pool_size,
                                                     use_ssl=True, ca_certs=ca_certs, cert=cert, key=key_file)
                    else:
                        client = PoolingThriftClient(endpoints, clazz, pool_size=pool_size)

                    self.__clientMap[key] = client
                return client

        except Exception, e:
            raise TException(str(e))
Example #12
0
def ca_server(ezconfig, service_name=None, ca_name="ezbakeca", zoo_host=None,
              host=None, port=None, verify_pattern=None, ssldir=None):
    Crypto.Random.atfork()
    # make sure zookeeper is available for registering with service discovery
    if zoo_host is None:
        zooConf = ZookeeperConfiguration(ezconfig)
        zoo_host = zooConf.getZookeeperConnectionString()
        if not zoo_host:
            raise RuntimeError("Zookeeper connection string must be specified "
                "in EzConfiguration")

    # make sure the ssl certificate directory is available
    if not ssldir:
        ac = ApplicationConfiguration(ezconfig)
        ssldir = ac.getCertificatesDir()
        if not ssldir:
            raise RuntimeError("Certificates Directory \"{0}\" must be set in"
                " EzConfiguration!".format(
                ApplicationConfiguration.CERTIFICATES_DIRECTORY_KEY))

    # get a free port to bind to (and figure out our hostname)
    if not port:
        port = get_port(range(31005,34999))
    if not host:
        host = socket.gethostname()

    # register with ezdiscovery
    ezdiscovery = ServiceDiscoveryClient(zoo_host)
    try:
        if service_name is None:
            service_name = ezbake.ezca.constants.SERVICE_NAME

        logger.info('Registering with service discovery')
        ezdiscovery.register_common_endpoint(service_name=service_name, host=host, port=port)
        ezdiscovery.set_security_id_for_common_service(service_name=service_name, security_id="EzCAService")
    except TimeoutError as e:
        logger.error("Fatal timeout connecting to zookeeper. Unable to "
                     "register with service discovery.")
        raise e

    # create the thrift handler
    handler = EzCAHandler(ca_name, ezconfig)

    # generate/get the server SSL certs and write them to disk
    certs = handler._server_certs()
    cert_files = []
    for k, cert in certs.items():
        of = os.path.join(ssldir, k)
        cert_files.append(of)
        with os.fdopen(os.open(of, os.O_WRONLY | os.O_CREAT, 0o600), 'w') as ofs:
            ofs.write(str(cert))

    # generate certs for configured clients (read from ezconfig)
    clients = ezconfig.get(EzCAHandler.CLIENT_CERTS)
    if clients:
        gen_client_certs(handler.ca, clients.split(','),
                         ezconfig.get(EzCAHandler.CLIENT_CERT_O))

    # start the thrift server
    processor = EzCA.Processor(handler)
    transport = TSSLServerSocket(host=host, port=port,
                                 verify_pattern=verify_pattern,
                                 ca_certs=cert_files[0],
                                 cert=cert_files[1],
                                 key=cert_files[2])
    tfactory = TTransport.TBufferedTransportFactory()
    pfactory = TBinaryProtocol.TBinaryProtocolFactory()
    server = TServer.TThreadPoolServer(processor, transport, tfactory, pfactory)
    logger.info('Starting ezca service on {}:{}'.format(host,port))
    server.serve()
def ca_server(ezconfig, service_name=None, ca_name="ezbakeca", zoo_host=None,
              host=None, port=None, verify_pattern=None, ssldir=None):
    Crypto.Random.atfork()
    # make sure zookeeper is available for registering with service discovery
    if zoo_host is None:
        zooConf = ZookeeperConfiguration(ezconfig)
        zoo_host = zooConf.getZookeeperConnectionString()
        if not zoo_host:
            raise RuntimeError("Zookeeper connection string must be specified "
                "in EzConfiguration")

    # make sure the ssl certificate directory is available
    if not ssldir:
        ac = ApplicationConfiguration(ezconfig)
        ssldir = ac.getCertificatesDir()
        if not ssldir:
            raise RuntimeError("Certificates Directory \"{0}\" must be set in"
                " EzConfiguration!".format(
                ApplicationConfiguration.CERTIFICATES_DIRECTORY_KEY))

    # get a free port to bind to (and figure out our hostname)
    if not port:
        port = get_port(range(31005,34999))
    if not host:
        host = socket.gethostname()

    # register with ezdiscovery
    ezdiscovery = ServiceDiscoveryClient(zoo_host)
    try:
        if service_name is None:
            service_name = ezbake.ezca.constants.SERVICE_NAME

        logger.info('Registering with service discovery')
        ezdiscovery.register_common_endpoint(service_name=service_name, host=host, port=port)
    except TimeoutError as e:
        logger.error("Fatal timeout connecting to zookeeper. Unable to "
                     "register with service discovery.")
        raise e

    # create the thrift handler
    handler = EzCAHandler(ca_name, ezconfig)

    # generate/get the server SSL certs and write them to disk
    certs = handler._server_certs()
    cert_files = []
    for k, cert in certs.items():
        of = os.path.join(ssldir, k)
        cert_files.append(of)
        with os.fdopen(os.open(of, os.O_WRONLY | os.O_CREAT, 0o600), 'w') as ofs:
            ofs.write(str(cert))

    # generate certs for configured clients (read from ezconfig)
    clients = ezconfig.get(EzCAHandler.CLIENT_CERTS)
    if clients:
        gen_client_certs(handler.ca, clients.split(','),
                         ezconfig.get(EzCAHandler.CLIENT_CERT_O))

    # start the thrift server
    processor = EzCA.Processor(handler)
    transport = TSSLServerSocket(host=host, port=port,
                                 verify_pattern=verify_pattern,
                                 ca_certs=cert_files[0],
                                 cert=cert_files[1],
                                 key=cert_files[2])
    tfactory = TTransport.TBufferedTransportFactory()
    pfactory = TBinaryProtocol.TBinaryProtocolFactory()
    server = TServer.TThreadPoolServer(processor, transport, tfactory, pfactory)
    logger.info('Starting ezca service on {}:{}'.format(host,port))
    server.serve()