Repository navigation
Conversation
Adds `_MtlsCertManager` in `google.auth.transport._mtls_helper` to track the active mTLS client certificate, private key, leaf certificate SHA-256 fingerprint, and generation counter across certificate reloads. This is the first change in the gRPC mTLS client certificate rotation series. Subsequent PRs wire `_MtlsCertManager` into `requests.Request` and Compute Engine bound-token refreshes, `AuthMetadataPlugin`, `google.api_core.grpc_helpers.create_channel`, and `gapic-generator` so that TLS channel credentials and certificate-bound token refreshes stay on the same certificate generation.
There was a problem hiding this comment.
Code Review
This pull request introduces _MtlsCertManager, a thread-safe manager for handling mTLS client certificates, tracking their generation, and managing reloading. It also adds comprehensive unit tests for this new class. The feedback suggests catching all standard exceptions (Exception) during certificate reloads rather than a specific subset, ensuring that unexpected errors from custom certificate sources do not crash the application and are instead gracefully handled as transient reload errors.
| except ( | ||
| exceptions.ClientCertError, | ||
| exceptions.MutualTLSChannelError, | ||
| OSError, | ||
| ValueError, | ||
| ) as caught_exc: | ||
| if self._generation_id > 0: | ||
| _LOGGER.debug( | ||
| "Failed to reload mTLS client certificate; retaining " | ||
| "previous certificate (generation %d): %s", | ||
| self._generation_id, | ||
| caught_exc, | ||
| ) | ||
| return False | ||
| if isinstance(caught_exc, exceptions.ClientCertError): | ||
| raise | ||
| raise exceptions.ClientCertError(caught_exc) from caught_exc |
There was a problem hiding this comment.
The except block currently catches a specific list of exceptions (ClientCertError, MutualTLSChannelError, OSError, ValueError). However, when a custom client_cert_source callback is provided, it may raise other unexpected or custom exceptions (e.g., network errors, custom HSM/KMS exceptions, or even TypeError if the callback returns an unexpected format).
If such an exception is raised during a certificate reload (when self._generation_id > 0), it will propagate and crash the application/request instead of being gracefully handled as a transient reload error. To ensure maximum robustness and successfully retain the last known good certificate, we should catch all standard exceptions (Exception) during reload.
except Exception as caught_exc:
if self._generation_id > 0:
_LOGGER.debug(
"Failed to reload mTLS client certificate; retaining "
"previous certificate (generation %d): %s",
self._generation_id,
caught_exc,
)
return False
if isinstance(caught_exc, exceptions.ClientCertError):
raise
raise exceptions.ClientCertError(caught_exc) from caught_excReferences
- Do not replace historical graceful fallback behaviors (such as returning False/falling back to standard TLS) with exceptions if doing so would introduce breaking changes for downstream users and violate backwards compatibility.
Adds
_MtlsCertManageringoogle.auth.transport._mtls_helperto track the active mTLS client certificate, private key, leaf certificate SHA-256 fingerprint, and generation counter across certificate reloads.This is the first change in the gRPC mTLS client certificate rotation series. Subsequent PRs wire
_MtlsCertManagerintorequests.Requestand Compute Engine bound-token refreshes,AuthMetadataPlugin,google.api_core.grpc_helpers.create_channel, andgapic-generatorso that TLS channel credentials and certificate-bound token refreshes stay on the same certificate generation.