diff --git a/.github/workflows/healthchecks_network_ci.yml b/.github/workflows/healthchecks_network_ci.yml index 053b61ff53..718f815daa 100644 --- a/.github/workflows/healthchecks_network_ci.yml +++ b/.github/workflows/healthchecks_network_ci.yml @@ -29,71 +29,8 @@ on: jobs: build: - runs-on: ubuntu-latest - #services: - # ftp: - # image: bogem/ftp - # ports: - # - 21:21 - # - 47400-47470:47400-47470 - # env: - # FTP_USER: bob - # FTP_PASS: 12345 - # PASV_ADDRESS: 127.0.0.1 - # sftp: - # image: atmoz/sftp - # ports: - # - 22:22 - # volumes: - # - ${{ github.workspace }}/build/docker-services/certificate/id_rsa.pub:/home/foo/.ssh/keys/id_rsa.pub #:ro - # - ${{ github.workspace }}/build/docker-services/sftp/users.conf:/etc/sftp/users.conf #:ro - # mail: - # image: tvial/docker-mailserver:latest - # options: --hostname mail --container_name mail --domainname healthchecks.com - # ports: - # - 25:25 - # - 143:143 - # - 465:465 - # - 587:587 - # - 993:993 - # - 995:995 - # env: - # SSL_TYPE: self-signed - # DMS_DEBUG: 1 - # volumes: - # - ${{ github.workspace }}/build/docker-services/mail/:/tmp/docker-mailserver/ - steps: - - uses: actions/checkout@v3 - - name: Setup .NET - uses: actions/setup-dotnet@v4 - with: - dotnet-version: | - 8.0.x - 9.0.x - - name: Restore - run: | - dotnet restore ./src/HealthChecks.Network/HealthChecks.Network.csproj && - dotnet restore ./test/HealthChecks.Network.Tests/HealthChecks.Network.Tests.csproj - - name: Check formatting - run: | - dotnet format --no-restore --verify-no-changes --severity warn ./src/HealthChecks.Network/HealthChecks.Network.csproj || (echo "Run 'dotnet format' to fix issues" && exit 1) && - dotnet format --no-restore --verify-no-changes --severity warn ./test/HealthChecks.Network.Tests/HealthChecks.Network.Tests.csproj || (echo "Run 'dotnet format' to fix issues" && exit 1) - - name: Build - run: | - dotnet build --no-restore ./src/HealthChecks.Network/HealthChecks.Network.csproj && - dotnet build --no-restore ./test/HealthChecks.Network.Tests/HealthChecks.Network.Tests.csproj - #- name: Test - # run: > - # dotnet test - # ./test/HealthChecks.Network.Tests/HealthChecks.Network.Tests.csproj - # --no-restore - # --no-build - # --collect "XPlat Code Coverage" - # --results-directory .coverage - # -- - # DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=opencover - #- name: Upload Coverage - # uses: codecov/codecov-action@v3 - # with: - # flags: Network - # directory: .coverage + uses: ./.github/workflows/reusable_ci_workflow.yml + with: + PROJECT_PATH: ./src/HealthChecks.Network/HealthChecks.Network.csproj + TEST_PROJECT_PATH: ./test/HealthChecks.Network.Tests/HealthChecks.Network.Tests.csproj + CODECOV_FLAGS: Network diff --git a/test/HealthChecks.Network.Tests/Fixtures/DockerMailServerContainerFixture.cs b/test/HealthChecks.Network.Tests/Fixtures/DockerMailServerContainerFixture.cs new file mode 100644 index 0000000000..8054e4afe0 --- /dev/null +++ b/test/HealthChecks.Network.Tests/Fixtures/DockerMailServerContainerFixture.cs @@ -0,0 +1,120 @@ +using DotNet.Testcontainers.Builders; +using DotNet.Testcontainers.Containers; + +namespace HealthChecks.Network.Tests.Fixtures; + +public class DockerMailServerContainerFixture : IAsyncLifetime +{ + protected const string Registry = "docker.io"; + + protected const string Image = "mailserver/docker-mailserver"; + + protected const string Tag = "15.1.0"; + + protected const int ExplicitTlsSmtpPort = 587; + + protected const int ImplicitTlsSmtpPort = 465; + + protected const int ExplicitTlsImapPort = 143; + + protected const int ImplicitTlsImapPort = 993; + + protected const string Email = "user@healthchecks.com"; + + protected const string Password = "password"; + + public IContainer? Container { get; private set; } + + public (string Host, int ExplicitTlsPort, int ImplicitTlsPort, string Username, string Password) GetSmtpConnectionProperties() + { + if (Container is null) + { + throw new InvalidOperationException("The test container was not initialized."); + } + + return ( + Container.Hostname, + Container.GetMappedPublicPort(ExplicitTlsSmtpPort), + Container.GetMappedPublicPort(ImplicitTlsSmtpPort), + Email, + Password + ); + } + + public (string Host, int ExplicitTlsPort, int ImplicitTlsPort, string Username, string Password) GetImapConnectionProperties() + { + if (Container is null) + { + throw new InvalidOperationException("The test container was not initialized."); + } + + return ( + Container.Hostname, + Container.GetMappedPublicPort(ExplicitTlsImapPort), + Container.GetMappedPublicPort(ImplicitTlsImapPort), + Email, + Password + ); + } + + public async Task InitializeAsync() => Container = await CreateContainerAsync(); + + public Task DisposeAsync() => Container?.DisposeAsync().AsTask() ?? Task.CompletedTask; + + protected virtual ContainerBuilder Configure(ContainerBuilder builder) => builder; + + private async Task CreateContainerAsync() + { + var waitStrategy = Wait + .ForUnixContainer() + .UntilCommandIsCompleted("setup", "email", "add", Email, Password) + .UntilMessageIsLogged(".+ is up and running") + .UntilMessageIsLogged(".+daemon started.+") + .UntilPortIsAvailable(ImplicitTlsSmtpPort) + .UntilPortIsAvailable(ExplicitTlsSmtpPort); + + var builder = new ContainerBuilder() + .WithImage($"{Registry}/{Image}:{Tag}") + .WithEnvironment("OVERRIDE_HOSTNAME", "mail.beatpulse.com") + .WithEnvironment("POSTFIX_INET_PROTOCOLS", "ipv4") + .WithEnvironment("DOVECOT_INET_PROTOCOLS", "ipv4") + .WithEnvironment("ENABLE_CLAMAV", "0") + .WithEnvironment("ENABLE_AMAVIS", "0") + .WithEnvironment("ENABLE_RSPAMD", "0") + .WithEnvironment("ENABLE_OPENDKIM", "0") + .WithEnvironment("ENABLE_OPENDMARC", "0") + .WithEnvironment("ENABLE_POLICYD_SPF", "0") + .WithEnvironment("ENABLE_SPAMASSASSIN", "0") + .WithPortBinding(ExplicitTlsSmtpPort, true) + .WithPortBinding(ImplicitTlsSmtpPort, true) + .WithPortBinding(ExplicitTlsImapPort, true) + .WithPortBinding(ImplicitTlsImapPort, true) + .WithWaitStrategy(waitStrategy); + + builder = Configure(builder); + + var container = builder.Build(); + + await container.StartAsync(); + + return container; + } +} + +public class SecureDockerMailServerContainerFixture : DockerMailServerContainerFixture +{ + protected override ContainerBuilder Configure(ContainerBuilder builder) + { + var certsPath = new DirectoryInfo(Path.Combine( + Directory.GetCurrentDirectory(), + "Resources", + "docker-mailserver", + "certs")); + + return builder + .WithEnvironment("SSL_TYPE", "manual") + .WithResourceMapping(certsPath, "/tmp/docker-mailserver/certs") + .WithEnvironment("SSL_CERT_PATH", "/tmp/docker-mailserver/certs/public.crt") + .WithEnvironment("SSL_KEY_PATH", "/tmp/docker-mailserver/certs/private.key"); + } +} diff --git a/test/HealthChecks.Network.Tests/Fixtures/SftpGoContainerFixture.cs b/test/HealthChecks.Network.Tests/Fixtures/SftpGoContainerFixture.cs new file mode 100644 index 0000000000..c3b536c476 --- /dev/null +++ b/test/HealthChecks.Network.Tests/Fixtures/SftpGoContainerFixture.cs @@ -0,0 +1,231 @@ +using System.Net; +using System.Net.Mime; +using System.Net.Sockets; +using System.Text; +using System.Text.Json; +using DotNet.Testcontainers.Builders; +using DotNet.Testcontainers.Containers; + +namespace HealthChecks.Network.Tests.Fixtures; + +public class SftpGoContainerFixture : IAsyncLifetime +{ + private const string Registry = "docker.io"; + + private const string Image = "drakkan/sftpgo"; + + private const string Tag = "v2.6.6-distroless-slim"; + + private const int FtpPort = 21; + + private const int SftpPort = 2022; + + private const int ApiPort = 8080; + + private const string Username = "user"; + + private const string Password = "password"; + + private const string Passphrase = "beatpulse"; + + private string? _privateKey; + + public IContainer? Container { get; private set; } + + public (string Hostname, int Port, string Username, string Password) GetFtpConnectionProperties() + { + if (Container is null) + { + throw new InvalidOperationException("The test container was not initialized."); + } + + return (Container.Hostname, Container.GetMappedPublicPort(FtpPort), Username, Password); + } + + public (string Hostname, int Port, string Username, string Password, string PrivateKey, string Passphrase) GetSftpConnectionProperties() + { + if (Container is null) + { + throw new InvalidOperationException("The test container was not initialized."); + } + + if (_privateKey is null) + { + throw new InvalidOperationException("The test container was not initialized."); + } + + return (Container.Hostname, Container.GetMappedPublicPort(SftpPort), Username, Password, _privateKey, Passphrase); + } + + public async Task InitializeAsync() + { + Container = await CreateContainerAsync(); + + // Initialize SFTPGo via its HTTP API: get admin token and create a user + await InitializeSftpGoAsync(Container); + } + + public Task DisposeAsync() => Container?.DisposeAsync().AsTask() ?? Task.CompletedTask; + + private async Task CreateContainerAsync() + { + var waitStrategy = Wait + .ForUnixContainer() + .UntilMessageIsLogged(".+server listener registered.+"); + + var passivePorts = FindPortRangeForPassiveMode(count: 3); + + int rangeStart = passivePorts[0]; + int rangeEnd = passivePorts[^1]; + + var builder = new ContainerBuilder() + .WithImage($"{Registry}/{Image}:{Tag}") + .WithEnvironment("STPFGO_DATA_PROVIDER__DRIVER", "memory") + .WithEnvironment("SFTPGO_DATA_PROVIDER__UPDATE_MODE", "0") + .WithEnvironment("SFTPGO_DATA_PROVIDER__CREATE_DEFAULT_ADMIN", "true") + .WithEnvironment("SFTPGO_DEFAULT_ADMIN_USERNAME", Username) + .WithEnvironment("SFTPGO_DEFAULT_ADMIN_PASSWORD", Password) + .WithEnvironment("SFTPGO_FTPD__BINDINGS__0__PORT", FtpPort.ToString()) + .WithEnvironment("SFTPGO_FTPD__PASSIVE_PORT_RANGE__START", rangeStart.ToString()) + .WithEnvironment("SFTPGO_FTPD__PASSIVE_PORT_RANGE__END", rangeEnd.ToString()) + .WithPortBinding(FtpPort, true) + .WithPortBinding(SftpPort, true) + .WithPortBinding(ApiPort, true) + .WithWaitStrategy(waitStrategy); + + foreach (int port in passivePorts) + { + builder = builder.WithPortBinding(port, port); + } + + var container = builder.Build(); + + await container.StartAsync(); + + return container; + } + + private async Task InitializeSftpGoAsync(IContainer container) + { + string keysPath = Path.Combine(Directory.GetCurrentDirectory(), "Resources", "sftpgo", "keys"); + + string privateKeyPath = Path.Combine(keysPath, "id_rsa"); + string publicKeyPath = Path.Combine(keysPath, "id_rsa.pub"); + + _privateKey = await File.ReadAllTextAsync(privateKeyPath); + string publicKey = await File.ReadAllTextAsync(publicKeyPath); + + var uriBuilder = new UriBuilder( + Uri.UriSchemeHttp, + container.Hostname, + container.GetMappedPublicPort(ApiPort), + "/api/v2/"); + + using var client = new HttpClient(); + + client.BaseAddress = uriBuilder.Uri; + + string token = await GetAdminTokenAsync(client); + + await CreateOrUpsertUserAsync(client, token, publicKey); + } + + private static async Task GetAdminTokenAsync(HttpClient client) + { + using var request = new HttpRequestMessage(HttpMethod.Get, "token"); + + request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue( + nameof(AuthenticationSchemes.Basic), + Convert.ToBase64String(Encoding.UTF8.GetBytes($"{Username}:{Password}"))); + + using var response = await client.SendAsync(request); + + await using var stream = await response.Content.ReadAsStreamAsync(); + + var json = await JsonDocument.ParseAsync(stream); + + return json.RootElement.GetProperty("access_token").GetString()!; + } + + private static async Task CreateOrUpsertUserAsync(HttpClient client, string token, string publicKey) + { + using var request = new HttpRequestMessage(HttpMethod.Post, "users"); + + request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue( + "Bearer", + token); + + var payload = new + { + id = 1, + status = 1, + username = Username, + email = $"{Username}@healthchecks.com", + password = Password, + public_keys = new[] { publicKey }, + permissions = new Dictionary + { + ["/"] = ["*"] + } + }; + + string json = JsonSerializer.Serialize(payload); + + request.Content = new StringContent(json, Encoding.UTF8, MediaTypeNames.Application.Json); + + await client.SendAsync(request); + } + + private static IReadOnlyList FindPortRangeForPassiveMode(int count, int rangeStart = 50000, int rangeEnd = 65000) + { + int totalSpan = rangeEnd - rangeStart + 1 - (count - 1); + + int randomOffset = Random.Shared.Next(0, totalSpan); + + for (int i = 0; i < totalSpan; i++) + { + int start = rangeStart + (randomOffset + i) % totalSpan; + + var listeners = new List(capacity: count); + + try + { + for (int p = start; p < start + count; p++) + { + var l = new TcpListener(IPAddress.Loopback, p); + + l.Server.ExclusiveAddressUse = true; + + l.Start(); + + listeners.Add(l); + } + + int[] result = Enumerable.Range(start, count).ToArray(); + + foreach (var l in listeners) + { + l.Stop(); + } + + return result; + } + catch + { + foreach (var l in listeners) + { + try + { + l.Stop(); + } + catch + { + // ignored + } + } + } + } + + throw new InvalidOperationException($"Unable to find {count} consecutive free ports in range {rangeStart}-{rangeEnd}."); + } +} diff --git a/test/HealthChecks.Network.Tests/Functional/DnsResolveCountHealthCheckTests.cs b/test/HealthChecks.Network.Tests/Functional/DnsResolveCountHealthCheckTests.cs index 230272527b..c6e490a996 100644 --- a/test/HealthChecks.Network.Tests/Functional/DnsResolveCountHealthCheckTests.cs +++ b/test/HealthChecks.Network.Tests/Functional/DnsResolveCountHealthCheckTests.cs @@ -1,6 +1,4 @@ using System.Net; -using HealthChecks.UI.Client; -using HealthChecks.UI.Core; namespace HealthChecks.Network.Tests.Functional; @@ -71,15 +69,14 @@ public async Task be_unhealthy_when_the_configured_number_of_resolved_is_out_of_ { config.MapHealthChecks("/health", new HealthCheckOptions { - Predicate = r => true, - ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse + Predicate = r => true }); }); - }); using var server = new TestServer(webHostBuilder); - var response = await server.CreateClient().GetAsJson("/health"); - response.ShouldNotBeNull(); + using var response = await server.CreateRequest("/health").GetAsync(); + + response.StatusCode.ShouldBe(HttpStatusCode.ServiceUnavailable); } } diff --git a/test/HealthChecks.Network.Tests/Functional/FtpHealthCheckTests.cs b/test/HealthChecks.Network.Tests/Functional/FtpHealthCheckTests.cs index 813d5eca28..49bdb3ad8d 100644 --- a/test/HealthChecks.Network.Tests/Functional/FtpHealthCheckTests.cs +++ b/test/HealthChecks.Network.Tests/Functional/FtpHealthCheckTests.cs @@ -1,23 +1,26 @@ using System.Net; +using HealthChecks.Network.Tests.Fixtures; using Microsoft.AspNetCore.Http; namespace HealthChecks.Network.Tests.Functional; -public class ftp_healthcheck_should +public class ftp_healthcheck_should(SftpGoContainerFixture sftpGoFixture) : IClassFixture { [Fact] public async Task be_healthy_when_connection_is_successful() { + var properties = sftpGoFixture.GetFtpConnectionProperties(); + var webHostBuilder = new WebHostBuilder() .ConfigureServices(services => { services.AddHealthChecks() .AddFtpHealthCheck(setup => { - setup.AddHost("ftp://localhost:21", + setup.AddHost($"ftp://{properties.Hostname}:{properties.Port}", createFile: false, - credentials: new NetworkCredential("bob", "12345")); + credentials: new NetworkCredential(properties.Username, properties.Password)); }, tags: ["ftp"]); }) .Configure(app => @@ -37,15 +40,17 @@ public async Task be_healthy_when_connection_is_successful() [Fact] public async Task be_healthy_when_connection_is_successful_and_file_is_created() { + var properties = sftpGoFixture.GetFtpConnectionProperties(); + var webHostBuilder = new WebHostBuilder() .ConfigureServices(services => { services.AddHealthChecks() .AddFtpHealthCheck(setup => { - setup.AddHost("ftp://localhost:21", + setup.AddHost($"ftp://{properties.Hostname}:{properties.Port}", createFile: true, - credentials: new NetworkCredential("bob", "12345")); + credentials: new NetworkCredential(properties.Username, properties.Password)); }, tags: ["ftp"]); }) .Configure(app => @@ -66,7 +71,7 @@ public async Task be_healthy_when_connection_is_successful_and_file_is_created() public async Task respect_configured_timeout_and_throw_operation_cancelled_exception() { var options = new FtpHealthCheckOptions(); - options.AddHost("ftp://invalid:21"); + options.AddHost("ftp://10.255.255.255:21"); var ftpHealthCheck = new FtpHealthCheck(options); var result = await ftpHealthCheck.CheckHealthAsync(new HealthCheckContext diff --git a/test/HealthChecks.Network.Tests/Functional/ImapHealthCheckTests.cs b/test/HealthChecks.Network.Tests/Functional/ImapHealthCheckTests.cs index 4df4e8d558..8682372faa 100644 --- a/test/HealthChecks.Network.Tests/Functional/ImapHealthCheckTests.cs +++ b/test/HealthChecks.Network.Tests/Functional/ImapHealthCheckTests.cs @@ -1,28 +1,26 @@ using System.Net; using HealthChecks.Network.Core; +using HealthChecks.Network.Tests.Fixtures; namespace HealthChecks.Network.Tests.Functional; -public class imap_healthcheck_should +public class imap_healthcheck_should(SecureDockerMailServerContainerFixture dockerMailServerFixture) : IClassFixture { - - //Host and login account to fast switch tests against different server - private const string _host = "localhost"; - private const string _validAccount = "admin@healthchecks.com"; - private const string _validPassword = "beatpulse"; - [Fact] public async Task be_healthy_when_connecting_to_imap_ssl_port_without_login() { + var properties = dockerMailServerFixture.GetImapConnectionProperties(); + var webHostBuilder = new WebHostBuilder() .ConfigureServices(services => { services.AddHealthChecks() .AddImapHealthCheck(setup => { - setup.Host = _host; - setup.Port = 993; + setup.Host = properties.Host; + setup.Port = properties.ImplicitTlsPort; setup.AllowInvalidRemoteCertificates = true; + setup.ConnectionType = ImapConnectionType.SSL_TLS; }, tags: ["imap"]); }) .Configure(app => @@ -42,16 +40,19 @@ public async Task be_healthy_when_connecting_to_imap_ssl_port_without_login() [Fact] public async Task be_healthy_when_connecting_to_imap_ssl_and_login_with_correct_account() { + var properties = dockerMailServerFixture.GetImapConnectionProperties(); + var webHostBuilder = new WebHostBuilder() .ConfigureServices(services => { services.AddHealthChecks() .AddImapHealthCheck(setup => { - setup.Host = _host; - setup.Port = 993; + setup.Host = properties.Host; + setup.Port = properties.ImplicitTlsPort; + setup.ConnectionType = ImapConnectionType.SSL_TLS; setup.AllowInvalidRemoteCertificates = true; - setup.LoginWith(_validAccount, _validPassword); + setup.LoginWith(properties.Username, properties.Password); }, tags: ["imap"]); }) .Configure(app => @@ -71,14 +72,16 @@ public async Task be_healthy_when_connecting_to_imap_ssl_and_login_with_correct_ [Fact] public async Task be_unhealthy_when_connecting_to_imap_ssl_and_login_with_an_incorrect_account() { + var properties = dockerMailServerFixture.GetImapConnectionProperties(); + var webHostBuilder = new WebHostBuilder() .ConfigureServices(services => { services.AddHealthChecks() .AddImapHealthCheck(setup => { - setup.Host = _host; - setup.Port = 993; + setup.Host = properties.Host; + setup.Port = properties.ImplicitTlsPort; setup.ConnectionType = ImapConnectionType.SSL_TLS; setup.AllowInvalidRemoteCertificates = true; setup.LoginWith("invalid@healthchecks.com", "invalidpassword"); @@ -101,16 +104,19 @@ public async Task be_unhealthy_when_connecting_to_imap_ssl_and_login_with_an_inc [Fact] public async Task be_healthy_when_connecting_to_imap_ssl_with_a_correct_account_checking_an_existing_folder() { + var properties = dockerMailServerFixture.GetImapConnectionProperties(); + var webHostBuilder = new WebHostBuilder() .ConfigureServices(services => { services.AddHealthChecks() .AddImapHealthCheck(setup => { - setup.Host = _host; - setup.Port = 143; + setup.Host = properties.Host; + setup.Port = properties.ImplicitTlsPort; + setup.ConnectionType = ImapConnectionType.SSL_TLS; setup.AllowInvalidRemoteCertificates = true; - setup.LoginWith(_validAccount, _validPassword); + setup.LoginWith(properties.Username, properties.Password); setup.CheckFolderExists("INBOX"); }, tags: ["imap"]); }) @@ -131,16 +137,19 @@ public async Task be_healthy_when_connecting_to_imap_ssl_with_a_correct_account_ [Fact] public async Task be_unhealthy_when_connecting_to_imap_ssl_with_a_correct_account_checking_an_non_existing_folder() { + var properties = dockerMailServerFixture.GetImapConnectionProperties(); + var webHostBuilder = new WebHostBuilder() .ConfigureServices(services => { services.AddHealthChecks() .AddImapHealthCheck(setup => { - setup.Host = _host; - setup.Port = 993; + setup.Host = properties.Host; + setup.Port = properties.ImplicitTlsPort; + setup.ConnectionType = ImapConnectionType.SSL_TLS; setup.AllowInvalidRemoteCertificates = true; - setup.LoginWith(_validAccount, _validPassword); + setup.LoginWith(properties.Username, properties.Password); setup.CheckFolderExists("INVALIDFOLDER"); }, tags: ["imap"]); }) @@ -161,14 +170,17 @@ public async Task be_unhealthy_when_connecting_to_imap_ssl_with_a_correct_accoun [Fact] public async Task be_healthy_when_imap_connects_to_starttls_port() { + var properties = dockerMailServerFixture.GetImapConnectionProperties(); + var webHostBuilder = new WebHostBuilder() .ConfigureServices(services => { services.AddHealthChecks() .AddImapHealthCheck(setup => { - setup.Host = _host; - setup.Port = 143; + setup.Host = properties.Host; + setup.Port = properties.ExplicitTlsPort; + setup.ConnectionType = ImapConnectionType.STARTTLS; setup.AllowInvalidRemoteCertificates = true; }, tags: ["imap"]); }) @@ -189,16 +201,19 @@ public async Task be_healthy_when_imap_connects_to_starttls_port() [Fact] public async Task be_healthy_when_imap_performs_login_using_starttls_handshake() { + var properties = dockerMailServerFixture.GetImapConnectionProperties(); + var webHostBuilder = new WebHostBuilder() .ConfigureServices(services => { services.AddHealthChecks() .AddImapHealthCheck(setup => { - setup.Host = _host; - setup.Port = 143; + setup.Host = properties.Host; + setup.Port = properties.ExplicitTlsPort; + setup.ConnectionType = ImapConnectionType.STARTTLS; setup.AllowInvalidRemoteCertificates = true; - setup.LoginWith(_validAccount, _validPassword); + setup.LoginWith(properties.Username, properties.Password); }, tags: ["imap"]); }) .Configure(app => @@ -218,17 +233,19 @@ public async Task be_healthy_when_imap_performs_login_using_starttls_handshake() [Fact] public async Task be_healthy_when_imap_performs_login_and_folder_check_using_starttls_handshake() { + var properties = dockerMailServerFixture.GetImapConnectionProperties(); + var webHostBuilder = new WebHostBuilder() .ConfigureServices(services => { services.AddHealthChecks() .AddImapHealthCheck(setup => { - setup.Host = _host; - setup.Port = 143; + setup.Host = properties.Host; + setup.Port = properties.ExplicitTlsPort; setup.ConnectionType = ImapConnectionType.STARTTLS; setup.AllowInvalidRemoteCertificates = true; - setup.LoginWith(_validAccount, _validPassword); + setup.LoginWith(properties.Username, properties.Password); setup.CheckFolderExists("INBOX"); }, tags: ["imap"]); }) @@ -249,13 +266,15 @@ public async Task be_healthy_when_imap_performs_login_and_folder_check_using_sta [Fact] public async Task be_unhealthy_when_using_configuration_auto_with_an_invalid_imap_port() { + var properties = dockerMailServerFixture.GetImapConnectionProperties(); + var webHostBuilder = new WebHostBuilder() .ConfigureServices(services => { services.AddHealthChecks() .AddImapHealthCheck(setup => { - setup.Host = _host; + setup.Host = properties.Host; setup.Port = 135; }, tags: ["imap"]); }) @@ -279,7 +298,7 @@ public async Task be_unhealthy_when_using_configuration_auto_with_an_invalid_ima [Fact] public async Task respect_configured_timeout_and_throw_operation_cancelled_exception() { - var options = new ImapHealthCheckOptions() { Host = "invalid", Port = 993 }; + var options = new ImapHealthCheckOptions() { Host = "10.255.255.255", Port = 993 }; options.LoginWith("user", "pass"); var imapHealthCheck = new ImapHealthCheck(options); @@ -292,7 +311,7 @@ public async Task respect_configured_timeout_and_throw_operation_cancelled_excep failureStatus: HealthStatus.Degraded, null, timeout: null) - }, new CancellationTokenSource(TimeSpan.FromSeconds(2)).Token); + }, new CancellationTokenSource(TimeSpan.FromSeconds(5)).Token); result.Exception.ShouldBeOfType(); } diff --git a/test/HealthChecks.Network.Tests/Functional/SftpHealthCheckTests.cs b/test/HealthChecks.Network.Tests/Functional/SftpHealthCheckTests.cs index 1332cb3aae..3f63c7832f 100644 --- a/test/HealthChecks.Network.Tests/Functional/SftpHealthCheckTests.cs +++ b/test/HealthChecks.Network.Tests/Functional/SftpHealthCheckTests.cs @@ -1,21 +1,23 @@ using System.Net; +using HealthChecks.Network.Tests.Fixtures; namespace HealthChecks.Network.Tests.Functional; -public class sftp_healthcheck_should +public class sftp_healthcheck_should(SftpGoContainerFixture sftpGoFixture) : IClassFixture { - [Fact] public async Task be_healthy_when_connection_to_sftp_is_successful_using_password_authentication() { + var properties = sftpGoFixture.GetSftpConnectionProperties(); + var webHostBuilder = new WebHostBuilder() .ConfigureServices(services => { services.AddHealthChecks() .AddSftpHealthCheck(setup => { - var cfg = new SftpConfigurationBuilder("localhost", 22, "foo") - .AddPasswordAuthentication("pass") + var cfg = new SftpConfigurationBuilder(properties.Hostname, properties.Port, properties.Username) + .AddPasswordAuthentication(properties.Password) .Build(); setup.AddHost(cfg); @@ -39,13 +41,15 @@ public async Task be_healthy_when_connection_to_sftp_is_successful_using_passwor [Fact] public async Task be_unhealthy_when_connection_to_sftp_is_using_wrong_password() { + var properties = sftpGoFixture.GetSftpConnectionProperties(); + var webHostBuilder = new WebHostBuilder() .ConfigureServices(services => { services.AddHealthChecks() .AddSftpHealthCheck(setup => { - var cfg = new SftpConfigurationBuilder("localhost", 22, "foo") + var cfg = new SftpConfigurationBuilder(properties.Hostname, properties.Port, properties.Username) .AddPasswordAuthentication("wrongpass") .Build(); @@ -70,7 +74,7 @@ public async Task be_unhealthy_when_connection_to_sftp_is_using_wrong_password() [Fact] public async Task be_healthy_when_connection_to_sftp_is_successful_using_private_key() { - string privateKey = File.ReadAllText("id_rsa"); + var properties = sftpGoFixture.GetSftpConnectionProperties(); var webHostBuilder = new WebHostBuilder() .ConfigureServices(services => @@ -78,8 +82,8 @@ public async Task be_healthy_when_connection_to_sftp_is_successful_using_private services.AddHealthChecks() .AddSftpHealthCheck(setup => { - var cfg = new SftpConfigurationBuilder("localhost", 22, "foo") - .AddPrivateKeyAuthentication(privateKey, "beatpulse") + var cfg = new SftpConfigurationBuilder(properties.Hostname, properties.Port, properties.Username) + .AddPrivateKeyAuthentication(properties.PrivateKey, properties.Passphrase) .Build(); setup.AddHost(cfg); @@ -103,7 +107,7 @@ public async Task be_healthy_when_connection_to_sftp_is_successful_using_private [Fact] public async Task be_healthy_with_valid_authorization_and_file_creation_enabled() { - string privateKey = File.ReadAllText("id_rsa"); + var properties = sftpGoFixture.GetSftpConnectionProperties(); var webHostBuilder = new WebHostBuilder() .ConfigureServices(services => @@ -111,9 +115,9 @@ public async Task be_healthy_with_valid_authorization_and_file_creation_enabled( services.AddHealthChecks() .AddSftpHealthCheck(setup => { - var cfg = new SftpConfigurationBuilder("localhost", 22, "foo") - .AddPrivateKeyAuthentication(privateKey, "beatpulse") - .CreateFileOnConnect("upload/beatpulse") + var cfg = new SftpConfigurationBuilder(properties.Hostname, properties.Port, properties.Username) + .AddPrivateKeyAuthentication(properties.PrivateKey, properties.Passphrase) + .CreateFileOnConnect("beatpulse") .Build(); setup.AddHost(cfg); @@ -137,7 +141,7 @@ public async Task be_healthy_with_valid_authorization_and_file_creation_enabled( [Fact] public async Task be_healthy_with_one_valid_authorization() { - string privateKey = File.ReadAllText("id_rsa"); + var properties = sftpGoFixture.GetSftpConnectionProperties(); var webHostBuilder = new WebHostBuilder() .ConfigureServices(services => @@ -145,9 +149,9 @@ public async Task be_healthy_with_one_valid_authorization() services.AddHealthChecks() .AddSftpHealthCheck(setup => { - var cfg = new SftpConfigurationBuilder("localhost", 22, "foo") + var cfg = new SftpConfigurationBuilder(properties.Hostname, properties.Port, properties.Username) .AddPasswordAuthentication("wrongpass") - .AddPrivateKeyAuthentication(privateKey, "beatpulse") + .AddPrivateKeyAuthentication(properties.PrivateKey, properties.Passphrase) .Build(); setup.AddHost(cfg); diff --git a/test/HealthChecks.Network.Tests/Functional/SmtpHealthCheckTests.cs b/test/HealthChecks.Network.Tests/Functional/SmtpHealthCheckTests.cs index 99d137a611..40ea6b2422 100644 --- a/test/HealthChecks.Network.Tests/Functional/SmtpHealthCheckTests.cs +++ b/test/HealthChecks.Network.Tests/Functional/SmtpHealthCheckTests.cs @@ -1,20 +1,16 @@ using System.Net; using HealthChecks.Network.Core; +using HealthChecks.Network.Tests.Fixtures; namespace HealthChecks.Network.Tests.Functional; - -public class smtp_healthcheck_should +public class smtp_healthcheck_should(SecureDockerMailServerContainerFixture dockerMailServerFixture) : IClassFixture { - - //Host and login account to fast switch tests against different server - private const string _host = "localhost"; - private const string _validAccount = "admin@healthchecks.com"; - private const string _validPassword = "beatpulse"; - [Fact] public async Task be_healthy_when_connecting_using_ssl() { + var properties = dockerMailServerFixture.GetSmtpConnectionProperties(); + var webHostBuilder = new WebHostBuilder() .ConfigureServices(services => { @@ -22,8 +18,8 @@ public async Task be_healthy_when_connecting_using_ssl() .AddSmtpHealthCheck(setup => { //SSL on by default - setup.Host = _host; - setup.Port = 465; + setup.Host = properties.Host; + setup.Port = properties.ImplicitTlsPort; setup.ConnectionType = SmtpConnectionType.SSL; setup.AllowInvalidRemoteCertificates = true; }, tags: ["smtp"]); @@ -45,6 +41,8 @@ public async Task be_healthy_when_connecting_using_ssl() [Fact] public async Task be_healthy_when_connecting_using_tls() { + var properties = dockerMailServerFixture.GetSmtpConnectionProperties(); + var webHostBuilder = new WebHostBuilder() .ConfigureServices(services => { @@ -52,8 +50,8 @@ public async Task be_healthy_when_connecting_using_tls() .AddSmtpHealthCheck(setup => { //SSL on by default - setup.Host = _host; - setup.Port = 587; + setup.Host = properties.Host; + setup.Port = properties.ExplicitTlsPort; setup.ConnectionType = SmtpConnectionType.TLS; setup.AllowInvalidRemoteCertificates = true; }, tags: ["smtp"]); @@ -73,16 +71,19 @@ public async Task be_healthy_when_connecting_using_tls() } [Fact] - public async Task be_healthy_when_connecting_using_connection_type_auto() + public async Task be_healthy_when_connecting_using_connection_type_tls() { + var properties = dockerMailServerFixture.GetSmtpConnectionProperties(); + var webHostBuilder = new WebHostBuilder() .ConfigureServices(services => { services.AddHealthChecks() .AddSmtpHealthCheck(setup => { - setup.Host = _host; - setup.Port = 587; + setup.Host = properties.Host; + setup.Port = properties.ExplicitTlsPort; + setup.ConnectionType = SmtpConnectionType.TLS; setup.AllowInvalidRemoteCertificates = true; }, tags: ["smtp"]); }) @@ -103,13 +104,15 @@ public async Task be_healthy_when_connecting_using_connection_type_auto() [Fact] public async Task be_unhealthy_when_connecting_to_an_invalid_smtp_port_with_mode_auto() { + var properties = dockerMailServerFixture.GetSmtpConnectionProperties(); + var webHostBuilder = new WebHostBuilder() .ConfigureServices(services => { services.AddHealthChecks() .AddSmtpHealthCheck(setup => { - setup.Host = _host; + setup.Host = properties.Host; setup.Port = 45; setup.AllowInvalidRemoteCertificates = true; }, tags: ["smtp"]); @@ -129,18 +132,21 @@ public async Task be_unhealthy_when_connecting_to_an_invalid_smtp_port_with_mode } [Fact] - public async Task be_healthy_when_connection_and_login_with_valid_account_using_ssl_port_and_mode_auto() + public async Task be_healthy_when_connection_and_login_with_valid_account_using_ssl() { + var properties = dockerMailServerFixture.GetSmtpConnectionProperties(); + var webHostBuilder = new WebHostBuilder() .ConfigureServices(services => { services.AddHealthChecks() .AddSmtpHealthCheck(setup => { - setup.Host = _host; - setup.Port = 465; + setup.Host = properties.Host; + setup.Port = dockerMailServerFixture.Container!.GetMappedPublicPort(465); setup.AllowInvalidRemoteCertificates = true; - setup.LoginWith(_validAccount, _validPassword); + setup.ConnectionType = SmtpConnectionType.SSL; + setup.LoginWith(properties.Username, properties.Password); }, tags: ["smtp"]); }) .Configure(app => @@ -158,18 +164,21 @@ public async Task be_healthy_when_connection_and_login_with_valid_account_using_ } [Fact] - public async Task be_healthy_when_connection_and_login_with_valid_account_using_tls_port_and_mode_auto() + public async Task be_healthy_when_connection_and_login_with_valid_account_using_tls() { + var properties = dockerMailServerFixture.GetSmtpConnectionProperties(); + var webHostBuilder = new WebHostBuilder() .ConfigureServices(services => { services.AddHealthChecks() .AddSmtpHealthCheck(setup => { - setup.Host = _host; - setup.Port = 587; + setup.Host = properties.Host; + setup.Port = properties.ExplicitTlsPort; setup.AllowInvalidRemoteCertificates = true; - setup.LoginWith(_validAccount, _validPassword); + setup.ConnectionType = SmtpConnectionType.TLS; + setup.LoginWith(properties.Username, properties.Password); }, tags: ["smtp"]); }) .Configure(app => @@ -190,16 +199,19 @@ public async Task be_healthy_when_connection_and_login_with_valid_account_using_ [Fact] public async Task be_unhealthy_when_connection_and_login_with_an_invalid_account() { + var properties = dockerMailServerFixture.GetSmtpConnectionProperties(); + var webHostBuilder = new WebHostBuilder() .ConfigureServices(services => { services.AddHealthChecks() .AddSmtpHealthCheck(setup => { - setup.Host = _host; - setup.Port = 587; + setup.Host = properties.Host; + setup.Port = properties.ExplicitTlsPort; + setup.ConnectionType = SmtpConnectionType.TLS; setup.AllowInvalidRemoteCertificates = true; - setup.LoginWith(_validAccount, "wrongpass"); + setup.LoginWith("admin@healthchecks.com", "wrongpass"); }, tags: ["smtp"]); }) .Configure(app => @@ -214,46 +226,12 @@ public async Task be_unhealthy_when_connection_and_login_with_an_invalid_account using var response = await server.CreateRequest("/health").GetAsync(); response.StatusCode.ShouldBe(HttpStatusCode.ServiceUnavailable); - - } - - [Fact(Skip = "The SMTP interoperability service at test.smtp.org has been shut down due to abuse.")] - public async Task be_healthty_when_login_with_plain_smtp() - { - /* We use test.smtp.org service to test raw smtp connections as nowadays - most mail server docker images does not support this scenario - This test is skipped as this service might not be working in the future */ - - var webHostBuilder = new WebHostBuilder() - .ConfigureServices(services => - { - services.AddHealthChecks() - .AddSmtpHealthCheck(setup => - { - setup.Host = "test.smtp.org"; - setup.Port = 25; - setup.ConnectionType = SmtpConnectionType.PLAIN; - setup.LoginWith("user19@test.smtp.org", "pass19"); - }, tags: ["smtp"]); - }) - .Configure(app => - { - app.UseHealthChecks("/health", new HealthCheckOptions - { - Predicate = r => r.Tags.Contains("smtp") - }); - }); - - using var server = new TestServer(webHostBuilder); - using var response = await server.CreateRequest("/health").GetAsync(); - - response.EnsureSuccessStatusCode(); } [Fact] public async Task respect_configured_timeout_and_throw_operation_cancelled_exception() { - var options = new SmtpHealthCheckOptions() { Host = "github.com", Port = 25 }; + var options = new SmtpHealthCheckOptions() { Host = "10.255.255.255", Port = 25 }; options.LoginWith("user", "pass"); var smtpHealthCheck = new SmtpHealthCheck(options); @@ -271,3 +249,38 @@ public async Task respect_configured_timeout_and_throw_operation_cancelled_excep result.Exception.ShouldBeOfType(); } } + +public class plaintext_smtp_healthcheck_should(DockerMailServerContainerFixture dockerMailServerFixture) : IClassFixture +{ + [Fact] + public async Task be_healthy_when_login_with_plain_smtp() + { + var properties = dockerMailServerFixture.GetSmtpConnectionProperties(); + + var webHostBuilder = new WebHostBuilder() + .ConfigureServices(services => + { + services.AddHealthChecks() + .AddSmtpHealthCheck(setup => + { + setup.Host = properties.Host; + setup.Port = properties.ExplicitTlsPort; + setup.ConnectionType = SmtpConnectionType.PLAIN; + setup.AllowInvalidRemoteCertificates = true; + setup.LoginWith(properties.Username, properties.Password); + }, tags: ["smtp"]); + }) + .Configure(app => + { + app.UseHealthChecks("/health", new HealthCheckOptions + { + Predicate = r => r.Tags.Contains("smtp") + }); + }); + + using var server = new TestServer(webHostBuilder); + using var response = await server.CreateRequest("/health").GetAsync(); + + response.EnsureSuccessStatusCode(); + } +} diff --git a/test/HealthChecks.Network.Tests/Functional/SslHealthCheckTests.cs b/test/HealthChecks.Network.Tests/Functional/SslHealthCheckTests.cs index c070a12f03..72bfab08ab 100644 --- a/test/HealthChecks.Network.Tests/Functional/SslHealthCheckTests.cs +++ b/test/HealthChecks.Network.Tests/Functional/SslHealthCheckTests.cs @@ -4,13 +4,12 @@ namespace HealthChecks.Network.Tests.Functional; public class ssl_healthcheck_should { - //Use https://badssl.com web site, witch provide samples certificates with various states and types - private const string _validHost256 = "sha256.badssl.com"; - private const string _validHost384 = "sha384.badssl.com"; - private const string _validHost512 = "sha512.badssl.com"; - private const string _httpHost = "http.badssl.com"; - private const string _revokedHost = "revoked.badssl.com"; - private const string _expiredHost = "expired.badssl.com"; + private const string ValidHost = "microsoft.com"; + + // TODO: BadSSL is archived, tests might break in the future: https://github.com/chromium/badssl.com + private const string HttpHost = "http.badssl.com"; + private const string RevokedHost = "revoked.badssl.com"; + private const string ExpiredHost = "expired.badssl.com"; [Fact] public async Task be_healthy_if_ssl_is_valid() @@ -21,9 +20,7 @@ public async Task be_healthy_if_ssl_is_valid() services.AddHealthChecks() .AddSslHealthCheck(options => { - options.AddHost(_validHost256); - options.AddHost(_validHost384); - options.AddHost(_validHost512); + options.AddHost(ValidHost, checkLeftDays: 0); }, tags: ["ssl"]); }) .Configure(app => @@ -48,7 +45,7 @@ public async Task be_unhealthy_if_ssl_is_not_present() .ConfigureServices(services => { services.AddHealthChecks() - .AddSslHealthCheck(options => options.AddHost(_httpHost, 80), tags: ["ssl"]); + .AddSslHealthCheck(options => options.AddHost(HttpHost, 80), tags: ["ssl"]); }) .Configure(app => { @@ -72,7 +69,7 @@ public async Task be_unhealthy_if_ssl_is_not_valid() .ConfigureServices(services => { services.AddHealthChecks() - .AddSslHealthCheck(options => options.AddHost(_revokedHost), tags: ["ssl"]); + .AddSslHealthCheck(options => options.AddHost(RevokedHost), tags: ["ssl"]); }) .Configure(app => { @@ -96,7 +93,7 @@ public async Task be_unhealthy_if_ssl_is_expired() .ConfigureServices(services => { services.AddHealthChecks() - .AddSslHealthCheck(options => options.AddHost(_expiredHost), tags: ["ssl"]); + .AddSslHealthCheck(options => options.AddHost(ExpiredHost), tags: ["ssl"]); }) .Configure(app => { @@ -120,7 +117,7 @@ public async Task be_degraded_if_ssl_daysbefore() .ConfigureServices(services => { services.AddHealthChecks() - .AddSslHealthCheck(options => options.AddHost(_validHost256, checkLeftDays: 1095), tags: ["ssl"]); + .AddSslHealthCheck(options => options.AddHost(ValidHost, checkLeftDays: 1095), tags: ["ssl"]); }) .Configure(app => { @@ -143,7 +140,7 @@ public async Task be_degraded_if_ssl_daysbefore() public async Task respect_configured_timeout_and_throw_operation_cancelled_exception() { var options = new SslHealthCheckOptions(); - options.AddHost("invalid", 5555); + options.AddHost("10.255.255.255", 5555); var sslHealthCheck = new SslHealthCheck(options); diff --git a/test/HealthChecks.Network.Tests/Functional/TcpHealthCheckTests.cs b/test/HealthChecks.Network.Tests/Functional/TcpHealthCheckTests.cs index 77f88e4288..0af734166a 100644 --- a/test/HealthChecks.Network.Tests/Functional/TcpHealthCheckTests.cs +++ b/test/HealthChecks.Network.Tests/Functional/TcpHealthCheckTests.cs @@ -9,8 +9,8 @@ public async Task respect_configured_timeout_and_throw_operation_cancelled_excep { var options = new TcpHealthCheckOptions(); - options.AddHost("invalid", 5555); - options.AddressFamily = AddressFamily.InterNetworkV6; + options.AddHost("10.255.255.255", 5555); + options.AddressFamily = AddressFamily.InterNetwork; var tcpHealthCheck = new TcpHealthCheck(options); diff --git a/test/HealthChecks.Network.Tests/HealthChecks.Network.Tests.csproj b/test/HealthChecks.Network.Tests/HealthChecks.Network.Tests.csproj index 948765027f..003a17fc3c 100644 --- a/test/HealthChecks.Network.Tests/HealthChecks.Network.Tests.csproj +++ b/test/HealthChecks.Network.Tests/HealthChecks.Network.Tests.csproj @@ -5,12 +5,12 @@ - + - - PreserveNewest + + PreserveNewest diff --git a/test/HealthChecks.Network.Tests/Resources/docker-mailserver/certs/private.key b/test/HealthChecks.Network.Tests/Resources/docker-mailserver/certs/private.key new file mode 100644 index 0000000000..81c5d40e57 --- /dev/null +++ b/test/HealthChecks.Network.Tests/Resources/docker-mailserver/certs/private.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDAHzRN0ooNejiF +ZzBwJpobEz04PZbXSbLKUD+VmrQVNz5zYATTK2vYuakEEVBAizpqDI45bgN0Zkog +FanAoAN2wNspmO/BAvjJrEnlz6PaasImPo7mctHyVqX3bRM/BTAEp03i5FlbiTfE +Jas3NTiL8z0QqhX1vuCcrzEQTIXMGXAfgXt6EgwfnsdMcYLzgqV3paNG4ePEdSc+ +byl2bWHNCNMXPNrQ04+Mk6OuLqfZlw4bCCmxsjt9hkeIMIfdRQ5Vn8IrnsbXW/by +LaHRJFGyR2KwsQSlUBjYP5hm1sPUPz/CBEHmDAKfpZmQs8RV2vEpxREXVVK9IAJk +2cvty66zAgMBAAECggEBALSc4UQEGQrAiuBG+Q+GCrxHYvc7V1I/k5iExrHzRTbo +v4ohi4emO3X8XHtZd3OmMB1AfnhZB2BnRWpSU0qmY3tBpQe/Ii32iEK3+KTWhniw +gqMHjrnw2ZSUhuRLo5tMWi8Vxa/28laOcmGw8/wryWQwIIlJDOoBLxG91Uc4WVRc +OBQzsHzzyn7+7JRhR8tlAQ1zBTXSMMcr1cLeOoFPomImtqOgxSKUnCOtnLIw+tV6 +ADD+u/dPZjzBS+XFlPByk0CrsZ1UgYH8uaFrnnhLTuvRb4P8hbQMkwHVPYq/qbEW +ZWWNfr1Ct9KgggWs1zlrQ7fEGUpmYSWLzjydGpCf/+ECgYEA6t6gP5X4HHrzDt7c +gk2m3mvKoB9dvVjgvrTKLRnqU1bYUc3Dw6uZmuBJlA2ztXicerAPW9s8HLwWSiig +ELIv+zpUtonhc/Qv/udEZHZaSv38nK/IsZKNKXQm9grgQNIdYzx3OhXr/FUXcf8j +IjWVXQZbJyiS1bPNDkylkT2OvdECgYEA0WgJ2OJ9/CWW4mSw0fmXzFaI7PAMT28J +0tFvtjARgdMnw3jimybMTtRHbvdtV8ctqxoZ+GGzlqRjDVyiCvPjUYtYEPvEhFXQ +cBD46+X8axp9T4Gvuqlpbxm8SRdPvaEqDrLrwM/GL8/Ny6pRRtdvWn6V8we+54pR +wwq08w0rMUMCgYBN9wbk9Kh+88VZa1txmctJzChgDOl2IFnClIsEe7TQY2S9ivtw +Kbd8tPVXw1Cjbd0r0OPYTydeNoWDqoav5CaPU+apDY4cirOf/y8x1iPU/wjrDmMl +pwta9ma0iBm3Csicl4bQblR+19RHkDUedwEU9zYtAofzjpMEKydO1kta8QKBgQCV +N7msnth/kJmQAYguV9jfdtpjXDqpb8pkO3GLNX2EMV8oXz+6p0727TVp0U5NOlVE +k3jmEVjTg5hBsTyW6WuWc+DxWTaTxkKdWLrH/j58Y4ff293I+Wd0D7anrsDXs7ww +dTahUm07LKzM8DSyclma9pELeP2EKIBSp5KBj2Sz2QKBgQCB58hQSmFwabY/HOhz +vjPUfVl7dQW3Qh99pyIzJLTbYuVrtOGAe91jj39pMcae2AApshv1P+CHdUIdc+lb +19UDQ3EsezMayK0FUX1jXMPeSngGllqAMDX/D9AaPtYwnZYcaOsQecp5yENPFKYm +nLpGS9lBnFzQHLlYquayP7OwxQ== +-----END PRIVATE KEY----- diff --git a/test/HealthChecks.Network.Tests/Resources/docker-mailserver/certs/public.crt b/test/HealthChecks.Network.Tests/Resources/docker-mailserver/certs/public.crt new file mode 100644 index 0000000000..5d3b16cb9a --- /dev/null +++ b/test/HealthChecks.Network.Tests/Resources/docker-mailserver/certs/public.crt @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC9jCCAd6gAwIBAgIJANGdx9rZBKBsMA0GCSqGSIb3DQEBCwUAMB0xGzAZBgNV +BAMMEm1haWwuYmVhdHB1bHNlLmNvbTAeFw0yNTA4MTcxMTMzMTNaFw0zNTA4MTUx +MTMzMTNaMB0xGzAZBgNVBAMMEm1haWwuYmVhdHB1bHNlLmNvbTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAMAfNE3Sig16OIVnMHAmmhsTPTg9ltdJsspQ +P5WatBU3PnNgBNMra9i5qQQRUECLOmoMjjluA3RmSiAVqcCgA3bA2ymY78EC+Mms +SeXPo9pqwiY+juZy0fJWpfdtEz8FMASnTeLkWVuJN8Qlqzc1OIvzPRCqFfW+4Jyv +MRBMhcwZcB+Be3oSDB+ex0xxgvOCpXelo0bh48R1Jz5vKXZtYc0I0xc82tDTj4yT +o64up9mXDhsIKbGyO32GR4gwh91FDlWfwiuextdb9vItodEkUbJHYrCxBKVQGNg/ +mGbWw9Q/P8IEQeYMAp+lmZCzxFXa8SnFERdVUr0gAmTZy+3LrrMCAwEAAaM5MDcw +NQYDVR0RBC4wLIISbWFpbC5iZWF0cHVsc2UuY29thwR/AAABhxAAAAAAAAAAAAAA +AAAAAAABMA0GCSqGSIb3DQEBCwUAA4IBAQBP+Dvt0zbcr+4e64bVwGLe4vFx8Vq8 +KBgIcusNdQSox/aiYC5AnCtzsPAxUAJQYyrP0iEvwpilZLwFdWCnBVHbt0AiMYzd +Zwj/aiCXOUEmusOZsSJkiPYhQHPjgjKeCRNs7RqA20Lw+2ZfiPRRPbfaZgVhkP68 +slvoe4QT2I76Mm3gGxnrL2xD8+G7OlVJiNeMvmbayisBdHd6PEn95W6bmHZcdKpZ ++0nmt/2SBw+vXGD9nwSjee9JnA6orUa7leZ0wGsEh/o6cI4jyA09vxt3bL6LV8xs +9+3FVYhZ7/kjEUnzM6pWK/nGU17GelPvhIqnTg/GL9sowVKz9VlMG0if +-----END CERTIFICATE----- diff --git a/test/HealthChecks.Network.Tests/id_rsa b/test/HealthChecks.Network.Tests/Resources/sftpgo/keys/id_rsa similarity index 100% rename from test/HealthChecks.Network.Tests/id_rsa rename to test/HealthChecks.Network.Tests/Resources/sftpgo/keys/id_rsa diff --git a/test/HealthChecks.Network.Tests/Resources/sftpgo/keys/id_rsa.pub b/test/HealthChecks.Network.Tests/Resources/sftpgo/keys/id_rsa.pub new file mode 100644 index 0000000000..2762cc6fca --- /dev/null +++ b/test/HealthChecks.Network.Tests/Resources/sftpgo/keys/id_rsa.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDp8U07cuv1NVZs/7mLmfYZgSj4f0MKh9WXpxn+Ka1TbPOsyot90n62+SVsB01blFcLwFBvveDv+PAKsPLG6L+Jxsja0Q6bA4DEjz0nvdYFR8eNV66zTPTrJaf2yEWP18c52eV/E+7bVsWC9FQHpL+5L1dckQN6asK+H4HzTa8p/lVbzNk6bg4/kiGyxGyisDCtCznejcrSYf5544FmIxg1D98YTfE6abUR5lOXqqgD3q23jg/ZE/0n+6c7oURWfPYCo1sfqKZdJ9j1EV7wGp/+2UG19P7sFUMUlQQdT1Gmn87XtmA9yCctGSQi6tsF3Lr49zx7StY2P784H6EAvcyp carlo@Demon