fleet/orbit/pkg/update/disk_encryption.go

57 lines
1.6 KiB
Go
Raw Normal View History

package update
import (
"errors"
"sync/atomic"
"github.com/fleetdm/fleet/v4/orbit/pkg/useraction"
"github.com/fleetdm/fleet/v4/server/fleet"
"github.com/rs/zerolog/log"
)
const maxRetries = 2
type DiskEncryptionRunner struct {
isRunning atomic.Bool
capabilitiesFetcher func() fleet.CapabilityMap
triggerOrbitRestart func(reason string)
}
func ApplyDiskEncryptionRunnerMiddleware(
capabilitiesFetcher func() fleet.CapabilityMap,
triggerOrbitRestart func(reason string),
) fleet.OrbitConfigReceiver {
return &DiskEncryptionRunner{
capabilitiesFetcher: capabilitiesFetcher,
triggerOrbitRestart: triggerOrbitRestart,
}
}
Orbit config receiver (#18518) New interface for adding periodic jobs that rely on notifications/config changes in Orbit. Previously if we wanted to have recurring checks in Orbit, we would add them into a chain of `GetConfig` calls. This call chain would be run periodically by one of the runners registered with the cli application framework. The new method to register `OrbitConfigReceivers` with the `OrbitClient`, and then register the orbit client itself with the application framework. Instead of having giving each fetcher an internal reference to the previous fetcher that it must call, the receiver is registered with the client and the new config is passed to the receiver. This is the old `GetConfig()` interface: ```go type OrbitConfigFetcher interface { GetConfig() (*fleet.OrbitConfig, error) } ``` This is the new `OrbitConfigReceiver` interface: ```go type OrbitConfigReceiver interface { Run(*OrbitConfig) error } ``` To register a new receiver, you call the `RegisterConfigReceiver` method on the client. ```go orbitClient.RegisterConfigReceiver(extRunner) ``` Downsides of the old method: - Spaghetti call chain setup - Cascading failure, of one fails, all after it fail - Run in series, one long function call holds up the rest - Anything that wants to restart orbit is added as a Runner to the application, meaning there could be several timers calling `GetConfig` and running the chain Benefits of the new method: - Clean `RegisterConfigReceiver` api, no call chaining required - Config receivers can be added at runtime - Isolated receivers, one failing call don't effect others - All calls are run in parallel in goroutines, no calls can hold up the rest - No more need for multiple runners, using a context cancel, any receiver can queue a call to restart orbit - Single point to handle errors and logging for all receivers - Panic recovery to stop orbit from crashing - Easier to test, configs are passed in and do not require a call chain This branch contains a little bit of code from the installer method I was working on because I branched it off of that. (oops) Not all code comments surrounding old `GetConfig()` methods have been fully updated yet Possible changes: - Update the interface to take a context, so we can let receivers know to exit early. I can imagine two cases for this: - The application is about to restart - We can set a timeout for how long receivers are allowed to take Closes #12662 --------- Co-authored-by: Martin Angers <martin.n.angers@gmail.com> Co-authored-by: Roberto Dip <dip.jesusr@gmail.com>
2024-05-09 19:22:56 +00:00
func (d *DiskEncryptionRunner) Run(cfg *fleet.OrbitConfig) error {
log.Debug().Msgf("running disk encryption fetcher middleware, notification: %v, isIdle: %v", cfg.Notifications.RotateDiskEncryptionKey, d.isRunning.Load())
if d.capabilitiesFetcher == nil {
return errors.New("disk encryption runner needs a capabilitites fetcher configured")
}
if d.triggerOrbitRestart == nil {
return errors.New("disk encryption runner needs a function to trigger orbit restarts configured")
}
if d.capabilitiesFetcher().Has(fleet.CapabilityEscrowBuddy) {
d.triggerOrbitRestart("server has Escrow Buddy capability but old disk encryption fetcher was running")
return nil
}
if cfg.Notifications.RotateDiskEncryptionKey && !d.isRunning.Swap(true) {
go func() {
defer d.isRunning.Store(false)
if err := useraction.RotateDiskEncryptionKey(maxRetries); err != nil {
log.Error().Err(err).Msg("rotating encryption key")
}
}()
}
Orbit config receiver (#18518) New interface for adding periodic jobs that rely on notifications/config changes in Orbit. Previously if we wanted to have recurring checks in Orbit, we would add them into a chain of `GetConfig` calls. This call chain would be run periodically by one of the runners registered with the cli application framework. The new method to register `OrbitConfigReceivers` with the `OrbitClient`, and then register the orbit client itself with the application framework. Instead of having giving each fetcher an internal reference to the previous fetcher that it must call, the receiver is registered with the client and the new config is passed to the receiver. This is the old `GetConfig()` interface: ```go type OrbitConfigFetcher interface { GetConfig() (*fleet.OrbitConfig, error) } ``` This is the new `OrbitConfigReceiver` interface: ```go type OrbitConfigReceiver interface { Run(*OrbitConfig) error } ``` To register a new receiver, you call the `RegisterConfigReceiver` method on the client. ```go orbitClient.RegisterConfigReceiver(extRunner) ``` Downsides of the old method: - Spaghetti call chain setup - Cascading failure, of one fails, all after it fail - Run in series, one long function call holds up the rest - Anything that wants to restart orbit is added as a Runner to the application, meaning there could be several timers calling `GetConfig` and running the chain Benefits of the new method: - Clean `RegisterConfigReceiver` api, no call chaining required - Config receivers can be added at runtime - Isolated receivers, one failing call don't effect others - All calls are run in parallel in goroutines, no calls can hold up the rest - No more need for multiple runners, using a context cancel, any receiver can queue a call to restart orbit - Single point to handle errors and logging for all receivers - Panic recovery to stop orbit from crashing - Easier to test, configs are passed in and do not require a call chain This branch contains a little bit of code from the installer method I was working on because I branched it off of that. (oops) Not all code comments surrounding old `GetConfig()` methods have been fully updated yet Possible changes: - Update the interface to take a context, so we can let receivers know to exit early. I can imagine two cases for this: - The application is about to restart - We can set a timeout for how long receivers are allowed to take Closes #12662 --------- Co-authored-by: Martin Angers <martin.n.angers@gmail.com> Co-authored-by: Roberto Dip <dip.jesusr@gmail.com>
2024-05-09 19:22:56 +00:00
return nil
}