Introduce SSH agent interfacing on The Annoying OS in the test suite
Marco Ricci

Marco Ricci commited on 2025-12-25 14:33:08
Zeige 6 geänderte Dateien mit 239 Einfügungen und 56 Löschungen.


Introduce SSH agent spawning functions that interface with running SSH
agents on The Annoying OS.  Also officially activate interfacing with
the system SSH agent on The Annoying OS, now that there are working SSH
agent socket providers on The Annoying OS that do not require UNIX
domain socket support.  Because the socket provider registry drastically
changed shape since 0123456789abcdef, also update the tests referencing
registry entries to use the correct non-alias base entry, if needed.

The two most common agents on The Annoying OS, PuTTY/Pageant and OpenSSH
on Windows, do not support session- or subshell-scoped spawning as they
do on UNIX.  So technically, these new "spawning" functions are actually
"interfacing" functions.  Introduce a matching type
`SSHAgentInterfaceFunc` for these functions, as aluded to in a previous
commit.  Because the type does not return a process object, consumers of
`SSHAgentSpawnFunc | SSHAgentInterfaceFunc` need to be adapted
accordingly, leading to a couple of code changes.
... ...
@@ -6,15 +6,15 @@ from __future__ import annotations
6 6
 
7 7
 import base64
8 8
 import contextlib
9
+import ctypes
9 10
 import datetime
10 11
 import importlib
11 12
 import importlib.util
12 13
 import os
13
-import shutil
14 14
 import socket
15 15
 import subprocess
16 16
 import sys
17
-from typing import TYPE_CHECKING, Protocol, TypeVar
17
+from typing import TYPE_CHECKING, Any, Protocol, TypeVar
18 18
 
19 19
 import hypothesis
20 20
 import packaging.version
... ...
@@ -25,6 +25,7 @@ import tests.data
25 25
 import tests.data.callables
26 26
 import tests.machinery
27 27
 from derivepassphrase import _types, ssh_agent
28
+from derivepassphrase.ssh_agent import socketprovider
28 29
 
29 30
 if TYPE_CHECKING:
30 31
     from collections.abc import Iterator, Sequence
