feat!: probes generate their own keys and enroll with a join token; node and peer keys are separate [CI]
ci/woodpecker/push/main-amd64-build Pipeline was successful
ci/woodpecker/push/main-amd64-build Pipeline was successful
This commit is contained in:
1 parent
1ff847e45a
commit
a9f562441f
51 files changed
+505
-749
No files matched your search
@@ -19,6 +19,13 @@ public sealed class EnrollRequest
|
||||
[JsonPropertyName("tls_spki")]
|
||||
public string TlsSpki { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// 同一把 TLS 密钥的完整公钥(SPKI,base64),必须和 <see cref="TlsSpki"/> 对得上。节点用这把密钥做对等面的签名认证
|
||||
/// (和连服务端用的身份密钥是两把独立的密钥),对端要验签就需要完整的公钥,而不只是指纹。
|
||||
/// </summary>
|
||||
[JsonPropertyName("tls_pubkey")]
|
||||
public string TlsPublicKey { get; set; } = "";
|
||||
|
||||
/// <summary>持有证明:对 <c>fleet|v1|enroll|{sha256_hex(join_token)}|{pubkey}</c> 的签名(base64)。</summary>
|
||||
[JsonPropertyName("proof")]
|
||||
public string Proof { get; set; } = "";
|
||||
|
||||
@@ -29,9 +29,16 @@ public sealed partial class FleetEnrollmentService
|
||||
|
||||
if (!TryDecode(request.PublicKey, out byte[] publicKey) || !NodeIdentity.IsValidPublicKey(publicKey)
|
||||
|| !TryDecode(request.TlsSpki, out byte[] tlsSpki) || tlsSpki.Length != 32
|
||||
|| !TryDecode(request.TlsPublicKey, out byte[] tlsPublicKey) || !NodeIdentity.IsValidPublicKey(tlsPublicKey)
|
||||
|| !TryDecode(request.Proof, out byte[] proof))
|
||||
{
|
||||
return Result<EnrollResponse>.Fail(FleetErrors.InvalidParams, "pubkey, tls_spki or proof is malformed");
|
||||
return Result<EnrollResponse>.Fail(FleetErrors.InvalidParams, "pubkey, tls_spki, tls_pubkey or proof is malformed");
|
||||
}
|
||||
|
||||
// 指纹和完整公钥必须是同一把密钥,否则对端按指纹固定证书、按公钥验签,会各认各的
|
||||
if (!System.Security.Cryptography.CryptographicOperations.FixedTimeEquals(NodeIdentity.Fingerprint(tlsPublicKey), tlsSpki))
|
||||
{
|
||||
return Result<EnrollResponse>.Fail(FleetErrors.InvalidParams, "tls_spki does not match tls_pubkey");
|
||||
}
|
||||
|
||||
byte[] tokenHash = TokenHash.Sha256(request.JoinToken);
|
||||
@@ -61,8 +68,9 @@ public sealed partial class FleetEnrollmentService
|
||||
bool nameTaken = await _store.FindEstablishedNodeByNameAsync(request.Name, ct) is not null;
|
||||
NodeStatus status = token.AutoApprove && !nameTaken ? NodeStatus.Active : NodeStatus.Pending;
|
||||
|
||||
string prefix = token.Kind.Length > 0 && _options.NodeIdPrefixes.TryGetValue(token.Kind, out string? kindPrefix) ? kindPrefix : _options.NodeIdPrefix;
|
||||
var node = new NewNode(
|
||||
new NodeId(Ulid.NewPrefixed(_options.NodeIdPrefix, _time)),
|
||||
new NodeId(Ulid.NewPrefixed(prefix, _time)),
|
||||
request.Name,
|
||||
status,
|
||||
publicKey,
|
||||
@@ -70,7 +78,9 @@ public sealed partial class FleetEnrollmentService
|
||||
token.Labels,
|
||||
request.Meta?.GetRawText(),
|
||||
request.NodeVersion,
|
||||
nowMs);
|
||||
nowMs,
|
||||
token.Kind,
|
||||
tlsPublicKey);
|
||||
|
||||
Result<NodeRecord> created = await _store.CreateNodeAsync(node, ct);
|
||||
if (!created.TryGet(out NodeRecord? record, out FleetError? error))
|
||||
|
||||
Reference in new issue
Block a user