**Related issue:** Resolves #45710 # Checklist for submitter - [x] Changes file added (`changes/45710-zorin-os-support`). - [x] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters. - [x] Timeouts are implemented and retries are limited to avoid infinite loops. - [x] If paths of existing endpoints are modified without backwards compatibility, checked the frontend/CLI for any necessary changes. ## Testing - [x] Added/updated automated tests — `server/vulnerabilities/oval/oval_platform_test.go` extended with Zorin → Ubuntu LTS mapping cases (16/17/18) plus an unknown-version case (`Zorin OS 99` → `zorin_99`, which `IsSupported()` rejects). - [x] QA'd all new/changed functionality manually — Zorin OS 17.0 and 18.1 hosts enrolled against a patched Fleet server, host details show `platform=zorin`, software inventory populates, and OVAL CVE matching produces results against the corresponding `ubuntu_2204` / `ubuntu_2404` feeds. ## Database migrations - N/A. No schema changes. ## New Fleet configuration settings - N/A. No new settings. ## fleetd/orbit/Fleet Desktop - N/A. Server + frontend only; no fleetd/orbit changes. --- ## Summary Fleet previously logged `unrecognized platform` for Zorin OS hosts (osquery reports `platform=zorin` from `/etc/os-release` `ID=zorin`). The common workaround was running osquery with `--force_platform=ubuntu`, which masquerades the host. This change adds `zorin` as a first-class Linux platform alongside Ubuntu: - **`server/fleet/hosts.go`** — register `zorin` in `HostLinuxOSs` and `HostDebPackageOSs` - **`server/datastore/mysql/linux_mdm.go`** — include Zorin in the Linux disk-encryption summary query - **`server/vulnerabilities/oval/oval_platform.go`** — map Zorin major version to the underlying Ubuntu LTS OVAL feed (16 → 20.04, 17 → 22.04, 18 → 24.04). Unknown future versions fall through to an unsupported `zorin_<major>` identifier so vulnerability scanning is skipped rather than served stale data from an aging LTS feed. - **frontend** — add `zorin` to `HOST_LINUX_PLATFORMS`, the disk-encryption support list and type guard, the label platform dropdown, and the icon mapping (Ubuntu icon, since no Zorin-specific asset exists in the repo). No new dependency, schema migration, or config setting. Reuses existing Ubuntu OVAL feeds and the existing Ubuntu icon. Diff is ~30 lines net across 9 files (8 patched + 1 `changes/` file). <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added Zorin OS as a supported Linux platform. * Zorin hosts included in Linux disk-encryption summaries and treated as disk-encryption capable. * Zorin OS available as a selectable/filterable platform label and considered DEB-install compatible. * Vulnerability scanning enabled for Zorin 16→Ubuntu 20.04, 17→22.04, 18→24.04; unknown/future Zorin versions are marked unsupported and skipped for CVE matching. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45712?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai -->
135 lines
4.6 KiB
Go
135 lines
4.6 KiB
Go
package oval
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestOvalPlatform(t *testing.T) {
|
|
t.Run("NewPlatform", func(t *testing.T) {
|
|
cases := []struct {
|
|
platform string
|
|
osVersion string
|
|
expected string
|
|
}{
|
|
{"centos", "CentOS Linux 8.3.2011", "centos_08"},
|
|
{"ubuntu", "Ubuntu 20.4.0", "ubuntu_2004"},
|
|
{"centos", "CentOS 6.10.0", "centos_06"},
|
|
{"debian", "Debian GNU/Linux 9.0.0", "debian_09"},
|
|
{"debian", "Debian GNU/Linux 10.0.0", "debian_10"},
|
|
{"centos", "CentOS Linux 7.9.2009", "centos_07"},
|
|
{"ubuntu", "Ubuntu 16.4.0", "ubuntu_1604"},
|
|
{"ubuntu", "Ubuntu 18.4.0", "ubuntu_1804"},
|
|
{"ubuntu", "Ubuntu 18.4", "ubuntu_1804"},
|
|
{"ubuntu", "Ubuntu 18.4.0 ", "ubuntu_1804"},
|
|
{"ubuntu", "Ubuntu 18.4.0 LTS asdfasd", "ubuntu_1804"},
|
|
{"rhel", "CentOS Linux 7.9.2009", "rhel_07"},
|
|
{"amzn", "Amazon Linux 2.0.0", "amzn_02"},
|
|
{"amzn", "Amazon Linux 2023.0.0", "amzn_2023"},
|
|
{"rhel", "Fedora Linux 12.0.0", "rhel_06"},
|
|
{"rhel", "Fedora Linux 13.0.0", "rhel_06"},
|
|
{"rhel", "Fedora Linux 14.0.0", "rhel_06"},
|
|
{"rhel", "Fedora Linux 15.0.0", "rhel_06"},
|
|
{"rhel", "Fedora Linux 16.0.0", "rhel_06"},
|
|
{"rhel", "Fedora Linux 17.0.0", "rhel_06"},
|
|
{"rhel", "Fedora Linux 18.0.0", "rhel_06"},
|
|
{"rhel", "Fedora Linux 19.0.0", "rhel_07"},
|
|
{"rhel", "Fedora Linux 20.0.0", "rhel_07"},
|
|
{"rhel", "Fedora Linux 21.0.0", "rhel_07"},
|
|
{"rhel", "Fedora Linux 22.0.0", "rhel_07"},
|
|
{"rhel", "Fedora Linux 23.0.0", "rhel_07"},
|
|
{"rhel", "Fedora Linux 24.0.0", "rhel_07"},
|
|
{"rhel", "Fedora Linux 25.0.0", "rhel_07"},
|
|
{"rhel", "Fedora Linux 26.0.0", "rhel_07"},
|
|
{"rhel", "Fedora Linux 27.0.0", "rhel_07"},
|
|
{"rhel", "Fedora Linux 28.0.0", "rhel_08"},
|
|
{"rhel", "Fedora Linux 29.0.0", "rhel_08"},
|
|
{"rhel", "Fedora Linux 30.0.0", "rhel_08"},
|
|
{"rhel", "Fedora Linux 31.0.0", "rhel_08"},
|
|
{"rhel", "Fedora Linux 32.0.0", "rhel_08"},
|
|
{"rhel", "Fedora Linux 33.0.0", "rhel_08"},
|
|
{"rhel", "Fedora Linux 34.0.0", "rhel_09"},
|
|
{"rhel", "Fedora Linux 35.0.0", "rhel_09"},
|
|
{"rhel", "Fedora Linux 36.0.0", "rhel_09"},
|
|
{"ubuntu", "Ubuntu 20.04.2 LTS", "ubuntu_2004"},
|
|
{"zorin", "Zorin OS 16.0.0", "ubuntu_2004"},
|
|
{"zorin", "Zorin OS 17.0.0", "ubuntu_2204"},
|
|
{"zorin", "Zorin OS 18.1", "ubuntu_2404"},
|
|
{"zorin", "Zorin OS 99.0.0", "zorin_99"},
|
|
}
|
|
|
|
for _, c := range cases {
|
|
require.Equal(t, c.expected, string(NewPlatform(c.platform, c.osVersion)), c)
|
|
}
|
|
})
|
|
|
|
t.Run("ToFilename", func(t *testing.T) {
|
|
cases := []struct {
|
|
date time.Time
|
|
expected string
|
|
}{
|
|
{time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC), "fleet_oval_ubuntu_2004-2020_01_01.json"},
|
|
{time.Date(2020, 10, 10, 0, 0, 0, 0, time.UTC), "fleet_oval_ubuntu_2004-2020_10_10.json"},
|
|
}
|
|
for _, c := range cases {
|
|
plat := NewPlatform("ubuntu", "Ubuntu 20.4.0")
|
|
require.Equal(t, c.expected, plat.ToFilename(c.date, "json"))
|
|
}
|
|
})
|
|
|
|
t.Run("ToGovalDictionaryFilename", func(t *testing.T) {
|
|
cases := []struct {
|
|
version string
|
|
expected string
|
|
}{
|
|
{"Amazon Linux 2.0.0", "fleet_goval_dictionary_amzn_02.sqlite3"},
|
|
{"Amazon Linux 2023.0.0", "fleet_goval_dictionary_amzn_2023.sqlite3"},
|
|
}
|
|
for _, c := range cases {
|
|
plat := NewPlatform("amzn", c.version)
|
|
require.Equal(t, c.expected, plat.ToGovalDictionaryFilename())
|
|
}
|
|
})
|
|
|
|
t.Run("ToGovalDatabaseFilename", func(t *testing.T) {
|
|
cases := []struct {
|
|
version string
|
|
expected string
|
|
}{
|
|
{"Amazon Linux 1.0.0", "amzn_01.sqlite3"},
|
|
{"Amazon Linux 2.0.0", "amzn_02.sqlite3"},
|
|
{"Amazon Linux 2022.0.0", "amzn_2022.sqlite3"},
|
|
{"Amazon Linux 2023.0.0", "amzn_2023.sqlite3"},
|
|
}
|
|
for _, c := range cases {
|
|
plat := NewPlatform("amzn", c.version)
|
|
require.Equal(t, c.expected, plat.ToGovalDatabaseFilename())
|
|
}
|
|
})
|
|
|
|
t.Run("IsGovalDictionaryKernelOnly", func(t *testing.T) {
|
|
cases := []struct {
|
|
platform string
|
|
osVersion string
|
|
kernelOnly bool
|
|
}{
|
|
// Amazon Linux is NOT kernel-only (full goval-dictionary scanning)
|
|
{"amzn", "Amazon Linux 1.0.0", false},
|
|
{"amzn", "Amazon Linux 2.0.0", false},
|
|
{"amzn", "Amazon Linux 2023.0.0", false},
|
|
// RHEL is kernel-only (only kernel packages scanned via goval-dictionary)
|
|
{"rhel", "CentOS Linux 7.9.2009", true},
|
|
{"rhel", "CentOS Linux 8.3.2011", true},
|
|
{"rhel", "Red Hat Enterprise Linux 9.0.0", true},
|
|
// Ubuntu is not supported by goval-dictionary at all
|
|
{"ubuntu", "Ubuntu 20.4.0", false},
|
|
}
|
|
for _, c := range cases {
|
|
plat := NewPlatform(c.platform, c.osVersion)
|
|
require.Equal(t, c.kernelOnly, plat.IsGovalDictionaryKernelOnly(), "platform=%s, osVersion=%s", c.platform, c.osVersion)
|
|
}
|
|
})
|
|
}
|