37 lines
1.5 KiB
C#
37 lines
1.5 KiB
C#
|
|
using System.Net;
|
||
|
|
using w4c_workflows.Services.Security;
|
||
|
|
using Xunit;
|
||
|
|
|
||
|
|
namespace w4c_workflows.Tests;
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// P0-8: egress clients must re-validate the resolved address at connect time, so
|
||
|
|
/// a DNS name that answers with a public address for the pre-flight guard and a
|
||
|
|
/// private one for the real connection cannot be reached.
|
||
|
|
/// </summary>
|
||
|
|
public class EgressPinningTests
|
||
|
|
{
|
||
|
|
[Fact]
|
||
|
|
public async Task Connect_is_blocked_when_the_host_resolves_to_a_private_address()
|
||
|
|
{
|
||
|
|
var resolver = StubHostAddressResolver.Returning("10.1.2.3");
|
||
|
|
using var handler = EgressPinning.CreateHandler(EgressTestData.Policy(), resolver);
|
||
|
|
using var client = new HttpClient(handler);
|
||
|
|
|
||
|
|
var ex = await Assert.ThrowsAsync<HttpRequestException>(
|
||
|
|
() => client.GetAsync("http://rebind.example/resource"));
|
||
|
|
|
||
|
|
// The connect callback reports the block; the transport may wrap it.
|
||
|
|
Assert.Contains("egress blocked", ex.ToString(), StringComparison.OrdinalIgnoreCase);
|
||
|
|
Assert.Contains("rebind.example", resolver.Queries);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Fact]
|
||
|
|
public void Skips_address_checks_for_allow_listed_hosts_and_private_mode()
|
||
|
|
{
|
||
|
|
Assert.True(EgressTestData.Policy(o => o.AllowPrivateNetworks = true).SkipsAddressChecks("any.test"));
|
||
|
|
Assert.True(EgressTestData.Policy(o => o.AllowedHosts = ["allowed.test"]).SkipsAddressChecks("allowed.test"));
|
||
|
|
Assert.False(EgressTestData.Policy().SkipsAddressChecks("blocked.test"));
|
||
|
|
}
|
||
|
|
}
|