fix: installer checks containers only; the panel reads signed manifests from the registry when it has none; unsigned-updater nodes are labeled from the panel's manifests; sign node release images; release 0.3.0 [CI]
This commit is contained in:
1 parent
4a1e48db20
commit
879d1c8593
15 files changed
+372
-18
No files matched your search
@@ -29,12 +29,14 @@ public sealed class BinaryBindingService : IBinaryAttestor
|
||||
public const string Off = "off";
|
||||
|
||||
private readonly INodeBindingStore _store;
|
||||
private readonly ISettingsStore _settings;
|
||||
private readonly IReleaseKey _key;
|
||||
private readonly BackendOptions _options;
|
||||
private readonly TimeProvider _time;
|
||||
|
||||
public BinaryBindingService(INodeBindingStore store, IReleaseKey key, BackendOptions options, TimeProvider time)
|
||||
public BinaryBindingService(INodeBindingStore store, ISettingsStore settings, IReleaseKey key, BackendOptions options, TimeProvider time)
|
||||
{
|
||||
_settings = settings;
|
||||
_store = store;
|
||||
_key = key;
|
||||
_options = options;
|
||||
@@ -72,18 +74,22 @@ public sealed class BinaryBindingService : IBinaryAttestor
|
||||
return new BinaryDecision(policy != Enforce, "the reported binary hash is malformed");
|
||||
}
|
||||
|
||||
Official? official = VerifyManifest(evidence, component);
|
||||
// 节点自己带来的清单(宿主机更新器验过的那份);没有更新器的节点(一键容器安装、二进制安装)没有,就用面板自己手里的:
|
||||
// 面板登记它们时已经验过 CI 签名,这里再验一遍。只有节点自带的清单才能因为「不在清单里」而被拒绝,面板手里的只用来把绑定标成已签名。
|
||||
Official? official = VerifyManifest(evidence.Manifest, evidence.Signature, component);
|
||||
bool carried = official is not null;
|
||||
official ??= await StoredOfficialAsync(component, ct);
|
||||
bool listed = official is not null && official.Binaries.Contains(hash);
|
||||
|
||||
if (binding is null)
|
||||
{
|
||||
if (official is not null && !listed)
|
||||
if (carried && !listed)
|
||||
{
|
||||
// 带着一份有效的签名清单,自己的哈希却不在里面:它不是这份清单对应的官方二进制
|
||||
return new BinaryDecision(policy != Enforce, "this binary is not in the CI-signed manifest it was installed from");
|
||||
}
|
||||
|
||||
await _store.UpsertAsync(new NodeBinding(node.Id.Value, hash, official?.Seq ?? 0, listed, now, null, null), ct);
|
||||
await _store.UpsertAsync(new NodeBinding(node.Id.Value, hash, listed ? official!.Seq : 0, listed, now, null, null), ct);
|
||||
return new BinaryDecision(true);
|
||||
}
|
||||
|
||||
@@ -120,10 +126,13 @@ public sealed class BinaryBindingService : IBinaryAttestor
|
||||
private sealed record Official(long Seq, HashSet<string> Binaries);
|
||||
|
||||
/// <summary>用内嵌的 CI 公钥验清单;验过且是这个组件的才返回它列出的官方二进制哈希。</summary>
|
||||
private Official? VerifyManifest(BinaryEvidence evidence, string component)
|
||||
private async ValueTask<Official?> StoredOfficialAsync(string component, CancellationToken ct) =>
|
||||
VerifyManifest(await _settings.GetAsync(ReleaseService.Key(component, "manifest"), ct), await _settings.GetAsync(ReleaseService.Key(component, "signature"), ct), component);
|
||||
|
||||
private Official? VerifyManifest(string? manifestText, string? signatureText, string component)
|
||||
{
|
||||
if (evidence.Manifest is not { Length: > 0 and <= ReleaseService.MaxManifestBytes } manifest
|
||||
|| evidence.Signature is not { Length: > 0 and <= ReleaseService.MaxSignatureBytes } signature
|
||||
if (manifestText is not { Length: > 0 and <= ReleaseService.MaxManifestBytes } manifest
|
||||
|| signatureText is not { Length: > 0 and <= ReleaseService.MaxSignatureBytes } signature
|
||||
|| !ReleaseSignature.Verify(_key.Pem, manifest, signature))
|
||||
{
|
||||
return null;
|
||||
|
||||
Reference in new issue
Block a user