From 87706fd9561aeb651ef551f3576f236a73fad27a Mon Sep 17 00:00:00 2001 From: arithmetic1728 <58957152+arithmetic1728@users.noreply.github.com> Date: Tue, 25 Jan 2022 03:21:25 -0800 Subject: [PATCH 1/3] chore: update user cred for system test (#957) --- system_tests/secrets.tar.enc | Bin 10324 -> 10324 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/system_tests/secrets.tar.enc b/system_tests/secrets.tar.enc index f0df346746ed938164c53d3c2b6229137951f350..77e60a3091201b58e1e56dd722425a57acd72775 100644 GIT binary patch literal 10324 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 mZa5AE>1)MOG-%qDIgvIBk+gnOfM< Date: Tue, 25 Jan 2022 15:36:43 -0500 Subject: [PATCH 2/3] feat: ADC can load an impersonated service account credentials. (#956) * Make code changes in _default * Add unit tests. * Fix docstring. Co-authored-by: arithmetic1728 <58957152+arithmetic1728@users.noreply.github.com> --- google/auth/_default.py | 151 +++++++++++++----- ...ervice_account_authorized_user_source.json | 13 ++ ...ervice_account_service_account_source.json | 17 ++ ...ed_service_account_with_quota_project.json | 14 ++ tests/test__default.py | 92 +++++++++++ 5 files changed, 251 insertions(+), 36 deletions(-) create mode 100644 tests/data/impersonated_service_account_authorized_user_source.json create mode 100644 tests/data/impersonated_service_account_service_account_source.json create mode 100644 tests/data/impersonated_service_account_with_quota_project.json diff --git a/google/auth/_default.py b/google/auth/_default.py index 54d656164..c70dccfaa 100644 --- a/google/auth/_default.py +++ b/google/auth/_default.py @@ -35,7 +35,13 @@ _AUTHORIZED_USER_TYPE = "authorized_user" _SERVICE_ACCOUNT_TYPE = "service_account" _EXTERNAL_ACCOUNT_TYPE = "external_account" -_VALID_TYPES = (_AUTHORIZED_USER_TYPE, _SERVICE_ACCOUNT_TYPE, _EXTERNAL_ACCOUNT_TYPE) +_IMPERSONATED_SERVICE_ACCOUNT_TYPE = "impersonated_service_account" +_VALID_TYPES = ( + _AUTHORIZED_USER_TYPE, + _SERVICE_ACCOUNT_TYPE, + _EXTERNAL_ACCOUNT_TYPE, + _IMPERSONATED_SERVICE_ACCOUNT_TYPE, +) # Help message when no credentials can be found. _HELP_MESSAGE = """\ @@ -79,7 +85,8 @@ def load_credentials_from_file( """Loads Google credentials from a file. The credentials file must be a service account key, stored authorized - user credentials or external account credentials. + user credentials, external account credentials, or impersonated service + account credentials. Args: filename (str): The full path to the credentials file. @@ -119,42 +126,25 @@ def load_credentials_from_file( "File {} is not a valid json file.".format(filename), caught_exc ) six.raise_from(new_exc, caught_exc) + return _load_credentials_from_info( + filename, info, scopes, default_scopes, quota_project_id, request + ) + - # The type key should indicate that the file is either a service account - # credentials file or an authorized user credentials file. +def _load_credentials_from_info( + filename, info, scopes, default_scopes, quota_project_id, request +): credential_type = info.get("type") if credential_type == _AUTHORIZED_USER_TYPE: - from google.oauth2 import credentials - - try: - credentials = credentials.Credentials.from_authorized_user_info( - info, scopes=scopes - ) - except ValueError as caught_exc: - msg = "Failed to load authorized user credentials from {}".format(filename) - new_exc = exceptions.DefaultCredentialsError(msg, caught_exc) - six.raise_from(new_exc, caught_exc) - if quota_project_id: - credentials = credentials.with_quota_project(quota_project_id) - if not credentials.quota_project_id: - _warn_about_problematic_credentials(credentials) - return credentials, None + credentials, project_id = _get_authorized_user_credentials( + filename, info, scopes + ) elif credential_type == _SERVICE_ACCOUNT_TYPE: - from google.oauth2 import service_account - - try: - credentials = service_account.Credentials.from_service_account_info( - info, scopes=scopes, default_scopes=default_scopes - ) - except ValueError as caught_exc: - msg = "Failed to load service account credentials from {}".format(filename) - new_exc = exceptions.DefaultCredentialsError(msg, caught_exc) - six.raise_from(new_exc, caught_exc) - if quota_project_id: - credentials = credentials.with_quota_project(quota_project_id) - return credentials, info.get("project_id") + credentials, project_id = _get_service_account_credentials( + filename, info, scopes, default_scopes + ) elif credential_type == _EXTERNAL_ACCOUNT_TYPE: credentials, project_id = _get_external_account_credentials( @@ -164,10 +154,10 @@ def load_credentials_from_file( default_scopes=default_scopes, request=request, ) - if quota_project_id: - credentials = credentials.with_quota_project(quota_project_id) - return credentials, project_id - + elif credential_type == _IMPERSONATED_SERVICE_ACCOUNT_TYPE: + credentials, project_id = _get_impersonated_service_account_credentials( + filename, info, scopes + ) else: raise exceptions.DefaultCredentialsError( "The file {file} does not have a valid type. " @@ -175,6 +165,8 @@ def load_credentials_from_file( file=filename, type=credential_type, valid_types=_VALID_TYPES ) ) + credentials = _apply_quota_project_id(credentials, quota_project_id) + return credentials, project_id def _get_gcloud_sdk_credentials(quota_project_id=None): @@ -371,6 +363,93 @@ def get_api_key_credentials(api_key_value): return api_key.Credentials(api_key_value) +def _get_authorized_user_credentials(filename, info, scopes=None): + from google.oauth2 import credentials + + try: + credentials = credentials.Credentials.from_authorized_user_info( + info, scopes=scopes + ) + except ValueError as caught_exc: + msg = "Failed to load authorized user credentials from {}".format(filename) + new_exc = exceptions.DefaultCredentialsError(msg, caught_exc) + six.raise_from(new_exc, caught_exc) + return credentials, None + + +def _get_service_account_credentials(filename, info, scopes=None, default_scopes=None): + from google.oauth2 import service_account + + try: + credentials = service_account.Credentials.from_service_account_info( + info, scopes=scopes, default_scopes=default_scopes + ) + except ValueError as caught_exc: + msg = "Failed to load service account credentials from {}".format(filename) + new_exc = exceptions.DefaultCredentialsError(msg, caught_exc) + six.raise_from(new_exc, caught_exc) + return credentials, info.get("project_id") + + +def _get_impersonated_service_account_credentials(filename, info, scopes): + from google.auth import impersonated_credentials + + try: + source_credentials_info = info.get("source_credentials") + source_credentials_type = source_credentials_info.get("type") + if source_credentials_type == _AUTHORIZED_USER_TYPE: + source_credentials, _ = _get_authorized_user_credentials( + filename, source_credentials_info + ) + elif source_credentials_type == _SERVICE_ACCOUNT_TYPE: + source_credentials, _ = _get_service_account_credentials( + filename, source_credentials_info + ) + else: + raise ValueError( + "source credential of type {} is not supported.".format( + source_credentials_type + ) + ) + impersonation_url = info.get("service_account_impersonation_url") + start_index = impersonation_url.rfind("/") + end_index = impersonation_url.find(":generateAccessToken") + if start_index == -1 or end_index == -1 or start_index > end_index: + raise ValueError( + "Cannot extract target principal from {}".format(impersonation_url) + ) + target_principal = impersonation_url[start_index + 1 : end_index] + delegates = info.get("delegates") + quota_project_id = info.get("quota_project_id") + credentials = impersonated_credentials.Credentials( + source_credentials, + target_principal, + scopes, + delegates, + quota_project_id=quota_project_id, + ) + except ValueError as caught_exc: + msg = "Failed to load impersonated service account credentials from {}".format( + filename + ) + new_exc = exceptions.DefaultCredentialsError(msg, caught_exc) + six.raise_from(new_exc, caught_exc) + return credentials, None + + +def _apply_quota_project_id(credentials, quota_project_id): + if quota_project_id: + credentials = credentials.with_quota_project(quota_project_id) + + from google.oauth2 import credentials as authorized_user_credentials + + if isinstance(credentials, authorized_user_credentials.Credentials) and ( + not credentials.quota_project_id + ): + _warn_about_problematic_credentials(credentials) + return credentials + + def default(scopes=None, request=None, quota_project_id=None, default_scopes=None): """Gets the default credentials for the current environment. diff --git a/tests/data/impersonated_service_account_authorized_user_source.json b/tests/data/impersonated_service_account_authorized_user_source.json new file mode 100644 index 000000000..0e545392c --- /dev/null +++ b/tests/data/impersonated_service_account_authorized_user_source.json @@ -0,0 +1,13 @@ +{ + "delegates": [ + "service-account-delegate@example.com" + ], + "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/service-account-target@example.com:generateAccessToken", + "source_credentials": { + "client_id": "123", + "client_secret": "secret", + "refresh_token": "alabalaportocala", + "type": "authorized_user" + }, + "type": "impersonated_service_account" +} \ No newline at end of file diff --git a/tests/data/impersonated_service_account_service_account_source.json b/tests/data/impersonated_service_account_service_account_source.json new file mode 100644 index 000000000..e1ff8e81f --- /dev/null +++ b/tests/data/impersonated_service_account_service_account_source.json @@ -0,0 +1,17 @@ +{ + "delegates": [ + "service-account-delegate@example.com" + ], + "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/service-account-target@example.com:generateAccessToken", + "source_credentials": { + "type": "service_account", + "project_id": "example-project", + "private_key_id": "1", + "private_key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEA4ej0p7bQ7L/r4rVGUz9RN4VQWoej1Bg1mYWIDYslvKrk1gpj\n7wZgkdmM7oVK2OfgrSj/FCTkInKPqaCR0gD7K80q+mLBrN3PUkDrJQZpvRZIff3/\nxmVU1WeruQLFJjnFb2dqu0s/FY/2kWiJtBCakXvXEOb7zfbINuayL+MSsCGSdVYs\nSliS5qQpgyDap+8b5fpXZVJkq92hrcNtbkg7hCYUJczt8n9hcCTJCfUpApvaFQ18\npe+zpyl4+WzkP66I28hniMQyUlA1hBiskT7qiouq0m8IOodhv2fagSZKjOTTU2xk\nSBc//fy3ZpsL7WqgsZS7Q+0VRK8gKfqkxg5OYQIDAQABAoIBAQDGGHzQxGKX+ANk\nnQi53v/c6632dJKYXVJC+PDAz4+bzU800Y+n/bOYsWf/kCp94XcG4Lgsdd0Gx+Zq\nHD9CI1IcqqBRR2AFscsmmX6YzPLTuEKBGMW8twaYy3utlFxElMwoUEsrSWRcCA1y\nnHSDzTt871c7nxCXHxuZ6Nm/XCL7Bg8uidRTSC1sQrQyKgTPhtQdYrPQ4WZ1A4J9\nIisyDYmZodSNZe5P+LTJ6M1SCgH8KH9ZGIxv3diMwzNNpk3kxJc9yCnja4mjiGE2\nYCNusSycU5IhZwVeCTlhQGcNeV/skfg64xkiJE34c2y2ttFbdwBTPixStGaF09nU\nZ422D40BAoGBAPvVyRRsC3BF+qZdaSMFwI1yiXY7vQw5+JZh01tD28NuYdRFzjcJ\nvzT2n8LFpj5ZfZFvSMLMVEFVMgQvWnN0O6xdXvGov6qlRUSGaH9u+TCPNnIldjMP\nB8+xTwFMqI7uQr54wBB+Poq7dVRP+0oHb0NYAwUBXoEuvYo3c/nDoRcZAoGBAOWl\naLHjMv4CJbArzT8sPfic/8waSiLV9Ixs3Re5YREUTtnLq7LoymqB57UXJB3BNz/2\neCueuW71avlWlRtE/wXASj5jx6y5mIrlV4nZbVuyYff0QlcG+fgb6pcJQuO9DxMI\naqFGrWP3zye+LK87a6iR76dS9vRU+bHZpSVvGMKJAoGAFGt3TIKeQtJJyqeUWNSk\nklORNdcOMymYMIlqG+JatXQD1rR6ThgqOt8sgRyJqFCVT++YFMOAqXOBBLnaObZZ\nCFbh1fJ66BlSjoXff0W+SuOx5HuJJAa5+WtFHrPajwxeuRcNa8jwxUsB7n41wADu\nUqWWSRedVBg4Ijbw3nWwYDECgYB0pLew4z4bVuvdt+HgnJA9n0EuYowVdadpTEJg\nsoBjNHV4msLzdNqbjrAqgz6M/n8Ztg8D2PNHMNDNJPVHjJwcR7duSTA6w2p/4k28\nbvvk/45Ta3XmzlxZcZSOct3O31Cw0i2XDVc018IY5be8qendDYM08icNo7vQYkRH\n504kQQKBgQDjx60zpz8ozvm1XAj0wVhi7GwXe+5lTxiLi9Fxq721WDxPMiHDW2XL\nYXfFVy/9/GIMvEiGYdmarK1NW+VhWl1DC5xhDg0kvMfxplt4tynoq1uTsQTY31Mx\nBeF5CT/JuNYk3bEBF0H/Q3VGO1/ggVS+YezdFbLWIRoMnLj6XCFEGg==\n-----END RSA PRIVATE KEY-----\n", + "client_email": "service-account@example.com", + "client_id": "1234", + "auth_uri": "https://accounts.google.com/o/oauth2/auth", + "token_uri": "https://accounts.google.com/o/oauth2/token" + }, + "type": "impersonated_service_account" +} \ No newline at end of file diff --git a/tests/data/impersonated_service_account_with_quota_project.json b/tests/data/impersonated_service_account_with_quota_project.json new file mode 100644 index 000000000..89db9617c --- /dev/null +++ b/tests/data/impersonated_service_account_with_quota_project.json @@ -0,0 +1,14 @@ +{ + "delegates": [ + "service-account-delegate@example.com" + ], + "quota_project_id": "quota_project", + "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/service-account-target@example.com:generateAccessToken", + "source_credentials": { + "client_id": "123", + "client_secret": "secret", + "refresh_token": "alabalaportocala", + "type": "authorized_user" + }, + "type": "impersonated_service_account" +} \ No newline at end of file diff --git a/tests/test__default.py b/tests/test__default.py index 67795ef02..1c27ac11c 100644 --- a/tests/test__default.py +++ b/tests/test__default.py @@ -28,6 +28,7 @@ from google.auth import exceptions from google.auth import external_account from google.auth import identity_pool +from google.auth import impersonated_credentials from google.oauth2 import service_account import google.oauth2.credentials @@ -128,6 +129,19 @@ "workforce_pool_user_project": WORKFORCE_POOL_USER_PROJECT, } +IMPERSONATED_SERVICE_ACCOUNT_AUTHORIZED_USER_SOURCE_FILE = os.path.join( + DATA_DIR, "impersonated_service_account_authorized_user_source.json" +) + +IMPERSONATED_SERVICE_ACCOUNT_WITH_QUOTA_PROJECT_FILE = os.path.join( + DATA_DIR, "impersonated_service_account_with_quota_project.json" +) + +IMPERSONATED_SERVICE_ACCOUNT_SERVICE_ACCOUNT_SOURCE_FILE = os.path.join( + DATA_DIR, "impersonated_service_account_service_account_source.json" +) + + MOCK_CREDENTIALS = mock.Mock(spec=credentials.CredentialsWithQuotaProject) MOCK_CREDENTIALS.with_quota_project.return_value = MOCK_CREDENTIALS @@ -278,6 +292,84 @@ def test_load_credentials_from_file_service_account_bad_format(tmpdir): assert excinfo.match(r"missing fields") +def test_load_credentials_from_file_impersonated_with_authorized_user_source(): + credentials, project_id = _default.load_credentials_from_file( + IMPERSONATED_SERVICE_ACCOUNT_AUTHORIZED_USER_SOURCE_FILE + ) + assert isinstance(credentials, impersonated_credentials.Credentials) + assert isinstance( + credentials._source_credentials, google.oauth2.credentials.Credentials + ) + assert credentials.service_account_email == "service-account-target@example.com" + assert credentials._delegates == ["service-account-delegate@example.com"] + assert not credentials._quota_project_id + assert not credentials._target_scopes + assert project_id is None + + +def test_load_credentials_from_file_impersonated_with_quota_project(): + credentials, _ = _default.load_credentials_from_file( + IMPERSONATED_SERVICE_ACCOUNT_WITH_QUOTA_PROJECT_FILE + ) + assert isinstance(credentials, impersonated_credentials.Credentials) + assert credentials._quota_project_id == "quota_project" + + +def test_load_credentials_from_file_impersonated_with_service_account_source(): + credentials, _ = _default.load_credentials_from_file( + IMPERSONATED_SERVICE_ACCOUNT_SERVICE_ACCOUNT_SOURCE_FILE + ) + assert isinstance(credentials, impersonated_credentials.Credentials) + assert isinstance(credentials._source_credentials, service_account.Credentials) + assert not credentials._quota_project_id + + +def test_load_credentials_from_file_impersonated_passing_quota_project(): + credentials, _ = _default.load_credentials_from_file( + IMPERSONATED_SERVICE_ACCOUNT_SERVICE_ACCOUNT_SOURCE_FILE, + quota_project_id="new_quota_project", + ) + assert credentials._quota_project_id == "new_quota_project" + + +def test_load_credentials_from_file_impersonated_passing_scopes(): + credentials, _ = _default.load_credentials_from_file( + IMPERSONATED_SERVICE_ACCOUNT_SERVICE_ACCOUNT_SOURCE_FILE, + scopes=["scope1", "scope2"], + ) + assert credentials._target_scopes == ["scope1", "scope2"] + + +def test_load_credentials_from_file_impersonated_wrong_target_principal(tmpdir): + + with open(IMPERSONATED_SERVICE_ACCOUNT_AUTHORIZED_USER_SOURCE_FILE) as fh: + impersonated_credentials_info = json.load(fh) + impersonated_credentials_info[ + "service_account_impersonation_url" + ] = "something_wrong" + + jsonfile = tmpdir.join("invalid.json") + jsonfile.write(json.dumps(impersonated_credentials_info)) + with pytest.raises(exceptions.DefaultCredentialsError) as excinfo: + _default.load_credentials_from_file(str(jsonfile)) + + assert excinfo.match(r"Cannot extract target principal") + + +def test_load_credentials_from_file_impersonated_wrong_source_type(tmpdir): + + with open(IMPERSONATED_SERVICE_ACCOUNT_AUTHORIZED_USER_SOURCE_FILE) as fh: + impersonated_credentials_info = json.load(fh) + impersonated_credentials_info["source_credentials"]["type"] = "external_account" + + jsonfile = tmpdir.join("invalid.json") + jsonfile.write(json.dumps(impersonated_credentials_info)) + with pytest.raises(exceptions.DefaultCredentialsError) as excinfo: + _default.load_credentials_from_file(str(jsonfile)) + + assert excinfo.match(r"source credential of type external_account is not supported") + + @EXTERNAL_ACCOUNT_GET_PROJECT_ID_PATCH def test_load_credentials_from_file_external_account_identity_pool( get_project_id, tmpdir From 3c9feff3e9037a15bf07496623e3a810f117adcf Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 25 Jan 2022 13:24:19 -0800 Subject: [PATCH 3/3] chore(main): release 2.5.0 (#960) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- CHANGELOG.md | 7 +++++++ google/auth/version.py | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a93eece7d..9249639b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ [1]: https://pypi.org/project/google-auth/#history +## [2.5.0](https://github.com/googleapis/google-auth-library-python/compare/v2.4.1...v2.5.0) (2022-01-25) + + +### Features + +* ADC can load an impersonated service account credentials. ([#956](https://github.com/googleapis/google-auth-library-python/issues/956)) ([a8eb4c8](https://github.com/googleapis/google-auth-library-python/commit/a8eb4c8693055a3420cfe9c3420aae2bc8cd465a)) + ### [2.4.1](https://github.com/googleapis/google-auth-library-python/compare/v2.4.0...v2.4.1) (2022-01-21) diff --git a/google/auth/version.py b/google/auth/version.py index 9ccf875c0..e6c150fc9 100644 --- a/google/auth/version.py +++ b/google/auth/version.py @@ -12,4 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -__version__ = "2.4.1" +__version__ = "2.5.0"