This commit is contained in:
Daniel
2024-11-12 13:30:47 +01:00
parent ddf7ba170e
commit 8b1bdc7eb1
9 changed files with 70 additions and 50 deletions

View File

@@ -10,6 +10,8 @@ import (
"sync" "sync"
) )
// FIXME: version does not show in portmaster
var ( var (
name string name string
license string license string

View File

@@ -24,6 +24,7 @@ import (
func init() { func init() {
// flag.BoolVar(&updates.RebootOnRestart, "reboot-on-restart", false, "reboot server on auto-upgrade") // flag.BoolVar(&updates.RebootOnRestart, "reboot-on-restart", false, "reboot server on auto-upgrade")
// FIXME
} }
var sigUSR1 = syscall.Signal(0xa) var sigUSR1 = syscall.Signal(0xa)
@@ -48,6 +49,8 @@ func main() {
log.SetLogLevel(log.WarningLevel) log.SetLogLevel(log.WarningLevel)
_ = log.Start() _ = log.Start()
// FIXME: Use service?
// Create instance. // Create instance.
var execCmdLine bool var execCmdLine bool
instance, err := spn.New() instance, err := spn.New()
@@ -109,7 +112,7 @@ func main() {
slog.Warn("program was interrupted, stopping") slog.Warn("program was interrupted, stopping")
} }
case <-instance.Stopped(): case <-instance.ShutdownComplete():
log.Shutdown() log.Shutdown()
os.Exit(instance.ExitCode()) os.Exit(instance.ExitCode())
} }

View File

@@ -78,6 +78,8 @@ func main() {
} }
instance.AddModule(observer) instance.AddModule(observer)
// FIXME: Use service?
// Execute command line operation, if requested or available. // Execute command line operation, if requested or available.
switch { switch {
case !execCmdLine: case !execCmdLine:
@@ -126,7 +128,7 @@ func main() {
slog.Warn("program was interrupted, stopping") slog.Warn("program was interrupted, stopping")
} }
case <-instance.Stopped(): case <-instance.ShuttingDown():
log.Shutdown() log.Shutdown()
os.Exit(instance.ExitCode()) os.Exit(instance.ExitCode())
} }

View File

