feat: add certificate v2 WireGuard binding#132
Conversation
There was a problem hiding this comment.
Pull request overview
This PR introduces NodeCertificate v2 to MeshGuard’s trust model and wire protocol, adding an org-signed WireGuard public-key binding and a one-hop delegated issuer mechanism (org -> issuer -> device). It maintains backwards compatibility by continuing to accept legacy v1 (186-byte) certificates during rollout, while standardizing the on-wire cert slot to 314 bytes.
Changes:
- Bump org-certificate wire slot size to 314 bytes and update codec parsing to accept legacy v1 extensions.
- Add v2 certificate serialization/parsing + verification, including WG key binding and delegated issuer grant/signature verification.
- Extend SWIM admission/revocation logic to support delegated issuer revocation evicting leaves, and update CLI/docs for v1/v2 migration and
org-sign --wg-pubkey.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/protocol/messages.zig | Updates org cert wire size constant to 314 for v2 slot. |
| src/protocol/codec.zig | Decodes org-cert extension with v1 compatibility; adds tests for legacy acceptance. |
| src/main.zig | Adds --wg-pubkey to org-sign, prints cert version, and uses updated cert wire sizing. |
| src/identity/org.zig | Implements NodeCertificate v2 fields, serialization/deserialization, delegated issuance, and signature verification; adds tests. |
| src/discovery/swim.zig | Binds WG pubkey from signed cert, tracks delegated issuer pubkey, and evicts leaves on issuer revocation; adds tests covering attack/regression cases. |
| src/discovery/membership.zig | Adds cert_issuer_pubkey to peer state for delegated admission tracking. |
| README.md | Documents v1 vs v2 cert outputs and sizes; shows org-sign --wg-pubkey usage. |
| docs/reference/cli.md | Updates org-sign CLI reference and migration guidance. |
| docs/guide/trust-model.md | Documents v1/v2 cert formats, delegation semantics, and rollout policy. |
| docs/concepts/wire-protocol.md | Updates org-cert extension format and v1 compatibility behavior. |
| docs/concepts/swim-discovery.md | Updates MTU/size discussion for v2-sized extensions. |
| docs/concepts/security.md | Updates node certificate sizing and description. |
| docs/concepts/identity-and-trust.md | Updates certificate description to include v2 WG binding. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (pos + ORG_CERT_V1_EXTENSION_SIZE > data.len) return; | ||
| @memset(cert, 0); | ||
| const available = data.len - pos - 1; | ||
| const copy_len = @min(available, messages.ORG_CERT_WIRE_SIZE); | ||
| @memcpy(cert[0..copy_len], data[pos + 1 ..][0..copy_len]); |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c43ed471ab
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (self.handler) |h| { | ||
| h.onPeerJoin(h.ctx, peer); |
There was a problem hiding this comment.
Defer cert-bound joins until gossip metadata is applied
When a new v2-certified peer pings, handlePing records the certificate before iterating ping.gossip(), so this onPeerJoin fires as soon as the signed WG key is set. In kernel mode wgOnPeerJoin only programs a WireGuard endpoint when the peer's NAT type is already .public (src/main.zig:1904-1920); at this point NAT/public endpoint metadata carried in the same gossip packet has not been applied yet, and later applyGossip will not re-fire because wg_pubkey is already non-null. Public v2 peers can therefore be added to kernel WireGuard without an endpoint and never get updated.
Useful? React with 👍 / 👎.
Summary
Closes #124.
org -> issuer -> deviceadmission can be verified, and issuer revocation evicts admitted leavesorg-sign --wg-pubkey,config show, and trust/wire-protocol docs for v2 certsValidation
zig build test --summary allzig build --summary allzig build -Dtarget=x86_64-linux-gnu -Dno-sodium=true --summary allzig build -Dtarget=x86_64-macos -Doptimize=ReleaseFast --summary allzig build -Dtarget=x86_64-freebsd -Doptimize=ReleaseFast --summary allgit diff --checkorg-sign --wg-pubkey, verified 314-byte v2 cert output, and confirmedconfig showreports v2 plus the bound WireGuard key