def _get_tickets(manifest, container_dir): """Get tickets.""" principals = set(manifest.get('tickets', [])) if not principals: return False tkts_spool_dir = os.path.join(container_dir, 'root', 'var', 'spool', 'tickets') try: tickets.request_tickets(context.GLOBAL.zk.conn, manifest['name'], tkts_spool_dir, principals) except Exception: _LOGGER.exception('Exception processing tickets.') raise exc.ContainerSetupError('Get tickets error', app_abort.AbortedReason.TICKETS) # Check that all requested tickets are valid. for princ in principals: krbcc_file = os.path.join(tkts_spool_dir, princ) if not tickets.krbcc_ok(krbcc_file): _LOGGER.error('Missing or expired tickets: %s, %s', princ, krbcc_file) raise exc.ContainerSetupError(princ, app_abort.AbortedReason.TICKETS) _LOGGER.info('Ticket ok: %s, %s', princ, krbcc_file) return True
def _refresh_tickets(manifest, container_dir): """Refreshes the tickets with the given frequency.""" tkts_spool_dir = os.path.join(container_dir, 'root', 'var', 'spool', 'tickets') principals = set(manifest.get('tickets', [])) tickets.request_tickets(context.GLOBAL.zk.conn, manifest['name'], tkts_spool_dir, principals)
def _refresh_tickets(manifest, container_dir): """Refreshes the tickets with the given frequency.""" tkts_spool_dir = os.path.join(container_dir, 'root', 'var', 'spool', 'tickets') # we do not abort here as we will make service fetch ticket again # after register service is started again principals = set(manifest.get('tickets', [])) tickets.request_tickets(context.GLOBAL.zk.conn, manifest['name'], tkts_spool_dir, principals)
def _register(self, manifest, refresh_interval=None): app_presence = presence.EndpointPresence(context.GLOBAL.zk.conn, manifest) try: app_presence.register() if manifest.get('tickets', None): _get_tickets(manifest['name'], manifest, self.container_dir) _start_service_sup(self.container_dir) except exc.ContainerSetupError as err: app_abort.abort(self.tm_env, manifest['name'], reason=str(err)) # If tickets are not ok, app will be aborted. Waiting for tickets # in the loop is harmless way to wait for that. # # If tickets acquired successfully, services will start, and # tickets will be refreshed after each interval. tkts_spool_dir = os.path.join(self.container_dir, 'root', 'var', 'spool', 'tickets') while True: time.sleep(refresh_interval) reply = tickets.request_tickets(context.GLOBAL.zk.conn, manifest['name']) if reply: tickets.store_tickets(reply, tkts_spool_dir) else: _LOGGER.error('Error requesting tickets.')
def test_request_tickets(self): """Test parsing output of request_tickets.""" treadmill.zkutils.connect.return_value = kazoo.client.KazooClient() kazoo.client.KazooClient.get_children.return_value = [ 'xxx.xx.com:1234', 'yyy.xx.com:1234' ] # base64.urlsafe_b64encode('abcd') : YWJjZA== lines = [b'foo@bar:YWJjZA==', b''] treadmill.gssapiprotocol.GSSAPILineClient.read.side_effect = ( lambda: lines.pop(0)) tickets.request_tickets(kazoo.client.KazooClient(), 'myapp', self.tkt_dir, set(['foo@bar'])) tickets.Ticket.write.assert_called_with() tickets.Ticket.copy.assert_called_with( os.path.join(self.tkt_dir, 'foo@bar'))
def test_request_tickets(self): """Test parsing output of request_tickets.""" treadmill.zkutils.connect.return_value = kazoo.client.KazooClient() kazoo.client.KazooClient.get_children.return_value = [ 'xxx.xx.com:1234', 'yyy.xx.com:1234' ] # base64.urlsafe_b64encode('abcd') : YWJjZA== lines = ['foo@bar:YWJjZA==', ''] treadmill.gssapiprotocol.GSSAPILineClient.read.side_effect = ( lambda: lines.pop(0)) reply = tickets.request_tickets(kazoo.client.KazooClient(), 'myapp') self.assertEqual([tickets.Ticket('foo@bar', b'abcd')], reply)
def test_request_tickets(self, client_cls): """Test parsing output of request_tickets.""" treadmill.zkutils.connect.return_value = kazoo.client.KazooClient() kazoo.client.KazooClient.get_children.return_value = [ 'xxx.xx.com:1234', 'yyy.xx.com:1234', 'zzz.xx.com:1234' ] # base64.urlsafe_b64encode('abcd') : YWJjZA== lockers = { ('xxx.xx.com', 1234): [b'foo@bar:YWJjZA==', b''], ('yyy.xx.com', 1234): [b'foo@bar:YWJjZA==', b''], ('zzz.xx.com', 1234): [b'foo@bar:YWJjZA==', b''], } def create_mock_client(host, port): """Create mock client.""" mock_client = mock.Mock() mock_client.read.side_effect = lambda: lockers[(host, port)].pop(0) return mock_client client_cls.side_effect = lambda host, port, _: create_mock_client( host, port) tickets.request_tickets(kazoo.client.KazooClient(), 'myapp', self.tkt_dir, set(['foo@bar'])) tickets.Ticket.write.assert_called_with() self.assertEqual(tickets.Ticket.write.call_count, 2) tickets.Ticket.copy.assert_called_with( os.path.join(self.tkt_dir, 'foo@bar')) self.assertEqual(tickets.Ticket.copy.call_count, 1) # The first ticket was invalid (expired), had to try the second locker. self.assertEqual(len(lockers[('xxx.xx.com', 1234)]), 0) self.assertEqual(len(lockers[('yyy.xx.com', 1234)]), 0) self.assertEqual(len(lockers[('zzz.xx.com', 1234)]), 2)
def _get_tickets(appname, app, container_dir): """Get tickets.""" tkts_spool_dir = os.path.join( container_dir, 'root', 'var', 'spool', 'tickets') reply = tickets.request_tickets(context.GLOBAL.zk.conn, appname) if reply: tickets.store_tickets(reply, tkts_spool_dir) # Check that all requested tickets are valid. for princ in app.get('tickets', []): krbcc_file = os.path.join(tkts_spool_dir, princ) if not tickets.krbcc_ok(krbcc_file): _LOGGER.error('Missing or expired tickets: %s, %s', princ, krbcc_file) raise exc.ContainerSetupError('tickets.%s' % princ) else: _LOGGER.info('Ticket ok: %s, %s', princ, krbcc_file)
def register(approot, refresh_interval, manifest, container_dir, appevents_dir): """Register container presence.""" del appevents_dir tm_env = appmgr.AppEnvironment(approot) app = yaml.load(manifest.read()) appname = app['name'] app_presence = presence.EndpointPresence( context.GLOBAL.zk.conn, app ) try: app_presence.register() _get_tickets(appname, app, container_dir) _start_service_sup(container_dir) except exc.ContainerSetupError as err: app_abort.abort( tm_env, appname, reason=str(err) ) # If tickets are not ok, app will be aborted. Waiting for tickets # in the loop is harmless way to wait for that. # # If tickets acquired successfully, services will start, and # tickets will be refreshed after each interval. tkts_spool_dir = os.path.join( container_dir, 'root', 'var', 'spool', 'tickets') while True: time.sleep(refresh_interval) reply = tickets.request_tickets(context.GLOBAL.zk.conn, appname) if reply: tickets.store_tickets(reply, tkts_spool_dir) else: _LOGGER.error('Error requesting tickets.')