syspolicy.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. // Copyright (c) Tailscale Inc & AUTHORS
  2. // SPDX-License-Identifier: BSD-3-Clause
  3. // Package syspolicy provides functions to retrieve system settings of a device.
  4. package syspolicy
  5. import (
  6. "errors"
  7. "time"
  8. "tailscale.com/util/syspolicy/internal/loggerx"
  9. "tailscale.com/util/syspolicy/setting"
  10. )
  11. func GetString(key Key, defaultValue string) (string, error) {
  12. markHandlerInUse()
  13. v, err := handler.ReadString(string(key))
  14. if errors.Is(err, ErrNoSuchKey) {
  15. return defaultValue, nil
  16. }
  17. return v, err
  18. }
  19. func GetUint64(key Key, defaultValue uint64) (uint64, error) {
  20. markHandlerInUse()
  21. v, err := handler.ReadUInt64(string(key))
  22. if errors.Is(err, ErrNoSuchKey) {
  23. return defaultValue, nil
  24. }
  25. return v, err
  26. }
  27. func GetBoolean(key Key, defaultValue bool) (bool, error) {
  28. markHandlerInUse()
  29. v, err := handler.ReadBoolean(string(key))
  30. if errors.Is(err, ErrNoSuchKey) {
  31. return defaultValue, nil
  32. }
  33. return v, err
  34. }
  35. func GetStringArray(key Key, defaultValue []string) ([]string, error) {
  36. markHandlerInUse()
  37. v, err := handler.ReadStringArray(string(key))
  38. if errors.Is(err, ErrNoSuchKey) {
  39. return defaultValue, nil
  40. }
  41. return v, err
  42. }
  43. // GetPreferenceOption loads a policy from the registry that can be
  44. // managed by an enterprise policy management system and allows administrative
  45. // overrides of users' choices in a way that we do not want tailcontrol to have
  46. // the authority to set. It describes user-decides/always/never options, where
  47. // "always" and "never" remove the user's ability to make a selection. If not
  48. // present or set to a different value, "user-decides" is the default.
  49. func GetPreferenceOption(name Key) (setting.PreferenceOption, error) {
  50. s, err := GetString(name, "user-decides")
  51. if err != nil {
  52. return setting.ShowChoiceByPolicy, err
  53. }
  54. var opt setting.PreferenceOption
  55. err = opt.UnmarshalText([]byte(s))
  56. return opt, err
  57. }
  58. // GetVisibility loads a policy from the registry that can be managed
  59. // by an enterprise policy management system and describes show/hide decisions
  60. // for UI elements. The registry value should be a string set to "show" (return
  61. // true) or "hide" (return true). If not present or set to a different value,
  62. // "show" (return false) is the default.
  63. func GetVisibility(name Key) (setting.Visibility, error) {
  64. s, err := GetString(name, "show")
  65. if err != nil {
  66. return setting.VisibleByPolicy, err
  67. }
  68. var visibility setting.Visibility
  69. visibility.UnmarshalText([]byte(s))
  70. return visibility, nil
  71. }
  72. // GetDuration loads a policy from the registry that can be managed
  73. // by an enterprise policy management system and describes a duration for some
  74. // action. The registry value should be a string that time.ParseDuration
  75. // understands. If the registry value is "" or can not be processed,
  76. // defaultValue is returned instead.
  77. func GetDuration(name Key, defaultValue time.Duration) (time.Duration, error) {
  78. opt, err := GetString(name, "")
  79. if opt == "" || err != nil {
  80. return defaultValue, err
  81. }
  82. v, err := time.ParseDuration(opt)
  83. if err != nil || v < 0 {
  84. return defaultValue, nil
  85. }
  86. return v, nil
  87. }
  88. // SelectControlURL returns the ControlURL to use based on a value in
  89. // the registry (LoginURL) and the one on disk (in the GUI's
  90. // prefs.conf). If both are empty, it returns a default value. (It
  91. // always return a non-empty value)
  92. //
  93. // See https://github.com/tailscale/tailscale/issues/2798 for some background.
  94. func SelectControlURL(reg, disk string) string {
  95. const def = "https://controlplane.tailscale.com"
  96. // Prior to Dec 2020's commit 739b02e6, the installer
  97. // wrote a LoginURL value of https://login.tailscale.com to the registry.
  98. const oldRegDef = "https://login.tailscale.com"
  99. // If they have an explicit value in the registry, use it,
  100. // unless it's an old default value from an old installer.
  101. // Then we have to see which is better.
  102. if reg != "" {
  103. if reg != oldRegDef {
  104. // Something explicit in the registry that we didn't
  105. // set ourselves by the installer.
  106. return reg
  107. }
  108. if disk == "" {
  109. // Something in the registry is better than nothing on disk.
  110. return reg
  111. }
  112. if disk != def && disk != oldRegDef {
  113. // The value in the registry is the old
  114. // default (login.tailscale.com) but the value
  115. // on disk is neither our old nor new default
  116. // value, so it must be some custom thing that
  117. // the user cares about. Prefer the disk value.
  118. return disk
  119. }
  120. }
  121. if disk != "" {
  122. return disk
  123. }
  124. return def
  125. }
  126. // SetDebugLoggingEnabled controls whether spammy debug logging is enabled.
  127. func SetDebugLoggingEnabled(v bool) {
  128. loggerx.SetDebugLoggingEnabled(v)
  129. }