[management] Prevent deletion of peers linked to network routers (#3881)

- Prevent deletion of peers linked to network routers
- Add API endpoint to list all network routers
This commit is contained in:
Bethuel Mmbaga
2025-05-29 18:50:00 +03:00
committed by GitHub
parent 0492c1724a
commit 684501fd35
3 changed files with 77 additions and 3 deletions

View File

@@ -4068,6 +4068,31 @@ paths:
"$ref": "#/components/responses/forbidden"
'500':
"$ref": "#/components/responses/internal_error"
/api/networks/routers:
get:
summary: List all Network Routers
description: Returns a list of all routers in a network
tags: [ Networks ]
security:
- BearerAuth: [ ]
- TokenAuth: [ ]
responses:
'200':
description: A JSON Array of Routers
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/NetworkRouter'
'400':
"$ref": "#/components/responses/bad_request"
'401':
"$ref": "#/components/responses/requires_authentication"
'403':
"$ref": "#/components/responses/forbidden"
'500':
"$ref": "#/components/responses/internal_error"
/api/dns/nameservers:
get:
summary: List all Nameserver Groups

View File

@@ -19,7 +19,8 @@ type routersHandler struct {
func addRouterEndpoints(routersManager routers.Manager, router *mux.Router) {
routersHandler := newRoutersHandler(routersManager)
router.HandleFunc("/networks/{networkId}/routers", routersHandler.getAllRouters).Methods("GET", "OPTIONS")
router.HandleFunc("/networks/routers", routersHandler.getAllRouters).Methods("GET", "OPTIONS")
router.HandleFunc("/networks/{networkId}/routers", routersHandler.getNetworkRouters).Methods("GET", "OPTIONS")
router.HandleFunc("/networks/{networkId}/routers", routersHandler.createRouter).Methods("POST", "OPTIONS")
router.HandleFunc("/networks/{networkId}/routers/{routerId}", routersHandler.getRouter).Methods("GET", "OPTIONS")
router.HandleFunc("/networks/{networkId}/routers/{routerId}", routersHandler.updateRouter).Methods("PUT", "OPTIONS")
@@ -41,6 +42,31 @@ func (h *routersHandler) getAllRouters(w http.ResponseWriter, r *http.Request) {
accountID, userID := userAuth.AccountId, userAuth.UserId
routersMap, err := h.routersManager.GetAllRoutersInAccount(r.Context(), accountID, userID)
if err != nil {
util.WriteError(r.Context(), err, w)
return
}
routersResponse := make([]*api.NetworkRouter, 0)
for _, routers := range routersMap {
for _, router := range routers {
routersResponse = append(routersResponse, router.ToAPIResponse())
}
}
util.WriteJSONObject(r.Context(), w, routersResponse)
}
func (h *routersHandler) getNetworkRouters(w http.ResponseWriter, r *http.Request) {
userAuth, err := nbcontext.GetUserAuthFromContext(r.Context())
if err != nil {
util.WriteError(r.Context(), err, w)
return
}
accountID, userID := userAuth.AccountId, userAuth.UserId
networkID := mux.Vars(r)["networkId"]
routers, err := h.routersManager.GetAllRoutersInNetwork(r.Context(), accountID, userID, networkID)
if err != nil {

View File

@@ -17,6 +17,7 @@ import (
"github.com/netbirdio/netbird/management/domain"
"github.com/netbirdio/netbird/management/server/geolocation"
routerTypes "github.com/netbirdio/netbird/management/server/networks/routers/types"
"github.com/netbirdio/netbird/management/server/permissions/modules"
"github.com/netbirdio/netbird/management/server/permissions/operations"
@@ -352,7 +353,7 @@ func (am *DefaultAccountManager) DeletePeer(ctx context.Context, accountID, peer
return err
}
if err = am.validatePeerDelete(ctx, accountID, peerID); err != nil {
if err = am.validatePeerDelete(ctx, transaction, accountID, peerID); err != nil {
return err
}
@@ -1543,7 +1544,7 @@ func ConvertSliceToMap(existingLabels []string) map[string]struct{} {
}
// validatePeerDelete checks if the peer can be deleted.
func (am *DefaultAccountManager) validatePeerDelete(ctx context.Context, accountId, peerId string) error {
func (am *DefaultAccountManager) validatePeerDelete(ctx context.Context, transaction store.Store, accountId, peerId string) error {
linkedInIngressPorts, err := am.proxyController.IsPeerInIngressPorts(ctx, accountId, peerId)
if err != nil {
return err
@@ -1553,5 +1554,27 @@ func (am *DefaultAccountManager) validatePeerDelete(ctx context.Context, account
return status.Errorf(status.PreconditionFailed, "peer is linked to ingress ports: %s", peerId)
}
linked, router := isPeerLinkedToNetworkRouter(ctx, transaction, accountId, peerId)
if linked {
return status.Errorf(status.PreconditionFailed, "peer is linked to a network router: %s", router.ID)
}
return nil
}
// isPeerLinkedToNetworkRouter checks if a peer is linked to any network router in the account.
func isPeerLinkedToNetworkRouter(ctx context.Context, transaction store.Store, accountID string, peerID string) (bool, *routerTypes.NetworkRouter) {
routers, err := transaction.GetNetworkRoutersByAccountID(ctx, store.LockingStrengthShare, accountID)
if err != nil {
log.WithContext(ctx).Errorf("error retrieving network routers while checking peer linkage: %v", err)
return false, nil
}
for _, router := range routers {
if router.Peer == peerID {
return true, router
}
}
return false, nil
}