Skip to content

Commit dfcf035

Browse files
authored
🐛 Fetch primary group members from /etc/passwd (#5458)
The primary group for a user isn't in /etc/group https://askubuntu.com/questions/1373865/etc-group-why-the-username-does-not-appear-in-its-own-primary-group
1 parent 16eec4c commit dfcf035

File tree

5 files changed

+94
-7
lines changed

5 files changed

+94
-7
lines changed

providers/os/resources/groups/etcgroups.go

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,17 @@ package groups
55

66
import (
77
"bufio"
8+
"errors"
89
"io"
910
"strconv"
1011
"strings"
1112

13+
"slices"
14+
1215
"github.com/rs/zerolog/log"
1316
"go.mondoo.com/cnquery/v11/providers/os/connection/shared"
17+
"go.mondoo.com/cnquery/v11/providers/os/resources/users"
18+
"go.mondoo.com/cnquery/v11/utils/multierr"
1419
)
1520

1621
// a good description of this file is available at:
@@ -77,7 +82,40 @@ func (s *UnixGroupManager) List() ([]*Group, error) {
7782
if err != nil {
7883
return nil, err
7984
}
80-
8185
defer f.Close()
82-
return ParseEtcGroup(f)
86+
87+
groups, err := ParseEtcGroup(f)
88+
if err != nil {
89+
return nil, multierr.Wrap(err, "could not parse /etc/group")
90+
}
91+
92+
um, err := users.ResolveManager(s.conn)
93+
if err != nil {
94+
return nil, multierr.Wrap(err, "cannot resolve users manager")
95+
}
96+
if um == nil {
97+
return nil, errors.New("cannot find users manager")
98+
}
99+
100+
groupsByGid := map[int64]*Group{}
101+
for i := range groups {
102+
g := groups[i]
103+
groupsByGid[g.Gid] = g
104+
}
105+
106+
users, err := um.List()
107+
if err != nil {
108+
return nil, multierr.Wrap(err, "could not retrieve users list")
109+
}
110+
111+
for _, u := range users {
112+
if g, ok := groupsByGid[u.Gid]; ok {
113+
if slices.Contains(g.Members, u.Name) {
114+
continue
115+
}
116+
g.Members = append(g.Members, u.Name)
117+
}
118+
}
119+
120+
return groups, nil
83121
}

providers/os/resources/groups/etcgroups_test.go

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
// Copyright (c) Mondoo, Inc.
22
// SPDX-License-Identifier: BUSL-1.1
33

4-
package groups_test
4+
package groups
55

66
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"
12-
"go.mondoo.com/cnquery/v11/providers/os/resources/groups"
1313
)
1414

1515
func TestParseLinuxEtcGroups(t *testing.T) {
@@ -24,7 +24,7 @@ func TestParseLinuxEtcGroups(t *testing.T) {
2424
assert.Nil(t, err)
2525
defer f.Close()
2626

27-
m, err := groups.ParseEtcGroup(f)
27+
m, err := ParseEtcGroup(f)
2828
assert.Nil(t, err)
2929
assert.Equal(t, 23, len(m), "detected the right amount of services")
3030

@@ -53,7 +53,7 @@ func TestParseFreebsd12EtcGroups(t *testing.T) {
5353
assert.Nil(t, err)
5454
defer f.Close()
5555

56-
m, err := groups.ParseEtcGroup(f)
56+
m, err := ParseEtcGroup(f)
5757
assert.Nil(t, err)
5858
assert.Equal(t, 36, len(m), "detected the right amount of services")
5959

@@ -69,3 +69,32 @@ func TestParseFreebsd12EtcGroups(t *testing.T) {
6969
assert.Equal(t, "", m[35].Sid, "detected sid")
7070
assert.Equal(t, []string{}, m[35].Members, "user description")
7171
}
72+
73+
func TestUnixGroupManager(t *testing.T) {
74+
mock, err := mock.New(0, "./testdata/debian.toml", &inventory.Asset{
75+
Platform: &inventory.Platform{
76+
Family: []string{"unix"},
77+
},
78+
})
79+
require.NoError(t, err)
80+
gm := &UnixGroupManager{
81+
conn: mock,
82+
}
83+
84+
groups, err := gm.List()
85+
require.NoError(t, err)
86+
87+
var vagrantGroup *Group
88+
for _, g := range groups {
89+
if g.Name == "vagrant" {
90+
vagrantGroup = g
91+
break
92+
}
93+
}
94+
95+
require.NotNil(t, vagrantGroup)
96+
assert.Equal(t, "vagrant", vagrantGroup.Name)
97+
assert.Equal(t, int64(1000), vagrantGroup.Gid)
98+
assert.Equal(t, "1000", vagrantGroup.ID)
99+
assert.Equal(t, []string{"vagrant"}, vagrantGroup.Members)
100+
}

providers/os/resources/groups/manager_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func TestManagerDebian(t *testing.T) {
3030
assert.Equal(t, "0", grp.ID)
3131
assert.Equal(t, int64(0), grp.Gid)
3232
assert.Equal(t, "root", grp.Name)
33-
assert.Equal(t, []string{}, grp.Members)
33+
assert.Equal(t, []string{"root", "sync", "shutdown", "halt", "operator"}, grp.Members)
3434

3535
assert.Equal(t, 23, len(groupList))
3636
}

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,22 @@ dbus:x:81:
2323
sshd:x:74:
2424
vagrant:x:1000:vagrant"""
2525

26+
[files."/etc/passwd"]
27+
content="""root:x:0:0:root:/root:/bin/bash
28+
bin:x:1:1:bin:/bin:/sbin/nologin
29+
daemon:x:2:2:daemon:/sbin:/sbin/nologin
30+
adm:x:3:4:adm:/var/adm:/sbin/nologin
31+
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
32+
sync:x:5:0:sync:/sbin:/bin/sync
33+
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
34+
halt:x:7:0:halt:/sbin:/sbin/halt
35+
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
36+
operator:x:11:0:operator:/root:/sbin/nologin
37+
games:x:12:100:games:/usr/games:/sbin/nologin
38+
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
39+
nobody:x:99:99:Nobody:/:/sbin/nologin
40+
vagrant:x:1000:1000::/home/vagrant:/bin/bash"""
41+
2642
[commands."uname -r"]
2743
stdout = "4.19.76-linuxkit"
2844

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ nobody:*:65534:
3838
messagebus:*:556:
3939
vagrant:*:1001:"""
4040

41+
[files."/etc/passwd"]
42+
content="""root:x:0:0:root:/root:/bin/bash
43+
"""
44+
4145
[commands."uname -s"]
4246
stdout = "FreeBSD"
4347

0 commit comments

Comments
 (0)