Solución:
Terminé usando la biblioteca pymssql, que básicamente es pyodbc sobre el controlador FreeTDS. Funcionó fuera de la caja.
Es extraño cómo me costó tanto descubrir esta biblioteca …
Debe obtener un vale de Kerberos para que esto funcione. Su ejemplo no especifica si su sistema Linux está configurado para autenticarse a través de Kerberos o si ha obtenido previamente un ticket de Kerberos antes de que su código llegue a su cadena de conexión.
Si su sistema Linux está configurado para autenticarse a través de Kerberos, entonces, como prueba de concepto, puede obtener un ticket de Kerberos usando kinit desde la línea de comando. Esto es lo que me funciona en python3 que se ejecuta en Ubuntu en Windows a través de WSL. El código de Python:
#!/usr/bin/env python
# minimal example using Kerberos auth
import sys
import re
import pyodbc
driver="{ODBC Driver 17 for SQL Server}"
server = sys.argv[1]
database = sys.argv[2]
# trusted_connection uses kerberos ticket and ignores UID and PASSWORD in connection string
# https://docs.microsoft.com/en-us/sql/connect/odbc/linux-mac/using-integrated-authentication?view=sql-server-ver15
try:
cnxn = pyodbc.connect(driver=driver, server=server, database=database, trusted_connection='yes')
cursor = cnxn.cursor()
except pyodbc.Error as ex:
msg = ex.args[1]
if re.search('No Kerberos', msg):
print('You must login using kinit before using this script.')
exit(1)
else:
raise
# Sample select query
cursor.execute("SELECT @@version;")
row = cursor.fetchone()
while row:
print(row[0])
row = cursor.fetchone()
print('success')
Esto le indica si no tiene un boleto. Dado que utiliza un ticket, no es necesario que especifique un usuario o contraseña en el script. Ignorará ambos.
Ahora lo ejecutamos:
[email protected]:~# kdestroy # make sure there are no active tickets
kdestroy: No credentials cache found while destroying cache
[email protected]:~# python pyodbc_sql_server_test.py tcp:dbserver.example.com mydatabase
You must login using kinit before using this script.
[email protected]:~# kinit
Password for [email protected]:
[email protected]:~# python pyodbc_sql_server_test.py tcp:dbserver.example.com mydatabase
Microsoft SQL Server 2016 (SP2-GDR) (KB4505220) - 13.0.5101.9 (X64)
Jun 15 2019 23:15:58
Copyright (c) Microsoft Corporation
Enterprise Edition (64-bit) on Windows Server 2016 Datacenter 10.0 <X64> (Build 14393: )
success
[email protected]:~#
También puede tener éxito al obtener un boleto de Kerberos a partir del código de Python que se ejecuta antes de realizar esta conexión, pero eso está más allá del alcance de esta respuesta. Una búsqueda de módulos de Python Kerberos podría indicarle una solución.
También parece posible configurar el sistema Linux para que, tan pronto como un usuario inicie sesión, obtenga automáticamente un vale de Kerberos que pueda pasarse a otros procesos. Eso también está fuera del alcance de esta respuesta, pero una búsqueda de un ticket Kerberos automático al iniciar sesión en Linux puede dar algunas pistas.
Encuentro dos formas para la misma tarea. Tengo un servidor MSSQL con autenticación AD.
Puede utilizar JVM. Cargue e instale JAVA https://www.oracle.com/technetwork/java/javase/downloads/jre8-downloads-2133155.html. También instale JPype1 versión 0.6.3 pip install JPype==0.6.3
. La versión anterior a 0.6.3 no funcionará correctamente
import jaydebeapi
import pandas as pd
driver_name = "net.sourceforge.jtds.jdbc.Driver"
connection_url="jdbc:jtds:sqlserver://<server>:<port>/<database name>"
connection_properties = {
"domain": "<domain name>",
"user": "<username>",
"password": "<pwd>"}
jar_path = <path to jsds>"/jtds-1.3.1.jar"
CONN = jaydebeapi.connect(driver_name, connection_url, connection_properties, jar_path)
sql = "SELECT * FROM INFORMATION_SCHEMA.COLUMNS"
df = pd.read_sql(sql, CONN)
Esta versión fue demasiado lenta para mí.
También puedes usar pyodbc a través de FreeTDS. Para crear una conexión FreeTDS Instale FreeTDS en su Linux apt-get install tdsodbc freetds-bin
, configurar FreeTDS /etc/odbcinst.ini como esto:
[FreeTDS]
Description=FreeTDS
Driver=/usr/lib/x86_64-linux-gnu/odbc/libtdsodbc.so
Setup=/usr/lib/x86_64-linux-gnu/odbc/libtdsS.so
y enciéndelo odbcinst -i -d -f /etc/odbcinst.ini
Después de eso, puedes usar pyodbc
import pandas as pd
import pyodbc
CONN =pyodbc.connect('DRIVER={FreeTDS};'
'Server=<server>;'
'Database=<database>;'
'UID=<domain name>\<username>;'
'PWD=<password>;'
'TDS_Version=8.0;'
'Port=1433;')
sql = "SELECT * FROM INFORMATION_SCHEMA.COLUMNS"
df = pd.read_sql(sql, CONN)
Funciona mucho mas rapido