Skip to content

[client] Add --disable-networks flag to block network selection#5896

Merged
lixmal merged 4 commits intomainfrom
disable-networks-selection
Apr 16, 2026
Merged

[client] Add --disable-networks flag to block network selection#5896
lixmal merged 4 commits intomainfrom
disable-networks-selection

Conversation

@lixmal
Copy link
Copy Markdown
Collaborator

@lixmal lixmal commented Apr 15, 2026

Describe your changes

Add a --disable-networks service flag that blocks network and exit node selection at the daemon level. For deployments where users should not modify routing.

  • Block ListNetworks, SelectNetworks, and DeselectNetworks RPCs when the flag is set, returning a gRPC Unavailable error
  • Add disable_networks to the GetFeaturesResponse proto so the UI can hide the Networks and Exit Node menus
  • Persist the flag in service.json across reinstalls, following the same pattern as --disable-profiles and --disable-update-settings

Usage: netbird service install --disable-networks

Issue ticket number and link

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)

Flag follows the exact same pattern as existing --disable-profiles and --disable-update-settings which are already documented. Can be added to the same docs page.

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/__

Summary by CodeRabbit

  • New Features

    • Added --disable-networks CLI flag to disable network listing, selection, and deselection
    • Network-disable setting is persisted and retained across restarts
    • Daemon now reports network-disable capability so clients can react
  • Bug Fixes / UX

    • Networks and Exit Node menu items enable/disable dynamically based on feature availability
    • Attempts to use networks when disabled now return a clear "networks disabled" error

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 15, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: cea43703-d8b6-458b-b859-9cc57a5f8f5c

📥 Commits

Reviewing files that changed from the base of the PR and between b8061c2 and d5eda84.

📒 Files selected for processing (1)
  • client/ui/client_ui.go

📝 Walkthrough

Walkthrough

Adds a --disable-networks option and propagates its state from CLI to service installer, server constructor, gRPC feature reporting, server RPC guards, persisted service params, tests, and UI menu enablement.

Changes

Cohort / File(s) Summary
CLI Flags & Globals
client/cmd/root.go, client/cmd/service.go
Add package-level networksDisabled and persistent --disable-networks flag wired to that variable.
Service Startup & Persistence
client/cmd/service_controller.go, client/cmd/service_installer.go, client/cmd/service_params.go, client/cmd/service_params_test.go
Pass networksDisabled into service startup and server constructor; persist as DisableNetworks in serviceParams; installer appends --disable-networks when set; tests updated for mapping.
Daemon Protocol & Test Helpers
client/proto/daemon.proto, client/cmd/testutil_test.go, client/server/server_test.go, client/server/setconfig_test.go
Add disable_networks to GetFeaturesResponse; update client constructor/test call sites to new parameter arity.
Server Implementation & RPC Guards
client/server/server.go, client/server/network.go
Extend New(...) to accept networksDisabled, store on Server, include in GetFeatures; network RPCs now return gRPC Unavailable when networks are disabled.
UI Layer
client/ui/client_ui.go
Introduce networksEnabled state; enable/disable Networks and ExitNode menu items based on daemon feature (DisableNetworks) and connection state; reorder feature check/update sequence.

Sequence Diagram(s)

sequenceDiagram
    participant CLI as CLI (--disable-networks)
    participant Installer as Service Installer
    participant Server as Daemon Server
    participant UI as Client UI
    participant RPC as Client RPC

    CLI->>Installer: start service with --disable-networks
    Installer->>Server: New(..., networksDisabled=true)
    Server->>Server: store s.networksDisabled
    UI->>Server: GetFeatures()
    Server-->>UI: GetFeaturesResponse{disable_networks:true}
    UI->>UI: set networksEnabled = false (disable menus)
    RPC->>Server: ListNetworks / SelectNetworks / DeselectNetworks
    Server-->>RPC: gRPC Unavailable (errNetworksDisabled)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • pappz
  • pascal-fischer

Poem

🐰 I nudged a tiny networks switch,
From CLI seed to server stitch,
Menubar quiet, RPCs decline,
Flags aligned in tidy line,
Hop, code, hop — the feature's mine!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 63.64% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely describes the main change: adding a --disable-networks flag to block network selection.
Description check ✅ Passed The description provides a clear explanation of the changes, marks it as a feature enhancement, and explains why documentation is not needed. The template structure is followed.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch disable-networks-selection

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@lixmal lixmal changed the title [client] Add --disable-networks flag for MDM lockdown [client] Add --disable-networks flag to block network selection Apr 15, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
client/server/network.go (1)

32-34: Optional: extract a shared checkNetworksDisabled helper to reduce duplication.

Same guard logic is repeated in three methods. A small helper would keep future behavior changes centralized.

