From 03b18a81e3b5b31e3f94040eae0ec2d05542b5d6 Mon Sep 17 00:00:00 2001 From: Christoph Hartmann Date: Wed, 31 Jan 2024 15:02:52 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=A7=B9=20ensure=20we=20use=20fqdn=20for?= =?UTF-8?q?=20hostname=20platform=20id=20on=20unix=20systems=20(#3166)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- providers/os/id/hostname/hostname.go | 30 +++++++++++----- providers/os/id/hostname/hostname_test.go | 12 +++++++ .../id/hostname/testdata/hostname_fqdn.toml | 36 +++++++++++++++++++ 3 files changed, 70 insertions(+), 8 deletions(-) create mode 100644 providers/os/id/hostname/testdata/hostname_fqdn.toml diff --git a/providers/os/id/hostname/hostname.go b/providers/os/id/hostname/hostname.go index 0484e0c8c1..be6bc77ae3 100644 --- a/providers/os/id/hostname/hostname.go +++ b/providers/os/id/hostname/hostname.go @@ -13,6 +13,11 @@ import ( "go.mondoo.com/cnquery/v10/providers/os/connection/shared" ) +// Hostname returns the hostname of the system. + +// On Linux systems we prefer `hostname -f` over `/etc/hostname` since systemd is not updating the value all the time. +// On Windows the `hostname` command (without the -f flag) works more reliable than `powershell -c "$env:computername"` +// since it will return a non-zero exit code. func Hostname(conn shared.Connection, pf *inventory.Platform) (string, bool) { var hostname string @@ -21,12 +26,20 @@ func Hostname(conn shared.Connection, pf *inventory.Platform) (string, bool) { return hostname, false } - // linux: - // we prefer the hostname over /etc/hostname since systemd is not updating the value all the time - // - // windows: - // hostname command works more reliable than t.RunCommand("powershell -c \"$env:computername\"") - // since it will return a non-zero exit code. + // on unix systems we try to get the hostname via `hostname -f` first since it returns the fqdn + if pf.IsFamily(inventory.FAMILY_UNIX) { + cmd, err := conn.RunCommand("hostname -f") + if err == nil && cmd.ExitStatus == 0 { + data, err := io.ReadAll(cmd.Stdout) + if err == nil { + return strings.TrimSpace(string(data)), true + } + } else { + log.Debug().Err(err).Msg("could not run `hostname -f` command") + } + } + + // This is the preferred way to get the hostname on windows, it is important to not use the -f flag here cmd, err := conn.RunCommand("hostname") if err == nil && cmd.ExitStatus == 0 { data, err := io.ReadAll(cmd.Stdout) @@ -34,10 +47,11 @@ func Hostname(conn shared.Connection, pf *inventory.Platform) (string, bool) { return strings.TrimSpace(string(data)), true } } else { - log.Debug().Err(err).Msg("could not run hostname command") + log.Debug().Err(err).Msg("could not run `hostname` command") } - // try to use /etc/hostname since it's also working on static analysis + // Fallback to for unix systems to /etc/hostname, since hostname command is not available on all systems + // This mechanism is also working for static analysis if pf.IsFamily(inventory.FAMILY_LINUX) { afs := &afero.Afero{Fs: conn.FileSystem()} ok, err := afs.Exists("/etc/hostname") diff --git a/providers/os/id/hostname/hostname_test.go b/providers/os/id/hostname/hostname_test.go index 9fee24b327..f1933110f6 100644 --- a/providers/os/id/hostname/hostname_test.go +++ b/providers/os/id/hostname/hostname_test.go @@ -37,6 +37,18 @@ func TestHostnameLinux(t *testing.T) { assert.Equal(t, "abefed34cc9c", hostame) } +func TestHostnameLinuxFqdn(t *testing.T) { + conn, err := mock.New("./testdata/hostname_fqdn.toml", nil) + require.NoError(t, err) + platform, ok := detector.DetectOS(conn) + require.True(t, ok) + + hostame, ok := hostname.Hostname(conn, platform) + require.True(t, ok) + + assert.Equal(t, "myhost.example.com", hostame) +} + func TestHostnameWindows(t *testing.T) { conn, err := mock.New("./testdata/hostname_windows.toml", nil) require.NoError(t, err) diff --git a/providers/os/id/hostname/testdata/hostname_fqdn.toml b/providers/os/id/hostname/testdata/hostname_fqdn.toml new file mode 100644 index 0000000000..8f927dba8c --- /dev/null +++ b/providers/os/id/hostname/testdata/hostname_fqdn.toml @@ -0,0 +1,36 @@ +[commands."hostname"] +stdout="myhost" + +[commands."hostname -f"] +stdout="myhost.example.com" + +[commands."uname -s"] +stdout = "Linux" + +[commands."uname -m"] +stdout = "x86_64" + +[commands."uname -r"] +stdout = "4.9.125-linuxkit" + +[files."/etc/redhat-release"] +content = "Red Hat Enterprise Linux Server release 7.2 (Maipo)" + +[files."/etc/os-release"] +content = """ +NAME="Red Hat Enterprise Linux Server" +VERSION="7.2 (Maipo)" +ID="rhel" +ID_LIKE="fedora" +VERSION_ID="7.2" +PRETTY_NAME="Red Hat Enterprise Linux Server 7.2 (Maipo)" +ANSI_COLOR="0;31" +CPE_NAME="cpe:/o:redhat:enterprise_linux:7.2:GA:server" +HOME_URL="https://www.redhat.com/" +BUG_REPORT_URL="https://bugzilla.redhat.com/" + +REDHAT_BUGZILLA_PRODUCT="Red Hat Enterprise Linux 7" +REDHAT_BUGZILLA_PRODUCT_VERSION=7.2 +REDHAT_SUPPORT_PRODUCT="Red Hat Enterprise Linux" +REDHAT_SUPPORT_PRODUCT_VERSION="7.2" +""" \ No newline at end of file