... ...
@@ -184,6 +185,37 @@ class SSHAgentSpawnFunc(Protocol):
184 185
         """
185 186
 
186 187
 
188
+class SSHAgentInterfaceFunc(Protocol):
189
+    """Interface an SSH agent, if possible."""
190
+
191
+    def __call__(
192
+        self,
193
+        executable: str | None,
194
+        env: dict[str, Any],
195
+    ) -> _types.SSHAgentSocket | None:
196
+        """Interface the SSH agent.
197
+
198
+        Args:
199
+            env:
200
+                A configuration environment to interface the agent.
201
+                Will typically include some kind of address setting
202
+                detailing how to communicate with the agent.  The
203
+                exact contents depend on the specific agent.
204
+
205
+        Other Args:
206
+            executable:
207
+                (Ignored.  Not relevant for interfacing functions.)
208
+
209
+        Returns:
210
+            An abstract socket connected to the specified SSH agent, if
211
+            possible; otherwise, `None`.
212
+
213
+            It is the caller's responsibility to clean up the socket
214
+            (through use of the context manager protocol).
215
+
216
+        """
217
+
218
+
187 219
 def spawn_pageant_on_posix(  # pragma: no cover [external]
188 220
     executable: str | None, env: dict[str, str]
189 221
 ) -> subprocess.Popen[str] | None:
... ...
@@ -296,8 +328,58 @@ def spawn_noop(  # pragma: no cover [unused]
296 328
     """Placeholder function. Does nothing."""
297 329
 
298 330
 
331
+def interface_pageant_on_the_annoying_os(
332
+    executable: str | None,
333
+    env: dict[str, Any],
334
+) -> _types.SSHAgentSocket | None:  # pragma: no cover [external]
335
+    """Interface a Pageant instance on The Annoying OS, if possible.
336
+
337
+    Args:
338
+        env:
339
+            (Ignored.)
340
+
341
+    Returns:
342
+        An abstract socket connected to Pageant, if possible; else
343
+        `None`.
344
+
345
+        It is the caller's responsibility to clean up the socket
346
+        (through use of the context manager protocol).
347
+
348
+    """
349
+    del executable, env
350
+    try:
351
+        return socketprovider.SocketProvider.windows_named_pipe_for_pageant()
352
+    except (OSError, socketprovider.WindowsNamedPipesNotAvailableError):
353
+        return None
354
+
355
+
356
+def interface_openssh_agent_on_the_annoying_os(
357
+    executable: str | None,
358
+    env: dict[str, Any],
359
+) -> _types.SSHAgentSocket | None:  # pragma: no cover [external]
360
+    """Interface an OpenSSH agent instance on The Annoying OS, if possible.
361
+
362
+    Args:
363
+        env:
364
+            (Ignored.)
365
+
366
+    Returns:
367
+        An abstract socket connected to the OpenSSH agent, if possible;
368
+        else `None`.
369
+
370
+        It is the caller's responsibility to clean up the socket
371
+        (through use of the context manager protocol).
372
+
373
+    """
374
+    del executable, env
375
+    try:
376
+        return socketprovider.SocketProvider.windows_named_pipe_for_openssh()
377
+    except (OSError, socketprovider.WindowsNamedPipesNotAvailableError):
378
+        return None
379
+
380
+
299 381
 class SpawnHandler(NamedTuple):
300
-    """A handler for a spawned SSH agent.
382
+    """A handler for a spawned or interfaced SSH agent.
301 383
 
302 384
     Attributes:
303 385
         key:
... ...
@@ -307,7 +389,7 @@ class SpawnHandler(NamedTuple):
307 389
         spawn_func:
308 390
             The spawn function.
309 391
         agent_type:
310
-            The type of the spawned SSH agent.
392
+            The type of the spawned or interfaced SSH agent.
311 393
         agent_name:
312 394
             The (optional) display name for this handler.
313 395
 
... ...
@@ -315,7 +397,7 @@ class SpawnHandler(NamedTuple):
315 397
 
316 398
     key: str
317 399
     executable: str | None
318
-    spawn_func: SSHAgentSpawnFunc
400
+    spawn_func: SSHAgentSpawnFunc | SSHAgentInterfaceFunc
319 401
     agent_type: tests.data.KnownSSHAgent
320 402
     agent_name: str | None
321 403
 
... ...
@@ -335,7 +417,21 @@ spawn_handlers: dict[str, SpawnHandler] = {
335 417
         tests.data.KnownSSHAgent.OpenSSHAgent,
336 418
         "ssh-agent (OpenSSH)",
337 419
     ),
338
-    "stub_agent_with_address": (
420
+    "pageant": SpawnHandler(
421
+        "pageant",
422
+        None,
423
+        interface_pageant_on_the_annoying_os,
424
+        tests.data.KnownSSHAgent.Pageant,
425
+        "Pageant",
426
+    ),
427
+    "openssh-on-windows": SpawnHandler(
428
+        "openssh-on-windows",
429
+        None,
430
+        interface_openssh_agent_on_the_annoying_os,
431
+        tests.data.KnownSSHAgent.OpenSSHAgentOnWindows,
432
+        "ssh-agent (OpenSSH on Windows)",
433
+    ),
434
+    "stub_agent_with_address": SpawnHandler(
339 435
         "stub_agent_with_address",
340 436
         None,
341 437
         spawn_noop,
... ...
@@ -405,15 +501,25 @@ for key, handler in spawn_handlers.items():
405 501
             "environment variable.",
406 502
         ),
407 503
     ]
408
-    if key in {"unix-pageant", "openssh", "(system-agent)"}:
504
+    # Some agents require UNIX domain socket support.
505
+    if key in {"unix-pageant", "openssh"}:
409 506
         marks.append(
410 507
             pytest.mark.skipif(
411 508
                 not hasattr(socket, "AF_UNIX"),
412 509
                 reason="No Python or system support for UNIX domain sockets.",
413 510
             )
414 511
         )
512
+    # Others require Windows named pipe support.
513
+    if key in {"pageant", "openssh-on-windows"}:
514
+        marks.append(
515
+            pytest.mark.skipif(
516
+                not hasattr(ctypes, "WinDLL"),
517
+                reason="No Python or system support for Windows named pipes.",
518
+            )
519
+        )
415 520
     spawn_handlers_params.append(pytest.param(handler, id=key, marks=marks))
416 521
 
522
+
417 523
 Popen = TypeVar("Popen", bound=subprocess.Popen)
418 524
 
419 525
 
... ...
@@ -442,9 +548,9 @@ class CannotSpawnError(RuntimeError):
442 548
     """Cannot spawn the SSH agent."""
443 549
 
444 550
 
445
-def spawn_named_agent(
551
+def spawn_named_agent(  # noqa: C901
446 552
     executable: str | None,
447
-    spawn_func: SSHAgentSpawnFunc,
553
+    spawn_func: SSHAgentSpawnFunc | SSHAgentInterfaceFunc,
448 554
     agent_type: tests.data.KnownSSHAgent,
449 555
     agent_name: str,
450 556
 ) -> Iterator[tests.data.SpawnedSSHAgentInfo]:  # pragma: no cover [external]
... ...
@@ -504,24 +610,17 @@ def spawn_named_agent(
504 610
     exit_stack = contextlib.ExitStack()
505 611
     agent_env = os.environ.copy()
506 612
     ssh_auth_sock = agent_env.pop("SSH_AUTH_SOCK", None)
507
-    proc = spawn_func(
508
-        executable=shutil.which(executable)
509
-        if executable is not None
510
-        else None,
511
-        env=agent_env,
512
-    )
613
+    proc_or_socket = spawn_func(executable=executable, env=agent_env)
513 614
     with exit_stack:
514
-        if (
515
-            spawn_func is spawn_noop
516
-            and agent_type == tests.data.KnownSSHAgent.StubbedSSHAgent
517
-        ):
615
+        if agent_type == tests.data.KnownSSHAgent.StubbedSSHAgent:
518 616
             ssh_auth_sock = None
519 617
         elif spawn_func is spawn_noop:
520
-            ssh_auth_sock = os.environ["SSH_AUTH_SOCK"]
521
-        elif proc is None:  # pragma: no cover [external]
522
-            err_msg = f"Cannot spawn usable {agent_name}"
618
+            ssh_auth_sock = os.environ.get("SSH_AUTH_SOCK")
619
+        elif proc_or_socket is None:  # pragma: no cover [external]
620
+            err_msg = f"Cannot spawn or interface with usable {agent_name}"
523 621
             raise CannotSpawnError(err_msg)
524
-        else:
622
+        elif isinstance(proc_or_socket, subprocess.Popen):
623
+            proc = proc_or_socket
525 624
             exit_stack.enter_context(terminate_on_exit(proc))
526 625
             assert os.environ.get("SSH_AUTH_SOCK") == startup_ssh_auth_sock, (
527 626
                 f"SSH_AUTH_SOCK mismatch after spawning {agent_name}"
... ...
@@ -543,12 +642,8 @@ def spawn_named_agent(
543 642
                 err_msg = f"Cannot parse agent output: {pid_line!r}"
544 643
                 raise CannotSpawnError(err_msg)
545 644
         monkeypatch = exit_stack.enter_context(pytest.MonkeyPatch.context())
546
-        if ssh_auth_sock is not None:
547
-            monkeypatch.setenv("SSH_AUTH_SOCK", ssh_auth_sock)
548
-            client = exit_stack.enter_context(
549
-                ssh_agent.SSHAgentClient.ensure_agent_subcontext()
550
-            )
551
-        else:
645
+        if agent_type == tests.data.KnownSSHAgent.StubbedSSHAgent:
646
+            assert ssh_auth_sock is None
552 647
             monkeypatch.setenv(
553 648
                 "SSH_AUTH_SOCK",
554 649
                 tests.machinery.StubbedSSHAgentSocketWithAddress.ADDRESS,
... ...
@@ -567,6 +662,20 @@ def spawn_named_agent(
567 662
                     else tests.machinery.StubbedSSHAgentSocketWithAddress()
568 663
                 )
569 664
             )
665
+        elif (
666
+            not isinstance(proc_or_socket, subprocess.Popen)
667
+            and proc_or_socket is not None
668
+        ):
669
+            socket: _types.SSHAgentSocket = proc_or_socket
670
+            client = exit_stack.enter_context(
671
+                ssh_agent.SSHAgentClient.ensure_agent_subcontext(conn=socket)
672
+            )
673
+        else:
674
+            if ssh_auth_sock:
675
+                monkeypatch.setenv("SSH_AUTH_SOCK", ssh_auth_sock)
676
+            client = exit_stack.enter_context(
677
+                ssh_agent.SSHAgentClient.ensure_agent_subcontext()
678
+            )
570 679
         # We sanity-test the connected SSH agent if it is not one of our
571 680
         # test agents, because allowing the user to run the test suite
572 681
         # with a clearly faulty agent would likely and unfairly
... ...
@@ -168,6 +168,12 @@ class KnownSSHAgent(str, enum.Enum):
168 168
             UNIX/BSD/POSIX).
169 169
         OpenSSHAgent (str):
170 170
             The agent from OpenBSD's OpenSSH suite (on UNIX/BSD/POSIX).
171
+        Pageant (str):
172
+            The agent from Simon Tatham's PuTTY suite (on The Annoying
173
+            OS).
174
+        OpenSSHAgentOnWindows (str):
175
+            The agent from OpenBSD's OpenSSH suite (PowerShell/Windows
176
+            version, on The Annoying OS).
171 177
         StubbedSSHAgent (str):
172 178
             The stubbed, fake agent pseudo-socket defined in this test
173 179
             suite.
... ...
@@ -180,6 +186,10 @@ class KnownSSHAgent(str, enum.Enum):
180 186
     """"""
181 187
     OpenSSHAgent = "OpenSSHAgent"
182 188
     """"""
189
+    Pageant = "Pageant"
190
+    """"""
191
+    OpenSSHAgentOnWindows = "OpenSSHAgentOnWindows"
192
+    """"""
183 193
     StubbedSSHAgent = "StubbedSSHAgent"
184 194
     """"""
185 195
 
... ...
@@ -343,22 +353,25 @@ class VaultTestConfig(NamedTuple):
343 353
 # ------------------------------
344 354
 
345 355
 
346
-posix_entry = _types.SSHAgentSocketProviderEntry(
347
-    socketprovider.SocketProvider.resolve("posix"), "posix", ()
356
+ssh_auth_sock_on_posix_entry = _types.SSHAgentSocketProviderEntry(
357
+    socketprovider.SocketProvider.resolve("ssh_auth_sock_on_posix"),
358
+    "ssh_auth_sock_on_posix",
359
+    (),
348 360
 )
349 361
 """
