Always use system TLS defaults#706
Open
rhysparry wants to merge 12 commits into
Open
Conversation
b0ca0ef to
cf44e2e
Compare
3 tasks
cf44e2e to
3d39af8
Compare
…ollisions on net48 With SslProtocols.None on .NET Framework 4.8, Windows SChannel uses a per-process TLS session cache keyed on certificate + hostname. Reusing the same static certs (Octopus, TentacleListening, TentaclePolling) across tests in the same process causes SChannel to incorrectly reuse session entries when connecting to localhost, producing AuthenticationExceptions that cause ~202 test failures on net48. Fix by generating fresh unique certificates per test in: - LatestClientAndLatestServiceBuilder (Listening/Polling/PollingOverWebSocket factories) - SecureClientFixture (SetUp + SecureClientClearsPoolWhenAllConnectionsCorrupt) - ClientServerLifecycleTests (ListeningConfiguration/PollingConfiguration/ListeningThenPollingConfiguration) Tests that explicitly call WithCertificates(...) are unaffected.
…cert tests Add ServiceThumbprint property to ClientAndService so bad-certificate tests can reference the service's actual cert thumbprint rather than the client's configured trusted thumbprint (which differs in WithClientTrustingTheWrongCertificate tests). Also fixes DiscoveryClientFixture and backwards compatibility builders.
The unique-cert-per-test fix (added to work around SChannel session-cache collisions under SslProtocols.None on net48) was applied to all target frameworks. On net80 this defeats SChannel TLS session resumption, so every handshake becomes a slow full handshake. With a short receive timeout that bleeds into the handshake (ssl.ReadTimeout), this made ReceiveResponseTimeoutTests.WhenRpcExecutionIsWithinReceiveResponseTimeout_ButSubsequentDataIsDelayed fail consistently on net80 Windows. Move all of the conditional logic into a single TestCertificates helper that generates fresh certs per test only on net48, and otherwise returns the shared static certs (Octopus/TentacleListening/TentaclePolling) used on main. This restores fast resumed handshakes on net80/Linux while keeping the net48 collision fix intact.
The client-only path (LatestClientBuilder.ForServiceConnectionType, used by
CreateClientOnlyTestCaseBuilder) still used the shared static Octopus cert on
net48. Under SslProtocols.None this intermittently triggers the same SChannel
session-cache collision as before, surfacing as an AuthenticationException
('a call to SSPI failed ... they do not possess a common algorithm'). That is
classified as UnknownError rather than IsNetworkError, causing
ExceptionReturnedByHalibutProxyExtensionMethodFixture.BecauseTheListeningTentacleIsNotResponding
to flake on net48 Windows.
Generate a fresh per-test client certificate on net48 (Polling/Listening) and
dispose its TmpDirectory with the client. PollingOverWebSocket keeps the Ssl
cert (bound via netsh). No-op on net80/Linux.
WhenPollingMultipleClientsWithOneService builds two client-only polling clients plus one service that polls both. The service builder trusted a single static thumbprint and dialled every listening client expecting it, which only worked while all client-only builders shared the static Octopus cert. Generating a unique client cert per test on net48 broke that contract, failing RequestsShouldBeTakenFromAnyClient on every net48 build. Carry each client's own certificate thumbprint from the client-only builder through to the service builder so the polling service dials each listening client with that client's thumbprint: - expose LatestClient.ClientThumbprint (via IClient) - WithListeningClient/WithListeningClients now take (uri, thumbprint) Identical behaviour on net80/Linux (every client resolves to the shared Octopus thumbprint); on net48 the service trusts each unique client cert.
The previous change had the combined builder dial each listening client with that client's actual certificate thumbprint. That overrode the service's configured serviceTrustsThumbprint, which the wrong-certificate test helpers deliberately set to a non-matching value. As a result the polling service accepted connections it should have rejected, breaking the bad-certificate negative tests on every platform: - BadCertificatesTests.FailWhenClientPresentsWrongCertificateToPollingService - ConnectionObserverFixture.ObserveUnauthorizedPollingWebSocketConnections Make the per-client thumbprint optional. The combined builder passes none, so the polling loop falls back to serviceTrustsThumbprint (its previous, known- good behaviour). Only the standalone multi-client test, which has two clients with distinct certs and no wrong-certificate setup, passes explicit per-client thumbprints via WithListeningClients.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Background
While we were rolling out the change to adapt Halibut configuration to use system defaults we provided a mechanism for consumers of Halibut (i.e. Tentacle and Octopus) to override these defaults if necessary.
Now that we have confirmed that switching to system defaults has not caused issues, and has improved security (by allowing older TLS protocols to be disabled by the Operating System) we are removing the ability to configure these protocols directly.
Results
ISslConfigurationProviderand its provided implementationsSslProtocolsvalue used internally viaSslConfiguration.SupportedProtocols. This value has been set toNone, which "Allows the operating system to choose the best protocol to use, and to block protocols that are not secure." (see docs)ISslConfigurationProviderto access this static property.HalibutRuntimeBuilderBefore
After
How to review this PR
Quality ✔️
Pre-requisites