From f7c5096bc6a7c9b02433ed08d5f3700826d91421 Mon Sep 17 00:00:00 2001 From: Jaap-Jan de Wit | DodoTech Date: Fri, 31 Jul 2026 11:06:46 +0200 Subject: [PATCH] Keep the stub servers on loopback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Running the tests raised a Windows Firewall prompt, and raised it again from every worktree. WireMockServer.Start() with no settings listens on 0.0.0.0 and [::], and the prompt is keyed to the binary that opened the socket — so each test executable asks once per bin path, which a new worktree or a switch between Debug and Release makes new again. The three suites that hold a firewall rule on this machine are exactly the three that use WireMock; every other listener in the repository already binds 127.0.0.1. The stubs now say so explicitly. Port 0 is still WireMock's own free-port search and still comes back on server.Url, which is what each stub builds its base URL from, so the authority the API validates against and the issuer its tokens claim follow the binding rather than being pinned to a host name. Sampling the listening sockets of a full DodoSSH.Api.Tests run afterwards finds one, 127.0.0.1, where there were previously three. --- tests/DodoSSH.Api.Tests/StubIdentityProvider.cs | 7 ++++++- tests/DodoSSH.Client.Api.Tests/StubServer.cs | 10 +++++++++- tests/DodoSSH.Client.Auth.Tests/StubProvider.cs | 6 +++++- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/tests/DodoSSH.Api.Tests/StubIdentityProvider.cs b/tests/DodoSSH.Api.Tests/StubIdentityProvider.cs index b81edce..399bcc5 100644 --- a/tests/DodoSSH.Api.Tests/StubIdentityProvider.cs +++ b/tests/DodoSSH.Api.Tests/StubIdentityProvider.cs @@ -6,6 +6,7 @@ using Microsoft.IdentityModel.Tokens; using WireMock.RequestBuilders; using WireMock.ResponseBuilders; using WireMock.Server; +using WireMock.Settings; namespace DodoSSH.Api.Tests; @@ -30,7 +31,11 @@ public sealed class StubIdentityProvider : IDisposable var rsa = RSA.Create(2048); signingKey = new RsaSecurityKey(rsa) { KeyId = KeyId }; - server = WireMockServer.Start(); + // Loopback explicitly: WireMock's default listens on every interface, which makes Windows Firewall + // prompt the first time each test executable runs — per binary path, so a new worktree or + // configuration asks again. Port 0 still picks a free port and reports it on server.Url, which is + // what Authority below is built from, so the issuer the tokens claim follows the binding. + server = WireMockServer.Start(new WireMockServerSettings { Urls = ["http://127.0.0.1:0"] }); Authority = server.Url!.TrimEnd('/'); StubDiscovery(); diff --git a/tests/DodoSSH.Client.Api.Tests/StubServer.cs b/tests/DodoSSH.Client.Api.Tests/StubServer.cs index dd5f46d..cd69f49 100644 --- a/tests/DodoSSH.Client.Api.Tests/StubServer.cs +++ b/tests/DodoSSH.Client.Api.Tests/StubServer.cs @@ -4,6 +4,7 @@ using DodoSSH.Contracts; using WireMock.RequestBuilders; using WireMock.ResponseBuilders; using WireMock.Server; +using WireMock.Settings; namespace DodoSSH.Client.Api.Tests; @@ -15,7 +16,14 @@ namespace DodoSSH.Client.Api.Tests; /// internal sealed class StubServer : IDisposable { - private readonly WireMockServer server = WireMockServer.Start(); + /// + /// Bound to loopback explicitly. WireMock's default listens on every interface, which makes Windows + /// Firewall prompt the first time each test executable runs — and the prompt is per binary path, so a + /// new worktree or configuration asks again. Port 0 still picks a free port and reports it on + /// . + /// + private readonly WireMockServer server = WireMockServer.Start( + new WireMockServerSettings { Urls = ["http://127.0.0.1:0"] }); internal Uri BaseUrl => new(server.Url!, UriKind.Absolute); diff --git a/tests/DodoSSH.Client.Auth.Tests/StubProvider.cs b/tests/DodoSSH.Client.Auth.Tests/StubProvider.cs index b235770..c0aa700 100644 --- a/tests/DodoSSH.Client.Auth.Tests/StubProvider.cs +++ b/tests/DodoSSH.Client.Auth.Tests/StubProvider.cs @@ -4,6 +4,7 @@ using System.Text.Json.Nodes; using WireMock.RequestBuilders; using WireMock.ResponseBuilders; using WireMock.Server; +using WireMock.Settings; namespace DodoSSH.Client.Auth.Tests; @@ -16,7 +17,10 @@ internal sealed class StubProvider : IDisposable bool advertiseS256 = true, string? issuerOverride = null) { - server = WireMockServer.Start(); + // Loopback explicitly: WireMock's default listens on every interface, which makes Windows Firewall + // prompt the first time each test executable runs — per binary path, so a new worktree or + // configuration asks again. Port 0 still picks a free port and reports it on server.Url. + server = WireMockServer.Start(new WireMockServerSettings { Urls = ["http://127.0.0.1:0"] }); Authority = new Uri(server.Url!.TrimEnd('/'), UriKind.Absolute); StubDiscovery(advertiseS256, issuerOverride);