denisenkom / pytds

Python DBAPI driver for MSSQL using pure Python TDS (Tabular Data Stream) protocol implementation

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Support for Kerberos tokens?

amachanic opened this issue · comments

I'm trying to use pytds on Linux, in conjunction with a Kerberos token for integrated authentication. I tried instantiating SspiAuth as on Windows, but I get an error when it attempts to import WINFUNCTYPE.

Not sure if I'm missing something or if this is completely unsupported. Is there any existing way to get this working? If not, any chance of an enhancement along these lines?

Thank you!

Currently Kerberos support is not implemented on Linux. I may be able to look into that but I would need help with testing. Would you be able to help with that?

I would be happy to help.

I pushed POC code into separate branch: https://github.com/denisenkom/pytds/tree/kerberos-support

To test you would need to install kerberos package:
pip install kerberos

To connect using Kerberos modify your connect call as specified in below example:
connect(..., auth=pytds.login.KerberosAuth('MSSQLSvc/yourserver:yourport'))

If this does not work send me logged output.

Hm, no luck on the first try:

"...python_tds-1.9.0_112_g55a7-py3.6.egg/pytds/login.py", line 169, in create_packet
kerberos.GSSError: (('Unspecified GSS failure. Minor code may provide more information', 851968), ('Server not found in Kerberos database', -1765328377))

The token has been cached using kinit and trusted auth works fine in pyodbc.

Is there a more detailed log somewhere?

I did some research on the kerberos module usage and found that the following form is recommended in most places:

MSSQLSvc@server

... where "server" is a FQDN. Doing this got me past the initial error, and now I'm hitting a new one:

"...python_tds-1.9.0_112_g55a7-py3.6.egg/pytds/login.py", line 178, in handle_next
TypeError: argument 2 must be str, not bytes

I'll keep messing around with it.

Got it working!

I changed line 178 from:

res = self._kerberos.authGSSClientStep(self._context, base64.b64encode(packet))

to:

res = self._kerberos.authGSSClientStep(self._context, base64.b64encode(packet).decode('utf-8'))

Not sure if there's a more direct way to do that but I just ran a few queries and data is properly flowing end-to-end...

Nice, I did not expect it to that simple. So you say you used principal like MSSQLSvc@server, did you include port number? E.g. MSSQLSvc@dbserver:1234? Or is it just MSSQLSvc@dbserver? Do you know if it is configurable on the server?

I just tested and it works either with or without a port number. The port is configurable, but I don't have a server here running anything other than 1433 so I can't test that. I did try using an invalid port number and it failed, so apparently it does do something.

I pushed improved version. Please test it. To connect use following:
connect(..., use_sso=True)

I can also confirm after using 1.11.0 for several months now, the use_sso=True feature works to integrate with our kerberos authentication.
Thank you!