Add setup key events

This commit is contained in:
braginini
2022-12-22 12:06:15 +01:00
parent 747192c9f8
commit 91b61efe60
6 changed files with 88 additions and 14 deletions
+2 -2
View File
@@ -40,8 +40,8 @@ func cacheEntryExpiration() time.Duration {
type AccountManager interface { type AccountManager interface {
GetOrCreateAccountByUser(userId, domain string) (*Account, error) GetOrCreateAccountByUser(userId, domain string) (*Account, error)
CreateSetupKey(accountID string, keyName string, keyType SetupKeyType, expiresIn time.Duration, CreateSetupKey(accountID string, keyName string, keyType SetupKeyType, expiresIn time.Duration,
autoGroups []string, usageLimit int) (*SetupKey, error) autoGroups []string, usageLimit int, userID string) (*SetupKey, error)
SaveSetupKey(accountID string, key *SetupKey) (*SetupKey, error) SaveSetupKey(accountID string, key *SetupKey, userID string) (*SetupKey, error)
CreateUser(accountID, userID string, key *UserInfo) (*UserInfo, error) CreateUser(accountID, userID string, key *UserInfo) (*UserInfo, error)
ListSetupKeys(accountID, userID string) ([]*SetupKey, error) ListSetupKeys(accountID, userID string) ([]*SetupKey, error)
SaveUser(accountID string, key *User) (*UserInfo, error) SaveUser(accountID string, key *User) (*UserInfo, error)
+32
View File
@@ -21,6 +21,14 @@ const (
RuleUpdated RuleUpdated
// RuleRemoved indicates that a user removed a rule // RuleRemoved indicates that a user removed a rule
RuleRemoved RuleRemoved
// SetupKeyCreated indicates that a user created a new setup key
SetupKeyCreated
// SetupKeyUpdated indicates that a user updated a setup key
SetupKeyUpdated
// SetupKeyRevoked indicates that a user revoked a setup key
SetupKeyRevoked
// SetupKeyOverused indicates that setup key usage exhausted
SetupKeyOverused
) )
const ( const (
@@ -42,6 +50,14 @@ const (
RuleRemovedMessage string = "Rule deleted" RuleRemovedMessage string = "Rule deleted"
// RuleUpdatedMessage is a human-readable text message of the RuleRemoved activity // RuleUpdatedMessage is a human-readable text message of the RuleRemoved activity
RuleUpdatedMessage string = "Rule updated" RuleUpdatedMessage string = "Rule updated"
// SetupKeyCreatedMessage is a human-readable text message of the SetupKeyCreated activity
SetupKeyCreatedMessage string = "Setup key created"
// SetupKeyUpdatedMessage is a human-readable text message of the SetupKeyUpdated activity
SetupKeyUpdatedMessage string = "Setup key updated"
// SetupKeyRevokedMessage is a human-readable text message of the SetupKeyRevoked activity
SetupKeyRevokedMessage string = "Setup key revoked"
// SetupKeyOverusedMessage is a human-readable text message of the SetupKeyOverused activity
SetupKeyOverusedMessage string = "Setup key overused"
) )
// Activity that triggered an Event // Activity that triggered an Event
@@ -68,6 +84,14 @@ func (a Activity) Message() string {
return RuleRemovedMessage return RuleRemovedMessage
case RuleUpdated: case RuleUpdated:
return RuleUpdatedMessage return RuleUpdatedMessage
case SetupKeyCreated:
return SetupKeyCreatedMessage
case SetupKeyUpdated:
return SetupKeyUpdatedMessage
case SetupKeyRevoked:
return SetupKeyRevokedMessage
case SetupKeyOverused:
return SetupKeyOverusedMessage
default: default:
return "UNKNOWN_ACTIVITY" return "UNKNOWN_ACTIVITY"
} }
@@ -94,6 +118,14 @@ func (a Activity) StringCode() string {
return "rule.delete" return "rule.delete"
case RuleUpdated: case RuleUpdated:
return "rule.update" return "rule.update"
case SetupKeyCreated:
return "setupkey.add"
case SetupKeyRevoked:
return "setupkey.revoke"
case SetupKeyOverused:
return "setupkey.overuse"
case SetupKeyUpdated:
return "setupkey.update"
default: default:
return "UNKNOWN_ACTIVITY" return "UNKNOWN_ACTIVITY"
} }
+5 -1
View File
@@ -519,7 +519,11 @@ components:
activity_code: activity_code:
description: The string code of the activity that occurred during the event description: The string code of the activity that occurred during the event
type: string type: string
enum: [ "account.create", "user.join", "user.invite", "user.peer.add", "setupkey.peer.add", "user.peer.delete", "rule.add", "rule.delete", "rule.update"] enum: [ "user.peer.delete", "user.join", "user.invite", "user.peer.add",
"setupkey.peer.add", "setupkey.add", "setupkey.update", "setupkey.revoke", "setupkey.overuse",
"rule.add", "rule.delete", "rule.update",
"account.create",
]
initiator_id: initiator_id:
description: The ID of the initiator of the event. E.g., an ID of a user that triggered the event. description: The ID of the initiator of the event. E.g., an ID of a user that triggered the event.
type: string type: string
+4
View File
@@ -17,7 +17,11 @@ const (
EventActivityCodeRuleAdd EventActivityCode = "rule.add" EventActivityCodeRuleAdd EventActivityCode = "rule.add"
EventActivityCodeRuleDelete EventActivityCode = "rule.delete" EventActivityCodeRuleDelete EventActivityCode = "rule.delete"
EventActivityCodeRuleUpdate EventActivityCode = "rule.update" EventActivityCodeRuleUpdate EventActivityCode = "rule.update"
EventActivityCodeSetupkeyAdd EventActivityCode = "setupkey.add"
EventActivityCodeSetupkeyOveruse EventActivityCode = "setupkey.overuse"
EventActivityCodeSetupkeyPeerAdd EventActivityCode = "setupkey.peer.add" EventActivityCodeSetupkeyPeerAdd EventActivityCode = "setupkey.peer.add"
EventActivityCodeSetupkeyRevoke EventActivityCode = "setupkey.revoke"
EventActivityCodeSetupkeyUpdate EventActivityCode = "setupkey.update"
EventActivityCodeUserInvite EventActivityCode = "user.invite" EventActivityCodeUserInvite EventActivityCode = "user.invite"
EventActivityCodeUserJoin EventActivityCode = "user.join" EventActivityCodeUserJoin EventActivityCode = "user.join"
EventActivityCodeUserPeerAdd EventActivityCode = "user.peer.add" EventActivityCodeUserPeerAdd EventActivityCode = "user.peer.add"
+4 -4
View File
@@ -30,7 +30,7 @@ func NewSetupKeysHandler(accountManager server.AccountManager, authAudience stri
// CreateSetupKeyHandler is a POST requests that creates a new SetupKey // CreateSetupKeyHandler is a POST requests that creates a new SetupKey
func (h *SetupKeys) CreateSetupKeyHandler(w http.ResponseWriter, r *http.Request) { func (h *SetupKeys) CreateSetupKeyHandler(w http.ResponseWriter, r *http.Request) {
claims := h.jwtExtractor.ExtractClaimsFromRequestContext(r, h.authAudience) claims := h.jwtExtractor.ExtractClaimsFromRequestContext(r, h.authAudience)
account, _, err := h.accountManager.GetAccountFromToken(claims) account, user, err := h.accountManager.GetAccountFromToken(claims)
if err != nil { if err != nil {
util.WriteError(err, w) util.WriteError(err, w)
return return
@@ -61,7 +61,7 @@ func (h *SetupKeys) CreateSetupKeyHandler(w http.ResponseWriter, r *http.Request
} }
setupKey, err := h.accountManager.CreateSetupKey(account.Id, req.Name, server.SetupKeyType(req.Type), expiresIn, setupKey, err := h.accountManager.CreateSetupKey(account.Id, req.Name, server.SetupKeyType(req.Type), expiresIn,
req.AutoGroups, req.UsageLimit) req.AutoGroups, req.UsageLimit, user.Id)
if err != nil { if err != nil {
util.WriteError(err, w) util.WriteError(err, w)
return return
@@ -98,7 +98,7 @@ func (h *SetupKeys) GetSetupKeyHandler(w http.ResponseWriter, r *http.Request) {
// UpdateSetupKeyHandler is a PUT request to update server.SetupKey // UpdateSetupKeyHandler is a PUT request to update server.SetupKey
func (h *SetupKeys) UpdateSetupKeyHandler(w http.ResponseWriter, r *http.Request) { func (h *SetupKeys) UpdateSetupKeyHandler(w http.ResponseWriter, r *http.Request) {
claims := h.jwtExtractor.ExtractClaimsFromRequestContext(r, h.authAudience) claims := h.jwtExtractor.ExtractClaimsFromRequestContext(r, h.authAudience)
account, _, err := h.accountManager.GetAccountFromToken(claims) account, user, err := h.accountManager.GetAccountFromToken(claims)
if err != nil { if err != nil {
util.WriteError(err, w) util.WriteError(err, w)
return return
@@ -134,7 +134,7 @@ func (h *SetupKeys) UpdateSetupKeyHandler(w http.ResponseWriter, r *http.Request
newKey.Name = req.Name newKey.Name = req.Name
newKey.Id = keyID newKey.Id = keyID
newKey, err = h.accountManager.SaveSetupKey(account.Id, newKey) newKey, err = h.accountManager.SaveSetupKey(account.Id, newKey, user.Id)
if err != nil { if err != nil {
util.WriteError(err, w) util.WriteError(err, w)
return return
+41 -7
View File
@@ -2,6 +2,7 @@ package server
import ( import (
"github.com/google/uuid" "github.com/google/uuid"
"github.com/netbirdio/netbird/management/server/activity"
"github.com/netbirdio/netbird/management/server/status" "github.com/netbirdio/netbird/management/server/status"
"hash/fnv" "hash/fnv"
"strconv" "strconv"
@@ -107,12 +108,20 @@ func (key *SetupKey) Copy() *SetupKey {
} }
} }
// EventMeta returns activity event meta related to the peer
func (key *SetupKey) EventMeta() map[string]any {
return map[string]any{"name": key.Name, "type": key.Type, "key": key.HiddenCopy(1).Key}
}
// HiddenCopy returns a copy of the key with a Key value hidden with "*" and a 5 character prefix. // HiddenCopy returns a copy of the key with a Key value hidden with "*" and a 5 character prefix.
// E.g., "831F6*******************************" // E.g., "831F6*******************************"
func (key *SetupKey) HiddenCopy() *SetupKey { func (key *SetupKey) HiddenCopy(length int) *SetupKey {
k := key.Copy() k := key.Copy()
prefix := k.Key[0:5] prefix := k.Key[0:5]
k.Key = prefix + strings.Repeat("*", utf8.RuneCountInString(key.Key)-len(prefix)) if length > utf8.RuneCountInString(key.Key) {
length = utf8.RuneCountInString(key.Key) - len(prefix)
}
k.Key = prefix + strings.Repeat("*", length)
return k return k
} }
@@ -189,7 +198,7 @@ func Hash(s string) uint32 {
// CreateSetupKey generates a new setup key with a given name, type, list of groups IDs to auto-assign to peers registered with this key, // CreateSetupKey generates a new setup key with a given name, type, list of groups IDs to auto-assign to peers registered with this key,
// and adds it to the specified account. A list of autoGroups IDs can be empty. // and adds it to the specified account. A list of autoGroups IDs can be empty.
func (am *DefaultAccountManager) CreateSetupKey(accountID string, keyName string, keyType SetupKeyType, func (am *DefaultAccountManager) CreateSetupKey(accountID string, keyName string, keyType SetupKeyType,
expiresIn time.Duration, autoGroups []string, usageLimit int) (*SetupKey, error) { expiresIn time.Duration, autoGroups []string, usageLimit int, userID string) (*SetupKey, error) {
unlock := am.Store.AcquireAccountLock(accountID) unlock := am.Store.AcquireAccountLock(accountID)
defer unlock() defer unlock()
@@ -211,12 +220,23 @@ func (am *DefaultAccountManager) CreateSetupKey(accountID string, keyName string
setupKey := GenerateSetupKey(keyName, keyType, keyDuration, autoGroups, usageLimit) setupKey := GenerateSetupKey(keyName, keyType, keyDuration, autoGroups, usageLimit)
account.SetupKeys[setupKey.Key] = setupKey account.SetupKeys[setupKey.Key] = setupKey
err = am.Store.SaveAccount(account) err = am.Store.SaveAccount(account)
if err != nil { if err != nil {
return nil, status.Errorf(status.Internal, "failed adding account key") return nil, status.Errorf(status.Internal, "failed adding account key")
} }
_, err = am.eventStore.Save(&activity.Event{
Timestamp: time.Now(),
Activity: activity.SetupKeyCreated,
InitiatorID: userID,
TargetID: setupKey.Id,
AccountID: accountID,
Meta: setupKey.EventMeta(),
})
if err != nil {
return nil, err
}
return setupKey, nil return setupKey, nil
} }
@@ -224,7 +244,7 @@ func (am *DefaultAccountManager) CreateSetupKey(accountID string, keyName string
// Due to the unique nature of a SetupKey certain properties must not be overwritten // Due to the unique nature of a SetupKey certain properties must not be overwritten
// (e.g. the key itself, creation date, ID, etc). // (e.g. the key itself, creation date, ID, etc).
// These properties are overwritten: Name, AutoGroups, Revoked. The rest is copied from the existing key. // These properties are overwritten: Name, AutoGroups, Revoked. The rest is copied from the existing key.
func (am *DefaultAccountManager) SaveSetupKey(accountID string, keyToSave *SetupKey) (*SetupKey, error) { func (am *DefaultAccountManager) SaveSetupKey(accountID string, keyToSave *SetupKey, userID string) (*SetupKey, error) {
unlock := am.Store.AcquireAccountLock(accountID) unlock := am.Store.AcquireAccountLock(accountID)
defer unlock() defer unlock()
@@ -261,6 +281,20 @@ func (am *DefaultAccountManager) SaveSetupKey(accountID string, keyToSave *Setup
return nil, err return nil, err
} }
if !oldKey.Revoked && newKey.Revoked {
_, err = am.eventStore.Save(&activity.Event{
Timestamp: time.Now(),
Activity: activity.SetupKeyRevoked,
InitiatorID: userID,
TargetID: newKey.Id,
AccountID: accountID,
Meta: newKey.EventMeta(),
})
if err != nil {
return nil, err
}
}
return newKey, am.updateAccountPeers(account) return newKey, am.updateAccountPeers(account)
} }
@@ -282,7 +316,7 @@ func (am *DefaultAccountManager) ListSetupKeys(accountID, userID string) ([]*Set
for _, key := range account.SetupKeys { for _, key := range account.SetupKeys {
var k *SetupKey var k *SetupKey
if !user.IsAdmin() { if !user.IsAdmin() {
k = key.HiddenCopy() k = key.HiddenCopy(999)
} else { } else {
k = key.Copy() k = key.Copy()
} }
@@ -324,7 +358,7 @@ func (am *DefaultAccountManager) GetSetupKey(accountID, userID, keyID string) (*
} }
if !user.IsAdmin() { if !user.IsAdmin() {
foundKey = foundKey.HiddenCopy() foundKey = foundKey.HiddenCopy(999)
} }
return foundKey, nil return foundKey, nil