[PR #5881] [client][management] feat: TPM/Secure Enclave certificate-based device authentication #24237

Open
opened 2026-08-05 06:08:26 -04:00 by saavagebueno · 0 comments
Owner

Original Pull Request: https://github.com/netbirdio/netbird/pull/5881

State: closed
Merged: No


Describe your changes

Implement hardware-backed device certificate authentication using TPM 2.0 and Apple Secure Enclave. Device certificates are issued by an in-process CA and used for mTLS on the management gRPC channel — not the WireGuard data plane.

Architecture

Certificates authenticate the management-plane gRPC connection, not WireGuard tunnels. Two layers:

  1. mTLS — server verifies client certificate on every gRPC connection
  2. Login RPC — certificate serial checked against issued/revoked inventory even when mTLS passes

This ensures a revoked device is blocked at reconnect even if its certificate is still within validity period.

What's added

Management server (management/):

  • server/devicepki/BuiltinCA (in-process ECDSA P-256 CA, AES-256-GCM key at rest, PKCS#12 export), ExternalCA adapter (signs CSRs against an admin-provided CA), CertificateFactory (selects backend)
  • server/secretenc/FileKeyProvider AES-256-GCM envelope encryption for CA private key
  • internals/shared/grpc/AttestationSessionStore (in-memory with TTL + background cleanup), AttestationHandler (BeginTPMAttestation, CompleteTPMAttestation, AttestAppleSE), device enrollment RPC, revocation check wired into Login
  • HTTP API endpoints: POST /api/accounts/{accountId}/device-ca, GET /api/accounts/{accountId}/device-ca, GET /api/accounts/{accountId}/device-ca/cacert, POST /api/accounts/{accountId}/device-enrollments/{enrollmentId}/approve, POST /api/accounts/{accountId}/device-enrollments/{enrollmentId}/reject, POST /api/accounts/{accountId}/device-certs/{certId}/revoke
  • New cert_approver RBAC role — may approve/reject enrollments without full admin privileges
  • DeviceCertificate and DeviceEnrollment store models

Management proto (proto/):

  • BeginTPMAttestation / CompleteTPMAttestation — two-round TPM credential-activation protocol (EK → AK binding)
  • AttestAppleSE — single-round Apple Secure Enclave attestation with CBOR decode + chain verification
  • GetDeviceEnrollmentStatus, SubmitDeviceCertRenewal RPCs

Client (client/):

  • internal/enrollment/Manager drives the full enrollment lifecycle: CSR generation, submission, poll-until-approved, store cert, build mTLS config, StartRenewalLoop (7-day threshold, 6-hour check interval)
  • tpm/TPMProvider (TPM 2.0 via google/go-tpm): GenerateAK, ActivateCredential
  • se/SEProvider (Apple Secure Enclave via github.com/fxamacker/cbor): CreateAttestation
  • connect.go — wraps enrollment in tpmProv.Available() guard (skips on iOS/Android/WASM), upgrades connection to mTLS after enrollment

Documentation:

  • docs/DEVICE-SECURITY.md — full architecture description, sequence diagrams for all three enrollment modes (admin-issued, TPM, Apple SE), issueDeviceCert step-by-step, revocation algorithm, known limitations (L-1 through L-6)

Known limitations (documented, deferred)

  • L-1: Active Sync streams not interrupted on revocation — peer blocked at next reconnect
  • L-2: No dashboard UI for TPM/SE attestation status (API-only)
  • L-3: No EK certificate pinning to a specific TPM vendor CA
  • L-4: Single-account CA — multi-tenant isolation deferred
  • L-5: CRL not distributed to peers (management-plane-only enforcement)
  • L-6: cert_approver role not yet surfaced in dashboard RBAC UI

Closes #4773

  • netbirdio/dashboard#612 — dashboard UI for device certificate management (CA settings, enrollment approval, revocation)

Stack

Checklist

  • Is it a bug fix
  • Is a typo/documentation fix
  • Is a feature enhancement
  • It is a refactor
  • Created tests that fail without the change (if possible)

By submitting this pull request, you confirm that you have read and agree to the terms of the Contributor License Agreement.

Documentation

Select exactly one:

  • I added/updated documentation for this change
  • Documentation is not needed for this change (explain why)

Docs PR URL (required if "docs added" is checked)

Paste the PR link from https://github.com/netbirdio/docs here:

See docs/DEVICE-SECURITY.md in this PR. External docs PR to follow.

Summary by CodeRabbit

  • New Features
    • Device certificate authentication (mTLS) with enrollment, approval/rejection, renewal, and CRL support.
    • Hardware-backed attestation: TPM 2.0 and Apple Secure Enclave enrollment flows.
    • Device inventory integrations for automated checks (Intune, Jamf).
  • Developer / Devops
    • Local device-auth test stand, helper scripts, Docker/Makefile targets, and CLI tools for enrollment/mTLS demos.
    • CI: new workflows for TPM, device-auth, and E2E test runs.
  • Documentation
    • Added comprehensive Device Security documentation and dev stand guides.
**Original Pull Request:** https://github.com/netbirdio/netbird/pull/5881 **State:** closed **Merged:** No --- ## Describe your changes Implement hardware-backed device certificate authentication using TPM 2.0 and Apple Secure Enclave. Device certificates are issued by an in-process CA and used for mTLS on the management gRPC channel — **not** the WireGuard data plane. ### Architecture Certificates authenticate the management-plane gRPC connection, not WireGuard tunnels. Two layers: 1. **mTLS** — server verifies client certificate on every gRPC connection 2. **Login RPC** — certificate serial checked against issued/revoked inventory even when mTLS passes This ensures a revoked device is blocked at reconnect even if its certificate is still within validity period. ### What's added **Management server (`management/`):** - `server/devicepki/` — `BuiltinCA` (in-process ECDSA P-256 CA, AES-256-GCM key at rest, PKCS#12 export), `ExternalCA` adapter (signs CSRs against an admin-provided CA), `CertificateFactory` (selects backend) - `server/secretenc/` — `FileKeyProvider` AES-256-GCM envelope encryption for CA private key - `internals/shared/grpc/` — `AttestationSessionStore` (in-memory with TTL + background cleanup), `AttestationHandler` (`BeginTPMAttestation`, `CompleteTPMAttestation`, `AttestAppleSE`), device enrollment RPC, revocation check wired into `Login` - HTTP API endpoints: `POST /api/accounts/{accountId}/device-ca`, `GET /api/accounts/{accountId}/device-ca`, `GET /api/accounts/{accountId}/device-ca/cacert`, `POST /api/accounts/{accountId}/device-enrollments/{enrollmentId}/approve`, `POST /api/accounts/{accountId}/device-enrollments/{enrollmentId}/reject`, `POST /api/accounts/{accountId}/device-certs/{certId}/revoke` - New `cert_approver` RBAC role — may approve/reject enrollments without full admin privileges - `DeviceCertificate` and `DeviceEnrollment` store models **Management proto (`proto/`):** - `BeginTPMAttestation` / `CompleteTPMAttestation` — two-round TPM credential-activation protocol (EK → AK binding) - `AttestAppleSE` — single-round Apple Secure Enclave attestation with CBOR decode + chain verification - `GetDeviceEnrollmentStatus`, `SubmitDeviceCertRenewal` RPCs **Client (`client/`):** - `internal/enrollment/` — `Manager` drives the full enrollment lifecycle: CSR generation, submission, poll-until-approved, store cert, build mTLS config, `StartRenewalLoop` (7-day threshold, 6-hour check interval) - `tpm/` — `TPMProvider` (TPM 2.0 via `google/go-tpm`): `GenerateAK`, `ActivateCredential` - `se/` — `SEProvider` (Apple Secure Enclave via `github.com/fxamacker/cbor`): `CreateAttestation` - `connect.go` — wraps enrollment in `tpmProv.Available()` guard (skips on iOS/Android/WASM), upgrades connection to mTLS after enrollment **Documentation:** - `docs/DEVICE-SECURITY.md` — full architecture description, sequence diagrams for all three enrollment modes (admin-issued, TPM, Apple SE), `issueDeviceCert` step-by-step, revocation algorithm, known limitations (L-1 through L-6) ### Known limitations (documented, deferred) - L-1: Active `Sync` streams not interrupted on revocation — peer blocked at next reconnect - L-2: No dashboard UI for TPM/SE attestation status (API-only) - L-3: No EK certificate pinning to a specific TPM vendor CA - L-4: Single-account CA — multi-tenant isolation deferred - L-5: CRL not distributed to peers (management-plane-only enforcement) - L-6: `cert_approver` role not yet surfaced in dashboard RBAC UI ## Issue ticket number and link Closes #4773 ## Related PRs - netbirdio/dashboard#612 — dashboard UI for device certificate management (CA settings, enrollment approval, revocation) ## Stack <!-- branch-stack --> ### Checklist - [ ] Is it a bug fix - [ ] Is a typo/documentation fix - [x] Is a feature enhancement - [ ] It is a refactor - [x] Created tests that fail without the change (if possible) > By submitting this pull request, you confirm that you have read and agree to the terms of the [Contributor License Agreement](https://github.com/netbirdio/netbird/blob/main/CONTRIBUTOR_LICENSE_AGREEMENT.md). ## Documentation Select exactly one: - [x] I added/updated documentation for this change - [ ] Documentation is **not needed** for this change (explain why) ### Docs PR URL (required if "docs added" is checked) Paste the PR link from https://github.com/netbirdio/docs here: See `docs/DEVICE-SECURITY.md` in this PR. External docs PR to follow. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Device certificate authentication (mTLS) with enrollment, approval/rejection, renewal, and CRL support. * Hardware-backed attestation: TPM 2.0 and Apple Secure Enclave enrollment flows. * Device inventory integrations for automated checks (Intune, Jamf). * **Developer / Devops** * Local device-auth test stand, helper scripts, Docker/Makefile targets, and CLI tools for enrollment/mTLS demos. * CI: new workflows for TPM, device-auth, and E2E test runs. * **Documentation** * Added comprehensive Device Security documentation and dev stand guides. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
saavagebueno added the pull-request label 2026-08-05 06:08:26 -04:00
Sign in to join this conversation.
No Label pull-request
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: DYNR/netbird#24237