350 362
 The standard [`_types.SSHAgentSocketProviderEntry`][] for the UNIX
351 363
 domain socket handler on POSIX systems.
352 364
 """
353 365
 
354
-the_annoying_os_entry = _types.SSHAgentSocketProviderEntry(
355
-    socketprovider.SocketProvider.resolve("the_annoying_os"),
356
-    "the_annoying_os",
366
+pageant_on_the_annoying_os_entry = _types.SSHAgentSocketProviderEntry(
367
+    socketprovider.SocketProvider.resolve("pageant_on_the_annoying_os"),
368
+    "pageant_on_the_annoying_os",
357 369
     (),
358 370
 )
359 371
 """
360 372
 The standard [`_types.SSHAgentSocketProviderEntry`][] for the Windows
361
-named pipe handler on The Annoying Operating System.
373
+named pipe handler (connecting to Pageant) on The Annoying Operating
374
+System.
362 375
 """
363 376
 
364 377
 faulty_entry_callable = _types.SSHAgentSocketProviderEntry(
... ...
@@ -204,12 +204,18 @@ class SocketAddressAction(str, enum.Enum):
204 204
 
205 205
             For UNIX domain sockets, mangle the `SSH_AUTH_SOCK`
206 206
             environment variable.
207
+
208
+            For Windows named pipes, skip the test.  (Addresses are
209
+            fixed, so cannot be mangled.)
207 210
         UNSET_ADDRESS:
208 211
             Unset the socket address.
209 212
 
210 213
             For UNIX domain sockets, unset the `SSH_AUTH_SOCK`
211 214
             environment variable.
212 215
 
216
+            For Windows named pipes, skip the test.  (Adresses are
217
+            fixed, so cannot be unset.)
218
+
213 219
     """
