@@ -18,6 +18,7 @@ import (
18
18
"net/http"
19
19
_ "net/http/pprof"
20
20
"os"
21
+ "sort"
21
22
"strconv"
22
23
"strings"
23
24
"sync"
@@ -2097,8 +2098,9 @@ func (a *agent) runLiveQuery(query string) (results []map[string]string, status
2097
2098
}
2098
2099
}
2099
2100
2100
- func (a * agent ) processQuery (name , query string ) (
2101
- handled bool , results []map [string ]string , status * fleet.OsqueryStatus , message * string , stats * fleet.Stats ,
2101
+ func (a * agent ) processQuery (name , query string , cachedResults * cachedResults ) (
2102
+ handled bool , results []map [string ]string ,
2103
+ status * fleet.OsqueryStatus , message * string , stats * fleet.Stats ,
2102
2104
) {
2103
2105
const (
2104
2106
hostPolicyQueryPrefix = "fleet_policy_query_"
@@ -2164,6 +2166,33 @@ func (a *agent) processQuery(name, query string) (
2164
2166
}
2165
2167
if ss == fleet .StatusOK {
2166
2168
results = a .softwareMacOS ()
2169
+ cachedResults .software = results
2170
+ }
2171
+ return true , results , & ss , nil , nil
2172
+ case name == hostDetailQueryPrefix + "software_macos_codesign" :
2173
+ // Given queries run in lexicographic order software_macos already run and
2174
+ // cachedResults.software should have its results.
2175
+ ss := fleet .StatusOK
2176
+ if a .softwareQueryFailureProb > 0.0 && rand .Float64 () <= a .softwareQueryFailureProb {
2177
+ ss = fleet .OsqueryStatus (1 )
2178
+ }
2179
+ if ss == fleet .StatusOK {
2180
+ if len (cachedResults .software ) > 0 {
2181
+ for _ , s := range cachedResults .software {
2182
+ if s ["source" ] != "apps" {
2183
+ continue
2184
+ }
2185
+ installedPath := s ["installed_path" ]
2186
+ teamIdentifier := s ["name" ] // use name to be fixed (more realistic than changing often).
2187
+ if len (teamIdentifier ) > 10 {
2188
+ teamIdentifier = teamIdentifier [:10 ]
2189
+ }
2190
+ results = append (results , map [string ]string {
2191
+ "path" : installedPath ,
2192
+ "team_identifier" : teamIdentifier ,
2193
+ })
2194
+ }
2195
+ }
2167
2196
}
2168
2197
return true , results , & ss , nil , nil
2169
2198
case name == hostDetailQueryPrefix + "software_windows" :
@@ -2254,6 +2283,10 @@ func (a *agent) processQuery(name, query string) (
2254
2283
}
2255
2284
}
2256
2285
2286
+ type cachedResults struct {
2287
+ software []map [string ]string
2288
+ }
2289
+
2257
2290
func (a * agent ) DistributedWrite (queries map [string ]string ) error {
2258
2291
r := service.SubmitDistributedQueryResultsRequest {
2259
2292
Results : make (fleet.OsqueryDistributedQueryResults ),
@@ -2262,8 +2295,21 @@ func (a *agent) DistributedWrite(queries map[string]string) error {
2262
2295
Stats : make (map [string ]* fleet.Stats ),
2263
2296
}
2264
2297
r .NodeKey = a .nodeKey
2265
- for name , query := range queries {
2266
- handled , results , status , message , stats := a .processQuery (name , query )
2298
+
2299
+ cachedResults := cachedResults {}
2300
+
2301
+ // Sort queries to be executed by lexicographic name order (for result processing
2302
+ // to be more predictable). This aligns to how osquery executes the queries.
2303
+ queryNames := make ([]string , 0 , len (queries ))
2304
+ for name := range queries {
2305
+ queryNames = append (queryNames , name )
2306
+ }
2307
+ sort .Strings (queryNames )
2308
+
2309
+ for _ , name := range queryNames {
2310
+ query := queries [name ]
2311
+
2312
+ handled , results , status , message , stats := a .processQuery (name , query , & cachedResults )
2267
2313
if ! handled {
2268
2314
// If osquery-perf does not handle the incoming query,
2269
2315
// always return status OK and the default query result.
0 commit comments