fix(google-auth): fail loudly when dynamically disabling mTLS on active sessions - #18005
fix(google-auth): fail loudly when dynamically disabling mTLS on active sessions#18005gorthitk wants to merge 3 commits into
Conversation
…ve sessions (googleapis#17761) When mTLS is previously enabled on an active transport session (requests, urllib3, or aiohttp), attempting to disable mTLS mid-lifecycle in configure_mtls_channel() now raises a MutualTLSChannelError instead of exiting early or replacing adapters. This prevents thread-safety violations from connection pool mutation and eliminates zombie state mismatches where active sessions continue sending client certificates while auth checks treat mTLS as disabled.
There was a problem hiding this comment.
Code Review
This pull request prevents mid-lifecycle transitions from mTLS-enabled to mTLS-disabled states on active sessions across the aio, requests, and urllib3 transports by raising a MutualTLSChannelError. However, the review feedback highlights that raising this exception replaces historical graceful fallback behaviors (such as falling back to standard TLS or returning False), which introduces breaking changes for downstream users and violates backwards compatibility.
| # Dynamically disabling mTLS on an active session is unsafe in concurrent | ||
| # environments and can cause a zombie state mismatch where mTLS contexts | ||
| # remain attached while auth checks believe mTLS is disabled. | ||
| if getattr(self, "_is_mtls", False): |
There was a problem hiding this comment.
self._is_mtls is explicitly initialized to False in init across AsyncAuthorizedSession, AuthorizedSession, and AuthorizedHttp. Using getattr(self, "_is_mtls", False) is unnecessary, we can access self._is_mtls directly.
| # remain attached while auth checks believe mTLS is disabled. | ||
| if getattr(self, "_is_mtls", False): | ||
| raise exceptions.MutualTLSChannelError( | ||
| "Cannot disable mTLS on an active session. A new AuthorizedSession must be created." |
There was a problem hiding this comment.
Please update this to reference AsyncAuthorizedSession instead of AuthorizedSession so async users aren't directed to the synchronous requests transport class.
| "Cannot disable mTLS on an active session. A new AuthorizedSession must be created." | |
| "Cannot disable mTLS on an active session. A new AsyncAuthorizedSession must be created." |
| # Prevent mid-lifecycle transition from mTLS-enabled to mTLS-disabled state. | ||
| if getattr(self, "_is_mtls", False) and not is_mtls: | ||
| raise exceptions.MutualTLSChannelError( | ||
| "Cannot disable mTLS on an active session. A new AuthorizedSession must be created." |
There was a problem hiding this comment.
Same here
| "Cannot disable mTLS on an active session. A new AuthorizedSession must be created." | |
| "Cannot disable mTLS on an active session. A new AsyncAuthorizedSession must be created." |
| use_client_cert = google.auth.transport._mtls_helper.check_use_client_cert() | ||
| if not use_client_cert: | ||
| # Dynamically disabling mTLS on an active session is unsafe in concurrent | ||
| # environments and can cause a zombie state mismatch where mTLS adapters |
There was a problem hiding this comment.
nit
| # environments and can cause a zombie state mismatch where mTLS adapters | |
| # environments and can cause a state mismatch where mTLS adapters |
| use_client_cert = transport._mtls_helper.check_use_client_cert() | ||
| if not use_client_cert: | ||
| # Dynamically disabling mTLS on an active session is unsafe in concurrent | ||
| # environments and can cause a zombie state mismatch where mTLS connection |
There was a problem hiding this comment.
nit:
| # environments and can cause a zombie state mismatch where mTLS connection | |
| # environments and can cause a state mismatch where mTLS connection |
|
Hi @gorthitk, I'm going to mark this as draft since presubmits are failing but please feel free to mark it ready for review once checks are green |
…tly in mTLS checks - Add _is_mtls_configured() helper across AuthorizedSession, AuthorizedHttp, and AsyncAuthorizedSession. - Inspect adapter types (_MutualTlsAdapter, _MutualTlsOffloadAdapter), PoolManager connection_pool_kw ssl_context, connector SSL context, and cached certificates directly. - Add unit tests verifying desynchronized state detection across all transports.
…yncAuthorizedSession
When mTLS is previously enabled on an active transport session (requests, urllib3, or aiohttp), attempting to disable mTLS mid-lifecycle in configure_mtls_channel() now raises a MutualTLSChannelError instead of exiting early or replacing adapters.
This prevents thread-safety violations from connection pool mutation and eliminates zombie state mismatches where active sessions continue sending client certificates while auth checks treat mTLS as disabled.
Fixes #17761