feat: pinned agents and probes only accept peers carrying the operator's proof; the panel ships the signed operator chain with the rosters [CI SKIP]

This commit is contained in:
justme committed 2026-10-07 23:24:33 +08:00
1 parent fc2bbdcc6d
commit 9bb6841dce
11 files changed
+129 -12

No files matched your search

@@ -1,5 +1,6 @@
using System.Text.Json;
using Fleet.Core;
using Fleet.Identity;
using Fleet.Hosting;
using MoShiro.Protocol;
@@ -16,11 +17,13 @@ public sealed class AgentDirectory
private readonly object _gate = new();
private readonly ConfigStore _store;
private readonly INodeLog _log;
private readonly TrustAnchor _trust;
private List<KnownAgent> _agents = [];
private long _version;
public AgentDirectory(ConfigStore store, string configDirectory, INodeLog log)
public AgentDirectory(ConfigStore store, string configDirectory, INodeLog log, TrustAnchor? trust = null)
{
_trust = trust ?? TrustAnchor.None;
_store = store;
_log = log;
string cache = Path.Combine(configDirectory, FileName);
@@ -64,12 +67,34 @@ public sealed class AgentDirectory
}
}
private static bool TryKey(string text, out byte[] key)
{
try
{
key = Convert.FromBase64String(text);
return key.Length > 0;
}
catch (FormatException)
{
key = [];
return false;
}
}
/// <summary>应用面板下发的列表。版本不比当前新的忽略(乱序到达的旧推送)。</summary>
public void Apply(ProbeAgentList result)
{
var next = new List<KnownAgent>();
_trust.Update(result.TrustChain);
foreach (AgentEndpoint agent in result.Agents)
{
// 固定了操作员创世的 Probe 只连操作员批准过的 Agent(证明验不过的,面板塞进来的也不连)
if (!TryKey(agent.PublicKey, out byte[] key) || _trust.VerifyPeer(agent.Proof, key, "agent") != TrustFailure.None)
{
_log.Warn("an agent from the panel carries no valid operator proof; not connecting", ("agent", agent.AgentId.Value));
continue;
}
if (!string.IsNullOrWhiteSpace(agent.Host))
{
next.Add(new KnownAgent { AgentId = agent.AgentId.Value, Host = agent.Host, TcpPort = agent.TcpPort, PublicKey = agent.PublicKey });
+1 -1
View File
@@ -27,7 +27,7 @@ public sealed class ProbeApp : IDisposable
public ProbeApp(ProbeFile file, LoadedNodeIdentity identity, string configDirectory, TimeProvider time, INodeLog log, RestartController? restart = null)
{
_log = log;
var directory = new AgentDirectory(new ConfigStore(configDirectory), configDirectory, log);
var directory = new AgentDirectory(new ConfigStore(configDirectory), configDirectory, log, TrustAnchor.Load(file.Fleet.IdentityDir, log));
_env = new ConnectionEnv(identity.PeerIdentity, identity.NodeId.Value, file.Limits, directory, new MonoClock(time), time, log);
directory.Changed += () => _changed.Release();