mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-18 08:16:39 +00:00
Use Peer.ID instead of Peer.Key as peer identifier (#664)
Replace Peer.Key as internal identifier with a randomly generated Peer.ID in the Management service. Every group now references peers by ID instead of a public key. Every route now references peers by ID instead of a public key. FileStore does store.json file migration on startup by generating Peer.ID and replacing all Peer.Key identifier references .
This commit is contained in:
@@ -96,10 +96,16 @@ func (h *Groups) UpdateGroupHandler(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
var peers []string
|
||||
if req.Peers == nil {
|
||||
peers = make([]string, 0)
|
||||
} else {
|
||||
peers = *req.Peers
|
||||
}
|
||||
group := server.Group{
|
||||
ID: groupID,
|
||||
Name: *req.Name,
|
||||
Peers: peerIPsToKeys(account, req.Peers),
|
||||
Peers: peers,
|
||||
}
|
||||
|
||||
if err := h.accountManager.SaveGroup(account.Id, user.Id, &group); err != nil {
|
||||
@@ -191,10 +197,9 @@ func (h *Groups) PatchGroupHandler(w http.ResponseWriter, r *http.Request) {
|
||||
Values: peerKeys,
|
||||
})
|
||||
case api.GroupPatchOperationOpAdd:
|
||||
peerKeys := peerIPsToKeys(account, &patch.Value)
|
||||
operations = append(operations, server.GroupUpdateOperation{
|
||||
Type: server.InsertPeersToGroup,
|
||||
Values: peerKeys,
|
||||
Values: patch.Value,
|
||||
})
|
||||
default:
|
||||
util.WriteError(status.Errorf(status.InvalidArgument,
|
||||
@@ -237,10 +242,16 @@ func (h *Groups) CreateGroupHandler(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
var peers []string
|
||||
if req.Peers == nil {
|
||||
peers = make([]string, 0)
|
||||
} else {
|
||||
peers = *req.Peers
|
||||
}
|
||||
group := server.Group{
|
||||
ID: xid.New().String(),
|
||||
Name: req.Name,
|
||||
Peers: peerIPsToKeys(account, req.Peers),
|
||||
Peers: peers,
|
||||
}
|
||||
|
||||
err = h.accountManager.SaveGroup(account.Id, user.Id, &group)
|
||||
@@ -359,7 +370,7 @@ func toGroupResponse(account *server.Account, group *server.Group) *api.Group {
|
||||
continue
|
||||
}
|
||||
peerResp := api.PeerMinimum{
|
||||
Id: peer.IP.String(),
|
||||
Id: peer.ID,
|
||||
Name: peer.Name,
|
||||
}
|
||||
cache[pid] = peerResp
|
||||
|
||||
@@ -22,8 +22,8 @@ import (
|
||||
)
|
||||
|
||||
var TestPeers = map[string]*server.Peer{
|
||||
"A": {Key: "A", IP: net.ParseIP("100.100.100.100")},
|
||||
"B": {Key: "B", IP: net.ParseIP("200.200.200.200")},
|
||||
"A": {Key: "A", ID: "peer-A-ID", IP: net.ParseIP("100.100.100.100")},
|
||||
"B": {Key: "B", ID: "peer-B-ID", IP: net.ParseIP("200.200.200.200")},
|
||||
}
|
||||
|
||||
func initGroupTestData(user *server.User, groups ...*server.Group) *Groups {
|
||||
@@ -269,8 +269,8 @@ func TestWriteGroup(t *testing.T) {
|
||||
Id: "id-existed",
|
||||
PeersCount: 2,
|
||||
Peers: []api.PeerMinimum{
|
||||
{Id: "100.100.100.100"},
|
||||
{Id: "200.200.200.200"}},
|
||||
{Id: "peer-A-ID"},
|
||||
{Id: "peer-B-ID"}},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ func NewPeers(accountManager server.AccountManager, authAudience string) *Peers
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Peers) updatePeer(account *server.Account, user *server.User, peer *server.Peer, w http.ResponseWriter, r *http.Request) {
|
||||
func (h *Peers) updatePeer(account *server.Account, user *server.User, peerID string, w http.ResponseWriter, r *http.Request) {
|
||||
req := &api.PutApiPeersIdJSONBody{}
|
||||
err := json.NewDecoder(r.Body).Decode(&req)
|
||||
if err != nil {
|
||||
@@ -35,8 +35,8 @@ func (h *Peers) updatePeer(account *server.Account, user *server.User, peer *ser
|
||||
return
|
||||
}
|
||||
|
||||
update := &server.Peer{Key: peer.Key, SSHEnabled: req.SshEnabled, Name: req.Name}
|
||||
peer, err = h.accountManager.UpdatePeer(account.Id, user.Id, update)
|
||||
update := &server.Peer{ID: peerID, SSHEnabled: req.SshEnabled, Name: req.Name}
|
||||
peer, err := h.accountManager.UpdatePeer(account.Id, user.Id, update)
|
||||
if err != nil {
|
||||
util.WriteError(err, w)
|
||||
return
|
||||
@@ -45,8 +45,8 @@ func (h *Peers) updatePeer(account *server.Account, user *server.User, peer *ser
|
||||
util.WriteJSONObject(w, toPeerResponse(peer, account, dnsDomain))
|
||||
}
|
||||
|
||||
func (h *Peers) deletePeer(accountID, userID string, peer *server.Peer, w http.ResponseWriter, r *http.Request) {
|
||||
_, err := h.accountManager.DeletePeer(accountID, peer.Key, userID)
|
||||
func (h *Peers) deletePeer(accountID, userID string, peerID string, w http.ResponseWriter) {
|
||||
_, err := h.accountManager.DeletePeer(accountID, peerID, userID)
|
||||
if err != nil {
|
||||
util.WriteError(err, w)
|
||||
return
|
||||
@@ -62,31 +62,19 @@ func (h *Peers) HandlePeer(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
vars := mux.Vars(r)
|
||||
peerId := vars["id"] //effectively peer IP address
|
||||
if len(peerId) == 0 {
|
||||
peerID := vars["id"]
|
||||
if len(peerID) == 0 {
|
||||
util.WriteError(status.Errorf(status.InvalidArgument, "invalid peer ID"), w)
|
||||
return
|
||||
}
|
||||
|
||||
peer, err := h.accountManager.GetPeerByIP(account.Id, peerId)
|
||||
if err != nil {
|
||||
util.WriteError(err, w)
|
||||
return
|
||||
}
|
||||
|
||||
dnsDomain := h.accountManager.GetDNSDomain()
|
||||
|
||||
switch r.Method {
|
||||
case http.MethodDelete:
|
||||
h.deletePeer(account.Id, user.Id, peer, w, r)
|
||||
h.deletePeer(account.Id, user.Id, peerID, w)
|
||||
return
|
||||
case http.MethodPut:
|
||||
h.updatePeer(account, user, peer, w, r)
|
||||
h.updatePeer(account, user, peerID, w, r)
|
||||
return
|
||||
case http.MethodGet:
|
||||
util.WriteJSONObject(w, toPeerResponse(peer, account, dnsDomain))
|
||||
return
|
||||
|
||||
default:
|
||||
util.WriteError(status.Errorf(status.NotFound, "unknown METHOD"), w)
|
||||
}
|
||||
@@ -132,7 +120,7 @@ func toPeerResponse(peer *server.Peer, account *server.Account, dnsDomain string
|
||||
}
|
||||
groupsChecked[group.ID] = struct{}{}
|
||||
for _, pk := range group.Peers {
|
||||
if pk == peer.Key {
|
||||
if pk == peer.ID {
|
||||
info := api.GroupMinimum{
|
||||
Id: group.ID,
|
||||
Name: group.Name,
|
||||
@@ -149,7 +137,7 @@ func toPeerResponse(peer *server.Peer, account *server.Account, dnsDomain string
|
||||
fqdn = peer.DNSLabel
|
||||
}
|
||||
return &api.Peer{
|
||||
Id: peer.IP.String(),
|
||||
Id: peer.ID,
|
||||
Name: peer.Name,
|
||||
Ip: peer.IP.String(),
|
||||
Connected: peer.Status.Connected,
|
||||
|
||||
@@ -45,7 +45,7 @@ func (h *Routes) GetAllRoutesHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
apiRoutes := make([]*api.Route, 0)
|
||||
for _, r := range routes {
|
||||
apiRoutes = append(apiRoutes, toRouteResponse(account, r))
|
||||
apiRoutes = append(apiRoutes, toRouteResponse(r))
|
||||
}
|
||||
|
||||
util.WriteJSONObject(w, apiRoutes)
|
||||
@@ -85,7 +85,7 @@ func (h *Routes) CreateRouteHandler(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
resp := toRouteResponse(account, newRoute)
|
||||
resp := toRouteResponse(newRoute)
|
||||
|
||||
util.WriteJSONObject(w, &resp)
|
||||
}
|
||||
@@ -126,16 +126,6 @@ func (h *Routes) UpdateRouteHandler(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
peerKey := req.Peer
|
||||
if req.Peer != "" {
|
||||
peer := account.GetPeerByIP(req.Peer)
|
||||
if peer == nil {
|
||||
util.WriteError(status.Errorf(status.NotFound, "peer %s not found", req.Peer), w)
|
||||
return
|
||||
}
|
||||
peerKey = peer.Key
|
||||
}
|
||||
|
||||
if utf8.RuneCountInString(req.NetworkId) > route.MaxNetIDChar || req.NetworkId == "" {
|
||||
util.WriteError(status.Errorf(status.InvalidArgument,
|
||||
"identifier should be between 1 and %d", route.MaxNetIDChar), w)
|
||||
@@ -148,7 +138,7 @@ func (h *Routes) UpdateRouteHandler(w http.ResponseWriter, r *http.Request) {
|
||||
NetID: req.NetworkId,
|
||||
NetworkType: prefixType,
|
||||
Masquerade: req.Masquerade,
|
||||
Peer: peerKey,
|
||||
Peer: req.Peer,
|
||||
Metric: req.Metric,
|
||||
Description: req.Description,
|
||||
Enabled: req.Enabled,
|
||||
@@ -161,7 +151,7 @@ func (h *Routes) UpdateRouteHandler(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
resp := toRouteResponse(account, newRoute)
|
||||
resp := toRouteResponse(newRoute)
|
||||
|
||||
util.WriteJSONObject(w, &resp)
|
||||
}
|
||||
@@ -245,18 +235,9 @@ func (h *Routes) PatchRouteHandler(w http.ResponseWriter, r *http.Request) {
|
||||
"value field only accepts 1 value, got %d", len(patch.Value)), w)
|
||||
return
|
||||
}
|
||||
peerValue := patch.Value
|
||||
if patch.Value[0] != "" {
|
||||
peer, err := h.accountManager.GetPeerByIP(account.Id, patch.Value[0])
|
||||
if err != nil {
|
||||
util.WriteError(err, w)
|
||||
return
|
||||
}
|
||||
peerValue = []string{peer.Key}
|
||||
}
|
||||
operations = append(operations, server.RouteUpdateOperation{
|
||||
Type: server.UpdateRoutePeer,
|
||||
Values: peerValue,
|
||||
Values: patch.Value,
|
||||
})
|
||||
case api.RoutePatchOperationPathMetric:
|
||||
if patch.Op != api.RoutePatchOperationOpReplace {
|
||||
@@ -305,13 +286,13 @@ func (h *Routes) PatchRouteHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
route, err := h.accountManager.UpdateRoute(account.Id, routeID, operations)
|
||||
root, err := h.accountManager.UpdateRoute(account.Id, routeID, operations)
|
||||
if err != nil {
|
||||
util.WriteError(err, w)
|
||||
return
|
||||
}
|
||||
|
||||
resp := toRouteResponse(account, route)
|
||||
resp := toRouteResponse(root)
|
||||
|
||||
util.WriteJSONObject(w, &resp)
|
||||
}
|
||||
@@ -361,25 +342,16 @@ func (h *Routes) GetRouteHandler(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
util.WriteJSONObject(w, toRouteResponse(account, foundRoute))
|
||||
util.WriteJSONObject(w, toRouteResponse(foundRoute))
|
||||
}
|
||||
|
||||
func toRouteResponse(account *server.Account, serverRoute *route.Route) *api.Route {
|
||||
var peerIP string
|
||||
if serverRoute.Peer != "" {
|
||||
peer, found := account.Peers[serverRoute.Peer]
|
||||
if !found {
|
||||
panic("peer ID not found")
|
||||
}
|
||||
peerIP = peer.IP.String()
|
||||
}
|
||||
|
||||
func toRouteResponse(serverRoute *route.Route) *api.Route {
|
||||
return &api.Route{
|
||||
Id: serverRoute.ID,
|
||||
Description: serverRoute.Description,
|
||||
NetworkId: serverRoute.NetID,
|
||||
Enabled: serverRoute.Enabled,
|
||||
Peer: peerIP,
|
||||
Peer: serverRoute.Peer,
|
||||
Network: serverRoute.Network.String(),
|
||||
NetworkType: serverRoute.NetworkType.String(),
|
||||
Masquerade: serverRoute.Masquerade,
|
||||
|
||||
@@ -24,8 +24,9 @@ import (
|
||||
const (
|
||||
existingRouteID = "existingRouteID"
|
||||
notFoundRouteID = "notFoundRouteID"
|
||||
existingPeerID = "100.64.0.100"
|
||||
notFoundPeerID = "100.64.0.200"
|
||||
existingPeerIP = "100.64.0.100"
|
||||
existingPeerID = "peer-id"
|
||||
notFoundPeerID = "nonExistingPeer"
|
||||
existingPeerKey = "existingPeerKey"
|
||||
testAccountID = "test_id"
|
||||
existingGroupID = "testGroup"
|
||||
@@ -47,9 +48,10 @@ var testingAccount = &server.Account{
|
||||
Id: testAccountID,
|
||||
Domain: "hotmail.com",
|
||||
Peers: map[string]*server.Peer{
|
||||
existingPeerKey: {
|
||||
existingPeerID: {
|
||||
Key: existingPeerKey,
|
||||
IP: netip.MustParseAddr(existingPeerID).AsSlice(),
|
||||
IP: netip.MustParseAddr(existingPeerIP).AsSlice(),
|
||||
ID: existingPeerID,
|
||||
},
|
||||
},
|
||||
Users: map[string]*server.User{
|
||||
@@ -66,18 +68,15 @@ func initRoutesTestData() *Routes {
|
||||
}
|
||||
return nil, status.Errorf(status.NotFound, "route with ID %s not found", routeID)
|
||||
},
|
||||
CreateRouteFunc: func(accountID string, network, peerIP, description, netID string, masquerade bool, metric int, groups []string, enabled bool, _ string) (*route.Route, error) {
|
||||
|
||||
peer := testingAccount.GetPeerByIP(peerIP)
|
||||
if peer == nil {
|
||||
return nil, status.Errorf(status.NotFound, "peer %s not found", peerIP)
|
||||
CreateRouteFunc: func(accountID string, network, peerID, description, netID string, masquerade bool, metric int, groups []string, enabled bool, _ string) (*route.Route, error) {
|
||||
if peerID == notFoundPeerID {
|
||||
return nil, status.Errorf(status.InvalidArgument, "peer with ID %s not found", peerID)
|
||||
}
|
||||
|
||||
networkType, p, _ := route.ParseNetwork(network)
|
||||
return &route.Route{
|
||||
ID: existingRouteID,
|
||||
NetID: netID,
|
||||
Peer: peer.Key,
|
||||
Peer: peerID,
|
||||
Network: p,
|
||||
NetworkType: networkType,
|
||||
Description: description,
|
||||
@@ -86,7 +85,10 @@ func initRoutesTestData() *Routes {
|
||||
Groups: groups,
|
||||
}, nil
|
||||
},
|
||||
SaveRouteFunc: func(_, _ string, _ *route.Route) error {
|
||||
SaveRouteFunc: func(_, _ string, r *route.Route) error {
|
||||
if r.Peer == notFoundPeerID {
|
||||
return status.Errorf(status.InvalidArgument, "peer with ID %s not found", r.Peer)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
DeleteRouteFunc: func(_ string, routeID string, _ string) error {
|
||||
@@ -119,6 +121,9 @@ func initRoutesTestData() *Routes {
|
||||
routeToUpdate.NetID = operation.Values[0]
|
||||
case server.UpdateRoutePeer:
|
||||
routeToUpdate.Peer = operation.Values[0]
|
||||
if routeToUpdate.Peer == notFoundPeerID {
|
||||
return nil, status.Errorf(status.InvalidArgument, "peer with ID %s not found", routeToUpdate.Peer)
|
||||
}
|
||||
case server.UpdateRouteMetric:
|
||||
routeToUpdate.Metric, _ = strconv.Atoi(operation.Values[0])
|
||||
case server.UpdateRouteMasquerade:
|
||||
@@ -166,7 +171,7 @@ func TestRoutesHandlers(t *testing.T) {
|
||||
requestPath: "/api/routes/" + existingRouteID,
|
||||
expectedStatus: http.StatusOK,
|
||||
expectedBody: true,
|
||||
expectedRoute: toRouteResponse(testingAccount, baseExistingRoute),
|
||||
expectedRoute: toRouteResponse(baseExistingRoute),
|
||||
},
|
||||
{
|
||||
name: "Get Not Existing Route",
|
||||
@@ -212,7 +217,7 @@ func TestRoutesHandlers(t *testing.T) {
|
||||
requestType: http.MethodPost,
|
||||
requestPath: "/api/routes",
|
||||
requestBody: bytes.NewBufferString(fmt.Sprintf("{\"Description\":\"Post\",\"Network\":\"192.168.0.0/16\",\"network_id\":\"awesomeNet\",\"Peer\":\"%s\",\"groups\":[\"%s\"]}", notFoundPeerID, existingGroupID)),
|
||||
expectedStatus: http.StatusNotFound,
|
||||
expectedStatus: http.StatusUnprocessableEntity,
|
||||
expectedBody: false,
|
||||
},
|
||||
{
|
||||
@@ -263,7 +268,7 @@ func TestRoutesHandlers(t *testing.T) {
|
||||
requestType: http.MethodPut,
|
||||
requestPath: "/api/routes/" + existingRouteID,
|
||||
requestBody: bytes.NewBufferString(fmt.Sprintf("{\"Description\":\"Post\",\"Network\":\"192.168.0.0/16\",\"network_id\":\"awesomeNet\",\"Peer\":\"%s\",\"groups\":[\"%s\"]}", notFoundPeerID, existingGroupID)),
|
||||
expectedStatus: http.StatusNotFound,
|
||||
expectedStatus: http.StatusUnprocessableEntity,
|
||||
expectedBody: false,
|
||||
},
|
||||
{
|
||||
@@ -326,7 +331,7 @@ func TestRoutesHandlers(t *testing.T) {
|
||||
requestType: http.MethodPatch,
|
||||
requestPath: "/api/routes/" + existingRouteID,
|
||||
requestBody: bytes.NewBufferString(fmt.Sprintf("[{\"op\":\"replace\",\"path\":\"peer\",\"value\":[\"%s\"]}]", notFoundPeerID)),
|
||||
expectedStatus: http.StatusNotFound,
|
||||
expectedStatus: http.StatusUnprocessableEntity,
|
||||
expectedBody: false,
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user