Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 1.8k
refactor(auth): replace pyOpenSSL with standard ssl and cryptography#16976
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
baa87d97fd35594a4f58219b29ab648a9b0553b05c91d0fe833c837703ab6ce73e6e912d1bb5c1e37bd62b14fbc6e4d6b2c82de5c40499750f533163fff58d38fb4f8567b90af86e926fdebe2f342100a13c4c77f0e27cadc96d2bdc656ee9c6db6f52a0090d812a1ba77eac2dc0d45e0c003a1File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -120,8 +120,9 @@ def __init__( | ||
| self.ssl_context = ssl.create_default_context() | ||
| self.ssl_context.load_verify_locations(cafile=mds_mtls_config.ca_cert_path) | ||
| self.ssl_context.load_cert_chain( | ||
| certfile=mds_mtls_config.client_combined_cert_path | ||
| certfile=mds_mtls_config.client_combined_cert_path, password="" | ||
nbayati marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| ) | ||
| self._fallback_adapter = HTTPAdapter() | ||
| super(MdsMtlsAdapter, self).__init__(*args, **kwargs) | ||
| def init_poolmanager(self, *args, **kwargs): | ||
| @@ -146,6 +147,8 @@ def send(self, request, **kwargs): | ||
| ssl.SSLError, | ||
| requests.exceptions.SSLError, | ||
| requests.exceptions.HTTPError, | ||
| requests.exceptions.ConnectionError, | ||
| requests.exceptions.Timeout, | ||
| ) as e: | ||
| _LOGGER.warning( | ||
| "mTLS connection to Compute Engine Metadata server failed. " | ||
| @@ -157,6 +160,9 @@ def send(self, request, **kwargs): | ||
| http_fallback_url = urlunparse(parsed_original_url._replace(scheme="http")) | ||
| request.url = http_fallback_url | ||
| # Use a standard HTTPAdapter for the fallback | ||
| http_adapter = HTTPAdapter() | ||
| return http_adapter.send(request, **kwargs) | ||
| # Use the cached standard HTTPAdapter for the fallback | ||
| return self._fallback_adapter.send(request, **kwargs) | ||
| def close(self): | ||
| self._fallback_adapter.close() | ||
| super(MdsMtlsAdapter, self).close() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -152,28 +152,34 @@ def __init__(self, trust_chain_path, leaf_cert_callback): | ||
| @_helpers.copy_docstring(SubjectTokenSupplier) | ||
| def get_subject_token(self, context, request): | ||
| # Import OpennSSL inline because it is an extra import only required by customers | ||
| # using mTLS. | ||
| from OpenSSL import crypto | ||
| from cryptography import x509 | ||
| leaf_cert = crypto.load_certificate( | ||
| crypto.FILETYPE_PEM, self._leaf_cert_callback() | ||
| ) | ||
| try: | ||
nbayati marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| leaf_cert_data = self._leaf_cert_callback() | ||
| except Exception as e: | ||
| raise exceptions.RefreshError("Failed to retrieve leaf certificate.") from e | ||
| try: | ||
| if isinstance(leaf_cert_data, str): | ||
| leaf_cert_data = leaf_cert_data.encode("utf-8") | ||
| leaf_cert = x509.load_pem_x509_certificate(leaf_cert_data) | ||
| except Exception as e: | ||
| raise exceptions.RefreshError("Failed to parse leaf certificate.") from e | ||
| trust_chain = self._read_trust_chain() | ||
| cert_chain = [] | ||
| cert_chain.append(_X509Supplier._encode_cert(leaf_cert)) | ||
| cert_chain.append(_encode_cert(leaf_cert)) | ||
| if trust_chain is None or len(trust_chain) == 0: | ||
| return json.dumps(cert_chain) | ||
| # Append the first cert if it is not the leaf cert. | ||
| first_cert = _X509Supplier._encode_cert(trust_chain[0]) | ||
| first_cert = _encode_cert(trust_chain[0]) | ||
| if first_cert != cert_chain[0]: | ||
| cert_chain.append(first_cert) | ||
| for i in range(1, len(trust_chain)): | ||
| encoded = _X509Supplier._encode_cert(trust_chain[i]) | ||
| encoded = _encode_cert(trust_chain[i]) | ||
| # Check if the current cert is the leaf cert and raise an exception if it is. | ||
| if encoded == cert_chain[0]: | ||
| raise exceptions.RefreshError( | ||
| @@ -184,9 +190,7 @@ def get_subject_token(self, context, request): | ||
| return json.dumps(cert_chain) | ||
| def _read_trust_chain(self): | ||
| # Import OpennSSL inline because it is an extra import only required by customers | ||
| # using mTLS. | ||
| from OpenSSL import crypto | ||
| from cryptography import x509 | ||
| certificate_trust_chain = [] | ||
| # If no trust chain path was provided, return an empty list. | ||
| @@ -204,9 +208,7 @@ def _read_trust_chain(self): | ||
| cert_data = b"-----BEGIN CERTIFICATE-----" + cert_block | ||
| try: | ||
| # Load each certificate and add it to the trust chain. | ||
| cert = crypto.load_certificate( | ||
| crypto.FILETYPE_PEM, cert_data | ||
| ) | ||
| cert = x509.load_pem_x509_certificate(cert_data) | ||
nbayati marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| certificate_trust_chain.append(cert) | ||
| except Exception as e: | ||
| raise exceptions.RefreshError( | ||
| @@ -215,19 +217,22 @@ def _read_trust_chain(self): | ||
| ) | ||
| ) from e | ||
| return certificate_trust_chain | ||
| except FileNotFoundError: | ||
| except FileNotFoundError as e: | ||
| raise exceptions.RefreshError( | ||
| "Trust chain file '{}' was not found.".format(self._trust_chain_path) | ||
| ) | ||
| ) from e | ||
| except OSError as e: | ||
| raise exceptions.RefreshError( | ||
| "Error accessing trust chain file '{}'.".format(self._trust_chain_path) | ||
| ) from e | ||
| def _encode_cert(cert): | ||
| # Import OpennSSL inline because it is an extra import only required by customers | ||
| # using mTLS. | ||
| from OpenSSL import crypto | ||
| def _encode_cert(cert): | ||
| from cryptography.hazmat.primitives import serialization | ||
| return base64.b64encode( | ||
| crypto.dump_certificate(crypto.FILETYPE_ASN1, cert) | ||
| ).decode("utf-8") | ||
| return base64.b64encode(cert.public_bytes(serialization.Encoding.DER)).decode( | ||
| "utf-8" | ||
| ) | ||
| def _parse_token_data(token_content, format_type="text", subject_token_field_name=None): | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -21,9 +21,9 @@ | ||
| import json | ||
| import logging | ||
| import os | ||
| import ssl | ||
| import sys | ||
| import cffi # type: ignore | ||
| import sysconfig | ||
| from google.auth import exceptions | ||
| @@ -45,16 +45,23 @@ | ||
| ) | ||
| # Cast SSL_CTX* to void* | ||
| def _cast_ssl_ctx_to_void_p_pyopenssl(ssl_ctx): | ||
| return ctypes.cast(int(cffi.FFI().cast("intptr_t", ssl_ctx)), ctypes.c_void_p) | ||
| # Cast SSL_CTX* to void* | ||
| def _cast_ssl_ctx_to_void_p_stdlib(context): | ||
| return ctypes.c_void_p.from_address( | ||
| id(context) + ctypes.sizeof(ctypes.c_void_p) * 2 | ||
| ) | ||
| if not issubclass(type(context), ssl.SSLContext): | ||
| raise TypeError("context must be an instance of ssl.SSLContext, not a mock") | ||
| if ( | ||
| sys.implementation.name != "cpython" | ||
| or hasattr(sys, "getobjects") | ||
| or sysconfig.get_config_var("Py_DEBUG") | ||
| or sysconfig.get_config_var("Py_GIL_DISABLED") == 1 | ||
| ): | ||
| raise exceptions.MutualTLSChannelError( | ||
| "Custom TLS signing is only supported on standard release CPython runtimes." | ||
| ) | ||
| offset = sys.getsizeof(object()) | ||
| return ctypes.c_void_p.from_address(id(context) + offset) | ||
| # Load offload library and set up the function types. | ||
| @@ -274,7 +281,7 @@ def attach_to_ssl_context(self, ctx): | ||
| if not self._offload_lib.ConfigureSslContext( | ||
| self._sign_callback, | ||
| ctypes.c_char_p(self._cert), | ||
| _cast_ssl_ctx_to_void_p_pyopenssl(ctx._ctx._context), | ||
| _cast_ssl_ctx_to_void_p_stdlib(ctx), | ||
nbayati marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| ): | ||
| raise exceptions.MutualTLSChannelError( | ||
| "failed to configure ECP Offload SSL context" | ||
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.