refactor(rotation): port netbird-ingress to netbird-key mode #335

Merged
k.renner merged 1 commits from feat/port-netbird-rotator into master 2026-07-21 22:43:44 +00:00
Member

Step 2 of 2. Ports the NetBird rotator from inline python to the binary's netbird-key mode (merged in #334). Net -30 lines.

Tested live end-to-end (via the real binary image)

job Complete: minted 'ingress-rotated', OpenBao rolled 8a0aa8d4 -> 77f1be0c
NetBird: 2 'ingress-rotated' keys now (new added, old KEPT — create-new)
ESO synced -> Reloader restarted the DaemonSet
rolling update (maxUnavailable 1) -> 3/3 ready, updated=3, 0 errors
new key: used_times=3, last_used just now  (all 3 pods enrolled)
pods actively handshaking peers (WireGuard/relay connected)
old key: still valid, untouched (expires naturally)

Real re-enrollment with no ingress outage — maxUnavailable=1 restarts one pod at a time, and create-new keeps the old key valid throughout, so there's no window.

Faithful port

Same POST /api/setup-keys body (reusable, ephemeral, 1yr expiry, auto_groups), same Token auth, same bootstrap PAT + target path. The binary stores the key verbatim (no trailing newline) and never deletes old keys.

Flux strips the old python command on apply (verified on the earlier ports); a manual kubectl apply would not — port via Flux.

Image digest sha256:49bfddd8…. After this merges, only pve-exporter remains on inline python.

🤖 Generated with Claude Code

Step 2 of 2. Ports the NetBird rotator from inline python to the binary's `netbird-key` mode (merged in #334). **Net -30 lines.** ## Tested live end-to-end (via the real binary image) ``` job Complete: minted 'ingress-rotated', OpenBao rolled 8a0aa8d4 -> 77f1be0c NetBird: 2 'ingress-rotated' keys now (new added, old KEPT — create-new) ESO synced -> Reloader restarted the DaemonSet rolling update (maxUnavailable 1) -> 3/3 ready, updated=3, 0 errors new key: used_times=3, last_used just now (all 3 pods enrolled) pods actively handshaking peers (WireGuard/relay connected) old key: still valid, untouched (expires naturally) ``` Real re-enrollment with no ingress outage — `maxUnavailable=1` restarts one pod at a time, and create-new keeps the old key valid throughout, so there's no window. ## Faithful port Same POST /api/setup-keys body (reusable, ephemeral, 1yr expiry, `auto_groups`), same `Token` auth, same bootstrap PAT + target path. The binary stores the key verbatim (no trailing newline) and never deletes old keys. Flux strips the old python `command` on apply (verified on the earlier ports); a manual `kubectl apply` would not — port via Flux. Image digest `sha256:49bfddd8…`. After this merges, **only pve-exporter remains** on inline python. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
claude-bot added 1 commit 2026-07-21 15:32:18 +00:00
Replaces the inline python NetBird rotator with the secret-rotator binary's
netbird-key mode. Net -30 lines; the login+POST+parse python and the
python:3.13-alpine image go away.

Mints a fresh reusable setup key via POST /api/setup-keys and patches it into
OpenBao. Create-new, not roll-in-place: the old key is left to expire, so
there is no window — it stays valid while the netbird-ingress DaemonSet
re-enrolls its pods on the new one. Nothing is deleted (deliberately — a past
manual delete-filter bug wiped unrelated keys).

Tested live end-to-end via the real binary image:
  - job Complete: minted 'ingress-rotated', OpenBao rolled 8a0aa8d4 -> 77f1be0c
  - NetBird now has 2 'ingress-rotated' keys (new added, old kept — create-new)
  - ESO synced; Reloader restarted the DaemonSet; rolling update (maxUnavailable
    1) completed 3/3 with 0 errors
  - all 3 pods re-enrolled: the new key shows used_times=3, last_used just now;
    pods actively handshaking peers (WireGuard/relay connected)
  - old key still valid, untouched

Flux server-side apply strips the old python `command` (verified on the other
ports); a manual `kubectl apply` would not, so port via Flux.

Image digest sha256:49bfddd8…

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
review-bot left a comment
Member

🤖 Automated review — model claude-sonnet-5 (complexity: normal), commit 92b59f7c8894354ce679e06dcf4cde132529d5b7.

Advisory review by the review-bot pipeline. It never approves; a human merges. Push new commits to get a fresh review.


Summary

PR #335 ports the netbird-ingress rotation CronJob from an inline Python script (embedded as a shell-style heredoc) to the secret-rotator binary's new netbird-key mode, following the pattern already established for the other rotators (crowdsec-bouncer-key.yaml, cloudflare.yaml, etc.). It's a manifest-only change (no Rust code touched here — netbird-key mode itself was added in the already-merged #334). I traced every env var the new manifest sets against secret-rotator/src/main.rs::rotate_netbird_key, netbird.rs, and bao.rs in the checkout, and the behavior is a faithful, correct port: same OpenBao role (rotator-netbird), same bootstrap/target KV paths, same default bootstrap field (pat) and target field (setup-key), same setup-key request body semantics (reusable, 1yr expiry, ephemeral, allow_extra_dns_labels, same auto_groups). No blocking issues found.

