tailscale/util/winutil/policy/policy_windows.go
Andrew Dunham 280255acae
various: add golangci-lint, fix issues (#7905)
This adds an initial and intentionally minimal configuration for
golang-ci, fixes the issues reported, and adds a GitHub Action to check
new pull requests against this linter configuration.

Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
Change-Id: I8f38fbc315836a19a094d0d3e986758b9313f163
2023-04-17 18:38:24 -04:00

150 lines
4.8 KiB
Go

// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
// Package policy contains higher-level abstractions for accessing Windows enterprise policies.
package policy
import (
"time"
"tailscale.com/util/winutil"
)
// PreferenceOptionPolicy is a policy that governs whether a boolean variable
// is forcibly assigned an administrator-defined value, or allowed to receive
// a user-defined value.
type PreferenceOptionPolicy int
const (
showChoiceByPolicy PreferenceOptionPolicy = iota
neverByPolicy
alwaysByPolicy
)
// Show returns if the UI option that controls the choice administered by this
// policy should be shown. Currently this is true if and only if the policy is
// showChoiceByPolicy.
func (p PreferenceOptionPolicy) Show() bool {
return p == showChoiceByPolicy
}
// ShouldEnable checks if the choice administered by this policy should be
// enabled. If the administrator has chosen a setting, the administrator's
// setting is returned, otherwise userChoice is returned.
func (p PreferenceOptionPolicy) ShouldEnable(userChoice bool) bool {
switch p {
case neverByPolicy:
return false
case alwaysByPolicy:
return true
default:
return userChoice
}
}
// GetPreferenceOptionPolicy loads a policy from the registry that can be
// managed by an enterprise policy management system and allows administrative
// overrides of users' choices in a way that we do not want tailcontrol to have
// the authority to set. It describes user-decides/always/never options, where
// "always" and "never" remove the user's ability to make a selection. If not
// present or set to a different value, "user-decides" is the default.
func GetPreferenceOptionPolicy(name string) PreferenceOptionPolicy {
opt := winutil.GetPolicyString(name, "user-decides")
switch opt {
case "always":
return alwaysByPolicy
case "never":
return neverByPolicy
default:
return showChoiceByPolicy
}
}
// VisibilityPolicy is a policy that controls whether or not a particular
// component of a user interface is to be shown.
type VisibilityPolicy byte
const (
visibleByPolicy VisibilityPolicy = 'v'
hiddenByPolicy VisibilityPolicy = 'h'
)
// Show reports whether the UI option administered by this policy should be shown.
// Currently this is true if and only if the policy is visibleByPolicy.
func (p VisibilityPolicy) Show() bool {
return p == visibleByPolicy
}
// GetVisibilityPolicy loads a policy from the registry that can be managed
// by an enterprise policy management system and describes show/hide decisions
// for UI elements. The registry value should be a string set to "show" (return
// true) or "hide" (return true). If not present or set to a different value,
// "show" (return false) is the default.
func GetVisibilityPolicy(name string) VisibilityPolicy {
opt := winutil.GetPolicyString(name, "show")
switch opt {
case "hide":
return hiddenByPolicy
default:
return visibleByPolicy
}
}
// GetDurationPolicy loads a policy from the registry that can be managed
// by an enterprise policy management system and describes a duration for some
// action. The registry value should be a string that time.ParseDuration
// understands. If the registry value is "" or can not be processed,
// defaultValue is returned instead.
func GetDurationPolicy(name string, defaultValue time.Duration) time.Duration {
opt := winutil.GetPolicyString(name, "")
if opt == "" {
return defaultValue
}
v, err := time.ParseDuration(opt)
if err != nil || v < 0 {
return defaultValue
}
return v
}
// SelectControlURL returns the ControlURL to use based on a value in
// the registry (LoginURL) and the one on disk (in the GUI's
// prefs.conf). If both are empty, it returns a default value. (It
// always return a non-empty value)
//
// See https://github.com/tailscale/tailscale/issues/2798 for some background.
func SelectControlURL(reg, disk string) string {
const def = "https://controlplane.tailscale.com"
// Prior to Dec 2020's commit 739b02e6, the installer
// wrote a LoginURL value of https://login.tailscale.com to the registry.
const oldRegDef = "https://login.tailscale.com"
// If they have an explicit value in the registry, use it,
// unless it's an old default value from an old installer.
// Then we have to see which is better.
if reg != "" {
if reg != oldRegDef {
// Something explicit in the registry that we didn't
// set ourselves by the installer.
return reg
}
if disk == "" {
// Something in the registry is better than nothing on disk.
return reg
}
if disk != def && disk != oldRegDef {
// The value in the registry is the old
// default (login.tailscale.com) but the value
// on disk is neither our old nor new default
// value, so it must be some custom thing that
// the user cares about. Prefer the disk value.
return disk
}
}
if disk != "" {
return disk
}
return def
}