From 333cb765b52028329ec3ca04edf32c5764b1db68 Mon Sep 17 00:00:00 2001 From: arithmetic1728 <58957152+arithmetic1728@users.noreply.github.com> Date: Thu, 25 Feb 2021 15:42:32 -0800 Subject: [PATCH] fix: use gcloud creds flow (#705) --- google/auth/_default.py | 13 +++++++++++++ google/auth/_default_async.py | 9 +++++++++ tests/test__default.py | 18 ++++++++++++++++++ tests_async/test__default_async.py | 18 ++++++++++++++++++ 4 files changed, 58 insertions(+) diff --git a/google/auth/_default.py b/google/auth/_default.py index 8e3b2100d..4dc0725e7 100644 --- a/google/auth/_default.py +++ b/google/auth/_default.py @@ -198,12 +198,25 @@ def _get_gcloud_sdk_credentials(): def _get_explicit_environ_credentials(): """Gets credentials from the GOOGLE_APPLICATION_CREDENTIALS environment variable.""" + from google.auth import _cloud_sdk + + cloud_sdk_adc_path = _cloud_sdk.get_application_default_credentials_path() explicit_file = os.environ.get(environment_vars.CREDENTIALS) _LOGGER.debug( "Checking %s for explicit credentials as part of auth process...", explicit_file ) + if explicit_file is not None and explicit_file == cloud_sdk_adc_path: + # Cloud sdk flow calls gcloud to fetch project id, so if the explicit + # file path is cloud sdk credentials path, then we should fall back + # to cloud sdk flow, otherwise project id cannot be obtained. + _LOGGER.debug( + "Explicit credentials path %s is the same as Cloud SDK credentials path, fall back to Cloud SDK credentials flow...", + explicit_file, + ) + return _get_gcloud_sdk_credentials() + if explicit_file is not None: credentials, project_id = load_credentials_from_file( os.environ[environment_vars.CREDENTIALS] diff --git a/google/auth/_default_async.py b/google/auth/_default_async.py index 1a725afba..d12a642af 100644 --- a/google/auth/_default_async.py +++ b/google/auth/_default_async.py @@ -127,8 +127,17 @@ def _get_gcloud_sdk_credentials(): def _get_explicit_environ_credentials(): """Gets credentials from the GOOGLE_APPLICATION_CREDENTIALS environment variable.""" + from google.auth import _cloud_sdk + + cloud_sdk_adc_path = _cloud_sdk.get_application_default_credentials_path() explicit_file = os.environ.get(environment_vars.CREDENTIALS) + if explicit_file is not None and explicit_file == cloud_sdk_adc_path: + # Cloud sdk flow calls gcloud to fetch project id, so if the explicit + # file path is cloud sdk credentials path, then we should fall back + # to cloud sdk flow, otherwise project id cannot be obtained. + return _get_gcloud_sdk_credentials() + if explicit_file is not None: credentials, project_id = load_credentials_from_file( os.environ[environment_vars.CREDENTIALS] diff --git a/tests/test__default.py b/tests/test__default.py index 74ed61855..e13689625 100644 --- a/tests/test__default.py +++ b/tests/test__default.py @@ -350,6 +350,24 @@ def test__get_explicit_environ_credentials_no_project_id(load, monkeypatch): assert project_id is None +@mock.patch( + "google.auth._cloud_sdk.get_application_default_credentials_path", autospec=True +) +@mock.patch("google.auth._default._get_gcloud_sdk_credentials", autospec=True) +def test__get_explicit_environ_credentials_fallback_to_gcloud( + get_gcloud_creds, get_adc_path, monkeypatch +): + # Set explicit credentials path to cloud sdk credentials path. + get_adc_path.return_value = "filename" + monkeypatch.setenv(environment_vars.CREDENTIALS, "filename") + + _default._get_explicit_environ_credentials() + + # Check we fall back to cloud sdk flow since explicit credentials path is + # cloud sdk credentials path + get_gcloud_creds.assert_called_once() + + @LOAD_FILE_PATCH @mock.patch( "google.auth._cloud_sdk.get_application_default_credentials_path", autospec=True diff --git a/tests_async/test__default_async.py b/tests_async/test__default_async.py index bca396aee..527a8da45 100644 --- a/tests_async/test__default_async.py +++ b/tests_async/test__default_async.py @@ -187,6 +187,24 @@ def test__get_explicit_environ_credentials_no_project_id(load, monkeypatch): assert project_id is None +@mock.patch( + "google.auth._cloud_sdk.get_application_default_credentials_path", autospec=True +) +@mock.patch("google.auth._default_async._get_gcloud_sdk_credentials", autospec=True) +def test__get_explicit_environ_credentials_fallback_to_gcloud( + get_gcloud_creds, get_adc_path, monkeypatch +): + # Set explicit credentials path to cloud sdk credentials path. + get_adc_path.return_value = "filename" + monkeypatch.setenv(environment_vars.CREDENTIALS, "filename") + + _default._get_explicit_environ_credentials() + + # Check we fall back to cloud sdk flow since explicit credentials path is + # cloud sdk credentials path + get_gcloud_creds.assert_called_once() + + @LOAD_FILE_PATCH @mock.patch( "google.auth._cloud_sdk.get_application_default_credentials_path", autospec=True