From 2882ef338c334c51d25f613a144bbae260f080bb Mon Sep 17 00:00:00 2001 From: Christoph Hartmann Date: Tue, 26 Sep 2023 22:14:37 +0200 Subject: [PATCH 1/2] =?UTF-8?q?=E2=AD=90=EF=B8=8F=20aix=20platform=20detec?= =?UTF-8?q?tion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- providers/os/detector/detector_all.go | 38 ++++++++++- .../os/resources/packages/aix_packages.go | 68 +++++++++++++++++++ .../resources/packages/aix_packages_test.go | 30 ++++++++ providers/os/resources/packages/packages.go | 2 + .../packages/testdata/packages_aix.txt | 17 +++++ 5 files changed, 153 insertions(+), 2 deletions(-) create mode 100644 providers/os/resources/packages/aix_packages.go create mode 100644 providers/os/resources/packages/aix_packages_test.go create mode 100644 providers/os/resources/packages/testdata/packages_aix.txt diff --git a/providers/os/detector/detector_all.go b/providers/os/detector/detector_all.go index 717b49b104..7df5d27724 100644 --- a/providers/os/detector/detector_all.go +++ b/providers/os/detector/detector_all.go @@ -1005,7 +1005,7 @@ var linuxFamily = &PlatformResolver{ var unixFamily = &PlatformResolver{ Name: inventory.FAMILY_UNIX, IsFamily: true, - Children: []*PlatformResolver{bsdFamily, linuxFamily, solaris}, + Children: []*PlatformResolver{bsdFamily, linuxFamily, solaris, aix}, Detect: func(r *PlatformResolver, pf *inventory.Platform, conn shared.Connection) (bool, error) { // in order to support linux container image detection, we cannot run // processes here, lets just read files to detect a system @@ -1019,7 +1019,6 @@ var solaris = &PlatformResolver{ Detect: func(r *PlatformResolver, pf *inventory.Platform, conn shared.Connection) (bool, error) { osrd := NewOSReleaseDetector(conn) - // check if we got vmkernel unames, err := osrd.unames() if err != nil { return false, err @@ -1062,6 +1061,41 @@ var solaris = &PlatformResolver{ }, } +var aixUnameParser = regexp.MustCompile(`(\d+)\s+(\d+)\s+(.*)`) + +var aix = &PlatformResolver{ + Name: "aix", + IsFamily: false, + Detect: func(r *PlatformResolver, pf *inventory.Platform, conn shared.Connection) (bool, error) { + osrd := NewOSReleaseDetector(conn) + + unames, err := osrd.unames() + if err != nil { + return false, err + } + + if strings.Contains(strings.ToLower(unames), "aix") == false { + return false, nil + } + + pf.Name = "aix" + pf.Title = "AIX" + + // try to read the architecture and version + unamervp, err := osrd.command("uname -rvp") + if err == nil { + m := aixUnameParser.FindStringSubmatch(unamervp) + if len(m) == 4 { + pf.Version = m[2] + "." + m[1] + pf.Version = pf.Version + pf.Arch = m[3] + } + } + + return true, nil + }, +} + var esxi = &PlatformResolver{ Name: "esxi", IsFamily: false, diff --git a/providers/os/resources/packages/aix_packages.go b/providers/os/resources/packages/aix_packages.go new file mode 100644 index 0000000000..c9f689ea2c --- /dev/null +++ b/providers/os/resources/packages/aix_packages.go @@ -0,0 +1,68 @@ +// Copyright (c) Mondoo, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package packages + +import ( + "bufio" + "fmt" + "go.mondoo.com/cnquery/providers/os/connection/shared" + "io" + "strings" +) + +const ( + AixPkgFormat = "bff" +) + +func parseAixPackages(r io.Reader) ([]Package, error) { + pkgs := []Package{} + + scanner := bufio.NewScanner(r) + i := 0 + for scanner.Scan() { + line := scanner.Text() + i++ + + if i == 1 { + continue + } + + record := strings.Split(line, ":") + + // Fileset, Level, PtfID, State, Type, Description, EFIXLocked + pkgs = append(pkgs, Package{ + Name: record[1], + Version: record[2], + Description: strings.TrimSpace(record[6]), + Format: AixPkgFormat, + }) + + } + return pkgs, nil +} + +type AixPkgManager struct { + conn shared.Connection +} + +func (f *AixPkgManager) Name() string { + return "AIX Package Manager" +} + +func (f *AixPkgManager) Format() string { + return AixPkgFormat +} + +func (f *AixPkgManager) List() ([]Package, error) { + cmd, err := f.conn.RunCommand("lslpp -cl ") + if err != nil { + return nil, fmt.Errorf("could not read freebsd package list") + } + + return parseAixPackages(cmd.Stdout) +} + +func (f *AixPkgManager) Available() (map[string]PackageUpdate, error) { + return map[string]PackageUpdate{}, nil +} diff --git a/providers/os/resources/packages/aix_packages_test.go b/providers/os/resources/packages/aix_packages_test.go new file mode 100644 index 0000000000..67abe8a565 --- /dev/null +++ b/providers/os/resources/packages/aix_packages_test.go @@ -0,0 +1,30 @@ +// Copyright (c) Mondoo, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package packages + +import ( + "os" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestParseAixPackages(t *testing.T) { + f, err := os.Open("testdata/packages_aix.txt") + require.NoError(t, err) + + m, err := parseAixPackages(f) + require.Nil(t, err) + assert.Equal(t, 16, len(m), "detected the right amount of packages") + + var p Package + p = Package{ + Name: "X11.apps.msmit", + Version: "7.3.0.0", + Description: "AIXwindows msmit Application", + Format: "bff", + } + assert.Contains(t, m, p) +} diff --git a/providers/os/resources/packages/packages.go b/providers/os/resources/packages/packages.go index bf9b63af31..0e3bf5be27 100644 --- a/providers/os/resources/packages/packages.go +++ b/providers/os/resources/packages/packages.go @@ -73,6 +73,8 @@ func ResolveSystemPkgManager(conn shared.Connection) (OperatingSystemPkgManager, pm = &CosPkgManager{conn: conn} case asset.Platform.Name == "freebsd": pm = &FreeBSDPkgManager{conn: conn} + case asset.Platform.Name == "aix": + pm = &AixPkgManager{conn: conn} case asset.Platform.IsFamily("linux"): // no clear package manager for linux platform found // most likely we land here if we have a yocto-based system diff --git a/providers/os/resources/packages/testdata/packages_aix.txt b/providers/os/resources/packages/testdata/packages_aix.txt new file mode 100644 index 0000000000..d5194cc463 --- /dev/null +++ b/providers/os/resources/packages/testdata/packages_aix.txt @@ -0,0 +1,17 @@ +#Fileset:Level:PTF Id:State:Type:Description:EFIX Locked +/usr/lib/objrepos:ICU4C.rte:7.3.0.0::COMMITTED:I:International Components for Unicode : +/usr/lib/objrepos:Java8_64.jre:8.0.0.636::COMMITTED:I:Java SDK 64-bit Java Runtime Environment : +/usr/lib/objrepos:Java8_64.sdk:8.0.0.636::COMMITTED:I:Java SDK 64-bit Development Kit : +/usr/lib/objrepos:X11.adt.bitmaps:7.3.0.0::COMMITTED:I:AIXwindows Application Development Toolkit Bitmap Files : +/usr/lib/objrepos:X11.adt.imake:7.3.0.0::COMMITTED:I:AIXwindows Application Development Toolkit imake : +/usr/lib/objrepos:X11.adt.include:7.3.0.0::COMMITTED:I:AIXwindows Application Development Toolkit Include Files : +/usr/lib/objrepos:X11.adt.lib:7.3.0.0::COMMITTED:I:AIXwindows Application Development Toolkit Libraries : +/usr/lib/objrepos:X11.apps.aixterm:7.3.0.0::COMMITTED:I:AIXwindows aixterm Application : +/usr/lib/objrepos:X11.apps.clients:7.3.0.0::COMMITTED:I:AIXwindows Client Applications : +/usr/lib/objrepos:X11.apps.config:7.3.0.0::COMMITTED:I:AIXwindows Configuration Applications : +/usr/lib/objrepos:X11.apps.custom:7.3.0.0::COMMITTED:I:AIXwindows Customizing Tool : +/usr/lib/objrepos:X11.apps.msmit:7.3.0.0::COMMITTED:I:AIXwindows msmit Application : +/usr/lib/objrepos:X11.apps.rte:7.3.0.0::COMMITTED:I:AIXwindows Runtime Configuration Applications : +/usr/lib/objrepos:X11.apps.util:7.3.0.0::COMMITTED:I:AIXwindows Utility Applications : +/usr/lib/objrepos:X11.apps.xdm:7.3.0.0::COMMITTED:I:AIXwindows xdm Application : +/usr/lib/objrepos:X11.apps.xterm:7.3.0.0::COMMITTED:I:AIXwindows xterm Application : From b5793bb53c614709e879a9cf9fc815c6d1ac9009 Mon Sep 17 00:00:00 2001 From: Christoph Hartmann Date: Tue, 26 Sep 2023 23:45:14 +0200 Subject: [PATCH 2/2] =?UTF-8?q?=E2=AD=90=EF=B8=8F=20support=20aix=20servic?= =?UTF-8?q?es?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- providers/os/resources/services/aixlssrc.go | 66 +++++++++++++++++++ .../os/resources/services/aixlssrc_test.go | 35 ++++++++++ providers/os/resources/services/manager.go | 2 + 3 files changed, 103 insertions(+) create mode 100644 providers/os/resources/services/aixlssrc.go create mode 100644 providers/os/resources/services/aixlssrc_test.go diff --git a/providers/os/resources/services/aixlssrc.go b/providers/os/resources/services/aixlssrc.go new file mode 100644 index 0000000000..75ebd89b6a --- /dev/null +++ b/providers/os/resources/services/aixlssrc.go @@ -0,0 +1,66 @@ +// Copyright (c) Mondoo, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package services + +import ( + "bufio" + "go.mondoo.com/cnquery/providers/os/connection/shared" + "io" + "regexp" +) + +type AixServiceManager struct { + conn shared.Connection +} + +func (s *AixServiceManager) Name() string { + return "System Resource Controller" +} + +func (s *AixServiceManager) List() ([]*Service, error) { + cmd, err := s.conn.RunCommand("lssrc -a") + if err != nil { + return nil, err + } + + entries := parseLssrc(cmd.Stdout) + services := make([]*Service, len(entries)) + for i, entry := range entries { + services[i] = &Service{ + Name: entry.Subsystem, + Enabled: entry.Status == "active", + Installed: true, + Running: entry.Status == "active", + Type: "aix", + } + } + return services, nil +} + +type lssrcEntry struct { + Subsystem string + Group string + PID string + Status string +} + +var lssrcRegex = regexp.MustCompile(`^\s([\w.-]+)(\s+[\w]+\s+){0,1}([\d]+){0,1}\s+([\w]+)$`) + +func parseLssrc(input io.Reader) []lssrcEntry { + entries := []lssrcEntry{} + scanner := bufio.NewScanner(input) + for scanner.Scan() { + line := scanner.Text() + m := lssrcRegex.FindStringSubmatch(line) + if len(m) == 5 { + entries = append(entries, lssrcEntry{ + Subsystem: m[1], + Group: m[2], + PID: m[3], + Status: m[4], + }) + } + } + return entries +} diff --git a/providers/os/resources/services/aixlssrc_test.go b/providers/os/resources/services/aixlssrc_test.go new file mode 100644 index 0000000000..af43a0106c --- /dev/null +++ b/providers/os/resources/services/aixlssrc_test.go @@ -0,0 +1,35 @@ +// Copyright (c) Mondoo, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package services + +import ( + "github.com/stretchr/testify/assert" + "strings" + "testing" +) + +func TestLssrcParse(t *testing.T) { + testOutput := ` +Subsystem Group PID Status + syslogd ras 3932558 active + aso 4653462 active + biod nfs 5046692 active + rpc.lockd nfs 5636560 active + qdaemon spooler 5767630 active + ctrmc rsct 5439966 active + pmperfrec 6881768 active + IBM.HostRM rsct_rm 5898530 active + automountd autofs 7340402 active + lpd spooler inoperative + nimsh nimclient inoperative + nimhttp inoperative + timed tcpip inoperative +` + entries := parseLssrc(strings.NewReader(testOutput)) + assert.Equal(t, 13, len(entries), "detected the right amount of services") + assert.Equal(t, "syslogd", entries[0].Subsystem, "service name detected") + assert.Equal(t, "active", entries[0].Status, "service status detected") + assert.Equal(t, "timed", entries[12].Subsystem, "service name detected") + assert.Equal(t, "inoperative", entries[12].Status, "service status detected") +} diff --git a/providers/os/resources/services/manager.go b/providers/os/resources/services/manager.go index 6b7f24974d..00d4d80ab6 100644 --- a/providers/os/resources/services/manager.go +++ b/providers/os/resources/services/manager.go @@ -139,6 +139,8 @@ func ResolveManager(conn shared.Connection) (OSServiceManager, error) { osm = &AlpineOpenrcServiceManager{conn: conn} case asset.Platform.Name == "cos": osm = ResolveSystemdServiceManager(conn) + case asset.Platform.Name == "aix": + osm = &AixServiceManager{conn: conn} case asset.Platform.Name == "kali": // debian based with versions from 2015 onwards being systemd based osm = ResolveSystemdServiceManager(conn) }