104 lines
4.7 KiB
C#
104 lines
4.7 KiB
C#
using System.Net;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using MoShiro.Backend.Application;
|
|
using MoShiro.Protocol;
|
|
using System.Text.Json.Nodes;
|
|
using MoShiro.TestSupport;
|
|
|
|
namespace MoShiro.Backend.Tests;
|
|
|
|
/// <summary>public_host 和 ipv6_host 自动识别:Agent 上报公网地址,手填的优先,可以撤销手填。</summary>
|
|
[Collection("probe-e2e")]
|
|
public sealed class AddressTests
|
|
{
|
|
private const string V4 = "8.8.4.4";
|
|
private const string V6 = "2606:4700:4700::1111";
|
|
private readonly BackendFixture _backend;
|
|
|
|
public AddressTests(BackendFixture backend)
|
|
{
|
|
_backend = backend;
|
|
}
|
|
|
|
private async Task<JsonNode> AgentAsync(string id) => await _backend.GetJsonAsync(_backend.Admin, "/api/admin/agents/" + id);
|
|
|
|
private async Task<JsonNode> PatchAsync(string id, JsonObject body)
|
|
{
|
|
using HttpResponseMessage response = await _backend.Admin.PatchAsync("/api/admin/agents/" + id, BackendFixture.Json(body));
|
|
string text = await response.Content.ReadAsStringAsync();
|
|
Assert.True(response.IsSuccessStatusCode, text);
|
|
return JsonNode.Parse(text)!;
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Hello_FillsPublicHostAndIpv6Host_PrivateAndTemporaryAddressesAreIgnored()
|
|
{
|
|
await using AgentSimulator agent = await _backend.ConnectAgentAsync(hello: false);
|
|
agent.Addresses = ["10.0.0.5", "192.168.1.9", "fd00::1", "fe80::1", V6, V4];
|
|
await agent.HelloAsync();
|
|
|
|
JsonNode view = null!;
|
|
await BackendFixture.EventuallyAsync(async () => (view = await AgentAsync(agent.NodeId.Value))["ipv6_host"]!.GetValue<string>() == V6);
|
|
Assert.Equal(V4, view["public_host"]!.GetValue<string>());
|
|
Assert.True(view["public_host_auto"]!.GetValue<bool>());
|
|
Assert.True(view["ipv6_host_auto"]!.GetValue<bool>());
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ManualValues_WinOverAutoDetection_AndCanBeRevokedBackToAuto()
|
|
{
|
|
await using AgentSimulator agent = await _backend.ConnectAgentAsync(hello: false);
|
|
string id = agent.NodeId.Value;
|
|
agent.Addresses = [V4, V6];
|
|
await agent.HelloAsync();
|
|
await BackendFixture.EventuallyAsync(async () => (await AgentAsync(id))["ipv6_host"]!.GetValue<string>() == V6);
|
|
|
|
// 手填:标记为手动,之后 Agent 再上报别的地址也不覆盖
|
|
JsonNode manual = await PatchAsync(id, new JsonObject { ["public_host"] = "agent.example.net", ["ipv6_host"] = "" });
|
|
Assert.False(manual["public_host_auto"]!.GetValue<bool>());
|
|
Assert.False(manual["ipv6_host_auto"]!.GetValue<bool>());
|
|
agent.Addresses = ["1.1.1.1", "2606:4700:4700::1001"];
|
|
await agent.HelloAsync();
|
|
await Task.Delay(300);
|
|
JsonNode kept = await AgentAsync(id);
|
|
Assert.Equal("agent.example.net", kept["public_host"]!.GetValue<string>());
|
|
Assert.Equal("", kept["ipv6_host"]!.GetValue<string>()); // 空 = 手动关闭 IPv6
|
|
|
|
// 撤销手填:马上按最近一次上报的地址重新识别
|
|
JsonNode auto = await PatchAsync(id, new JsonObject { ["public_host_auto"] = true, ["ipv6_host_auto"] = true });
|
|
Assert.Equal("1.1.1.1", auto["public_host"]!.GetValue<string>());
|
|
Assert.Equal("2606:4700:4700::1001", auto["ipv6_host"]!.GetValue<string>());
|
|
Assert.True(auto["public_host_auto"]!.GetValue<bool>());
|
|
}
|
|
|
|
[Fact]
|
|
public async Task AutoDetectedAddress_StaysWhileItIsStillReported_SoReorderingDoesNotFlap()
|
|
{
|
|
await using AgentSimulator agent = await _backend.ConnectAgentAsync(hello: false);
|
|
string id = agent.NodeId.Value;
|
|
agent.Addresses = [V4, "9.9.9.9"];
|
|
await agent.HelloAsync();
|
|
await BackendFixture.EventuallyAsync(async () => (await AgentAsync(id))["public_host"]!.GetValue<string>() == V4);
|
|
|
|
agent.Addresses = ["1.0.0.1", V4];
|
|
await agent.HelloAsync();
|
|
await Task.Delay(300);
|
|
Assert.Equal(V4, (await AgentAsync(id))["public_host"]!.GetValue<string>());
|
|
|
|
// 原来的地址不见了才换
|
|
agent.Addresses = ["1.0.0.1"];
|
|
await agent.HelloAsync();
|
|
await BackendFixture.EventuallyAsync(async () => (await AgentAsync(id))["public_host"]!.GetValue<string>() == "1.0.0.1");
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ProbeAgentList_CarriesTheCertificatePublicKeyTheAgentReported_ForPinningAndKnocking()
|
|
{
|
|
await using AgentSimulator agent = await _backend.ConnectAgentAsync();
|
|
AgentService service = _backend.Services.GetRequiredService<AgentService>();
|
|
ProbeAgentList list = await service.ProbeAgentsAsync(_backend.DefaultProbeId, default);
|
|
AgentEndpoint endpoint = Assert.Single(list.Agents, a => a.AgentId == agent.NodeId);
|
|
Assert.Equal(Convert.ToBase64String(agent.TlsPublicKey), endpoint.PublicKey);
|
|
}
|
|
}
|