From 6d2c1fbc866390dcf07dbf7201e18990777ca3c4 Mon Sep 17 00:00:00 2001 From: Sai Sunder Srinivasan Date: Wed, 12 Oct 2022 22:45:53 +0000 Subject: [PATCH 1/4] feat: Read Quota Project from Environment Variable --- google/auth/_default.py | 2 ++ google/auth/credentials.py | 9 ++++++++- google/auth/environment_vars.py | 4 ++++ tests/test__default.py | 21 +++++++++++++++++++++ 4 files changed, 35 insertions(+), 1 deletion(-) diff --git a/google/auth/_default.py b/google/auth/_default.py index bef09659b..8fe168428 100644 --- a/google/auth/_default.py +++ b/google/auth/_default.py @@ -479,6 +479,8 @@ def _get_gdch_service_account_credentials(filename, info): def _apply_quota_project_id(credentials, quota_project_id): if quota_project_id: credentials = credentials.with_quota_project(quota_project_id) + else: + credentials = credentials.with_quota_project_from_environment() from google.oauth2 import credentials as authorized_user_credentials diff --git a/google/auth/credentials.py b/google/auth/credentials.py index 2735892d4..bfe14da25 100644 --- a/google/auth/credentials.py +++ b/google/auth/credentials.py @@ -16,10 +16,11 @@ """Interfaces for credentials.""" import abc +import os import six -from google.auth import _helpers +from google.auth import _helpers, environment_vars @six.add_metaclass(abc.ABCMeta) @@ -149,6 +150,12 @@ def with_quota_project(self, quota_project_id): """ raise NotImplementedError("This credential does not support quota project.") + def with_quota_project_from_environment(self): + quota_from_env = os.environ.get(environment_vars.GOOGLE_CLOUD_QUOTA_PROJECT) + if quota_from_env is not None: + return self.with_quota_project(quota_from_env) + return self + class CredentialsWithTokenUri(Credentials): """Abstract base for credentials supporting ``with_token_uri`` factory""" diff --git a/google/auth/environment_vars.py b/google/auth/environment_vars.py index c076dc59d..81f31571e 100644 --- a/google/auth/environment_vars.py +++ b/google/auth/environment_vars.py @@ -29,6 +29,10 @@ situations (such as Google App Engine). """ +GOOGLE_CLOUD_QUOTA_PROJECT = "GOOGLE_CLOUD_QUOTA_PROJECT" +"""Environment variable defining the project to be used for +quota and billing.""" + CREDENTIALS = "GOOGLE_APPLICATION_CREDENTIALS" """Environment variable defining the location of Google application default credentials.""" diff --git a/tests/test__default.py b/tests/test__default.py index 11d87f4cb..ab1de2651 100644 --- a/tests/test__default.py +++ b/tests/test__default.py @@ -1214,3 +1214,24 @@ def test_default_gdch_service_account_credentials(get_adc_path): assert creds._token_uri == "https://service-identity./authenticate" assert creds._ca_cert_path == "/path/to/ca/cert" assert project == "project_foo" + + +@mock.patch.dict(os.environ) +@mock.patch( + "google.auth._cloud_sdk.get_application_default_credentials_path", autospec=True +) +def test_quota_project_from_environment(get_adc_path): + get_adc_path.return_value = AUTHORIZED_USER_CLOUD_SDK_WITH_QUOTA_PROJECT_ID_FILE + + credentials, _ = _default.default(quota_project_id=None) + assert credentials.quota_project_id == "quota_project_id" + + quota_from_env = "quota_from_env" + # monkeypatch.setenv(environment_vars.GOOGLE_CLOUD_QUOTA_PROJECT, quota_from_env) + os.environ[environment_vars.GOOGLE_CLOUD_QUOTA_PROJECT] = quota_from_env + credentials, _ = _default.default(quota_project_id=None) + assert credentials.quota_project_id == quota_from_env + + explicit_quota = "explicit_quota" + credentials, _ = _default.default(quota_project_id=explicit_quota) + assert credentials.quota_project_id == explicit_quota From c6c0104a9d55891c1136ec223bb7d9653e142cd1 Mon Sep 17 00:00:00 2001 From: Sai Sunder Srinivasan Date: Wed, 12 Oct 2022 22:51:30 +0000 Subject: [PATCH 2/4] remove unused code --- tests/test__default.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test__default.py b/tests/test__default.py index ab1de2651..26b41b995 100644 --- a/tests/test__default.py +++ b/tests/test__default.py @@ -1227,7 +1227,6 @@ def test_quota_project_from_environment(get_adc_path): assert credentials.quota_project_id == "quota_project_id" quota_from_env = "quota_from_env" - # monkeypatch.setenv(environment_vars.GOOGLE_CLOUD_QUOTA_PROJECT, quota_from_env) os.environ[environment_vars.GOOGLE_CLOUD_QUOTA_PROJECT] = quota_from_env credentials, _ = _default.default(quota_project_id=None) assert credentials.quota_project_id == quota_from_env From 9590e0e84194992564f67c43e4c37c1148fa7b85 Mon Sep 17 00:00:00 2001 From: sai-sunder-s <4540365+sai-sunder-s@users.noreply.github.com> Date: Wed, 12 Oct 2022 23:12:35 +0000 Subject: [PATCH 3/4] Update google/auth/credentials.py Co-authored-by: Carl Lundin <108372512+clundin25@users.noreply.github.com> --- google/auth/credentials.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/google/auth/credentials.py b/google/auth/credentials.py index bfe14da25..ca1032a14 100644 --- a/google/auth/credentials.py +++ b/google/auth/credentials.py @@ -152,7 +152,7 @@ def with_quota_project(self, quota_project_id): def with_quota_project_from_environment(self): quota_from_env = os.environ.get(environment_vars.GOOGLE_CLOUD_QUOTA_PROJECT) - if quota_from_env is not None: + if quota_from_env: return self.with_quota_project(quota_from_env) return self From 9389489a1534bb989ffb05c0456ba751fe50a959 Mon Sep 17 00:00:00 2001 From: Sai Sunder Srinivasan Date: Mon, 31 Oct 2022 20:19:18 +0000 Subject: [PATCH 4/4] update rt --- system_tests/secrets.tar.enc | Bin 10323 -> 10324 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/system_tests/secrets.tar.enc b/system_tests/secrets.tar.enc index 79b062223349fdf241980b73500b05710d3d387b..abfaddd92913cbd9392312fc240a82ee8fe99e47 100644 GIT binary patch literal 10324 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�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 literal 10323 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