214 220
 
215 221
     MANGLE_ADDRESS = enum.auto()
... ...
@@ -225,6 +231,20 @@ class SocketAddressAction(str, enum.Enum):
225 231
         # matching.
226 232
         # https://the13thletter.info/derivepassphrase/latest/pycompatibility/#after-eol-py3.9
227 233
         if self == self.MANGLE_ADDRESS:
234
+
235
+            def mangled_address(*_args: Any, **_kwargs: Any) -> NoReturn:
236
+                raise OSError(errno.ENOENT, os.strerror(errno.ENOENT))
237
+
238
+            monkeypatch.setattr(
239
+                socketprovider.WindowsNamedPipeHandle,
240
+                "for_pageant",
241
+                mangled_address,
242
+            )
243
+            monkeypatch.setattr(
244
+                socketprovider.WindowsNamedPipeHandle,
245
+                "for_openssh",
246
+                mangled_address,
247
+            )
228 248
             monkeypatch.setenv(
229 249
                 "SSH_AUTH_SOCK",
230 250
                 os.environ["SSH_AUTH_SOCK"] + "~"
... ...
@@ -232,6 +252,20 @@ class SocketAddressAction(str, enum.Enum):
232 252
                 else "/",
233 253
             )
234 254
         elif self == self.UNSET_ADDRESS:
