Skip to content

Commit c79b736

Browse files
agottardonickkhyl
andauthored
ipnlocal: allow overriding os.Hostname() via syspolicy (tailscale#14676)
Updates tailscale/corp#25936 This defines a new syspolicy 'Hostname' and allows an IT administrator to override the value we normally read from os.Hostname(). This is particularly useful on Android and iOS devices, where the hostname we get from the OS is really just the device model (a platform restriction to prevent fingerprinting). If we don't implement this, all devices on the customer's side will look like `google-pixel-7a-1`, `google-pixel-7a-2`, `google-pixel-7a-3`, etc. and it is not feasible for the customer to use the API or worse the admin console to manually fix these names. Apply code review comment by @nickkhyl Signed-off-by: Andrea Gottardo <[email protected]> Co-authored-by: Nick Khyl <[email protected]>
1 parent 97a44d6 commit c79b736

File tree

2 files changed

+37
-0
lines changed

2 files changed

+37
-0
lines changed

ipn/ipnlocal/local.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1703,6 +1703,37 @@ func applySysPolicy(prefs *ipn.Prefs, lastSuggestedExitNode tailcfg.StableNodeID
17031703
anyChange = true
17041704
}
17051705

1706+
const sentinel = "HostnameDefaultValue"
1707+
hostnameFromPolicy, _ := syspolicy.GetString(syspolicy.Hostname, sentinel)
1708+
switch hostnameFromPolicy {
1709+
case sentinel:
1710+
// An empty string for this policy value means that the admin wants to delete
1711+
// the hostname stored in the ipn.Prefs. To make that work, we need to
1712+
// distinguish between an empty string and a policy that was not set.
1713+
// We cannot do that with the current implementation of syspolicy.GetString.
1714+
// It currently does not return an error if a policy was not configured.
1715+
// Instead, it returns the default value provided as the second argument.
1716+
// This behavior makes it impossible to distinguish between a policy that
1717+
// was not set and a policy that was set to an empty default value.
1718+
// Checking for sentinel here is a workaround to distinguish between
1719+
// the two cases. If we get it, we do nothing because the policy was not set.
1720+
//
1721+
// TODO(angott,nickkhyl): clean up this behavior once syspolicy.GetString starts
1722+
// properly returning errors.
1723+
case "":
1724+
// The policy was set to an empty string, which means the admin intends
1725+
// to clear the hostname stored in preferences.
1726+
prefs.Hostname = ""
1727+
anyChange = true
1728+
default:
1729+
// The policy was set to a non-empty string, which means the admin wants
1730+
// to override the hostname stored in preferences.
1731+
if prefs.Hostname != hostnameFromPolicy {
1732+
prefs.Hostname = hostnameFromPolicy
1733+
anyChange = true
1734+
}
1735+
}
1736+
17061737
if exitNodeIDStr, _ := syspolicy.GetString(syspolicy.ExitNodeID, ""); exitNodeIDStr != "" {
17071738
exitNodeID := tailcfg.StableNodeID(exitNodeIDStr)
17081739
if shouldAutoExitNode() && lastSuggestedExitNode != "" {

util/syspolicy/policy_keys.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,11 @@ const (
123123
// Example: "CN=Tailscale Inc Test Root CA,OU=Tailscale Inc Test Certificate Authority,O=Tailscale Inc,ST=ON,C=CA"
124124
MachineCertificateSubject Key = "MachineCertificateSubject"
125125

126+
// Hostname is the hostname of the device that is running Tailscale.
127+
// When this policy is set, it overrides the hostname that the client
128+
// would otherwise obtain from the OS, e.g. by calling os.Hostname().
129+
Hostname Key = "Hostname"
130+
126131
// Keys with a string array value.
127132
// 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.
128133
AllowedSuggestedExitNodes Key = "AllowedSuggestedExitNodes"
@@ -148,6 +153,7 @@ var implicitDefinitions = []*setting.Definition{
148153
setting.NewDefinition(ExitNodeID, setting.DeviceSetting, setting.StringValue),
149154
setting.NewDefinition(ExitNodeIP, setting.DeviceSetting, setting.StringValue),
150155
setting.NewDefinition(FlushDNSOnSessionUnlock, setting.DeviceSetting, setting.BooleanValue),
156+
setting.NewDefinition(Hostname, setting.DeviceSetting, setting.StringValue),
151157
setting.NewDefinition(LogSCMInteractions, setting.DeviceSetting, setting.BooleanValue),
152158
setting.NewDefinition(LogTarget, setting.DeviceSetting, setting.StringValue),
153159
setting.NewDefinition(MachineCertificateSubject, setting.DeviceSetting, setting.StringValue),

0 commit comments

Comments
 (0)