mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-25 11:05:45 +00:00
version,cli,safesocket: detect non-sandboxed macOS GUI (#11369)
Updates ENG-2848 We can safely disable the App Sandbox for our macsys GUI, allowing us to use `tailscale ssh` and do a few other things that we've wanted to do for a while. This PR: - allows Tailscale SSH to be used from the macsys GUI binary when called from a CLI - tweaks the detection of client variants in prop.go, with new functions `IsMacSys()`, `IsMacSysApp()` and `IsMacAppSandboxEnabled()` Signed-off-by: Andrea Gottardo <andrea@gottardo.me>
This commit is contained in:
parent
ea55f96310
commit
08ebac9acb
@ -48,8 +48,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runSSH(ctx context.Context, args []string) error {
|
func runSSH(ctx context.Context, args []string) error {
|
||||||
if runtime.GOOS == "darwin" && version.IsSandboxedMacOS() && !envknob.UseWIPCode() {
|
if runtime.GOOS == "darwin" && version.IsMacAppStore() && !envknob.UseWIPCode() {
|
||||||
return errors.New("The 'tailscale ssh' subcommand is not available on sandboxed macOS builds.\nUse the regular 'ssh' client instead.")
|
return errors.New("The 'tailscale ssh' subcommand is not available on macOS builds distributed through the App Store or TestFlight.\nInstall the Standalone variant of Tailscale (download it from https://pkgs.tailscale.com), or use the regular 'ssh' client instead.")
|
||||||
}
|
}
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
return errors.New("usage: ssh [user@]<host>")
|
return errors.New("usage: ssh [user@]<host>")
|
||||||
|
@ -74,7 +74,7 @@ func localTCPPortAndTokenDarwin() (port int, token string, err error) {
|
|||||||
|
|
||||||
if dir := os.Getenv("TS_MACOS_CLI_SHARED_DIR"); dir != "" {
|
if dir := os.Getenv("TS_MACOS_CLI_SHARED_DIR"); dir != "" {
|
||||||
// First see if we're running as the non-AppStore "macsys" variant.
|
// First see if we're running as the non-AppStore "macsys" variant.
|
||||||
if version.IsMacSysExt() {
|
if version.IsMacSys() {
|
||||||
if port, token, err := localTCPPortAndTokenMacsys(); err == nil {
|
if port, token, err := localTCPPortAndTokenMacsys(); err == nil {
|
||||||
return port, token, nil
|
return port, token, nil
|
||||||
}
|
}
|
||||||
|
@ -48,10 +48,38 @@ func IsSandboxedMacOS() bool {
|
|||||||
return IsMacAppStore() || IsMacSysExt()
|
return IsMacAppStore() || IsMacSysExt()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsMacSys reports whether this process is part of the Standalone variant of
|
||||||
|
// Tailscale for macOS, either the main GUI process (non-sandboxed) or the
|
||||||
|
// system extension (sandboxed).
|
||||||
|
func IsMacSys() bool {
|
||||||
|
return IsMacSysExt() || IsMacSysApp()
|
||||||
|
}
|
||||||
|
|
||||||
|
var isMacSysApp lazy.SyncValue[bool]
|
||||||
|
|
||||||
|
// IsMacSysApp reports whether this process is the main, non-sandboxed GUI process
|
||||||
|
// that ships with the Standalone variant of Tailscale for macOS.
|
||||||
|
func IsMacSysApp() bool {
|
||||||
|
if runtime.GOOS != "darwin" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return isMacSysApp.Get(func() bool {
|
||||||
|
exe, err := os.Executable()
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// Check that this is the GUI binary, and it is not sandboxed. The GUI binary
|
||||||
|
// shipped in the App Store will always have the App Sandbox enabled.
|
||||||
|
return strings.HasSuffix(exe, "/Contents/MacOS/Tailscale") && !IsMacAppSandboxEnabled()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
var isMacSysExt lazy.SyncValue[bool]
|
var isMacSysExt lazy.SyncValue[bool]
|
||||||
|
|
||||||
// IsMacSysExt whether this binary is from the standalone "System
|
// IsMacSysExt reports whether this binary is the system extension shipped as part of
|
||||||
// Extension" (a.k.a. "macsys") version of Tailscale for macOS.
|
// the standalone "System Extension" (a.k.a. "macsys") version of Tailscale
|
||||||
|
// for macOS.
|
||||||
func IsMacSysExt() bool {
|
func IsMacSysExt() bool {
|
||||||
if runtime.GOOS != "darwin" {
|
if runtime.GOOS != "darwin" {
|
||||||
return false
|
return false
|
||||||
@ -68,6 +96,19 @@ func IsMacSysExt() bool {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isMacAppSandboxEnabled lazy.SyncValue[bool]
|
||||||
|
|
||||||
|
// IsMacAppSandboxEnabled reports whether this process is subject to the App Sandbox
|
||||||
|
// on macOS.
|
||||||
|
func IsMacAppSandboxEnabled() bool {
|
||||||
|
if runtime.GOOS != "darwin" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return isMacAppSandboxEnabled.Get(func() bool {
|
||||||
|
return os.Getenv("APP_SANDBOX_CONTAINER_ID") != ""
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
var isMacAppStore lazy.SyncValue[bool]
|
var isMacAppStore lazy.SyncValue[bool]
|
||||||
|
|
||||||
// IsMacAppStore whether this binary is from the App Store version of Tailscale
|
// IsMacAppStore whether this binary is from the App Store version of Tailscale
|
||||||
@ -80,6 +121,11 @@ func IsMacAppStore() bool {
|
|||||||
// Both macsys and app store versions can run CLI executable with
|
// Both macsys and app store versions can run CLI executable with
|
||||||
// suffix /Contents/MacOS/Tailscale. Check $HOME to filter out running
|
// suffix /Contents/MacOS/Tailscale. Check $HOME to filter out running
|
||||||
// as macsys.
|
// as macsys.
|
||||||
|
if !IsMacAppSandboxEnabled() {
|
||||||
|
// If no sandbox found, we're definitely not on an App Store release, as you cannot push
|
||||||
|
// anything to the App Store that has the App Sandbox disabled.
|
||||||
|
return false
|
||||||
|
}
|
||||||
if strings.Contains(os.Getenv("HOME"), "/Containers/io.tailscale.ipn.macsys/") {
|
if strings.Contains(os.Getenv("HOME"), "/Containers/io.tailscale.ipn.macsys/") {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user