255
+
256
+            def no_address(*_args: Any, **_kwargs: Any) -> NoReturn:
257
+                raise KeyError("SSH_AUTH_SOCK environment variable")  # noqa: EM101, TRY003
258
+
259
+            monkeypatch.setattr(
260
+                socketprovider.WindowsNamedPipeHandle,
261
+                "for_pageant",
262
+                no_address,
263
+            )
264
+            monkeypatch.setattr(
265
+                socketprovider.WindowsNamedPipeHandle,
266
+                "for_openssh",
267
+                no_address,
268
+            )
235 269
             monkeypatch.delenv("SSH_AUTH_SOCK", raising=False)
236 270
         else:
237 271
             raise AssertionError()
... ...
@@ -33,6 +33,7 @@ from derivepassphrase import _types, cli, ssh_agent
33 33
 from derivepassphrase._internals import (
34 34
     cli_helpers,
35 35
 )
36
+from derivepassphrase.ssh_agent import socketprovider
36 37
 from tests import data, machinery
37 38
 from tests.data import callables
38 39
 from tests.machinery import hypothesis as hypothesis_machinery
... ...
@@ -796,6 +797,16 @@ class TestStoringConfigurationFailures:
796 797
             error_text="Cannot find any running SSH agent",
797 798
             patch_suitable_ssh_keys=False,
798 799
         ) as monkeypatch:
800
+
801
+            def no_agent(*_args: Any, **_kwargs: Any) -> NoReturn:
802
+                raise KeyError("SSH_AUTH_SOCK environment variable")  # noqa: EM101, TRY003
803
+
804
+            monkeypatch.setattr(
805
+                socketprovider.WindowsNamedPipeHandle, "for_pageant", no_agent
806
+            )
807
+            monkeypatch.setattr(
808
+                socketprovider.WindowsNamedPipeHandle, "for_openssh", no_agent
809
+            )
799 810
             monkeypatch.delenv("SSH_AUTH_SOCK", raising=False)
800 811
 
