denisenkom / pytds

Python DBAPI driver for MSSQL using pure Python TDS (Tabular Data Stream) protocol implementation
MIT License
191 stars 53 forks source link

Support for Kerberos tokens? #102

Open amachanic opened 6 years ago

amachanic commented 6 years ago

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!

denisenkom commented 6 years ago

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?

amachanic commented 6 years ago

I would be happy to help.

denisenkom commented 6 years ago

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.

amachanic commented 6 years ago

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?

amachanic commented 6 years ago

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.

amachanic commented 6 years ago

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...

denisenkom commented 6 years ago

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?

amachanic commented 6 years ago

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.

denisenkom commented 6 years ago

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

airdrik commented 3 years ago

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!