-
Notifications
You must be signed in to change notification settings - Fork 24
/
ids.go
155 lines (133 loc) · 5.63 KB
/
ids.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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
package unifi
import (
"encoding/json"
"fmt"
"sort"
"time"
)
// IDS holds an Intrusion Prevention System Event.
type IDS struct {
AppProto string `json:"app_proto,omitempty"`
Archived FlexBool `json:"archived"`
Catname FlexString `json:"catname"`
Datetime time.Time `fake:"{recent_time}" json:"datetime"`
DestIP string `fake:"{ipv4address}" json:"dest_ip"`
DestIPGeo IPGeo `json:"dstipGeo"`
DestPort int `fake:"{port}" json:"dest_port,omitempty"`
DstIPASN string `fake:"{address}" json:"dstipASN"`
DstIPCountry string `fake:"{country}" json:"dstipCountry"`
DstMAC string `fake:"{macaddress}" json:"dst_mac"`
EventType string `json:"event_type"`
FlowID int64 `json:"flow_id"`
Host string `json:"host"`
ID string `fake:"{uuid}" json:"_id"`
InIface string `json:"in_iface"`
InnerAlertAction string `json:"inner_alert_action"`
InnerAlertCategory string `json:"inner_alert_category"`
InnerAlertGID int64 `json:"inner_alert_gid"`
InnerAlertRev int64 `json:"inner_alert_rev"`
InnerAlertSeverity int64 `json:"inner_alert_severity"`
InnerAlertSignature string `json:"inner_alert_signature"`
InnerAlertSignatureID int64 `json:"inner_alert_signature_id"`
Key string `fake:"{uuid}" json:"key"`
Msg string `fake:"{buzzword}" json:"msg"`
Proto string `json:"proto"`
SiteID string `fake:"{uuid}" json:"site_id"`
SiteName string `json:"-"`
SourceIPGeo IPGeo `json:"srcipGeo"`
SourceName string `json:"-"`
SrcIP string `fake:"{ipv4address}" json:"src_ip"`
SrcIPASN string `fake:"{address}" json:"srcipASN"`
SrcIPCountry string `fake:"{country}" json:"srcipCountry"`
SrcMAC string `fake:"{macaddress}" json:"src_mac"`
SrcPort int `fake:"{port}" json:"src_port,omitempty"`
Subsystem string `json:"subsystem"`
Time int64 `fake:"{timestamp}" json:"time"`
Timestamp int64 `fake:"{timestamp}" json:"timestamp"`
USGIP string `fake:"{ipv4address}" json:"usgip"`
USGIPASN string `fake:"{address}" json:"usgipASN"`
USGIPCountry string `fake:"{country}" json:"usgipCountry"`
USGIPGeo IPGeo `json:"usgipGeo"`
UniqueAlertID string `json:"unique_alertid"`
}
// GetIDS returns Intrusion Detection Systems events for a list of Sites.
// timeRange may have a length of 0, 1 or 2. The first time is Start, the second is End.
// Events between start and end are returned. End defaults to time.Now().
func (u *Unifi) GetIDS(sites []*Site, timeRange ...time.Time) ([]*IDS, error) {
data := []*IDS{}
for _, site := range sites {
response, err := u.GetIDSSite(site, timeRange...)
if err != nil {
return data, err
}
data = append(data, response...)
}
return data, nil
}
// GetIDSSite retrieves the Intrusion Detection System Data for a single Site.
// timeRange may have a length of 0, 1 or 2. The first time is Start, the second is End.
// Events between start and end are returned. End defaults to time.Now().
func (u *Unifi) GetIDSSite(site *Site, timeRange ...time.Time) ([]*IDS, error) {
if site == nil || site.Name == "" {
return nil, ErrNoSiteProvided
}
u.DebugLog("Polling Controller for IDS Events, site %s", site.SiteName)
var (
path = fmt.Sprintf(APIEventPathIDS, site.Name)
ids struct {
Data idsList `json:"data"`
}
)
if params, err := makeEventParams(timeRange...); err != nil {
return ids.Data, err
} else if err = u.GetData(path, &ids, params); err != nil {
return ids.Data, err
}
for i := range ids.Data {
// Add special SourceName value.
ids.Data[i].SourceName = u.URL
// Add the special "Site Name" to each event. This becomes a Grafana filter somewhere.
ids.Data[i].SiteName = site.SiteName
}
sort.Sort(ids.Data)
return ids.Data, nil
}
func makeEventParams(timeRange ...time.Time) (string, error) {
type eventReq struct {
Start int64 `json:"start,omitempty"`
End int64 `json:"end,omitempty"`
Limit int `json:"_limit,omitempty"`
Sort string `json:"_sort"`
}
rp := eventReq{Limit: eventLimit, Sort: "-time"}
switch len(timeRange) {
case 0:
rp.End = time.Now().Unix() * int64(time.Microsecond)
case 1:
rp.Start = timeRange[0].Unix() * int64(time.Microsecond)
rp.End = time.Now().Unix() * int64(time.Microsecond)
case 2: // nolint: gomnd
rp.Start = timeRange[0].Unix() * int64(time.Microsecond)
rp.End = timeRange[1].Unix() * int64(time.Microsecond)
default:
return "", ErrInvalidTimeRange
}
params, err := json.Marshal(&rp)
if err != nil {
return "", fmt.Errorf("json marshal: %w", err)
}
return string(params), nil
}
type idsList []*IDS
// Len satisfies sort.Interface.
func (e idsList) Len() int {
return len(e)
}
// Swap satisfies sort.Interface.
func (e idsList) Swap(i, j int) {
e[i], e[j] = e[j], e[i]
}
// Less satisfies sort.Interface. Sort our list by Datetime.
func (e idsList) Less(i, j int) bool {
return e[i].Datetime.Before(e[j].Datetime)
}