mirror of
https://github.com/safing/portmaster
synced 2025-09-01 18:19:12 +00:00
Improve status module
This commit is contained in:
parent
e8b5cedc9d
commit
321f3feec5
13 changed files with 342 additions and 107 deletions
|
@ -135,7 +135,7 @@ func EnsureProfile(r record.Record) (*Profile, error) {
|
|||
// or adjust type
|
||||
new, ok := r.(*Profile)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("record not of type *Example, but %T", r)
|
||||
return nil, fmt.Errorf("record not of type *Profile, but %T", r)
|
||||
}
|
||||
return new, nil
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ func updateListener(sub *database.Subscription) {
|
|||
|
||||
profile, err := EnsureProfile(r)
|
||||
if err != nil {
|
||||
log.Errorf("profile: received update for special profile, but could not read: %s", err)
|
||||
log.Errorf("profile: received update for profile, but could not read: %s", err)
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
47
status/database.go
Normal file
47
status/database.go
Normal file
|
@ -0,0 +1,47 @@
|
|||
package status
|
||||
|
||||
import (
|
||||
"github.com/Safing/portbase/database"
|
||||
"github.com/Safing/portbase/database/query"
|
||||
"github.com/Safing/portbase/database/record"
|
||||
)
|
||||
|
||||
const (
|
||||
statusDBKey = "core:status/status"
|
||||
)
|
||||
|
||||
var (
|
||||
statusDB = database.NewInterface(nil)
|
||||
hook *database.RegisteredHook
|
||||
)
|
||||
|
||||
type statusHook struct {
|
||||
database.HookBase
|
||||
}
|
||||
|
||||
// UsesPrePut implements the Hook interface.
|
||||
func (sh *statusHook) UsesPrePut() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// PrePut implements the Hook interface.
|
||||
func (sh *statusHook) PrePut(r record.Record) (record.Record, error) {
|
||||
newStatus, err := EnsureSystemStatus(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newStatus.Lock()
|
||||
defer newStatus.Unlock()
|
||||
|
||||
// apply applicable settings
|
||||
setSelectedSecurityLevel(newStatus.SelectedSecurityLevel)
|
||||
// TODO: allow setting of Gate17 status (on/off)
|
||||
|
||||
// return original status
|
||||
return status, nil
|
||||
}
|
||||
|
||||
func initStatusHook() (err error) {
|
||||
hook, err = database.RegisterHook(query.New(statusDBKey), &statusHook{})
|
||||
return err
|
||||
}
|
|
@ -20,7 +20,7 @@ func max(a, b uint8) uint8 {
|
|||
func ConfigIsActive(name string) SecurityLevelOption {
|
||||
activeAtLevel := config.GetAsInt(name, int64(SecurityLevelDynamic))
|
||||
return func(minSecurityLevel uint8) bool {
|
||||
return uint8(activeAtLevel()) <= max(CurrentSecurityLevel(), minSecurityLevel)
|
||||
return uint8(activeAtLevel()) <= max(ActiveSecurityLevel(), minSecurityLevel)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,6 @@ func ConfigIsActive(name string) SecurityLevelOption {
|
|||
func ConfigIsActiveConcurrent(name string) SecurityLevelOption {
|
||||
activeAtLevel := config.Concurrent.GetAsInt(name, int64(SecurityLevelDynamic))
|
||||
return func(minSecurityLevel uint8) bool {
|
||||
return uint8(activeAtLevel()) <= max(CurrentSecurityLevel(), minSecurityLevel)
|
||||
return uint8(activeAtLevel()) <= max(ActiveSecurityLevel(), minSecurityLevel)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,32 +5,29 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
currentSecurityLevel *uint32
|
||||
activeSecurityLevel *uint32
|
||||
selectedSecurityLevel *uint32
|
||||
threatLevel *uint32
|
||||
portmasterStatus *uint32
|
||||
gate17Status *uint32
|
||||
)
|
||||
|
||||
func init() {
|
||||
var (
|
||||
currentSecurityLevelValue uint32
|
||||
activeSecurityLevelValue uint32
|
||||
selectedSecurityLevelValue uint32
|
||||
threatLevelValue uint32
|
||||
portmasterStatusValue uint32
|
||||
gate17StatusValue uint32
|
||||
)
|
||||
|
||||
currentSecurityLevel = ¤tSecurityLevelValue
|
||||
activeSecurityLevel = &activeSecurityLevelValue
|
||||
selectedSecurityLevel = &selectedSecurityLevelValue
|
||||
threatLevel = &threatLevelValue
|
||||
portmasterStatus = &portmasterStatusValue
|
||||
gate17Status = &gate17StatusValue
|
||||
}
|
||||
|
||||
// CurrentSecurityLevel returns the current security level.
|
||||
func CurrentSecurityLevel() uint8 {
|
||||
return uint8(atomic.LoadUint32(currentSecurityLevel))
|
||||
// ActiveSecurityLevel returns the current security level.
|
||||
func ActiveSecurityLevel() uint8 {
|
||||
return uint8(atomic.LoadUint32(activeSecurityLevel))
|
||||
}
|
||||
|
||||
// SelectedSecurityLevel returns the selected security level.
|
||||
|
@ -38,11 +35,6 @@ func SelectedSecurityLevel() uint8 {
|
|||
return uint8(atomic.LoadUint32(selectedSecurityLevel))
|
||||
}
|
||||
|
||||
// ThreatLevel returns the current threat level.
|
||||
func ThreatLevel() uint8 {
|
||||
return uint8(atomic.LoadUint32(threatLevel))
|
||||
}
|
||||
|
||||
// PortmasterStatus returns the current Portmaster status.
|
||||
func PortmasterStatus() uint8 {
|
||||
return uint8(atomic.LoadUint32(portmasterStatus))
|
||||
|
|
|
@ -5,9 +5,9 @@ import "testing"
|
|||
func TestGet(t *testing.T) {
|
||||
|
||||
// only test for panics
|
||||
CurrentSecurityLevel()
|
||||
// TODO: write real tests
|
||||
ActiveSecurityLevel()
|
||||
SelectedSecurityLevel()
|
||||
ThreatLevel()
|
||||
PortmasterStatus()
|
||||
Gate17Status()
|
||||
option := ConfigIsActive("invalid")
|
||||
|
|
|
@ -1,25 +1,59 @@
|
|||
package status
|
||||
|
||||
import (
|
||||
"github.com/Safing/portbase/database"
|
||||
"github.com/Safing/portbase/log"
|
||||
"github.com/Safing/portbase/modules"
|
||||
)
|
||||
|
||||
var (
|
||||
shutdownSignal = make(chan struct{})
|
||||
)
|
||||
|
||||
func init() {
|
||||
modules.Register("status", prep, nil, nil)
|
||||
modules.Register("status", nil, start, stop)
|
||||
}
|
||||
|
||||
func prep() error {
|
||||
func start() error {
|
||||
var loadedStatus *SystemStatus
|
||||
|
||||
if CurrentSecurityLevel() == SecurityLevelOff {
|
||||
log.Infof("switching to default active security level: dynamic")
|
||||
SetCurrentSecurityLevel(SecurityLevelDynamic)
|
||||
// load status from database
|
||||
r, err := statusDB.Get(statusDBKey)
|
||||
switch err {
|
||||
case nil:
|
||||
loadedStatus, err = EnsureSystemStatus(r)
|
||||
if err != nil {
|
||||
log.Criticalf("status: failed to unwrap system status: %s", err)
|
||||
loadedStatus = nil
|
||||
}
|
||||
case database.ErrNotFound:
|
||||
// create new status
|
||||
default:
|
||||
log.Criticalf("status: failed to load system status: %s", err)
|
||||
}
|
||||
|
||||
if SelectedSecurityLevel() == SecurityLevelOff {
|
||||
log.Infof("switching to default selected security level: dynamic")
|
||||
SetSelectedSecurityLevel(SecurityLevelDynamic)
|
||||
// activate loaded status, if available
|
||||
if loadedStatus != nil {
|
||||
status = loadedStatus
|
||||
}
|
||||
status.Lock()
|
||||
defer status.Unlock()
|
||||
|
||||
// load status into atomic getters
|
||||
atomicUpdateSelectedSecurityLevel(status.SelectedSecurityLevel)
|
||||
atomicUpdatePortmasterStatus(status.PortmasterStatus)
|
||||
atomicUpdateGate17Status(status.Gate17Status)
|
||||
|
||||
// update status
|
||||
status.updateThreatMitigationLevel()
|
||||
status.autopilot()
|
||||
|
||||
go status.Save()
|
||||
|
||||
return initStatusHook()
|
||||
}
|
||||
|
||||
func stop() error {
|
||||
close(shutdownSignal)
|
||||
return nil
|
||||
}
|
||||
|
|
106
status/set.go
106
status/set.go
|
@ -1,61 +1,93 @@
|
|||
package status
|
||||
|
||||
import "sync/atomic"
|
||||
import (
|
||||
"sync/atomic"
|
||||
|
||||
// SetCurrentSecurityLevel sets the current security level.
|
||||
func SetCurrentSecurityLevel(level uint8) {
|
||||
sysStatusLock.Lock()
|
||||
defer sysStatusLock.Unlock()
|
||||
sysStatus.CurrentSecurityLevel = level
|
||||
atomicUpdateCurrentSecurityLevel(level)
|
||||
"github.com/Safing/portbase/log"
|
||||
)
|
||||
|
||||
// autopilot automatically adjusts the security level as needed
|
||||
func (s *SystemStatus) autopilot() {
|
||||
// check if users is overruling
|
||||
if s.SelectedSecurityLevel > SecurityLevelOff {
|
||||
s.ActiveSecurityLevel = s.SelectedSecurityLevel
|
||||
atomicUpdateActiveSecurityLevel(s.SelectedSecurityLevel)
|
||||
return
|
||||
}
|
||||
|
||||
// update active security level
|
||||
switch s.ThreatMitigationLevel {
|
||||
case SecurityLevelOff:
|
||||
s.ActiveSecurityLevel = SecurityLevelDynamic
|
||||
atomicUpdateActiveSecurityLevel(SecurityLevelDynamic)
|
||||
case SecurityLevelDynamic, SecurityLevelSecure, SecurityLevelFortress:
|
||||
s.ActiveSecurityLevel = s.ThreatMitigationLevel
|
||||
atomicUpdateActiveSecurityLevel(s.ThreatMitigationLevel)
|
||||
default:
|
||||
log.Errorf("status: threat mitigation level is set to invalid value: %d", s.ThreatMitigationLevel)
|
||||
}
|
||||
}
|
||||
|
||||
// SetSelectedSecurityLevel sets the selected security level.
|
||||
func SetSelectedSecurityLevel(level uint8) {
|
||||
sysStatusLock.Lock()
|
||||
defer sysStatusLock.Unlock()
|
||||
sysStatus.SelectedSecurityLevel = level
|
||||
atomicUpdateSelectedSecurityLevel(level)
|
||||
}
|
||||
// setSelectedSecurityLevel sets the selected security level.
|
||||
func setSelectedSecurityLevel(level uint8) {
|
||||
switch level {
|
||||
case SecurityLevelOff, SecurityLevelDynamic, SecurityLevelSecure, SecurityLevelFortress:
|
||||
status.Lock()
|
||||
defer status.Unlock()
|
||||
|
||||
// SetThreatLevel sets the current threat level.
|
||||
func SetThreatLevel(level uint8) {
|
||||
sysStatusLock.Lock()
|
||||
defer sysStatusLock.Unlock()
|
||||
sysStatus.ThreatLevel = level
|
||||
atomicUpdateThreatLevel(level)
|
||||
status.SelectedSecurityLevel = level
|
||||
atomicUpdateSelectedSecurityLevel(level)
|
||||
status.autopilot()
|
||||
|
||||
go status.Save()
|
||||
default:
|
||||
log.Errorf("status: tried to set selected security level to invalid value: %d", level)
|
||||
}
|
||||
}
|
||||
|
||||
// SetPortmasterStatus sets the current Portmaster status.
|
||||
func SetPortmasterStatus(status uint8) {
|
||||
sysStatusLock.Lock()
|
||||
defer sysStatusLock.Unlock()
|
||||
sysStatus.PortmasterStatus = status
|
||||
atomicUpdatePortmasterStatus(status)
|
||||
func SetPortmasterStatus(pmStatus uint8, msg string) {
|
||||
switch pmStatus {
|
||||
case StatusOff, StatusError, StatusWarning, StatusOk:
|
||||
status.Lock()
|
||||
defer status.Unlock()
|
||||
|
||||
status.PortmasterStatus = pmStatus
|
||||
status.PortmasterStatusMsg = msg
|
||||
atomicUpdatePortmasterStatus(pmStatus)
|
||||
|
||||
go status.Save()
|
||||
default:
|
||||
log.Errorf("status: tried to set portmaster to invalid status: %d", status)
|
||||
}
|
||||
}
|
||||
|
||||
// SetGate17Status sets the current Gate17 status.
|
||||
func SetGate17Status(status uint8) {
|
||||
sysStatusLock.Lock()
|
||||
defer sysStatusLock.Unlock()
|
||||
sysStatus.Gate17Status = status
|
||||
atomicUpdateGate17Status(status)
|
||||
func SetGate17Status(g17Status uint8, msg string) {
|
||||
switch g17Status {
|
||||
case StatusOff, StatusError, StatusWarning, StatusOk:
|
||||
status.Lock()
|
||||
defer status.Unlock()
|
||||
|
||||
status.Gate17Status = g17Status
|
||||
status.Gate17StatusMsg = msg
|
||||
atomicUpdateGate17Status(g17Status)
|
||||
|
||||
go status.Save()
|
||||
default:
|
||||
log.Errorf("status: tried to set gate17 to invalid status: %d", status)
|
||||
}
|
||||
}
|
||||
|
||||
// update functions for atomic stuff
|
||||
|
||||
func atomicUpdateCurrentSecurityLevel(level uint8) {
|
||||
atomic.StoreUint32(currentSecurityLevel, uint32(level))
|
||||
func atomicUpdateActiveSecurityLevel(level uint8) {
|
||||
atomic.StoreUint32(activeSecurityLevel, uint32(level))
|
||||
}
|
||||
|
||||
func atomicUpdateSelectedSecurityLevel(level uint8) {
|
||||
atomic.StoreUint32(selectedSecurityLevel, uint32(level))
|
||||
}
|
||||
|
||||
func atomicUpdateThreatLevel(level uint8) {
|
||||
atomic.StoreUint32(threatLevel, uint32(level))
|
||||
}
|
||||
|
||||
func atomicUpdatePortmasterStatus(status uint8) {
|
||||
atomic.StoreUint32(portmasterStatus, uint32(status))
|
||||
}
|
||||
|
|
|
@ -5,10 +5,9 @@ import "testing"
|
|||
func TestSet(t *testing.T) {
|
||||
|
||||
// only test for panics
|
||||
SetCurrentSecurityLevel(0)
|
||||
SetSelectedSecurityLevel(0)
|
||||
SetThreatLevel(0)
|
||||
SetPortmasterStatus(0)
|
||||
SetGate17Status(0)
|
||||
// TODO: write real tests
|
||||
setSelectedSecurityLevel(0)
|
||||
SetPortmasterStatus(0, "")
|
||||
SetGate17Status(0, "")
|
||||
|
||||
}
|
||||
|
|
|
@ -1,38 +1,81 @@
|
|||
package status
|
||||
|
||||
import "sync"
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/Safing/portbase/database/record"
|
||||
"github.com/Safing/portbase/log"
|
||||
)
|
||||
|
||||
var (
|
||||
sysStatus *SystemStatus
|
||||
sysStatusLock sync.RWMutex
|
||||
status *SystemStatus
|
||||
)
|
||||
|
||||
func init() {
|
||||
sysStatus = &SystemStatus{}
|
||||
status = &SystemStatus{
|
||||
Threats: make(map[string]*Threat),
|
||||
}
|
||||
status.SetKey(statusDBKey)
|
||||
}
|
||||
|
||||
// SystemStatus saves basic information about the current system status.
|
||||
type SystemStatus struct {
|
||||
// database.Base
|
||||
CurrentSecurityLevel uint8
|
||||
record.Base
|
||||
sync.Mutex
|
||||
|
||||
ActiveSecurityLevel uint8
|
||||
SelectedSecurityLevel uint8
|
||||
|
||||
ThreatLevel uint8 `json:",omitempty" bson:",omitempty"`
|
||||
ThreatReason string `json:",omitempty" bson:",omitempty"`
|
||||
PortmasterStatus uint8
|
||||
PortmasterStatusMsg string
|
||||
|
||||
PortmasterStatus uint8 `json:",omitempty" bson:",omitempty"`
|
||||
PortmasterStatusMsg string `json:",omitempty" bson:",omitempty"`
|
||||
Gate17Status uint8
|
||||
Gate17StatusMsg string
|
||||
|
||||
Gate17Status uint8 `json:",omitempty" bson:",omitempty"`
|
||||
Gate17StatusMsg string `json:",omitempty" bson:",omitempty"`
|
||||
ThreatMitigationLevel uint8
|
||||
Threats map[string]*Threat
|
||||
|
||||
UpdateStatus string
|
||||
}
|
||||
|
||||
// FmtCurrentSecurityLevel returns the current security level as a string.
|
||||
func FmtCurrentSecurityLevel() string {
|
||||
current := CurrentSecurityLevel()
|
||||
selected := SelectedSecurityLevel()
|
||||
s := FmtSecurityLevel(current)
|
||||
if current != selected {
|
||||
// Save saves the SystemStatus to the database
|
||||
func (s *SystemStatus) Save() {
|
||||
err := statusDB.Put(s)
|
||||
if err != nil {
|
||||
log.Errorf("status: could not save status to database: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
// EnsureSystemStatus ensures that the given record is of type SystemStatus and unwraps it, if needed.
|
||||
func EnsureSystemStatus(r record.Record) (*SystemStatus, error) {
|
||||
// unwrap
|
||||
if r.IsWrapped() {
|
||||
// only allocate a new struct, if we need it
|
||||
new := &SystemStatus{}
|
||||
err := record.Unwrap(r, new)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return new, nil
|
||||
}
|
||||
|
||||
// or adjust type
|
||||
new, ok := r.(*SystemStatus)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("record not of type *SystemStatus, but %T", r)
|
||||
}
|
||||
return new, nil
|
||||
}
|
||||
|
||||
// FmtActiveSecurityLevel returns the current security level as a string.
|
||||
func FmtActiveSecurityLevel() string {
|
||||
status.Lock()
|
||||
mitigationLevel := status.ThreatMitigationLevel
|
||||
status.Unlock()
|
||||
active := ActiveSecurityLevel()
|
||||
s := FmtSecurityLevel(active)
|
||||
if mitigationLevel > 0 && active != mitigationLevel {
|
||||
s += "*"
|
||||
}
|
||||
return s
|
||||
|
|
|
@ -4,33 +4,31 @@ import "testing"
|
|||
|
||||
func TestStatus(t *testing.T) {
|
||||
|
||||
SetCurrentSecurityLevel(SecurityLevelOff)
|
||||
SetSelectedSecurityLevel(SecurityLevelOff)
|
||||
if FmtCurrentSecurityLevel() != "Off" {
|
||||
t.Error("unexpected string representation")
|
||||
setSelectedSecurityLevel(SecurityLevelOff)
|
||||
if FmtActiveSecurityLevel() != "Dynamic" {
|
||||
t.Errorf("unexpected string representation: %s", FmtActiveSecurityLevel())
|
||||
}
|
||||
|
||||
SetCurrentSecurityLevel(SecurityLevelDynamic)
|
||||
SetSelectedSecurityLevel(SecurityLevelDynamic)
|
||||
if FmtCurrentSecurityLevel() != "Dynamic" {
|
||||
t.Error("unexpected string representation")
|
||||
setSelectedSecurityLevel(SecurityLevelDynamic)
|
||||
AddOrUpdateThreat(&Threat{MitigationLevel: SecurityLevelSecure})
|
||||
if FmtActiveSecurityLevel() != "Dynamic*" {
|
||||
t.Errorf("unexpected string representation: %s", FmtActiveSecurityLevel())
|
||||
}
|
||||
|
||||
SetCurrentSecurityLevel(SecurityLevelSecure)
|
||||
SetSelectedSecurityLevel(SecurityLevelSecure)
|
||||
if FmtCurrentSecurityLevel() != "Secure" {
|
||||
t.Error("unexpected string representation")
|
||||
setSelectedSecurityLevel(SecurityLevelSecure)
|
||||
if FmtActiveSecurityLevel() != "Secure" {
|
||||
t.Errorf("unexpected string representation: %s", FmtActiveSecurityLevel())
|
||||
}
|
||||
|
||||
SetCurrentSecurityLevel(SecurityLevelFortress)
|
||||
SetSelectedSecurityLevel(SecurityLevelFortress)
|
||||
if FmtCurrentSecurityLevel() != "Fortress" {
|
||||
t.Error("unexpected string representation")
|
||||
setSelectedSecurityLevel(SecurityLevelSecure)
|
||||
AddOrUpdateThreat(&Threat{MitigationLevel: SecurityLevelFortress})
|
||||
if FmtActiveSecurityLevel() != "Secure*" {
|
||||
t.Errorf("unexpected string representation: %s", FmtActiveSecurityLevel())
|
||||
}
|
||||
|
||||
SetSelectedSecurityLevel(SecurityLevelDynamic)
|
||||
if FmtCurrentSecurityLevel() != "Fortress*" {
|
||||
t.Error("unexpected string representation")
|
||||
setSelectedSecurityLevel(SecurityLevelFortress)
|
||||
if FmtActiveSecurityLevel() != "Fortress" {
|
||||
t.Errorf("unexpected string representation: %s", FmtActiveSecurityLevel())
|
||||
}
|
||||
|
||||
}
|
||||
|
|
72
status/threat.go
Normal file
72
status/threat.go
Normal file
|
@ -0,0 +1,72 @@
|
|||
package status
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Threat describes a detected threat.
|
||||
type Threat struct {
|
||||
ID string // A unique ID chosen by reporting module (eg. modulePrefix-incident) to periodically check threat existence
|
||||
Name string // Descriptive (human readable) name for detected threat
|
||||
Description string // Simple description
|
||||
AdditionalData interface{} // Additional data a module wants to make available for the user
|
||||
MitigationLevel uint8 // Recommended Security Level to switch to for mitigation
|
||||
Started int64
|
||||
Ended int64
|
||||
}
|
||||
|
||||
// AddOrUpdateThreat adds or updates a new threat in the system status.
|
||||
func AddOrUpdateThreat(new *Threat) {
|
||||
status.Lock()
|
||||
defer status.Unlock()
|
||||
|
||||
status.Threats[new.ID] = new
|
||||
status.updateThreatMitigationLevel()
|
||||
status.autopilot()
|
||||
|
||||
go status.Save()
|
||||
}
|
||||
|
||||
// DeleteThreat deletes a threat from the system status.
|
||||
func DeleteThreat(id string) {
|
||||
status.Lock()
|
||||
defer status.Unlock()
|
||||
|
||||
delete(status.Threats, id)
|
||||
status.updateThreatMitigationLevel()
|
||||
status.autopilot()
|
||||
|
||||
go status.Save()
|
||||
}
|
||||
|
||||
// GetThreats returns all threats who's IDs are prefixed by the given string, and also a locker for editing them.
|
||||
func GetThreats(idPrefix string) ([]*Threat, sync.Locker) {
|
||||
status.Lock()
|
||||
defer status.Unlock()
|
||||
|
||||
var exportedThreats []*Threat
|
||||
for id, threat := range status.Threats {
|
||||
if strings.HasPrefix(id, idPrefix) {
|
||||
exportedThreats = append(exportedThreats, threat)
|
||||
}
|
||||
}
|
||||
|
||||
return exportedThreats, &status.Mutex
|
||||
}
|
||||
|
||||
func (s *SystemStatus) updateThreatMitigationLevel() {
|
||||
// get highest mitigationLevel
|
||||
var mitigationLevel uint8
|
||||
for _, threat := range s.Threats {
|
||||
switch threat.MitigationLevel {
|
||||
case SecurityLevelDynamic, SecurityLevelSecure, SecurityLevelFortress:
|
||||
if threat.MitigationLevel > mitigationLevel {
|
||||
mitigationLevel = threat.MitigationLevel
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// set new ThreatMitigationLevel
|
||||
s.ThreatMitigationLevel = mitigationLevel
|
||||
}
|
18
status/updates.go
Normal file
18
status/updates.go
Normal file
|
@ -0,0 +1,18 @@
|
|||
package status
|
||||
|
||||
// Update status options
|
||||
const (
|
||||
UpdateStatusCurrentStable = "stable"
|
||||
UpdateStatusCurrentBeta = "beta"
|
||||
UpdateStatusAvailable = "available" // restart or reboot required
|
||||
UpdateStatusFailed = "failed" // check logs
|
||||
)
|
||||
|
||||
// SetUpdateStatus updates the system status with a new update status.
|
||||
func SetUpdateStatus(newStatus string) {
|
||||
status.Lock()
|
||||
status.UpdateStatus = newStatus
|
||||
status.Unlock()
|
||||
|
||||
go status.Save()
|
||||
}
|
Loading…
Add table
Reference in a new issue