From f2e38a62bcc80912536f1e1b5cde43d2f681f239 Mon Sep 17 00:00:00 2001 From: zackattack01 Date: Wed, 17 Jul 2024 17:14:47 -0400 Subject: [PATCH] testing with simulated update now actor invocation --- cmd/launcher/launcher.go | 27 +++++++++++++++++++++++++++ ee/tuf/autoupdate.go | 23 ++++++++++++----------- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/cmd/launcher/launcher.go b/cmd/launcher/launcher.go index ca4a3bdfb..4a7fb6b66 100644 --- a/cmd/launcher/launcher.go +++ b/cmd/launcher/launcher.go @@ -540,6 +540,33 @@ func runLauncher(ctx context.Context, cancel func(), multiSlogger, systemMultiSl if actionsQueue != nil { actionsQueue.RegisterActor(tuf.AutoupdateSubsystemName, tufAutoupdater) } + + // in some cases, (e.g. rolling back a windows installation to a previous osquery version) it is possible that + // the installer leaves us in a situation where there is no osqueryd on disk. + // we can detect this and attempt to download the correct version into the TUF update library to run from that. + // This must be done as a blocking operation before the rungroups start, because the osquery runner will fail to + // launch and trigger a restart immediately + currentOsquerydBinaryPath := k.LatestOsquerydPath(ctx) + if _, err = os.Stat(currentOsquerydBinaryPath); os.IsNotExist(err) { + slogger.Log(ctx, slog.LevelInfo, + "detected missing osqueryd executable, will attempt to download", + ) + + // simulate control server request for immediate update, noting to bypass the initial delay window + actionReader := strings.NewReader(`{ + "bypass_initial_delay": true, + "binaries_to_update": [ + { "name": "osqueryd" } + ] + }`) + + if err = tufAutoupdater.Do(actionReader); err != nil { + slogger.Log(ctx, slog.LevelError, + "failure triggering immediate osquery update", + "err", err, + ) + } + } } startupSpan.End() diff --git a/ee/tuf/autoupdate.go b/ee/tuf/autoupdate.go index 4b78226c8..5fbbf0e48 100644 --- a/ee/tuf/autoupdate.go +++ b/ee/tuf/autoupdate.go @@ -62,7 +62,8 @@ const AutoupdateSubsystemName = "autoupdate" type ( controlServerAutoupdateRequest struct { - BinariesToUpdate []binaryToUpdate `json:"binaries_to_update"` + BinariesToUpdate []binaryToUpdate `json:"binaries_to_update"` + BypassInitialDelay bool `json:"bypass_initial_delay,omitempty"` } // In the future, we may allow for setting a particular version here as well @@ -278,16 +279,6 @@ func (ta *TufAutoupdater) Interrupt(_ error) { // Do satisfies the actionqueue.actor interface; it allows the control server to send // requests down to autoupdate immediately. func (ta *TufAutoupdater) Do(data io.Reader) error { - if time.Now().Before(ta.initialDelayEnd) { - ta.slogger.Log(context.TODO(), slog.LevelWarn, - "received update request during initial delay, discarding", - "initial_delay_end", ta.initialDelayEnd.UTC().Format(time.RFC3339), - ) - // We don't return an error because there's no need for the actionqueue to retry this request -- - // we're going to perform an autoupdate check as soon as we exit the delay anyway. - return nil - } - var updateRequest controlServerAutoupdateRequest if err := json.NewDecoder(data).Decode(&updateRequest); err != nil { ta.slogger.Log(context.TODO(), slog.LevelWarn, @@ -298,6 +289,16 @@ func (ta *TufAutoupdater) Do(data io.Reader) error { return nil } + if time.Now().Before(ta.initialDelayEnd) && !updateRequest.BypassInitialDelay { + ta.slogger.Log(context.TODO(), slog.LevelWarn, + "received update request during initial delay, discarding", + "initial_delay_end", ta.initialDelayEnd.UTC().Format(time.RFC3339), + ) + // We don't return an error because there's no need for the actionqueue to retry this request -- + // we're going to perform an autoupdate check as soon as we exit the delay anyway. + return nil + } + binariesToUpdate := make([]autoupdatableBinary, 0) for _, b := range updateRequest.BinariesToUpdate { if val, ok := autoupdatableBinaryMap[b.Name]; ok {