mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-18 08:16:39 +00:00
Add system activity tracking and event store (#636)
This PR adds system activity tracking. The management service records events like add/remove peer, group, rule, route, etc. The activity events are stored in the SQLite event store and can be queried by the HTTP API.
This commit is contained in:
@@ -1,6 +1,11 @@
|
||||
package server
|
||||
|
||||
import "github.com/netbirdio/netbird/management/server/status"
|
||||
import (
|
||||
"github.com/netbirdio/netbird/management/server/activity"
|
||||
"github.com/netbirdio/netbird/management/server/status"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Group of the peers for ACL
|
||||
type Group struct {
|
||||
@@ -34,6 +39,11 @@ type GroupUpdateOperation struct {
|
||||
Values []string
|
||||
}
|
||||
|
||||
// EventMeta returns activity event meta related to the group
|
||||
func (g *Group) EventMeta() map[string]any {
|
||||
return map[string]any{"name": g.Name}
|
||||
}
|
||||
|
||||
func (g *Group) Copy() *Group {
|
||||
return &Group{
|
||||
ID: g.ID,
|
||||
@@ -62,7 +72,7 @@ func (am *DefaultAccountManager) GetGroup(accountID, groupID string) (*Group, er
|
||||
}
|
||||
|
||||
// SaveGroup object of the peers
|
||||
func (am *DefaultAccountManager) SaveGroup(accountID string, group *Group) error {
|
||||
func (am *DefaultAccountManager) SaveGroup(accountID, userID string, newGroup *Group) error {
|
||||
|
||||
unlock := am.Store.AcquireAccountLock(accountID)
|
||||
defer unlock()
|
||||
@@ -71,17 +81,95 @@ func (am *DefaultAccountManager) SaveGroup(accountID string, group *Group) error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
account.Groups[group.ID] = group
|
||||
oldGroup, exists := account.Groups[newGroup.ID]
|
||||
account.Groups[newGroup.ID] = newGroup
|
||||
|
||||
account.Network.IncSerial()
|
||||
if err = am.Store.SaveAccount(account); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !exists {
|
||||
_, err = am.eventStore.Save(&activity.Event{
|
||||
Timestamp: time.Now(),
|
||||
Activity: activity.GroupCreated,
|
||||
InitiatorID: userID,
|
||||
TargetID: newGroup.ID,
|
||||
AccountID: accountID,
|
||||
Meta: newGroup.EventMeta(),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
addedPeers := make([]string, 0)
|
||||
removedPeers := make([]string, 0)
|
||||
if !exists {
|
||||
addedPeers = append(addedPeers, newGroup.Peers...)
|
||||
} else {
|
||||
addedPeers = difference(newGroup.Peers, oldGroup.Peers)
|
||||
removedPeers = difference(oldGroup.Peers, newGroup.Peers)
|
||||
}
|
||||
|
||||
for _, p := range addedPeers {
|
||||
peer := account.Peers[p]
|
||||
if peer == nil {
|
||||
log.Errorf("peer %s not found under account %s while saving group", p, accountID)
|
||||
continue
|
||||
}
|
||||
_, err = am.eventStore.Save(&activity.Event{
|
||||
Timestamp: time.Now(),
|
||||
Activity: activity.GroupAddedToPeer,
|
||||
InitiatorID: userID,
|
||||
TargetID: peer.IP.String(),
|
||||
AccountID: accountID,
|
||||
Meta: map[string]any{"group": newGroup.Name, "group_id": newGroup.ID, "peer_ip": peer.IP.String(),
|
||||
"peer_fqdn": peer.FQDN(am.GetDNSDomain())},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for _, p := range removedPeers {
|
||||
peer := account.Peers[p]
|
||||
if peer == nil {
|
||||
log.Errorf("peer %s not found under account %s while saving group", p, accountID)
|
||||
continue
|
||||
}
|
||||
_, err = am.eventStore.Save(&activity.Event{
|
||||
Timestamp: time.Now(),
|
||||
Activity: activity.GroupRemovedFromPeer,
|
||||
InitiatorID: userID,
|
||||
TargetID: peer.IP.String(),
|
||||
AccountID: accountID,
|
||||
Meta: map[string]any{"group": newGroup.Name, "group_id": newGroup.ID, "peer_ip": peer.IP.String(),
|
||||
"peer_fqdn": peer.FQDN(am.GetDNSDomain())},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return am.updateAccountPeers(account)
|
||||
}
|
||||
|
||||
// difference returns the elements in `a` that aren't in `b`.
|
||||
func difference(a, b []string) []string {
|
||||
mb := make(map[string]struct{}, len(b))
|
||||
for _, x := range b {
|
||||
mb[x] = struct{}{}
|
||||
}
|
||||
var diff []string
|
||||
for _, x := range a {
|
||||
if _, found := mb[x]; !found {
|
||||
diff = append(diff, x)
|
||||
}
|
||||
}
|
||||
return diff
|
||||
}
|
||||
|
||||
// UpdateGroup updates a group using a list of operations
|
||||
func (am *DefaultAccountManager) UpdateGroup(accountID string,
|
||||
groupID string, operations []GroupUpdateOperation) (*Group, error) {
|
||||
|
||||
Reference in New Issue
Block a user