Marco Ricci commited on 2024-11-26 14:26:21
Zeige 4 geänderte Dateien mit 33 Einfügungen und 22 Löschungen.
In the current test scenario, where multiple SSH agents are spawned if possible, it is highly unhelpful to know *that* a running SSH agent failed, but not *which* agent did. For debugging purposes, it is better if the `running_ssh_agent` test fixture reports not only the agent's socket, but also its type. It is sufficient to have the type passed as a fixture output/test function input, because `pytest` will then pretty-print it when a test function fails.
| ... | ... |
@@ -462,6 +462,11 @@ class SpawnedSSHAgentInfo(NamedTuple): |
| 462 | 462 |
isolated: bool |
| 463 | 463 |
|
| 464 | 464 |
|
| 465 |
+class RunningSSHAgentInfo(NamedTuple): |
|
| 466 |
+ socket: str |
|
| 467 |
+ agent_type: KnownSSHAgent |
|
| 468 |
+ |
|
| 469 |
+ |
|
| 465 | 470 |
SUPPORTED_KEYS: Mapping[str, SSHTestKey] = {
|
| 466 | 471 |
'ed25519': {
|
| 467 | 472 |
'private_key': rb"""-----BEGIN OPENSSH PRIVATE KEY----- |
| ... | ... |
@@ -234,7 +234,7 @@ _spawn_handlers = [ |
| 234 | 234 |
@pytest.fixture |
| 235 | 235 |
def running_ssh_agent( # pragma: no cover |
| 236 | 236 |
skip_if_no_af_unix_support: None, |
| 237 |
-) -> Iterator[str]: |
|
| 237 |
+) -> Iterator[tests.RunningSSHAgentInfo]: |
|
| 238 | 238 |
"""Ensure a running SSH agent, if possible, as a pytest fixture. |
| 239 | 239 |
|
| 240 | 240 |
Check for a running SSH agent, or spawn a new one if possible. We |
| ... | ... |
@@ -245,9 +245,11 @@ def running_ssh_agent( # pragma: no cover |
| 245 | 245 |
can it guarantee a particular set of loaded keys. |
| 246 | 246 |
|
| 247 | 247 |
Yields: |
| 248 |
- str: |
|
| 249 |
- The value of the SSH_AUTH_SOCK environment variable, to be |
|
| 250 |
- used to connect to the running agent. |
|
| 248 |
+ : |
|
| 249 |
+ A 2-tuple `(ssh_auth_sock, agent_type)`, where |
|
| 250 |
+ `ssh_auth_sock` is the value of the `SSH_AUTH_SOCK` |
|
| 251 |
+ environment variable, to be used to connect to the running |
|
| 252 |
+ agent, and `agent_type` is the agent type. |
|
| 251 | 253 |
|
| 252 | 254 |
Raises: |
| 253 | 255 |
pytest.skip.Exception: |
| ... | ... |
@@ -279,7 +281,7 @@ def running_ssh_agent( # pragma: no cover |
| 279 | 281 |
monkeypatch.setenv('SSH_AUTH_SOCK', startup_ssh_auth_sock)
|
| 280 | 282 |
else: # pragma: no cover |
| 281 | 283 |
monkeypatch.delenv('SSH_AUTH_SOCK', raising=False)
|
| 282 |
- for exec_name, spawn_func, _ in _spawn_handlers: |
|
| 284 |
+ for exec_name, spawn_func, agent_type in _spawn_handlers: |
|
| 283 | 285 |
# Use match/case here once Python 3.9 becomes unsupported. |
| 284 | 286 |
if exec_name == '(system)': |
| 285 | 287 |
assert ( |
| ... | ... |
@@ -291,7 +293,9 @@ def running_ssh_agent( # pragma: no cover |
| 291 | 293 |
client.list_keys() |
| 292 | 294 |
except (KeyError, OSError): |
| 293 | 295 |
continue |
| 294 |
- yield os.environ['SSH_AUTH_SOCK'] |
|
| 296 |
+ yield tests.RunningSSHAgentInfo( |
|
| 297 |
+ os.environ['SSH_AUTH_SOCK'], agent_type |
|
| 298 |
+ ) |
|
| 295 | 299 |
assert ( |
| 296 | 300 |
os.environ.get('SSH_AUTH_SOCK', None)
|
| 297 | 301 |
== startup_ssh_auth_sock |
| ... | ... |
@@ -342,7 +346,7 @@ def running_ssh_agent( # pragma: no cover |
| 342 | 346 |
pytest.MonkeyPatch.context() |
| 343 | 347 |
) |
| 344 | 348 |
monkeypatch2.setenv('SSH_AUTH_SOCK', ssh_auth_sock)
|
| 345 |
- yield ssh_auth_sock |
|
| 349 |
+ yield tests.RunningSSHAgentInfo(ssh_auth_sock, agent_type) |
|
| 346 | 350 |
assert ( |
| 347 | 351 |
os.environ.get('SSH_AUTH_SOCK', None)
|
| 348 | 352 |
== startup_ssh_auth_sock |
| ... | ... |
@@ -403,12 +403,12 @@ class TestCLI: |
| 403 | 403 |
def test_204c_key_override_on_command_line( |
| 404 | 404 |
self, |
| 405 | 405 |
monkeypatch: pytest.MonkeyPatch, |
| 406 |
- running_ssh_agent: str, |
|
| 406 |
+ running_ssh_agent: tests.RunningSSHAgentInfo, |
|
| 407 | 407 |
config: dict[str, Any], |
| 408 | 408 |
key_index: int, |
| 409 | 409 |
) -> None: |
| 410 | 410 |
with monkeypatch.context(): |
| 411 |
- monkeypatch.setenv('SSH_AUTH_SOCK', running_ssh_agent)
|
|
| 411 |
+ monkeypatch.setenv('SSH_AUTH_SOCK', running_ssh_agent.socket)
|
|
| 412 | 412 |
monkeypatch.setattr( |
| 413 | 413 |
ssh_agent.SSHAgentClient, 'list_keys', tests.list_keys |
| 414 | 414 |
) |
| ... | ... |
@@ -433,10 +433,10 @@ class TestCLI: |
| 433 | 433 |
def test_205_service_phrase_if_key_in_global_config( |
| 434 | 434 |
self, |
| 435 | 435 |
monkeypatch: pytest.MonkeyPatch, |
| 436 |
- running_ssh_agent: str, |
|
| 436 |
+ running_ssh_agent: tests.RunningSSHAgentInfo, |
|
| 437 | 437 |
) -> None: |
| 438 | 438 |
with monkeypatch.context(): |
| 439 |
- monkeypatch.setenv('SSH_AUTH_SOCK', running_ssh_agent)
|
|
| 439 |
+ monkeypatch.setenv('SSH_AUTH_SOCK', running_ssh_agent.socket)
|
|
| 440 | 440 |
monkeypatch.setattr( |
| 441 | 441 |
ssh_agent.SSHAgentClient, 'list_keys', tests.list_keys |
| 442 | 442 |
) |
| ... | ... |
@@ -491,11 +491,11 @@ class TestCLI: |
| 491 | 491 |
def test_206_setting_service_phrase_thus_overriding_key_in_config( |
| 492 | 492 |
self, |
| 493 | 493 |
monkeypatch: pytest.MonkeyPatch, |
| 494 |
- running_ssh_agent: str, |
|
| 494 |
+ running_ssh_agent: tests.RunningSSHAgentInfo, |
|
| 495 | 495 |
config: _types.VaultConfig, |
| 496 | 496 |
) -> None: |
| 497 | 497 |
with monkeypatch.context(): |
| 498 |
- monkeypatch.setenv('SSH_AUTH_SOCK', running_ssh_agent)
|
|
| 498 |
+ monkeypatch.setenv('SSH_AUTH_SOCK', running_ssh_agent.socket)
|
|
| 499 | 499 |
monkeypatch.setattr( |
| 500 | 500 |
ssh_agent.SSHAgentClient, 'list_keys', tests.list_keys |
| 501 | 501 |
) |
| ... | ... |
@@ -1789,11 +1789,11 @@ Boo. |
| 1789 | 1789 |
def test_227_get_suitable_ssh_keys( |
| 1790 | 1790 |
self, |
| 1791 | 1791 |
monkeypatch: pytest.MonkeyPatch, |
| 1792 |
- running_ssh_agent: str, |
|
| 1792 |
+ running_ssh_agent: tests.RunningSSHAgentInfo, |
|
| 1793 | 1793 |
conn_hint: str, |
| 1794 | 1794 |
) -> None: |
| 1795 | 1795 |
with monkeypatch.context(): |
| 1796 |
- monkeypatch.setenv('SSH_AUTH_SOCK', running_ssh_agent)
|
|
| 1796 |
+ monkeypatch.setenv('SSH_AUTH_SOCK', running_ssh_agent.socket)
|
|
| 1797 | 1797 |
monkeypatch.setattr( |
| 1798 | 1798 |
ssh_agent.SSHAgentClient, 'list_keys', tests.list_keys |
| 1799 | 1799 |
) |
| ... | ... |
@@ -1803,7 +1803,7 @@ Boo. |
| 1803 | 1803 |
hint = ssh_agent.SSHAgentClient() |
| 1804 | 1804 |
elif conn_hint == 'socket': |
| 1805 | 1805 |
hint = socket.socket(family=socket.AF_UNIX) |
| 1806 |
- hint.connect(running_ssh_agent) |
|
| 1806 |
+ hint.connect(running_ssh_agent.socket) |
|
| 1807 | 1807 |
else: |
| 1808 | 1808 |
assert conn_hint == 'none' |
| 1809 | 1809 |
hint = None |
| ... | ... |
@@ -348,10 +348,12 @@ class TestAgentInteraction: |
| 348 | 348 |
def test_300_constructor_bad_running_agent( |
| 349 | 349 |
self, |
| 350 | 350 |
monkeypatch: pytest.MonkeyPatch, |
| 351 |
- running_ssh_agent: str, |
|
| 351 |
+ running_ssh_agent: tests.RunningSSHAgentInfo, |
|
| 352 | 352 |
) -> None: |
| 353 | 353 |
with monkeypatch.context() as monkeypatch2: |
| 354 |
- monkeypatch2.setenv('SSH_AUTH_SOCK', running_ssh_agent + '~')
|
|
| 354 |
+ monkeypatch2.setenv( |
|
| 355 |
+ 'SSH_AUTH_SOCK', running_ssh_agent.socket + '~' |
|
| 356 |
+ ) |
|
| 355 | 357 |
sock = socket.socket(family=socket.AF_UNIX) |
| 356 | 358 |
with pytest.raises(OSError): # noqa: PT011 |
| 357 | 359 |
ssh_agent.SSHAgentClient(socket=sock) |
| ... | ... |
@@ -379,7 +381,7 @@ class TestAgentInteraction: |
| 379 | 381 |
def test_310_truncated_server_response( |
| 380 | 382 |
self, |
| 381 | 383 |
monkeypatch: pytest.MonkeyPatch, |
| 382 |
- running_ssh_agent: str, |
|
| 384 |
+ running_ssh_agent: tests.RunningSSHAgentInfo, |
|
| 383 | 385 |
response: bytes, |
| 384 | 386 |
) -> None: |
| 385 | 387 |
del running_ssh_agent |
| ... | ... |
@@ -424,7 +426,7 @@ class TestAgentInteraction: |
| 424 | 426 |
def test_320_list_keys_error_responses( |
| 425 | 427 |
self, |
| 426 | 428 |
monkeypatch: pytest.MonkeyPatch, |
| 427 |
- running_ssh_agent: str, |
|
| 429 |
+ running_ssh_agent: tests.RunningSSHAgentInfo, |
|
| 428 | 430 |
response_code: _types.SSH_AGENT, |
| 429 | 431 |
response: bytes | bytearray, |
| 430 | 432 |
exc_type: type[Exception], |
| ... | ... |
@@ -500,7 +502,7 @@ class TestAgentInteraction: |
| 500 | 502 |
def test_330_sign_error_responses( |
| 501 | 503 |
self, |
| 502 | 504 |
monkeypatch: pytest.MonkeyPatch, |
| 503 |
- running_ssh_agent: str, |
|
| 505 |
+ running_ssh_agent: tests.RunningSSHAgentInfo, |
|
| 504 | 506 |
key: bytes | bytearray, |
| 505 | 507 |
check: bool, |
| 506 | 508 |
response_code: _types.SSH_AGENT, |
| ... | ... |
@@ -567,7 +569,7 @@ class TestAgentInteraction: |
| 567 | 569 |
) |
| 568 | 570 |
def test_340_request_error_responses( |
| 569 | 571 |
self, |
| 570 |
- running_ssh_agent: str, |
|
| 572 |
+ running_ssh_agent: tests.RunningSSHAgentInfo, |
|
| 571 | 573 |
request_code: _types.SSH_AGENTC, |
| 572 | 574 |
response_code: _types.SSH_AGENT, |
| 573 | 575 |
exc_type: type[Exception], |
| 574 | 576 |