feat: every agent and probe must have an owner passkey, enforced by the panel, the installers and fleet-enroll [CI]

This commit is contained in:
justme committed 2026-10-08 06:04:04 +08:00
1 parent 0b384a58f5
commit 8c37db1577
14 files changed
+207 -12

No files matched your search

@@ -0,0 +1,32 @@
using Fleet.Core;
using Fleet.Identity;
namespace MoShiro.Backend.Application;
/// <summary>
/// 节点的属主:创建加入码时选定的 passkey 凭证 id,写进安装命令,节点注册时固定在本地。
/// 属主必须是操作员集合里的凭证;<see cref="BackendOptions.RequireOwner"/> 打开时(默认)必须已经有信任根,并且至少选一把——
/// 不选属主的节点没有人能授权它的敏感操作,也就不该存在。没有明确指定时默认是操作员集合里的全部 passkey。
/// </summary>
public static class OwnerPolicy
{
public static Result<string[]> Resolve(bool required, OperatorSet? set, IReadOnlyList<string>? requested)
{
if (set is null)
{
return required
? ValidationError.Fail<string[]>("controllers", "set up the trust root first (System, Trust): every node needs an owner passkey")
: Result<string[]>.Ok([]);
}
string[] chosen = requested is null ? [.. set.Keys.Select(k => k.CredentialId)] : [.. requested.Distinct(StringComparer.Ordinal)];
if (chosen.Any(c => set.Keys.All(k => k.CredentialId != c)))
{
return ValidationError.Fail<string[]>("controllers", "must be passkeys of the operator set");
}
return required && chosen.Length == 0
? ValidationError.Fail<string[]>("controllers", "pick at least one owner passkey: a node's owner is who its sensitive sessions and data are bound to")
: Result<string[]>.Ok(chosen);
}
}
@@ -26,6 +26,12 @@ public sealed class BackendOptions
/// </summary>
public string BinaryPolicy { get; set; } = "enforce";
/// <summary>
/// 每个 Agent 和 Probe 都必须有属主(passkey):创建加入码时必须已经建立信任根,并且至少选一把操作员集合里的 passkey 作为属主。
/// 属主是节点敏感内容(extension 会话、加密数据)绑定的人,装上时固定在节点本地,面板改不了。默认开;没有信任根的老部署才需要关掉。
/// </summary>
public bool RequireOwner { get; set; } = true;
/// <summary>面板的对外地址(用于生成安装命令)。</summary>
public string? PublicUrl { get; set; }