Browse Source

util/syspolicy: add auto exit node related keys (#11996)

Updates tailscale/corp#19681

Signed-off-by: Claire Wang <[email protected]>
Claire Wang 1 year ago
parent
commit
41f2195899
2 changed files with 65 additions and 0 deletions
  1. 7 0
      util/syspolicy/policy_keys.go
  2. 58 0
      util/syspolicy/syspolicy_test.go

+ 7 - 0
util/syspolicy/policy_keys.go

@@ -58,6 +58,9 @@ const (
 	// installations and uses the Sparkle naming convention, even though it does
 	// not actually control updates, merely the UI for that setting.
 	AutoUpdateVisibility Key = "ApplyUpdates"
+	// SuggestedExitNodeVisibility controls the visibility of suggested exit nodes in the client GUI.
+	// When this system policy is set to 'hide', an exit node suggestion won't be presented to the user as part of the exit nodes picker.
+	SuggestedExitNodeVisibility Key = "SuggestedExitNode"
 
 	// Keys with a string value formatted for use with time.ParseDuration().
 	KeyExpirationNoticeTime Key = "KeyExpirationNotice" // default 24 hours
@@ -84,4 +87,8 @@ const (
 	// ManagedByURL is a valid URL pointing to a support help desk for Tailscale within the
 	// organization. A button in the client UI provides easy access to this URL.
 	ManagedByURL Key = "ManagedByURL"
+
+	// Keys with a string array value.
+	// AllowedSuggestedExitNodes's string array value is a list of exit node IDs that restricts which exit nodes are considered when generating suggestions for exit nodes.
+	AllowedSuggestedExitNodes Key = "AllowedSuggestedExitNodes"
 )

+ 58 - 0
util/syspolicy/syspolicy_test.go

@@ -5,6 +5,7 @@ package syspolicy
 
 import (
 	"errors"
+	"slices"
 	"testing"
 	"time"
 )
@@ -408,6 +409,63 @@ func TestGetDuration(t *testing.T) {
 	}
 }
 
+func TestGetStringArray(t *testing.T) {
+	tests := []struct {
+		name         string
+		key          Key
+		handlerValue []string
+		handlerError error
+		defaultValue []string
+		wantValue    []string
+		wantError    error
+	}{
+		{
+			name:         "read existing value",
+			key:          AllowedSuggestedExitNodes,
+			handlerValue: []string{"foo", "bar"},
+			wantValue:    []string{"foo", "bar"},
+		},
+		{
+			name:         "read non-existing value",
+			key:          AllowedSuggestedExitNodes,
+			handlerError: ErrNoSuchKey,
+			wantError:    nil,
+		},
+		{
+			name:         "read non-existing value, non nil default",
+			key:          AllowedSuggestedExitNodes,
+			handlerError: ErrNoSuchKey,
+			defaultValue: []string{"foo", "bar"},
+			wantValue:    []string{"foo", "bar"},
+			wantError:    nil,
+		},
+		{
+			name:         "reading value returns other error",
+			key:          AllowedSuggestedExitNodes,
+			handlerError: someOtherError,
+			wantError:    someOtherError,
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			SetHandlerForTest(t, &testHandler{
+				t:    t,
+				key:  tt.key,
+				sArr: tt.handlerValue,
+				err:  tt.handlerError,
+			})
+			value, err := GetStringArray(tt.key, tt.defaultValue)
+			if err != tt.wantError {
+				t.Errorf("err=%q, want %q", err, tt.wantError)
+			}
+			if !slices.Equal(tt.wantValue, value) {
+				t.Errorf("value=%v, want %v", value, tt.wantValue)
+			}
+		})
+	}
+}
+
 func TestSelectControlURL(t *testing.T) {
 	tests := []struct {
 		reg, disk, want string