def request_tickets_from(host, port, appname, tkt_spool_dir, expected=None): """Request tickets from given locker endpoint.""" service = 'host@%s' % host _LOGGER.info('connecting: %s:%s, %s', host, port, service) client = gssapiprotocol.GSSAPILineClient(host, int(port), service) if expected is None: expected = set() try: if client.connect(): _LOGGER.debug('connected to: %s:%s, %s', host, port, service) client.write(appname.encode()) _LOGGER.debug('sent: %r', appname) while True: line = client.read() if not line: _LOGGER.debug('Got empty response.') break princ, encoded = line.split(b':', 1) princ = princ.decode() ticket_data = base64.standard_b64decode(encoded) if ticket_data: _LOGGER.info('got ticket %s:%s', princ, hashlib.sha1(encoded).hexdigest()) tkt = Ticket(princ, ticket_data) if store_ticket(tkt, tkt_spool_dir): expected.discard(princ) else: _LOGGER.info('got ticket %s:None', princ) else: _LOGGER.warning('Cannot connect to %s:%s, %s', host, port, service) finally: client.disconnect()
def _gssapiprotocol_loop(request, server_list, sprinc): """Iterate gssaprotocol service instances.""" for server, port in server_list: _LOGGER.debug('Connecting to %s:%d', server, port) client = gssapiprotocol.GSSAPILineClient(server, port, '%s@%s' % (sprinc, server), 2) if not client.connect(): _LOGGER.debug( 'failed to connect to %s:%d, failing over to next server', server, port) continue client.write(request.encode('utf-8')) _LOGGER.debug('Sent request [%s] to %s:%d', request, server, port) line = client.read().decode('utf-8') _LOGGER.debug('Received response from %s:%d', server, port) client.disconnect() response = json.loads(line) return response response = {} response['status'] = 'failure' response['result'] = {} response['result']['why'] = 'unable to connect to any servers' return response
def _request_keytab(server, port, principal): """Request keytab from keytab server.""" client = gssapiprotocol.GSSAPILineClient(server, port, "host@%s" % server) if not client.connect(): _LOGGER.warning('Failed to connect/authenticate to %s:%s', server, port) return None client.write(principal.encode("utf-8")) line = client.read().decode("utf-8") client.disconnect() response = json.loads(line) if response['status'] == 'failure': # TODO: need better output for error messages. _LOGGER.error('Error requesting keytab: %s', json.dumps(response, indent=4, sort_keys=True)) return None if response['status'] == 'success': keytab_entries = base64.standard_b64decode( response['result']['keytab_entries']) return keytab_entries raise Exception('Unexpected error: %s' % json.dumps(response, indent=4, sort_keys=True))
def _request_keytab(server, port, principal): """Request keytab from keytab server.""" client = gssapiprotocol.GSSAPILineClient(server, port, "host@%s" % server) client.connect() client.write(principal.encode("utf-8")) line = client.read().decode("utf-8") client.disconnect() return json.loads(line)
def request_tickets(zkclient, appname, tkt_spool_dir, principals): """Request tickets from the locker for the given app. """ # Too many nested blocks. # # pylint: disable=R0101 lockers = zkutils.with_retry(zkclient.get_children, z.TICKET_LOCKER) random.shuffle(lockers) expected = set(principals) for locker in lockers: if not expected: _LOGGER.info('Done: all tickets retrieved.') return host, port = locker.split(':') service = 'host@%s' % host _LOGGER.info('connecting: %s:%s, %s', host, port, service) client = gssapiprotocol.GSSAPILineClient(host, int(port), service) try: if client.connect(): _LOGGER.debug('connected to: %s:%s, %s', host, port, service) client.write(appname.encode()) _LOGGER.debug('sent: %r', appname) while True: line = client.read() if not line: _LOGGER.debug('Got empty response.') break princ, encoded = line.split(b':', 1) princ = princ.decode() ticket_data = base64.standard_b64decode(encoded) if ticket_data: _LOGGER.info('got ticket %s:%s', princ, hashlib.sha1(encoded).hexdigest()) store_ticket(Ticket(princ, ticket_data), tkt_spool_dir) expected.discard(princ) else: _LOGGER.info('got ticket %s:None', princ) else: _LOGGER.warning('Cannot connect to %s:%s, %s', host, port, service) finally: client.disconnect()
def _get_keytabs_from(host, port, spool_dir): """Get keytabs from keytab locker server. """ from treadmill import gssapiprotocol service = 'host@%s' % host _LOGGER.info('connecting: %s:%s, %s', host, port, service) client = gssapiprotocol.GSSAPILineClient(host, int(port), service) try: if not client.connect(): _LOGGER.warning( 'Cannot connect to %s:%s, %s', host, port, service ) return False _LOGGER.debug('connected to: %s:%s, %s', host, port, service) client.write(b'get') while True: line = client.read() if not line: _LOGGER.debug('End of response.') break ktname, encoded = line.split(b':', 1) ktname = ktname.decode() if encoded: _LOGGER.info('got keytab %s:%r', ktname, hashlib.sha1(encoded).hexdigest()) keytab_data = base64.urlsafe_b64decode(encoded) kt_file = os.path.join(spool_dir, ktname) _write_keytab(kt_file, keytab_data) else: _LOGGER.warning('got empty keytab %s', ktname) return True finally: client.disconnect()
def forward(host, port, tktfile=None): """Forward tickets to the ticket acceptor.""" service = 'host@%s' % host _LOGGER.debug('connecting: %s:%s, %s', host, port, service) if tktfile is None: krb5ccname = os.environ.get('KRB5CCNAME', 'FILE:/tmp/krb5cc_{}'.format(os.getuid())) if krb5ccname.startswith('KEYRING'): raise Exception('Keyring is not supported yet.') if krb5ccname.startswith('FILE:'): tktfile = krb5ccname[len('FILE:'):] else: tktfile = krb5ccname _LOGGER.debug('Using KRB5CCNAME: %s', tktfile) with io.open(tktfile, 'rb') as f: tkt = f.read() _LOGGER.debug('Ticket checksum: %s', hashlib.sha1(tkt).hexdigest()) # encoded = base64.urlsafe_b64encode(tkt) client = gssapiprotocol.GSSAPILineClient(host, int(port), service) try: if client.connect(): client.write(tkt) line = client.read() _LOGGER.debug('Got reply: %s', line.decode()) except Exception as err: # pylint: disable=broad-except _LOGGER.warning('Failed to forward tickets: %s:%s, %s', host, port, err) return False finally: client.disconnect() return True