Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions google/auth/transport/mtls.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

"""Utilites for mutual TLS."""

from os import getenv

from google.auth import exceptions
from google.auth.transport import _mtls_helper

Expand All @@ -36,6 +38,12 @@ def has_default_client_cert_source():
is not None
):
return True
cert_config_path = getenv("GOOGLE_API_CERTIFICATE_CONFIG")
if (
cert_config_path
and _mtls_helper._check_config_path(cert_config_path) is not None
):
return True
return False


Expand Down
95 changes: 81 additions & 14 deletions tests/transport/test_mtls.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,26 +21,93 @@
from google.auth.transport import mtls


@mock.patch("google.auth.transport._mtls_helper._check_config_path", autospec=True)
def test_has_default_client_cert_source(check_config_path):
def return_path_for_metadata(path):
return mock.Mock() if path == _mtls_helper.CONTEXT_AWARE_METADATA_PATH else None
@mock.patch("google.auth.transport._mtls_helper._check_config_path")
def test_has_default_client_cert_source_with_context_aware_metadata(mock_check):
"""
Directly tests the logic: if CONTEXT_AWARE_METADATA_PATH is found, return True.
"""

check_config_path.side_effect = return_path_for_metadata
assert mtls.has_default_client_cert_source()
# Setup: Return a path only for the Context Aware Metadata Path
def side_effect(path):
if path == _mtls_helper.CONTEXT_AWARE_METADATA_PATH:
return "/path/to/context_aware_metadata.json"
return None

mock_check.side_effect = side_effect

# Execute
result = mtls.has_default_client_cert_source()

# Assert
assert result is True
mock_check.assert_any_call(_mtls_helper.CONTEXT_AWARE_METADATA_PATH)
assert side_effect("non-matching-path") is None


@mock.patch("google.auth.transport._mtls_helper._check_config_path")
def test_has_default_client_cert_source_falls_back(mock_check):
"""
Tests that it skips CONTEXT_AWARE_METADATA_PATH if None, and checks the next path.
"""

# Setup: First path is None, second path is valid
def side_effect(path):
if path == _mtls_helper.CERTIFICATE_CONFIGURATION_DEFAULT_PATH:
return "/path/to/default_cert.json"
return None

mock_check.side_effect = side_effect

def return_path_for_cert_config(path):
return (
mock.Mock()
if path == _mtls_helper.CERTIFICATE_CONFIGURATION_DEFAULT_PATH
else None
)
# Execute
result = mtls.has_default_client_cert_source()

check_config_path.side_effect = return_path_for_cert_config
# Assert
assert result is True
# Verify the sequence of calls
expected_calls = [
mock.call(_mtls_helper.CONTEXT_AWARE_METADATA_PATH),
mock.call(_mtls_helper.CERTIFICATE_CONFIGURATION_DEFAULT_PATH),
]
mock_check.assert_has_calls(expected_calls)


@mock.patch("google.auth.transport.mtls.getenv", autospec=True)
@mock.patch("google.auth.transport._mtls_helper._check_config_path", autospec=True)
def test_has_default_client_cert_source_env_var_success(check_config_path, mock_getenv):
# 1. Mock getenv to return our test path
mock_getenv.side_effect = (
lambda var: "path/to/cert.json"
if var == "GOOGLE_API_CERTIFICATE_CONFIG"
else None
)

# 2. Mock _check_config_path side effect
def side_effect(path):
# Return None for legacy paths to ensure we reach the env var logic
if path == "path/to/cert.json":
return "/absolute/path/to/cert.json"
return None

check_config_path.side_effect = side_effect

# 3. This should now return True
assert mtls.has_default_client_cert_source()

check_config_path.side_effect = None
# 4. Verify the env var path was checked
check_config_path.assert_called_with("path/to/cert.json")


@mock.patch("google.auth.transport.mtls.getenv", autospec=True)
@mock.patch("google.auth.transport._mtls_helper._check_config_path", autospec=True)
def test_has_default_client_cert_source_env_var_invalid_config_path(
check_config_path, mock_getenv
):
# Set the env var but make the check fail
mock_getenv.side_effect = (
lambda var: "invalid/path" if var == "GOOGLE_API_CERTIFICATE_CONFIG" else None
)
check_config_path.return_value = None

assert not mtls.has_default_client_cert_source()


Expand Down