From 5f22f726365851acfb189bfedf436ac34ef42782 Mon Sep 17 00:00:00 2001 From: Tom Proctor Date: Tue, 15 Oct 2024 19:38:11 +0100 Subject: [PATCH] hostinfo,build_docker.sh,tailcfg: more reliably detect being in a container (#13826) Our existing container-detection tricks did not work on Kubernetes, where Docker is no longer used as a container runtime. Extends the existing go build tags for containers to the other container packages and uses that to reliably detect builds that were created by Tailscale for use in a container. Unfortunately this doesn't necessarily improve detection for users' custom builds, but that's a separate issue. Updates #13825 Signed-off-by: Tom Proctor --- build_docker.sh | 2 ++ hostinfo/hostinfo.go | 13 +++++++++++-- hostinfo/hostinfo_container_linux_test.go | 16 ++++++++++++++++ hostinfo/hostinfo_linux_test.go | 8 +++++++- tailcfg/tailcfg.go | 2 +- 5 files changed, 37 insertions(+), 4 deletions(-) create mode 100644 hostinfo/hostinfo_container_linux_test.go diff --git a/build_docker.sh b/build_docker.sh index 1cbdc4b9e..e8b1c8f28 100755 --- a/build_docker.sh +++ b/build_docker.sh @@ -56,6 +56,7 @@ case "$TARGET" in -X tailscale.com/version.gitCommitStamp=${VERSION_GIT_HASH}" \ --base="${BASE}" \ --tags="${TAGS}" \ + --gotags="ts_kube,ts_package_container" \ --repos="${REPOS}" \ --push="${PUSH}" \ --target="${PLATFORM}" \ @@ -72,6 +73,7 @@ case "$TARGET" in -X tailscale.com/version.gitCommitStamp=${VERSION_GIT_HASH}" \ --base="${BASE}" \ --tags="${TAGS}" \ + --gotags="ts_kube,ts_package_container" \ --repos="${REPOS}" \ --push="${PUSH}" \ --target="${PLATFORM}" \ diff --git a/hostinfo/hostinfo.go b/hostinfo/hostinfo.go index 1f9037829..3233a422d 100644 --- a/hostinfo/hostinfo.go +++ b/hostinfo/hostinfo.go @@ -280,13 +280,22 @@ func getEnvType() EnvType { return "" } -// inContainer reports whether we're running in a container. +// inContainer reports whether we're running in a container. Best-effort only, +// there's no foolproof way to detect this, but the build tag should catch all +// official builds from 1.78.0. func inContainer() opt.Bool { if runtime.GOOS != "linux" { return "" } var ret opt.Bool ret.Set(false) + if packageType != nil && packageType() == "container" { + // Go build tag ts_package_container was set during build. + ret.Set(true) + return ret + } + // Only set if using docker's container runtime. Not guaranteed by + // documentation, but it's been in place for a long time. if _, err := os.Stat("/.dockerenv"); err == nil { ret.Set(true) return ret @@ -362,7 +371,7 @@ func inFlyDotIo() bool { } func inReplit() bool { - // https://docs.replit.com/programming-ide/getting-repl-metadata + // https://docs.replit.com/replit-workspace/configuring-repl#environment-variables if os.Getenv("REPL_OWNER") != "" && os.Getenv("REPL_SLUG") != "" { return true } diff --git a/hostinfo/hostinfo_container_linux_test.go b/hostinfo/hostinfo_container_linux_test.go new file mode 100644 index 000000000..594a5f512 --- /dev/null +++ b/hostinfo/hostinfo_container_linux_test.go @@ -0,0 +1,16 @@ +// Copyright (c) Tailscale Inc & AUTHORS +// SPDX-License-Identifier: BSD-3-Clause + +//go:build linux && !android && ts_package_container + +package hostinfo + +import ( + "testing" +) + +func TestInContainer(t *testing.T) { + if got := inContainer(); !got.EqualBool(true) { + t.Errorf("inContainer = %v; want true due to ts_package_container build tag", got) + } +} diff --git a/hostinfo/hostinfo_linux_test.go b/hostinfo/hostinfo_linux_test.go index 4859167a2..c8bd2abbe 100644 --- a/hostinfo/hostinfo_linux_test.go +++ b/hostinfo/hostinfo_linux_test.go @@ -1,7 +1,7 @@ // Copyright (c) Tailscale Inc & AUTHORS // SPDX-License-Identifier: BSD-3-Clause -//go:build linux && !android +//go:build linux && !android && !ts_package_container package hostinfo @@ -34,3 +34,9 @@ func TestQnap(t *testing.T) { t.Errorf("got %q; want %q", got, want) } } + +func TestInContainer(t *testing.T) { + if got := inContainer(); !got.EqualBool(false) { + t.Errorf("inContainer = %v; want false due to absence of ts_package_container build tag", got) + } +} diff --git a/tailcfg/tailcfg.go b/tailcfg/tailcfg.go index df50a8603..92bf2cd95 100644 --- a/tailcfg/tailcfg.go +++ b/tailcfg/tailcfg.go @@ -771,7 +771,7 @@ type Hostinfo struct { // "5.10.0-17-amd64". OSVersion string `json:",omitempty"` - Container opt.Bool `json:",omitempty"` // whether the client is running in a container + Container opt.Bool `json:",omitempty"` // best-effort whether the client is running in a container Env string `json:",omitempty"` // a hostinfo.EnvType in string form Distro string `json:",omitempty"` // "debian", "ubuntu", "nixos", ... DistroVersion string `json:",omitempty"` // "20.04", ...