Skip to content

Commit 10f9273

Browse files
feat: consolidate mTLS channel errors (#480)
feat: consolidate mTLS channel errors
1 parent 6dd304b commit 10f9273

File tree

7 files changed

+112
-55
lines changed

7 files changed

+112
-55
lines changed

packages/google-auth/google/auth/exceptions.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,7 @@ class UserAccessTokenError(GoogleAuthError):
3434

3535
class DefaultCredentialsError(GoogleAuthError):
3636
"""Used to indicate that acquiring default credentials failed."""
37+
38+
39+
class MutualTLSChannelError(GoogleAuthError):
40+
"""Used to indicate that mutual TLS channel creation is failed."""

packages/google-auth/google/auth/transport/grpc.py

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import six
2222

23+
from google.auth import exceptions
2324
from google.auth.transport import _mtls_helper
2425

2526
try:
@@ -217,17 +218,8 @@ def my_client_cert_callback():
217218
grpc.Channel: The created gRPC channel.
218219
219220
Raises:
220-
OSError: If the cert provider command launch fails during the application
221-
default SSL credentials loading process on devices with endpoint
222-
verification support.
223-
RuntimeError: If the cert provider command has a runtime error during the
224-
application default SSL credentials loading process on devices with
225-
endpoint verification support.
226-
ValueError:
227-
If the context aware metadata file is malformed or if the cert provider
228-
command doesn't produce both client certificate and key during the
229-
application default SSL credentials loading process on devices with
230-
endpoint verification support.
221+
google.auth.exceptions.MutualTLSChannelError: If mutual TLS channel
222+
creation failed for any reason.
231223
"""
232224
# Create the metadata plugin for inserting the authorization header.
233225
metadata_plugin = AuthMetadataPlugin(credentials, request)
@@ -293,20 +285,21 @@ def ssl_credentials(self):
293285
grpc.ChannelCredentials: The created grpc channel credentials.
294286
295287
Raises:
296-
OSError: If the cert provider command launch fails.
297-
RuntimeError: If the cert provider command has a runtime error.
298-
ValueError:
299-
If the context aware metadata file is malformed or if the cert provider
300-
command doesn't produce both the client certificate and key.
288+
google.auth.exceptions.MutualTLSChannelError: If mutual TLS channel
289+
creation failed for any reason.
301290
"""
302291
if self._context_aware_metadata_path:
303-
metadata = _mtls_helper._read_dca_metadata_file(
304-
self._context_aware_metadata_path
305-
)
306-
cert, key = _mtls_helper.get_client_ssl_credentials(metadata)
307-
self._ssl_credentials = grpc.ssl_channel_credentials(
308-
certificate_chain=cert, private_key=key
309-
)
292+
try:
293+
metadata = _mtls_helper._read_dca_metadata_file(
294+
self._context_aware_metadata_path
295+
)
296+
cert, key = _mtls_helper.get_client_ssl_credentials(metadata)
297+
self._ssl_credentials = grpc.ssl_channel_credentials(
298+
certificate_chain=cert, private_key=key
299+
)
300+
except (OSError, RuntimeError, ValueError) as caught_exc:
301+
new_exc = exceptions.MutualTLSChannelError(caught_exc)
302+
six.raise_from(new_exc, caught_exc)
310303
else:
311304
self._ssl_credentials = grpc.ssl_channel_credentials()
312305

packages/google-auth/google/auth/transport/requests.py

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -355,23 +355,32 @@ def configure_mtls_channel(self, client_cert_callback=None):
355355
will be used.
356356
357357
Raises:
358-
ImportError: If certifi or pyOpenSSL is not installed.
359-
OpenSSL.crypto.Error: If client cert or key is invalid.
360-
OSError: If the cert provider command launch fails during the
361-
application default SSL credentials loading process.
362-
RuntimeError: If the cert provider command has a runtime error during
363-
the application default SSL credentials loading process.
364-
ValueError: If the context aware metadata file is malformed or the
365-
cert provider command doesn't produce both client certicate and
366-
key during the application default SSL credentials loading process.
358+
google.auth.exceptions.MutualTLSChannelError: If mutual TLS channel
359+
creation failed for any reason.
367360
"""
368-
self._is_mtls, cert, key = google.auth.transport._mtls_helper.get_client_cert_and_key(
369-
client_cert_callback
370-
)
361+
try:
362+
import OpenSSL
363+
except ImportError as caught_exc:
364+
new_exc = exceptions.MutualTLSChannelError(caught_exc)
365+
six.raise_from(new_exc, caught_exc)
371366

372-
if self._is_mtls:
373-
mtls_adapter = _MutualTlsAdapter(cert, key)
374-
self.mount("https://", mtls_adapter)
367+
try:
368+
self._is_mtls, cert, key = google.auth.transport._mtls_helper.get_client_cert_and_key(
369+
client_cert_callback
370+
)
371+
372+
if self._is_mtls:
373+
mtls_adapter = _MutualTlsAdapter(cert, key)
374+
self.mount("https://", mtls_adapter)
375+
except (
376+
ImportError,
377+
OpenSSL.crypto.Error,
378+
OSError,
379+
RuntimeError,
380+
ValueError,
381+
) as caught_exc:
382+
new_exc = exceptions.MutualTLSChannelError(caught_exc)
383+
six.raise_from(new_exc, caught_exc)
375384

376385
def request(
377386
self,

packages/google-auth/google/auth/transport/urllib3.py

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -297,24 +297,33 @@ def configure_mtls_channel(self, client_cert_callabck=None):
297297
True if the channel is mutual TLS and False otherwise.
298298
299299
Raises:
300-
ImportError: If certifi or pyOpenSSL is not installed.
301-
OpenSSL.crypto.Error: If client cert or key is invalid.
302-
OSError: If the cert provider command launch fails during the
303-
application default SSL credentials loading process.
304-
RuntimeError: If the cert provider command has a runtime error during
305-
the application default SSL credentials loading process.
306-
ValueError: If the context aware metadata file is malformed or the
307-
cert provider command doesn't produce both client certicate and
308-
key during the application default SSL credentials loading process.
300+
google.auth.exceptions.MutualTLSChannelError: If mutual TLS channel
301+
creation failed for any reason.
309302
"""
310-
found_cert_key, cert, key = transport._mtls_helper.get_client_cert_and_key(
311-
client_cert_callabck
312-
)
303+
try:
304+
import OpenSSL
305+
except ImportError as caught_exc:
306+
new_exc = exceptions.MutualTLSChannelError(caught_exc)
307+
six.raise_from(new_exc, caught_exc)
313308

314-
if found_cert_key:
315-
self.http = _make_mutual_tls_http(cert, key)
316-
else:
317-
self.http = _make_default_http()
309+
try:
310+
found_cert_key, cert, key = transport._mtls_helper.get_client_cert_and_key(
311+
client_cert_callabck
312+
)
313+
314+
if found_cert_key:
315+
self.http = _make_mutual_tls_http(cert, key)
316+
else:
317+
self.http = _make_default_http()
318+
except (
319+
ImportError,
320+
OpenSSL.crypto.Error,
321+
OSError,
322+
RuntimeError,
323+
ValueError,
324+
) as caught_exc:
325+
new_exc = exceptions.MutualTLSChannelError(caught_exc)
326+
six.raise_from(new_exc, caught_exc)
318327

319328
if self._has_user_provided_http:
320329
self._has_user_provided_http = False

packages/google-auth/tests/transport/test_grpc.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
from google.auth import _helpers
2323
from google.auth import credentials
24+
from google.auth import exceptions
2425
from google.auth import transport
2526

2627
try:
@@ -315,7 +316,7 @@ def test_get_client_ssl_credentials_failure(
315316
# Mock that client cert and key are not loaded and exception is raised.
316317
mock_get_client_ssl_credentials.side_effect = ValueError()
317318

318-
with pytest.raises(ValueError):
319+
with pytest.raises(exceptions.MutualTLSChannelError):
319320
assert google.auth.transport.grpc.SslCredentials().ssl_credentials
320321

321322
def test_get_client_ssl_credentials_success(

packages/google-auth/tests/transport/test_requests.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
import datetime
1616
import functools
17+
import sys
1718

1819
import freezegun
1920
import mock
@@ -23,6 +24,7 @@
2324
import requests.adapters
2425
from six.moves import http_client
2526

27+
from google.auth import exceptions
2628
import google.auth.credentials
2729
import google.auth.transport._mtls_helper
2830
import google.auth.transport.requests
@@ -414,3 +416,21 @@ def test_configure_mtls_channel_non_mtls(
414416

415417
# Assert _MutualTlsAdapter constructor is not called.
416418
mock_adapter_ctor.assert_not_called()
419+
420+
@mock.patch(
421+
"google.auth.transport._mtls_helper.get_client_cert_and_key", autospec=True
422+
)
423+
def test_configure_mtls_channel_exceptions(self, mock_get_client_cert_and_key):
424+
mock_get_client_cert_and_key.side_effect = ValueError()
425+
426+
auth_session = google.auth.transport.requests.AuthorizedSession(
427+
credentials=mock.Mock()
428+
)
429+
with pytest.raises(exceptions.MutualTLSChannelError):
430+
auth_session.configure_mtls_channel()
431+
432+
mock_get_client_cert_and_key.return_value = (False, None, None)
433+
with mock.patch.dict("sys.modules"):
434+
sys.modules["OpenSSL"] = None
435+
with pytest.raises(exceptions.MutualTLSChannelError):
436+
auth_session.configure_mtls_channel()

packages/google-auth/tests/transport/test_urllib3.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,15 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
import sys
16+
1517
import mock
1618
import OpenSSL
1719
import pytest
1820
from six.moves import http_client
1921
import urllib3
2022

23+
from google.auth import exceptions
2124
import google.auth.credentials
2225
import google.auth.transport._mtls_helper
2326
import google.auth.transport.urllib3
@@ -221,3 +224,21 @@ def test_configure_mtls_channel_non_mtls(
221224
assert not is_mtls
222225
mock_get_client_cert_and_key.assert_called_once()
223226
mock_make_mutual_tls_http.assert_not_called()
227+
228+
@mock.patch(
229+
"google.auth.transport._mtls_helper.get_client_cert_and_key", autospec=True
230+
)
231+
def test_configure_mtls_channel_exceptions(self, mock_get_client_cert_and_key):
232+
authed_http = google.auth.transport.urllib3.AuthorizedHttp(
233+
credentials=mock.Mock()
234+
)
235+
236+
mock_get_client_cert_and_key.side_effect = ValueError()
237+
with pytest.raises(exceptions.MutualTLSChannelError):
238+
authed_http.configure_mtls_channel()
239+
240+
mock_get_client_cert_and_key.return_value = (False, None, None)
241+
with mock.patch.dict("sys.modules"):
242+
sys.modules["OpenSSL"] = None
243+
with pytest.raises(exceptions.MutualTLSChannelError):
244+
authed_http.configure_mtls_channel()

0 commit comments

Comments
 (0)