[PR #6967] [MERGED] [client] Authorize daemon IPC callers by their local identity #27653

Closed
opened 2026-08-05 07:09:02 -04:00 by saavagebueno · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/netbirdio/netbird/pull/6967
Author: @lixmal
Created: 7/29/2026
Status: Merged
Merged: 7/29/2026
Merged by: @lixmal

Base: mainHead: ssh-ipc-privilege-gates


📝 Commits (1)

  • 8972f2a Authorize daemon IPC callers by their local identity

📊 Changes

58 files changed (+3789 additions, -157 deletions)

View changed files

📝 CONTRIBUTING.md (+12 -2)
client/cmd/daemon_error.go (+66 -0)
📝 client/cmd/logout.go (+1 -1)
📝 client/cmd/root.go (+7 -9)
📝 client/cmd/service.go (+9 -4)
📝 client/cmd/service_controller.go (+116 -45)
📝 client/cmd/service_json_gateway.go (+105 -7)
client/cmd/service_json_gateway_test.go (+261 -0)
📝 client/cmd/service_params.go (+8 -0)
client/cmd/service_pipe_other.go (+14 -0)
client/cmd/service_pipe_windows.go (+41 -0)
📝 client/cmd/service_socket.go (+10 -2)
📝 client/cmd/up.go (+3 -3)
client/internal/daemonaddr/owner.go (+15 -0)
client/internal/daemonaddr/owner_unix.go (+40 -0)
client/internal/daemonaddr/owner_unix_test.go (+62 -0)
client/internal/daemonaddr/owner_windows.go (+42 -0)
client/internal/daemonaddr/pipe.go (+103 -0)
client/internal/daemonaddr/pipe_other.go (+15 -0)
client/internal/daemonaddr/pipe_test.go (+30 -0)

...and 38 more files

📄 Description

Describe your changes

The daemon accepts any local caller on its IPC and applies whatever config it is handed. It now reads the caller's local identity from the socket and requires root/administrator for the settings that only an administrator should be able to turn on, matching how the same settings are treated elsewhere.

  • Authorize per caller identity on the daemon IPC: SO_PEERCRED on Linux, LOCAL_PEERCRED on macOS/FreeBSD, and the named-pipe client token on Windows, with callers whose identity cannot be established refused
  • Require root/administrator to enable the SSH server, enable SSH root login or disable SSH authentication, and to change the management URL or deregister while a profile has the SSH server enabled; turning any of them off, or restating a value that is already set, stays unprivileged
  • Treat a caller sharing the identity of an unprivileged daemon as privileged, so rootless containers and netstack mode keep working
  • Serve the Windows daemon on a named pipe rather than loopback TCP, so the caller's identity is available there too, preferring the namespace only administrators can create in and falling back to a plain name for an unprivileged daemon; clients check the pipe's owner before using a name that carries no such guarantee
  • Migrate a persisted tcp://127.0.0.1:41731 daemon address to the pipe, and report rather than silently use the legacy address when only that answers
  • Forward the HTTP client's identity through the optional JSON gateway, authenticated with a per-process value so only the in-process gateway can speak for someone else
  • Return refusals as a PermissionDenied with an ErrorInfo detail carrying a summary and the command that performs the same operation with the privileges it needs, so the CLI prints guidance instead of a gRPC error
  • In the UI, roll back a save the daemon refused, show the refusal with a copy button, and disable the guarded controls with the command inline for callers that cannot use them

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)
  • This change does not modify the public API, gRPC protocols, functionality behavior, CLI / service flags, or introduce a new feature — OR I have discussed it with the NetBird team beforehand (link the issue / Slack thread in the description). See CONTRIBUTING.md.

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)

Only which callers may apply existing settings changes; the settings, flags and their meanings are unchanged. CONTRIBUTING.md covers the Windows pipe for the dev loop.

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

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

https://github.com/netbirdio/docs/pull/__


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