♻️ Proposed refactor
+func (s *Server) checkNetworksDisabled() error {
+	if s.networksDisabled {
+		return gstatus.Errorf(codes.Unavailable, errNetworksDisabled)
+	}
+	return nil
+}
+
 func (s *Server) ListNetworks(context.Context, *proto.ListNetworksRequest) (*proto.ListNetworksResponse, error) {
 	s.mutex.Lock()
 	defer s.mutex.Unlock()
 
-	if s.networksDisabled {
-		return nil, gstatus.Errorf(codes.Unavailable, errNetworksDisabled)
+	if err := s.checkNetworksDisabled(); err != nil {
+		return nil, err
 	}
@@
 func (s *Server) SelectNetworks(_ context.Context, req *proto.SelectNetworksRequest) (*proto.SelectNetworksResponse, error) {
 	s.mutex.Lock()
 	defer s.mutex.Unlock()
 
-	if s.networksDisabled {
-		return nil, gstatus.Errorf(codes.Unavailable, errNetworksDisabled)
+	if err := s.checkNetworksDisabled(); err != nil {
+		return nil, err
 	}
@@
 func (s *Server) DeselectNetworks(_ context.Context, req *proto.SelectNetworksRequest) (*proto.SelectNetworksResponse, error) {
 	s.mutex.Lock()
 	defer s.mutex.Unlock()
 
-	if s.networksDisabled {
-		return nil, gstatus.Errorf(codes.Unavailable, errNetworksDisabled)
+	if err := s.checkNetworksDisabled(); err != nil {
+		return nil, err
 	}

Also applies to: 127-129, 177-179

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/server/network.go` around lines 32 - 34, Extract the repeated guard
into a single helper on the server type, e.g. add a method func (s *Server)
checkNetworksDisabled() error that returns gstatus.Errorf(codes.Unavailable,
errNetworksDisabled) when s.networksDisabled is true and nil otherwise, then
replace the three inline blocks (the if s.networksDisabled { return nil,
gstatus.Errorf... } occurrences) with if err := s.checkNetworksDisabled(); err
!= nil { return nil, err } so the behavior is centralized and future changes are
made in one place.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@client/ui/client_ui.go`:
- Around line 1307-1317: The current logic flips s.mNetworks and s.mExitNode to
enabled whenever networksEnabled becomes true regardless of daemon connection;
update the branch so that when networksEnabled is true you only call
s.mNetworks.Enable() and s.mExitNode.Enable() if the UI knows the daemon is
connected (use your existing connection flag, e.g. s.daemonConnected or
s.connected) and otherwise keep them disabled; keep the disable branch unchanged
so features disabling still calls s.mNetworks.Disable() and
s.mExitNode.Disable().

---

Nitpick comments:
In `@client/server/network.go`:
- Around line 32-34: Extract the repeated guard into a single helper on the
server type, e.g. add a method func (s *Server) checkNetworksDisabled() error
that returns gstatus.Errorf(codes.Unavailable, errNetworksDisabled) when
s.networksDisabled is true and nil otherwise, then replace the three inline
blocks (the if s.networksDisabled { return nil, gstatus.Errorf... } occurrences)
with if err := s.checkNetworksDisabled(); err != nil { return nil, err } so the
behavior is centralized and future changes are made in one place.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 21a7c75e-1922-4c2e-a68e-2fc9dfa533cd

📥 Commits

Reviewing files that changed from the base of the PR and between 95bc01e and f3cb652.

⛔ Files ignored due to path filters (1)
  • client/proto/daemon.pb.go is excluded by !**/*.pb.go
📒 Files selected for processing (11)
  • client/cmd/root.go
  • client/cmd/service.go
  • client/cmd/service_controller.go
  • client/cmd/service_installer.go
  • client/cmd/service_params.go
  • client/cmd/service_params_test.go
  • client/cmd/testutil_test.go
  • client/proto/daemon.proto
  • client/server/network.go
  • client/server/server.go
  • client/ui/client_ui.go

Comment thread client/ui/client_ui.go Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@client/ui/client_ui.go`:
- Line 372: The default optimistic initialization of networksEnabled
(networksEnabled: true) allows updateStatus() to briefly show Networks/Exit Node
as enabled before checkAndUpdateFeatures() runs; change initialization so
s.networksEnabled is set from the real daemon feature state before the first
status refresh — either initialize networksEnabled to false and then set
s.networksEnabled from the existing getFeatures() result in onTrayReady(), or
seed s.networksEnabled directly from getFeatures() prior to calling
updateStatus(); update the same pattern for the other occurrences noted around
the 925-928 block to avoid the transient UI gap.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2e93db20-849c-4d50-9646-0750c6a043b3

📥 Commits

Reviewing files that changed from the base of the PR and between 997f98f and b8061c2.

📒 Files selected for processing (1)
  • client/ui/client_ui.go

Comment thread client/ui/client_ui.go
@sonarqubecloud
Copy link
Copy Markdown

@lixmal lixmal merged commit 6b540d1 into main Apr 16, 2026
43 checks passed
@lixmal lixmal deleted the disable-networks-selection branch April 16, 2026 12:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants