/
threat.go
133 lines (111 loc) Β· 3.12 KB
/
threat.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
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
}