mirror of
https://github.com/netbirdio/netbird.git
synced 2025-08-19 11:20:18 +02:00
[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:
@@ -4068,6 +4068,31 @@ paths:
|
|||||||
"$ref": "#/components/responses/forbidden"
|
"$ref": "#/components/responses/forbidden"
|
||||||
'500':
|
'500':
|
||||||
"$ref": "#/components/responses/internal_error"
|
"$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:
|
/api/dns/nameservers:
|
||||||
get:
|
get:
|
||||||
summary: List all Nameserver Groups
|
summary: List all Nameserver Groups
|
||||||
|
@@ -19,7 +19,8 @@ type routersHandler struct {
|
|||||||
|
|
||||||
func addRouterEndpoints(routersManager routers.Manager, router *mux.Router) {
|
func addRouterEndpoints(routersManager routers.Manager, router *mux.Router) {
|
||||||
routersHandler := newRoutersHandler(routersManager)
|
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", routersHandler.createRouter).Methods("POST", "OPTIONS")
|
||||||
router.HandleFunc("/networks/{networkId}/routers/{routerId}", routersHandler.getRouter).Methods("GET", "OPTIONS")
|
router.HandleFunc("/networks/{networkId}/routers/{routerId}", routersHandler.getRouter).Methods("GET", "OPTIONS")
|
||||||
router.HandleFunc("/networks/{networkId}/routers/{routerId}", routersHandler.updateRouter).Methods("PUT", "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
|
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"]
|
networkID := mux.Vars(r)["networkId"]
|
||||||
routers, err := h.routersManager.GetAllRoutersInNetwork(r.Context(), accountID, userID, networkID)
|
routers, err := h.routersManager.GetAllRoutersInNetwork(r.Context(), accountID, userID, networkID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@@ -17,6 +17,7 @@ import (
|
|||||||
|
|
||||||
"github.com/netbirdio/netbird/management/domain"
|
"github.com/netbirdio/netbird/management/domain"
|
||||||
"github.com/netbirdio/netbird/management/server/geolocation"
|
"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/modules"
|
||||||
"github.com/netbirdio/netbird/management/server/permissions/operations"
|
"github.com/netbirdio/netbird/management/server/permissions/operations"
|
||||||
|
|
||||||
@@ -352,7 +353,7 @@ func (am *DefaultAccountManager) DeletePeer(ctx context.Context, accountID, peer
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = am.validatePeerDelete(ctx, accountID, peerID); err != nil {
|
if err = am.validatePeerDelete(ctx, transaction, accountID, peerID); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1543,7 +1544,7 @@ func ConvertSliceToMap(existingLabels []string) map[string]struct{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// validatePeerDelete checks if the peer can be deleted.
|
// 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)
|
linkedInIngressPorts, err := am.proxyController.IsPeerInIngressPorts(ctx, accountId, peerId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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)
|
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
|
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
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user