go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers/os/resources/groups/dscache.go (about) 1 // Copyright (c) Mondoo, Inc. 2 // SPDX-License-Identifier: BUSL-1.1 3 4 package groups 5 6 import ( 7 "bufio" 8 "io" 9 "regexp" 10 "strconv" 11 "strings" 12 13 "github.com/rs/zerolog/log" 14 "go.mondoo.com/cnquery/providers/os/connection/shared" 15 ) 16 17 var GROUP_OSX_DSCACHEUTIL_REGEX = regexp.MustCompile(`^(\S+):\s(.*?)$`) 18 19 func ParseDscacheutilResult(input io.Reader) ([]*Group, error) { 20 groups := map[string]*Group{} 21 22 add := func(group Group) { 23 // a group must have a username, otherwise it is not valid 24 // this will happen at least for the last item, where we got an empty row 25 // we also need to eliminate duplicates, it happens on macos with dscacheutil -q group 26 if len(group.ID) != 0 { 27 groups[group.ID] = &group 28 } 29 } 30 31 scanner := bufio.NewScanner(input) 32 group := Group{Members: []string{}} 33 34 var key string 35 for scanner.Scan() { 36 line := scanner.Text() 37 38 // reset group definition once we reach an empty line 39 if len(line) == 0 { 40 add(group) 41 group = Group{Members: []string{}} 42 } 43 44 m := GROUP_OSX_DSCACHEUTIL_REGEX.FindStringSubmatch(line) 45 key = "" 46 if m != nil { 47 key = m[1] 48 } 49 50 // Parse the group content 51 switch key { 52 case "name": 53 group.Name = strings.TrimSpace(m[2]) 54 case "password": 55 // we ignore the password for now 56 case "gid": 57 gid, err := strconv.ParseInt(m[2], 10, 0) 58 if err != nil { 59 log.Error().Err(err).Str("group", m[0]).Msg("could not parse gid") 60 } 61 group.ID = m[2] 62 group.Gid = gid 63 case "users": 64 content := strings.TrimSpace(m[2]) 65 if len(content) > 0 { 66 group.Members = strings.Split(content, " ") 67 } 68 } 69 } 70 71 // if the last line is not an empty line we have things in flight, lets check it 72 add(group) 73 74 res := []*Group{} 75 for k := range groups { 76 res = append(res, groups[k]) 77 } 78 79 return res, nil 80 } 81 82 type OSXGroupManager struct { 83 conn shared.Connection 84 } 85 86 func (s *OSXGroupManager) Name() string { 87 return "macOS Group Manager" 88 } 89 90 func (s *OSXGroupManager) Group(id string) (*Group, error) { 91 groups, err := s.List() 92 if err != nil { 93 return nil, err 94 } 95 96 return findGroup(groups, id) 97 } 98 99 func (s *OSXGroupManager) List() ([]*Group, error) { 100 c, err := s.conn.RunCommand("dscacheutil -q group") 101 if err != nil { 102 return nil, err 103 } 104 return ParseDscacheutilResult(c.Stdout) 105 }