Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions client/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ var (
mtu uint16
profilesDisabled bool
updateSettingsDisabled bool
networksDisabled bool

rootCmd = &cobra.Command{
Use: "netbird",
Expand Down
1 change: 1 addition & 0 deletions client/cmd/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ func init() {
serviceCmd.AddCommand(runCmd, startCmd, stopCmd, restartCmd, svcStatusCmd, installCmd, uninstallCmd, reconfigureCmd, resetParamsCmd)
serviceCmd.PersistentFlags().BoolVar(&profilesDisabled, "disable-profiles", false, "Disables profiles feature. If enabled, the client will not be able to change or edit any profile. To persist this setting, use: netbird service install --disable-profiles")
serviceCmd.PersistentFlags().BoolVar(&updateSettingsDisabled, "disable-update-settings", false, "Disables update settings feature. If enabled, the client will not be able to change or edit any settings. To persist this setting, use: netbird service install --disable-update-settings")
serviceCmd.PersistentFlags().BoolVar(&networksDisabled, "disable-networks", false, "Disables network selection. If enabled, the client will not allow listing, selecting, or deselecting networks. To persist, use: netbird service install --disable-networks")

rootCmd.PersistentFlags().StringVarP(&serviceName, "service", "s", defaultServiceName, "Netbird system service name")
serviceEnvDesc := `Sets extra environment variables for the service. ` +
Expand Down
2 changes: 1 addition & 1 deletion client/cmd/service_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func (p *program) Start(svc service.Service) error {
}
}

serverInstance := server.New(p.ctx, util.FindFirstLogPath(logFiles), configPath, profilesDisabled, updateSettingsDisabled)
serverInstance := server.New(p.ctx, util.FindFirstLogPath(logFiles), configPath, profilesDisabled, updateSettingsDisabled, networksDisabled)
if err := serverInstance.Start(); err != nil {
log.Fatalf("failed to start daemon: %v", err)
}
Expand Down
4 changes: 4 additions & 0 deletions client/cmd/service_installer.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ func buildServiceArguments() []string {
args = append(args, "--disable-update-settings")
}

if networksDisabled {
args = append(args, "--disable-networks")
}

return args
}

Expand Down
6 changes: 6 additions & 0 deletions client/cmd/service_params.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ type serviceParams struct {
LogFiles []string `json:"log_files,omitempty"`
DisableProfiles bool `json:"disable_profiles,omitempty"`
DisableUpdateSettings bool `json:"disable_update_settings,omitempty"`
DisableNetworks bool `json:"disable_networks,omitempty"`
ServiceEnvVars map[string]string `json:"service_env_vars,omitempty"`
}

Expand Down Expand Up @@ -78,6 +79,7 @@ func currentServiceParams() *serviceParams {
LogFiles: logFiles,
DisableProfiles: profilesDisabled,
DisableUpdateSettings: updateSettingsDisabled,
DisableNetworks: networksDisabled,
}

if len(serviceEnvVars) > 0 {
Expand Down Expand Up @@ -142,6 +144,10 @@ func applyServiceParams(cmd *cobra.Command, params *serviceParams) {
updateSettingsDisabled = params.DisableUpdateSettings
}

if !serviceCmd.PersistentFlags().Changed("disable-networks") {
networksDisabled = params.DisableNetworks
}

applyServiceEnvParams(cmd, params)
}

Expand Down
1 change: 1 addition & 0 deletions client/cmd/service_params_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,7 @@ func fieldToGlobalVar(field string) string {
"LogFiles": "logFiles",
"DisableProfiles": "profilesDisabled",
"DisableUpdateSettings": "updateSettingsDisabled",
"DisableNetworks": "networksDisabled",
"ServiceEnvVars": "serviceEnvVars",
}
if v, ok := m[field]; ok {
Expand Down
2 changes: 1 addition & 1 deletion client/cmd/testutil_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ func startClientDaemon(
s := grpc.NewServer()

server := client.New(ctx,
"", "", false, false)
"", "", false, false, false)
if err := server.Start(); err != nil {
t.Fatal(err)
}
Expand Down
13 changes: 11 additions & 2 deletions client/proto/daemon.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions client/proto/daemon.proto
Original file line number Diff line number Diff line change
Expand Up @@ -727,6 +727,7 @@ message GetFeaturesRequest{}
message GetFeaturesResponse{
bool disable_profiles = 1;
bool disable_update_settings = 2;
bool disable_networks = 3;
}

message TriggerUpdateRequest {}
Expand Down
14 changes: 14 additions & 0 deletions client/server/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (
"strings"

"golang.org/x/exp/maps"
"google.golang.org/grpc/codes"
gstatus "google.golang.org/grpc/status"

"github.com/netbirdio/netbird/client/proto"
"github.com/netbirdio/netbird/route"
Expand All @@ -27,6 +29,10 @@ func (s *Server) ListNetworks(context.Context, *proto.ListNetworksRequest) (*pro
s.mutex.Lock()
defer s.mutex.Unlock()

if s.networksDisabled {
return nil, gstatus.Errorf(codes.Unavailable, errNetworksDisabled)
}

if s.connectClient == nil {
return nil, fmt.Errorf("not connected")
}
Expand Down Expand Up @@ -118,6 +124,10 @@ func (s *Server) SelectNetworks(_ context.Context, req *proto.SelectNetworksRequ
s.mutex.Lock()
defer s.mutex.Unlock()

if s.networksDisabled {
return nil, gstatus.Errorf(codes.Unavailable, errNetworksDisabled)
}

if s.connectClient == nil {
return nil, fmt.Errorf("not connected")
}
Expand Down Expand Up @@ -164,6 +174,10 @@ func (s *Server) DeselectNetworks(_ context.Context, req *proto.SelectNetworksRe
s.mutex.Lock()
defer s.mutex.Unlock()

if s.networksDisabled {
return nil, gstatus.Errorf(codes.Unavailable, errNetworksDisabled)
}

if s.connectClient == nil {
return nil, fmt.Errorf("not connected")
}
Expand Down
6 changes: 5 additions & 1 deletion client/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ const (
errRestoreResidualState = "failed to restore residual state: %v"
errProfilesDisabled = "profiles are disabled, you cannot use this feature without profiles enabled"
errUpdateSettingsDisabled = "update settings are disabled, you cannot use this feature without update settings enabled"
errNetworksDisabled = "network selection is disabled by the administrator"
)

var ErrServiceNotUp = errors.New("service is not up")
Expand Down Expand Up @@ -88,6 +89,7 @@ type Server struct {
profileManager *profilemanager.ServiceManager
profilesDisabled bool
updateSettingsDisabled bool
networksDisabled bool

sleepHandler *sleephandler.SleepHandler

Expand All @@ -104,7 +106,7 @@ type oauthAuthFlow struct {
}

// New server instance constructor.
func New(ctx context.Context, logFile string, configFile string, profilesDisabled bool, updateSettingsDisabled bool) *Server {
func New(ctx context.Context, logFile string, configFile string, profilesDisabled bool, updateSettingsDisabled bool, networksDisabled bool) *Server {
s := &Server{
rootCtx: ctx,
logFile: logFile,
Expand All @@ -113,6 +115,7 @@ func New(ctx context.Context, logFile string, configFile string, profilesDisable
profileManager: profilemanager.NewServiceManager(configFile),
profilesDisabled: profilesDisabled,
updateSettingsDisabled: updateSettingsDisabled,
networksDisabled: networksDisabled,
jwtCache: newJWTCache(),
}
agent := &serverAgent{s}
Expand Down Expand Up @@ -1628,6 +1631,7 @@ func (s *Server) GetFeatures(ctx context.Context, msg *proto.GetFeaturesRequest)
features := &proto.GetFeaturesResponse{
DisableProfiles: s.checkProfilesDisabled(),
DisableUpdateSettings: s.checkUpdateSettingsDisabled(),
DisableNetworks: s.networksDisabled,
}

return features, nil
Expand Down
6 changes: 3 additions & 3 deletions client/server/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ func TestConnectWithRetryRuns(t *testing.T) {
t.Fatalf("failed to set active profile state: %v", err)
}

s := New(ctx, "debug", "", false, false)
s := New(ctx, "debug", "", false, false, false)

s.config = config

Expand Down Expand Up @@ -164,7 +164,7 @@ func TestServer_Up(t *testing.T) {
t.Fatalf("failed to set active profile state: %v", err)
}

s := New(ctx, "console", "", false, false)
s := New(ctx, "console", "", false, false, false)
err = s.Start()
require.NoError(t, err)

Expand Down Expand Up @@ -234,7 +234,7 @@ func TestServer_SubcribeEvents(t *testing.T) {
t.Fatalf("failed to set active profile state: %v", err)
}

s := New(ctx, "console", "", false, false)
s := New(ctx, "console", "", false, false, false)

err = s.Start()
require.NoError(t, err)
Expand Down
2 changes: 1 addition & 1 deletion client/server/setconfig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func TestSetConfig_AllFieldsSaved(t *testing.T) {
require.NoError(t, err)

ctx := context.Background()
s := New(ctx, "console", "", false, false)
s := New(ctx, "console", "", false, false, false)

rosenpassEnabled := true
rosenpassPermissive := true
Expand Down
24 changes: 19 additions & 5 deletions client/ui/client_ui.go
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,7 @@ type serviceClient struct {
lastNotifiedVersion string
settingsEnabled bool
profilesEnabled bool
networksEnabled bool
showNetworks bool
wNetworks fyne.Window
wProfiles fyne.Window
Expand Down Expand Up @@ -368,6 +369,7 @@ func newServiceClient(args *newServiceClientArgs) *serviceClient {

showAdvancedSettings: args.showSettings,
showNetworks: args.showNetworks,
networksEnabled: true,
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}

s.eventHandler = newEventHandler(s)
Expand Down Expand Up @@ -920,8 +922,10 @@ func (s *serviceClient) updateStatus() error {
s.mStatus.SetIcon(s.icConnectedDot)
s.mUp.Disable()
s.mDown.Enable()
s.mNetworks.Enable()
s.mExitNode.Enable()
if s.networksEnabled {
s.mNetworks.Enable()
s.mExitNode.Enable()
}
s.startExitNodeRefresh()
systrayIconState = true
case status.Status == string(internal.StatusConnecting):
Expand Down Expand Up @@ -1093,14 +1097,14 @@ func (s *serviceClient) onTrayReady() {
s.getSrvConfig()
time.Sleep(100 * time.Millisecond) // To prevent race condition caused by systray not being fully initialized and ignoring setIcon
for {
// Check features before status so menus respect disable flags before being enabled
s.checkAndUpdateFeatures()

err := s.updateStatus()
if err != nil {
log.Errorf("error while updating status: %v", err)
}

// Check features periodically to handle daemon restarts
s.checkAndUpdateFeatures()

time.Sleep(2 * time.Second)
}
}()
Expand Down Expand Up @@ -1299,6 +1303,16 @@ func (s *serviceClient) checkAndUpdateFeatures() {
s.mProfile.setEnabled(profilesEnabled)
}
}

// Update networks and exit node menus based on current features
s.networksEnabled = features == nil || !features.DisableNetworks
if s.networksEnabled && s.connected {
s.mNetworks.Enable()
s.mExitNode.Enable()
} else {
s.mNetworks.Disable()
s.mExitNode.Disable()
}
}

// getFeatures from the daemon to determine which features are enabled/disabled.
Expand Down
Loading