snowflake-connector-python 3.16.0__cp313-cp313-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (246) hide show
  1. snowflake/connector/__init__.py +96 -0
  2. snowflake/connector/_query_context_cache.py +276 -0
  3. snowflake/connector/_sql_util.py +48 -0
  4. snowflake/connector/_utils.py +70 -0
  5. snowflake/connector/arrow_context.py +203 -0
  6. snowflake/connector/auth/__init__.py +53 -0
  7. snowflake/connector/auth/_auth.py +586 -0
  8. snowflake/connector/auth/_http_server.py +220 -0
  9. snowflake/connector/auth/_oauth_base.py +400 -0
  10. snowflake/connector/auth/by_plugin.py +219 -0
  11. snowflake/connector/auth/default.py +36 -0
  12. snowflake/connector/auth/idtoken.py +72 -0
  13. snowflake/connector/auth/keypair.py +222 -0
  14. snowflake/connector/auth/no_auth.py +39 -0
  15. snowflake/connector/auth/oauth.py +49 -0
  16. snowflake/connector/auth/oauth_code.py +479 -0
  17. snowflake/connector/auth/oauth_credentials.py +66 -0
  18. snowflake/connector/auth/okta.py +335 -0
  19. snowflake/connector/auth/pat.py +39 -0
  20. snowflake/connector/auth/usrpwdmfa.py +69 -0
  21. snowflake/connector/auth/webbrowser.py +502 -0
  22. snowflake/connector/auth/workload_identity.py +94 -0
  23. snowflake/connector/azure_storage_client.py +276 -0
  24. snowflake/connector/backoff_policies.py +141 -0
  25. snowflake/connector/bind_upload_agent.py +89 -0
  26. snowflake/connector/cache.py +696 -0
  27. snowflake/connector/compat.py +127 -0
  28. snowflake/connector/config_manager.py +496 -0
  29. snowflake/connector/connection.py +2273 -0
  30. snowflake/connector/connection_diagnostic.py +776 -0
  31. snowflake/connector/constants.py +442 -0
  32. snowflake/connector/converter.py +785 -0
  33. snowflake/connector/converter_issue23517.py +87 -0
  34. snowflake/connector/converter_null.py +14 -0
  35. snowflake/connector/converter_snowsql.py +205 -0
  36. snowflake/connector/cursor.py +1951 -0
  37. snowflake/connector/dbapi.py +53 -0
  38. snowflake/connector/description.py +19 -0
  39. snowflake/connector/direct_file_operation_utils.py +88 -0
  40. snowflake/connector/encryption_util.py +220 -0
  41. snowflake/connector/errorcode.py +91 -0
  42. snowflake/connector/errors.py +615 -0
  43. snowflake/connector/externals_utils/__init__.py +0 -0
  44. snowflake/connector/externals_utils/externals_setup.py +27 -0
  45. snowflake/connector/feature.py +4 -0
  46. snowflake/connector/file_compression_type.py +118 -0
  47. snowflake/connector/file_lock.py +72 -0
  48. snowflake/connector/file_transfer_agent.py +1215 -0
  49. snowflake/connector/file_util.py +153 -0
  50. snowflake/connector/gcs_storage_client.py +474 -0
  51. snowflake/connector/gzip_decoder.py +85 -0
  52. snowflake/connector/local_storage_client.py +90 -0
  53. snowflake/connector/log_configuration.py +60 -0
  54. snowflake/connector/logging_utils/__init__.py +0 -0
  55. snowflake/connector/logging_utils/filters.py +72 -0
  56. snowflake/connector/nanoarrow_arrow_iterator.cp313-win_amd64.pyd +0 -0
  57. snowflake/connector/nanoarrow_cpp/ArrowIterator/ArrayConverter.cpp +60 -0
  58. snowflake/connector/nanoarrow_cpp/ArrowIterator/ArrayConverter.hpp +29 -0
  59. snowflake/connector/nanoarrow_cpp/ArrowIterator/BinaryConverter.cpp +19 -0
  60. snowflake/connector/nanoarrow_cpp/ArrowIterator/BinaryConverter.hpp +26 -0
  61. snowflake/connector/nanoarrow_cpp/ArrowIterator/BooleanConverter.cpp +21 -0
  62. snowflake/connector/nanoarrow_cpp/ArrowIterator/BooleanConverter.hpp +23 -0
  63. snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowChunkIterator.cpp +557 -0
  64. snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowChunkIterator.hpp +98 -0
  65. snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowIterator.cpp +125 -0
  66. snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowIterator.hpp +115 -0
  67. snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowTableIterator.cpp +1005 -0
  68. snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowTableIterator.hpp +127 -0
  69. snowflake/connector/nanoarrow_cpp/ArrowIterator/DateConverter.cpp +47 -0
  70. snowflake/connector/nanoarrow_cpp/ArrowIterator/DateConverter.hpp +46 -0
  71. snowflake/connector/nanoarrow_cpp/ArrowIterator/DecFloatConverter.cpp +83 -0
  72. snowflake/connector/nanoarrow_cpp/ArrowIterator/DecFloatConverter.hpp +35 -0
  73. snowflake/connector/nanoarrow_cpp/ArrowIterator/DecimalConverter.cpp +97 -0
  74. snowflake/connector/nanoarrow_cpp/ArrowIterator/DecimalConverter.hpp +72 -0
  75. snowflake/connector/nanoarrow_cpp/ArrowIterator/FixedSizeListConverter.cpp +73 -0
  76. snowflake/connector/nanoarrow_cpp/ArrowIterator/FixedSizeListConverter.hpp +28 -0
  77. snowflake/connector/nanoarrow_cpp/ArrowIterator/FloatConverter.cpp +30 -0
  78. snowflake/connector/nanoarrow_cpp/ArrowIterator/FloatConverter.hpp +35 -0
  79. snowflake/connector/nanoarrow_cpp/ArrowIterator/IColumnConverter.hpp +17 -0
  80. snowflake/connector/nanoarrow_cpp/ArrowIterator/IntConverter.cpp +23 -0
  81. snowflake/connector/nanoarrow_cpp/ArrowIterator/IntConverter.hpp +45 -0
  82. snowflake/connector/nanoarrow_cpp/ArrowIterator/IntervalConverter.cpp +71 -0
  83. snowflake/connector/nanoarrow_cpp/ArrowIterator/IntervalConverter.hpp +56 -0
  84. snowflake/connector/nanoarrow_cpp/ArrowIterator/LICENSE.txt +209 -0
  85. snowflake/connector/nanoarrow_cpp/ArrowIterator/MapConverter.cpp +75 -0
  86. snowflake/connector/nanoarrow_cpp/ArrowIterator/MapConverter.hpp +30 -0
  87. snowflake/connector/nanoarrow_cpp/ArrowIterator/ObjectConverter.cpp +46 -0
  88. snowflake/connector/nanoarrow_cpp/ArrowIterator/ObjectConverter.hpp +29 -0
  89. snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Common.cpp +8 -0
  90. snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Common.hpp +95 -0
  91. snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Helpers.cpp +57 -0
  92. snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Helpers.hpp +36 -0
  93. snowflake/connector/nanoarrow_cpp/ArrowIterator/SnowflakeType.cpp +34 -0
  94. snowflake/connector/nanoarrow_cpp/ArrowIterator/SnowflakeType.hpp +48 -0
  95. snowflake/connector/nanoarrow_cpp/ArrowIterator/StringConverter.cpp +19 -0
  96. snowflake/connector/nanoarrow_cpp/ArrowIterator/StringConverter.hpp +26 -0
  97. snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeConverter.cpp +36 -0
  98. snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeConverter.hpp +31 -0
  99. snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeStampConverter.cpp +346 -0
  100. snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeStampConverter.hpp +145 -0
  101. snowflake/connector/nanoarrow_cpp/ArrowIterator/Util/macros.hpp +14 -0
  102. snowflake/connector/nanoarrow_cpp/ArrowIterator/Util/time.cpp +65 -0
  103. snowflake/connector/nanoarrow_cpp/ArrowIterator/Util/time.hpp +68 -0
  104. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_accessors.h +101 -0
  105. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_alloc.h +127 -0
  106. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_assert.h +45 -0
  107. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_builder.h +1908 -0
  108. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_emitter.h +215 -0
  109. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_endian.h +125 -0
  110. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_epilogue.h +7 -0
  111. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_flatbuffers.h +55 -0
  112. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_identifier.h +148 -0
  113. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_iov.h +31 -0
  114. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_prologue.h +8 -0
  115. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_refmap.h +144 -0
  116. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_rtconfig.h +162 -0
  117. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_types.h +97 -0
  118. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_verifier.h +239 -0
  119. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/flatcc_portable.h +14 -0
  120. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/paligned_alloc.h +210 -0
  121. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pattributes.h +84 -0
  122. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic.h +84 -0
  123. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic_pop.h +20 -0
  124. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic_push.h +51 -0
  125. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pendian.h +206 -0
  126. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pendian_detect.h +118 -0
  127. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pinline.h +19 -0
  128. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pinttypes.h +52 -0
  129. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/portable.h +2 -0
  130. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/portable_basic.h +25 -0
  131. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstatic_assert.h +67 -0
  132. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstdalign.h +162 -0
  133. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstdint.h +898 -0
  134. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/punaligned.h +190 -0
  135. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pversion.h +6 -0
  136. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pwarnings.h +52 -0
  137. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc.c +3204 -0
  138. snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow.c +3217 -0
  139. snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow.h +3618 -0
  140. snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow.hpp +379 -0
  141. snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_arrow_iterator.pyx +256 -0
  142. snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_device.c +512 -0
  143. snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_device.h +350 -0
  144. snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_ipc.c +33273 -0
  145. snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_ipc.h +397 -0
  146. snowflake/connector/nanoarrow_cpp/Logging/logging.cpp +100 -0
  147. snowflake/connector/nanoarrow_cpp/Logging/logging.hpp +49 -0
  148. snowflake/connector/network.py +1297 -0
  149. snowflake/connector/ocsp_asn1crypto.py +447 -0
  150. snowflake/connector/ocsp_snowflake.py +1883 -0
  151. snowflake/connector/options.py +131 -0
  152. snowflake/connector/pandas_tools.py +732 -0
  153. snowflake/connector/proxy.py +43 -0
  154. snowflake/connector/py.typed +0 -0
  155. snowflake/connector/result_batch.py +786 -0
  156. snowflake/connector/result_set.py +319 -0
  157. snowflake/connector/s3_storage_client.py +605 -0
  158. snowflake/connector/secret_detector.py +181 -0
  159. snowflake/connector/sf_dirs.py +64 -0
  160. snowflake/connector/sfbinaryformat.py +35 -0
  161. snowflake/connector/sfdatetime.py +345 -0
  162. snowflake/connector/snow_logging.py +144 -0
  163. snowflake/connector/sqlstate.py +9 -0
  164. snowflake/connector/ssd_internal_keys.py +30 -0
  165. snowflake/connector/ssl_wrap_socket.py +134 -0
  166. snowflake/connector/storage_client.py +478 -0
  167. snowflake/connector/telemetry.py +249 -0
  168. snowflake/connector/telemetry_oob.py +543 -0
  169. snowflake/connector/test_util.py +30 -0
  170. snowflake/connector/time_util.py +159 -0
  171. snowflake/connector/token_cache.py +402 -0
  172. snowflake/connector/tool/__init__.py +0 -0
  173. snowflake/connector/tool/dump_certs.py +57 -0
  174. snowflake/connector/tool/dump_ocsp_response.py +139 -0
  175. snowflake/connector/tool/dump_ocsp_response_cache.py +194 -0
  176. snowflake/connector/tool/probe_connection.py +69 -0
  177. snowflake/connector/url_util.py +49 -0
  178. snowflake/connector/util_text.py +301 -0
  179. snowflake/connector/vendored/__init__.py +3 -0
  180. snowflake/connector/vendored/requests/LICENSE +175 -0
  181. snowflake/connector/vendored/requests/__init__.py +169 -0
  182. snowflake/connector/vendored/requests/__version__.py +14 -0
  183. snowflake/connector/vendored/requests/_internal_utils.py +50 -0
  184. snowflake/connector/vendored/requests/adapters.py +537 -0
  185. snowflake/connector/vendored/requests/api.py +157 -0
  186. snowflake/connector/vendored/requests/auth.py +315 -0
  187. snowflake/connector/vendored/requests/certs.py +17 -0
  188. snowflake/connector/vendored/requests/compat.py +79 -0
  189. snowflake/connector/vendored/requests/cookies.py +561 -0
  190. snowflake/connector/vendored/requests/exceptions.py +140 -0
  191. snowflake/connector/vendored/requests/help.py +134 -0
  192. snowflake/connector/vendored/requests/hooks.py +33 -0
  193. snowflake/connector/vendored/requests/models.py +1033 -0
  194. snowflake/connector/vendored/requests/sessions.py +833 -0
  195. snowflake/connector/vendored/requests/status_codes.py +128 -0
  196. snowflake/connector/vendored/requests/structures.py +99 -0
  197. snowflake/connector/vendored/requests/utils.py +1093 -0
  198. snowflake/connector/vendored/urllib3/LICENSE.txt +21 -0
  199. snowflake/connector/vendored/urllib3/__init__.py +85 -0
  200. snowflake/connector/vendored/urllib3/_collections.py +355 -0
  201. snowflake/connector/vendored/urllib3/_version.py +2 -0
  202. snowflake/connector/vendored/urllib3/connection.py +572 -0
  203. snowflake/connector/vendored/urllib3/connectionpool.py +1137 -0
  204. snowflake/connector/vendored/urllib3/contrib/__init__.py +0 -0
  205. snowflake/connector/vendored/urllib3/contrib/_appengine_environ.py +36 -0
  206. snowflake/connector/vendored/urllib3/contrib/_securetransport/__init__.py +0 -0
  207. snowflake/connector/vendored/urllib3/contrib/_securetransport/bindings.py +519 -0
  208. snowflake/connector/vendored/urllib3/contrib/_securetransport/low_level.py +397 -0
  209. snowflake/connector/vendored/urllib3/contrib/appengine.py +314 -0
  210. snowflake/connector/vendored/urllib3/contrib/ntlmpool.py +130 -0
  211. snowflake/connector/vendored/urllib3/contrib/pyopenssl.py +509 -0
  212. snowflake/connector/vendored/urllib3/contrib/securetransport.py +920 -0
  213. snowflake/connector/vendored/urllib3/contrib/socks.py +216 -0
  214. snowflake/connector/vendored/urllib3/exceptions.py +323 -0
  215. snowflake/connector/vendored/urllib3/fields.py +274 -0
  216. snowflake/connector/vendored/urllib3/filepost.py +98 -0
  217. snowflake/connector/vendored/urllib3/packages/__init__.py +0 -0
  218. snowflake/connector/vendored/urllib3/packages/backports/__init__.py +0 -0
  219. snowflake/connector/vendored/urllib3/packages/backports/makefile.py +51 -0
  220. snowflake/connector/vendored/urllib3/packages/backports/weakref_finalize.py +155 -0
  221. snowflake/connector/vendored/urllib3/packages/six.py +1076 -0
  222. snowflake/connector/vendored/urllib3/poolmanager.py +540 -0
  223. snowflake/connector/vendored/urllib3/request.py +191 -0
  224. snowflake/connector/vendored/urllib3/response.py +885 -0
  225. snowflake/connector/vendored/urllib3/util/__init__.py +49 -0
  226. snowflake/connector/vendored/urllib3/util/connection.py +156 -0
  227. snowflake/connector/vendored/urllib3/util/proxy.py +57 -0
  228. snowflake/connector/vendored/urllib3/util/queue.py +22 -0
  229. snowflake/connector/vendored/urllib3/util/request.py +146 -0
  230. snowflake/connector/vendored/urllib3/util/response.py +107 -0
  231. snowflake/connector/vendored/urllib3/util/retry.py +620 -0
  232. snowflake/connector/vendored/urllib3/util/ssl_.py +495 -0
  233. snowflake/connector/vendored/urllib3/util/ssl_match_hostname.py +159 -0
  234. snowflake/connector/vendored/urllib3/util/ssltransport.py +221 -0
  235. snowflake/connector/vendored/urllib3/util/timeout.py +271 -0
  236. snowflake/connector/vendored/urllib3/util/url.py +435 -0
  237. snowflake/connector/vendored/urllib3/util/wait.py +152 -0
  238. snowflake/connector/version.py +3 -0
  239. snowflake/connector/wif_util.py +407 -0
  240. snowflake_connector_python-3.16.0.dist-info/METADATA +1475 -0
  241. snowflake_connector_python-3.16.0.dist-info/RECORD +246 -0
  242. snowflake_connector_python-3.16.0.dist-info/WHEEL +5 -0
  243. snowflake_connector_python-3.16.0.dist-info/entry_points.txt +4 -0
  244. snowflake_connector_python-3.16.0.dist-info/licenses/LICENSE.txt +202 -0
  245. snowflake_connector_python-3.16.0.dist-info/licenses/NOTICE +8 -0
  246. snowflake_connector_python-3.16.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,53 @@