🟡 Suggestions

  • kubernetes/infrastructure/openbao/rotation/netbird-ingress.yaml:34 — the old inline # tested + enabled 2026-07-19 comment on suspend: false was dropped, and no equivalent note was added elsewhere in the file for this specific rollout. Not a defect, but the sibling files (e.g. crowdsec-bouncer-key.yaml's ON-DEMAND: kubectl ... create job ... line) keep an operational breadcrumb; consider whether this file should too, for consistency with the rest of the fleet.
  • The image digest (sha256:49bfddd8…) differs from every other rotator in this directory (which pin either 159e5888… for random/ha-token modes or 978fe53c… for cloudflare-roll). That's expected here since this is the first consumer of netbird-key mode, but worth flagging only because it means this job is now running a binary version no other CronJob has exercised in production yet — the live test in the PR description covers that risk directly, so this is just a note, not a concern.

🟢 Nits

  • netbird-ingress.yaml:52 — suspend: false is the default; the field is arguably redundant now that its explanatory comment is gone, but it was already present before this PR and isn't part of what changed here.

Tests

No unit tests accompany this change, but none are expected for a manifest-only diff — the actual rotation logic (rotate_netbird_key, create_setup_key, Bao::patch_field/assert_fields_exist) lives in secret-rotator and was presumably covered when netbird-key mode was introduced in #334. The PR body documents a live end-to-end test against the real cluster (key minted, ESO synced, DaemonSet rolled, new key handshaking, old key untouched) which is the appropriate validation for this kind of infra change and is more convincing than a unit test would be here.

Recommendation

Looks reasonable — no blocking issues; comments above are optional.

🤖 **Automated review** — model `claude-sonnet-5` (complexity: normal), commit `92b59f7c8894354ce679e06dcf4cde132529d5b7`. > Advisory review by the `review-bot` pipeline. It never approves; a human merges. Push new commits to get a fresh review. --- ## Summary PR #335 ports the `netbird-ingress` rotation CronJob from an inline Python script (embedded as a shell-style heredoc) to the `secret-rotator` binary's new `netbird-key` mode, following the pattern already established for the other rotators (`crowdsec-bouncer-key.yaml`, `cloudflare.yaml`, etc.). It's a manifest-only change (no Rust code touched here — `netbird-key` mode itself was added in the already-merged #334). I traced every env var the new manifest sets against `secret-rotator/src/main.rs::rotate_netbird_key`, `netbird.rs`, and `bao.rs` in the checkout, and the behavior is a faithful, correct port: same OpenBao role (`rotator-netbird`), same bootstrap/target KV paths, same default bootstrap field (`pat`) and target field (`setup-key`), same setup-key request body semantics (reusable, 1yr expiry, ephemeral, `allow_extra_dns_labels`, same `auto_groups`). No blocking issues found. ## 🟡 Suggestions - `kubernetes/infrastructure/openbao/rotation/netbird-ingress.yaml:34` — the old inline `# tested + enabled 2026-07-19` comment on `suspend: false` was dropped, and no equivalent note was added elsewhere in the file for this specific rollout. Not a defect, but the sibling files (e.g. `crowdsec-bouncer-key.yaml`'s `ON-DEMAND: kubectl ... create job ...` line) keep an operational breadcrumb; consider whether this file should too, for consistency with the rest of the fleet. - The image digest (`sha256:49bfddd8…`) differs from every other rotator in this directory (which pin either `159e5888…` for `random`/`ha-token` modes or `978fe53c…` for `cloudflare-roll`). That's expected here since this is the first consumer of `netbird-key` mode, but worth flagging only because it means this job is now running a binary version no other CronJob has exercised in production yet — the live test in the PR description covers that risk directly, so this is just a note, not a concern. ## 🟢 Nits - `netbird-ingress.yaml:52` — `suspend: false` is the default; the field is arguably redundant now that its explanatory comment is gone, but it was already present before this PR and isn't part of what changed here. ## Tests No unit tests accompany this change, but none are expected for a manifest-only diff — the actual rotation logic (`rotate_netbird_key`, `create_setup_key`, `Bao::patch_field`/`assert_fields_exist`) lives in `secret-rotator` and was presumably covered when `netbird-key` mode was introduced in #334. The PR body documents a live end-to-end test against the real cluster (key minted, ESO synced, DaemonSet rolled, new key handshaking, old key untouched) which is the appropriate validation for this kind of infra change and is more convincing than a unit test would be here. ## Recommendation Looks reasonable — no blocking issues; comments above are optional. <!-- pr-review:sha=92b59f7c8894354ce679e06dcf4cde132529d5b7 -->
k.renner merged commit 733e645638 into master 2026-07-21 22:43:44 +00:00
Sign in to join this conversation.