mirror of
https://github.com/fleetdm/fleet
synced 2026-05-15 21:18:29 +00:00
This reverts commit a5bd50716d which was
this PR: https://github.com/fleetdm/fleet/pull/28742
It was determined that the behavior changes here conflict with other
changes being asked for by `customer-starchik`. Design to review and
come up with a different strategy for improving the behavior this change
originally was intended to fix
- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.
- [x] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)
- For Orbit and Fleet Desktop changes:
- [x] Make sure fleetd is compatible with the latest released version of
Fleet (see [Must
rule](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/workflows/fleetd-development-and-release-strategy.md)).
- [x] Orbit runs on macOS, Linux and Windows. Check if the orbit
feature/bugfix should only apply to one platform (`runtime.GOOS`).
- [x] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- [x] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).
- [x] For unreleased bug fixes in a release candidate, confirmed that
the fix is not expected to adversely impact load test results or alerted
the release DRI if additional load testing is needed.
143 lines
5.3 KiB
Go
143 lines
5.3 KiB
Go
package update
|
|
|
|
import (
|
|
"fmt"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/rs/zerolog/log"
|
|
|
|
"github.com/fleetdm/fleet/v4/server/fleet"
|
|
)
|
|
|
|
// EscrowBuddyRunner sets up [Escrow Buddy][1] to rotate FileVault keys on
|
|
// macOS without user interaction. This runner:
|
|
//
|
|
// - Ensures Escrow Buddy is added as a target for the update runner, so the
|
|
// authorization plugin is downloaded and installed.
|
|
// - Shells out to call `defaults` to configure Escrow Buddy according to
|
|
// server instructions provided via notifications.
|
|
//
|
|
// [1]: https://github.com/macadmins/escrow-buddy
|
|
type EscrowBuddyRunner struct {
|
|
// updateRunner is the wrapped Runner where Escrow Buddy will be set as
|
|
// a target.
|
|
updateRunner *Runner
|
|
// runCmdFunc can be set in tests to mock the command executed to
|
|
// configure Escrow Buddy
|
|
runCmdFunc func(cmd string, args ...string) error
|
|
// runMu guards runs to prevent multiple Run calls happening at the
|
|
// same time.
|
|
runMu sync.Mutex
|
|
// lastRun is used to guarantee that the run interval is enforced
|
|
lastRun time.Time
|
|
// interval defines how often Run is allowed to perform work
|
|
interval time.Duration
|
|
}
|
|
|
|
// NewEscrowBuddyRunner returns a new instance configured with the provided values
|
|
func NewEscrowBuddyRunner(runner *Runner, interval time.Duration) fleet.OrbitConfigReceiver {
|
|
return &EscrowBuddyRunner{updateRunner: runner, interval: interval}
|
|
}
|
|
|
|
func (e *EscrowBuddyRunner) Run(cfg *fleet.OrbitConfig) error {
|
|
log.Debug().Msgf("EscrowBuddyRunner: notification: %t", cfg.Notifications.RotateDiskEncryptionKey)
|
|
|
|
if e.updateRunner == nil {
|
|
log.Info().Msg("EscrowBuddyRunner: received nil UpdateRunner, this probably indicates that updates are turned off. Skipping any actions related to Disk encryption")
|
|
return nil
|
|
}
|
|
|
|
if !e.runMu.TryLock() {
|
|
log.Debug().Msg("EscrowBuddyRunner: a previous instance is currently running, returning early")
|
|
return nil
|
|
}
|
|
|
|
defer e.runMu.Unlock()
|
|
if time.Since(e.lastRun) < e.interval {
|
|
log.Debug().Msgf("EscrowBuddyRunner: last run (%v) is less than the configured interval (%v), returning early", e.lastRun, e.interval)
|
|
return nil
|
|
}
|
|
|
|
if cfg.Notifications.RunSetupExperience {
|
|
log.Debug().Msg("EscrowBuddyRunner: skipping any actions related to disk encryption, setup experience is running")
|
|
return nil
|
|
}
|
|
|
|
updaterHasTarget := e.updateRunner.HasRunnerOptTarget("escrowBuddy")
|
|
// if the notification is false, it could mean that we shouldn't do
|
|
// anything at all (eg: MDM is not configured) or that this host
|
|
// doesn't need to rotate the key.
|
|
//
|
|
// if Escrow Buddy is a TUF target, it means that we tried to rotate
|
|
// the key before, and we must disable it to keep the local state as
|
|
// instructed by the server.
|
|
if !cfg.Notifications.RotateDiskEncryptionKey {
|
|
if updaterHasTarget {
|
|
log.Debug().Msg("EscrowBuddyRunner: disabling disk encryption rotation")
|
|
e.lastRun = time.Now()
|
|
return e.setGenerateNewKeyTo(false)
|
|
}
|
|
|
|
log.Debug().Msg("EscrowBuddyRunner: skipping any actions related to disk encryption")
|
|
return nil
|
|
}
|
|
|
|
runnerHasLocalHash := e.updateRunner.HasLocalHash("escrowBuddy")
|
|
if !updaterHasTarget || !runnerHasLocalHash {
|
|
log.Info().Msg("refreshing the update runner config with Escrow Buddy targets and hashes")
|
|
log.Debug().Msgf("updater has target: %t, runner has local hash: %t", updaterHasTarget, runnerHasLocalHash)
|
|
if err := e.setTargetsAndHashes(); err != nil {
|
|
return fmt.Errorf("setting Escrow Buddy targets and hashes: %w", err)
|
|
}
|
|
}
|
|
|
|
// Some macOS updates and upgrades reset the authorization database to its default state
|
|
// which will deactivate Escrow Buddy and prevent FileVault key generation upon next login.
|
|
log.Debug().Msg("EscrowBuddyRunner: re-enable Escrow Buddy in the authorization database")
|
|
if err := e.setAuthDBSetup(); err != nil {
|
|
return fmt.Errorf("failed to re-enable Escrow Buddy in the authorization database, err: %w", err)
|
|
}
|
|
|
|
log.Debug().Msg("EscrowBuddyRunner: enabling disk encryption rotation")
|
|
if err := e.setGenerateNewKeyTo(true); err != nil {
|
|
return fmt.Errorf("enabling disk encryption rotation: %w", err)
|
|
}
|
|
|
|
e.lastRun = time.Now()
|
|
return nil
|
|
}
|
|
|
|
func (e *EscrowBuddyRunner) setTargetsAndHashes() error {
|
|
e.updateRunner.AddRunnerOptTarget("escrowBuddy")
|
|
e.updateRunner.updater.SetTargetInfo("escrowBuddy", EscrowBuddyMacOSTarget)
|
|
// we don't want to keep escrowBuddy as a target if we failed to update the
|
|
// cached hashes in the runner.
|
|
if err := e.updateRunner.StoreLocalHash("escrowBuddy"); err != nil {
|
|
log.Debug().Msgf("removing escrowBuddy from target options, error updating local hashes: %s", err)
|
|
e.updateRunner.RemoveRunnerOptTarget("escrowBuddy")
|
|
e.updateRunner.updater.RemoveTargetInfo("escrowBuddy")
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (e *EscrowBuddyRunner) setGenerateNewKeyTo(enabled bool) error {
|
|
log.Debug().Msgf("running defaults write to configure Escrow Buddy with value %t", enabled)
|
|
cmd := fmt.Sprintf("defaults write /Library/Preferences/com.netflix.Escrow-Buddy.plist GenerateNewKey -bool %t", enabled)
|
|
fn := e.runCmdFunc
|
|
if fn == nil {
|
|
fn = runCmdCollectErr
|
|
}
|
|
return fn("sh", "-c", cmd)
|
|
}
|
|
|
|
func (e *EscrowBuddyRunner) setAuthDBSetup() error {
|
|
log.Debug().Msg("ready to re-enable Escrow Buddy in the authorization database")
|
|
cmd := "/Library/Security/SecurityAgentPlugins/Escrow\\ Buddy.bundle/Contents/Resources/AuthDBSetup.sh"
|
|
fn := e.runCmdFunc
|
|
if fn == nil {
|
|
fn = runCmdCollectErr
|
|
}
|
|
return fn("sh", "-c", cmd)
|
|
}
|