Skip to content

Commit a821d71

Browse files
authored
feat: ECP Provider drop cryptography requirement (#1524)
The ECP provider can work with the Python std lib SSL library. This simplifies packaging, as cryptography can be omitted. This patch makes the code use the standard SSL library if a provider implementation is detected.
1 parent 8cfc91d commit a821d71

File tree

5 files changed

+58
-12
lines changed

5 files changed

+58
-12
lines changed

google/auth/transport/_custom_tls_signer.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,17 @@
4646

4747

4848
# Cast SSL_CTX* to void*
49-
def _cast_ssl_ctx_to_void_p(ssl_ctx):
49+
def _cast_ssl_ctx_to_void_p_pyopenssl(ssl_ctx):
5050
return ctypes.cast(int(cffi.FFI().cast("intptr_t", ssl_ctx)), ctypes.c_void_p)
5151

5252

53+
# Cast SSL_CTX* to void*
54+
def _cast_ssl_ctx_to_void_p_stdlib(context):
55+
return ctypes.c_void_p.from_address(
56+
id(context) + ctypes.sizeof(ctypes.c_void_p) * 2
57+
)
58+
59+
5360
# Load offload library and set up the function types.
5461
def load_offload_lib(offload_lib_path):
5562
_LOGGER.debug("loading offload library from %s", offload_lib_path)
@@ -249,10 +256,15 @@ def set_up_custom_key(self):
249256
self._signer_lib, self._enterprise_cert_file_path
250257
)
251258

252-
def attach_to_ssl_context(self, ctx):
259+
def should_use_provider(self):
253260
if self._provider_lib:
261+
return True
262+
return False
263+
264+
def attach_to_ssl_context(self, ctx):
265+
if self.should_use_provider():
254266
if not self._provider_lib.ECP_attach_to_ctx(
255-
_cast_ssl_ctx_to_void_p(ctx._ctx._context),
267+
_cast_ssl_ctx_to_void_p_stdlib(ctx),
256268
self._enterprise_cert_file_path.encode("ascii"),
257269
):
258270
raise exceptions.MutualTLSChannelError(
@@ -262,7 +274,7 @@ def attach_to_ssl_context(self, ctx):
262274
if not self._offload_lib.ConfigureSslContext(
263275
self._sign_callback,
264276
ctypes.c_char_p(self._cert),
265-
_cast_ssl_ctx_to_void_p(ctx._ctx._context),
277+
_cast_ssl_ctx_to_void_p_pyopenssl(ctx._ctx._context),
266278
):
267279
raise exceptions.MutualTLSChannelError(
268280
"failed to configure ECP Offload SSL context"

google/auth/transport/requests.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -262,19 +262,16 @@ class _MutualTlsOffloadAdapter(requests.adapters.HTTPAdapter):
262262

263263
def __init__(self, enterprise_cert_file_path):
264264
import certifi
265-
import urllib3.contrib.pyopenssl
266-
267265
from google.auth.transport import _custom_tls_signer
268266

269-
# Call inject_into_urllib3 to activate certificate checking. See the
270-
# following links for more info:
271-
# (1) doc: https://github.com/urllib3/urllib3/blob/cb9ebf8aac5d75f64c8551820d760b72b619beff/src/urllib3/contrib/pyopenssl.py#L31-L32
272-
# (2) mTLS example: https://github.com/urllib3/urllib3/issues/474#issuecomment-253168415
273-
urllib3.contrib.pyopenssl.inject_into_urllib3()
274-
275267
self.signer = _custom_tls_signer.CustomTlsSigner(enterprise_cert_file_path)
276268
self.signer.load_libraries()
277269

270+
if not self.signer.should_use_provider():
271+
import urllib3.contrib.pyopenssl
272+
273+
urllib3.contrib.pyopenssl.inject_into_urllib3()
274+
278275
poolmanager = create_urllib3_context()
279276
poolmanager.load_verify_locations(cafile=certifi.where())
280277
self.signer.attach_to_ssl_context(poolmanager)

system_tests/secrets.tar.enc

0 Bytes
Binary file not shown.

tests/transport/test__custom_tls_signer.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ def test_custom_tls_signer():
195195
get_cert.assert_called_once()
196196
get_sign_callback.assert_called_once()
197197
offload_lib.ConfigureSslContext.assert_called_once()
198+
assert not signer_object.should_use_provider()
198199
assert signer_object._enterprise_cert_file_path == ENTERPRISE_CERT_FILE
199200
assert signer_object._offload_lib == offload_lib
200201
assert signer_object._signer_lib == signer_lib
@@ -216,6 +217,7 @@ def test_custom_tls_signer_provider():
216217
signer_object.load_libraries()
217218
signer_object.attach_to_ssl_context(mock.MagicMock())
218219

220+
assert signer_object.should_use_provider()
219221
assert signer_object._enterprise_cert_file_path == ENTERPRISE_CERT_FILE_PROVIDER
220222
assert signer_object._provider_lib == provider_lib
221223
load_provider_lib.assert_called_with("/path/to/provider/lib")

tests/transport/test_requests.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,3 +568,38 @@ def test_success(
568568

569569
adapter.proxy_manager_for()
570570
mock_proxy_manager_for.assert_called_with(ssl_context=adapter._ctx_proxymanager)
571+
572+
@mock.patch.object(requests.adapters.HTTPAdapter, "init_poolmanager")
573+
@mock.patch.object(requests.adapters.HTTPAdapter, "proxy_manager_for")
574+
@mock.patch.object(
575+
google.auth.transport._custom_tls_signer.CustomTlsSigner, "should_use_provider"
576+
)
577+
@mock.patch.object(
578+
google.auth.transport._custom_tls_signer.CustomTlsSigner, "load_libraries"
579+
)
580+
@mock.patch.object(
581+
google.auth.transport._custom_tls_signer.CustomTlsSigner,
582+
"attach_to_ssl_context",
583+
)
584+
def test_success_should_use_provider(
585+
self,
586+
mock_attach_to_ssl_context,
587+
mock_load_libraries,
588+
mock_should_use_provider,
589+
mock_proxy_manager_for,
590+
mock_init_poolmanager,
591+
):
592+
enterprise_cert_file_path = "/path/to/enterprise/cert/json"
593+
adapter = google.auth.transport.requests._MutualTlsOffloadAdapter(
594+
enterprise_cert_file_path
595+
)
596+
597+
mock_should_use_provider.side_effect = True
598+
mock_load_libraries.assert_called_once()
599+
assert mock_attach_to_ssl_context.call_count == 2
600+
601+
adapter.init_poolmanager()
602+
mock_init_poolmanager.assert_called_with(ssl_context=adapter._ctx_poolmanager)
603+
604+
adapter.proxy_manager_for()
605+
mock_proxy_manager_for.assert_called_with(ssl_context=adapter._ctx_proxymanager)

0 commit comments

Comments
 (0)