Skip to content

Commit d80d47a

Browse files
authored
[management] Add peer disapproval reason (#4468)
1 parent 96f71ff commit d80d47a

File tree

9 files changed

+61
-25
lines changed

9 files changed

+61
-25
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ require (
6262
github.com/miekg/dns v1.1.59
6363
github.com/mitchellh/hashstructure/v2 v2.0.2
6464
github.com/nadoo/ipset v0.5.0
65-
github.com/netbirdio/management-integrations/integrations v0.0.0-20251010134843-7af36217ac1f
65+
github.com/netbirdio/management-integrations/integrations v0.0.0-20251022080146-b1caade69396
6666
github.com/netbirdio/signal-dispatcher/dispatcher v0.0.0-20250805121659-6b4ac470ca45
6767
github.com/okta/okta-sdk-golang/v2 v2.18.0
6868
github.com/oschwald/maxminddb-golang v1.12.0

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -503,8 +503,8 @@ github.com/netbirdio/go-netroute v0.0.0-20240611143515-f59b0e1d3944 h1:TDtJKmM6S
503503
github.com/netbirdio/go-netroute v0.0.0-20240611143515-f59b0e1d3944/go.mod h1:sHA6TRxjQ6RLbnI+3R4DZo2Eseg/iKiPRfNmcuNySVQ=
504504
github.com/netbirdio/ice/v4 v4.0.0-20250908184934-6202be846b51 h1:Ov4qdafATOgGMB1wbSuh+0aAHcwz9hdvB6VZjh1mVMI=
505505
github.com/netbirdio/ice/v4 v4.0.0-20250908184934-6202be846b51/go.mod h1:ZSIbPdBn5hePO8CpF1PekH2SfpTxg1PDhEwtbqZS7R8=
506-
github.com/netbirdio/management-integrations/integrations v0.0.0-20251010134843-7af36217ac1f h1:XIpRDlpPz3zFUkpwaqDRHjwpQRsf2ZKHggoex1MTafs=
507-
github.com/netbirdio/management-integrations/integrations v0.0.0-20251010134843-7af36217ac1f/go.mod h1:v0nUbbHbuQnqR7yKIYnKzsLBCswLtp2JctmKYmGgVhc=
506+
github.com/netbirdio/management-integrations/integrations v0.0.0-20251022080146-b1caade69396 h1:aXHS63QWf0Z5fDN19Swl6npdJjGMyXthAvvgW7rbKJQ=
507+
github.com/netbirdio/management-integrations/integrations v0.0.0-20251022080146-b1caade69396/go.mod h1:v0nUbbHbuQnqR7yKIYnKzsLBCswLtp2JctmKYmGgVhc=
508508
github.com/netbirdio/service v0.0.0-20240911161631-f62744f42502 h1:3tHlFmhTdX9axERMVN63dqyFqnvuD+EMJHzM7mNGON8=
509509
github.com/netbirdio/service v0.0.0-20240911161631-f62744f42502/go.mod h1:CIMRFEJVL+0DS1a3Nx06NaMn4Dz63Ng6O7dl0qH0zVM=
510510
github.com/netbirdio/signal-dispatcher/dispatcher v0.0.0-20250805121659-6b4ac470ca45 h1:ujgviVYmx243Ksy7NdSwrdGPSRNE3pb8kEDSpH0QuAQ=

management/server/account/manager.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ type Manager interface {
109109
GetIdpManager() idp.Manager
110110
UpdateIntegratedValidator(ctx context.Context, accountID, userID, validator string, groups []string) error
111111
GroupValidation(ctx context.Context, accountId string, groups []string) (bool, error)
112-
GetValidatedPeers(ctx context.Context, accountID string) (map[string]struct{}, error)
112+
GetValidatedPeers(ctx context.Context, accountID string) (map[string]struct{}, map[string]string, error)
113113
SyncAndMarkPeer(ctx context.Context, accountID string, peerPubKey string, meta nbpeer.PeerSystemMeta, realIP net.IP) (*nbpeer.Peer, *types.NetworkMap, []*posture.Checks, error)
114114
OnPeerDisconnected(ctx context.Context, accountID string, peerPubKey string) error
115115
SyncPeerMeta(ctx context.Context, peerPubKey string, meta nbpeer.PeerSystemMeta) error

management/server/http/handlers/peers/peers_handler.go

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -78,15 +78,17 @@ func (h *Handler) getPeer(ctx context.Context, accountID, peerID, userID string,
7878
grps, _ := h.accountManager.GetPeerGroups(ctx, accountID, peerID)
7979
grpsInfoMap := groups.ToGroupsInfoMap(grps, 0)
8080

81-
validPeers, err := h.accountManager.GetValidatedPeers(ctx, accountID)
81+
validPeers, invalidPeers, err := h.accountManager.GetValidatedPeers(ctx, accountID)
8282
if err != nil {
8383
log.WithContext(ctx).Errorf("failed to list approved peers: %v", err)
8484
util.WriteError(ctx, fmt.Errorf("internal error"), w)
8585
return
8686
}
8787

8888
_, valid := validPeers[peer.ID]
89-
util.WriteJSONObject(ctx, w, toSinglePeerResponse(peerToReturn, grpsInfoMap[peerID], dnsDomain, valid))
89+
reason := invalidPeers[peer.ID]
90+
91+
util.WriteJSONObject(ctx, w, toSinglePeerResponse(peerToReturn, grpsInfoMap[peerID], dnsDomain, valid, reason))
9092
}
9193

9294
func (h *Handler) updatePeer(ctx context.Context, accountID, userID, peerID string, w http.ResponseWriter, r *http.Request) {
@@ -147,16 +149,17 @@ func (h *Handler) updatePeer(ctx context.Context, accountID, userID, peerID stri
147149

148150
grpsInfoMap := groups.ToGroupsInfoMap(peerGroups, 0)
149151

150-
validPeers, err := h.accountManager.GetValidatedPeers(ctx, accountID)
152+
validPeers, invalidPeers, err := h.accountManager.GetValidatedPeers(ctx, accountID)
151153
if err != nil {
152-
log.WithContext(ctx).Errorf("failed to list appreoved peers: %v", err)
154+
log.WithContext(ctx).Errorf("failed to get validated peers: %v", err)
153155
util.WriteError(ctx, fmt.Errorf("internal error"), w)
154156
return
155157
}
156158

157159
_, valid := validPeers[peer.ID]
160+
reason := invalidPeers[peer.ID]
158161

159-
util.WriteJSONObject(r.Context(), w, toSinglePeerResponse(peer, grpsInfoMap[peerID], dnsDomain, valid))
162+
util.WriteJSONObject(r.Context(), w, toSinglePeerResponse(peer, grpsInfoMap[peerID], dnsDomain, valid, reason))
160163
}
161164

162165
func (h *Handler) deletePeer(ctx context.Context, accountID, userID string, peerID string, w http.ResponseWriter) {
@@ -240,22 +243,25 @@ func (h *Handler) GetAllPeers(w http.ResponseWriter, r *http.Request) {
240243
respBody = append(respBody, toPeerListItemResponse(peerToReturn, grpsInfoMap[peer.ID], dnsDomain, 0))
241244
}
242245

243-
validPeersMap, err := h.accountManager.GetValidatedPeers(r.Context(), accountID)
246+
validPeersMap, invalidPeersMap, err := h.accountManager.GetValidatedPeers(r.Context(), accountID)
244247
if err != nil {
245-
log.WithContext(r.Context()).Errorf("failed to list appreoved peers: %v", err)
248+
log.WithContext(r.Context()).Errorf("failed to get validated peers: %v", err)
246249
util.WriteError(r.Context(), fmt.Errorf("internal error"), w)
247250
return
248251
}
249-
h.setApprovalRequiredFlag(respBody, validPeersMap)
252+
h.setApprovalRequiredFlag(respBody, validPeersMap, invalidPeersMap)
250253

251254
util.WriteJSONObject(r.Context(), w, respBody)
252255
}
253256

254-
func (h *Handler) setApprovalRequiredFlag(respBody []*api.PeerBatch, approvedPeersMap map[string]struct{}) {
257+
func (h *Handler) setApprovalRequiredFlag(respBody []*api.PeerBatch, validPeersMap map[string]struct{}, invalidPeersMap map[string]string) {
255258
for _, peer := range respBody {
256-
_, ok := approvedPeersMap[peer.Id]
259+
_, ok := validPeersMap[peer.Id]
257260
if !ok {
258261
peer.ApprovalRequired = true
262+
263+
reason := invalidPeersMap[peer.Id]
264+
peer.DisapprovalReason = &reason
259265
}
260266
}
261267
}
@@ -304,7 +310,7 @@ func (h *Handler) GetAccessiblePeers(w http.ResponseWriter, r *http.Request) {
304310
}
305311
}
306312

307-
validPeers, err := h.accountManager.GetValidatedPeers(r.Context(), accountID)
313+
validPeers, _, err := h.accountManager.GetValidatedPeers(r.Context(), accountID)
308314
if err != nil {
309315
log.WithContext(r.Context()).Errorf("failed to list approved peers: %v", err)
310316
util.WriteError(r.Context(), fmt.Errorf("internal error"), w)
@@ -430,13 +436,13 @@ func peerToAccessiblePeer(peer *nbpeer.Peer, dnsDomain string) api.AccessiblePee
430436
}
431437
}
432438

433-
func toSinglePeerResponse(peer *nbpeer.Peer, groupsInfo []api.GroupMinimum, dnsDomain string, approved bool) *api.Peer {
439+
func toSinglePeerResponse(peer *nbpeer.Peer, groupsInfo []api.GroupMinimum, dnsDomain string, approved bool, reason string) *api.Peer {
434440
osVersion := peer.Meta.OSVersion
435441
if osVersion == "" {
436442
osVersion = peer.Meta.Core
437443
}
438444

439-
return &api.Peer{
445+
apiPeer := &api.Peer{
440446
CreatedAt: peer.CreatedAt,
441447
Id: peer.ID,
442448
Name: peer.Name,
@@ -465,6 +471,12 @@ func toSinglePeerResponse(peer *nbpeer.Peer, groupsInfo []api.GroupMinimum, dnsD
465471
InactivityExpirationEnabled: peer.InactivityExpirationEnabled,
466472
Ephemeral: peer.Ephemeral,
467473
}
474+
475+
if !approved {
476+
apiPeer.DisapprovalReason = &reason
477+
}
478+
479+
return apiPeer
468480
}
469481

470482
func toPeerListItemResponse(peer *nbpeer.Peer, groupsInfo []api.GroupMinimum, dnsDomain string, accessiblePeersCount int) *api.PeerBatch {

management/server/integrated_validator.go

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,28 +88,38 @@ func (am *DefaultAccountManager) GroupValidation(ctx context.Context, accountID
8888
return true, nil
8989
}
9090

91-
func (am *DefaultAccountManager) GetValidatedPeers(ctx context.Context, accountID string) (map[string]struct{}, error) {
91+
func (am *DefaultAccountManager) GetValidatedPeers(ctx context.Context, accountID string) (map[string]struct{}, map[string]string, error) {
9292
var err error
9393
var groups []*types.Group
9494
var peers []*nbpeer.Peer
9595
var settings *types.Settings
9696

9797
groups, err = am.Store.GetAccountGroups(ctx, store.LockingStrengthNone, accountID)
9898
if err != nil {
99-
return nil, err
99+
return nil, nil, err
100100
}
101101

102102
peers, err = am.Store.GetAccountPeers(ctx, store.LockingStrengthNone, accountID, "", "")
103103
if err != nil {
104-
return nil, err
104+
return nil, nil, err
105105
}
106106

107107
settings, err = am.Store.GetAccountSettings(ctx, store.LockingStrengthNone, accountID)
108108
if err != nil {
109-
return nil, err
109+
return nil, nil, err
110110
}
111111

112-
return am.integratedPeerValidator.GetValidatedPeers(ctx, accountID, groups, peers, settings.Extra)
112+
validPeers, err := am.integratedPeerValidator.GetValidatedPeers(ctx, accountID, groups, peers, settings.Extra)
113+
if err != nil {
114+
return nil, nil, err
115+
}
116+
117+
invalidPeers, err := am.integratedPeerValidator.GetInvalidPeers(ctx, accountID, settings.Extra)
118+
if err != nil {
119+
return nil, nil, err
120+
}
121+
122+
return validPeers, invalidPeers, nil
113123
}
114124

115125
type MockIntegratedValidator struct {
@@ -136,6 +146,10 @@ func (a MockIntegratedValidator) GetValidatedPeers(_ context.Context, accountID
136146
return validatedPeers, nil
137147
}
138148

149+
func (a MockIntegratedValidator) GetInvalidPeers(_ context.Context, accountID string, extraSettings *types.ExtraSettings) (map[string]string, error) {
150+
return make(map[string]string), nil
151+
}
152+
139153
func (MockIntegratedValidator) PreparePeer(_ context.Context, accountID string, peer *nbpeer.Peer, peersGroup []string, extraSettings *types.ExtraSettings, temporary bool) *nbpeer.Peer {
140154
return peer
141155
}

management/server/integrations/integrated_validator/interface.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ type IntegratedValidator interface {
1515
PreparePeer(ctx context.Context, accountID string, peer *nbpeer.Peer, peersGroup []string, extraSettings *types.ExtraSettings, temporary bool) *nbpeer.Peer
1616
IsNotValidPeer(ctx context.Context, accountID string, peer *nbpeer.Peer, peersGroup []string, extraSettings *types.ExtraSettings) (bool, bool, error)
1717
GetValidatedPeers(ctx context.Context, accountID string, groups []*types.Group, peers []*nbpeer.Peer, extraSettings *types.ExtraSettings) (map[string]struct{}, error)
18+
GetInvalidPeers(ctx context.Context, accountID string, extraSettings *types.ExtraSettings) (map[string]string, error)
1819
PeerDeleted(ctx context.Context, accountID, peerID string, extraSettings *types.ExtraSettings) error
1920
SetPeerInvalidationListener(fn func(accountID string, peerIDs []string))
2021
Stop(ctx context.Context)

management/server/mock_server/account_mock.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -189,17 +189,17 @@ func (am *MockAccountManager) OnPeerDisconnected(_ context.Context, accountID st
189189
panic("implement me")
190190
}
191191

192-
func (am *MockAccountManager) GetValidatedPeers(ctx context.Context, accountID string) (map[string]struct{}, error) {
192+
func (am *MockAccountManager) GetValidatedPeers(ctx context.Context, accountID string) (map[string]struct{}, map[string]string, error) {
193193
account, err := am.GetAccountFunc(ctx, accountID)
194194
if err != nil {
195-
return nil, err
195+
return nil, nil, err
196196
}
197197

198198
approvedPeers := make(map[string]struct{})
199199
for id := range account.Peers {
200200
approvedPeers[id] = struct{}{}
201201
}
202-
return approvedPeers, nil
202+
return approvedPeers, nil, nil
203203
}
204204

205205
// GetGroup mock implementation of GetGroup from server.AccountManager interface

shared/management/http/api/openapi.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,9 @@ components:
463463
description: (Cloud only) Indicates whether peer needs approval
464464
type: boolean
465465
example: true
466+
disapproval_reason:
467+
description: (Cloud only) Reason why the peer requires approval
468+
type: string
466469
country_code:
467470
$ref: '#/components/schemas/CountryCode'
468471
city_name:

shared/management/http/api/types.gen.go

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)