summaryrefslogtreecommitdiffstats
path: root/contrib/python/google-auth/py3/tests
diff options
context:
space:
mode:
authorrobot-piglet <[email protected]>2025-04-29 13:13:02 +0300
committerrobot-piglet <[email protected]>2025-04-29 13:30:37 +0300
commit43c48235ff779855489561438e0ba08bd8dfb4fc (patch)
tree38288f51b582424c1fc554aab78a5e27f303d72a /contrib/python/google-auth/py3/tests
parent46634855c4eebcbf9416afe1bd0448058aa40373 (diff)
Intermediate changes
commit_hash:8152cafb3d167774615b4df5bf4470b6269e88a7
Diffstat (limited to 'contrib/python/google-auth/py3/tests')
-rw-r--r--contrib/python/google-auth/py3/tests/compute_engine/test__metadata.py26
-rw-r--r--contrib/python/google-auth/py3/tests/data/trust_chain_with_leaf.pem52
-rw-r--r--contrib/python/google-auth/py3/tests/data/trust_chain_without_leaf.pem33
-rw-r--r--contrib/python/google-auth/py3/tests/data/trust_chain_wrong_order.pem52
-rw-r--r--contrib/python/google-auth/py3/tests/oauth2/test_id_token.py15
-rw-r--r--contrib/python/google-auth/py3/tests/test__oauth2client.py16
-rw-r--r--contrib/python/google-auth/py3/tests/test_identity_pool.py157
-rw-r--r--contrib/python/google-auth/py3/tests/test_impersonated_credentials.py39
8 files changed, 388 insertions, 2 deletions
diff --git a/contrib/python/google-auth/py3/tests/compute_engine/test__metadata.py b/contrib/python/google-auth/py3/tests/compute_engine/test__metadata.py
index a768b17fa0d..98d08fe4505 100644
--- a/contrib/python/google-auth/py3/tests/compute_engine/test__metadata.py
+++ b/contrib/python/google-auth/py3/tests/compute_engine/test__metadata.py
@@ -176,6 +176,7 @@ def test_get_success_json():
method="GET",
url=_metadata._METADATA_ROOT + PATH,
headers=_metadata._METADATA_HEADERS,
+ timeout=_metadata._METADATA_DEFAULT_TIMEOUT,
)
assert result[key] == value
@@ -194,6 +195,7 @@ def test_get_success_json_content_type_charset():
method="GET",
url=_metadata._METADATA_ROOT + PATH,
headers=_metadata._METADATA_HEADERS,
+ timeout=_metadata._METADATA_DEFAULT_TIMEOUT,
)
assert result[key] == value
@@ -213,6 +215,7 @@ def test_get_success_retry(mock_sleep):
method="GET",
url=_metadata._METADATA_ROOT + PATH,
headers=_metadata._METADATA_HEADERS,
+ timeout=_metadata._METADATA_DEFAULT_TIMEOUT,
)
assert request.call_count == 2
assert result[key] == value
@@ -228,6 +231,7 @@ def test_get_success_text():
method="GET",
url=_metadata._METADATA_ROOT + PATH,
headers=_metadata._METADATA_HEADERS,
+ timeout=_metadata._METADATA_DEFAULT_TIMEOUT,
)
assert result == data
@@ -243,6 +247,7 @@ def test_get_success_params():
method="GET",
url=_metadata._METADATA_ROOT + PATH + "?recursive=true",
headers=_metadata._METADATA_HEADERS,
+ timeout=_metadata._METADATA_DEFAULT_TIMEOUT,
)
assert result == data
@@ -257,6 +262,7 @@ def test_get_success_recursive_and_params():
method="GET",
url=_metadata._METADATA_ROOT + PATH + "?recursive=true",
headers=_metadata._METADATA_HEADERS,
+ timeout=_metadata._METADATA_DEFAULT_TIMEOUT,
)
assert result == data
@@ -271,6 +277,7 @@ def test_get_success_recursive():
method="GET",
url=_metadata._METADATA_ROOT + PATH + "?recursive=true",
headers=_metadata._METADATA_HEADERS,
+ timeout=_metadata._METADATA_DEFAULT_TIMEOUT,
)
assert result == data
@@ -292,6 +299,7 @@ def _test_get_success_custom_root_new_variable():
method="GET",
url="http://{}/computeMetadata/v1/{}".format(fake_root, PATH),
headers=_metadata._METADATA_HEADERS,
+ timeout=_metadata._METADATA_DEFAULT_TIMEOUT,
)
@@ -312,6 +320,7 @@ def _test_get_success_custom_root_old_variable():
method="GET",
url="http://{}/computeMetadata/v1/{}".format(fake_root, PATH),
headers=_metadata._METADATA_HEADERS,
+ timeout=_metadata._METADATA_DEFAULT_TIMEOUT,
)
@@ -328,6 +337,7 @@ def test_get_failure(mock_sleep):
method="GET",
url=_metadata._METADATA_ROOT + PATH,
headers=_metadata._METADATA_HEADERS,
+ timeout=_metadata._METADATA_DEFAULT_TIMEOUT,
)
@@ -340,6 +350,7 @@ def test_get_return_none_for_not_found_error():
method="GET",
url=_metadata._METADATA_ROOT + PATH,
headers=_metadata._METADATA_HEADERS,
+ timeout=_metadata._METADATA_DEFAULT_TIMEOUT,
)
@@ -359,6 +370,7 @@ def test_get_failure_connection_failed(mock_sleep):
method="GET",
url=_metadata._METADATA_ROOT + PATH,
headers=_metadata._METADATA_HEADERS,
+ timeout=_metadata._METADATA_DEFAULT_TIMEOUT,
)
assert request.call_count == 5
@@ -377,6 +389,7 @@ def test_get_too_many_requests_retryable_error_failure():
method="GET",
url=_metadata._METADATA_ROOT + PATH,
headers=_metadata._METADATA_HEADERS,
+ timeout=_metadata._METADATA_DEFAULT_TIMEOUT,
)
assert request.call_count == 5
@@ -393,6 +406,7 @@ def test_get_failure_bad_json():
method="GET",
url=_metadata._METADATA_ROOT + PATH,
headers=_metadata._METADATA_HEADERS,
+ timeout=_metadata._METADATA_DEFAULT_TIMEOUT,
)
@@ -406,6 +420,7 @@ def test_get_project_id():
method="GET",
url=_metadata._METADATA_ROOT + "project/project-id",
headers=_metadata._METADATA_HEADERS,
+ timeout=_metadata._METADATA_DEFAULT_TIMEOUT,
)
assert project_id == project
@@ -421,6 +436,7 @@ def test_get_universe_domain_success():
method="GET",
url=_metadata._METADATA_ROOT + "universe/universe-domain",
headers=_metadata._METADATA_HEADERS,
+ timeout=_metadata._METADATA_DEFAULT_TIMEOUT,
)
assert universe_domain == "fake_universe_domain"
@@ -434,6 +450,7 @@ def test_get_universe_domain_success_empty_response():
method="GET",
url=_metadata._METADATA_ROOT + "universe/universe-domain",
headers=_metadata._METADATA_HEADERS,
+ timeout=_metadata._METADATA_DEFAULT_TIMEOUT,
)
assert universe_domain == "googleapis.com"
@@ -449,6 +466,7 @@ def test_get_universe_domain_not_found():
method="GET",
url=_metadata._METADATA_ROOT + "universe/universe-domain",
headers=_metadata._METADATA_HEADERS,
+ timeout=_metadata._METADATA_DEFAULT_TIMEOUT,
)
assert universe_domain == "googleapis.com"
@@ -469,6 +487,7 @@ def test_get_universe_domain_retryable_error_failure():
method="GET",
url=_metadata._METADATA_ROOT + "universe/universe-domain",
headers=_metadata._METADATA_HEADERS,
+ timeout=_metadata._METADATA_DEFAULT_TIMEOUT,
)
assert request.call_count == 5
@@ -511,11 +530,13 @@ def test_get_universe_domain_retryable_error_success():
method="GET",
url=_metadata._METADATA_ROOT + "universe/universe-domain",
headers=_metadata._METADATA_HEADERS,
+ timeout=_metadata._METADATA_DEFAULT_TIMEOUT,
)
request_ok.assert_called_once_with(
method="GET",
url=_metadata._METADATA_ROOT + "universe/universe-domain",
headers=_metadata._METADATA_HEADERS,
+ timeout=_metadata._METADATA_DEFAULT_TIMEOUT,
)
assert universe_domain == "fake_universe_domain"
@@ -535,6 +556,7 @@ def test_get_universe_domain_other_error():
method="GET",
url=_metadata._METADATA_ROOT + "universe/universe-domain",
headers=_metadata._METADATA_HEADERS,
+ timeout=_metadata._METADATA_DEFAULT_TIMEOUT,
)
@@ -559,6 +581,7 @@ def test_get_service_account_token(utcnow, mock_metrics_header_value):
"metadata-flavor": "Google",
"x-goog-api-client": ACCESS_TOKEN_REQUEST_METRICS_HEADER_VALUE,
},
+ timeout=_metadata._METADATA_DEFAULT_TIMEOUT,
)
assert token == "token"
assert expiry == utcnow() + datetime.timedelta(seconds=ttl)
@@ -585,6 +608,7 @@ def test_get_service_account_token_with_scopes_list(utcnow, mock_metrics_header_
"metadata-flavor": "Google",
"x-goog-api-client": ACCESS_TOKEN_REQUEST_METRICS_HEADER_VALUE,
},
+ timeout=_metadata._METADATA_DEFAULT_TIMEOUT,
)
assert token == "token"
assert expiry == utcnow() + datetime.timedelta(seconds=ttl)
@@ -613,6 +637,7 @@ def test_get_service_account_token_with_scopes_string(
"metadata-flavor": "Google",
"x-goog-api-client": ACCESS_TOKEN_REQUEST_METRICS_HEADER_VALUE,
},
+ timeout=_metadata._METADATA_DEFAULT_TIMEOUT,
)
assert token == "token"
assert expiry == utcnow() + datetime.timedelta(seconds=ttl)
@@ -630,6 +655,7 @@ def test_get_service_account_info():
method="GET",
url=_metadata._METADATA_ROOT + PATH + "/?recursive=true",
headers=_metadata._METADATA_HEADERS,
+ timeout=_metadata._METADATA_DEFAULT_TIMEOUT,
)
assert info[key] == value
diff --git a/contrib/python/google-auth/py3/tests/data/trust_chain_with_leaf.pem b/contrib/python/google-auth/py3/tests/data/trust_chain_with_leaf.pem
new file mode 100644
index 00000000000..250387d9d59
--- /dev/null
+++ b/contrib/python/google-auth/py3/tests/data/trust_chain_with_leaf.pem
@@ -0,0 +1,52 @@
+-----BEGIN CERTIFICATE-----
+MIIDIzCCAgugAwIBAgIJAMfISuBQ5m+5MA0GCSqGSIb3DQEBBQUAMBUxEzARBgNV
+BAMTCnVuaXQtdGVzdHMwHhcNMTExMjA2MTYyNjAyWhcNMjExMjAzMTYyNjAyWjAV
+MRMwEQYDVQQDEwp1bml0LXRlc3RzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEA4ej0p7bQ7L/r4rVGUz9RN4VQWoej1Bg1mYWIDYslvKrk1gpj7wZgkdmM
+7oVK2OfgrSj/FCTkInKPqaCR0gD7K80q+mLBrN3PUkDrJQZpvRZIff3/xmVU1Wer
+uQLFJjnFb2dqu0s/FY/2kWiJtBCakXvXEOb7zfbINuayL+MSsCGSdVYsSliS5qQp
+gyDap+8b5fpXZVJkq92hrcNtbkg7hCYUJczt8n9hcCTJCfUpApvaFQ18pe+zpyl4
++WzkP66I28hniMQyUlA1hBiskT7qiouq0m8IOodhv2fagSZKjOTTU2xkSBc//fy3
+ZpsL7WqgsZS7Q+0VRK8gKfqkxg5OYQIDAQABo3YwdDAdBgNVHQ4EFgQU2RQ8yO+O
+gN8oVW2SW7RLrfYd9jEwRQYDVR0jBD4wPIAU2RQ8yO+OgN8oVW2SW7RLrfYd9jGh
+GaQXMBUxEzARBgNVBAMTCnVuaXQtdGVzdHOCCQDHyErgUOZvuTAMBgNVHRMEBTAD
+AQH/MA0GCSqGSIb3DQEBBQUAA4IBAQBRv+M/6+FiVu7KXNjFI5pSN17OcW5QUtPr
+odJMlWrJBtynn/TA1oJlYu3yV5clc/71Vr/AxuX5xGP+IXL32YDF9lTUJXG/uUGk
++JETpKmQviPbRsvzYhz4pf6ZIOZMc3/GIcNq92ECbseGO+yAgyWUVKMmZM0HqXC9
+ovNslqe0M8C1sLm1zAR5z/h/litE7/8O2ietija3Q/qtl2TOXJdCA6sgjJX2WUql
+ybrC55ct18NKf3qhpcEkGQvFU40rVYApJpi98DiZPYFdx1oBDp/f4uZ3ojpxRVFT
+cDwcJLfNRCPUhormsY7fDS9xSyThiHsW9mjJYdcaKQkwYZ0F11yB
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIFtTCCA52gAwIBAgIJAPBsLZmNGfKtMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
+BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX
+aWRnaXRzIFB0eSBMdGQwHhcNMTYwOTIxMDI0NTEyWhcNMTYxMDIxMDI0NTEyWjBF
+MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50
+ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
+CgKCAgEAsiMC7mTsmUXwZoYlT4aHY1FLw8bxIXC+z3IqA+TY1WqfbeiZRo8MA5Zx
+lTTxYMKPCZUE1XBc7jvD8GJhWIj6pToPYHn73B01IBkLBxq4kF1yV2Z7DVmkvc6H
+EcxXXq8zkCx0j6XOfiI4+qkXnuQn8cvrk8xfhtnMMZM7iVm6VSN93iRP/8ey6xuL
+XTHrDX7ukoRce1hpT8O+15GXNrY0irhhYQz5xKibNCJF3EjV28WMry8y7I8uYUFU
+RWDiQawwK9ec1zhZ94v92+GZDlPevmcFmSERKYQ0NsKcT0Y3lGuGnaExs8GyOpnC
+oksu4YJGXQjg7lkv4MxzsNbRqmCkUwxw1Mg6FP0tsCNsw9qTrkvWCRA9zp/aU+sZ
+IBGh1t4UGCub8joeQFvHxvr/3F7mH/dyvCjA34u0Lo1VPx+jYUIi9i0odltMspDW
+xOpjqdGARZYmlJP5Au9q5cQjPMcwS/EBIb8cwNl32mUE6WnFlep+38mNR/FghIjO
+ViAkXuKQmcHe6xppZAoHFsO/t3l4Tjek5vNW7erI1rgrFku/fvkIW/G8V1yIm/+Q
+F+CE4maQzCJfhftpkhM/sPC/FuLNBmNE8BHVX8y58xG4is/cQxL4Z9TsFIw0C5+3
+uTrFW9D0agysahMVzPGtCqhDQqJdIJrBQqlS6bztpzBA8zEI0skCAwEAAaOBpzCB
+pDAdBgNVHQ4EFgQUz/8FmW6TfqXyNJZr7rhc+Tn5sKQwdQYDVR0jBG4wbIAUz/8F
+mW6TfqXyNJZr7rhc+Tn5sKShSaRHMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpT
+b21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGSCCQDw
+bC2ZjRnyrTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4ICAQCQmrcfhurX
+riR3Q0Y+nq040/3dJIAJXjyI9CEtxaU0nzCNTng7PwgZ0CKmCelQfInuwWFwBSHS
+6kBfC1rgJeFnjnTt8a3RCgRlIgUr9NCdPSEccB7TurobwPJ2h6cJjjR8urcb0CXh
+CEMvPneyPj0xUFY8vVKXMGWahz/kyfwIiVqcX/OtMZ29fUu1onbWl71g2gVLtUZl
+sECdZ+AC/6HDCVpYIVETMl1T7N/XyqXZQiDLDNRDeZhnapz8w9fsW1KVujAZLNQR
+pVnw2qa2UK1dSf2FHX+lQU5mFSYM4vtwaMlX/LgfdLZ9I796hFh619WwTVz+LO2N
+vHnwBMabld3XSPuZRqlbBulDQ07Vbqdjv8DYSLA2aKI4ZkMMKuFLG/oS28V2ZYmv
+/KpGEs5UgKY+P9NulYpTDwCU/6SomuQpP795wbG6sm7Hzq82r2RmB61GupNRGeqi
+pXKsy69T388zBxYu6zQrosXiDl5YzaViH7tm0J7opye8dCWjjpnahki0vq2znti7
+6cWla2j8Xz1glvLz+JI/NCOMfxUInb82T7ijo80N0VJ2hzf7p2GxRZXAxAV9knLI
+nM4F5TLjSd7ZhOOZ7ni/eZFueTMisWfypt2nc41whGjHMX/Zp1kPfhB4H2bLKIX/
+lSrwNr3qbGTEJX8JqpDBNVAd96XkMvDNyA==
+-----END CERTIFICATE----- \ No newline at end of file
diff --git a/contrib/python/google-auth/py3/tests/data/trust_chain_without_leaf.pem b/contrib/python/google-auth/py3/tests/data/trust_chain_without_leaf.pem
new file mode 100644
index 00000000000..9da0f37fedf
--- /dev/null
+++ b/contrib/python/google-auth/py3/tests/data/trust_chain_without_leaf.pem
@@ -0,0 +1,33 @@
+-----BEGIN CERTIFICATE-----
+MIIFtTCCA52gAwIBAgIJAPBsLZmNGfKtMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
+BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX
+aWRnaXRzIFB0eSBMdGQwHhcNMTYwOTIxMDI0NTEyWhcNMTYxMDIxMDI0NTEyWjBF
+MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50
+ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
+CgKCAgEAsiMC7mTsmUXwZoYlT4aHY1FLw8bxIXC+z3IqA+TY1WqfbeiZRo8MA5Zx
+lTTxYMKPCZUE1XBc7jvD8GJhWIj6pToPYHn73B01IBkLBxq4kF1yV2Z7DVmkvc6H
+EcxXXq8zkCx0j6XOfiI4+qkXnuQn8cvrk8xfhtnMMZM7iVm6VSN93iRP/8ey6xuL
+XTHrDX7ukoRce1hpT8O+15GXNrY0irhhYQz5xKibNCJF3EjV28WMry8y7I8uYUFU
+RWDiQawwK9ec1zhZ94v92+GZDlPevmcFmSERKYQ0NsKcT0Y3lGuGnaExs8GyOpnC
+oksu4YJGXQjg7lkv4MxzsNbRqmCkUwxw1Mg6FP0tsCNsw9qTrkvWCRA9zp/aU+sZ
+IBGh1t4UGCub8joeQFvHxvr/3F7mH/dyvCjA34u0Lo1VPx+jYUIi9i0odltMspDW
+xOpjqdGARZYmlJP5Au9q5cQjPMcwS/EBIb8cwNl32mUE6WnFlep+38mNR/FghIjO
+ViAkXuKQmcHe6xppZAoHFsO/t3l4Tjek5vNW7erI1rgrFku/fvkIW/G8V1yIm/+Q
+F+CE4maQzCJfhftpkhM/sPC/FuLNBmNE8BHVX8y58xG4is/cQxL4Z9TsFIw0C5+3
+uTrFW9D0agysahMVzPGtCqhDQqJdIJrBQqlS6bztpzBA8zEI0skCAwEAAaOBpzCB
+pDAdBgNVHQ4EFgQUz/8FmW6TfqXyNJZr7rhc+Tn5sKQwdQYDVR0jBG4wbIAUz/8F
+mW6TfqXyNJZr7rhc+Tn5sKShSaRHMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpT
+b21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGSCCQDw
+bC2ZjRnyrTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4ICAQCQmrcfhurX
+riR3Q0Y+nq040/3dJIAJXjyI9CEtxaU0nzCNTng7PwgZ0CKmCelQfInuwWFwBSHS
+6kBfC1rgJeFnjnTt8a3RCgRlIgUr9NCdPSEccB7TurobwPJ2h6cJjjR8urcb0CXh
+CEMvPneyPj0xUFY8vVKXMGWahz/kyfwIiVqcX/OtMZ29fUu1onbWl71g2gVLtUZl
+sECdZ+AC/6HDCVpYIVETMl1T7N/XyqXZQiDLDNRDeZhnapz8w9fsW1KVujAZLNQR
+pVnw2qa2UK1dSf2FHX+lQU5mFSYM4vtwaMlX/LgfdLZ9I796hFh619WwTVz+LO2N
+vHnwBMabld3XSPuZRqlbBulDQ07Vbqdjv8DYSLA2aKI4ZkMMKuFLG/oS28V2ZYmv
+/KpGEs5UgKY+P9NulYpTDwCU/6SomuQpP795wbG6sm7Hzq82r2RmB61GupNRGeqi
+pXKsy69T388zBxYu6zQrosXiDl5YzaViH7tm0J7opye8dCWjjpnahki0vq2znti7
+6cWla2j8Xz1glvLz+JI/NCOMfxUInb82T7ijo80N0VJ2hzf7p2GxRZXAxAV9knLI
+nM4F5TLjSd7ZhOOZ7ni/eZFueTMisWfypt2nc41whGjHMX/Zp1kPfhB4H2bLKIX/
+lSrwNr3qbGTEJX8JqpDBNVAd96XkMvDNyA==
+-----END CERTIFICATE----- \ No newline at end of file
diff --git a/contrib/python/google-auth/py3/tests/data/trust_chain_wrong_order.pem b/contrib/python/google-auth/py3/tests/data/trust_chain_wrong_order.pem
new file mode 100644
index 00000000000..e8dc5d35931
--- /dev/null
+++ b/contrib/python/google-auth/py3/tests/data/trust_chain_wrong_order.pem
@@ -0,0 +1,52 @@
+-----BEGIN CERTIFICATE-----
+MIIFtTCCA52gAwIBAgIJAPBsLZmNGfKtMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
+BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX
+aWRnaXRzIFB0eSBMdGQwHhcNMTYwOTIxMDI0NTEyWhcNMTYxMDIxMDI0NTEyWjBF
+MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50
+ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
+CgKCAgEAsiMC7mTsmUXwZoYlT4aHY1FLw8bxIXC+z3IqA+TY1WqfbeiZRo8MA5Zx
+lTTxYMKPCZUE1XBc7jvD8GJhWIj6pToPYHn73B01IBkLBxq4kF1yV2Z7DVmkvc6H
+EcxXXq8zkCx0j6XOfiI4+qkXnuQn8cvrk8xfhtnMMZM7iVm6VSN93iRP/8ey6xuL
+XTHrDX7ukoRce1hpT8O+15GXNrY0irhhYQz5xKibNCJF3EjV28WMry8y7I8uYUFU
+RWDiQawwK9ec1zhZ94v92+GZDlPevmcFmSERKYQ0NsKcT0Y3lGuGnaExs8GyOpnC
+oksu4YJGXQjg7lkv4MxzsNbRqmCkUwxw1Mg6FP0tsCNsw9qTrkvWCRA9zp/aU+sZ
+IBGh1t4UGCub8joeQFvHxvr/3F7mH/dyvCjA34u0Lo1VPx+jYUIi9i0odltMspDW
+xOpjqdGARZYmlJP5Au9q5cQjPMcwS/EBIb8cwNl32mUE6WnFlep+38mNR/FghIjO
+ViAkXuKQmcHe6xppZAoHFsO/t3l4Tjek5vNW7erI1rgrFku/fvkIW/G8V1yIm/+Q
+F+CE4maQzCJfhftpkhM/sPC/FuLNBmNE8BHVX8y58xG4is/cQxL4Z9TsFIw0C5+3
+uTrFW9D0agysahMVzPGtCqhDQqJdIJrBQqlS6bztpzBA8zEI0skCAwEAAaOBpzCB
+pDAdBgNVHQ4EFgQUz/8FmW6TfqXyNJZr7rhc+Tn5sKQwdQYDVR0jBG4wbIAUz/8F
+mW6TfqXyNJZr7rhc+Tn5sKShSaRHMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpT
+b21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGSCCQDw
+bC2ZjRnyrTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4ICAQCQmrcfhurX
+riR3Q0Y+nq040/3dJIAJXjyI9CEtxaU0nzCNTng7PwgZ0CKmCelQfInuwWFwBSHS
+6kBfC1rgJeFnjnTt8a3RCgRlIgUr9NCdPSEccB7TurobwPJ2h6cJjjR8urcb0CXh
+CEMvPneyPj0xUFY8vVKXMGWahz/kyfwIiVqcX/OtMZ29fUu1onbWl71g2gVLtUZl
+sECdZ+AC/6HDCVpYIVETMl1T7N/XyqXZQiDLDNRDeZhnapz8w9fsW1KVujAZLNQR
+pVnw2qa2UK1dSf2FHX+lQU5mFSYM4vtwaMlX/LgfdLZ9I796hFh619WwTVz+LO2N
+vHnwBMabld3XSPuZRqlbBulDQ07Vbqdjv8DYSLA2aKI4ZkMMKuFLG/oS28V2ZYmv
+/KpGEs5UgKY+P9NulYpTDwCU/6SomuQpP795wbG6sm7Hzq82r2RmB61GupNRGeqi
+pXKsy69T388zBxYu6zQrosXiDl5YzaViH7tm0J7opye8dCWjjpnahki0vq2znti7
+6cWla2j8Xz1glvLz+JI/NCOMfxUInb82T7ijo80N0VJ2hzf7p2GxRZXAxAV9knLI
+nM4F5TLjSd7ZhOOZ7ni/eZFueTMisWfypt2nc41whGjHMX/Zp1kPfhB4H2bLKIX/
+lSrwNr3qbGTEJX8JqpDBNVAd96XkMvDNyA==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDIzCCAgugAwIBAgIJAMfISuBQ5m+5MA0GCSqGSIb3DQEBBQUAMBUxEzARBgNV
+BAMTCnVuaXQtdGVzdHMwHhcNMTExMjA2MTYyNjAyWhcNMjExMjAzMTYyNjAyWjAV
+MRMwEQYDVQQDEwp1bml0LXRlc3RzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEA4ej0p7bQ7L/r4rVGUz9RN4VQWoej1Bg1mYWIDYslvKrk1gpj7wZgkdmM
+7oVK2OfgrSj/FCTkInKPqaCR0gD7K80q+mLBrN3PUkDrJQZpvRZIff3/xmVU1Wer
+uQLFJjnFb2dqu0s/FY/2kWiJtBCakXvXEOb7zfbINuayL+MSsCGSdVYsSliS5qQp
+gyDap+8b5fpXZVJkq92hrcNtbkg7hCYUJczt8n9hcCTJCfUpApvaFQ18pe+zpyl4
++WzkP66I28hniMQyUlA1hBiskT7qiouq0m8IOodhv2fagSZKjOTTU2xkSBc//fy3
+ZpsL7WqgsZS7Q+0VRK8gKfqkxg5OYQIDAQABo3YwdDAdBgNVHQ4EFgQU2RQ8yO+O
+gN8oVW2SW7RLrfYd9jEwRQYDVR0jBD4wPIAU2RQ8yO+OgN8oVW2SW7RLrfYd9jGh
+GaQXMBUxEzARBgNVBAMTCnVuaXQtdGVzdHOCCQDHyErgUOZvuTAMBgNVHRMEBTAD
+AQH/MA0GCSqGSIb3DQEBBQUAA4IBAQBRv+M/6+FiVu7KXNjFI5pSN17OcW5QUtPr
+odJMlWrJBtynn/TA1oJlYu3yV5clc/71Vr/AxuX5xGP+IXL32YDF9lTUJXG/uUGk
++JETpKmQviPbRsvzYhz4pf6ZIOZMc3/GIcNq92ECbseGO+yAgyWUVKMmZM0HqXC9
+ovNslqe0M8C1sLm1zAR5z/h/litE7/8O2ietija3Q/qtl2TOXJdCA6sgjJX2WUql
+ybrC55ct18NKf3qhpcEkGQvFU40rVYApJpi98DiZPYFdx1oBDp/f4uZ3ojpxRVFT
+cDwcJLfNRCPUhormsY7fDS9xSyThiHsW9mjJYdcaKQkwYZ0F11yB
+-----END CERTIFICATE----- \ No newline at end of file
diff --git a/contrib/python/google-auth/py3/tests/oauth2/test_id_token.py b/contrib/python/google-auth/py3/tests/oauth2/test_id_token.py
index 65189df128c..5dc125fb566 100644
--- a/contrib/python/google-auth/py3/tests/oauth2/test_id_token.py
+++ b/contrib/python/google-auth/py3/tests/oauth2/test_id_token.py
@@ -20,6 +20,7 @@ import pytest # type: ignore
from google.auth import environment_vars
from google.auth import exceptions
+from google.auth import impersonated_credentials
from google.auth import transport
from google.oauth2 import id_token
from google.oauth2 import service_account
@@ -28,6 +29,12 @@ import yatest.common as yc
SERVICE_ACCOUNT_FILE = os.path.join(
os.path.dirname(yc.source_path(__file__)), "../data/service_account.json"
)
+
+IMPERSONATED_SERVICE_ACCOUNT_FILE = os.path.join(
+ os.path.dirname(yc.source_path(__file__)),
+ "../data/impersonated_service_account_authorized_user_source.json",
+)
+
ID_TOKEN_AUDIENCE = "https://pubsub.googleapis.com"
@@ -263,6 +270,14 @@ def test_fetch_id_token_credentials_from_explicit_cred_json_file(monkeypatch):
assert cred._target_audience == ID_TOKEN_AUDIENCE
+def test_fetch_id_token_credentials_from_impersonated_cred_json_file(monkeypatch):
+ monkeypatch.setenv(environment_vars.CREDENTIALS, IMPERSONATED_SERVICE_ACCOUNT_FILE)
+
+ cred = id_token.fetch_id_token_credentials(ID_TOKEN_AUDIENCE)
+ assert isinstance(cred, impersonated_credentials.IDTokenCredentials)
+ assert cred._target_audience == ID_TOKEN_AUDIENCE
+
+
def test_fetch_id_token_credentials_no_cred_exists(monkeypatch):
monkeypatch.delenv(environment_vars.CREDENTIALS, raising=False)
diff --git a/contrib/python/google-auth/py3/tests/test__oauth2client.py b/contrib/python/google-auth/py3/tests/test__oauth2client.py
index 1db595fd9ac..61eaf17c2de 100644
--- a/contrib/python/google-auth/py3/tests/test__oauth2client.py
+++ b/contrib/python/google-auth/py3/tests/test__oauth2client.py
@@ -117,6 +117,14 @@ def _test__convert_appengine_app_assertion_credentials(
app_identity, mock_oauth2client_gae_imports
):
+ # `oauth2client` requires `cgi` which was removed in Python 3.13
+ # See https://github.com/googleapis/oauth2client/blob/50d20532a748f18e53f7d24ccbe6647132c979a9/oauth2client/contrib/appengine.py#L20
+ # oauth2client is no longer being updated so this test must be skipped on newer Python Runtimes
+ if sys.version_info >= (3, 13): # pragma: NO COVER
+ pytest.skip(
+ "Skipping test for Python 3.13+ due to oauth2client incompatibility."
+ )
+
import oauth2client.contrib.appengine # type: ignore
service_account_id = "service_account_id"
@@ -166,6 +174,14 @@ def reset__oauth2client_module():
def _test_import_has_app_engine(
mock_oauth2client_gae_imports, reset__oauth2client_module
):
+ # `oauth2client` requires `cgi` which was removed in Python 3.13
+ # See https://github.com/googleapis/oauth2client/blob/50d20532a748f18e53f7d24ccbe6647132c979a9/oauth2client/contrib/appengine.py#L20
+ # oauth2client is no longer being updated so this test must be skipped on newer Python Runtimes
+ if sys.version_info >= (3, 13): # pragma: NO COVER
+ pytest.skip(
+ "Skipping test for Python 3.13+ due to oauth2client incompatibility."
+ )
+
importlib.reload(_oauth2client)
assert _oauth2client._HAS_APPENGINE
diff --git a/contrib/python/google-auth/py3/tests/test_identity_pool.py b/contrib/python/google-auth/py3/tests/test_identity_pool.py
index cc6cbf08827..4d78a5c22ea 100644
--- a/contrib/python/google-auth/py3/tests/test_identity_pool.py
+++ b/contrib/python/google-auth/py3/tests/test_identity_pool.py
@@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+import base64
import datetime
import http.client as http_client
import json
@@ -19,6 +20,7 @@ import os
import urllib
import mock
+from OpenSSL import crypto
import pytest # type: ignore
from google.auth import _helpers, external_account
@@ -49,6 +51,13 @@ import yatest.common as yc
DATA_DIR = os.path.join(os.path.dirname(yc.source_path(__file__)), "data")
SUBJECT_TOKEN_TEXT_FILE = os.path.join(DATA_DIR, "external_subject_token.txt")
SUBJECT_TOKEN_JSON_FILE = os.path.join(DATA_DIR, "external_subject_token.json")
+TRUST_CHAIN_WITH_LEAF_FILE = os.path.join(DATA_DIR, "trust_chain_with_leaf.pem")
+TRUST_CHAIN_WITHOUT_LEAF_FILE = os.path.join(DATA_DIR, "trust_chain_without_leaf.pem")
+TRUST_CHAIN_WRONG_ORDER_FILE = os.path.join(DATA_DIR, "trust_chain_wrong_order.pem")
+CERT_FILE = os.path.join(DATA_DIR, "public_cert.pem")
+KEY_FILE = os.path.join(DATA_DIR, "privatekey.pem")
+OTHER_CERT_FILE = os.path.join(DATA_DIR, "other_cert.pem")
+
SUBJECT_TOKEN_FIELD_NAME = "access_token"
with open(SUBJECT_TOKEN_TEXT_FILE) as fh:
@@ -58,6 +67,20 @@ with open(SUBJECT_TOKEN_JSON_FILE) as fh:
JSON_FILE_CONTENT = json.load(fh)
JSON_FILE_SUBJECT_TOKEN = JSON_FILE_CONTENT.get(SUBJECT_TOKEN_FIELD_NAME)
+with open(CERT_FILE, "rb") as f:
+ CERT_FILE_CONTENT = base64.b64encode(
+ crypto.dump_certificate(
+ crypto.FILETYPE_ASN1, crypto.load_certificate(crypto.FILETYPE_PEM, f.read())
+ )
+ ).decode("utf-8")
+
+with open(OTHER_CERT_FILE, "rb") as f:
+ OTHER_CERT_FILE_CONTENT = base64.b64encode(
+ crypto.dump_certificate(
+ crypto.FILETYPE_ASN1, crypto.load_certificate(crypto.FILETYPE_PEM, f.read())
+ )
+ ).decode("utf-8")
+
TOKEN_URL = "https://sts.googleapis.com/v1/token"
TOKEN_INFO_URL = "https://sts.googleapis.com/v1/introspect"
SUBJECT_TOKEN_TYPE = "urn:ietf:params:oauth:token-type:jwt"
@@ -186,6 +209,24 @@ class TestCredentials(object):
CREDENTIAL_SOURCE_CERTIFICATE_NOT_DEFAULT = {
"certificate": {"certificate_config_location": "path/to/config"}
}
+ CREDENTIAL_SOURCE_CERTIFICATE_TRUST_CHAIN_WITH_LEAF = {
+ "certificate": {
+ "use_default_certificate_config": "true",
+ "trust_chain_path": TRUST_CHAIN_WITH_LEAF_FILE,
+ }
+ }
+ CREDENTIAL_SOURCE_CERTIFICATE_TRUST_CHAIN_WITHOUT_LEAF = {
+ "certificate": {
+ "use_default_certificate_config": "true",
+ "trust_chain_path": TRUST_CHAIN_WITHOUT_LEAF_FILE,
+ }
+ }
+ CREDENTIAL_SOURCE_CERTIFICATE_TRUST_CHAIN_WRONG_ORDER = {
+ "certificate": {
+ "use_default_certificate_config": "true",
+ "trust_chain_path": TRUST_CHAIN_WRONG_ORDER_FILE,
+ }
+ }
SUCCESS_RESPONSE = {
"access_token": "ACCESS_TOKEN",
"issued_token_type": "urn:ietf:params:oauth:token-type:access_token",
@@ -937,14 +978,126 @@ class TestCredentials(object):
assert subject_token == JSON_FILE_SUBJECT_TOKEN
- def test_retrieve_subject_token_certificate(self):
+ @mock.patch(
+ "google.auth.transport._mtls_helper._get_workload_cert_and_key_paths",
+ return_value=(CERT_FILE, KEY_FILE),
+ )
+ def test_retrieve_subject_token_certificate_default(
+ self, mock_get_workload_cert_and_key_paths
+ ):
credentials = self.make_credentials(
credential_source=self.CREDENTIAL_SOURCE_CERTIFICATE
)
subject_token = credentials.retrieve_subject_token(None)
- assert subject_token == ""
+ assert subject_token == json.dumps([CERT_FILE_CONTENT])
+
+ @mock.patch(
+ "google.auth.transport._mtls_helper._get_workload_cert_and_key_paths",
+ return_value=(CERT_FILE, KEY_FILE),
+ )
+ def test_retrieve_subject_token_certificate_non_default_path(
+ self, mock_get_workload_cert_and_key_paths
+ ):
+ credentials = self.make_credentials(
+ credential_source=self.CREDENTIAL_SOURCE_CERTIFICATE_NOT_DEFAULT
+ )
+
+ subject_token = credentials.retrieve_subject_token(None)
+
+ assert subject_token == json.dumps([CERT_FILE_CONTENT])
+
+ @mock.patch(
+ "google.auth.transport._mtls_helper._get_workload_cert_and_key_paths",
+ return_value=(CERT_FILE, KEY_FILE),
+ )
+ def test_retrieve_subject_token_certificate_trust_chain_with_leaf(
+ self, mock_get_workload_cert_and_key_paths
+ ):
+ credentials = self.make_credentials(
+ credential_source=self.CREDENTIAL_SOURCE_CERTIFICATE_TRUST_CHAIN_WITH_LEAF
+ )
+
+ subject_token = credentials.retrieve_subject_token(None)
+ assert subject_token == json.dumps([CERT_FILE_CONTENT, OTHER_CERT_FILE_CONTENT])
+
+ @mock.patch(
+ "google.auth.transport._mtls_helper._get_workload_cert_and_key_paths",
+ return_value=(CERT_FILE, KEY_FILE),
+ )
+ def test_retrieve_subject_token_certificate_trust_chain_without_leaf(
+ self, mock_get_workload_cert_and_key_paths
+ ):
+ credentials = self.make_credentials(
+ credential_source=self.CREDENTIAL_SOURCE_CERTIFICATE_TRUST_CHAIN_WITHOUT_LEAF
+ )
+
+ subject_token = credentials.retrieve_subject_token(None)
+ assert subject_token == json.dumps([CERT_FILE_CONTENT, OTHER_CERT_FILE_CONTENT])
+
+ @mock.patch(
+ "google.auth.transport._mtls_helper._get_workload_cert_and_key_paths",
+ return_value=(CERT_FILE, KEY_FILE),
+ )
+ def test_retrieve_subject_token_certificate_trust_chain_invalid_order(
+ self, mock_get_workload_cert_and_key_paths
+ ):
+
+ credentials = self.make_credentials(
+ credential_source=self.CREDENTIAL_SOURCE_CERTIFICATE_TRUST_CHAIN_WRONG_ORDER
+ )
+
+ with pytest.raises(exceptions.RefreshError) as excinfo:
+ credentials.retrieve_subject_token(None)
+
+ assert excinfo.match(
+ "The leaf certificate must be at the top of the trust chain file"
+ )
+
+ @mock.patch(
+ "google.auth.transport._mtls_helper._get_workload_cert_and_key_paths",
+ return_value=(CERT_FILE, KEY_FILE),
+ )
+ def test_retrieve_subject_token_certificate_trust_chain_file_does_not_exist(
+ self, mock_get_workload_cert_and_key_paths
+ ):
+
+ credentials = self.make_credentials(
+ credential_source={
+ "certificate": {
+ "use_default_certificate_config": "true",
+ "trust_chain_path": "fake.pem",
+ }
+ }
+ )
+
+ with pytest.raises(exceptions.RefreshError) as excinfo:
+ credentials.retrieve_subject_token(None)
+
+ assert excinfo.match("Trust chain file 'fake.pem' was not found.")
+
+ @mock.patch(
+ "google.auth.transport._mtls_helper._get_workload_cert_and_key_paths",
+ return_value=(CERT_FILE, KEY_FILE),
+ )
+ def test_retrieve_subject_token_certificate_invalid_trust_chain_file(
+ self, mock_get_workload_cert_and_key_paths
+ ):
+
+ credentials = self.make_credentials(
+ credential_source={
+ "certificate": {
+ "use_default_certificate_config": "true",
+ "trust_chain_path": SUBJECT_TOKEN_TEXT_FILE,
+ }
+ }
+ )
+
+ with pytest.raises(exceptions.RefreshError) as excinfo:
+ credentials.retrieve_subject_token(None)
+
+ assert excinfo.match("Error loading PEM certificates from the trust chain file")
def test_retrieve_subject_token_json_file_invalid_field_name(self):
credential_source = {
diff --git a/contrib/python/google-auth/py3/tests/test_impersonated_credentials.py b/contrib/python/google-auth/py3/tests/test_impersonated_credentials.py
index 0321a1a1d7b..9aeb505fdd9 100644
--- a/contrib/python/google-auth/py3/tests/test_impersonated_credentials.py
+++ b/contrib/python/google-auth/py3/tests/test_impersonated_credentials.py
@@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+import copy
import datetime
import http.client as http_client
import json
@@ -36,6 +37,9 @@ with open(os.path.join(DATA_DIR, "privatekey.pem"), "rb") as fh:
PRIVATE_KEY_BYTES = fh.read()
SERVICE_ACCOUNT_JSON_FILE = os.path.join(DATA_DIR, "service_account.json")
+IMPERSONATED_SERVICE_ACCOUNT_AUTHORIZED_USER_SOURCE_FILE = os.path.join(
+ DATA_DIR, "impersonated_service_account_authorized_user_source.json"
+)
ID_TOKEN_DATA = (
"eyJhbGciOiJSUzI1NiIsImtpZCI6ImRmMzc1ODkwOGI3OTIyOTNhZDk3N2Ew"
@@ -50,6 +54,9 @@ ID_TOKEN_EXPIRY = 1564475051
with open(SERVICE_ACCOUNT_JSON_FILE, "rb") as fh:
SERVICE_ACCOUNT_INFO = json.load(fh)
+with open(IMPERSONATED_SERVICE_ACCOUNT_AUTHORIZED_USER_SOURCE_FILE, "rb") as fh:
+ IMPERSONATED_SERVICE_ACCOUNT_AUTHORIZED_USER_SOURCE_INFO = json.load(fh)
+
SIGNER = crypt.RSASigner.from_string(PRIVATE_KEY_BYTES, "1")
TOKEN_URI = "https://example.com/oauth2/token"
@@ -149,6 +156,38 @@ class TestImpersonatedCredentials(object):
iam_endpoint_override=iam_endpoint_override,
)
+ def test_from_impersonated_service_account_info(self):
+ credentials = impersonated_credentials.Credentials.from_impersonated_service_account_info(
+ IMPERSONATED_SERVICE_ACCOUNT_AUTHORIZED_USER_SOURCE_INFO
+ )
+ assert isinstance(credentials, impersonated_credentials.Credentials)
+
+ def test_from_impersonated_service_account_info_with_invalid_source_credentials_type(
+ self
+ ):
+ info = copy.deepcopy(IMPERSONATED_SERVICE_ACCOUNT_AUTHORIZED_USER_SOURCE_INFO)
+ assert "source_credentials" in info
+ # Set the source_credentials to an invalid type
+ info["source_credentials"]["type"] = "invalid_type"
+ with pytest.raises(exceptions.DefaultCredentialsError) as excinfo:
+ impersonated_credentials.Credentials.from_impersonated_service_account_info(
+ info
+ )
+ assert excinfo.match(
+ "source credential of type {} is not supported".format("invalid_type")
+ )
+
+ def test_from_impersonated_service_account_info_with_invalid_impersonation_url(
+ self
+ ):
+ info = copy.deepcopy(IMPERSONATED_SERVICE_ACCOUNT_AUTHORIZED_USER_SOURCE_INFO)
+ info["service_account_impersonation_url"] = "invalid_url"
+ with pytest.raises(exceptions.DefaultCredentialsError) as excinfo:
+ impersonated_credentials.Credentials.from_impersonated_service_account_info(
+ info
+ )
+ assert excinfo.match(r"Cannot extract target principal from")
+
def test_get_cred_info(self):
credentials = self.make_credentials()
assert not credentials.get_cred_info()