auth: call_client_cert_callback() discards passphrase for encrypted keys #18467
Description
call_client_cert_callback() in google.auth.transport._mtls_helper calls get_client_ssl_credentials(generate_encrypted_key=True) and discards the returned passphrase, returning only (cert_bytes, key_bytes).
When using SecureConnect (context_aware_metadata.json), generate_encrypted_key=True passes --with_passphrase to the certificate provider command, producing an encrypted PEM private key. During 401 certificate rotation, AuthorizedSession.request() and AuthorizedHttp.urlopen() pass those credentials to configure_mtls_channel() without the passphrase. SSLContext.load_cert_chain() then receives the encrypted key with password=None, causing OpenSSL to prompt for a passphrase on /dev/tty or fail with OSError and raise MutualTLSChannelError.
By contrast, initial mTLS setup in get_client_cert_and_key() passes generate_encrypted_key=False, relying on secure_cert_key_paths() to keep private keys in memory (os.memfd_create on Linux) or encrypt them on the fly with an ephemeral passphrase when falling back to temporary files.
Proposed Fix
Update call_client_cert_callback() in packages/google-auth/google/auth/transport/_mtls_helper.py to pass generate_encrypted_key=False:
def call_client_cert_callback():
"""Calls the client cert callback and returns the certificate and key."""
_, cert_bytes, key_bytes, _ = get_client_ssl_credentials(
generate_encrypted_key=False
)
return cert_bytes, key_bytesUpdate test_call_client_cert_callback in packages/google-auth/tests/transport/test__mtls_helper.py to expect generate_encrypted_key=False.
Activity