Ejemplo n.º 1
0
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()
Ejemplo n.º 2
0
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
Ejemplo n.º 3
0
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))
Ejemplo n.º 4
0
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)
Ejemplo n.º 5
0
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()
Ejemplo n.º 6
0
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()
Ejemplo n.º 7
0
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