mirror of
https://github.com/netbirdio/netbird.git
synced 2025-06-19 17:31:39 +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
|
||||
- ssh_enabled
|
||||
- login_expiration_enabled
|
||||
Peer:
|
||||
PeerBase:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/PeerMinimum'
|
||||
- type: object
|
||||
@ -294,6 +294,50 @@ components:
|
||||
- login_expiration_enabled
|
||||
- login_expired
|
||||
- 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:
|
||||
type: object
|
||||
properties:
|
||||
@ -1364,7 +1408,7 @@ paths:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Peer'
|
||||
$ref: '#/components/schemas/PeerBatch'
|
||||
'400':
|
||||
"$ref": "#/components/responses/bad_request"
|
||||
'401':
|
||||
|
@ -117,6 +117,24 @@ const (
|
||||
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.
|
||||
type Account struct {
|
||||
// Id Account ID
|
||||
@ -302,6 +320,114 @@ type NameserverGroupRequest struct {
|
||||
|
||||
// Peer defines model for Peer.
|
||||
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 bool `json:"connected"`
|
||||
|
||||
|
@ -61,8 +61,14 @@ func (h *PeersHandler) getPeer(account *server.Account, peerID, userID string, w
|
||||
util.WriteError(err, w)
|
||||
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) {
|
||||
@ -81,7 +87,13 @@ func (h *PeersHandler) updatePeer(account *server.Account, user *server.User, pe
|
||||
return
|
||||
}
|
||||
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) {
|
||||
@ -142,14 +154,18 @@ func (h *PeersHandler) GetAllPeers(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
dnsDomain := h.accountManager.GetDNSDomain()
|
||||
|
||||
respBody := []*api.Peer{}
|
||||
respBody := make([]*api.PeerBatch, 0, len(peers))
|
||||
for _, peer := range peers {
|
||||
peerToReturn, err := h.checkPeerStatus(peer)
|
||||
if err != nil {
|
||||
util.WriteError(err, w)
|
||||
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)
|
||||
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
|
||||
groupsChecked := make(map[string]struct{})
|
||||
for _, group := range account.Groups {
|
||||
for _, group := range groups {
|
||||
_, ok := groupsChecked[group.ID]
|
||||
if ok {
|
||||
continue
|
||||
}
|
||||
groupsChecked[group.ID] = struct{}{}
|
||||
for _, pk := range group.Peers {
|
||||
if pk == peer.ID {
|
||||
if pk != peerID {
|
||||
info := api.GroupMinimum{
|
||||
Id: group.ID,
|
||||
Name: group.Name,
|
||||
@ -179,12 +226,10 @@ func toPeerResponse(peer *server.Peer, account *server.Account, dnsDomain string
|
||||
}
|
||||
}
|
||||
}
|
||||
return groupsInfo
|
||||
}
|
||||
|
||||
fqdn := peer.FQDN(dnsDomain)
|
||||
if fqdn == "" {
|
||||
fqdn = peer.DNSLabel
|
||||
}
|
||||
|
||||
func toSinglePeerResponse(peer *server.Peer, groupsInfo []api.GroupMinimum, dnsDomain string, accessiblePeer []api.AccessiblePeer) *api.Peer {
|
||||
return &api.Peer{
|
||||
Id: peer.ID,
|
||||
Name: peer.Name,
|
||||
@ -198,9 +243,41 @@ func toPeerResponse(peer *server.Peer, account *server.Account, dnsDomain string
|
||||
Hostname: peer.Meta.Hostname,
|
||||
UserId: &peer.UserID,
|
||||
UiVersion: &peer.Meta.UIVersion,
|
||||
DnsLabel: fqdn,
|
||||
DnsLabel: fqdn(peer, dnsDomain),
|
||||
LoginExpirationEnabled: peer.LoginExpirationEnabled,
|
||||
LastLogin: peer.LastLogin,
|
||||
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,
|
||||
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
|
||||
},
|
||||
|
||||
GetAllConnectedPeersFunc: func() (map[string]struct{}, error) {
|
||||
statuses := make(map[string]struct{})
|
||||
for _, peer := range peers {
|
||||
|
Loading…
x
Reference in New Issue
Block a user