|
15 | 15 | METADATA_GET = "google.auth.compute_engine._metadata.get" |
16 | 16 | METADATA_IS_ON_GCE = "google.auth.compute_engine._metadata.is_on_gce" |
17 | 17 | FETCH_ID_TOKEN_CREDS = "google.oauth2.id_token.fetch_id_token_credentials" |
| 18 | +COMPUTE_ID_TOKEN_CREDS = "google.auth.compute_engine.IDTokenCredentials" |
18 | 19 |
|
19 | 20 |
|
20 | 21 | def make_detector(**ctx): |
@@ -79,19 +80,42 @@ def test_falls_back_to_metadata_when_default_raises(self): |
79 | 80 | ), mock.patch(METADATA_GET, return_value="meta-jwt"): |
80 | 81 | assert make_detector().get_token() == "meta-jwt" |
81 | 82 |
|
82 | | - def test_raises_when_metadata_returns_blank(self): |
| 83 | + def test_falls_back_to_id_token_credentials_when_metadata_blank(self): |
| 84 | + # Cloud Build exposes no metadata identity endpoint (404 -> blank), so |
| 85 | + # the compute path must fall back to IAM Credentials generateIdToken. |
83 | 86 | compute_creds = mock.Mock(spec=compute_engine.Credentials) |
| 87 | + id_creds = mock.Mock(token="fallback-jwt") |
84 | 88 | with mock.patch( |
85 | 89 | "google.auth.default", return_value=(compute_creds, "proj") |
86 | | - ), mock.patch(METADATA_GET, return_value=" "): |
87 | | - with pytest.raises(ValueError): |
88 | | - make_detector().get_token() |
| 90 | + ), mock.patch(METADATA_GET, return_value=" "), mock.patch( |
| 91 | + COMPUTE_ID_TOKEN_CREDS, return_value=id_creds |
| 92 | + ) as id_token_credentials: |
| 93 | + token = make_detector(oidc_audience="aud").get_token() |
| 94 | + assert token == "fallback-jwt" |
| 95 | + _, kwargs = id_token_credentials.call_args |
| 96 | + assert kwargs["target_audience"] == "aud" |
| 97 | + assert kwargs["use_metadata_identity_endpoint"] is False |
| 98 | + id_creds.refresh.assert_called_once() |
| 99 | + |
| 100 | + def test_falls_back_to_id_token_credentials_when_metadata_errors(self): |
| 101 | + compute_creds = mock.Mock(spec=compute_engine.Credentials) |
| 102 | + id_creds = mock.Mock(token="fallback-jwt") |
| 103 | + with mock.patch( |
| 104 | + "google.auth.default", return_value=(compute_creds, "proj") |
| 105 | + ), mock.patch( |
| 106 | + METADATA_GET, side_effect=exceptions.TransportError("boom") |
| 107 | + ), mock.patch( |
| 108 | + COMPUTE_ID_TOKEN_CREDS, return_value=id_creds |
| 109 | + ): |
| 110 | + assert make_detector().get_token() == "fallback-jwt" |
89 | 111 |
|
90 | | - def test_raises_when_metadata_errors(self): |
| 112 | + def test_raises_when_metadata_and_fallback_both_fail(self): |
91 | 113 | compute_creds = mock.Mock(spec=compute_engine.Credentials) |
92 | 114 | with mock.patch( |
93 | 115 | "google.auth.default", return_value=(compute_creds, "proj") |
94 | | - ), mock.patch(METADATA_GET, side_effect=exceptions.TransportError("boom")): |
| 116 | + ), mock.patch(METADATA_GET, return_value=" "), mock.patch( |
| 117 | + COMPUTE_ID_TOKEN_CREDS, side_effect=exceptions.RefreshError("no perm") |
| 118 | + ): |
95 | 119 | with pytest.raises(ValueError): |
96 | 120 | make_detector().get_token() |
97 | 121 |
|
|
0 commit comments