credentials.pyx.pxi 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. # Copyright 2015 gRPC authors.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. def _spawn_callback_in_thread(cb_func, args):
  15. t = ForkManagedThread(target=cb_func, args=args)
  16. t.setDaemon(True)
  17. t.start()
  18. async_callback_func = _spawn_callback_in_thread
  19. def set_async_callback_func(callback_func):
  20. global async_callback_func
  21. async_callback_func = callback_func
  22. def _spawn_callback_async(callback, args):
  23. async_callback_func(callback, args)
  24. cdef class CallCredentials:
  25. cdef grpc_call_credentials *c(self) except *:
  26. raise NotImplementedError()
  27. cdef int _get_metadata(void *state,
  28. grpc_auth_metadata_context context,
  29. grpc_credentials_plugin_metadata_cb cb,
  30. void *user_data,
  31. grpc_metadata creds_md[GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX],
  32. size_t *num_creds_md,
  33. grpc_status_code *status,
  34. const char **error_details) except * with gil:
  35. cdef size_t metadata_count
  36. cdef grpc_metadata *c_metadata
  37. def callback(metadata, grpc_status_code status, bytes error_details):
  38. cdef char* c_error_details = NULL
  39. if error_details is not None:
  40. c_error_details = <char*> error_details
  41. if status == StatusCode.ok:
  42. _store_c_metadata(metadata, &c_metadata, &metadata_count)
  43. with nogil:
  44. cb(user_data, c_metadata, metadata_count, status, NULL)
  45. _release_c_metadata(c_metadata, metadata_count)
  46. else:
  47. with nogil:
  48. cb(user_data, NULL, 0, status, c_error_details)
  49. args = context.service_url, context.method_name, callback,
  50. plugin = <object>state
  51. if plugin._stored_ctx is not None:
  52. plugin._stored_ctx.copy().run(_spawn_callback_async, plugin, args)
  53. else:
  54. _spawn_callback_async(<object>state, args)
  55. return 0 # Asynchronous return
  56. cdef void _destroy(void *state) except * with gil:
  57. cpython.Py_DECREF(<object>state)
  58. grpc_shutdown()
  59. cdef class MetadataPluginCallCredentials(CallCredentials):
  60. def __cinit__(self, metadata_plugin, name):
  61. self._metadata_plugin = metadata_plugin
  62. self._name = name
  63. cdef grpc_call_credentials *c(self) except *:
  64. cdef grpc_metadata_credentials_plugin c_metadata_plugin
  65. c_metadata_plugin.get_metadata = _get_metadata
  66. c_metadata_plugin.destroy = _destroy
  67. c_metadata_plugin.state = <void *>self._metadata_plugin
  68. c_metadata_plugin.type = self._name
  69. cpython.Py_INCREF(self._metadata_plugin)
  70. fork_handlers_and_grpc_init()
  71. # TODO(yihuazhang): Expose min_security_level via the Python API so that
  72. # applications can decide what minimum security level their plugins require.
  73. return grpc_metadata_credentials_create_from_plugin(c_metadata_plugin, GRPC_PRIVACY_AND_INTEGRITY, NULL)
  74. cdef grpc_call_credentials *_composition(call_credentialses):
  75. call_credentials_iterator = iter(call_credentialses)
  76. cdef CallCredentials composition = next(call_credentials_iterator)
  77. cdef grpc_call_credentials *c_composition = composition.c()
  78. cdef CallCredentials additional_call_credentials
  79. cdef grpc_call_credentials *c_additional_call_credentials
  80. cdef grpc_call_credentials *c_next_composition
  81. for additional_call_credentials in call_credentials_iterator:
  82. c_additional_call_credentials = additional_call_credentials.c()
  83. c_next_composition = grpc_composite_call_credentials_create(
  84. c_composition, c_additional_call_credentials, NULL)
  85. grpc_call_credentials_release(c_composition)
  86. grpc_call_credentials_release(c_additional_call_credentials)
  87. c_composition = c_next_composition
  88. return c_composition
  89. cdef class CompositeCallCredentials(CallCredentials):
  90. def __cinit__(self, call_credentialses):
  91. self._call_credentialses = call_credentialses
  92. cdef grpc_call_credentials *c(self) except *:
  93. return _composition(self._call_credentialses)
  94. cdef class ChannelCredentials:
  95. cdef grpc_channel_credentials *c(self) except *:
  96. raise NotImplementedError()
  97. cdef class SSLSessionCacheLRU:
  98. def __cinit__(self, capacity):
  99. fork_handlers_and_grpc_init()
  100. self._cache = grpc_ssl_session_cache_create_lru(capacity)
  101. def __int__(self):
  102. return <uintptr_t>self._cache
  103. def __dealloc__(self):
  104. if self._cache != NULL:
  105. grpc_ssl_session_cache_destroy(self._cache)
  106. grpc_shutdown()
  107. cdef class SSLChannelCredentials(ChannelCredentials):
  108. def __cinit__(self, pem_root_certificates, private_key, certificate_chain):
  109. if pem_root_certificates is not None and not isinstance(pem_root_certificates, bytes):
  110. raise TypeError('expected certificate to be bytes, got %s' % (type(pem_root_certificates)))
  111. self._pem_root_certificates = pem_root_certificates
  112. self._private_key = private_key
  113. self._certificate_chain = certificate_chain
  114. cdef grpc_channel_credentials *c(self) except *:
  115. cdef const char *c_pem_root_certificates
  116. cdef grpc_ssl_pem_key_cert_pair c_pem_key_certificate_pair
  117. if self._pem_root_certificates is None:
  118. c_pem_root_certificates = NULL
  119. else:
  120. c_pem_root_certificates = self._pem_root_certificates
  121. if self._private_key is None and self._certificate_chain is None:
  122. return grpc_ssl_credentials_create(
  123. c_pem_root_certificates, NULL, NULL, NULL)
  124. else:
  125. if self._private_key:
  126. c_pem_key_certificate_pair.private_key = self._private_key
  127. else:
  128. c_pem_key_certificate_pair.private_key = NULL
  129. if self._certificate_chain:
  130. c_pem_key_certificate_pair.certificate_chain = self._certificate_chain
  131. else:
  132. c_pem_key_certificate_pair.certificate_chain = NULL
  133. return grpc_ssl_credentials_create(
  134. c_pem_root_certificates, &c_pem_key_certificate_pair, NULL, NULL)
  135. cdef class CompositeChannelCredentials(ChannelCredentials):
  136. def __cinit__(self, call_credentialses, channel_credentials):
  137. self._call_credentialses = call_credentialses
  138. self._channel_credentials = channel_credentials
  139. cdef grpc_channel_credentials *c(self) except *:
  140. cdef grpc_channel_credentials *c_channel_credentials
  141. c_channel_credentials = self._channel_credentials.c()
  142. cdef grpc_call_credentials *c_call_credentials_composition = _composition(
  143. self._call_credentialses)
  144. cdef grpc_channel_credentials *composition
  145. c_composition = grpc_composite_channel_credentials_create(
  146. c_channel_credentials, c_call_credentials_composition, NULL)
  147. grpc_channel_credentials_release(c_channel_credentials)
  148. grpc_call_credentials_release(c_call_credentials_composition)
  149. return c_composition
  150. cdef class XDSChannelCredentials(ChannelCredentials):
  151. def __cinit__(self, fallback_credentials):
  152. self._fallback_credentials = fallback_credentials
  153. cdef grpc_channel_credentials *c(self) except *:
  154. cdef grpc_channel_credentials *c_fallback_creds = self._fallback_credentials.c()
  155. cdef grpc_channel_credentials *xds_creds = grpc_xds_credentials_create(c_fallback_creds)
  156. grpc_channel_credentials_release(c_fallback_creds)
  157. return xds_creds
  158. cdef class ServerCertificateConfig:
  159. def __cinit__(self):
  160. fork_handlers_and_grpc_init()
  161. self.c_cert_config = NULL
  162. self.c_pem_root_certs = NULL
  163. self.c_ssl_pem_key_cert_pairs = NULL
  164. self.references = []
  165. def __dealloc__(self):
  166. grpc_ssl_server_certificate_config_destroy(self.c_cert_config)
  167. gpr_free(self.c_ssl_pem_key_cert_pairs)
  168. grpc_shutdown()
  169. cdef class ServerCredentials:
  170. def __cinit__(self):
  171. fork_handlers_and_grpc_init()
  172. self.c_credentials = NULL
  173. self.references = []
  174. self.initial_cert_config = None
  175. self.cert_config_fetcher = None
  176. self.initial_cert_config_fetched = False
  177. def __dealloc__(self):
  178. if self.c_credentials != NULL:
  179. grpc_server_credentials_release(self.c_credentials)
  180. grpc_shutdown()
  181. cdef const char* _get_c_pem_root_certs(pem_root_certs):
  182. if pem_root_certs is None:
  183. return NULL
  184. else:
  185. return pem_root_certs
  186. cdef grpc_ssl_pem_key_cert_pair* _create_c_ssl_pem_key_cert_pairs(pem_key_cert_pairs):
  187. # return a malloc'ed grpc_ssl_pem_key_cert_pair from a _list_ of SslPemKeyCertPair
  188. for pair in pem_key_cert_pairs:
  189. if not isinstance(pair, SslPemKeyCertPair):
  190. raise TypeError("expected pem_key_cert_pairs to be sequence of "
  191. "SslPemKeyCertPair")
  192. cdef size_t c_ssl_pem_key_cert_pairs_count = len(pem_key_cert_pairs)
  193. cdef grpc_ssl_pem_key_cert_pair* c_ssl_pem_key_cert_pairs = NULL
  194. with nogil:
  195. c_ssl_pem_key_cert_pairs = (
  196. <grpc_ssl_pem_key_cert_pair *>gpr_malloc(
  197. sizeof(grpc_ssl_pem_key_cert_pair) * c_ssl_pem_key_cert_pairs_count))
  198. for i in range(c_ssl_pem_key_cert_pairs_count):
  199. c_ssl_pem_key_cert_pairs[i] = (
  200. (<SslPemKeyCertPair>pem_key_cert_pairs[i]).c_pair)
  201. return c_ssl_pem_key_cert_pairs
  202. def server_credentials_ssl(pem_root_certs, pem_key_cert_pairs,
  203. bint force_client_auth):
  204. pem_root_certs = str_to_bytes(pem_root_certs)
  205. pem_key_cert_pairs = list(pem_key_cert_pairs)
  206. cdef ServerCredentials credentials = ServerCredentials()
  207. credentials.references.append(pem_root_certs)
  208. credentials.references.append(pem_key_cert_pairs)
  209. cdef const char * c_pem_root_certs = _get_c_pem_root_certs(pem_root_certs)
  210. credentials.c_ssl_pem_key_cert_pairs_count = len(pem_key_cert_pairs)
  211. credentials.c_ssl_pem_key_cert_pairs = _create_c_ssl_pem_key_cert_pairs(pem_key_cert_pairs)
  212. cdef grpc_ssl_server_certificate_config *c_cert_config = NULL
  213. c_cert_config = grpc_ssl_server_certificate_config_create(
  214. c_pem_root_certs, credentials.c_ssl_pem_key_cert_pairs,
  215. credentials.c_ssl_pem_key_cert_pairs_count)
  216. cdef grpc_ssl_server_credentials_options* c_options = NULL
  217. # C-core assumes ownership of c_cert_config
  218. c_options = grpc_ssl_server_credentials_create_options_using_config(
  219. GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY
  220. if force_client_auth else
  221. GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE,
  222. c_cert_config)
  223. # C-core assumes ownership of c_options
  224. credentials.c_credentials = grpc_ssl_server_credentials_create_with_options(c_options)
  225. return credentials
  226. def server_certificate_config_ssl(pem_root_certs, pem_key_cert_pairs):
  227. pem_root_certs = str_to_bytes(pem_root_certs)
  228. pem_key_cert_pairs = list(pem_key_cert_pairs)
  229. cdef ServerCertificateConfig cert_config = ServerCertificateConfig()
  230. cert_config.references.append(pem_root_certs)
  231. cert_config.references.append(pem_key_cert_pairs)
  232. cert_config.c_pem_root_certs = _get_c_pem_root_certs(pem_root_certs)
  233. cert_config.c_ssl_pem_key_cert_pairs_count = len(pem_key_cert_pairs)
  234. cert_config.c_ssl_pem_key_cert_pairs = _create_c_ssl_pem_key_cert_pairs(pem_key_cert_pairs)
  235. cert_config.c_cert_config = grpc_ssl_server_certificate_config_create(
  236. cert_config.c_pem_root_certs, cert_config.c_ssl_pem_key_cert_pairs,
  237. cert_config.c_ssl_pem_key_cert_pairs_count)
  238. return cert_config
  239. def server_credentials_ssl_dynamic_cert_config(initial_cert_config,
  240. cert_config_fetcher,
  241. bint force_client_auth):
  242. if not isinstance(initial_cert_config, grpc.ServerCertificateConfiguration):
  243. raise TypeError(
  244. 'initial_cert_config must be a grpc.ServerCertificateConfiguration')
  245. if not callable(cert_config_fetcher):
  246. raise TypeError('cert_config_fetcher must be callable')
  247. cdef ServerCredentials credentials = ServerCredentials()
  248. credentials.initial_cert_config = initial_cert_config
  249. credentials.cert_config_fetcher = cert_config_fetcher
  250. cdef grpc_ssl_server_credentials_options* c_options = NULL
  251. c_options = grpc_ssl_server_credentials_create_options_using_config_fetcher(
  252. GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY
  253. if force_client_auth else
  254. GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE,
  255. _server_cert_config_fetcher_wrapper,
  256. <void*>credentials)
  257. # C-core assumes ownership of c_options
  258. credentials.c_credentials = grpc_ssl_server_credentials_create_with_options(c_options)
  259. return credentials
  260. cdef grpc_ssl_certificate_config_reload_status _server_cert_config_fetcher_wrapper(
  261. void* user_data, grpc_ssl_server_certificate_config **config) with gil:
  262. # This is a credentials.ServerCertificateConfig
  263. cdef ServerCertificateConfig cert_config = None
  264. if not user_data:
  265. raise ValueError('internal error: user_data must be specified')
  266. credentials = <ServerCredentials>user_data
  267. if not credentials.initial_cert_config_fetched:
  268. # C-core is asking for the initial cert config
  269. credentials.initial_cert_config_fetched = True
  270. cert_config = credentials.initial_cert_config._certificate_configuration
  271. else:
  272. user_cb = credentials.cert_config_fetcher
  273. try:
  274. cert_config_wrapper = user_cb()
  275. except Exception:
  276. _LOGGER.exception('Error fetching certificate config')
  277. return GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_FAIL
  278. if cert_config_wrapper is None:
  279. return GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED
  280. elif not isinstance(
  281. cert_config_wrapper, grpc.ServerCertificateConfiguration):
  282. _LOGGER.error(
  283. 'Error fetching certificate configuration: certificate '
  284. 'configuration must be of type grpc.ServerCertificateConfiguration, '
  285. 'not %s' % type(cert_config_wrapper).__name__)
  286. return GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_FAIL
  287. else:
  288. cert_config = cert_config_wrapper._certificate_configuration
  289. config[0] = <grpc_ssl_server_certificate_config*>cert_config.c_cert_config
  290. # our caller will assume ownership of memory, so we have to recreate
  291. # a copy of c_cert_config here
  292. cert_config.c_cert_config = grpc_ssl_server_certificate_config_create(
  293. cert_config.c_pem_root_certs, cert_config.c_ssl_pem_key_cert_pairs,
  294. cert_config.c_ssl_pem_key_cert_pairs_count)
  295. return GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_NEW
  296. class LocalConnectionType:
  297. uds = UDS
  298. local_tcp = LOCAL_TCP
  299. cdef class LocalChannelCredentials(ChannelCredentials):
  300. def __cinit__(self, grpc_local_connect_type local_connect_type):
  301. self._local_connect_type = local_connect_type
  302. cdef grpc_channel_credentials *c(self) except *:
  303. cdef grpc_local_connect_type local_connect_type
  304. local_connect_type = self._local_connect_type
  305. return grpc_local_credentials_create(local_connect_type)
  306. def channel_credentials_local(grpc_local_connect_type local_connect_type):
  307. return LocalChannelCredentials(local_connect_type)
  308. cdef class InsecureChannelCredentials(ChannelCredentials):
  309. cdef grpc_channel_credentials *c(self) except *:
  310. return grpc_insecure_credentials_create()
  311. def channel_credentials_insecure():
  312. return InsecureChannelCredentials()
  313. def server_credentials_local(grpc_local_connect_type local_connect_type):
  314. cdef ServerCredentials credentials = ServerCredentials()
  315. credentials.c_credentials = grpc_local_server_credentials_create(local_connect_type)
  316. return credentials
  317. def xds_server_credentials(ServerCredentials fallback_credentials):
  318. cdef ServerCredentials credentials = ServerCredentials()
  319. credentials.c_credentials = grpc_xds_server_credentials_create(fallback_credentials.c_credentials)
  320. # NOTE: We do not need to call grpc_server_credentials_release on the
  321. # fallback credentials here because this will be done by the __dealloc__
  322. # method of its Cython wrapper.
  323. return credentials
  324. def insecure_server_credentials():
  325. cdef ServerCredentials credentials = ServerCredentials()
  326. credentials.c_credentials = grpc_insecure_server_credentials_create()
  327. return credentials
  328. cdef class ALTSChannelCredentials(ChannelCredentials):
  329. def __cinit__(self, list service_accounts):
  330. self.c_options = grpc_alts_credentials_client_options_create()
  331. cdef str account
  332. for account in service_accounts:
  333. grpc_alts_credentials_client_options_add_target_service_account(self.c_options, account)
  334. def __dealloc__(self):
  335. if self.c_options != NULL:
  336. grpc_alts_credentials_options_destroy(self.c_options)
  337. cdef grpc_channel_credentials *c(self) except *:
  338. return grpc_alts_credentials_create(self.c_options)
  339. def channel_credentials_alts(list service_accounts):
  340. return ALTSChannelCredentials(service_accounts)
  341. def server_credentials_alts():
  342. cdef ServerCredentials credentials = ServerCredentials()
  343. cdef grpc_alts_credentials_options* c_options = grpc_alts_credentials_server_options_create()
  344. credentials.c_credentials = grpc_alts_server_credentials_create(c_options)
  345. # Options can be destroyed as deep copy was performed.
  346. grpc_alts_credentials_options_destroy(c_options)
  347. return credentials
  348. cdef class ComputeEngineChannelCredentials(ChannelCredentials):
  349. cdef grpc_channel_credentials* _c_creds
  350. cdef grpc_call_credentials* _call_creds
  351. def __cinit__(self, CallCredentials call_creds):
  352. self._c_creds = NULL
  353. self._call_creds = call_creds.c()
  354. if self._call_creds == NULL:
  355. raise ValueError("Call credentials may not be NULL.")
  356. cdef grpc_channel_credentials *c(self) except *:
  357. self._c_creds = grpc_google_default_credentials_create(self._call_creds)
  358. return self._c_creds
  359. def channel_credentials_compute_engine(call_creds):
  360. return ComputeEngineChannelCredentials(call_creds)