1
+ from __future__ import annotations
2
+
3
+ from ._auth import Auth, get_public_key_fingerprint, get_token_from_private_key
4
+ from .by_plugin import AuthByPlugin, AuthType
5
+ from .default import AuthByDefault
6
+ from .idtoken import AuthByIdToken
7
+ from .keypair import AuthByKeyPair
8
+ from .no_auth import AuthNoAuth
9
+ from .oauth import AuthByOAuth
10
+ from .oauth_code import AuthByOauthCode
11
+ from .oauth_credentials import AuthByOauthCredentials
12
+ from .okta import AuthByOkta
13
+ from .pat import AuthByPAT
14
+ from .usrpwdmfa import AuthByUsrPwdMfa
15
+ from .webbrowser import AuthByWebBrowser
16
+ from .workload_identity import AuthByWorkloadIdentity
17
+
18
+ FIRST_PARTY_AUTHENTICATORS = frozenset(
19
+ (
20
+ AuthByDefault,
21
+ AuthByKeyPair,
22
+ AuthByOAuth,
23
+ AuthByOauthCode,
24
+ AuthByOauthCredentials,
25
+ AuthByOkta,
26
+ AuthByUsrPwdMfa,
27
+ AuthByWebBrowser,
28
+ AuthByIdToken,
29
+ AuthByPAT,
30
+ AuthByWorkloadIdentity,
31
+ AuthNoAuth,
32
+ )
33
+ )
34
+
35
+ __all__ = [
36
+ "AuthByPlugin",
37
+ "AuthByDefault",
38
+ "AuthByKeyPair",
39
+ "AuthByPAT",
40
+ "AuthByOAuth",
41
+ "AuthByOauthCode",
42
+ "AuthByOauthCredentials",
43
+ "AuthByOkta",
44
+ "AuthByUsrPwdMfa",
45
+ "AuthByWebBrowser",
46
+ "AuthByWorkloadIdentity",
47
+ "AuthNoAuth",
48
+ "Auth",
49
+ "AuthType",
50
+ "FIRST_PARTY_AUTHENTICATORS",
51
+ "get_public_key_fingerprint",
52
+ "get_token_from_private_key",
53
+ ]
@@ -0,0 +1,586 @@
1
+ from __future__ import annotations
2
+
3
+ import copy
4
+ import json
5
+ import logging
6
+ import uuid
7
+ from datetime import datetime, timezone
8
+ from threading import Thread
9
+ from typing import TYPE_CHECKING, Any, Callable
10
+
11
+ from cryptography.hazmat.backends import default_backend
12
+ from cryptography.hazmat.primitives.serialization import (
13
+ Encoding,
14
+ NoEncryption,
15
+ PrivateFormat,
16
+ load_der_private_key,
17
+ load_pem_private_key,
18
+ )
19
+
20
+ from ..compat import urlencode
21
+ from ..constants import (
22
+ DAY_IN_SECONDS,
23
+ HTTP_HEADER_ACCEPT,
24
+ HTTP_HEADER_CONTENT_TYPE,
25
+ HTTP_HEADER_SERVICE_NAME,
26
+ HTTP_HEADER_USER_AGENT,
27
+ PARAMETER_CLIENT_REQUEST_MFA_TOKEN,
28
+ PARAMETER_CLIENT_STORE_TEMPORARY_CREDENTIAL,
29
+ )
30
+ from ..description import (
31
+ COMPILER,
32
+ IMPLEMENTATION,
33
+ OPERATING_SYSTEM,
34
+ PLATFORM,
35
+ PYTHON_VERSION,
36
+ )
37
+ from ..errorcode import ER_FAILED_TO_CONNECT_TO_DB
38
+ from ..errors import (
39
+ BadGatewayError,
40
+ DatabaseError,
41
+ Error,
42
+ ForbiddenError,
43
+ ProgrammingError,
44
+ ServiceUnavailableError,
45
+ )
46
+ from ..network import (
47
+ ACCEPT_TYPE_APPLICATION_SNOWFLAKE,
48
+ CONTENT_TYPE_APPLICATION_JSON,
49
+ ID_TOKEN_INVALID_LOGIN_REQUEST_GS_CODE,
50
+ OAUTH_ACCESS_TOKEN_EXPIRED_GS_CODE,
51
+ PYTHON_CONNECTOR_USER_AGENT,
52
+ ReauthenticationRequest,
53
+ )
54
+ from ..sqlstate import SQLSTATE_CONNECTION_WAS_NOT_ESTABLISHED
55
+ from ..token_cache import TokenCache, TokenKey, TokenType
56
+ from ..version import VERSION
57
+ from .no_auth import AuthNoAuth
58
+
59
+ if TYPE_CHECKING:
60
+ from . import AuthByPlugin
61
+
62
+ logger = logging.getLogger(__name__)
63
+
64
+ # keyring
65
+ KEYRING_SERVICE_NAME = "net.snowflake.temporary_token"
66
+ KEYRING_USER = "temp_token"
67
+ KEYRING_DRIVER_NAME = "SNOWFLAKE-PYTHON-DRIVER"
68
+
69
+ ID_TOKEN = "ID_TOKEN"
70
+ MFA_TOKEN = "MFATOKEN"
71
+
72
+ AUTHENTICATION_REQUEST_KEY_WHITELIST = {
73
+ "ACCOUNT_NAME",
74
+ "AUTHENTICATOR",
75
+ "CLIENT_APP_ID",
76
+ "CLIENT_APP_VERSION",
77
+ "CLIENT_ENVIRONMENT",
78
+ "EXT_AUTHN_DUO_METHOD",
79
+ "LOGIN_NAME",
80
+ "SESSION_PARAMETERS",
81
+ "SVN_REVISION",
82
+ }
83
+
84
+
85
+ class Auth:
86
+ """Snowflake Authenticator."""
87
+
88
+ def __init__(self, rest) -> None:
89
+ self._rest = rest
90
+ self._token_cache: TokenCache | None = None
91
+
92
+ @staticmethod
93
+ def base_auth_data(
94
+ user,
95
+ account,
96
+ application,
97
+ internal_application_name,
98
+ internal_application_version,
99
+ ocsp_mode,
100
+ login_timeout: int | None = None,
101
+ network_timeout: int | None = None,
102
+ socket_timeout: int | None = None,
103
+ ):
104
+ return {
105
+ "data": {
106
+ "CLIENT_APP_ID": internal_application_name,
107
+ "CLIENT_APP_VERSION": internal_application_version,
108
+ "SVN_REVISION": VERSION[3],
109
+ "ACCOUNT_NAME": account,
110
+ "LOGIN_NAME": user,
111
+ "CLIENT_ENVIRONMENT": {
112
+ "APPLICATION": application,
113
+ "OS": OPERATING_SYSTEM,
114
+ "OS_VERSION": PLATFORM,
115
+ "PYTHON_VERSION": PYTHON_VERSION,
116
+ "PYTHON_RUNTIME": IMPLEMENTATION,
117
+ "PYTHON_COMPILER": COMPILER,
118
+ "OCSP_MODE": ocsp_mode.name,
119
+ "TRACING": logger.getEffectiveLevel(),
120
+ "LOGIN_TIMEOUT": login_timeout,
121
+ "NETWORK_TIMEOUT": network_timeout,
122
+ "SOCKET_TIMEOUT": socket_timeout,
123
+ },
124
+ },
125
+ }
126
+
127
+ def authenticate(
128
+ self,
129
+ auth_instance: AuthByPlugin,
130
+ account: str,
131
+ user: str,
132
+ database: str | None = None,
133
+ schema: str | None = None,
134
+ warehouse: str | None = None,
135
+ role: str | None = None,
136
+ passcode: str | None = None,
137
+ passcode_in_password: bool = False,
138
+ mfa_callback: Callable[[], None] | None = None,
139
+ password_callback: Callable[[], str] | None = None,
140
+ session_parameters: dict[Any, Any] | None = None,
141
+ # max time waiting for MFA response, currently unused
142
+ timeout: int | None = None,
143
+ ) -> dict[str, str | int | bool]:
144
+ logger.debug("authenticate")
145
+
146
+ # For no-auth connection, authentication is no-op, and we can return early here.
147
+ if isinstance(auth_instance, AuthNoAuth):
148
+ return {}
149
+
150
+ if timeout is None:
151
+ timeout = auth_instance.timeout
152
+
153
+ if session_parameters is None:
154
+ session_parameters = {}
155
+
156
+ request_id = str(uuid.uuid4())
157
+ headers = {
158
+ HTTP_HEADER_CONTENT_TYPE: CONTENT_TYPE_APPLICATION_JSON,
159
+ HTTP_HEADER_ACCEPT: ACCEPT_TYPE_APPLICATION_SNOWFLAKE,
160
+ HTTP_HEADER_USER_AGENT: PYTHON_CONNECTOR_USER_AGENT,
161
+ }
162
+ if HTTP_HEADER_SERVICE_NAME in session_parameters:
163
+ headers[HTTP_HEADER_SERVICE_NAME] = session_parameters[
164
+ HTTP_HEADER_SERVICE_NAME
165
+ ]
166
+ url = "/session/v1/login-request"
167
+
168
+ body_template = Auth.base_auth_data(
169
+ user,
170
+ account,
171
+ self._rest._connection.application,
172
+ self._rest._connection._internal_application_name,
173
+ self._rest._connection._internal_application_version,
174
+ self._rest._connection._ocsp_mode(),
175
+ self._rest._connection.login_timeout,
176
+ self._rest._connection._network_timeout,
177
+ self._rest._connection._socket_timeout,
178
+ )
179
+
180
+ body = copy.deepcopy(body_template)
181
+ # updating request body
182
+ auth_instance.update_body(body)
183
+
184
+ logger.debug(
185
+ "account=%s, user=%s, database=%s, schema=%s, "
186
+ "warehouse=%s, role=%s, request_id=%s",
187
+ account,
188
+ user,
189
+ database,
190
+ schema,
191
+ warehouse,
192
+ role,
193
+ request_id,
194
+ )
195
+ url_parameters = {"request_id": request_id}
196
+ if database is not None:
197
+ url_parameters["databaseName"] = database
198
+ if schema is not None:
199
+ url_parameters["schemaName"] = schema
200
+ if warehouse is not None:
201
+ url_parameters["warehouse"] = warehouse
202
+ if role is not None:
203
+ url_parameters["roleName"] = role
204
+
205
+ url = url + "?" + urlencode(url_parameters)
206
+
207
+ # first auth request
208
+ if passcode_in_password:
209
+ body["data"]["EXT_AUTHN_DUO_METHOD"] = "passcode"
210
+ elif passcode:
211
+ body["data"]["EXT_AUTHN_DUO_METHOD"] = "passcode"
212
+ body["data"]["PASSCODE"] = passcode
213
+
214
+ if session_parameters:
215
+ body["data"]["SESSION_PARAMETERS"] = session_parameters
216
+
217
+ logger.debug(
218
+ "body['data']: %s",
219
+ {
220
+ k: v if k in AUTHENTICATION_REQUEST_KEY_WHITELIST else "******"
221
+ for (k, v) in body["data"].items()
222
+ },
223
+ )
224
+
225
+ try:
226
+ ret = self._rest._post_request(
227
+ url,
228
+ headers,
229
+ json.dumps(body),
230
+ socket_timeout=auth_instance._socket_timeout,
231
+ )
232
+ except ForbiddenError as err:
233
+ # HTTP 403
234
+ raise err.__class__(
235
+ msg=(
236
+ "Failed to connect to DB. "
237
+ "Verify the account name is correct: {host}:{port}. "
238
+ "{message}"
239
+ ).format(
240
+ host=self._rest._host, port=self._rest._port, message=str(err)
241
+ ),
242
+ errno=ER_FAILED_TO_CONNECT_TO_DB,
243
+ sqlstate=SQLSTATE_CONNECTION_WAS_NOT_ESTABLISHED,
244
+ )
245
+ except (ServiceUnavailableError, BadGatewayError) as err:
246
+ # HTTP 502/504
247
+ raise err.__class__(
248
+ msg=(
249
+ "Failed to connect to DB. "
250
+ "Service is unavailable: {host}:{port}. "
251
+ "{message}"
252
+ ).format(
253
+ host=self._rest._host, port=self._rest._port, message=str(err)
254
+ ),
255
+ errno=ER_FAILED_TO_CONNECT_TO_DB,
256
+ sqlstate=SQLSTATE_CONNECTION_WAS_NOT_ESTABLISHED,
257
+ )
258
+
259
+ # waiting for MFA authentication
260
+ if ret["data"] and ret["data"].get("nextAction") in (
261
+ "EXT_AUTHN_DUO_ALL",
262
+ "EXT_AUTHN_DUO_PUSH_N_PASSCODE",
263
+ ):
264
+ body["inFlightCtx"] = ret["data"].get("inFlightCtx")
265
+ body["data"]["EXT_AUTHN_DUO_METHOD"] = "push"
266
+ self.ret = {"message": "Timeout", "data": {}}
267
+
268
+ def post_request_wrapper(self, url, headers, body) -> None:
269
+ # get the MFA response
270
+ self.ret = self._rest._post_request(
271
+ url,
272
+ headers,
273
+ body,
274
+ socket_timeout=auth_instance._socket_timeout,
275
+ )
276
+
277
+ # send new request to wait until MFA is approved
278
+ t = Thread(
279
+ target=post_request_wrapper, args=[self, url, headers, json.dumps(body)]
280
+ )
281
+ t.daemon = True
282
+ t.start()
283
+ if callable(mfa_callback):
284
+ c = mfa_callback()
285
+ while not self.ret or self.ret.get("message") == "Timeout":
286
+ next(c)
287
+ else:
288
+ # _post_request should already terminate on timeout, so this is just a safeguard
289
+ t.join(timeout=timeout)
290
+
291
+ ret = self.ret
292
+ if (
293
+ ret
294
+ and ret["data"]
295
+ and ret["data"].get("nextAction") == "EXT_AUTHN_SUCCESS"
296
+ ):
297
+ body = copy.deepcopy(body_template)
298
+ body["inFlightCtx"] = ret["data"].get("inFlightCtx")
299
+ # final request to get tokens
300
+ ret = self._rest._post_request(
301
+ url,
302
+ headers,
303
+ json.dumps(body),
304
+ socket_timeout=auth_instance._socket_timeout,
305
+ )
306
+ elif not ret or not ret["data"] or not ret["data"].get("token"):
307
+ # not token is returned.
308
+ Error.errorhandler_wrapper(
309
+ self._rest._connection,
310
+ None,
311
+ DatabaseError,
312
+ {
313
+ "msg": (
314
+ "Failed to connect to DB. MFA "
315
+ "authentication failed: {"
316
+ "host}:{port}. {message}"
317
+ ).format(
318
+ host=self._rest._host,
319
+ port=self._rest._port,
320
+ message=ret["message"],
321
+ ),
322
+ "errno": ER_FAILED_TO_CONNECT_TO_DB,
323
+ "sqlstate": SQLSTATE_CONNECTION_WAS_NOT_ESTABLISHED,
324
+ },
325
+ )
326
+ return session_parameters # required for unit test
327
+
328
+ elif ret["data"] and ret["data"].get("nextAction") == "PWD_CHANGE":
329
+ if callable(password_callback):
330
+ body = copy.deepcopy(body_template)
331
+ body["inFlightCtx"] = ret["data"].get("inFlightCtx")
332
+ body["data"]["LOGIN_NAME"] = user
333
+ body["data"]["PASSWORD"] = (
334
+ auth_instance.password
335
+ if hasattr(auth_instance, "password")
336
+ else None
337
+ )
338
+ body["data"]["CHOSEN_NEW_PASSWORD"] = password_callback()
339
+ # New Password input
340
+ ret = self._rest._post_request(
341
+ url,
342
+ headers,
343
+ json.dumps(body),
344
+ socket_timeout=auth_instance._socket_timeout,
345
+ )
346
+
347
+ logger.debug("completed authentication")
348
+ if not ret["success"]:
349
+ errno = ret.get("code", ER_FAILED_TO_CONNECT_TO_DB)
350
+ if errno == ID_TOKEN_INVALID_LOGIN_REQUEST_GS_CODE:
351
+ # clear stored id_token if failed to connect because of id_token
352
+ # raise an exception for reauth without id_token
353
+ self._rest.id_token = None
354
+ self._delete_temporary_credential(
355
+ self._rest._host, user, TokenType.ID_TOKEN
356
+ )
357
+ raise ReauthenticationRequest(
358
+ ProgrammingError(
359
+ msg=ret["message"],
360
+ errno=int(errno),
361
+ sqlstate=SQLSTATE_CONNECTION_WAS_NOT_ESTABLISHED,
362
+ )
363
+ )
364
+ elif errno == OAUTH_ACCESS_TOKEN_EXPIRED_GS_CODE:
365
+ raise ReauthenticationRequest(
366
+ ProgrammingError(
367
+ msg=ret["message"],
368
+ errno=int(errno),
369
+ sqlstate=SQLSTATE_CONNECTION_WAS_NOT_ESTABLISHED,
370
+ )
371
+ )
372
+
373
+ from . import AuthByKeyPair
374
+
375
+ if isinstance(auth_instance, AuthByKeyPair):
376
+ logger.debug(
377
+ "JWT Token authentication failed. "
378
+ "Token expires at: %s. "
379
+ "Current Time: %s",
380
+ str(auth_instance._jwt_token_exp),
381
+ str(datetime.now(timezone.utc).replace(tzinfo=None)),
382
+ )
383
+ from . import AuthByUsrPwdMfa
384
+
385
+ if isinstance(auth_instance, AuthByUsrPwdMfa):
386
+ self._delete_temporary_credential(
387
+ self._rest._host, user, TokenType.MFA_TOKEN
388
+ )
389
+ Error.errorhandler_wrapper(
390
+ self._rest._connection,
391
+ None,
392
+ DatabaseError,
393
+ {
394
+ "msg": (
395
+ "Failed to connect to DB: {host}:{port}. " "{message}"
396
+ ).format(
397
+ host=self._rest._host,
398
+ port=self._rest._port,
399
+ message=ret["message"],
400
+ ),
401
+ "errno": ER_FAILED_TO_CONNECT_TO_DB,
402
+ "sqlstate": SQLSTATE_CONNECTION_WAS_NOT_ESTABLISHED,
403
+ },
404
+ )
405
+ else:
406
+ logger.debug(
407
+ "token = %s",
408
+ (
409
+ "******"
410
+ if ret["data"] and ret["data"].get("token") is not None
411
+ else "NULL"
412
+ ),
413
+ )
414
+ logger.debug(
415
+ "master_token = %s",
416
+ (
417
+ "******"
418
+ if ret["data"] and ret["data"].get("masterToken") is not None
419
+ else "NULL"
420
+ ),
421
+ )
422
+ logger.debug(
423
+ "id_token = %s",
424
+ (
425
+ "******"
426
+ if ret["data"] and ret["data"].get("idToken") is not None
427
+ else "NULL"
428
+ ),
429
+ )
430
+ logger.debug(
431
+ "mfa_token = %s",
432
+ (
433
+ "******"
434
+ if ret["data"] and ret["data"].get("mfaToken") is not None
435
+ else "NULL"
436
+ ),
437
+ )
438
+ if not ret["data"]:
439
+ Error.errorhandler_wrapper(
440
+ None,
441
+ None,
442
+ Error,
443
+ {
444
+ "msg": "There is no data in the returning response, please retry the operation."
445
+ },
446
+ )
447
+ self._rest.update_tokens(
448
+ ret["data"].get("token"),
449
+ ret["data"].get("masterToken"),
450
+ master_validity_in_seconds=ret["data"].get("masterValidityInSeconds"),
451
+ id_token=ret["data"].get("idToken"),
452
+ mfa_token=ret["data"].get("mfaToken"),
453
+ )
454
+ self.write_temporary_credentials(
455
+ self._rest._host, user, session_parameters, ret
456
+ )
457
+ if ret["data"] and "sessionId" in ret["data"]:
458
+ self._rest._connection._session_id = ret["data"].get("sessionId")
459
+ if ret["data"] and "sessionInfo" in ret["data"]:
460
+ session_info = ret["data"].get("sessionInfo")
461
+ self._rest._connection._database = session_info.get("databaseName")
462
+ self._rest._connection._schema = session_info.get("schemaName")
463
+ self._rest._connection._warehouse = session_info.get("warehouseName")
464
+ self._rest._connection._role = session_info.get("roleName")
465
+ if ret["data"] and "parameters" in ret["data"]:
466
+ session_parameters.update(
467
+ {p["name"]: p["value"] for p in ret["data"].get("parameters")}
468
+ )
469
+ self._rest._connection._update_parameters(session_parameters)
470
+ return session_parameters
471
+
472
+ def _read_temporary_credential(
473
+ self,
474
+ host: str,
475
+ user: str,
476
+ cred_type: TokenType,
477
+ ) -> str | None:
478
+ return self.get_token_cache().retrieve(TokenKey(host, user, cred_type))
479
+
480
+ def read_temporary_credentials(
481
+ self,
482
+ host: str,
483
+ user: str,
484
+ session_parameters: dict[str, Any],
485
+ ) -> None:
486
+ if session_parameters.get(PARAMETER_CLIENT_STORE_TEMPORARY_CREDENTIAL, False):
487
+ self._rest.id_token = self._read_temporary_credential(
488
+ host,
489
+ user,
490
+ TokenType.ID_TOKEN,
491
+ )
492
+
493
+ if session_parameters.get(PARAMETER_CLIENT_REQUEST_MFA_TOKEN, False):
494
+ self._rest.mfa_token = self._read_temporary_credential(
495
+ host,
496
+ user,
497
+ TokenType.MFA_TOKEN,
498
+ )
499
+
500
+ def _write_temporary_credential(
501
+ self,
502
+ host: str,
503
+ user: str,
504
+ cred_type: TokenType,
505
+ cred: str | None,
506
+ ) -> None:
507
+ if not cred:
508
+ logger.debug(
509
+ "no credential is given when try to store temporary credential"
510
+ )
511
+ return
512
+ self.get_token_cache().store(TokenKey(host, user, cred_type), cred)
513
+
514
+ def write_temporary_credentials(
515
+ self,
516
+ host: str,
517
+ user: str,
518
+ session_parameters: dict[str, Any],
519
+ response: dict[str, Any],
520
+ ) -> None:
521
+ if (
522
+ self._rest._connection.auth_class.consent_cache_id_token
523
+ and session_parameters.get(
524
+ PARAMETER_CLIENT_STORE_TEMPORARY_CREDENTIAL, False
525
+ )
526
+ ):
527
+ self._write_temporary_credential(
528
+ host, user, TokenType.ID_TOKEN, response["data"].get("idToken")
529
+ )
530
+
531
+ if session_parameters.get(PARAMETER_CLIENT_REQUEST_MFA_TOKEN, False):
532
+ self._write_temporary_credential(
533
+ host, user, TokenType.MFA_TOKEN, response["data"].get("mfaToken")
534
+ )
535
+
536
+ def _delete_temporary_credential(
537
+ self, host: str, user: str, cred_type: TokenType
538
+ ) -> None:
539
+ self.get_token_cache().remove(TokenKey(host, user, cred_type))
540
+
541
+ def get_token_cache(self) -> TokenCache:
542
+ if self._token_cache is None:
543
+ self._token_cache = TokenCache.make()
544
+ return self._token_cache
545
+
546
+
547
+ def get_token_from_private_key(
548
+ user: str, account: str, privatekey_path: str, key_password: str | None
549
+ ) -> str:
550
+ encoded_password = key_password.encode() if key_password is not None else None
551
+ with open(privatekey_path, "rb") as key:
552
+ p_key = load_pem_private_key(
553
+ key.read(), password=encoded_password, backend=default_backend()
554
+ )
555
+
556
+ private_key = p_key.private_bytes(
557
+ encoding=Encoding.DER,
558
+ format=PrivateFormat.PKCS8,
559
+ encryption_algorithm=NoEncryption(),
560
+ )
561
+ from . import AuthByKeyPair
562
+
563
+ auth_instance = AuthByKeyPair(
564
+ private_key,
565
+ DAY_IN_SECONDS,
566
+ ) # token valid for 24 hours
567
+ return auth_instance.prepare(account=account, user=user)
568
+
569
+
570
+ def get_public_key_fingerprint(private_key_file: str, password: str) -> str:
571
+ """Helper function to generate the public key fingerprint from the private key file"""
572
+ with open(private_key_file, "rb") as key:
573
+ p_key = load_pem_private_key(
574
+ key.read(), password=password.encode(), backend=default_backend()
575
+ )
576
+ private_key = p_key.private_bytes(
577
+ encoding=Encoding.DER,
578
+ format=PrivateFormat.PKCS8,
579
+ encryption_algorithm=NoEncryption(),
580
+ )
581
+ private_key = load_der_private_key(
582
+ data=private_key, password=None, backend=default_backend()
583
+ )
584
+ from . import AuthByKeyPair
585
+
586
+ return AuthByKeyPair.calculate_public_key_fingerprint(private_key)