Files
Rendezvous/tests/FinalFactory.Rendezvous.Tests/Deployment/DeploymentOptionsTests.cs
KyuubiYoru 08729ae25c
quality-gate / quality (push) Failing after 1m9s
quality-gate / container (push) Has been skipped
feat(deployment): add secure Linux runtime (#17)
2026-07-16 15:03:04 +02:00

138 lines
5.0 KiB
C#

using FinalFactory.Rendezvous.Server.Abuse;
using FinalFactory.Rendezvous.Server.Deployment;
namespace FinalFactory.Rendezvous.Tests.Deployment;
public sealed class DeploymentOptionsTests
{
[Fact]
public void ProductionConfigurationAcceptsExplicitPublicEndpointsAndTrustBoundary()
{
DeploymentOptions options = ValidOptions();
AbuseProtectionOptions abuse = new()
{
TrustedProxyAddresses = ["192.0.2.10"],
};
IReadOnlyList<string> errors = options.ValidateProduction(
abuse,
"rendezvous.finalfactory.at");
Assert.Empty(errors);
}
[Fact]
public void ProductionConfigurationRejectsUnsafeAndAmbiguousDefaults()
{
DeploymentOptions options = new()
{
SingleActiveInstance = false,
};
IReadOnlyList<string> errors = options.ValidateProduction(
new AbuseProtectionOptions(),
"*");
Assert.Contains(errors, error => error.Contains("SingleActiveInstance", StringComparison.Ordinal));
Assert.Contains(errors, error => error.Contains("PublicHttpBaseUrl", StringComparison.Ordinal));
Assert.Contains(errors, error => error.Contains("PublicUdpHost", StringComparison.Ordinal));
Assert.Contains(errors, error => error.Contains("TrustedProxyAddresses", StringComparison.Ordinal));
Assert.Contains(errors, error => error.Contains("AllowedHosts", StringComparison.Ordinal));
}
[Theory]
[InlineData("http://rendezvous.example.com/")]
[InlineData("https://user@example.com/")]
[InlineData("https://rendezvous.example.com/path")]
[InlineData("https://localhost/")]
[InlineData("https://10.0.0.1/")]
[InlineData("https://192.0.2.10/")]
[InlineData("https://[::ffff:10.0.0.1]/")]
[InlineData("https://[ff02::1]/")]
[InlineData("https://rendezvous.invalid/")]
public void ProductionConfigurationRejectsUnsafeHttpEndpoint(string endpoint)
{
DeploymentOptions options = ValidOptions() with { PublicHttpBaseUrl = endpoint };
IReadOnlyList<string> errors = options.ValidateProduction(
new AbuseProtectionOptions { TrustedProxyAddresses = ["192.0.2.10"] },
"rendezvous.finalfactory.at");
Assert.Contains(errors, error => error.Contains("PublicHttpBaseUrl", StringComparison.Ordinal));
}
[Theory]
[InlineData("0.1.2.3")]
[InlineData("100.64.0.1")]
[InlineData("192.0.2.1")]
[InlineData("198.18.0.1")]
[InlineData("198.51.100.1")]
[InlineData("203.0.113.1")]
[InlineData("224.0.0.1")]
[InlineData("255.255.255.255")]
[InlineData("::ffff:192.168.1.1")]
[InlineData("2001:db8::1")]
[InlineData("ff02::1")]
[InlineData("rendezvous.example.com")]
[InlineData("rendezvous.home.arpa")]
[InlineData("rendezvous.alt")]
[InlineData("service.test")]
public void ProductionConfigurationRejectsNonPublicUdpEndpoint(string endpoint)
{
DeploymentOptions options = ValidOptions() with { PublicUdpHost = endpoint };
IReadOnlyList<string> errors = options.ValidateProduction(
new AbuseProtectionOptions { TrustedProxyAddresses = ["192.0.2.10"] },
"rendezvous.finalfactory.at");
Assert.Contains(errors, error => error.Contains("PublicUdpHost", StringComparison.Ordinal));
}
[Fact]
public void IsolatedSmokeTestRequiresExplicitPrivateEndpointOverride()
{
DeploymentOptions options = ValidOptions() with
{
PublicHttpBaseUrl = "https://localhost/",
PublicUdpHost = "127.0.0.1",
AllowPrivatePublicEndpoints = true,
};
IReadOnlyList<string> errors = options.ValidateProduction(
new AbuseProtectionOptions { TrustedProxyAddresses = ["127.0.0.1"] },
"localhost");
Assert.Empty(errors);
}
[Fact]
public void ProductionConfigurationRejectsInvalidPortsDeadlinesAndMismatchedHostFilter()
{
DeploymentOptions options = ValidOptions() with
{
PublicUdpPort = 0,
DrainDeadlineSeconds = 31,
MinimumDrainSeconds = 6,
};
IReadOnlyList<string> errors = options.ValidateProduction(
new AbuseProtectionOptions { TrustedProxyAddresses = ["192.0.2.10"] },
"different.finalfactory.at");
Assert.Contains(errors, error => error.Contains("PublicUdpPort", StringComparison.Ordinal));
Assert.Contains(errors, error => error.Contains("DrainDeadlineSeconds", StringComparison.Ordinal));
Assert.Contains(errors, error => error.Contains("MinimumDrainSeconds", StringComparison.Ordinal));
Assert.Contains(errors, error => error.Contains("exact host", StringComparison.Ordinal));
}
private static DeploymentOptions ValidOptions() => new()
{
PublicHttpBaseUrl = "https://rendezvous.finalfactory.at/",
PublicUdpHost = "rendezvous-udp.finalfactory.at",
PublicUdpPort = 9050,
DrainDeadlineSeconds = 10,
MinimumDrainSeconds = 1,
SingleActiveInstance = true,
};
}