Remove network rating / security level system, add migrations
This commit is contained in:
@@ -1,36 +0,0 @@
|
||||
package status
|
||||
|
||||
import "context"
|
||||
|
||||
var runAutoPilot = make(chan struct{}, 1)
|
||||
|
||||
func triggerAutopilot() {
|
||||
select {
|
||||
case runAutoPilot <- struct{}{}:
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
func autoPilot(ctx context.Context) error {
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil
|
||||
case <-runAutoPilot:
|
||||
}
|
||||
|
||||
selected := SelectedSecurityLevel()
|
||||
mitigation := getHighestMitigationLevel()
|
||||
|
||||
active := SecurityLevelNormal
|
||||
if selected != SecurityLevelOff {
|
||||
active = selected
|
||||
} else if mitigation != SecurityLevelOff {
|
||||
active = mitigation
|
||||
}
|
||||
|
||||
setActiveLevel(active)
|
||||
|
||||
pushSystemStatus()
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
package status
|
||||
|
||||
import "github.com/safing/portbase/config"
|
||||
|
||||
// Configuration Keys.
|
||||
var (
|
||||
CfgEnableNetworkRatingSystemKey = "core/enableNetworkRating"
|
||||
cfgEnableNetworkRatingSystem config.BoolOption
|
||||
)
|
||||
|
||||
func registerConfig() error {
|
||||
if err := config.Register(&config.Option{
|
||||
Name: "Enable Network Rating System",
|
||||
Key: CfgEnableNetworkRatingSystemKey,
|
||||
Description: `Enable the Network Rating System, which allows you to configure settings to be active in one environment but not in the other, like allowing sensitive connections at home but not at the public library.
|
||||
|
||||
Please note that this feature will be replaced by a superior and easier to understand system in the future.`,
|
||||
OptType: config.OptTypeBool,
|
||||
ExpertiseLevel: config.ExpertiseLevelExpert,
|
||||
ReleaseLevel: config.ReleaseLevelStable,
|
||||
DefaultValue: false,
|
||||
Annotations: config.Annotations{
|
||||
config.DisplayOrderAnnotation: 514,
|
||||
config.CategoryAnnotation: "User Interface",
|
||||
},
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
cfgEnableNetworkRatingSystem = config.Concurrent.GetAsBool(CfgEnableNetworkRatingSystemKey, false)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NetworkRatingEnabled returns true if the network rating system has been enabled.
|
||||
func NetworkRatingEnabled() bool {
|
||||
return cfgEnableNetworkRatingSystem()
|
||||
}
|
||||
|
||||
// SetNetworkRating enables or disables the network rating system.
|
||||
func SetNetworkRating(enabled bool) error {
|
||||
return config.SetConfigOption(CfgEnableNetworkRatingSystemKey, enabled)
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
package status
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/safing/portbase/log"
|
||||
)
|
||||
|
||||
type knownThreats struct {
|
||||
sync.RWMutex
|
||||
// active threats and their recommended mitigation level
|
||||
list map[string]uint8
|
||||
}
|
||||
|
||||
var threats = &knownThreats{
|
||||
list: make(map[string]uint8),
|
||||
}
|
||||
|
||||
// SetMitigationLevel sets the mitigation level for id
|
||||
// to mitigation. If mitigation is SecurityLevelOff the
|
||||
// mitigation record will be removed. If mitigation is
|
||||
// an invalid level the call to SetMitigationLevel is a
|
||||
// no-op.
|
||||
func SetMitigationLevel(id string, mitigation uint8) {
|
||||
if !IsValidSecurityLevel(mitigation) {
|
||||
log.Warningf("tried to set invalid mitigation level %d for threat %s", mitigation, id)
|
||||
return
|
||||
}
|
||||
|
||||
defer triggerAutopilot()
|
||||
|
||||
threats.Lock()
|
||||
defer threats.Unlock()
|
||||
if mitigation == 0 {
|
||||
delete(threats.list, id)
|
||||
} else {
|
||||
threats.list[id] = mitigation
|
||||
}
|
||||
}
|
||||
|
||||
// DeleteMitigationLevel deletes the mitigation level for id.
|
||||
func DeleteMitigationLevel(id string) {
|
||||
SetMitigationLevel(id, SecurityLevelOff)
|
||||
}
|
||||
|
||||
// getHighestMitigationLevel returns the highest mitigation
|
||||
// level set on a threat.
|
||||
func getHighestMitigationLevel() uint8 {
|
||||
threats.RLock()
|
||||
defer threats.RUnlock()
|
||||
|
||||
level := SecurityLevelNormal
|
||||
for _, lvl := range threats.list {
|
||||
if lvl > level {
|
||||
level = lvl
|
||||
}
|
||||
}
|
||||
|
||||
return level
|
||||
}
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
var module *modules.Module
|
||||
|
||||
func init() {
|
||||
module = modules.Register("status", prepare, start, nil, "base", "config")
|
||||
module = modules.Register("status", nil, start, nil, "base", "config")
|
||||
}
|
||||
|
||||
func start() error {
|
||||
@@ -20,57 +20,26 @@ func start() error {
|
||||
return err
|
||||
}
|
||||
|
||||
module.StartWorker("auto-pilot", autoPilot)
|
||||
|
||||
triggerAutopilot()
|
||||
|
||||
if err := module.RegisterEventHook(
|
||||
netenv.ModuleName,
|
||||
netenv.OnlineStatusChangedEvent,
|
||||
"update online status in system status",
|
||||
func(_ context.Context, _ interface{}) error {
|
||||
triggerAutopilot()
|
||||
pushSystemStatus()
|
||||
return nil
|
||||
},
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := module.RegisterEventHook(
|
||||
"config",
|
||||
"config change",
|
||||
"Update network rating system",
|
||||
func(_ context.Context, _ interface{}) error {
|
||||
if !NetworkRatingEnabled() && ActiveSecurityLevel() != SecurityLevelNormal {
|
||||
setSelectedLevel(SecurityLevelNormal)
|
||||
triggerAutopilot()
|
||||
}
|
||||
return nil
|
||||
},
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func prepare() error {
|
||||
if err := registerConfig(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddToDebugInfo adds the system status to the given debug.Info.
|
||||
func AddToDebugInfo(di *debug.Info) {
|
||||
di.AddSection(
|
||||
fmt.Sprintf("Status: %s", SecurityLevelString(ActiveSecurityLevel())),
|
||||
fmt.Sprintf("Status: %s", netenv.GetOnlineStatus()),
|
||||
debug.UseCodeSection|debug.AddContentLineBreaks,
|
||||
fmt.Sprintf("ActiveSecurityLevel: %s", SecurityLevelString(ActiveSecurityLevel())),
|
||||
fmt.Sprintf("SelectedSecurityLevel: %s", SecurityLevelString(SelectedSecurityLevel())),
|
||||
fmt.Sprintf("ThreatMitigationLevel: %s", SecurityLevelString(getHighestMitigationLevel())),
|
||||
fmt.Sprintf("CaptivePortal: %s", netenv.GetCaptivePortal().URL),
|
||||
fmt.Sprintf("OnlineStatus: %s", netenv.GetOnlineStatus()),
|
||||
fmt.Sprintf("CaptivePortal: %s", netenv.GetCaptivePortal().URL),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package status
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/safing/portbase/database/record"
|
||||
"github.com/safing/portbase/runtime"
|
||||
"github.com/safing/portmaster/netenv"
|
||||
@@ -12,7 +10,6 @@ var pushUpdate runtime.PushFunc
|
||||
|
||||
func setupRuntimeProvider() (err error) {
|
||||
// register the system status getter
|
||||
//
|
||||
statusProvider := runtime.SimpleValueGetterFunc(func(_ string) ([]record.Record, error) {
|
||||
return []record.Record{buildSystemStatus()}, nil
|
||||
})
|
||||
@@ -21,63 +18,14 @@ func setupRuntimeProvider() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
// register the selected security level setter
|
||||
//
|
||||
levelProvider := runtime.SimpleValueSetterFunc(setSelectedSecurityLevel)
|
||||
_, err = runtime.Register("system/security-level", levelProvider)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// setSelectedSecurityLevel updates the selected security level.
|
||||
func setSelectedSecurityLevel(r record.Record) (record.Record, error) {
|
||||
var upd *SelectedSecurityLevelRecord
|
||||
if r.IsWrapped() {
|
||||
upd = new(SelectedSecurityLevelRecord)
|
||||
if err := record.Unwrap(r, upd); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
// TODO(ppacher): this can actually never happen
|
||||
// as we're write-only and ValueProvider.Set() should
|
||||
// only ever be called from the HTTP API (so r must be wrapped).
|
||||
// Though, make sure we handle the case as well ...
|
||||
var ok bool
|
||||
upd, ok = r.(*SelectedSecurityLevelRecord)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("expected *SelectedSecurityLevelRecord but got %T", r)
|
||||
}
|
||||
}
|
||||
|
||||
// if the network rating system is not used at all we always force the security
|
||||
// level to trusted.
|
||||
if !NetworkRatingEnabled() {
|
||||
upd.SelectedSecurityLevel = SecurityLevelNormal
|
||||
}
|
||||
|
||||
if !IsValidSecurityLevel(upd.SelectedSecurityLevel) {
|
||||
return nil, fmt.Errorf("invalid security level: %d", upd.SelectedSecurityLevel)
|
||||
}
|
||||
|
||||
if SelectedSecurityLevel() != upd.SelectedSecurityLevel {
|
||||
setSelectedLevel(upd.SelectedSecurityLevel)
|
||||
triggerAutopilot()
|
||||
}
|
||||
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// buildSystemStatus build a new system status record.
|
||||
func buildSystemStatus() *SystemStatusRecord {
|
||||
status := &SystemStatusRecord{
|
||||
ActiveSecurityLevel: ActiveSecurityLevel(),
|
||||
SelectedSecurityLevel: SelectedSecurityLevel(),
|
||||
ThreatMitigationLevel: getHighestMitigationLevel(),
|
||||
CaptivePortal: netenv.GetCaptivePortal(),
|
||||
OnlineStatus: netenv.GetOnlineStatus(),
|
||||
CaptivePortal: netenv.GetCaptivePortal(),
|
||||
OnlineStatus: netenv.GetOnlineStatus(),
|
||||
}
|
||||
|
||||
status.CreateMeta()
|
||||
|
||||
@@ -13,15 +13,6 @@ type SystemStatusRecord struct {
|
||||
record.Base
|
||||
sync.Mutex
|
||||
|
||||
// ActiveSecurityLevel holds the currently
|
||||
// active security level.
|
||||
ActiveSecurityLevel uint8
|
||||
// SelectedSecurityLevel holds the security level
|
||||
// as selected by the user.
|
||||
SelectedSecurityLevel uint8
|
||||
// ThreatMitigationLevel holds the security level
|
||||
// as selected by the auto-pilot.
|
||||
ThreatMitigationLevel uint8
|
||||
// OnlineStatus holds the current online status as
|
||||
// seen by the netenv package.
|
||||
OnlineStatus netenv.OnlineStatus
|
||||
@@ -30,13 +21,3 @@ type SystemStatusRecord struct {
|
||||
// connected to, if any.
|
||||
CaptivePortal *netenv.CaptivePortal
|
||||
}
|
||||
|
||||
// SelectedSecurityLevelRecord is used as a dummy record.Record
|
||||
// to provide a simply runtime-configuration for the user.
|
||||
// It is write-only and exposed at "runtime:system/security-level".
|
||||
type SelectedSecurityLevelRecord struct {
|
||||
record.Base
|
||||
sync.Mutex
|
||||
|
||||
SelectedSecurityLevel uint8
|
||||
}
|
||||
|
||||
@@ -2,14 +2,50 @@ package status
|
||||
|
||||
import "github.com/safing/portbase/config"
|
||||
|
||||
type (
|
||||
// SecurityLevelOptionFunc can be called with a minimum security level
|
||||
// and returns whether or not a given security option is enabled or
|
||||
// not.
|
||||
// Use SecurityLevelOption() to get a SecurityLevelOptionFunc for a
|
||||
// specific option.
|
||||
SecurityLevelOptionFunc func(minSecurityLevel uint8) bool
|
||||
)
|
||||
// MigrateSecurityLevelToBoolean migrates a security level (int) option value to a boolean option value.
|
||||
func MigrateSecurityLevelToBoolean(option *config.Option, value any) any {
|
||||
// Check new (target) option type.
|
||||
if option.OptType != config.OptTypeBool {
|
||||
// This migration converts to boolean.
|
||||
// Thus, conversion is not applicable.
|
||||
return value
|
||||
}
|
||||
|
||||
// Convert value to uint8.
|
||||
var nVal uint8
|
||||
switch v := value.(type) {
|
||||
case int:
|
||||
nVal = uint8(v)
|
||||
case int8:
|
||||
nVal = uint8(v)
|
||||
case int16:
|
||||
nVal = uint8(v)
|
||||
case int32:
|
||||
nVal = uint8(v)
|
||||
case int64:
|
||||
nVal = uint8(v)
|
||||
case uint:
|
||||
nVal = uint8(v)
|
||||
case uint8:
|
||||
nVal = v
|
||||
case uint16:
|
||||
nVal = uint8(v)
|
||||
case uint32:
|
||||
nVal = uint8(v)
|
||||
case uint64:
|
||||
nVal = uint8(v)
|
||||
case float32:
|
||||
nVal = uint8(v)
|
||||
case float64:
|
||||
nVal = uint8(v)
|
||||
default:
|
||||
// Input type not compatible.
|
||||
return value
|
||||
}
|
||||
|
||||
// Convert to boolean.
|
||||
return nVal&SecurityLevelNormal > 0
|
||||
}
|
||||
|
||||
// DisplayHintSecurityLevel is an external option hint for security levels.
|
||||
// It's meant to be used as a value for config.DisplayHintAnnotation.
|
||||
@@ -17,102 +53,8 @@ const DisplayHintSecurityLevel string = "security level"
|
||||
|
||||
// Security levels.
|
||||
const (
|
||||
SecurityLevelOff uint8 = 0
|
||||
SecurityLevelNormal uint8 = 1
|
||||
SecurityLevelHigh uint8 = 2
|
||||
SecurityLevelExtreme uint8 = 4
|
||||
|
||||
SecurityLevelsNormalAndHigh uint8 = SecurityLevelNormal | SecurityLevelHigh
|
||||
SecurityLevelsNormalAndExtreme uint8 = SecurityLevelNormal | SecurityLevelExtreme
|
||||
SecurityLevelsHighAndExtreme uint8 = SecurityLevelHigh | SecurityLevelExtreme
|
||||
SecurityLevelsAll uint8 = SecurityLevelNormal | SecurityLevelHigh | SecurityLevelExtreme
|
||||
// SecurityLevelOff uint8 = 0
|
||||
SecurityLevelNormal uint8 = 1
|
||||
// SecurityLevelHigh uint8 = 2
|
||||
// SecurityLevelExtreme uint8 = 4
|
||||
)
|
||||
|
||||
// SecurityLevelValues defines all possible security levels.
|
||||
var SecurityLevelValues = []config.PossibleValue{
|
||||
{
|
||||
Name: "Trusted / Home Network",
|
||||
Value: SecurityLevelsAll,
|
||||
Description: "Setting is always enabled.",
|
||||
},
|
||||
{
|
||||
Name: "Untrusted / Public Network",
|
||||
Value: SecurityLevelsHighAndExtreme,
|
||||
Description: "Setting is enabled in untrusted and dangerous networks.",
|
||||
},
|
||||
{
|
||||
Name: "Danger / Hacked Network",
|
||||
Value: SecurityLevelExtreme,
|
||||
Description: "Setting is enabled only in dangerous networks.",
|
||||
},
|
||||
}
|
||||
|
||||
// AllSecurityLevelValues is like SecurityLevelValues but also includes Off.
|
||||
var AllSecurityLevelValues = append([]config.PossibleValue{
|
||||
{
|
||||
Name: "Off",
|
||||
Value: SecurityLevelOff,
|
||||
Description: "Setting is always disabled.",
|
||||
},
|
||||
},
|
||||
SecurityLevelValues...,
|
||||
)
|
||||
|
||||
// IsValidSecurityLevel returns true if level is a valid,
|
||||
// single security level. Level is also invalid if it's a
|
||||
// bitmask with more that one security level set.
|
||||
func IsValidSecurityLevel(level uint8) bool {
|
||||
return level == SecurityLevelOff ||
|
||||
level == SecurityLevelNormal ||
|
||||
level == SecurityLevelHigh ||
|
||||
level == SecurityLevelExtreme
|
||||
}
|
||||
|
||||
// IsValidSecurityLevelMask returns true if level is a valid
|
||||
// security level mask. It's like IsValidSecurityLevel but
|
||||
// also allows bitmask combinations.
|
||||
func IsValidSecurityLevelMask(level uint8) bool {
|
||||
return level <= 7
|
||||
}
|
||||
|
||||
func max(a, b uint8) uint8 {
|
||||
if a > b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// SecurityLevelOption returns a function to check if the option
|
||||
// identified by name is active at a given minimum security level.
|
||||
// The returned function is safe for concurrent use with configuration
|
||||
// updates.
|
||||
func SecurityLevelOption(name string) SecurityLevelOptionFunc {
|
||||
activeAtLevel := config.Concurrent.GetAsInt(name, int64(SecurityLevelsAll))
|
||||
return func(minSecurityLevel uint8) bool {
|
||||
return uint8(activeAtLevel())&max(ActiveSecurityLevel(), minSecurityLevel) > 0
|
||||
}
|
||||
}
|
||||
|
||||
// SecurityLevelString returns the given security level as a string.
|
||||
func SecurityLevelString(level uint8) string {
|
||||
switch level {
|
||||
case SecurityLevelOff:
|
||||
return "Off"
|
||||
case SecurityLevelNormal:
|
||||
return "Trusted"
|
||||
case SecurityLevelHigh:
|
||||
return "Untrusted"
|
||||
case SecurityLevelExtreme:
|
||||
return "Danger"
|
||||
case SecurityLevelsNormalAndHigh:
|
||||
return "Trusted and Untrusted"
|
||||
case SecurityLevelsNormalAndExtreme:
|
||||
return "Trusted and Danger"
|
||||
case SecurityLevelsHighAndExtreme:
|
||||
return "Untrusted and Danger"
|
||||
case SecurityLevelsAll:
|
||||
return "Trusted, Untrusted and Danger"
|
||||
default:
|
||||
return "INVALID"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
package status
|
||||
|
||||
import (
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
var (
|
||||
activeLevel = new(uint32)
|
||||
selectedLevel = new(uint32)
|
||||
)
|
||||
|
||||
func setActiveLevel(lvl uint8) {
|
||||
atomic.StoreUint32(activeLevel, uint32(lvl))
|
||||
}
|
||||
|
||||
func setSelectedLevel(lvl uint8) {
|
||||
atomic.StoreUint32(selectedLevel, uint32(lvl))
|
||||
}
|
||||
|
||||
// ActiveSecurityLevel returns the currently active security
|
||||
// level.
|
||||
func ActiveSecurityLevel() uint8 {
|
||||
return uint8(atomic.LoadUint32(activeLevel))
|
||||
}
|
||||
|
||||
// SelectedSecurityLevel returns the security level as selected
|
||||
// by the user.
|
||||
func SelectedSecurityLevel() uint8 {
|
||||
return uint8(atomic.LoadUint32(selectedLevel))
|
||||
}
|
||||
132
status/threat.go
132
status/threat.go
@@ -1,132 +0,0 @@
|
||||
package status
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/safing/portbase/log"
|
||||
"github.com/safing/portbase/notifications"
|
||||
)
|
||||
|
||||
// Threat represents a threat to the system.
|
||||
// A threat is basically a notification with strong
|
||||
// typed EventData. Use the methods expored on Threat
|
||||
// to manipulate the EventData field and push updates
|
||||
// of the notification.
|
||||
// Do not use EventData directly!
|
||||
type Threat struct {
|
||||
*notifications.Notification
|
||||
}
|
||||
|
||||
// ThreatPayload holds threat related information.
|
||||
type ThreatPayload struct {
|
||||
// MitigationLevel holds the recommended security
|
||||
// level to mitigate the threat.
|
||||
MitigationLevel uint8
|
||||
// Started holds the UNIX epoch timestamp in seconds
|
||||
// at which the threat has been detected the first time.
|
||||
Started int64
|
||||
// Ended holds the UNIX epoch timestamp in seconds
|
||||
// at which the threat has been detected the last time.
|
||||
Ended int64
|
||||
// Data may holds threat-specific data.
|
||||
Data interface{}
|
||||
}
|
||||
|
||||
// NewThreat returns a new threat. Note that the
|
||||
// threat only gets published once Publish is called.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// threat := NewThreat("portscan", "Someone is scanning you").
|
||||
// SetData(portscanResult).
|
||||
// SetMitigationLevel(SecurityLevelExtreme).
|
||||
// Publish()
|
||||
//
|
||||
// Once you're done, delete the threat
|
||||
// threat.Delete().Publish()
|
||||
func NewThreat(id, title, msg string) *Threat {
|
||||
t := &Threat{
|
||||
Notification: ¬ifications.Notification{
|
||||
EventID: id,
|
||||
Type: notifications.Warning,
|
||||
Title: title,
|
||||
Category: "Threat",
|
||||
Message: msg,
|
||||
},
|
||||
}
|
||||
|
||||
t.threatData().Started = time.Now().Unix()
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
// SetData sets the data member of the threat payload.
|
||||
func (t *Threat) SetData(data interface{}) *Threat {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.threatData().Data = data
|
||||
return t
|
||||
}
|
||||
|
||||
// SetMitigationLevel sets the mitigation level of the
|
||||
// threat data.
|
||||
func (t *Threat) SetMitigationLevel(lvl uint8) *Threat {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.threatData().MitigationLevel = lvl
|
||||
return t
|
||||
}
|
||||
|
||||
// Delete sets the ended timestamp of the threat.
|
||||
func (t *Threat) Delete() *Threat {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.threatData().Ended = time.Now().Unix()
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
// Payload returns a copy of the threat payload.
|
||||
func (t *Threat) Payload() ThreatPayload {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
return *t.threatData() // creates a copy
|
||||
}
|
||||
|
||||
// Publish publishes the current threat.
|
||||
// Publish should always be called when changes to
|
||||
// the threat are recorded.
|
||||
func (t *Threat) Publish() *Threat {
|
||||
data := t.Payload()
|
||||
if data.Ended > 0 {
|
||||
DeleteMitigationLevel(t.EventID)
|
||||
} else {
|
||||
SetMitigationLevel(t.EventID, data.MitigationLevel)
|
||||
}
|
||||
|
||||
t.Save()
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
// threatData returns the threat payload associated with this
|
||||
// threat. If not data has been created yet a new ThreatPayload
|
||||
// is attached to t and returned. The caller must make sure to
|
||||
// hold appropriate locks when working with the returned payload.
|
||||
func (t *Threat) threatData() *ThreatPayload {
|
||||
if t.EventData == nil {
|
||||
t.EventData = new(ThreatPayload)
|
||||
}
|
||||
|
||||
payload, ok := t.EventData.(*ThreatPayload)
|
||||
if !ok {
|
||||
log.Warningf("unexpected type %T in thread notification payload", t.EventData)
|
||||
return new(ThreatPayload)
|
||||
}
|
||||
|
||||
return payload
|
||||
}
|
||||
Reference in New Issue
Block a user