go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers/os/resources/services.go (about) 1 // Copyright (c) Mondoo, Inc. 2 // SPDX-License-Identifier: BUSL-1.1 3 4 package resources 5 6 import ( 7 "errors" 8 "sync" 9 10 "github.com/rs/zerolog/log" 11 "go.mondoo.com/cnquery/llx" 12 "go.mondoo.com/cnquery/providers-sdk/v1/plugin" 13 "go.mondoo.com/cnquery/providers/os/connection/shared" 14 "go.mondoo.com/cnquery/providers/os/resources/services" 15 ) 16 17 func initService(runtime *plugin.Runtime, args map[string]*llx.RawData) (map[string]*llx.RawData, plugin.Resource, error) { 18 if len(args) != 1 { 19 return args, nil, nil 20 } 21 22 x, ok := args["name"] 23 if !ok { 24 return nil, nil, errors.New("cannot initialize service, need at least a name to look it up") 25 } 26 27 name := x.Value.(string) 28 if name == "" { 29 return nil, nil, errors.New("cannot look for a service with an empty name") 30 } 31 32 raw, err := CreateResource(runtime, "services", nil) 33 if err != nil { 34 return nil, nil, err 35 } 36 services := raw.(*mqlServices) 37 38 if err := services.refreshCache(nil); err != nil { 39 return nil, nil, err 40 } 41 42 if srv, ok := services.namedServices[name]; ok { 43 return nil, srv, nil 44 } 45 46 res := &mqlService{} 47 res.Name = plugin.TValue[string]{Data: name, State: plugin.StateIsSet} 48 res.Description.State = plugin.StateIsSet | plugin.StateIsNull 49 res.Installed = plugin.TValue[bool]{Data: false, State: plugin.StateIsSet} 50 res.Running = plugin.TValue[bool]{Data: false, State: plugin.StateIsSet} 51 res.Enabled = plugin.TValue[bool]{Data: false, State: plugin.StateIsSet} 52 res.Type.State = plugin.StateIsSet | plugin.StateIsNull 53 res.Enabled = plugin.TValue[bool]{Data: false, State: plugin.StateIsSet} 54 res.Masked = plugin.TValue[bool]{Data: false, State: plugin.StateIsSet} 55 return nil, res, nil 56 } 57 58 func (x *mqlService) id() (string, error) { 59 return x.Name.Data, nil 60 } 61 62 type mqlServicesInternal struct { 63 lock sync.Mutex 64 namedServices map[string]*mqlService 65 } 66 67 func (x *mqlServices) list() ([]interface{}, error) { 68 x.lock.Lock() 69 defer x.lock.Unlock() 70 71 // find suitable service manager 72 conn := x.MqlRuntime.Connection.(shared.Connection) 73 osm, err := services.ResolveManager(conn) 74 if osm == nil || err != nil { 75 // there are valid cases where this error is happening, eg. you run a service query in 76 // asset filters for non-supported providers 77 log.Debug().Err(err).Msg("mql[services]> could not retrieve services list") 78 return nil, errors.New("cannot find service manager") 79 } 80 81 // retrieve all system services 82 services, err := osm.List() 83 if err != nil { 84 log.Debug().Err(err).Msg("mql[services]> could not retrieve service list") 85 return nil, errors.New("could not retrieve service list") 86 } 87 log.Debug().Int("services", len(services)).Msg("mql[services]> running services") 88 89 // convert to interface{}{} 90 mqlSrvs := []interface{}{} 91 92 for i := range services { 93 srv := services[i] 94 95 mqlSrv, err := CreateResource(x.MqlRuntime, "service", map[string]*llx.RawData{ 96 "name": llx.StringData(srv.Name), 97 "description": llx.StringData(srv.Description), 98 "installed": llx.BoolData(srv.Installed), 99 "enabled": llx.BoolData(srv.Enabled), 100 "masked": llx.BoolData(srv.Masked), 101 "running": llx.BoolData(srv.Running), 102 "type": llx.StringData(srv.Type), 103 }) 104 if err != nil { 105 return nil, err 106 } 107 108 mqlSrvs = append(mqlSrvs, mqlSrv.(*mqlService)) 109 } 110 111 return mqlSrvs, x.refreshCache(mqlSrvs) 112 } 113 114 func (x *mqlServices) refreshCache(all []interface{}) error { 115 if all == nil { 116 raw := x.GetList() 117 if raw.Error != nil { 118 return raw.Error 119 } 120 all = raw.Data 121 } 122 123 x.namedServices = map[string]*mqlService{} 124 for i := range all { 125 service := all[i].(*mqlService) 126 x.namedServices[service.Name.Data] = service 127 } 128 129 return nil 130 }