From 00505e7192adaeacd05a88ab47889e594c9d43a8 Mon Sep 17 00:00:00 2001 From: alix Date: Mon, 4 Nov 2024 17:10:44 +1100 Subject: [PATCH 1/8] what if we just like .... didn't ... specify tls versions tho? --- source/Halibut/Transport/DiscoveryClient.cs | 2 +- source/Halibut/Transport/SecureListener.cs | 2 +- source/Halibut/Transport/Streams/SslStreamExtensionMethods.cs | 1 - source/Halibut/Transport/TcpConnectionFactory.cs | 2 +- 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/source/Halibut/Transport/DiscoveryClient.cs b/source/Halibut/Transport/DiscoveryClient.cs index d95494d2a..8da4aeafd 100644 --- a/source/Halibut/Transport/DiscoveryClient.cs +++ b/source/Halibut/Transport/DiscoveryClient.cs @@ -42,7 +42,7 @@ public async Task DiscoverAsync(ServiceEndPoint serviceEndpoint #if NETFRAMEWORK // TODO: ASYNC ME UP! // AuthenticateAsClientAsync in .NET 4.8 does not support cancellation tokens. So `cancellationToken` is not respected here. - await ssl.AuthenticateAsClientAsync(serviceEndpoint.BaseUri.Host, new X509Certificate2Collection(), SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12, false); + await ssl.AuthenticateAsClientAsync(serviceEndpoint.BaseUri.Host, new X509Certificate2Collection(), false); #else await ssl.AuthenticateAsClientEnforcingTimeout(serviceEndpoint, new X509Certificate2Collection(), cancellationToken); #endif diff --git a/source/Halibut/Transport/SecureListener.cs b/source/Halibut/Transport/SecureListener.cs index aa1f66ad3..3431dcd56 100644 --- a/source/Halibut/Transport/SecureListener.cs +++ b/source/Halibut/Transport/SecureListener.cs @@ -298,7 +298,7 @@ async Task ExecuteRequest(TcpClient client) { log.Write(EventType.SecurityNegotiation, "Performing TLS server handshake"); - await ssl.AuthenticateAsServerAsync(serverCertificate, true, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12, false).ConfigureAwait(false); + await ssl.AuthenticateAsServerAsync(serverCertificate, true, false).ConfigureAwait(false); log.Write(EventType.SecurityNegotiation, "Secure connection established, client is not yet authenticated, client connected with {0}", ssl.SslProtocol.ToString()); diff --git a/source/Halibut/Transport/Streams/SslStreamExtensionMethods.cs b/source/Halibut/Transport/Streams/SslStreamExtensionMethods.cs index 67112cc76..b523df36b 100644 --- a/source/Halibut/Transport/Streams/SslStreamExtensionMethods.cs +++ b/source/Halibut/Transport/Streams/SslStreamExtensionMethods.cs @@ -23,7 +23,6 @@ internal static async Task AuthenticateAsClientEnforcingTimeout( { TargetHost = serviceEndpoint.BaseUri.Host, ClientCertificates = clientCertificates, - EnabledSslProtocols = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12, CertificateRevocationCheckMode = X509RevocationMode.NoCheck }; diff --git a/source/Halibut/Transport/TcpConnectionFactory.cs b/source/Halibut/Transport/TcpConnectionFactory.cs index 41512bc64..d5f67577e 100644 --- a/source/Halibut/Transport/TcpConnectionFactory.cs +++ b/source/Halibut/Transport/TcpConnectionFactory.cs @@ -47,7 +47,7 @@ public async Task EstablishNewConnectionAsync(ExchangeProtocolBuild #if NETFRAMEWORK // TODO: ASYNC ME UP! // AuthenticateAsClientAsync in .NET 4.8 does not support cancellation tokens. So `cancellationToken` is not respected here. - await ssl.AuthenticateAsClientAsync(serviceEndpoint.BaseUri.Host, new X509Certificate2Collection(clientCertificate), SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12, false); + await ssl.AuthenticateAsClientAsync(serviceEndpoint.BaseUri.Host, new X509Certificate2Collection(clientCertificate), false); #else await ssl.AuthenticateAsClientEnforcingTimeout(serviceEndpoint, new X509Certificate2Collection(clientCertificate), cancellationToken); #endif From a7a6ebf6222e26bf8b9478de084a4dd1fc174384 Mon Sep 17 00:00:00 2001 From: alix Date: Mon, 4 Nov 2024 19:02:23 +1100 Subject: [PATCH 2/8] okay that wasnt great what if we added it instead? --- source/Halibut/Transport/DiscoveryClient.cs | 2 +- source/Halibut/Transport/SecureListener.cs | 2 +- source/Halibut/Transport/Streams/SslStreamExtensionMethods.cs | 1 + source/Halibut/Transport/TcpConnectionFactory.cs | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/source/Halibut/Transport/DiscoveryClient.cs b/source/Halibut/Transport/DiscoveryClient.cs index 8da4aeafd..26859865b 100644 --- a/source/Halibut/Transport/DiscoveryClient.cs +++ b/source/Halibut/Transport/DiscoveryClient.cs @@ -42,7 +42,7 @@ public async Task DiscoverAsync(ServiceEndPoint serviceEndpoint #if NETFRAMEWORK // TODO: ASYNC ME UP! // AuthenticateAsClientAsync in .NET 4.8 does not support cancellation tokens. So `cancellationToken` is not respected here. - await ssl.AuthenticateAsClientAsync(serviceEndpoint.BaseUri.Host, new X509Certificate2Collection(), false); + await ssl.AuthenticateAsClientAsync(serviceEndpoint.BaseUri.Host, new X509Certificate2Collection(), SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13, false); #else await ssl.AuthenticateAsClientEnforcingTimeout(serviceEndpoint, new X509Certificate2Collection(), cancellationToken); #endif diff --git a/source/Halibut/Transport/SecureListener.cs b/source/Halibut/Transport/SecureListener.cs index 3431dcd56..61cad75a5 100644 --- a/source/Halibut/Transport/SecureListener.cs +++ b/source/Halibut/Transport/SecureListener.cs @@ -298,7 +298,7 @@ async Task ExecuteRequest(TcpClient client) { log.Write(EventType.SecurityNegotiation, "Performing TLS server handshake"); - await ssl.AuthenticateAsServerAsync(serverCertificate, true, false).ConfigureAwait(false); + await ssl.AuthenticateAsServerAsync(serverCertificate, true, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13, false).ConfigureAwait(false); log.Write(EventType.SecurityNegotiation, "Secure connection established, client is not yet authenticated, client connected with {0}", ssl.SslProtocol.ToString()); diff --git a/source/Halibut/Transport/Streams/SslStreamExtensionMethods.cs b/source/Halibut/Transport/Streams/SslStreamExtensionMethods.cs index b523df36b..ee1ab3ade 100644 --- a/source/Halibut/Transport/Streams/SslStreamExtensionMethods.cs +++ b/source/Halibut/Transport/Streams/SslStreamExtensionMethods.cs @@ -23,6 +23,7 @@ internal static async Task AuthenticateAsClientEnforcingTimeout( { TargetHost = serviceEndpoint.BaseUri.Host, ClientCertificates = clientCertificates, + EnabledSslProtocols = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13, CertificateRevocationCheckMode = X509RevocationMode.NoCheck }; diff --git a/source/Halibut/Transport/TcpConnectionFactory.cs b/source/Halibut/Transport/TcpConnectionFactory.cs index d5f67577e..0802d06e4 100644 --- a/source/Halibut/Transport/TcpConnectionFactory.cs +++ b/source/Halibut/Transport/TcpConnectionFactory.cs @@ -47,7 +47,7 @@ public async Task EstablishNewConnectionAsync(ExchangeProtocolBuild #if NETFRAMEWORK // TODO: ASYNC ME UP! // AuthenticateAsClientAsync in .NET 4.8 does not support cancellation tokens. So `cancellationToken` is not respected here. - await ssl.AuthenticateAsClientAsync(serviceEndpoint.BaseUri.Host, new X509Certificate2Collection(clientCertificate), false); + await ssl.AuthenticateAsClientAsync(serviceEndpoint.BaseUri.Host, new X509Certificate2Collection(clientCertificate), SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13, false); #else await ssl.AuthenticateAsClientEnforcingTimeout(serviceEndpoint, new X509Certificate2Collection(clientCertificate), cancellationToken); #endif From 7a2d6abecfdf8bcdfbd405080fe734f445237ccc Mon Sep 17 00:00:00 2001 From: alix Date: Mon, 4 Nov 2024 19:31:07 +1100 Subject: [PATCH 3/8] it's weird that the docs say `SslProtocols.SystemDefault` but the code we're depending on says `SslProtocols.None`. Apparently it'll do the right thing - allow the OS to specify which protocol to use --- source/Halibut/Transport/DiscoveryClient.cs | 2 +- source/Halibut/Transport/SecureListener.cs | 2 +- source/Halibut/Transport/Streams/SslStreamExtensionMethods.cs | 4 +++- source/Halibut/Transport/TcpConnectionFactory.cs | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/source/Halibut/Transport/DiscoveryClient.cs b/source/Halibut/Transport/DiscoveryClient.cs index 26859865b..1af4b5f2e 100644 --- a/source/Halibut/Transport/DiscoveryClient.cs +++ b/source/Halibut/Transport/DiscoveryClient.cs @@ -42,7 +42,7 @@ public async Task DiscoverAsync(ServiceEndPoint serviceEndpoint #if NETFRAMEWORK // TODO: ASYNC ME UP! // AuthenticateAsClientAsync in .NET 4.8 does not support cancellation tokens. So `cancellationToken` is not respected here. - await ssl.AuthenticateAsClientAsync(serviceEndpoint.BaseUri.Host, new X509Certificate2Collection(), SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13, false); + await ssl.AuthenticateAsClientAsync(serviceEndpoint.BaseUri.Host, new X509Certificate2Collection(), SslProtocols.None, false); #else await ssl.AuthenticateAsClientEnforcingTimeout(serviceEndpoint, new X509Certificate2Collection(), cancellationToken); #endif diff --git a/source/Halibut/Transport/SecureListener.cs b/source/Halibut/Transport/SecureListener.cs index 61cad75a5..8d11695a1 100644 --- a/source/Halibut/Transport/SecureListener.cs +++ b/source/Halibut/Transport/SecureListener.cs @@ -298,7 +298,7 @@ async Task ExecuteRequest(TcpClient client) { log.Write(EventType.SecurityNegotiation, "Performing TLS server handshake"); - await ssl.AuthenticateAsServerAsync(serverCertificate, true, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13, false).ConfigureAwait(false); + await ssl.AuthenticateAsServerAsync(serverCertificate, true, SslProtocols.None, false).ConfigureAwait(false); log.Write(EventType.SecurityNegotiation, "Secure connection established, client is not yet authenticated, client connected with {0}", ssl.SslProtocol.ToString()); diff --git a/source/Halibut/Transport/Streams/SslStreamExtensionMethods.cs b/source/Halibut/Transport/Streams/SslStreamExtensionMethods.cs index ee1ab3ade..e297f303a 100644 --- a/source/Halibut/Transport/Streams/SslStreamExtensionMethods.cs +++ b/source/Halibut/Transport/Streams/SslStreamExtensionMethods.cs @@ -23,7 +23,9 @@ internal static async Task AuthenticateAsClientEnforcingTimeout( { TargetHost = serviceEndpoint.BaseUri.Host, ClientCertificates = clientCertificates, - EnabledSslProtocols = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13, + // Despite what you might think, this option allows the OS to decide the SSL version to use and is the recommended approach per the code comments on the version of SslProtocols we're using + // This is current at time of writing. MS docs recommend using SslProtocols.SystemDefault which does not exist on this particular enum, so that's fun. + EnabledSslProtocols = SslProtocols.None, CertificateRevocationCheckMode = X509RevocationMode.NoCheck }; diff --git a/source/Halibut/Transport/TcpConnectionFactory.cs b/source/Halibut/Transport/TcpConnectionFactory.cs index 0802d06e4..f3ad3eee5 100644 --- a/source/Halibut/Transport/TcpConnectionFactory.cs +++ b/source/Halibut/Transport/TcpConnectionFactory.cs @@ -47,7 +47,7 @@ public async Task EstablishNewConnectionAsync(ExchangeProtocolBuild #if NETFRAMEWORK // TODO: ASYNC ME UP! // AuthenticateAsClientAsync in .NET 4.8 does not support cancellation tokens. So `cancellationToken` is not respected here. - await ssl.AuthenticateAsClientAsync(serviceEndpoint.BaseUri.Host, new X509Certificate2Collection(clientCertificate), SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13, false); + await ssl.AuthenticateAsClientAsync(serviceEndpoint.BaseUri.Host, new X509Certificate2Collection(clientCertificate), SslProtocols.None, false); #else await ssl.AuthenticateAsClientEnforcingTimeout(serviceEndpoint, new X509Certificate2Collection(clientCertificate), cancellationToken); #endif From 456d5b51e6fd3b2bbb28141b82f465c7d715f011 Mon Sep 17 00:00:00 2001 From: Geoff Battye Date: Tue, 26 Nov 2024 17:38:55 +1100 Subject: [PATCH 4/8] Restore specification of SSL protocols and add TLS 1.3. --- source/Halibut/Transport/DiscoveryClient.cs | 6 +++++- source/Halibut/Transport/SecureListener.cs | 8 +++++++- .../Transport/Streams/SslStreamExtensionMethods.cs | 2 +- source/Halibut/Transport/TcpConnectionFactory.cs | 6 +++++- 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/source/Halibut/Transport/DiscoveryClient.cs b/source/Halibut/Transport/DiscoveryClient.cs index 1af4b5f2e..79b343adb 100644 --- a/source/Halibut/Transport/DiscoveryClient.cs +++ b/source/Halibut/Transport/DiscoveryClient.cs @@ -42,7 +42,11 @@ public async Task DiscoverAsync(ServiceEndPoint serviceEndpoint #if NETFRAMEWORK // TODO: ASYNC ME UP! // AuthenticateAsClientAsync in .NET 4.8 does not support cancellation tokens. So `cancellationToken` is not respected here. - await ssl.AuthenticateAsClientAsync(serviceEndpoint.BaseUri.Host, new X509Certificate2Collection(), SslProtocols.None, false); + await ssl.AuthenticateAsClientAsync( + serviceEndpoint.BaseUri.Host, + new X509Certificate2Collection(), + SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13, + false); #else await ssl.AuthenticateAsClientEnforcingTimeout(serviceEndpoint, new X509Certificate2Collection(), cancellationToken); #endif diff --git a/source/Halibut/Transport/SecureListener.cs b/source/Halibut/Transport/SecureListener.cs index 8d11695a1..6105fa903 100644 --- a/source/Halibut/Transport/SecureListener.cs +++ b/source/Halibut/Transport/SecureListener.cs @@ -298,7 +298,13 @@ async Task ExecuteRequest(TcpClient client) { log.Write(EventType.SecurityNegotiation, "Performing TLS server handshake"); - await ssl.AuthenticateAsServerAsync(serverCertificate, true, SslProtocols.None, false).ConfigureAwait(false); + await ssl + .AuthenticateAsServerAsync( + serverCertificate, + true, + SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13, + false) + .ConfigureAwait(false); log.Write(EventType.SecurityNegotiation, "Secure connection established, client is not yet authenticated, client connected with {0}", ssl.SslProtocol.ToString()); diff --git a/source/Halibut/Transport/Streams/SslStreamExtensionMethods.cs b/source/Halibut/Transport/Streams/SslStreamExtensionMethods.cs index e297f303a..a2b0db036 100644 --- a/source/Halibut/Transport/Streams/SslStreamExtensionMethods.cs +++ b/source/Halibut/Transport/Streams/SslStreamExtensionMethods.cs @@ -25,7 +25,7 @@ internal static async Task AuthenticateAsClientEnforcingTimeout( ClientCertificates = clientCertificates, // Despite what you might think, this option allows the OS to decide the SSL version to use and is the recommended approach per the code comments on the version of SslProtocols we're using // This is current at time of writing. MS docs recommend using SslProtocols.SystemDefault which does not exist on this particular enum, so that's fun. - EnabledSslProtocols = SslProtocols.None, + EnabledSslProtocols = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13, CertificateRevocationCheckMode = X509RevocationMode.NoCheck }; diff --git a/source/Halibut/Transport/TcpConnectionFactory.cs b/source/Halibut/Transport/TcpConnectionFactory.cs index f3ad3eee5..3a13913a9 100644 --- a/source/Halibut/Transport/TcpConnectionFactory.cs +++ b/source/Halibut/Transport/TcpConnectionFactory.cs @@ -47,7 +47,11 @@ public async Task EstablishNewConnectionAsync(ExchangeProtocolBuild #if NETFRAMEWORK // TODO: ASYNC ME UP! // AuthenticateAsClientAsync in .NET 4.8 does not support cancellation tokens. So `cancellationToken` is not respected here. - await ssl.AuthenticateAsClientAsync(serviceEndpoint.BaseUri.Host, new X509Certificate2Collection(clientCertificate), SslProtocols.None, false); + await ssl.AuthenticateAsClientAsync( + serviceEndpoint.BaseUri.Host, + new X509Certificate2Collection(clientCertificate), + SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13, + false); #else await ssl.AuthenticateAsClientEnforcingTimeout(serviceEndpoint, new X509Certificate2Collection(clientCertificate), cancellationToken); #endif From 7bbf6cbfa1129e81e81ec2062a3d15759f3f62bf Mon Sep 17 00:00:00 2001 From: Geoff Battye Date: Tue, 26 Nov 2024 19:19:01 +1100 Subject: [PATCH 5/8] Remove outdated comment. --- source/Halibut/Transport/Streams/SslStreamExtensionMethods.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/source/Halibut/Transport/Streams/SslStreamExtensionMethods.cs b/source/Halibut/Transport/Streams/SslStreamExtensionMethods.cs index a2b0db036..ee1ab3ade 100644 --- a/source/Halibut/Transport/Streams/SslStreamExtensionMethods.cs +++ b/source/Halibut/Transport/Streams/SslStreamExtensionMethods.cs @@ -23,8 +23,6 @@ internal static async Task AuthenticateAsClientEnforcingTimeout( { TargetHost = serviceEndpoint.BaseUri.Host, ClientCertificates = clientCertificates, - // Despite what you might think, this option allows the OS to decide the SSL version to use and is the recommended approach per the code comments on the version of SslProtocols we're using - // This is current at time of writing. MS docs recommend using SslProtocols.SystemDefault which does not exist on this particular enum, so that's fun. EnabledSslProtocols = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13, CertificateRevocationCheckMode = X509RevocationMode.NoCheck }; From 6335269ab5a253237ab68bf7aa354667e035723d Mon Sep 17 00:00:00 2001 From: Geoff Battye Date: Thu, 28 Nov 2024 22:03:38 +1100 Subject: [PATCH 6/8] Added TLS test. --- source/Halibut.Tests/TlsFixture.cs | 66 ++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 source/Halibut.Tests/TlsFixture.cs diff --git a/source/Halibut.Tests/TlsFixture.cs b/source/Halibut.Tests/TlsFixture.cs new file mode 100644 index 000000000..ffc332f0b --- /dev/null +++ b/source/Halibut.Tests/TlsFixture.cs @@ -0,0 +1,66 @@ +// Copyright 2012-2013 Octopus Deploy Pty. Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Security.Authentication; +using System.Threading.Tasks; +using FluentAssertions; +using Halibut.Exceptions; +using Halibut.Tests.Support; +using Halibut.Tests.Support.TestAttributes; +using Halibut.Tests.Support.TestCases; +using Halibut.Tests.TestServices.Async; +using Halibut.Tests.Util; +using Halibut.TestUtils.Contracts; +using NUnit.Framework; + +namespace Halibut.Tests +{ + public class TlsFixture : BaseTest + { + [Test] + [LatestClientAndLatestServiceTestCases(testNetworkConditions: false)] + public async Task LatestClientAndServiceUseBestAvailableSslProtocol(ClientAndServiceTestCase clientAndServiceTestCase) + { + await using (var clientAndService = await clientAndServiceTestCase.CreateTestCaseBuilder() + .WithStandardServices() + .AsLatestClientAndLatestServiceBuilder() + .RecordingClientLogs(out var clientLogs) + .RecordingServiceLogs(out var serviceLogs) + .Build(CancellationToken)) + { + var echo = clientAndService.CreateAsyncClient(); + await echo.SayHelloAsync("World"); + + var connectionInitiatorLogs = clientAndServiceTestCase.ServiceConnectionType == ServiceConnectionType.Listening + ? clientLogs + : serviceLogs; + + // .NET does not support TLS 1.3 on Mac OS yet. + // https://github.com/dotnet/runtime/issues/1979 + var expectedSslProtocol = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) + ? SslProtocols.Tls12 + : SslProtocols.Tls13; + + connectionInitiatorLogs.Values + .SelectMany(log => log.GetLogs()) + .Should().Contain(logEvent => logEvent.FormattedMessage.Contains($"using protocol {expectedSslProtocol}")); + } + } + } +} \ No newline at end of file From 19ac3f58fae4e1cf6bb648ccd4245b41e8381cf0 Mon Sep 17 00:00:00 2001 From: Geoff Battye Date: Thu, 28 Nov 2024 22:04:48 +1100 Subject: [PATCH 7/8] Upgrade Serilog. --- source/Halibut.Tests.DotMemory/Halibut.Tests.DotMemory.csproj | 2 +- source/Halibut.Tests/Halibut.Tests.csproj | 2 +- .../Octopus.TestPortForwarder/Octopus.TestPortForwarder.csproj | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/Halibut.Tests.DotMemory/Halibut.Tests.DotMemory.csproj b/source/Halibut.Tests.DotMemory/Halibut.Tests.DotMemory.csproj index cbd3546a0..84fb9e318 100644 --- a/source/Halibut.Tests.DotMemory/Halibut.Tests.DotMemory.csproj +++ b/source/Halibut.Tests.DotMemory/Halibut.Tests.DotMemory.csproj @@ -39,7 +39,7 @@ - + diff --git a/source/Halibut.Tests/Halibut.Tests.csproj b/source/Halibut.Tests/Halibut.Tests.csproj index a89c6a6e1..3ab8e8e64 100644 --- a/source/Halibut.Tests/Halibut.Tests.csproj +++ b/source/Halibut.Tests/Halibut.Tests.csproj @@ -47,7 +47,7 @@ - + diff --git a/source/Octopus.TestPortForwarder/Octopus.TestPortForwarder.csproj b/source/Octopus.TestPortForwarder/Octopus.TestPortForwarder.csproj index b9a5fa5f6..405b6263a 100644 --- a/source/Octopus.TestPortForwarder/Octopus.TestPortForwarder.csproj +++ b/source/Octopus.TestPortForwarder/Octopus.TestPortForwarder.csproj @@ -14,7 +14,7 @@ net8.0 - + From c07d967d9527c494e24f0f9cdec21ecc6f4bac43 Mon Sep 17 00:00:00 2001 From: Geoff Battye Date: Thu, 28 Nov 2024 23:00:17 +1100 Subject: [PATCH 8/8] Added a TLS backwards compatibility test. --- source/Halibut.Tests/Halibut.Tests.csproj | 1 + ...tClientAndPreviousServiceVersionBuilder.cs | 18 ++++++++++++++- source/Halibut.Tests/TlsFixture.cs | 22 +++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/source/Halibut.Tests/Halibut.Tests.csproj b/source/Halibut.Tests/Halibut.Tests.csproj index 3ab8e8e64..4862ad729 100644 --- a/source/Halibut.Tests/Halibut.Tests.csproj +++ b/source/Halibut.Tests/Halibut.Tests.csproj @@ -44,6 +44,7 @@ + diff --git a/source/Halibut.Tests/Support/BackwardsCompatibility/LatestClientAndPreviousServiceVersionBuilder.cs b/source/Halibut.Tests/Support/BackwardsCompatibility/LatestClientAndPreviousServiceVersionBuilder.cs index 4d0d041d2..e2a3c904b 100644 --- a/source/Halibut.Tests/Support/BackwardsCompatibility/LatestClientAndPreviousServiceVersionBuilder.cs +++ b/source/Halibut.Tests/Support/BackwardsCompatibility/LatestClientAndPreviousServiceVersionBuilder.cs @@ -1,12 +1,17 @@ using System; +using System.Collections.Concurrent; +using System.IO; using System.Threading; using System.Threading.Tasks; +using Halibut.Diagnostics; using Halibut.Diagnostics.LogCreators; using Halibut.Logging; using Halibut.TestProxy; using Halibut.Tests.Support.Logging; using Halibut.Transport.Proxy; using Octopus.TestPortForwarder; +using Serilog; +using ILog = Halibut.Diagnostics.ILog; namespace Halibut.Tests.Support.BackwardsCompatibility { @@ -21,6 +26,7 @@ public class LatestClientAndPreviousServiceVersionBuilder : IClientAndServiceBui ProxyFactory? proxyFactory; Reference? proxyServiceReference; LogLevel halibutLogLevel = LogLevel.Trace; + StringWriter? loggerStringWriter; readonly OldServiceAvailableServices availableServices = new(false, false); LatestClientAndPreviousServiceVersionBuilder(ServiceConnectionType serviceConnectionType, CertAndThumbprint serviceCertAndThumbprint) @@ -59,6 +65,12 @@ public static LatestClientAndPreviousServiceVersionBuilder ForServiceConnectionT } } + public LatestClientAndPreviousServiceVersionBuilder RecordingLogs(out StringWriter stringWriter) + { + loggerStringWriter = stringWriter = new(); + return this; + } + public LatestClientAndPreviousServiceVersionBuilder WithServiceVersion(Version? version) { this.version = version; @@ -149,7 +161,11 @@ async Task IClientAndServiceBuilder.Build(CancellationToken c public async Task Build(CancellationToken cancellationToken) { - var logger = new SerilogLoggerBuilder().Build().ForContext(); + var logger = loggerStringWriter == null + ? new SerilogLoggerBuilder() + .Build().ForContext() + : new LoggerConfiguration().WriteTo.TextWriter(loggerStringWriter).CreateLogger(); + CancellationTokenSource cancellationTokenSource = new(); if (version == null) { diff --git a/source/Halibut.Tests/TlsFixture.cs b/source/Halibut.Tests/TlsFixture.cs index ffc332f0b..f6d9f0577 100644 --- a/source/Halibut.Tests/TlsFixture.cs +++ b/source/Halibut.Tests/TlsFixture.cs @@ -22,6 +22,7 @@ using FluentAssertions; using Halibut.Exceptions; using Halibut.Tests.Support; +using Halibut.Tests.Support.BackwardsCompatibility; using Halibut.Tests.Support.TestAttributes; using Halibut.Tests.Support.TestCases; using Halibut.Tests.TestServices.Async; @@ -62,5 +63,26 @@ public async Task LatestClientAndServiceUseBestAvailableSslProtocol(ClientAndSer .Should().Contain(logEvent => logEvent.FormattedMessage.Contains($"using protocol {expectedSslProtocol}")); } } + + [Test] + // [PreviousClientAndLatestServiceVersionsTestCases(testNetworkConditions: false)] + [LatestClientAndPreviousServiceVersionsTestCases(testNetworkConditions: false)] + public async Task PreviousClientXorServiceUsageMakeSslProtocolFallBackOnTls12(ClientAndServiceTestCase clientAndServiceTestCase) + { + await using (var clientAndService = await ((LatestClientAndPreviousServiceVersionBuilder)(clientAndServiceTestCase.CreateTestCaseBuilder() + .WithStandardServices())) + .RecordingLogs(out var stringWriter) + .Build(CancellationToken)) + { + var echo = clientAndService.CreateAsyncClient(); + await echo.SayHelloAsync("World"); + const SslProtocols expectedProtocol = SslProtocols.Tls12; + var expectedLogFragment = clientAndServiceTestCase.ServiceConnectionType == ServiceConnectionType.Listening + ? $"client connected with {expectedProtocol}" + : $"using protocol {expectedProtocol}"; + var logs = stringWriter.ToString(); + logs.Should().Contain(expectedLogFragment); + } + } } } \ No newline at end of file