Skip to content

Commit 9a63cde

Browse files
committed
⭐️ os: list users on linux via getent passwd
When a linux machine is enrolled in an Active Directory, we do not discover all the users on the system. This is affecting the `ports.listening` resource. This change uses `getent passwd` to fetch user information and, if that doesn't work, we fallback to the old method. https://man7.org/linux/man-pages/man1/getent.1.html Closes #5341 Signed-off-by: Salim Afiune Maya <afiune@mondoo.com>
1 parent ebb77e5 commit 9a63cde

5 files changed

Lines changed: 98 additions & 3 deletions

File tree

providers/os/resources/users/etcpasswd.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,29 @@ func (s *UnixUserManager) User(id string) (*User, error) {
7373
}
7474

7575
func (s *UnixUserManager) List() ([]*User, error) {
76+
users, err := s.listGetentPasswd()
77+
if err == nil && len(users) != 0 {
78+
return users, nil
79+
}
80+
// fallback to /etc/passwd
81+
return s.listEtcPasswd()
82+
}
83+
84+
func (s *UnixUserManager) listEtcPasswd() ([]*User, error) {
7685
f, err := s.conn.FileSystem().Open("/etc/passwd")
7786
if err != nil {
7887
return nil, err
7988
}
8089
defer f.Close()
8190
return ParseEtcPasswd(f)
8291
}
92+
93+
// https://man7.org/linux/man-pages/man1/getent.1.html
94+
func (s *UnixUserManager) listGetentPasswd() ([]*User, error) {
95+
getent, err := s.conn.RunCommand("getent passwd")
96+
if err != nil {
97+
return nil, err
98+
}
99+
100+
return ParseEtcPasswd(getent.Stdout)
101+
}

providers/os/resources/users/etcpasswd_test.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"testing"
88

99
"github.com/stretchr/testify/assert"
10+
"github.com/stretchr/testify/require"
1011
"go.mondoo.com/cnquery/v11/providers-sdk/v1/inventory"
1112
"go.mondoo.com/cnquery/v11/providers/os/connection/mock"
1213
"go.mondoo.com/cnquery/v11/providers/os/resources/users"
@@ -59,3 +60,25 @@ func TestParseFreebsdLinuxEtcPasswd(t *testing.T) {
5960
assert.Equal(t, "/root", m[0].Home, "detected user home")
6061
assert.Equal(t, "/bin/csh", m[0].Shell, "detected user shell")
6162
}
63+
64+
func TestParseLinuxGetentPasswd(t *testing.T) {
65+
conn, err := mock.New(0, "./testdata/oraclelinux_getent_passwd.toml", &inventory.Asset{
66+
Platform: &inventory.Platform{
67+
Family: []string{"os", "unix", "linux", "redhat"},
68+
},
69+
})
70+
require.NoError(t, err)
71+
m, err := users.ResolveManager(conn)
72+
require.Nil(t, err)
73+
74+
list, err := m.List()
75+
require.Nil(t, err)
76+
assert.Equal(t, 20, len(list), "detected the right amount of users")
77+
78+
assert.Equal(t, "root", list[0].Name, "detected user name")
79+
assert.Equal(t, int64(0), list[0].Uid, "detected uid")
80+
assert.Equal(t, int64(0), list[0].Gid, "detected gid")
81+
assert.Equal(t, "root", list[0].Description, "user description")
82+
assert.Equal(t, "/root", list[0].Home, "detected user home")
83+
assert.Equal(t, "/bin/bash", list[0].Shell, "detected user shell")
84+
}

providers/os/resources/users/testdata/debian.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,4 @@ ID=debian
3333
HOME_URL="https://www.debian.org/"
3434
SUPPORT_URL="https://www.debian.org/support"
3535
BUG_REPORT_URL="https://bugs.debian.org/"
36-
"""
36+
"""

providers/os/resources/users/testdata/freebsd12.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,11 @@ nobody:*:65534:65534:Unprivileged user:/nonexistent:/usr/sbin/nologin
3030
messagebus:*:556:556:D-BUS Daemon User:/nonexistent:/usr/sbin/nologin
3131
vagrant:*:1001:1001:Vagrant User:/home/vagrant:/bin/csh"""
3232

33-
3433
[commands."uname -s"]
3534
stdout = "FreeBSD"
3635

3736
[commands."uname -m"]
3837
stdout = "amd64"
3938

4039
[commands."uname -r"]
41-
stdout = "12.0-CURRENT"
40+
stdout = "12.0-CURRENT"
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
[commands."getent passwd"]
2+
stdout="""
3+
root:x:0:0:root:/root:/bin/bash
4+
bin:x:1:1:bin:/bin:/sbin/nologin
5+
daemon:x:2:2:daemon:/sbin:/sbin/nologin
6+
adm:x:3:4:adm:/var/adm:/sbin/nologin
7+
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
8+
sync:x:5:0:sync:/sbin:/bin/sync
9+
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
10+
halt:x:7:0:halt:/sbin:/sbin/halt
11+
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
12+
operator:x:11:0:operator:/root:/sbin/nologin
13+
games:x:12:100:games:/usr/games:/sbin/nologin
14+
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
15+
nobody:x:65534:65534:Kernel Overflow User:/:/sbin/nologin
16+
tss:x:59:59:Account used for TPM access:/:/usr/sbin/nologin
17+
systemd-coredump:x:999:997:systemd Core Dumper:/:/sbin/nologin
18+
dbus:x:81:81:System message bus:/:/sbin/nologin
19+
chrony:x:998:996:chrony system user:/var/lib/chrony:/sbin/nologin
20+
sshd:x:74:74:Privilege-separated SSH:/usr/share/empty.sshd:/usr/sbin/nologin
21+
vboxadd:x:997:1::/var/run/vboxadd:/bin/false
22+
vagrant:x:1000:1000::/home/vagrant:/bin/bash
23+
"""
24+
25+
[commands."uname -r"]
26+
stdout = "5.15.0-306.177.4.el9uek.aarch64"
27+
28+
[commands."uname -s"]
29+
stdout = "Linux"
30+
31+
[commands."uname -m"]
32+
stdout = "aarch64"
33+
34+
[files."/etc/os-release"]
35+
content = """
36+
NAME="Oracle Linux Server"
37+
VERSION="9.5"
38+
ID="ol"
39+
ID_LIKE="fedora"
40+
VARIANT="Server"
41+
VARIANT_ID="server"
42+
VERSION_ID="9.5"
43+
PLATFORM_ID="platform:el9"
44+
PRETTY_NAME="Oracle Linux Server 9.5"
45+
ANSI_COLOR="0;31"
46+
CPE_NAME="cpe:/o:oracle:linux:9:5:server"
47+
HOME_URL="https://linux.oracle.com/"
48+
BUG_REPORT_URL="https://github.com/oracle/oracle-linux"
49+
50+
ORACLE_BUGZILLA_PRODUCT="Oracle Linux 9"
51+
ORACLE_BUGZILLA_PRODUCT_VERSION=9.5
52+
ORACLE_SUPPORT_PRODUCT="Oracle Linux"
53+
ORACLE_SUPPORT_PRODUCT_VERSION=9.5
54+
"""

0 commit comments

Comments
 (0)