@@ -58,7 +58,7 @@ func initializeGlobals(cmd *cobra.Command, args []string) {
svcCfg = &service.ServiceConfig{ svcCfg = &service.ServiceConfig{
BinDir: binDir, BinDir: binDir,
DataDir: dataDir, DataDir: dataDir,
BinariesIndexURLs: service.DefaultBinaryIndexURLs, BinariesIndexURLs: service.DefaultStableBinaryIndexURLs,
IntelIndexURLs: service.DefaultIntelIndexURLs, IntelIndexURLs: service.DefaultIntelIndexURLs,
VerifyBinaryUpdates: service.BinarySigningTrustStore, VerifyBinaryUpdates: service.BinarySigningTrustStore,
VerifyIntelUpdates: service.BinarySigningTrustStore, VerifyIntelUpdates: service.BinarySigningTrustStore,

View File

@@ -60,7 +60,8 @@ func (sc *ServiceConfig) Init() error {
// Apply defaults for required fields. // Apply defaults for required fields.
if len(sc.BinariesIndexURLs) == 0 { if len(sc.BinariesIndexURLs) == 0 {
sc.BinariesIndexURLs = DefaultBinaryIndexURLs // FIXME: Select based on setting.
sc.BinariesIndexURLs = DefaultStableBinaryIndexURLs
} }
if len(sc.IntelIndexURLs) == 0 { if len(sc.IntelIndexURLs) == 0 {
sc.IntelIndexURLs = DefaultIntelIndexURLs sc.IntelIndexURLs = DefaultIntelIndexURLs

View File

@@ -256,7 +256,7 @@ func loadProcess(ctx context.Context, key string, pInfo *processInfo.Process) (*
// Username // Username
process.UserName, err = pInfo.UsernameWithContext(ctx) process.UserName, err = pInfo.UsernameWithContext(ctx)
if err != nil { if err != nil {
return nil, fmt.Errorf("process: failed to get Username for p%d: %w", pInfo.Pid, err) log.Tracer(ctx).Warningf("process: failed to get username (PID %d): %s", pInfo.Pid, err)
} }
// TODO: User Home // TODO: User Home

View File

@@ -9,9 +9,19 @@ import (
) )
var ( var (
DefaultBinaryIndexURLs = []string{ DefaultStableBinaryIndexURLs = []string{
"https://updates.safing.io/stable.v3.json", "https://updates.safing.io/stable.v3.json",
} }
DefaultBetaBinaryIndexURLs = []string{
"https://updates.safing.io/beta.v3.json",
}
DefaultStagingBinaryIndexURLs = []string{
"https://updates.safing.io/staging.v3.json",
}
DefaultSupportBinaryIndexURLs = []string{
"https://updates.safing.io/support.v3.json",
}
DefaultIntelIndexURLs = []string{ DefaultIntelIndexURLs = []string{
"https://updates.safing.io/intel.v3.json", "https://updates.safing.io/intel.v3.json",
} }
@@ -53,6 +63,7 @@ func MakeUpdateConfigs(svcCfg *ServiceConfig) (binaryUpdateConfig, intelUpdateCo
IndexURLs: svcCfg.BinariesIndexURLs, IndexURLs: svcCfg.BinariesIndexURLs,
IndexFile: "index.json", IndexFile: "index.json",
Verify: svcCfg.VerifyBinaryUpdates, Verify: svcCfg.VerifyBinaryUpdates,
AutoCheck: true, // FIXME: Get from setting.
AutoDownload: false, AutoDownload: false,
AutoApply: false, AutoApply: false,
NeedsRestart: true, NeedsRestart: true,
@@ -66,6 +77,7 @@ func MakeUpdateConfigs(svcCfg *ServiceConfig) (binaryUpdateConfig, intelUpdateCo
IndexURLs: svcCfg.IntelIndexURLs, IndexURLs: svcCfg.IntelIndexURLs,
IndexFile: "index.json", IndexFile: "index.json",
Verify: svcCfg.VerifyIntelUpdates, Verify: svcCfg.VerifyIntelUpdates,
AutoCheck: true, // FIXME: Get from setting.
AutoDownload: true, AutoDownload: true,
AutoApply: true, AutoApply: true,
NeedsRestart: false, NeedsRestart: false,
@@ -82,6 +94,7 @@ func MakeUpdateConfigs(svcCfg *ServiceConfig) (binaryUpdateConfig, intelUpdateCo
IndexURLs: svcCfg.BinariesIndexURLs, IndexURLs: svcCfg.BinariesIndexURLs,
IndexFile: "index.json", IndexFile: "index.json",
Verify: svcCfg.VerifyBinaryUpdates, Verify: svcCfg.VerifyBinaryUpdates,
AutoCheck: true, // FIXME: Get from setting.
AutoDownload: false, AutoDownload: false,
AutoApply: false, AutoApply: false,
NeedsRestart: true, NeedsRestart: true,
@@ -95,6 +108,7 @@ func MakeUpdateConfigs(svcCfg *ServiceConfig) (binaryUpdateConfig, intelUpdateCo
IndexURLs: svcCfg.IntelIndexURLs, IndexURLs: svcCfg.IntelIndexURLs,
IndexFile: "index.json", IndexFile: "index.json",
Verify: svcCfg.VerifyIntelUpdates, Verify: svcCfg.VerifyIntelUpdates,
AutoCheck: true, // FIXME: Get from setting.
AutoDownload: true, AutoDownload: true,
AutoApply: true, AutoApply: true,
NeedsRestart: false, NeedsRestart: false,

View File

@@ -41,6 +41,7 @@ var (
ErrNotFound = errors.New("file not found") ErrNotFound = errors.New("file not found")
ErrSameIndex = errors.New("same index") ErrSameIndex = errors.New("same index")
ErrAutoCheckDisabled = errors.New("automatic update checks are disabled")
ErrNoUpdateAvailable = errors.New("no update available") ErrNoUpdateAvailable = errors.New("no update available")
ErrActionRequired = errors.New("action required") ErrActionRequired = errors.New("action required")
) )
@@ -67,6 +68,8 @@ type Config struct {
// Verify enables and specifies the trust the index signatures will be checked against. // Verify enables and specifies the trust the index signatures will be checked against.
Verify jess.TrustStore Verify jess.TrustStore
// AutoCheck defines that new indexes may be downloaded automatically without outside trigger.
AutoCheck bool
// AutoDownload defines that updates may be downloaded automatically without outside trigger. // AutoDownload defines that updates may be downloaded automatically without outside trigger.
AutoDownload bool AutoDownload bool
// AutoApply defines that updates may be automatically applied without outside trigger. // AutoApply defines that updates may be automatically applied without outside trigger.
@@ -157,8 +160,7 @@ func New(instance instance, name string, cfg Config) (*Updater, error) {
} }
// Create Workers. // Create Workers.
module.updateCheckWorkerMgr = m.NewWorkerMgr("update checker", module.updateCheckWorker, nil). module.updateCheckWorkerMgr = m.NewWorkerMgr("update checker", module.updateCheckWorker, nil)
Repeat(updateTaskRepeatDuration)
module.upgradeWorkerMgr = m.NewWorkerMgr("upgrader", module.upgradeWorker, nil) module.upgradeWorkerMgr = m.NewWorkerMgr("upgrader", module.upgradeWorker, nil)
// Load index. // Load index.
@@ -207,12 +209,13 @@ func (u *Updater) updateAndUpgrade(w *mgr.WorkerCtx, indexURLs []string, ignoreV
} }
} }
// Get index to check version.
u.indexLock.Lock()
index := u.index
u.indexLock.Unlock()
// Check if there is a new version. // Check if there is a new version.
if !ignoreVersion { if !ignoreVersion && index != nil {
// Get index to check version.
u.indexLock.Lock()
index := u.index
u.indexLock.Unlock()
// Check with local pointer to index. // Check with local pointer to index.
if err := index.ShouldUpgradeTo(downloader.index); err != nil { if err := index.ShouldUpgradeTo(downloader.index); err != nil {
if errors.Is(err, ErrSameIndex) { if errors.Is(err, ErrSameIndex) {
@@ -351,44 +354,31 @@ func (u *Updater) updateAndUpgrade(w *mgr.WorkerCtx, indexURLs []string, ignoreV
} }
// Notify user that a restart is required. // Notify user that a restart is required.
if u.cfg.Notify && u.instance.Notifications() != nil { if u.cfg.Notify {
if u.instance.Notifications() != nil {
u.instance.Notifications().Notify(&notifications.Notification{ u.instance.Notifications().Notify(&notifications.Notification{
EventID: restartRequiredNotificationID, EventID: restartRequiredNotificationID,
Type: notifications.Info, Type: notifications.Info,
Title: "Restart Required", Title: "Restart Required",
Message: "Portmaster v" + downloader.index.Version + " is installed. Restart to use new version.", Message: "Portmaster v" + downloader.index.Version + " is installed. Restart to use new version.",
AvailableActions: []*notifications.Action{ AvailableActions: []*notifications.Action{
{ {
ID: "ack", ID: "ack",
Text: "Later", Text: "Later",
}, },
{ {
ID: "restart", ID: "restart",
Text: "Restart Now", Text: "Restart Now",
Type: notifications.ActionTypeWebhook, Type: notifications.ActionTypeWebhook,
Payload: notifications.ActionTypeWebhookPayload{ Payload: notifications.ActionTypeWebhookPayload{
Method: "POST", Method: "POST",
URL: "updates/apply", URL: "updates/apply",
},
}, },
}, },
}, })
}) }
u.instance.Notifications().NotifyInfo(
updateAvailableNotificationID,
"Restart Required",
"Portmaster v"+downloader.index.Version+" is installed. Restart to use new version.",
notifications.Action{
ID: "restart",
Text: "Restart Now",
Type: notifications.ActionTypeWebhook,
Payload: notifications.ActionTypeWebhookPayload{
Method: "POST",
URL: "core/restart",
},
},
)
return fmt.Errorf("%w: restart required", ErrActionRequired) return fmt.Errorf("%w: restart required", ErrActionRequired)
} }
@@ -470,6 +460,7 @@ func (u *Updater) Manager() *mgr.Manager {
// Start starts the module. // Start starts the module.
func (u *Updater) Start() error { func (u *Updater) Start() error {
if u.corruptedInstallation && u.cfg.Notify && u.instance.Notifications() != nil { if u.corruptedInstallation && u.cfg.Notify && u.instance.Notifications() != nil {
// FIXME: this might make sense as a module state
u.instance.Notifications().NotifyError( u.instance.Notifications().NotifyError(
corruptInstallationNotificationID, corruptInstallationNotificationID,
"Install Corruption", "Install Corruption",
@@ -477,7 +468,12 @@ func (u *Updater) Start() error {
) )
} }
u.updateCheckWorkerMgr.Delay(15 * time.Second) // Check for updates automatically, if enabled.
if u.cfg.AutoCheck {
u.updateCheckWorkerMgr.
Repeat(updateTaskRepeatDuration).
Delay(15 * time.Second)
}
return nil return nil
} }

View File

@@ -12,6 +12,8 @@ import (
"github.com/safing/portmaster/base/log" "github.com/safing/portmaster/base/log"
) )
// FIXME: previous update system did in-place service file upgrades. Check if this is still necessary and if changes are in current installers.
const ( const (
defaultFileMode = os.FileMode(0o0644) defaultFileMode = os.FileMode(0o0644)
executableFileMode = os.FileMode(0o0744) executableFileMode = os.FileMode(0o0744)
@@ -25,7 +27,7 @@ func (u *Updater) upgrade(downloader *Downloader, ignoreVersion bool) error {
defer u.indexLock.Unlock() defer u.indexLock.Unlock()
// Check if we should upgrade at all. // Check if we should upgrade at all.
if !ignoreVersion { if !ignoreVersion && u.index != nil {
if err := u.index.ShouldUpgradeTo(downloader.index); err != nil { if err := u.index.ShouldUpgradeTo(downloader.index); err != nil {
return fmt.Errorf("cannot upgrade: %w", ErrNoUpdateAvailable) return fmt.Errorf("cannot upgrade: %w", ErrNoUpdateAvailable)
} }