Problem:

Masz bazę danych Synapse dostępną w usłudze Azure. Posiadasz uprawnienia, żeby połączyć się do tej bazy przy użyciu service principala. To połączenie musisz wykonać w Pythonie. W jaki sposób połączyć się posiadając dane service principala do usługi Synapse?

Rozwiązanie:

Użyjemy .env do przechowywania zmienny środowiskowych. Użyjemy azure.identity żeby połączyć się z usługą i wygenerować token dostępowy. Następnie posiadając token utworzymy połączenie pyodbc.

Zawiłe? Teraz trochę bardziej szczegółowo.

Zdefiniowanie zmiennych środowiskowych

Co potrzebujemy przechowywać w zmiennych środowiskowych?

Identyfikator tenanta, service princiapal id oraz sekret. Nazwę bazy danych i serwera.

Oczywiście service principal musi mieć możliwość odczytywania danych z Synapse i dodawanie mu uprawnień jest poza zakresem tego artykułu.

Mógłbyś też tą konfigurację przechowywać w Key Vault i pewnie tak byś zrobił w środowisku produkcyjny. Tutaj używamy zmiennych środowiskowych dla uproszczenia.

Generowanie tokena

Zdefiniujmy jeszcze kontekst, dla którego będzie generowany token:

db_scope = 'https://database.windows.net/.default'

Użyjemy ClientSecretCredentials do wygenerowania tokena:

from azure.identity import ClientSecretCredential
auth = ClientSecretCredential(authority='https://login.microsoftonline.com/',
                              tenant_id=SynapseUtil.tenant_id,
                              client_id=SynapseUtil.client_id,
                              client_secret=SynapseUtil.client_secret)
access_token = auth.get_token(SynapseUtil.db_scope)
token = access_token.token

Ten kod wygeneruje token dostępowy do Synapsa.

Tworzenie połączenia do Synapse

Szczegóły połączenia wyglądają u mnie w ten sposób. Nie potrzebny jest ani użytkownik ani hasło.

connection_string = f"Driver={{ODBC Driver 18 for SQL Server}};Server={default_server};Database={default_database};Encrypt=yes;Connection Timeout=30"

Ta część kodu jest opisane na stronach Microsoftu. Może dlatego nie wygląda tak zrozumiale 😉

https://learn.microsoft.com/en-us/azure/azure-sql/database/azure-sql-python-quickstart?view=azuresql&tabs=windows%2Csql-auth

token_bytes = token.encode("UTF-16-LE")
token_struct = struct.pack(f'<I{len(token_bytes)}s', len(token_bytes), token_bytes)
        SQL_COPT_SS_ACCESS_TOKEN = 1256  # This connection option is defined by microsoft in msodbcsql.h
Connection = pyodbc.connect(connection_string, attrs_before={SQL_COPT_SS_ACCESS_TOKEN: token_struct})

W powyższej linii podstawiany jest przekształcony token i otwierane połączenie do bazy. Teraz już wolna droga do zadawania zapytań 🙂

Jak zwykle cały kod znajdziesz na GitHub.
https://github.com/rgogloza/nextlevelbi/blob/master/python/synapse_util.py