mirror of
https://github.com/netbirdio/netbird.git
synced 2025-06-20 01:38:41 +02:00
Extend API with accessible peers (#1284)
Extend the peer and peers API endpoints with accessible peers.
This commit is contained in:
parent
b726b3262d
commit
8be6e92563
@ -217,7 +217,7 @@ components:
|
|||||||
- name
|
- name
|
||||||
- ssh_enabled
|
- ssh_enabled
|
||||||
- login_expiration_enabled
|
- login_expiration_enabled
|
||||||
Peer:
|
PeerBase:
|
||||||
allOf:
|
allOf:
|
||||||
- $ref: '#/components/schemas/PeerMinimum'
|
- $ref: '#/components/schemas/PeerMinimum'
|
||||||
- type: object
|
- type: object
|
||||||
@ -294,6 +294,50 @@ components:
|
|||||||
- login_expiration_enabled
|
- login_expiration_enabled
|
||||||
- login_expired
|
- login_expired
|
||||||
- last_login
|
- last_login
|
||||||
|
AccessiblePeer:
|
||||||
|
allOf:
|
||||||
|
- $ref: '#/components/schemas/PeerMinimum'
|
||||||
|
- type: object
|
||||||
|
properties:
|
||||||
|
ip:
|
||||||
|
description: Peer's IP address
|
||||||
|
type: string
|
||||||
|
example: 10.64.0.1
|
||||||
|
dns_label:
|
||||||
|
description: Peer's DNS label is the parsed peer name for domain resolution. It is used to form an FQDN by appending the account's domain to the peer label. e.g. peer-dns-label.netbird.cloud
|
||||||
|
type: string
|
||||||
|
example: stage-host-1.netbird.cloud
|
||||||
|
user_id:
|
||||||
|
description: User ID of the user that enrolled this peer
|
||||||
|
type: string
|
||||||
|
example: google-oauth2|277474792786460067937
|
||||||
|
required:
|
||||||
|
- ip
|
||||||
|
- dns_label
|
||||||
|
- user_id
|
||||||
|
Peer:
|
||||||
|
allOf:
|
||||||
|
- $ref: '#/components/schemas/PeerBase'
|
||||||
|
- type: object
|
||||||
|
properties:
|
||||||
|
accessible_peers:
|
||||||
|
description: List of accessible peers
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/AccessiblePeer'
|
||||||
|
required:
|
||||||
|
- accessible_peers
|
||||||
|
PeerBatch:
|
||||||
|
allOf:
|
||||||
|
- $ref: '#/components/schemas/PeerBase'
|
||||||
|
- type: object
|
||||||
|
properties:
|
||||||
|
accessible_peers_count:
|
||||||
|
description: Number of accessible peers
|
||||||
|
type: integer
|
||||||
|
example: 5
|
||||||
|
required:
|
||||||
|
- accessible_peers_count
|
||||||
SetupKey:
|
SetupKey:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
@ -1364,7 +1408,7 @@ paths:
|
|||||||
schema:
|
schema:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: '#/components/schemas/Peer'
|
$ref: '#/components/schemas/PeerBatch'
|
||||||
'400':
|
'400':
|
||||||
"$ref": "#/components/responses/bad_request"
|
"$ref": "#/components/responses/bad_request"
|
||||||
'401':
|
'401':
|
||||||
|
@ -117,6 +117,24 @@ const (
|
|||||||
UserStatusInvited UserStatus = "invited"
|
UserStatusInvited UserStatus = "invited"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// AccessiblePeer defines model for AccessiblePeer.
|
||||||
|
type AccessiblePeer struct {
|
||||||
|
// DnsLabel Peer's DNS label is the parsed peer name for domain resolution. It is used to form an FQDN by appending the account's domain to the peer label. e.g. peer-dns-label.netbird.cloud
|
||||||
|
DnsLabel string `json:"dns_label"`
|
||||||
|
|
||||||
|
// Id Peer ID
|
||||||
|
Id string `json:"id"`
|
||||||
|
|
||||||
|
// Ip Peer's IP address
|
||||||
|
Ip string `json:"ip"`
|
||||||
|
|
||||||
|
// Name Peer's hostname
|
||||||
|
Name string `json:"name"`
|
||||||
|
|
||||||
|
// UserId User ID of the user that enrolled this peer
|
||||||
|
UserId string `json:"user_id"`
|
||||||
|
}
|
||||||
|
|
||||||
// Account defines model for Account.
|
// Account defines model for Account.
|
||||||
type Account struct {
|
type Account struct {
|
||||||
// Id Account ID
|
// Id Account ID
|
||||||
@ -302,6 +320,114 @@ type NameserverGroupRequest struct {
|
|||||||
|
|
||||||
// Peer defines model for Peer.
|
// Peer defines model for Peer.
|
||||||
type Peer struct {
|
type Peer struct {
|
||||||
|
// AccessiblePeers List of accessible peers
|
||||||
|
AccessiblePeers []AccessiblePeer `json:"accessible_peers"`
|
||||||
|
|
||||||
|
// Connected Peer to Management connection status
|
||||||
|
Connected bool `json:"connected"`
|
||||||
|
|
||||||
|
// DnsLabel Peer's DNS label is the parsed peer name for domain resolution. It is used to form an FQDN by appending the account's domain to the peer label. e.g. peer-dns-label.netbird.cloud
|
||||||
|
DnsLabel string `json:"dns_label"`
|
||||||
|
|
||||||
|
// Groups Groups that the peer belongs to
|
||||||
|
Groups []GroupMinimum `json:"groups"`
|
||||||
|
|
||||||
|
// Hostname Hostname of the machine
|
||||||
|
Hostname string `json:"hostname"`
|
||||||
|
|
||||||
|
// Id Peer ID
|
||||||
|
Id string `json:"id"`
|
||||||
|
|
||||||
|
// Ip Peer's IP address
|
||||||
|
Ip string `json:"ip"`
|
||||||
|
|
||||||
|
// LastLogin Last time this peer performed log in (authentication). E.g., user authenticated.
|
||||||
|
LastLogin time.Time `json:"last_login"`
|
||||||
|
|
||||||
|
// LastSeen Last time peer connected to Netbird's management service
|
||||||
|
LastSeen time.Time `json:"last_seen"`
|
||||||
|
|
||||||
|
// LoginExpirationEnabled Indicates whether peer login expiration has been enabled or not
|
||||||
|
LoginExpirationEnabled bool `json:"login_expiration_enabled"`
|
||||||
|
|
||||||
|
// LoginExpired Indicates whether peer's login expired or not
|
||||||
|
LoginExpired bool `json:"login_expired"`
|
||||||
|
|
||||||
|
// Name Peer's hostname
|
||||||
|
Name string `json:"name"`
|
||||||
|
|
||||||
|
// Os Peer's operating system and version
|
||||||
|
Os string `json:"os"`
|
||||||
|
|
||||||
|
// SshEnabled Indicates whether SSH server is enabled on this peer
|
||||||
|
SshEnabled bool `json:"ssh_enabled"`
|
||||||
|
|
||||||
|
// UiVersion Peer's desktop UI version
|
||||||
|
UiVersion *string `json:"ui_version,omitempty"`
|
||||||
|
|
||||||
|
// UserId User ID of the user that enrolled this peer
|
||||||
|
UserId *string `json:"user_id,omitempty"`
|
||||||
|
|
||||||
|
// Version Peer's daemon or cli version
|
||||||
|
Version string `json:"version"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PeerBase defines model for PeerBase.
|
||||||
|
type PeerBase struct {
|
||||||
|
// Connected Peer to Management connection status
|
||||||
|
Connected bool `json:"connected"`
|
||||||
|
|
||||||
|
// DnsLabel Peer's DNS label is the parsed peer name for domain resolution. It is used to form an FQDN by appending the account's domain to the peer label. e.g. peer-dns-label.netbird.cloud
|
||||||
|
DnsLabel string `json:"dns_label"`
|
||||||
|
|
||||||
|
// Groups Groups that the peer belongs to
|
||||||
|
Groups []GroupMinimum `json:"groups"`
|
||||||
|
|
||||||
|
// Hostname Hostname of the machine
|
||||||
|
Hostname string `json:"hostname"`
|
||||||
|
|
||||||
|
// Id Peer ID
|
||||||
|
Id string `json:"id"`
|
||||||
|
|
||||||
|
// Ip Peer's IP address
|
||||||
|
Ip string `json:"ip"`
|
||||||
|
|
||||||
|
// LastLogin Last time this peer performed log in (authentication). E.g., user authenticated.
|
||||||
|
LastLogin time.Time `json:"last_login"`
|
||||||
|
|
||||||
|
// LastSeen Last time peer connected to Netbird's management service
|
||||||
|
LastSeen time.Time `json:"last_seen"`
|
||||||
|
|
||||||
|
// LoginExpirationEnabled Indicates whether peer login expiration has been enabled or not
|
||||||
|
LoginExpirationEnabled bool `json:"login_expiration_enabled"`
|
||||||
|
|
||||||
|
// LoginExpired Indicates whether peer's login expired or not
|
||||||
|
LoginExpired bool `json:"login_expired"`
|
||||||
|
|
||||||
|
// Name Peer's hostname
|
||||||
|
Name string `json:"name"`
|
||||||
|
|
||||||
|
// Os Peer's operating system and version
|
||||||
|
Os string `json:"os"`
|
||||||
|
|
||||||
|
// SshEnabled Indicates whether SSH server is enabled on this peer
|
||||||
|
SshEnabled bool `json:"ssh_enabled"`
|
||||||
|
|
||||||
|
// UiVersion Peer's desktop UI version
|
||||||
|
UiVersion *string `json:"ui_version,omitempty"`
|
||||||
|
|
||||||
|
// UserId User ID of the user that enrolled this peer
|
||||||
|
UserId *string `json:"user_id,omitempty"`
|
||||||
|
|
||||||
|
// Version Peer's daemon or cli version
|
||||||
|
Version string `json:"version"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PeerBatch defines model for PeerBatch.
|
||||||
|
type PeerBatch struct {
|
||||||
|
// AccessiblePeersCount Number of accessible peers
|
||||||
|
AccessiblePeersCount int `json:"accessible_peers_count"`
|
||||||
|
|
||||||
// Connected Peer to Management connection status
|
// Connected Peer to Management connection status
|
||||||
Connected bool `json:"connected"`
|
Connected bool `json:"connected"`
|
||||||
|
|
||||||
|
@ -61,8 +61,14 @@ func (h *PeersHandler) getPeer(account *server.Account, peerID, userID string, w
|
|||||||
util.WriteError(err, w)
|
util.WriteError(err, w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
dnsDomain := h.accountManager.GetDNSDomain()
|
||||||
|
|
||||||
util.WriteJSONObject(w, toPeerResponse(peerToReturn, account, h.accountManager.GetDNSDomain()))
|
groupsInfo := toGroupsInfo(account.Groups, peer.ID)
|
||||||
|
|
||||||
|
netMap := account.GetPeerNetworkMap(peerID, h.accountManager.GetDNSDomain())
|
||||||
|
accessiblePeers := toAccessiblePeers(netMap, dnsDomain)
|
||||||
|
|
||||||
|
util.WriteJSONObject(w, toSinglePeerResponse(peerToReturn, groupsInfo, dnsDomain, accessiblePeers))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *PeersHandler) updatePeer(account *server.Account, user *server.User, peerID string, w http.ResponseWriter, r *http.Request) {
|
func (h *PeersHandler) updatePeer(account *server.Account, user *server.User, peerID string, w http.ResponseWriter, r *http.Request) {
|
||||||
@ -81,7 +87,13 @@ func (h *PeersHandler) updatePeer(account *server.Account, user *server.User, pe
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
dnsDomain := h.accountManager.GetDNSDomain()
|
dnsDomain := h.accountManager.GetDNSDomain()
|
||||||
util.WriteJSONObject(w, toPeerResponse(peer, account, dnsDomain))
|
|
||||||
|
groupMinimumInfo := toGroupsInfo(account.Groups, peer.ID)
|
||||||
|
|
||||||
|
netMap := account.GetPeerNetworkMap(peerID, h.accountManager.GetDNSDomain())
|
||||||
|
accessiblePeers := toAccessiblePeers(netMap, dnsDomain)
|
||||||
|
|
||||||
|
util.WriteJSONObject(w, toSinglePeerResponse(peer, groupMinimumInfo, dnsDomain, accessiblePeers))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *PeersHandler) deletePeer(accountID, userID string, peerID string, w http.ResponseWriter) {
|
func (h *PeersHandler) deletePeer(accountID, userID string, peerID string, w http.ResponseWriter) {
|
||||||
@ -142,14 +154,18 @@ func (h *PeersHandler) GetAllPeers(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
dnsDomain := h.accountManager.GetDNSDomain()
|
dnsDomain := h.accountManager.GetDNSDomain()
|
||||||
|
|
||||||
respBody := []*api.Peer{}
|
respBody := make([]*api.PeerBatch, 0, len(peers))
|
||||||
for _, peer := range peers {
|
for _, peer := range peers {
|
||||||
peerToReturn, err := h.checkPeerStatus(peer)
|
peerToReturn, err := h.checkPeerStatus(peer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
util.WriteError(err, w)
|
util.WriteError(err, w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
respBody = append(respBody, toPeerResponse(peerToReturn, account, dnsDomain))
|
groupMinimumInfo := toGroupsInfo(account.Groups, peer.ID)
|
||||||
|
|
||||||
|
accessiblePeerNumbers := h.accessiblePeersNumber(account, peer.ID)
|
||||||
|
|
||||||
|
respBody = append(respBody, toPeerListItemResponse(peerToReturn, groupMinimumInfo, dnsDomain, accessiblePeerNumbers))
|
||||||
}
|
}
|
||||||
util.WriteJSONObject(w, respBody)
|
util.WriteJSONObject(w, respBody)
|
||||||
return
|
return
|
||||||
@ -158,17 +174,48 @@ func (h *PeersHandler) GetAllPeers(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func toPeerResponse(peer *server.Peer, account *server.Account, dnsDomain string) *api.Peer {
|
func (h *PeersHandler) accessiblePeersNumber(account *server.Account, peerID string) int {
|
||||||
|
netMap := account.GetPeerNetworkMap(peerID, h.accountManager.GetDNSDomain())
|
||||||
|
return len(netMap.Peers) + len(netMap.OfflinePeers)
|
||||||
|
}
|
||||||
|
|
||||||
|
func toAccessiblePeers(netMap *server.NetworkMap, dnsDomain string) []api.AccessiblePeer {
|
||||||
|
accessiblePeers := make([]api.AccessiblePeer, 0, len(netMap.Peers)+len(netMap.OfflinePeers))
|
||||||
|
for _, p := range netMap.Peers {
|
||||||
|
ap := api.AccessiblePeer{
|
||||||
|
Id: p.ID,
|
||||||
|
Name: p.Name,
|
||||||
|
Ip: p.IP.String(),
|
||||||
|
DnsLabel: fqdn(p, dnsDomain),
|
||||||
|
UserId: p.UserID,
|
||||||
|
}
|
||||||
|
accessiblePeers = append(accessiblePeers, ap)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range netMap.OfflinePeers {
|
||||||
|
ap := api.AccessiblePeer{
|
||||||
|
Id: p.ID,
|
||||||
|
Name: p.Name,
|
||||||
|
Ip: p.IP.String(),
|
||||||
|
DnsLabel: fqdn(p, dnsDomain),
|
||||||
|
UserId: p.UserID,
|
||||||
|
}
|
||||||
|
accessiblePeers = append(accessiblePeers, ap)
|
||||||
|
}
|
||||||
|
return accessiblePeers
|
||||||
|
}
|
||||||
|
|
||||||
|
func toGroupsInfo(groups map[string]*server.Group, peerID string) []api.GroupMinimum {
|
||||||
var groupsInfo []api.GroupMinimum
|
var groupsInfo []api.GroupMinimum
|
||||||
groupsChecked := make(map[string]struct{})
|
groupsChecked := make(map[string]struct{})
|
||||||
for _, group := range account.Groups {
|
for _, group := range groups {
|
||||||
_, ok := groupsChecked[group.ID]
|
_, ok := groupsChecked[group.ID]
|
||||||
if ok {
|
if ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
groupsChecked[group.ID] = struct{}{}
|
groupsChecked[group.ID] = struct{}{}
|
||||||
for _, pk := range group.Peers {
|
for _, pk := range group.Peers {
|
||||||
if pk == peer.ID {
|
if pk != peerID {
|
||||||
info := api.GroupMinimum{
|
info := api.GroupMinimum{
|
||||||
Id: group.ID,
|
Id: group.ID,
|
||||||
Name: group.Name,
|
Name: group.Name,
|
||||||
@ -179,12 +226,10 @@ func toPeerResponse(peer *server.Peer, account *server.Account, dnsDomain string
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return groupsInfo
|
||||||
|
}
|
||||||
|
|
||||||
fqdn := peer.FQDN(dnsDomain)
|
func toSinglePeerResponse(peer *server.Peer, groupsInfo []api.GroupMinimum, dnsDomain string, accessiblePeer []api.AccessiblePeer) *api.Peer {
|
||||||
if fqdn == "" {
|
|
||||||
fqdn = peer.DNSLabel
|
|
||||||
}
|
|
||||||
|
|
||||||
return &api.Peer{
|
return &api.Peer{
|
||||||
Id: peer.ID,
|
Id: peer.ID,
|
||||||
Name: peer.Name,
|
Name: peer.Name,
|
||||||
@ -198,9 +243,41 @@ func toPeerResponse(peer *server.Peer, account *server.Account, dnsDomain string
|
|||||||
Hostname: peer.Meta.Hostname,
|
Hostname: peer.Meta.Hostname,
|
||||||
UserId: &peer.UserID,
|
UserId: &peer.UserID,
|
||||||
UiVersion: &peer.Meta.UIVersion,
|
UiVersion: &peer.Meta.UIVersion,
|
||||||
DnsLabel: fqdn,
|
DnsLabel: fqdn(peer, dnsDomain),
|
||||||
LoginExpirationEnabled: peer.LoginExpirationEnabled,
|
LoginExpirationEnabled: peer.LoginExpirationEnabled,
|
||||||
LastLogin: peer.LastLogin,
|
LastLogin: peer.LastLogin,
|
||||||
LoginExpired: peer.Status.LoginExpired,
|
LoginExpired: peer.Status.LoginExpired,
|
||||||
|
AccessiblePeers: accessiblePeer,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func toPeerListItemResponse(peer *server.Peer, groupsInfo []api.GroupMinimum, dnsDomain string, accessiblePeersCount int) *api.PeerBatch {
|
||||||
|
return &api.PeerBatch{
|
||||||
|
Id: peer.ID,
|
||||||
|
Name: peer.Name,
|
||||||
|
Ip: peer.IP.String(),
|
||||||
|
Connected: peer.Status.Connected,
|
||||||
|
LastSeen: peer.Status.LastSeen,
|
||||||
|
Os: fmt.Sprintf("%s %s", peer.Meta.OS, peer.Meta.Core),
|
||||||
|
Version: peer.Meta.WtVersion,
|
||||||
|
Groups: groupsInfo,
|
||||||
|
SshEnabled: peer.SSHEnabled,
|
||||||
|
Hostname: peer.Meta.Hostname,
|
||||||
|
UserId: &peer.UserID,
|
||||||
|
UiVersion: &peer.Meta.UIVersion,
|
||||||
|
DnsLabel: fqdn(peer, dnsDomain),
|
||||||
|
LoginExpirationEnabled: peer.LoginExpirationEnabled,
|
||||||
|
LastLogin: peer.LastLogin,
|
||||||
|
LoginExpired: peer.Status.LoginExpired,
|
||||||
|
AccessiblePeersCount: accessiblePeersCount,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func fqdn(peer *server.Peer, dnsDomain string) string {
|
||||||
|
fqdn := peer.FQDN(dnsDomain)
|
||||||
|
if fqdn == "" {
|
||||||
|
return peer.DNSLabel
|
||||||
|
} else {
|
||||||
|
return fqdn
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,8 +70,17 @@ func initTestMetaData(peers ...*server.Peer) *PeersHandler {
|
|||||||
PeerLoginExpirationEnabled: true,
|
PeerLoginExpirationEnabled: true,
|
||||||
PeerLoginExpiration: time.Hour,
|
PeerLoginExpiration: time.Hour,
|
||||||
},
|
},
|
||||||
|
Network: &server.Network{
|
||||||
|
Identifier: "ciclqisab2ss43jdn8q0",
|
||||||
|
Net: net.IPNet{
|
||||||
|
IP: net.ParseIP("100.67.0.0"),
|
||||||
|
Mask: net.IPv4Mask(255, 255, 0, 0),
|
||||||
|
},
|
||||||
|
Serial: 51,
|
||||||
|
},
|
||||||
}, user, nil
|
}, user, nil
|
||||||
},
|
},
|
||||||
|
|
||||||
GetAllConnectedPeersFunc: func() (map[string]struct{}, error) {
|
GetAllConnectedPeersFunc: func() (map[string]struct{}, error) {
|
||||||
statuses := make(map[string]struct{})
|
statuses := make(map[string]struct{})
|
||||||
for _, peer := range peers {
|
for _, peer := range peers {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user