Skip to content

Commit

Permalink
feat: expose universe_domain for external account creds (#1296)
Browse files Browse the repository at this point in the history
* feat: expose  for external account creds

* add universe_domain as info property

* fix info error

* adding coverage of explicit universe_domain assigning

* 🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

---------

Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
  • Loading branch information
BigTailWolf and gcf-owl-bot[bot] committed May 22, 2023
1 parent 8c8d4e4 commit ee07053
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 1 deletion.
8 changes: 8 additions & 0 deletions google/auth/external_account.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@
# Cloud resource manager URL used to retrieve project information.
_CLOUD_RESOURCE_MANAGER = "https://cloudresourcemanager.googleapis.com/v1/projects/"

_DEFAULT_UNIVERSE_DOMAIN = "googleapis.com"


@six.add_metaclass(abc.ABCMeta)
class Credentials(
Expand Down Expand Up @@ -82,6 +84,7 @@ def __init__(
scopes=None,
default_scopes=None,
workforce_pool_user_project=None,
universe_domain=_DEFAULT_UNIVERSE_DOMAIN,
):
"""Instantiates an external account credentials object.
Expand All @@ -105,6 +108,8 @@ def __init__(
a workload identity pool. The underlying principal must still have
serviceusage.services.use IAM permission to use the project for
billing/quota.
universe_domain (str): The universe domain. The default universe
domain is googleapis.com.
Raises:
google.auth.exceptions.RefreshError: If the generateAccessToken
endpoint returned an error.
Expand All @@ -125,6 +130,7 @@ def __init__(
self._scopes = scopes
self._default_scopes = default_scopes
self._workforce_pool_user_project = workforce_pool_user_project
self._universe_domain = universe_domain or _DEFAULT_UNIVERSE_DOMAIN

if self._client_id:
self._client_auth = utils.ClientAuthentication(
Expand Down Expand Up @@ -186,6 +192,7 @@ def _constructor_args(self):
"workforce_pool_user_project": self._workforce_pool_user_project,
"scopes": self._scopes,
"default_scopes": self._default_scopes,
"universe_domain": self._universe_domain,
}
if not self.is_workforce_pool:
args.pop("workforce_pool_user_project")
Expand Down Expand Up @@ -458,6 +465,7 @@ def from_info(cls, info, **kwargs):
credential_source=info.get("credential_source"),
quota_project_id=info.get("quota_project_id"),
workforce_pool_user_project=info.get("workforce_pool_user_project"),
universe_domain=info.get("universe_domain", _DEFAULT_UNIVERSE_DOMAIN),
**kwargs
)

Expand Down
7 changes: 7 additions & 0 deletions tests/test_aws.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
# Each tuple contains the following entries:
# region, time, credentials, original_request, signed_request

DEFAULT_UNIVERSE_DOMAIN = "googleapis.com"
VALID_TOKEN_URLS = [
"https://sts.googleapis.com",
"https://us-east-1.sts.googleapis.com",
Expand Down Expand Up @@ -925,6 +926,7 @@ def test_from_info_full_options(self, mock_init):
credential_source=self.CREDENTIAL_SOURCE,
quota_project_id=QUOTA_PROJECT_ID,
workforce_pool_user_project=None,
universe_domain=DEFAULT_UNIVERSE_DOMAIN,
)

@mock.patch.object(aws.Credentials, "__init__", return_value=None)
Expand Down Expand Up @@ -952,6 +954,7 @@ def test_from_info_required_options_only(self, mock_init):
credential_source=self.CREDENTIAL_SOURCE,
quota_project_id=None,
workforce_pool_user_project=None,
universe_domain=DEFAULT_UNIVERSE_DOMAIN,
)

@mock.patch.object(aws.Credentials, "__init__", return_value=None)
Expand All @@ -967,6 +970,7 @@ def test_from_file_full_options(self, mock_init, tmpdir):
"client_secret": CLIENT_SECRET,
"quota_project_id": QUOTA_PROJECT_ID,
"credential_source": self.CREDENTIAL_SOURCE,
"universe_domain": DEFAULT_UNIVERSE_DOMAIN,
}
config_file = tmpdir.join("config.json")
config_file.write(json.dumps(info))
Expand All @@ -986,6 +990,7 @@ def test_from_file_full_options(self, mock_init, tmpdir):
credential_source=self.CREDENTIAL_SOURCE,
quota_project_id=QUOTA_PROJECT_ID,
workforce_pool_user_project=None,
universe_domain=DEFAULT_UNIVERSE_DOMAIN,
)

@mock.patch.object(aws.Credentials, "__init__", return_value=None)
Expand Down Expand Up @@ -1014,6 +1019,7 @@ def test_from_file_required_options_only(self, mock_init, tmpdir):
credential_source=self.CREDENTIAL_SOURCE,
quota_project_id=None,
workforce_pool_user_project=None,
universe_domain=DEFAULT_UNIVERSE_DOMAIN,
)

def test_constructor_invalid_credential_source(self):
Expand Down Expand Up @@ -1067,6 +1073,7 @@ def test_info(self):
"token_url": TOKEN_URL,
"token_info_url": TOKEN_INFO_URL,
"credential_source": self.CREDENTIAL_SOURCE,
"universe_domain": DEFAULT_UNIVERSE_DOMAIN,
}

def test_token_info_url(self):
Expand Down
9 changes: 8 additions & 1 deletion tests/test_external_account.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ def make_credentials(
default_scopes=None,
service_account_impersonation_url=None,
service_account_impersonation_options={},
universe_domain=external_account._DEFAULT_UNIVERSE_DOMAIN,
):
return CredentialsImpl(
audience=cls.AUDIENCE,
Expand All @@ -158,6 +159,7 @@ def make_credentials(
quota_project_id=quota_project_id,
scopes=scopes,
default_scopes=default_scopes,
universe_domain=universe_domain,
)

@classmethod
Expand Down Expand Up @@ -378,6 +380,7 @@ def test_with_scopes_full_options_propagated(self):
quota_project_id=self.QUOTA_PROJECT_ID,
scopes=["email"],
default_scopes=["default2"],
universe_domain=external_account._DEFAULT_UNIVERSE_DOMAIN,
)

def test_with_token_uri(self):
Expand Down Expand Up @@ -465,6 +468,7 @@ def test_with_quota_project_full_options_propagated(self):
quota_project_id="project-foo",
scopes=self.SCOPES,
default_scopes=["default1"],
universe_domain=external_account._DEFAULT_UNIVERSE_DOMAIN,
)

def test_with_invalid_impersonation_target_principal(self):
Expand All @@ -478,14 +482,15 @@ def test_with_invalid_impersonation_target_principal(self):
)

def test_info(self):
credentials = self.make_credentials()
credentials = self.make_credentials(universe_domain="dummy_universe.com")

assert credentials.info == {
"type": "external_account",
"audience": self.AUDIENCE,
"subject_token_type": self.SUBJECT_TOKEN_TYPE,
"token_url": self.TOKEN_URL,
"credential_source": self.CREDENTIAL_SOURCE.copy(),
"universe_domain": "dummy_universe.com",
}

def test_info_workforce_pool(self):
Expand All @@ -500,6 +505,7 @@ def test_info_workforce_pool(self):
"token_url": self.TOKEN_URL,
"credential_source": self.CREDENTIAL_SOURCE.copy(),
"workforce_pool_user_project": self.WORKFORCE_POOL_USER_PROJECT,
"universe_domain": external_account._DEFAULT_UNIVERSE_DOMAIN,
}

def test_info_with_full_options(self):
Expand All @@ -524,6 +530,7 @@ def test_info_with_full_options(self):
"quota_project_id": self.QUOTA_PROJECT_ID,
"client_id": CLIENT_ID,
"client_secret": CLIENT_SECRET,
"universe_domain": external_account._DEFAULT_UNIVERSE_DOMAIN,
}

def test_service_account_email_without_impersonation(self):
Expand Down
10 changes: 10 additions & 0 deletions tests/test_identity_pool.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
WORKFORCE_SUBJECT_TOKEN_TYPE = "urn:ietf:params:oauth:token-type:id_token"
WORKFORCE_POOL_USER_PROJECT = "WORKFORCE_POOL_USER_PROJECT_NUMBER"

DEFAULT_UNIVERSE_DOMAIN = "googleapis.com"

VALID_TOKEN_URLS = [
"https://sts.googleapis.com",
Expand Down Expand Up @@ -410,6 +411,7 @@ def test_from_info_full_options(self, mock_init):
credential_source=self.CREDENTIAL_SOURCE_TEXT,
quota_project_id=QUOTA_PROJECT_ID,
workforce_pool_user_project=None,
universe_domain=DEFAULT_UNIVERSE_DOMAIN,
)

@mock.patch.object(identity_pool.Credentials, "__init__", return_value=None)
Expand Down Expand Up @@ -437,6 +439,7 @@ def test_from_info_required_options_only(self, mock_init):
credential_source=self.CREDENTIAL_SOURCE_TEXT,
quota_project_id=None,
workforce_pool_user_project=None,
universe_domain=DEFAULT_UNIVERSE_DOMAIN,
)

@mock.patch.object(identity_pool.Credentials, "__init__", return_value=None)
Expand Down Expand Up @@ -465,6 +468,7 @@ def test_from_info_workforce_pool(self, mock_init):
credential_source=self.CREDENTIAL_SOURCE_TEXT,
quota_project_id=None,
workforce_pool_user_project=WORKFORCE_POOL_USER_PROJECT,
universe_domain=DEFAULT_UNIVERSE_DOMAIN,
)

@mock.patch.object(identity_pool.Credentials, "__init__", return_value=None)
Expand Down Expand Up @@ -499,6 +503,7 @@ def test_from_file_full_options(self, mock_init, tmpdir):
credential_source=self.CREDENTIAL_SOURCE_TEXT,
quota_project_id=QUOTA_PROJECT_ID,
workforce_pool_user_project=None,
universe_domain=DEFAULT_UNIVERSE_DOMAIN,
)

@mock.patch.object(identity_pool.Credentials, "__init__", return_value=None)
Expand Down Expand Up @@ -527,6 +532,7 @@ def test_from_file_required_options_only(self, mock_init, tmpdir):
credential_source=self.CREDENTIAL_SOURCE_TEXT,
quota_project_id=None,
workforce_pool_user_project=None,
universe_domain=DEFAULT_UNIVERSE_DOMAIN,
)

@mock.patch.object(identity_pool.Credentials, "__init__", return_value=None)
Expand Down Expand Up @@ -556,6 +562,7 @@ def test_from_file_workforce_pool(self, mock_init, tmpdir):
credential_source=self.CREDENTIAL_SOURCE_TEXT,
quota_project_id=None,
workforce_pool_user_project=WORKFORCE_POOL_USER_PROJECT,
universe_domain=DEFAULT_UNIVERSE_DOMAIN,
)

def test_constructor_nonworkforce_with_workforce_pool_user_project(self):
Expand Down Expand Up @@ -639,6 +646,7 @@ def test_info_with_workforce_pool_user_project(self):
"token_info_url": TOKEN_INFO_URL,
"credential_source": self.CREDENTIAL_SOURCE_TEXT_URL,
"workforce_pool_user_project": WORKFORCE_POOL_USER_PROJECT,
"universe_domain": DEFAULT_UNIVERSE_DOMAIN,
}

def test_info_with_file_credential_source(self):
Expand All @@ -653,6 +661,7 @@ def test_info_with_file_credential_source(self):
"token_url": TOKEN_URL,
"token_info_url": TOKEN_INFO_URL,
"credential_source": self.CREDENTIAL_SOURCE_TEXT_URL,
"universe_domain": DEFAULT_UNIVERSE_DOMAIN,
}

def test_info_with_url_credential_source(self):
Expand All @@ -667,6 +676,7 @@ def test_info_with_url_credential_source(self):
"token_url": TOKEN_URL,
"token_info_url": TOKEN_INFO_URL,
"credential_source": self.CREDENTIAL_SOURCE_JSON_URL,
"universe_domain": DEFAULT_UNIVERSE_DOMAIN,
}

def test_retrieve_subject_token_missing_subject_token(self, tmpdir):
Expand Down
6 changes: 6 additions & 0 deletions tests/test_pluggable.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
TOKEN_INFO_URL = "https://sts.googleapis.com/v1/introspect"
SUBJECT_TOKEN_TYPE = "urn:ietf:params:oauth:token-type:jwt"
AUDIENCE = "//iam.googleapis.com/projects/123456/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID"
DEFAULT_UNIVERSE_DOMAIN = "googleapis.com"

VALID_TOKEN_URLS = [
"https://sts.googleapis.com",
Expand Down Expand Up @@ -278,6 +279,7 @@ def test_from_info_full_options(self, mock_init):
credential_source=self.CREDENTIAL_SOURCE,
quota_project_id=QUOTA_PROJECT_ID,
workforce_pool_user_project=None,
universe_domain=DEFAULT_UNIVERSE_DOMAIN,
)

@mock.patch.object(pluggable.Credentials, "__init__", return_value=None)
Expand Down Expand Up @@ -305,6 +307,7 @@ def test_from_info_required_options_only(self, mock_init):
credential_source=self.CREDENTIAL_SOURCE,
quota_project_id=None,
workforce_pool_user_project=None,
universe_domain=DEFAULT_UNIVERSE_DOMAIN,
)

@mock.patch.object(pluggable.Credentials, "__init__", return_value=None)
Expand Down Expand Up @@ -339,6 +342,7 @@ def test_from_file_full_options(self, mock_init, tmpdir):
credential_source=self.CREDENTIAL_SOURCE,
quota_project_id=QUOTA_PROJECT_ID,
workforce_pool_user_project=None,
universe_domain=DEFAULT_UNIVERSE_DOMAIN,
)

@mock.patch.object(pluggable.Credentials, "__init__", return_value=None)
Expand Down Expand Up @@ -367,6 +371,7 @@ def test_from_file_required_options_only(self, mock_init, tmpdir):
credential_source=self.CREDENTIAL_SOURCE,
quota_project_id=None,
workforce_pool_user_project=None,
universe_domain=DEFAULT_UNIVERSE_DOMAIN,
)

def test_constructor_invalid_options(self):
Expand Down Expand Up @@ -395,6 +400,7 @@ def test_info_with_credential_source(self):
"token_url": TOKEN_URL,
"token_info_url": TOKEN_INFO_URL,
"credential_source": self.CREDENTIAL_SOURCE,
"universe_domain": DEFAULT_UNIVERSE_DOMAIN,
}

def test_token_info_url(self):
Expand Down

0 comments on commit ee07053

Please sign in to comment.