Skip to content

Commit

Permalink
Merge pull request #1341 from netbirdio/feature/peer-approval
Browse files Browse the repository at this point in the history
Add peer and settings validation
  • Loading branch information
pascal-fischer authored Dec 5, 2023
2 parents 755ffcf + 0d2db4b commit 3f8b500
Show file tree
Hide file tree
Showing 34 changed files with 739 additions and 423 deletions.
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ require (
github.com/miekg/dns v1.1.43
github.com/mitchellh/hashstructure/v2 v2.0.2
github.com/nadoo/ipset v0.5.0
github.com/netbirdio/management-integrations/integrations v0.0.0-20231027143200-a966bce7db88
github.com/netbirdio/management-integrations/additions v0.0.0-20231204152258-2328ed53de48
github.com/netbirdio/management-integrations/integrations v0.0.0-20231128140355-566178608e97
github.com/okta/okta-sdk-golang/v2 v2.18.0
github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/pion/logging v0.2.2
Expand Down
6 changes: 4 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -495,8 +495,10 @@ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRW
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/nadoo/ipset v0.5.0 h1:5GJUAuZ7ITQQQGne5J96AmFjRtI8Avlbk6CabzYWVUc=
github.com/nadoo/ipset v0.5.0/go.mod h1:rYF5DQLRGGoQ8ZSWeK+6eX5amAuPqwFkWjhQlEITGJQ=
github.com/netbirdio/management-integrations/integrations v0.0.0-20231027143200-a966bce7db88 h1:zhe8qseauBuYOS910jpl5sv8Tb+36zxQPXrwYXqll0g=
github.com/netbirdio/management-integrations/integrations v0.0.0-20231027143200-a966bce7db88/go.mod h1:KSqjzHcqlodTWiuap5lRXxt5KT3vtYRoksL0KIrTK40=
github.com/netbirdio/management-integrations/additions v0.0.0-20231204152258-2328ed53de48 h1:TEaiKhkxwIFA2AmIj/7x9X/6zlXjV68Vs6Wclew1oTs=
github.com/netbirdio/management-integrations/additions v0.0.0-20231204152258-2328ed53de48/go.mod h1:31FhBNvQ+riHEIu6LSTmqr8IeuSIsGfQffqV4LFmbwA=
github.com/netbirdio/management-integrations/integrations v0.0.0-20231128140355-566178608e97 h1:2VmrReIXt4W45l7O93kzoTq7Bpn3CDGKhBwnqih0eao=
github.com/netbirdio/management-integrations/integrations v0.0.0-20231128140355-566178608e97/go.mod h1:eRv50kd3bXd2y59HK3OY4RI8YUL0JEN290D5dqW4llY=
github.com/netbirdio/service v0.0.0-20230215170314-b923b89432b0 h1:hirFRfx3grVA/9eEyjME5/z3nxdJlN9kfQpvWWPk32g=
github.com/netbirdio/service v0.0.0-20230215170314-b923b89432b0/go.mod h1:CIMRFEJVL+0DS1a3Nx06NaMn4Dz63Ng6O7dl0qH0zVM=
github.com/netbirdio/systray v0.0.0-20231030152038-ef1ed2a27949 h1:xbWM9BU6mwZZLHxEjxIX/V8Hv3HurQt4mReIE4mY4DM=
Expand Down
77 changes: 52 additions & 25 deletions management/server/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,18 @@ import (

"github.com/eko/gocache/v3/cache"
cacheStore "github.com/eko/gocache/v3/store"
"github.com/netbirdio/management-integrations/additions"
gocache "github.com/patrickmn/go-cache"
"github.com/rs/xid"
log "github.com/sirupsen/logrus"

"github.com/netbirdio/netbird/base62"
nbdns "github.com/netbirdio/netbird/dns"
"github.com/netbirdio/netbird/management/server/account"
"github.com/netbirdio/netbird/management/server/activity"
"github.com/netbirdio/netbird/management/server/idp"
"github.com/netbirdio/netbird/management/server/jwtclaims"
nbpeer "github.com/netbirdio/netbird/management/server/peer"
"github.com/netbirdio/netbird/management/server/status"
"github.com/netbirdio/netbird/route"
)
Expand Down Expand Up @@ -68,13 +71,13 @@ type AccountManager interface {
MarkPATUsed(tokenID string) error
GetUser(claims jwtclaims.AuthorizationClaims) (*User, error)
ListUsers(accountID string) ([]*User, error)
GetPeers(accountID, userID string) ([]*Peer, error)
GetPeers(accountID, userID string) ([]*nbpeer.Peer, error)
MarkPeerConnected(peerKey string, connected bool) error
DeletePeer(accountID, peerID, userID string) error
UpdatePeer(accountID, userID string, peer *Peer) (*Peer, error)
UpdatePeer(accountID, userID string, peer *nbpeer.Peer) (*nbpeer.Peer, error)
GetNetworkMap(peerID string) (*NetworkMap, error)
GetPeerNetwork(peerID string) (*Network, error)
AddPeer(setupKey, userID string, peer *Peer) (*Peer, *NetworkMap, error)
AddPeer(setupKey, userID string, peer *nbpeer.Peer) (*nbpeer.Peer, *NetworkMap, error)
CreatePAT(accountID string, initiatorUserID string, targetUserID string, tokenName string, expiresIn int) (*PersonalAccessTokenGenerated, error)
DeletePAT(accountID string, initiatorUserID string, targetUserID string, tokenID string) error
GetPAT(accountID string, initiatorUserID string, targetUserID string, tokenID string) (*PersonalAccessToken, error)
Expand Down Expand Up @@ -106,10 +109,10 @@ type AccountManager interface {
GetEvents(accountID, userID string) ([]*activity.Event, error)
GetDNSSettings(accountID string, userID string) (*DNSSettings, error)
SaveDNSSettings(accountID string, userID string, dnsSettingsToSave *DNSSettings) error
GetPeer(accountID, peerID, userID string) (*Peer, error)
GetPeer(accountID, peerID, userID string) (*nbpeer.Peer, error)
UpdateAccountSettings(accountID, userID string, newSettings *Settings) (*Account, error)
LoginPeer(login PeerLogin) (*Peer, *NetworkMap, error) // used by peer gRPC API
SyncPeer(sync PeerSync) (*Peer, *NetworkMap, error) // used by peer gRPC API
LoginPeer(login PeerLogin) (*nbpeer.Peer, *NetworkMap, error) // used by peer gRPC API
SyncPeer(sync PeerSync) (*nbpeer.Peer, *NetworkMap, error) // used by peer gRPC API
GetAllConnectedPeers() (map[string]struct{}, error)
GetExternalCacheManager() ExternalCacheManager
}
Expand Down Expand Up @@ -159,17 +162,24 @@ type Settings struct {

// JWTGroupsClaimName from which we extract groups name to add it to account groups
JWTGroupsClaimName string

// Extra is a dictionary of Account settings
Extra *account.ExtraSettings `gorm:"embedded;embeddedPrefix:extra_"`
}

// Copy copies the Settings struct
func (s *Settings) Copy() *Settings {
return &Settings{
settings := &Settings{
PeerLoginExpirationEnabled: s.PeerLoginExpirationEnabled,
PeerLoginExpiration: s.PeerLoginExpiration,
JWTGroupsEnabled: s.JWTGroupsEnabled,
JWTGroupsClaimName: s.JWTGroupsClaimName,
GroupsPropagationEnabled: s.GroupsPropagationEnabled,
}
if s.Extra != nil {
settings.Extra = s.Extra.Copy()
}
return settings
}

// Account represents a unique account of the system
Expand All @@ -185,8 +195,8 @@ type Account struct {
SetupKeys map[string]*SetupKey `gorm:"-"`
SetupKeysG []SetupKey `json:"-" gorm:"foreignKey:AccountID;references:id"`
Network *Network `gorm:"embedded;embeddedPrefix:network_"`
Peers map[string]*Peer `gorm:"-"`
PeersG []Peer `json:"-" gorm:"foreignKey:AccountID;references:id"`
Peers map[string]*nbpeer.Peer `gorm:"-"`
PeersG []nbpeer.Peer `json:"-" gorm:"foreignKey:AccountID;references:id"`
Users map[string]*User `gorm:"-"`
UsersG []User `json:"-" gorm:"foreignKey:AccountID;references:id"`
Groups map[string]*Group `gorm:"-"`
Expand Down Expand Up @@ -221,7 +231,7 @@ type UserInfo struct {
// getRoutesToSync returns the enabled routes for the peer ID and the routes
// from the ACL peers that have distribution groups associated with the peer ID.
// Please mind, that the returned route.Route objects will contain Peer.Key instead of Peer.ID.
func (a *Account) getRoutesToSync(peerID string, aclPeers []*Peer) []*route.Route {
func (a *Account) getRoutesToSync(peerID string, aclPeers []*nbpeer.Peer) []*route.Route {
routes, peerDisabledRoutes := a.getRoutingPeerRoutes(peerID)
peerRoutesMembership := make(lookupMap)
for _, r := range append(routes, peerDisabledRoutes...) {
Expand Down Expand Up @@ -345,10 +355,22 @@ func (a *Account) GetGroup(groupID string) *Group {

// GetPeerNetworkMap returns a group by ID if exists, nil otherwise
func (a *Account) GetPeerNetworkMap(peerID, dnsDomain string) *NetworkMap {
peer := a.Peers[peerID]
if peer == nil {
return &NetworkMap{
Network: a.Network.Copy(),
}
}
validatedPeers := additions.ValidatePeers([]*nbpeer.Peer{peer})
if len(validatedPeers) == 0 {
return &NetworkMap{
Network: a.Network.Copy(),
}
}
aclPeers, firewallRules := a.getPeerConnectionResources(peerID)
// exclude expired peers
var peersToConnect []*Peer
var expiredPeers []*Peer
var peersToConnect []*nbpeer.Peer
var expiredPeers []*nbpeer.Peer
for _, p := range aclPeers {
expired, _ := p.LoginExpired(a.Settings.PeerLoginExpiration)
if a.Settings.PeerLoginExpirationEnabled && expired {
Expand Down Expand Up @@ -386,8 +408,8 @@ func (a *Account) GetPeerNetworkMap(peerID, dnsDomain string) *NetworkMap {
}

// GetExpiredPeers returns peers that have been expired
func (a *Account) GetExpiredPeers() []*Peer {
var peers []*Peer
func (a *Account) GetExpiredPeers() []*nbpeer.Peer {
var peers []*nbpeer.Peer
for _, peer := range a.GetPeersWithExpiration() {
expired, _ := peer.LoginExpired(a.Settings.PeerLoginExpiration)
if expired {
Expand Down Expand Up @@ -426,8 +448,8 @@ func (a *Account) GetNextPeerExpiration() (time.Duration, bool) {
}

// GetPeersWithExpiration returns a list of peers that have Peer.LoginExpirationEnabled set to true and that were added by a user
func (a *Account) GetPeersWithExpiration() []*Peer {
peers := make([]*Peer, 0)
func (a *Account) GetPeersWithExpiration() []*nbpeer.Peer {
peers := make([]*nbpeer.Peer, 0)
for _, peer := range a.Peers {
if peer.LoginExpirationEnabled && peer.AddedWithSSOLogin() {
peers = append(peers, peer)
Expand All @@ -437,8 +459,8 @@ func (a *Account) GetPeersWithExpiration() []*Peer {
}

// GetPeers returns a list of all Account peers
func (a *Account) GetPeers() []*Peer {
var peers []*Peer
func (a *Account) GetPeers() []*nbpeer.Peer {
var peers []*nbpeer.Peer
for _, peer := range a.Peers {
peers = append(peers, peer)
}
Expand All @@ -452,7 +474,7 @@ func (a *Account) UpdateSettings(update *Settings) *Account {
}

// UpdatePeer saves new or replaces existing peer
func (a *Account) UpdatePeer(update *Peer) {
func (a *Account) UpdatePeer(update *nbpeer.Peer) {
a.Peers[update.ID] = update
}

Expand Down Expand Up @@ -481,7 +503,7 @@ func (a *Account) DeletePeer(peerID string) {

// FindPeerByPubKey looks for a Peer by provided WireGuard public key in the Account or returns error if it wasn't found.
// It will return an object copy of the peer.
func (a *Account) FindPeerByPubKey(peerPubKey string) (*Peer, error) {
func (a *Account) FindPeerByPubKey(peerPubKey string) (*nbpeer.Peer, error) {
for _, peer := range a.Peers {
if peer.Key == peerPubKey {
return peer.Copy(), nil
Expand All @@ -492,8 +514,8 @@ func (a *Account) FindPeerByPubKey(peerPubKey string) (*Peer, error) {
}

// FindUserPeers returns a list of peers that user owns (created)
func (a *Account) FindUserPeers(userID string) ([]*Peer, error) {
peers := make([]*Peer, 0)
func (a *Account) FindUserPeers(userID string) ([]*nbpeer.Peer, error) {
peers := make([]*nbpeer.Peer, 0)
for _, peer := range a.Peers {
if peer.UserID == userID {
peers = append(peers, peer)
Expand Down Expand Up @@ -585,7 +607,7 @@ func (a *Account) getPeerDNSLabels() lookupMap {
}

func (a *Account) Copy() *Account {
peers := map[string]*Peer{}
peers := map[string]*nbpeer.Peer{}
for id, peer := range a.Peers {
peers[id] = peer.Copy()
}
Expand Down Expand Up @@ -662,7 +684,7 @@ func (a *Account) GetGroupAll() (*Group, error) {
}

// GetPeer looks up a Peer by ID
func (a *Account) GetPeer(peerID string) *Peer {
func (a *Account) GetPeer(peerID string) *nbpeer.Peer {
return a.Peers[peerID]
}

Expand Down Expand Up @@ -872,6 +894,11 @@ func (am *DefaultAccountManager) UpdateAccountSettings(accountID, userID string,
return nil, err
}

err = additions.ValidateExtraSettings(newSettings.Extra, account.Settings.Extra, account.Peers, userID, accountID, am.eventStore)
if err != nil {
return nil, err
}

user, err := account.FindUser(userID)
if err != nil {
return nil, err
Expand Down Expand Up @@ -1698,7 +1725,7 @@ func newAccountWithId(accountID, userID, domain string) *Account {
log.Debugf("creating new account")

network := NewNetwork()
peers := make(map[string]*Peer)
peers := make(map[string]*nbpeer.Peer)
users := make(map[string]*User)
routes := make(map[string]*route.Route)
setupKeys := map[string]*SetupKey{}
Expand Down
13 changes: 13 additions & 0 deletions management/server/account/account.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package account

type ExtraSettings struct {
// PeerApprovalEnabled enables or disables the need for peers bo be approved by an administrator
PeerApprovalEnabled bool
}

// Copy copies the ExtraSettings struct
func (e *ExtraSettings) Copy() *ExtraSettings {
return &ExtraSettings{
PeerApprovalEnabled: e.PeerApprovalEnabled,
}
}
Loading

0 comments on commit 3f8b500

Please sign in to comment.