Update osquery-perf with DDM functionality (#18273)

This commit is contained in:
Sarah Gillespie 2024-04-15 15:56:25 -05:00 committed by GitHub
parent 8b9099717d
commit 9897649696
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 210 additions and 20 deletions

View file

@ -29,6 +29,7 @@ import (
"github.com/fleetdm/fleet/v4/server/fleet"
apple_mdm "github.com/fleetdm/fleet/v4/server/mdm/apple"
"github.com/fleetdm/fleet/v4/server/mdm/microsoft/syncml"
"github.com/fleetdm/fleet/v4/server/mdm/nanomdm/mdm"
"github.com/fleetdm/fleet/v4/server/ptr"
"github.com/fleetdm/fleet/v4/server/service"
"github.com/google/uuid"
@ -135,25 +136,33 @@ func init() {
}
type Stats struct {
startTime time.Time
errors int
osqueryEnrollments int
orbitEnrollments int
mdmEnrollments int
mdmSessions int
distributedWrites int
mdmCommandsReceived int
distributedReads int
configRequests int
configErrors int
resultLogRequests int
orbitErrors int
mdmErrors int
desktopErrors int
distributedReadErrors int
distributedWriteErrors int
resultLogErrors int
bufferedLogs int
startTime time.Time
errors int
osqueryEnrollments int
orbitEnrollments int
mdmEnrollments int
mdmSessions int
distributedWrites int
mdmCommandsReceived int
distributedReads int
configRequests int
configErrors int
resultLogRequests int
orbitErrors int
mdmErrors int
ddmDeclarationItemsErrors int
ddmConfigurationErrors int
ddmActivationErrors int
ddmStatusErrors int
ddmDeclarationItemsSuccess int
ddmConfigurationSuccess int
ddmActivationSuccess int
ddmStatusSuccess int
desktopErrors int
distributedReadErrors int
distributedWriteErrors int
resultLogErrors int
bufferedLogs int
l sync.Mutex
}
@ -236,6 +245,54 @@ func (s *Stats) IncrementMDMErrors() {
s.mdmErrors++
}
func (s *Stats) IncrementDDMDeclarationItemsErrors() {
s.l.Lock()
defer s.l.Unlock()
s.ddmDeclarationItemsErrors++
}
func (s *Stats) IncrementDDMConfigurationErrors() {
s.l.Lock()
defer s.l.Unlock()
s.ddmConfigurationErrors++
}
func (s *Stats) IncrementDDMActivationErrors() {
s.l.Lock()
defer s.l.Unlock()
s.ddmActivationErrors++
}
func (s *Stats) IncrementDDMStatusErrors() {
s.l.Lock()
defer s.l.Unlock()
s.ddmStatusErrors++
}
func (s *Stats) IncrementDDMDeclarationItemsSuccess() {
s.l.Lock()
defer s.l.Unlock()
s.ddmDeclarationItemsSuccess++
}
func (s *Stats) IncrementDDMConfigurationSuccess() {
s.l.Lock()
defer s.l.Unlock()
s.ddmConfigurationSuccess++
}
func (s *Stats) IncrementDDMActivationSuccess() {
s.l.Lock()
defer s.l.Unlock()
s.ddmActivationSuccess++
}
func (s *Stats) IncrementDDMStatusSuccess() {
s.l.Lock()
defer s.l.Unlock()
s.ddmStatusSuccess++
}
func (s *Stats) IncrementDesktopErrors() {
s.l.Lock()
defer s.l.Unlock()
@ -274,7 +331,7 @@ func (s *Stats) Log() {
defer s.l.Unlock()
log.Printf(
"uptime: %s, error rate: %.2f, osquery enrolls: %d, orbit enrolls: %d, mdm enrolls: %d, distributed/reads: %d, distributed/writes: %d, config requests: %d, result log requests: %d, mdm sessions initiated: %d, mdm commands received: %d, config errors: %d, distributed/read errors: %d, distributed/write errors: %d, log result errors: %d, orbit errors: %d, desktop errors: %d, mdm errors: %d, buffered logs: %d",
"uptime: %s, error rate: %.2f, osquery enrolls: %d, orbit enrolls: %d, mdm enrolls: %d, distributed/reads: %d, distributed/writes: %d, config requests: %d, result log requests: %d, mdm sessions initiated: %d, mdm commands received: %d, config errors: %d, distributed/read errors: %d, distributed/write errors: %d, log result errors: %d, orbit errors: %d, desktop errors: %d, mdm errors: %d, ddm declaration items success: %d, ddm declaration items errors: %d, ddm activation success: %d, ddm activation errors: %d, ddm configuration success: %d, ddm configuration errors: %d, ddm status success: %d, ddm status errors: %d, buffered logs: %d",
time.Since(s.startTime).Round(time.Second),
float64(s.errors)/float64(s.osqueryEnrollments),
s.osqueryEnrollments,
@ -293,6 +350,14 @@ func (s *Stats) Log() {
s.orbitErrors,
s.desktopErrors,
s.mdmErrors,
s.ddmDeclarationItemsSuccess,
s.ddmDeclarationItemsErrors,
s.ddmActivationSuccess,
s.ddmActivationErrors,
s.ddmConfigurationSuccess,
s.ddmConfigurationErrors,
s.ddmStatusSuccess,
s.ddmStatusErrors,
s.bufferedLogs,
)
}
@ -943,10 +1008,115 @@ func (a *agent) runMacosMDMLoop() {
a.stats.IncrementMDMErrors()
break INNER_FOR_LOOP
}
if mdmCommandPayload != nil && mdmCommandPayload.Command.RequestType == "DeclarativeManagement" {
a.doDeclarativeManagement(mdmCommandPayload)
}
}
}
}
func (a *agent) doDeclarativeManagement(cmd *mdm.Command) {
// defer log.Printf("Exiting DeclarativeManagement for command %s", cmd.CommandUUID)
// get declaration-items endpoint
r, err := a.macMDMClient.DeclarativeManagement("declaration-items")
if err != nil {
log.Printf("DDM %s declaration-items request failed: %s", cmd.CommandUUID, err)
a.stats.IncrementDDMDeclarationItemsErrors()
return
}
body, err := io.ReadAll(r.Body)
if err != nil {
log.Printf("DDM %s declaration-items read body failed: %s", cmd.CommandUUID, err)
a.stats.IncrementDDMDeclarationItemsErrors()
return
}
var items fleet.MDMAppleDDMDeclarationItemsResponse
err = json.Unmarshal(body, &items)
if err != nil {
log.Printf("DDM %s declaration-items unmarshal failed: %s", cmd.CommandUUID, err)
a.stats.IncrementDDMDeclarationItemsErrors()
return
}
a.stats.IncrementDDMDeclarationItemsSuccess()
// get declaration/configuration/:identifer endpoint
for _, d := range items.Declarations.Configurations {
path := fmt.Sprintf("declaration/%s/%s", "configuration", d.Identifier)
r, err := a.macMDMClient.DeclarativeManagement(path)
if err != nil {
log.Printf("DDM %s request failed: %s", path, err)
a.stats.IncrementDDMConfigurationErrors()
return
}
body, err := io.ReadAll(r.Body)
if err != nil {
log.Printf("DDM %s read body failed: %s", path, err)
a.stats.IncrementDDMConfigurationErrors()
return
}
var decl fleet.MDMAppleDeclaration
err = json.Unmarshal(body, &decl)
if err != nil {
log.Printf("DDM %s unmarshal failed: %s", path, err)
a.stats.IncrementDDMConfigurationErrors()
return
}
}
a.stats.IncrementDDMConfigurationSuccess()
// get declaration/activation/:identifer endpoint
for _, d := range items.Declarations.Activations {
path := fmt.Sprintf("declaration/%s/%s", "activation", d.Identifier)
r, err := a.macMDMClient.DeclarativeManagement(path)
if err != nil {
log.Printf("DDM %s request failed: %s", path, err)
a.stats.IncrementDDMActivationErrors()
return
}
body, err := io.ReadAll(r.Body)
if err != nil {
log.Printf("DDM %s read body failed: %s", path, err)
a.stats.IncrementDDMActivationErrors()
return
}
var act fleet.MDMAppleDDMActivation
err = json.Unmarshal(body, &act)
if err != nil {
log.Printf("DDM %s unmarshal failed: %s", path, err)
a.stats.IncrementDDMActivationErrors()
return
}
}
a.stats.IncrementDDMActivationSuccess()
// sent status report
for _, d := range items.Declarations.Configurations {
report := fleet.MDMAppleDDMStatusReport{}
report.StatusItems.Management.Declarations.Configurations = []fleet.MDMAppleDDMStatusDeclaration{
{Active: true, Valid: fleet.MDMAppleDeclarationValid, Identifier: d.Identifier, ServerToken: d.ServerToken},
}
r, err := a.macMDMClient.DeclarativeManagement("status", report)
if err != nil {
log.Printf("DDM %s status request failed: %s", d.Identifier, err)
a.stats.IncrementDDMStatusErrors()
return
}
// Apple's documentation has some conflicting information about the expected status here so we'll
// just check for both.
//
// https://developer.apple.com/documentation/devicemanagement/get_the_device_status#response-codes
// https://developer.apple.com/documentation/devicemanagement/statusreport#discussion
if r.StatusCode != http.StatusOK && r.StatusCode != http.StatusNoContent {
log.Printf("DDM %s status response unexpected: %d", d.Identifier, r.StatusCode)
a.stats.IncrementDDMStatusErrors()
return
}
}
a.stats.IncrementDDMStatusSuccess()
}
func (a *agent) runWindowsMDMLoop() {
mdmCheckInTicker := time.Tick(a.MDMCheckInInterval)

View file

@ -819,3 +819,23 @@ type MDMAppleDDMStatusErrorReason struct {
// error.
Details map[string]any `json:"Details"`
}
// MDMAppleDDMActivationPayload represents the payload of an activation declaration.
//
// https://developer.apple.com/documentation/devicemanagement/activationsimple
type MDMAppleDDMActivationPayload struct {
Predicate string `json:"Predicate"`
StandardConfigurations []string `json:"StandardConfigurations"`
}
// MDMAppleDDMActivation represents the declaration of an activation. It combines the base
// declaation with the activation payload.
//
// https://developer.apple.com/documentation/devicemanagement/declarationbase
// https://developer.apple.com/documentation/devicemanagement/activationsimple
type MDMAppleDDMActivation struct {
Identifier string `json:"Identifier"`
Payload MDMAppleDDMActivationPayload `json:"Payload"`
ServerToken string `json:"ServerToken"`
Type string `json:"Type"` // "com.apple.activation.simple"
}