Summary by CodeRabbit

  • New Features
    • Added improved daemon connectivity with Windows named-pipe support and Unix socket dialing, including safer daemon address resolution and legacy address migration.
    • Enhanced JSON gateway to forward real client identity and provide copyable “privilege required” guidance for SSH-related actions.
    • Added UI privilege awareness (localized hints) and command-ready error dialogs for refused privileged operations.
  • Bug Fixes
    • Prevented spoofed/forged forwarded-identity data from being trusted; unidentified requests are now correctly denied.
  • Documentation
    • Updated development and platform instructions to reflect the new daemon endpoint behavior and identity expectations.
  • Tests
    • Added coverage for JSON gateway identity forwarding and SSH/admin privilege gates.

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/netbirdio/netbird/pull/6967 **Author:** [@lixmal](https://github.com/lixmal) **Created:** 7/29/2026 **Status:** ✅ Merged **Merged:** 7/29/2026 **Merged by:** [@lixmal](https://github.com/lixmal) **Base:** `main` ← **Head:** `ssh-ipc-privilege-gates` --- ### 📝 Commits (1) - [`8972f2a`](https://github.com/netbirdio/netbird/commit/8972f2a270bbe02af4d41466864eeca302f7f034) Authorize daemon IPC callers by their local identity ### 📊 Changes **58 files changed** (+3789 additions, -157 deletions) <details> <summary>View changed files</summary> 📝 `CONTRIBUTING.md` (+12 -2) ➕ `client/cmd/daemon_error.go` (+66 -0) 📝 `client/cmd/logout.go` (+1 -1) 📝 `client/cmd/root.go` (+7 -9) 📝 `client/cmd/service.go` (+9 -4) 📝 `client/cmd/service_controller.go` (+116 -45) 📝 `client/cmd/service_json_gateway.go` (+105 -7) ➕ `client/cmd/service_json_gateway_test.go` (+261 -0) 📝 `client/cmd/service_params.go` (+8 -0) ➕ `client/cmd/service_pipe_other.go` (+14 -0) ➕ `client/cmd/service_pipe_windows.go` (+41 -0) 📝 `client/cmd/service_socket.go` (+10 -2) 📝 `client/cmd/up.go` (+3 -3) ➕ `client/internal/daemonaddr/owner.go` (+15 -0) ➕ `client/internal/daemonaddr/owner_unix.go` (+40 -0) ➕ `client/internal/daemonaddr/owner_unix_test.go` (+62 -0) ➕ `client/internal/daemonaddr/owner_windows.go` (+42 -0) ➕ `client/internal/daemonaddr/pipe.go` (+103 -0) ➕ `client/internal/daemonaddr/pipe_other.go` (+15 -0) ➕ `client/internal/daemonaddr/pipe_test.go` (+30 -0) _...and 38 more files_ </details> ### 📄 Description ## Describe your changes The daemon accepts any local caller on its IPC and applies whatever config it is handed. It now reads the caller's local identity from the socket and requires root/administrator for the settings that only an administrator should be able to turn on, matching how the same settings are treated elsewhere. - Authorize per caller identity on the daemon IPC: `SO_PEERCRED` on Linux, `LOCAL_PEERCRED` on macOS/FreeBSD, and the named-pipe client token on Windows, with callers whose identity cannot be established refused - Require root/administrator to enable the SSH server, enable SSH root login or disable SSH authentication, and to change the management URL or deregister while a profile has the SSH server enabled; turning any of them off, or restating a value that is already set, stays unprivileged - Treat a caller sharing the identity of an unprivileged daemon as privileged, so rootless containers and netstack mode keep working - Serve the Windows daemon on a named pipe rather than loopback TCP, so the caller's identity is available there too, preferring the namespace only administrators can create in and falling back to a plain name for an unprivileged daemon; clients check the pipe's owner before using a name that carries no such guarantee - Migrate a persisted `tcp://127.0.0.1:41731` daemon address to the pipe, and report rather than silently use the legacy address when only that answers - Forward the HTTP client's identity through the optional JSON gateway, authenticated with a per-process value so only the in-process gateway can speak for someone else - Return refusals as a `PermissionDenied` with an `ErrorInfo` detail carrying a summary and the command that performs the same operation with the privileges it needs, so the CLI prints guidance instead of a gRPC error - In the UI, roll back a save the daemon refused, show the refusal with a copy button, and disable the guarded controls with the command inline for callers that cannot use them ## Issue ticket number and link ## Stack <!-- branch-stack --> ### Checklist - [x] Is it a bug fix - [ ] Is a typo/documentation fix - [ ] Is a feature enhancement - [ ] It is a refactor - [x] Created tests that fail without the change (if possible) - [ ] This change does **not** modify the public API, gRPC protocols, functionality behavior, CLI / service flags, or introduce a new feature — **OR** I have discussed it with the NetBird team beforehand (link the issue / Slack thread in the description). See [CONTRIBUTING.md](https://github.com/netbirdio/netbird/blob/main/CONTRIBUTING.md#discuss-changes-with-the-netbird-team-first). > 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: - [ ] I added/updated documentation for this change - [x] Documentation is **not needed** for this change (explain why) Only which callers may apply existing settings changes; the settings, flags and their meanings are unchanged. `CONTRIBUTING.md` covers the Windows pipe for the dev loop. ### Docs PR URL (required if "docs added" is checked) Paste the PR link from https://github.com/netbirdio/docs here: https://github.com/netbirdio/docs/pull/__ <!-- codesmith:footer --> --- <a href="https://app.blacksmith.sh/netbirdio/codesmith/netbird/pr/6967"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img alt="View with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a> <a href="https://backend.blacksmith.sh/track/enable-autofix?expires=1787932475&installation_model_id=427504&pr_number=6967&repository=netbirdio%2Fnetbird&return_to=https%3A%2F%2Fgithub.com%2Fnetbirdio%2Fnetbird%2Fpull%2F6967&signature=949d4d321295413e78a3402b7b70b36a8eebea931c52584308870427b4f1127e"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a> <sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you need. Autofix is disabled.</sup> <!-- codesmith:autofix:disabled --> <!-- /codesmith:footer --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added improved daemon connectivity with Windows named-pipe support and Unix socket dialing, including safer daemon address resolution and legacy address migration. * Enhanced JSON gateway to forward real client identity and provide copyable “privilege required” guidance for SSH-related actions. * Added UI privilege awareness (localized hints) and command-ready error dialogs for refused privileged operations. * **Bug Fixes** * Prevented spoofed/forged forwarded-identity data from being trusted; unidentified requests are now correctly denied. * **Documentation** * Updated development and platform instructions to reflect the new daemon endpoint behavior and identity expectations. * **Tests** * Added coverage for JSON gateway identity forwarding and SSH/admin privilege gates. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
saavagebueno added the pull-request label 2026-08-05 07:09:02 -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#27653