|
18 | 18 |
|
19 | 19 | Everywhere else (hosted agents, local dev) the tests self-skip. |
20 | 20 | """ |
| 21 | +import hashlib |
21 | 22 | import os |
22 | 23 | import unittest |
23 | 24 |
|
|
46 | 47 | ) |
47 | 48 |
|
48 | 49 |
|
| 50 | +def _safe_error(result): |
| 51 | + """Return a log-safe summary of a failed result. |
| 52 | +
|
| 53 | + Only the non-sensitive error fields are surfaced, so an assertion failure can |
| 54 | + never spill an access token (or the whole result dict) into the CI logs. |
| 55 | + """ |
| 56 | + return { |
| 57 | + key: result[key] |
| 58 | + for key in ("error", "error_description", "correlation_id") |
| 59 | + if key in result |
| 60 | + } |
| 61 | + |
| 62 | + |
49 | 63 | def _acquire_token_twice_assert_caching(test, managed_identity): |
50 | 64 | """Acquire an ARM token twice for the given managed identity and assert the first |
51 | 65 | call reaches the identity provider while the second is served from the token cache. |
52 | 66 |
|
53 | 67 | Shared by the IMDS and Azure Arc E2E tests, mirroring the Go helper of the same name. |
54 | 68 | """ |
55 | | - client = ManagedIdentityClient(managed_identity, http_client=requests.Session()) |
56 | | - |
57 | | - first = client.acquire_token_for_client(resource=_ARM_RESOURCE) |
58 | | - test.assertNotIn("error", first, "first acquisition failed: {}".format(first)) |
59 | | - test.assertIn("access_token", first) |
60 | | - test.assertEqual( |
61 | | - "identity_provider", first.get("token_source"), |
62 | | - "first call should reach the identity provider") |
63 | | - |
64 | | - second = client.acquire_token_for_client(resource=_ARM_RESOURCE) |
65 | | - test.assertNotIn("error", second, "second acquisition failed: {}".format(second)) |
66 | | - test.assertEqual( |
67 | | - "cache", second.get("token_source"), |
68 | | - "second call should be served from the token cache") |
69 | | - test.assertEqual( |
70 | | - first["access_token"], second["access_token"], |
71 | | - "cached token should match the original token") |
| 69 | + http_client = requests.Session() |
| 70 | + client = ManagedIdentityClient(managed_identity, http_client=http_client) |
| 71 | + try: |
| 72 | + first = client.acquire_token_for_client(resource=_ARM_RESOURCE) |
| 73 | + test.assertNotIn( |
| 74 | + "error", first, "first acquisition failed: {}".format(_safe_error(first))) |
| 75 | + test.assertIn("access_token", first) |
| 76 | + test.assertEqual( |
| 77 | + "identity_provider", first.get("token_source"), |
| 78 | + "first call should reach the identity provider") |
| 79 | + |
| 80 | + second = client.acquire_token_for_client(resource=_ARM_RESOURCE) |
| 81 | + test.assertNotIn( |
| 82 | + "error", second, "second acquisition failed: {}".format(_safe_error(second))) |
| 83 | + test.assertIn("access_token", second) |
| 84 | + test.assertEqual( |
| 85 | + "cache", second.get("token_source"), |
| 86 | + "second call should be served from the token cache") |
| 87 | + # Compare tokens by SHA-256 digest so a mismatch never prints the actual |
| 88 | + # token material into CI logs. |
| 89 | + test.assertEqual( |
| 90 | + hashlib.sha256(first["access_token"].encode("utf-8")).hexdigest(), |
| 91 | + hashlib.sha256(second["access_token"].encode("utf-8")).hexdigest(), |
| 92 | + "cached token should match the original token") |
| 93 | + finally: |
| 94 | + http_client.close() |
72 | 95 |
|
73 | 96 |
|
74 | 97 | @unittest.skipUnless( |
|
0 commit comments