22import struct
33import time
44from contextlib import contextmanager
5+ from dataclasses import dataclass
56from itertools import chain , repeat
67from typing import Any , Callable , Dict , Mapping , Optional , Tuple , Type , Union
78
89import agate
910import dbt_common .exceptions
1011import pyodbc
11- from azure .core .credentials import AccessToken
12- from azure .identity import (
13- AzureCliCredential ,
14- ClientSecretCredential ,
15- DefaultAzureCredential ,
16- EnvironmentCredential ,
17- ManagedIdentityCredential ,
18- )
12+
13+ try :
14+ from azure .core .credentials import AccessToken
15+ except ModuleNotFoundError :
16+ @dataclass
17+ class AccessToken :
18+ token : str
19+ expires_on : int
20+
21+
22+ try :
23+ from azure .identity import (
24+ AzureCliCredential ,
25+ ClientSecretCredential ,
26+ DefaultAzureCredential ,
27+ EnvironmentCredential ,
28+ ManagedIdentityCredential ,
29+ )
30+
31+ _AZURE_IDENTITY_IMPORT_ERROR = None
32+ except ModuleNotFoundError as exc :
33+ AzureCliCredential = None
34+ ClientSecretCredential = None
35+ DefaultAzureCredential = None
36+ EnvironmentCredential = None
37+ ManagedIdentityCredential = None
38+ _AZURE_IDENTITY_IMPORT_ERROR = exc
39+
1940from dbt .adapters .contracts .connection import AdapterResponse , Connection , ConnectionState
2041from dbt .adapters .events .logging import AdapterLogger
2142from dbt .adapters .events .types import AdapterEventDebug , ConnectionUsed , SQLQuery , SQLQueryStatus
5172}
5273
5374
75+ def _require_azure_identity (authentication : str ) -> None :
76+ if _AZURE_IDENTITY_IMPORT_ERROR is not None :
77+ raise dbt_common .exceptions .DbtRuntimeError (
78+ "Azure authentication '{}' requires the optional dependency 'azure-identity'. "
79+ "Install it with `pip install azure-identity` or use a non-Azure authentication mode."
80+ .format (authentication )
81+ ) from _AZURE_IDENTITY_IMPORT_ERROR
82+
83+
5484def convert_bytes_to_mswindows_byte_string (value : bytes ) -> bytes :
5585 """
5686 Convert bytes to a Microsoft windows byte string.
@@ -110,6 +140,7 @@ def get_cli_access_token(
110140 Access token.
111141 """
112142 _ = credentials
143+ _require_azure_identity ("cli" )
113144 token = AzureCliCredential ().get_token (
114145 scope , timeout = getattr (credentials , "login_timeout" , None )
115146 )
@@ -132,6 +163,7 @@ def get_auto_access_token(
132163 out : AccessToken
133164 The access token.
134165 """
166+ _require_azure_identity ("auto" )
135167 token = DefaultAzureCredential ().get_token (
136168 scope , timeout = getattr (credentials , "login_timeout" , None )
137169 )
@@ -154,6 +186,7 @@ def get_environment_access_token(
154186 out : AccessToken
155187 The access token.
156188 """
189+ _require_azure_identity ("environment" )
157190 token = EnvironmentCredential ().get_token (
158191 scope , timeout = getattr (credentials , "login_timeout" , None )
159192 )
@@ -177,6 +210,7 @@ def get_msi_access_token(
177210 The access token.
178211 """
179212 _ = credentials
213+ _require_azure_identity ("msi" )
180214 token = ManagedIdentityCredential ().get_token (scope )
181215 return token
182216
@@ -198,6 +232,7 @@ def get_sp_access_token(
198232 The access token.
199233 """
200234 _ = scope
235+ _require_azure_identity ("serviceprincipal" )
201236 token = ClientSecretCredential (
202237 str (credentials .tenant_id ),
203238 str (credentials .client_id ),
0 commit comments