801 812
     def test_fail_because_bad_ssh_agent_connection(
... ...
@@ -811,6 +822,20 @@ class TestStoringConfigurationFailures:
811 822
             cwd = pathlib.Path.cwd().resolve()
812 823
             monkeypatch.setenv("SSH_AUTH_SOCK", str(cwd))
813 824
 
825
+            def mangled_address(*_args: Any, **_kwargs: Any) -> NoReturn:
826
+                raise OSError(errno.ENOENT, os.strerror(errno.ENOENT))
827
+
828
+            monkeypatch.setattr(
829
+                socketprovider.WindowsNamedPipeHandle,
830
+                "for_pageant",
831
+                mangled_address,
832
+            )
833
+            monkeypatch.setattr(
834
+                socketprovider.WindowsNamedPipeHandle,
835
+                "for_openssh",
836
+                mangled_address,
837
+            )
838
+
814 839
     @Parametrize.TRY_RACE_FREE_IMPLEMENTATION
815 840
     def test_fail_because_read_only_file(
816 841
         self, try_race_free_implementation: bool
... ...
@@ -80,14 +80,14 @@ class Parametrize(types.SimpleNamespace):
80 80
             pytest.param(
81 81
                 [
82 82
                     importlib.metadata.EntryPoint(
83
-                        name=data.posix_entry.key,
83
+                        name=data.ssh_auth_sock_on_posix_entry.key,
84 84
                         group=socketprovider.SocketProvider.ENTRY_POINT_GROUP_NAME,
85
-                        value="tests.data: posix_entry",
85
+                        value="tests.data: ssh_auth_sock_on_posix_entry",
86 86
                     ),
87 87
                     importlib.metadata.EntryPoint(
88
-                        name=data.the_annoying_os_entry.key,
88
+                        name=data.pageant_on_the_annoying_os_entry.key,
89 89
                         group=socketprovider.SocketProvider.ENTRY_POINT_GROUP_NAME,
90
-                        value="tests.data: the_annoying_os_entry",
90
+                        value="tests.data: pageant_on_the_annoying_os_entry",
91 91
                     ),
92 92
                 ],
93 93
                 id="existing-entries",
... ...
@@ -110,7 +110,7 @@ class Parametrize(types.SimpleNamespace):
110 110
         ],
111 111
     )
112 112
     EXISTING_REGISTRY_ENTRIES = pytest.mark.parametrize(
113
-        "existing", ["posix", "the_annoying_os"]
113
+        "existing", ["ssh_auth_sock_on_posix", "pageant_on_the_annoying_os"]
114 114
     )
115 115
     SSH_STRING_EXCEPTIONS = pytest.mark.parametrize(
116 116
         ["input", "exc_type", "exc_pattern"],
... ...
@@ -818,10 +818,10 @@ class TestSSHAgentSocketProviderRegistry:
818 818
     ) -> None:
819 819
         """Resolving a non-existant entry fails."""
820 820
         new_registry = {
821
-            "posix": socketprovider.SocketProvider.registry["posix"],
822
-            "the_annoying_os": socketprovider.SocketProvider.registry[
821
+            "posix": socketprovider.SocketProvider.resolve("posix"),
822
+            "the_annoying_os": socketprovider.SocketProvider.resolve(
823 823
                 "the_annoying_os"
824
-            ],
824
+            ),
825 825
         }
826 826
         with pytest.MonkeyPatch.context() as monkeypatch:
827 827
             monkeypatch.setattr(
... ...
@@ -840,10 +840,10 @@ class TestSSHAgentSocketProviderRegistry:
840 840
 
841 841
         names = ["spam", "ham", "eggs", "parrot"]
842 842
         new_registry = {
843
-            "posix": socketprovider.SocketProvider.registry["posix"],
844
-            "the_annoying_os": socketprovider.SocketProvider.registry[
843
+            "posix": socketprovider.SocketProvider.resolve("posix"),
844
+            "the_annoying_os": socketprovider.SocketProvider.resolve(
845 845
                 "the_annoying_os"
846
-            ],
846
+            ),
847 847
         }
848 848
         with pytest.MonkeyPatch.context() as monkeypatch:
849 849
             monkeypatch.setattr(
... ...
@@ -873,12 +873,14 @@ class TestSSHAgentSocketProviderRegistry:
873 873
 
874 874
         provider = socketprovider.SocketProvider.resolve(existing)
875 875
         new_registry = {
876
-            "posix": socketprovider.SocketProvider.registry["posix"],
877
-            "the_annoying_os": socketprovider.SocketProvider.registry[
878
-                "the_annoying_os"
879
-            ],
880
-            "unix_domain": "posix",
881
-            "the_annoying_os_named_pipe": "the_annoying_os",
876
+            "ssh_auth_sock_on_posix": socketprovider.SocketProvider.resolve(
877
+                "ssh_auth_sock_on_posix"
878
+            ),
879
+            "pageant_on_the_annoying_os": socketprovider.SocketProvider.resolve(
880
+                "pageant_on_the_annoying_os"
881
+            ),
882
+            "posix": "ssh_auth_sock_on_posix",
883
+            "the_annoying_os": "pageant_on_the_annoying_os",
882 884
         }
883 885
         names = [
884 886
             k
... ...
@@ -151,11 +151,11 @@ class SSHAgentSocketProviderRegistryStateMachine(
151 151
         self.registry: dict[
152 152
             str, _types.SSHAgentSocketProvider | str | None
153 153
         ] = {
154
-            "posix": self.orig_registry["posix"],
155
-            "the_annoying_os": self.orig_registry["the_annoying_os"],
154
+            "ssh_auth_sock_on_posix": self.orig_registry["ssh_auth_sock_on_posix"],
155
+            "pageant_on_the_annoying_os": self.orig_registry["pageant_on_the_annoying_os"],
156 156
             "native": self.orig_registry["native"],
157
-            "unix_domain": "posix",
158
-            "the_annoying_os_named_pipe": "the_annoying_os",
157
+            "posix": "ssh_auth_sock_on_posix",
158
+            "the_annoying_os": "pageant_on_the_annoying_os",
159 159
         }
160 160
         self.monkeypatch.setattr(
161 161
             socketprovider.SocketProvider, "registry", self.registry
162 162