go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers/os/resources/services/manager.go (about) 1 // Copyright (c) Mondoo, Inc. 2 // SPDX-License-Identifier: BUSL-1.1 3 4 package services 5 6 import ( 7 "errors" 8 "regexp" 9 10 "go.mondoo.com/cnquery/providers/os/connection/shared" 11 "go.mondoo.com/cnquery/providers/os/detector" 12 ) 13 14 type Service struct { 15 Name string 16 Description string 17 State State 18 Type string 19 Installed bool 20 Running bool 21 Enabled bool 22 Masked bool 23 } 24 25 type State string 26 27 const ( 28 ServiceContinuePending State = "ServiceContinuePending" 29 ServicePausePending State = "ServicePausePending" 30 ServicePaused State = "ServicePaused" 31 ServiceRunning State = "ServiceRunning" 32 ServiceStartPending State = "ServiceStartPending" 33 ServiceStopPending State = "ServiceStopPending" 34 ServiceStopped State = "ServiceStopped" 35 ServiceUnknown State = "ServiceUnknown" 36 ) 37 38 type OSServiceManager interface { 39 Name() string 40 List() ([]*Service, error) 41 } 42 43 var amazonlinux1version = regexp.MustCompile(`^201\d`) 44 45 func ResolveManager(conn shared.Connection) (OSServiceManager, error) { 46 var osm OSServiceManager 47 48 asset := conn.Asset() 49 if asset == nil || asset.Platform == nil { 50 return nil, errors.New("cannot find OS information for package detection") 51 } 52 53 switch { 54 case asset.Platform.IsFamily("arch"): // arch family 55 osm = ResolveSystemdServiceManager(conn) 56 case asset.Platform.Name == "amazonlinux": 57 if amazonlinux1version.MatchString(asset.Platform.Version) { 58 osm = &UpstartServiceManager{SysVServiceManager{conn: conn}} 59 } else { 60 osm = ResolveSystemdServiceManager(conn) 61 } 62 case asset.Platform.Name == "photon": 63 osm = ResolveSystemdServiceManager(conn) 64 // NOTE: we need to check fedora before rhel family, since its also rhel family 65 case asset.Platform.Name == "fedora": 66 rv := detector.ParseOsVersion(asset.Platform.Version) 67 v, err := rv.MajorAtoi() 68 if err != nil { 69 return nil, errors.New("unknown fedora version: " + asset.Platform.Version) 70 } 71 72 if v < 15 { 73 // upstart is only used since fedora 11 but we do not support those older versions 74 osm = &UpstartServiceManager{SysVServiceManager{conn: conn}} 75 } else { 76 osm = ResolveSystemdServiceManager(conn) 77 } 78 case asset.Platform.IsFamily("redhat"): 79 rv := detector.ParseOsVersion(asset.Platform.Version) 80 v, err := rv.MajorAtoi() 81 if err != nil { 82 return nil, errors.New("unknown redhat version: " + asset.Platform.Version) 83 } 84 if v < 7 { 85 osm = &UpstartServiceManager{SysVServiceManager{conn: conn}} 86 } else { 87 osm = ResolveSystemdServiceManager(conn) 88 } 89 case asset.Platform.Name == "ubuntu" || asset.Platform.Name == "linuxmint" || asset.Platform.Name == "pop": 90 rv := detector.ParseOsVersion(asset.Platform.Version) 91 v, err := rv.MajorAtoi() 92 if err != nil { 93 return nil, errors.New("unknown ubuntu version: " + asset.Platform.Version) 94 } 95 96 if v < 15 { 97 osm = &UpstartServiceManager{SysVServiceManager{conn: conn}} 98 } else { 99 osm = ResolveSystemdServiceManager(conn) 100 } 101 case asset.Platform.Name == "debian": 102 rv := detector.ParseOsVersion(asset.Platform.Version) 103 v, err := rv.MajorAtoi() 104 if err != nil { 105 return nil, errors.New("unknown debian version: " + asset.Platform.Version) 106 } 107 108 if v < 7 { 109 osm = &SysVServiceManager{conn: conn} 110 } else { 111 osm = ResolveSystemdServiceManager(conn) 112 } 113 case asset.Platform.Name == "raspbian": 114 osm = ResolveSystemdServiceManager(conn) 115 case asset.Platform.Name == "suse-microos": // it is suse family but uses a different version scheme 116 osm = ResolveSystemdServiceManager(conn) 117 case asset.Platform.IsFamily("suse"): 118 rv := detector.ParseOsVersion(asset.Platform.Version) 119 v, err := rv.MajorAtoi() 120 if err != nil { 121 return nil, errors.New("unknown suse version: " + asset.Platform.Version) 122 } 123 124 // NOTE: opensuse-tumbleweed uses version numbers like 20200622 125 if v < 12 { 126 osm = &SysVServiceManager{conn: conn} 127 } else { 128 osm = ResolveSystemdServiceManager(conn) 129 } 130 case asset.Platform.IsFamily("darwin"): // "macos", "darwin" 131 osm = &LaunchDServiceManager{conn: conn} 132 case asset.Platform.Name == "freebsd" || asset.Platform.Name == "dragonflybsd" || asset.Platform.Name == "netbsd": 133 osm = &BsdInitServiceManager{conn: conn} 134 case asset.Platform.Name == "openbsd": 135 osm = &OpenBsdRcctlServiceManager{conn: conn} 136 case asset.Platform.Name == "windows": 137 osm = &WindowsServiceManager{conn: conn} 138 case asset.Platform.Name == "alpine": 139 osm = &AlpineOpenrcServiceManager{conn: conn} 140 case asset.Platform.Name == "cos": 141 osm = ResolveSystemdServiceManager(conn) 142 case asset.Platform.Name == "aix": 143 osm = &AixServiceManager{conn: conn} 144 case asset.Platform.Name == "kali": // debian based with versions from 2015 onwards being systemd based 145 osm = ResolveSystemdServiceManager(conn) 146 } 147 148 if osm == nil { 149 return nil, errors.New("could not detect suitable service manager for platform: " + asset.Platform.Name) 150 } 151 152 return osm, nil 153 } 154 155 func FindService(services []*Service, name string) (*Service, error) { 156 // search for name 157 for i := range services { 158 service := services[i] 159 if service.Name == name { 160 return service, nil 161 } 162 } 163 164 return nil, errors.New("service> " + name + " does not exist") 165 }