go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers/os/resources/shadow.go (about) 1 // Copyright (c) Mondoo, Inc. 2 // SPDX-License-Identifier: BUSL-1.1 3 4 package resources 5 6 import ( 7 "errors" 8 "math" 9 "strconv" 10 "strings" 11 12 "github.com/rs/zerolog/log" 13 "go.mondoo.com/cnquery/llx" 14 "go.mondoo.com/cnquery/providers/os/resources/shadow" 15 ) 16 17 const defaultShadowConfig = "/etc/shadow" 18 19 func (s *mqlShadow) id() (string, error) { 20 return defaultShadowConfig, nil 21 } 22 23 func parseInt(s string, dflt int64, msg string) (int64, error) { 24 if s == "" { 25 return dflt, nil 26 } 27 28 res, err := strconv.ParseInt(s, 10, 64) 29 if err != nil { 30 return 0, errors.New("failed to parse " + msg + " as a number, it is '" + s + "'") 31 } 32 return res, nil 33 } 34 35 func (s *mqlShadow) list() ([]interface{}, error) { 36 // TODO: we may want to create a real mondoo file resource 37 o, err := CreateResource(s.MqlRuntime, "file", map[string]*llx.RawData{ 38 "path": llx.StringData(defaultShadowConfig), 39 }) 40 if err != nil { 41 return nil, err 42 } 43 44 file := o.(*mqlFile) 45 content := file.GetContent() 46 if content.Error != nil { 47 return nil, content.Error 48 } 49 50 entries, err := shadow.ParseShadow(strings.NewReader(content.Data)) 51 if err != nil { 52 return nil, err 53 } 54 55 shadowEntryResources := make([]interface{}, len(entries)) 56 for i := range entries { 57 entry := entries[i] 58 59 maxdays, err := parseInt(entry.MaxDays, math.MaxInt64, "MaxDays") 60 if err != nil { 61 return nil, err 62 } 63 64 mindays, err := parseInt(entry.MinDays, -1, "MinDays") 65 if err != nil { 66 return nil, err 67 } 68 69 warndays, err := parseInt(entry.WarnDays, -1, "WarnDays") 70 if err != nil { 71 return nil, err 72 } 73 74 inactivedays, err := parseInt(entry.InactiveDays, math.MaxInt64, "InactiveDays") 75 if err != nil { 76 return nil, err 77 } 78 79 lastChanged := llx.NilData 80 if entry.LastChanged != nil { 81 lastChanged = llx.TimeData(*entry.LastChanged) 82 } 83 84 o, err := CreateResource(s.MqlRuntime, "shadow.entry", map[string]*llx.RawData{ 85 "user": llx.StringData(entry.User), 86 "password": llx.StringData(entry.Password), 87 "lastchanged": lastChanged, 88 "mindays": llx.IntData(mindays), 89 "maxdays": llx.IntData(maxdays), 90 "warndays": llx.IntData(warndays), 91 "inactivedays": llx.IntData(inactivedays), 92 "expirydates": llx.StringData(entry.ExpiryDates), 93 "reserved": llx.StringData(entry.Reserved), 94 }) 95 if err != nil { 96 log.Error().Err(err).Str("shadow_entry", entry.User).Msg("mql[shadow_entry]> could not create shadow entry resource") 97 return nil, err 98 } 99 shadowEntryResources[i] = o.(*mqlShadowEntry) 100 } 101 102 return shadowEntryResources, nil 103 } 104 105 func (se *mqlShadowEntry) id() (string, error) { 106 return se.User.Data, nil 107 }