mirror of
https://github.com/netbirdio/netbird.git
synced 2025-08-09 23:27:58 +02:00
Extend management to sync meta and posture checks with peer (#1727)
* Add method to retrieve peer's applied posture checks * Add posture checks in server response and update proto messages * Refactor * Extends peer metadata synchronization through SyncRequest and propagate posture changes on syncResponse * Remove account lock * Pass system info on sync * Fix tests * Refactor * resolve merge * Evaluate process check on client (#1749) * implement server and client sync peer meta alongside mocks * wip: add check file and process * Add files to peer metadata for process check * wip: update peer meta on first sync * Add files to peer's metadata * Evaluate process check using files from peer metadata * Fix panic and append windows path to files * Fix check network address and files equality * Evaluate active process on darwin * Evaluate active process on linux * Skip processing processes if no paths are set * Return network map on peer meta-sync and update account peer's * Update client network map on meta sync * Get system info with applied checks * Add windows package * Remove a network map from sync meta-response * Update checks proto message * Keep client checks state and sync meta on checks change * Evaluate a running process * skip build for android and ios * skip check file and process for android and ios * bump gopsutil version * fix tests * move process check to separate os file * refactor * evaluate info with checks on receiving management events * skip meta-update for an old client with no meta-sync support * Check if peer meta is empty without reflection
This commit is contained in:
@ -237,7 +237,10 @@ func runClient(
|
|||||||
return wrapErr(err)
|
return wrapErr(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
engine := NewEngineWithProbes(engineCtx, cancel, signalClient, mgmClient, engineConfig, mobileDependency, statusRecorder, mgmProbe, signalProbe, relayProbe, wgProbe)
|
checks := loginResp.GetChecks()
|
||||||
|
|
||||||
|
engine := NewEngineWithProbes(engineCtx, cancel, signalClient, mgmClient, engineConfig,
|
||||||
|
mobileDependency, statusRecorder, mgmProbe, signalProbe, relayProbe, wgProbe, checks)
|
||||||
err = engine.Start()
|
err = engine.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("error while starting Netbird Connection Engine: %s", err)
|
log.Errorf("error while starting Netbird Connection Engine: %s", err)
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
"net/netip"
|
"net/netip"
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@ -27,6 +28,7 @@ import (
|
|||||||
"github.com/netbirdio/netbird/client/internal/routemanager"
|
"github.com/netbirdio/netbird/client/internal/routemanager"
|
||||||
"github.com/netbirdio/netbird/client/internal/wgproxy"
|
"github.com/netbirdio/netbird/client/internal/wgproxy"
|
||||||
nbssh "github.com/netbirdio/netbird/client/ssh"
|
nbssh "github.com/netbirdio/netbird/client/ssh"
|
||||||
|
"github.com/netbirdio/netbird/client/system"
|
||||||
nbdns "github.com/netbirdio/netbird/dns"
|
nbdns "github.com/netbirdio/netbird/dns"
|
||||||
"github.com/netbirdio/netbird/iface"
|
"github.com/netbirdio/netbird/iface"
|
||||||
"github.com/netbirdio/netbird/iface/bind"
|
"github.com/netbirdio/netbird/iface/bind"
|
||||||
@ -138,6 +140,9 @@ type Engine struct {
|
|||||||
signalProbe *Probe
|
signalProbe *Probe
|
||||||
relayProbe *Probe
|
relayProbe *Probe
|
||||||
wgProbe *Probe
|
wgProbe *Probe
|
||||||
|
|
||||||
|
// checks are the client-applied posture checks that need to be evaluated on the client
|
||||||
|
checks []*mgmProto.Checks
|
||||||
}
|
}
|
||||||
|
|
||||||
// Peer is an instance of the Connection Peer
|
// Peer is an instance of the Connection Peer
|
||||||
@ -155,6 +160,7 @@ func NewEngine(
|
|||||||
config *EngineConfig,
|
config *EngineConfig,
|
||||||
mobileDep MobileDependency,
|
mobileDep MobileDependency,
|
||||||
statusRecorder *peer.Status,
|
statusRecorder *peer.Status,
|
||||||
|
checks []*mgmProto.Checks,
|
||||||
) *Engine {
|
) *Engine {
|
||||||
return NewEngineWithProbes(
|
return NewEngineWithProbes(
|
||||||
ctx,
|
ctx,
|
||||||
@ -168,6 +174,7 @@ func NewEngine(
|
|||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
|
checks,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,6 +191,7 @@ func NewEngineWithProbes(
|
|||||||
signalProbe *Probe,
|
signalProbe *Probe,
|
||||||
relayProbe *Probe,
|
relayProbe *Probe,
|
||||||
wgProbe *Probe,
|
wgProbe *Probe,
|
||||||
|
checks []*mgmProto.Checks,
|
||||||
) *Engine {
|
) *Engine {
|
||||||
return &Engine{
|
return &Engine{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
@ -204,6 +212,7 @@ func NewEngineWithProbes(
|
|||||||
signalProbe: signalProbe,
|
signalProbe: signalProbe,
|
||||||
relayProbe: relayProbe,
|
relayProbe: relayProbe,
|
||||||
wgProbe: wgProbe,
|
wgProbe: wgProbe,
|
||||||
|
checks: checks,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -486,6 +495,10 @@ func (e *Engine) handleSync(update *mgmProto.SyncResponse) error {
|
|||||||
// todo update signal
|
// todo update signal
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := e.updateChecksIfNew(update.Checks); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if update.GetNetworkMap() != nil {
|
if update.GetNetworkMap() != nil {
|
||||||
// only apply new changes and ignore old ones
|
// only apply new changes and ignore old ones
|
||||||
err := e.updateNetworkMap(update.GetNetworkMap())
|
err := e.updateNetworkMap(update.GetNetworkMap())
|
||||||
@ -493,7 +506,27 @@ func (e *Engine) handleSync(update *mgmProto.SyncResponse) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// updateChecksIfNew updates checks if there are changes and sync new meta with management
|
||||||
|
func (e *Engine) updateChecksIfNew(checks []*mgmProto.Checks) error {
|
||||||
|
// if checks are equal, we skip the update
|
||||||
|
if isChecksEqual(e.checks, checks) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
e.checks = checks
|
||||||
|
|
||||||
|
info, err := system.GetInfoWithChecks(e.ctx, checks)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("failed to get system info with checks: %v", err)
|
||||||
|
info = system.GetInfo(e.ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := e.mgmClient.SyncMeta(info); err != nil {
|
||||||
|
log.Errorf("could not sync meta: error %s", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -583,7 +616,13 @@ func (e *Engine) updateConfig(conf *mgmProto.PeerConfig) error {
|
|||||||
// E.g. when a new peer has been registered and we are allowed to connect to it.
|
// E.g. when a new peer has been registered and we are allowed to connect to it.
|
||||||
func (e *Engine) receiveManagementEvents() {
|
func (e *Engine) receiveManagementEvents() {
|
||||||
go func() {
|
go func() {
|
||||||
err := e.mgmClient.Sync(e.handleSync)
|
info, err := system.GetInfoWithChecks(e.ctx, e.checks)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("failed to get system info with checks: %v", err)
|
||||||
|
info = system.GetInfo(e.ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = e.mgmClient.Sync(info, e.handleSync)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// happens if management is unavailable for a long time.
|
// happens if management is unavailable for a long time.
|
||||||
// We want to cancel the operation of the whole client
|
// We want to cancel the operation of the whole client
|
||||||
@ -1150,7 +1189,8 @@ func (e *Engine) close() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *Engine) readInitialSettings() ([]*route.Route, *nbdns.Config, error) {
|
func (e *Engine) readInitialSettings() ([]*route.Route, *nbdns.Config, error) {
|
||||||
netMap, err := e.mgmClient.GetNetworkMap()
|
info := system.GetInfo(e.ctx)
|
||||||
|
netMap, err := e.mgmClient.GetNetworkMap(info)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
@ -1328,3 +1368,10 @@ func (e *Engine) probeSTUNs() []relay.ProbeResult {
|
|||||||
func (e *Engine) probeTURNs() []relay.ProbeResult {
|
func (e *Engine) probeTURNs() []relay.ProbeResult {
|
||||||
return relay.ProbeAll(e.ctx, relay.ProbeTURN, e.TURNs)
|
return relay.ProbeAll(e.ctx, relay.ProbeTURN, e.TURNs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isChecksEqual checks if two slices of checks are equal.
|
||||||
|
func isChecksEqual(checks []*mgmProto.Checks, oChecks []*mgmProto.Checks) bool {
|
||||||
|
return slices.EqualFunc(checks, oChecks, func(checks, oChecks *mgmProto.Checks) bool {
|
||||||
|
return slices.Equal(checks.Files, oChecks.Files)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@ -76,7 +76,7 @@ func TestEngine_SSH(t *testing.T) {
|
|||||||
WgPrivateKey: key,
|
WgPrivateKey: key,
|
||||||
WgPort: 33100,
|
WgPort: 33100,
|
||||||
ServerSSHAllowed: true,
|
ServerSSHAllowed: true,
|
||||||
}, MobileDependency{}, peer.NewRecorder("https://mgm"))
|
}, MobileDependency{}, peer.NewRecorder("https://mgm"), nil)
|
||||||
|
|
||||||
engine.dnsServer = &dns.MockServer{
|
engine.dnsServer = &dns.MockServer{
|
||||||
UpdateDNSServerFunc: func(serial uint64, update nbdns.Config) error { return nil },
|
UpdateDNSServerFunc: func(serial uint64, update nbdns.Config) error { return nil },
|
||||||
@ -210,7 +210,7 @@ func TestEngine_UpdateNetworkMap(t *testing.T) {
|
|||||||
WgAddr: "100.64.0.1/24",
|
WgAddr: "100.64.0.1/24",
|
||||||
WgPrivateKey: key,
|
WgPrivateKey: key,
|
||||||
WgPort: 33100,
|
WgPort: 33100,
|
||||||
}, MobileDependency{}, peer.NewRecorder("https://mgm"))
|
}, MobileDependency{}, peer.NewRecorder("https://mgm"), nil)
|
||||||
newNet, err := stdnet.NewNet()
|
newNet, err := stdnet.NewNet()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -391,7 +391,7 @@ func TestEngine_Sync(t *testing.T) {
|
|||||||
// feed updates to Engine via mocked Management client
|
// feed updates to Engine via mocked Management client
|
||||||
updates := make(chan *mgmtProto.SyncResponse)
|
updates := make(chan *mgmtProto.SyncResponse)
|
||||||
defer close(updates)
|
defer close(updates)
|
||||||
syncFunc := func(msgHandler func(msg *mgmtProto.SyncResponse) error) error {
|
syncFunc := func(info *system.Info, msgHandler func(msg *mgmtProto.SyncResponse) error) error {
|
||||||
for msg := range updates {
|
for msg := range updates {
|
||||||
err := msgHandler(msg)
|
err := msgHandler(msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -406,7 +406,7 @@ func TestEngine_Sync(t *testing.T) {
|
|||||||
WgAddr: "100.64.0.1/24",
|
WgAddr: "100.64.0.1/24",
|
||||||
WgPrivateKey: key,
|
WgPrivateKey: key,
|
||||||
WgPort: 33100,
|
WgPort: 33100,
|
||||||
}, MobileDependency{}, peer.NewRecorder("https://mgm"))
|
}, MobileDependency{}, peer.NewRecorder("https://mgm"), nil)
|
||||||
|
|
||||||
engine.dnsServer = &dns.MockServer{
|
engine.dnsServer = &dns.MockServer{
|
||||||
UpdateDNSServerFunc: func(serial uint64, update nbdns.Config) error { return nil },
|
UpdateDNSServerFunc: func(serial uint64, update nbdns.Config) error { return nil },
|
||||||
@ -564,7 +564,7 @@ func TestEngine_UpdateNetworkMapWithRoutes(t *testing.T) {
|
|||||||
WgAddr: wgAddr,
|
WgAddr: wgAddr,
|
||||||
WgPrivateKey: key,
|
WgPrivateKey: key,
|
||||||
WgPort: 33100,
|
WgPort: 33100,
|
||||||
}, MobileDependency{}, peer.NewRecorder("https://mgm"))
|
}, MobileDependency{}, peer.NewRecorder("https://mgm"), nil)
|
||||||
newNet, err := stdnet.NewNet()
|
newNet, err := stdnet.NewNet()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -733,7 +733,7 @@ func TestEngine_UpdateNetworkMapWithDNSUpdate(t *testing.T) {
|
|||||||
WgAddr: wgAddr,
|
WgAddr: wgAddr,
|
||||||
WgPrivateKey: key,
|
WgPrivateKey: key,
|
||||||
WgPort: 33100,
|
WgPort: 33100,
|
||||||
}, MobileDependency{}, peer.NewRecorder("https://mgm"))
|
}, MobileDependency{}, peer.NewRecorder("https://mgm"), nil)
|
||||||
newNet, err := stdnet.NewNet()
|
newNet, err := stdnet.NewNet()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -1002,7 +1002,7 @@ func createEngine(ctx context.Context, cancel context.CancelFunc, setupKey strin
|
|||||||
WgPort: wgPort,
|
WgPort: wgPort,
|
||||||
}
|
}
|
||||||
|
|
||||||
return NewEngine(ctx, cancel, signalClient, mgmtClient, conf, MobileDependency{}, peer.NewRecorder("https://mgm")), nil
|
return NewEngine(ctx, cancel, signalClient, mgmtClient, conf, MobileDependency{}, peer.NewRecorder("https://mgm"), nil), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func startSignal() (*grpc.Server, string, error) {
|
func startSignal() (*grpc.Server, string, error) {
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
|
|
||||||
"google.golang.org/grpc/metadata"
|
"google.golang.org/grpc/metadata"
|
||||||
|
|
||||||
|
"github.com/netbirdio/netbird/management/proto"
|
||||||
"github.com/netbirdio/netbird/version"
|
"github.com/netbirdio/netbird/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -30,6 +31,12 @@ type Environment struct {
|
|||||||
Platform string
|
Platform string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type File struct {
|
||||||
|
Path string
|
||||||
|
Exist bool
|
||||||
|
ProcessIsRunning bool
|
||||||
|
}
|
||||||
|
|
||||||
// Info is an object that contains machine information
|
// Info is an object that contains machine information
|
||||||
// Most of the code is taken from https://github.com/matishsiao/goInfo
|
// Most of the code is taken from https://github.com/matishsiao/goInfo
|
||||||
type Info struct {
|
type Info struct {
|
||||||
@ -48,6 +55,7 @@ type Info struct {
|
|||||||
SystemProductName string
|
SystemProductName string
|
||||||
SystemManufacturer string
|
SystemManufacturer string
|
||||||
Environment Environment
|
Environment Environment
|
||||||
|
Files []File
|
||||||
}
|
}
|
||||||
|
|
||||||
// extractUserAgent extracts Netbird's agent (client) name and version from the outgoing context
|
// extractUserAgent extracts Netbird's agent (client) name and version from the outgoing context
|
||||||
@ -129,3 +137,21 @@ func isDuplicated(addresses []NetworkAddress, addr NetworkAddress) bool {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetInfoWithChecks retrieves and parses the system information with applied checks.
|
||||||
|
func GetInfoWithChecks(ctx context.Context, checks []*proto.Checks) (*Info, error) {
|
||||||
|
processCheckPaths := make([]string, 0)
|
||||||
|
for _, check := range checks {
|
||||||
|
processCheckPaths = append(processCheckPaths, check.GetFiles()...)
|
||||||
|
}
|
||||||
|
|
||||||
|
files, err := checkFileAndProcess(processCheckPaths)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
info := GetInfo(ctx)
|
||||||
|
info.Files = files
|
||||||
|
|
||||||
|
return info, nil
|
||||||
|
}
|
||||||
|
@ -36,6 +36,11 @@ func GetInfo(ctx context.Context) *Info {
|
|||||||
return gio
|
return gio
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// checkFileAndProcess checks if the file path exists and if a process is running at that path.
|
||||||
|
func checkFileAndProcess(paths []string) ([]File, error) {
|
||||||
|
return []File{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func uname() []string {
|
func uname() []string {
|
||||||
res := run("/system/bin/uname", "-a")
|
res := run("/system/bin/uname", "-a")
|
||||||
return strings.Split(res, " ")
|
return strings.Split(res, " ")
|
||||||
|
@ -25,6 +25,11 @@ func GetInfo(ctx context.Context) *Info {
|
|||||||
return gio
|
return gio
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// checkFileAndProcess checks if the file path exists and if a process is running at that path.
|
||||||
|
func checkFileAndProcess(paths []string) ([]File, error) {
|
||||||
|
return []File{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// extractOsVersion extracts operating system version from context or returns the default
|
// extractOsVersion extracts operating system version from context or returns the default
|
||||||
func extractOsVersion(ctx context.Context, defaultName string) string {
|
func extractOsVersion(ctx context.Context, defaultName string) string {
|
||||||
v, ok := ctx.Value(OsVersionCtxKey).(string)
|
v, ok := ctx.Value(OsVersionCtxKey).(string)
|
||||||
|
58
client/system/process.go
Normal file
58
client/system/process.go
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
//go:build windows || (linux && !android) || (darwin && !ios)
|
||||||
|
|
||||||
|
package system
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"slices"
|
||||||
|
|
||||||
|
"github.com/shirou/gopsutil/v3/process"
|
||||||
|
)
|
||||||
|
|
||||||
|
// getRunningProcesses returns a list of running process paths.
|
||||||
|
func getRunningProcesses() ([]string, error) {
|
||||||
|
processes, err := process.Processes()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
processMap := make(map[string]bool)
|
||||||
|
for _, p := range processes {
|
||||||
|
path, _ := p.Exe()
|
||||||
|
if path != "" {
|
||||||
|
processMap[path] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uniqueProcesses := make([]string, 0, len(processMap))
|
||||||
|
for p := range processMap {
|
||||||
|
uniqueProcesses = append(uniqueProcesses, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
return uniqueProcesses, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// checkFileAndProcess checks if the file path exists and if a process is running at that path.
|
||||||
|
func checkFileAndProcess(paths []string) ([]File, error) {
|
||||||
|
files := make([]File, len(paths))
|
||||||
|
if len(paths) == 0 {
|
||||||
|
return files, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
runningProcesses, err := getRunningProcesses()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, path := range paths {
|
||||||
|
file := File{Path: path}
|
||||||
|
|
||||||
|
_, err := os.Stat(path)
|
||||||
|
file.Exist = !os.IsNotExist(err)
|
||||||
|
|
||||||
|
file.ProcessIsRunning = slices.Contains(runningProcesses, path)
|
||||||
|
files[i] = file
|
||||||
|
}
|
||||||
|
|
||||||
|
return files, nil
|
||||||
|
}
|
14
go.mod
14
go.mod
@ -22,7 +22,7 @@ require (
|
|||||||
github.com/spf13/pflag v1.0.5
|
github.com/spf13/pflag v1.0.5
|
||||||
github.com/vishvananda/netlink v1.1.1-0.20211118161826-650dca95af54
|
github.com/vishvananda/netlink v1.1.1-0.20211118161826-650dca95af54
|
||||||
golang.org/x/crypto v0.18.0
|
golang.org/x/crypto v0.18.0
|
||||||
golang.org/x/sys v0.16.0
|
golang.org/x/sys v0.18.0
|
||||||
golang.zx2c4.com/wireguard v0.0.0-20230704135630-469159ecf7d1
|
golang.zx2c4.com/wireguard v0.0.0-20230704135630-469159ecf7d1
|
||||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
|
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
|
||||||
golang.zx2c4.com/wireguard/windows v0.5.3
|
golang.zx2c4.com/wireguard/windows v0.5.3
|
||||||
@ -44,7 +44,7 @@ require (
|
|||||||
github.com/gliderlabs/ssh v0.3.4
|
github.com/gliderlabs/ssh v0.3.4
|
||||||
github.com/godbus/dbus/v5 v5.1.0
|
github.com/godbus/dbus/v5 v5.1.0
|
||||||
github.com/golang/mock v1.6.0
|
github.com/golang/mock v1.6.0
|
||||||
github.com/google/go-cmp v0.5.9
|
github.com/google/go-cmp v0.6.0
|
||||||
github.com/google/gopacket v1.1.19
|
github.com/google/gopacket v1.1.19
|
||||||
github.com/google/martian/v3 v3.0.0
|
github.com/google/martian/v3 v3.0.0
|
||||||
github.com/google/nftables v0.0.0-20220808154552-2eca00135732
|
github.com/google/nftables v0.0.0-20220808154552-2eca00135732
|
||||||
@ -70,10 +70,11 @@ require (
|
|||||||
github.com/pion/turn/v3 v3.0.1
|
github.com/pion/turn/v3 v3.0.1
|
||||||
github.com/prometheus/client_golang v1.14.0
|
github.com/prometheus/client_golang v1.14.0
|
||||||
github.com/rs/xid v1.3.0
|
github.com/rs/xid v1.3.0
|
||||||
|
github.com/shirou/gopsutil/v3 v3.24.3
|
||||||
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966
|
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966
|
||||||
github.com/stretchr/testify v1.8.4
|
github.com/stretchr/testify v1.9.0
|
||||||
github.com/things-go/go-socks5 v0.0.4
|
github.com/things-go/go-socks5 v0.0.4
|
||||||
github.com/yusufpapurcu/wmi v1.2.3
|
github.com/yusufpapurcu/wmi v1.2.4
|
||||||
github.com/zcalusic/sysinfo v1.0.2
|
github.com/zcalusic/sysinfo v1.0.2
|
||||||
go.opentelemetry.io/otel v1.11.1
|
go.opentelemetry.io/otel v1.11.1
|
||||||
go.opentelemetry.io/otel/exporters/prometheus v0.33.0
|
go.opentelemetry.io/otel/exporters/prometheus v0.33.0
|
||||||
@ -131,6 +132,7 @@ require (
|
|||||||
github.com/jinzhu/now v1.1.5 // indirect
|
github.com/jinzhu/now v1.1.5 // indirect
|
||||||
github.com/josharian/native v1.1.0 // indirect
|
github.com/josharian/native v1.1.0 // indirect
|
||||||
github.com/kelseyhightower/envconfig v1.4.0 // indirect
|
github.com/kelseyhightower/envconfig v1.4.0 // indirect
|
||||||
|
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||||
github.com/mdlayher/genetlink v1.3.2 // indirect
|
github.com/mdlayher/genetlink v1.3.2 // indirect
|
||||||
github.com/mdlayher/netlink v1.7.2 // indirect
|
github.com/mdlayher/netlink v1.7.2 // indirect
|
||||||
@ -142,12 +144,16 @@ require (
|
|||||||
github.com/pion/randutil v0.1.0 // indirect
|
github.com/pion/randutil v0.1.0 // indirect
|
||||||
github.com/pion/transport/v2 v2.2.4 // indirect
|
github.com/pion/transport/v2 v2.2.4 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||||
github.com/prometheus/client_model v0.3.0 // indirect
|
github.com/prometheus/client_model v0.3.0 // indirect
|
||||||
github.com/prometheus/common v0.37.0 // indirect
|
github.com/prometheus/common v0.37.0 // indirect
|
||||||
github.com/prometheus/procfs v0.8.0 // indirect
|
github.com/prometheus/procfs v0.8.0 // indirect
|
||||||
|
github.com/shoenig/go-m1cpu v0.1.6 // indirect
|
||||||
github.com/spf13/cast v1.5.0 // indirect
|
github.com/spf13/cast v1.5.0 // indirect
|
||||||
github.com/srwiley/oksvg v0.0.0-20200311192757-870daf9aa564 // indirect
|
github.com/srwiley/oksvg v0.0.0-20200311192757-870daf9aa564 // indirect
|
||||||
github.com/srwiley/rasterx v0.0.0-20200120212402-85cb7272f5e9 // indirect
|
github.com/srwiley/rasterx v0.0.0-20200120212402-85cb7272f5e9 // indirect
|
||||||
|
github.com/tklauser/go-sysconf v0.3.13 // indirect
|
||||||
|
github.com/tklauser/numcpus v0.7.0 // indirect
|
||||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
|
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
|
||||||
github.com/yuin/goldmark v1.4.13 // indirect
|
github.com/yuin/goldmark v1.4.13 // indirect
|
||||||
go.opencensus.io v0.24.0 // indirect
|
go.opencensus.io v0.24.0 // indirect
|
||||||
|
32
go.sum
32
go.sum
@ -247,9 +247,11 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||||||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
|
||||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
|
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
|
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
|
||||||
@ -348,6 +350,8 @@ github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdA
|
|||||||
github.com/libp2p/go-netroute v0.2.1 h1:V8kVrpD8GK0Riv15/7VN6RbUQ3URNZVosw7H2v9tksU=
|
github.com/libp2p/go-netroute v0.2.1 h1:V8kVrpD8GK0Riv15/7VN6RbUQ3URNZVosw7H2v9tksU=
|
||||||
github.com/libp2p/go-netroute v0.2.1/go.mod h1:hraioZr0fhBjG0ZRXJJ6Zj2IVEVNx6tDTFQfSmcq7mQ=
|
github.com/libp2p/go-netroute v0.2.1/go.mod h1:hraioZr0fhBjG0ZRXJJ6Zj2IVEVNx6tDTFQfSmcq7mQ=
|
||||||
github.com/lucor/goinfo v0.0.0-20210802170112-c078a2b0f08b/go.mod h1:PRq09yoB+Q2OJReAmwzKivcYyremnibWGbK7WfftHzc=
|
github.com/lucor/goinfo v0.0.0-20210802170112-c078a2b0f08b/go.mod h1:PRq09yoB+Q2OJReAmwzKivcYyremnibWGbK7WfftHzc=
|
||||||
|
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
|
||||||
|
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||||
github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls=
|
github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls=
|
||||||
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||||
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
@ -449,6 +453,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
|
|||||||
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
|
||||||
|
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||||
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||||
@ -485,6 +491,12 @@ github.com/rs/xid v1.3.0 h1:6NjYksEUlhurdVehpc7S7dk6DAmcKv8V9gG0FsVN2U4=
|
|||||||
github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
|
github.com/shirou/gopsutil/v3 v3.24.3 h1:eoUGJSmdfLzJ3mxIhmOAhgKEKgQkeOwKpz1NbhVnuPE=
|
||||||
|
github.com/shirou/gopsutil/v3 v3.24.3/go.mod h1:JpND7O217xa72ewWz9zN2eIIkPWsDN/3pl0H8Qt0uwg=
|
||||||
|
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
|
||||||
|
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
|
||||||
|
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
|
||||||
|
github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
|
||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
@ -514,6 +526,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
|||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
|
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||||
github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
@ -524,10 +537,17 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
|||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/things-go/go-socks5 v0.0.4 h1:jMQjIc+qhD4z9cITOMnBiwo9dDmpGuXmBlkRFrl/qD0=
|
github.com/things-go/go-socks5 v0.0.4 h1:jMQjIc+qhD4z9cITOMnBiwo9dDmpGuXmBlkRFrl/qD0=
|
||||||
github.com/things-go/go-socks5 v0.0.4/go.mod h1:sh4K6WHrmHZpjxLTCHyYtXYH8OUuD+yZun41NomR1IQ=
|
github.com/things-go/go-socks5 v0.0.4/go.mod h1:sh4K6WHrmHZpjxLTCHyYtXYH8OUuD+yZun41NomR1IQ=
|
||||||
|
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
|
||||||
|
github.com/tklauser/go-sysconf v0.3.13 h1:GBUpcahXSpR2xN01jhkNAbTLRk2Yzgggk8IM08lq3r4=
|
||||||
|
github.com/tklauser/go-sysconf v0.3.13/go.mod h1:zwleP4Q4OehZHGn4CYZDipCgg9usW5IJePewFCGVEa0=
|
||||||
|
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
|
||||||
|
github.com/tklauser/numcpus v0.7.0 h1:yjuerZP127QG9m5Zh/mSO4wqurYil27tHrqwRoRjpr4=
|
||||||
|
github.com/tklauser/numcpus v0.7.0/go.mod h1:bb6dMVcj8A42tSE7i32fsIUCbQNllK5iDguyOZRUzAY=
|
||||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||||
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
||||||
@ -544,8 +564,8 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1
|
|||||||
github.com/yuin/goldmark v1.3.8/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
github.com/yuin/goldmark v1.3.8/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE=
|
github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE=
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw=
|
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
|
||||||
github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||||
github.com/zcalusic/sysinfo v1.0.2 h1:nwTTo2a+WQ0NXwo0BGRojOJvJ/5XKvQih+2RrtWqfxc=
|
github.com/zcalusic/sysinfo v1.0.2 h1:nwTTo2a+WQ0NXwo0BGRojOJvJ/5XKvQih+2RrtWqfxc=
|
||||||
github.com/zcalusic/sysinfo v1.0.2/go.mod h1:kluzTYflRWo6/tXVMJPdEjShsbPpsFRyy+p1mBQPC30=
|
github.com/zcalusic/sysinfo v1.0.2/go.mod h1:kluzTYflRWo6/tXVMJPdEjShsbPpsFRyy+p1mBQPC30=
|
||||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||||
@ -740,6 +760,7 @@ golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@ -761,8 +782,9 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|||||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
|
|
||||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
||||||
|
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
|
@ -3,19 +3,21 @@ package client
|
|||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/client/system"
|
"github.com/netbirdio/netbird/client/system"
|
||||||
"github.com/netbirdio/netbird/management/proto"
|
"github.com/netbirdio/netbird/management/proto"
|
||||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Client interface {
|
type Client interface {
|
||||||
io.Closer
|
io.Closer
|
||||||
Sync(msgHandler func(msg *proto.SyncResponse) error) error
|
Sync(sysInfo *system.Info, msgHandler func(msg *proto.SyncResponse) error) error
|
||||||
GetServerPublicKey() (*wgtypes.Key, error)
|
GetServerPublicKey() (*wgtypes.Key, error)
|
||||||
Register(serverKey wgtypes.Key, setupKey string, jwtToken string, sysInfo *system.Info, sshKey []byte) (*proto.LoginResponse, error)
|
Register(serverKey wgtypes.Key, setupKey string, jwtToken string, sysInfo *system.Info, sshKey []byte) (*proto.LoginResponse, error)
|
||||||
Login(serverKey wgtypes.Key, sysInfo *system.Info, sshKey []byte) (*proto.LoginResponse, error)
|
Login(serverKey wgtypes.Key, sysInfo *system.Info, sshKey []byte) (*proto.LoginResponse, error)
|
||||||
GetDeviceAuthorizationFlow(serverKey wgtypes.Key) (*proto.DeviceAuthorizationFlow, error)
|
GetDeviceAuthorizationFlow(serverKey wgtypes.Key) (*proto.DeviceAuthorizationFlow, error)
|
||||||
GetPKCEAuthorizationFlow(serverKey wgtypes.Key) (*proto.PKCEAuthorizationFlow, error)
|
GetPKCEAuthorizationFlow(serverKey wgtypes.Key) (*proto.PKCEAuthorizationFlow, error)
|
||||||
GetNetworkMap() (*proto.NetworkMap, error)
|
GetNetworkMap(sysInfo *system.Info) (*proto.NetworkMap, error)
|
||||||
IsHealthy() bool
|
IsHealthy() bool
|
||||||
|
SyncMeta(sysInfo *system.Info) error
|
||||||
}
|
}
|
||||||
|
@ -255,7 +255,7 @@ func TestClient_Sync(t *testing.T) {
|
|||||||
ch := make(chan *mgmtProto.SyncResponse, 1)
|
ch := make(chan *mgmtProto.SyncResponse, 1)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
err = client.Sync(func(msg *mgmtProto.SyncResponse) error {
|
err = client.Sync(info, func(msg *mgmtProto.SyncResponse) error {
|
||||||
ch <- msg
|
ch <- msg
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
@ -113,7 +113,7 @@ func (c *GrpcClient) ready() bool {
|
|||||||
|
|
||||||
// Sync wraps the real client's Sync endpoint call and takes care of retries and encryption/decryption of messages
|
// Sync wraps the real client's Sync endpoint call and takes care of retries and encryption/decryption of messages
|
||||||
// Blocking request. The result will be sent via msgHandler callback function
|
// Blocking request. The result will be sent via msgHandler callback function
|
||||||
func (c *GrpcClient) Sync(msgHandler func(msg *proto.SyncResponse) error) error {
|
func (c *GrpcClient) Sync(sysInfo *system.Info, msgHandler func(msg *proto.SyncResponse) error) error {
|
||||||
backOff := defaultBackoff(c.ctx)
|
backOff := defaultBackoff(c.ctx)
|
||||||
|
|
||||||
operation := func() error {
|
operation := func() error {
|
||||||
@ -135,7 +135,7 @@ func (c *GrpcClient) Sync(msgHandler func(msg *proto.SyncResponse) error) error
|
|||||||
|
|
||||||
ctx, cancelStream := context.WithCancel(c.ctx)
|
ctx, cancelStream := context.WithCancel(c.ctx)
|
||||||
defer cancelStream()
|
defer cancelStream()
|
||||||
stream, err := c.connectToStream(ctx, *serverPubKey)
|
stream, err := c.connectToStream(ctx, *serverPubKey, sysInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debugf("failed to open Management Service stream: %s", err)
|
log.Debugf("failed to open Management Service stream: %s", err)
|
||||||
if s, ok := gstatus.FromError(err); ok && s.Code() == codes.PermissionDenied {
|
if s, ok := gstatus.FromError(err); ok && s.Code() == codes.PermissionDenied {
|
||||||
@ -177,7 +177,7 @@ func (c *GrpcClient) Sync(msgHandler func(msg *proto.SyncResponse) error) error
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetNetworkMap return with the network map
|
// GetNetworkMap return with the network map
|
||||||
func (c *GrpcClient) GetNetworkMap() (*proto.NetworkMap, error) {
|
func (c *GrpcClient) GetNetworkMap(sysInfo *system.Info) (*proto.NetworkMap, error) {
|
||||||
serverPubKey, err := c.GetServerPublicKey()
|
serverPubKey, err := c.GetServerPublicKey()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debugf("failed getting Management Service public key: %s", err)
|
log.Debugf("failed getting Management Service public key: %s", err)
|
||||||
@ -186,7 +186,7 @@ func (c *GrpcClient) GetNetworkMap() (*proto.NetworkMap, error) {
|
|||||||
|
|
||||||
ctx, cancelStream := context.WithCancel(c.ctx)
|
ctx, cancelStream := context.WithCancel(c.ctx)
|
||||||
defer cancelStream()
|
defer cancelStream()
|
||||||
stream, err := c.connectToStream(ctx, *serverPubKey)
|
stream, err := c.connectToStream(ctx, *serverPubKey, sysInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debugf("failed to open Management Service stream: %s", err)
|
log.Debugf("failed to open Management Service stream: %s", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -219,8 +219,8 @@ func (c *GrpcClient) GetNetworkMap() (*proto.NetworkMap, error) {
|
|||||||
return decryptedResp.GetNetworkMap(), nil
|
return decryptedResp.GetNetworkMap(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *GrpcClient) connectToStream(ctx context.Context, serverPubKey wgtypes.Key) (proto.ManagementService_SyncClient, error) {
|
func (c *GrpcClient) connectToStream(ctx context.Context, serverPubKey wgtypes.Key, sysInfo *system.Info) (proto.ManagementService_SyncClient, error) {
|
||||||
req := &proto.SyncRequest{}
|
req := &proto.SyncRequest{Meta: infoToMetaData(sysInfo)}
|
||||||
|
|
||||||
myPrivateKey := c.key
|
myPrivateKey := c.key
|
||||||
myPublicKey := myPrivateKey.PublicKey()
|
myPublicKey := myPrivateKey.PublicKey()
|
||||||
@ -430,6 +430,35 @@ func (c *GrpcClient) GetPKCEAuthorizationFlow(serverKey wgtypes.Key) (*proto.PKC
|
|||||||
return flowInfoResp, nil
|
return flowInfoResp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SyncMeta sends updated system metadata to the Management Service.
|
||||||
|
// It should be used if there is changes on peer posture check after initial sync.
|
||||||
|
func (c *GrpcClient) SyncMeta(sysInfo *system.Info) error {
|
||||||
|
if !c.ready() {
|
||||||
|
return fmt.Errorf("no connection to management")
|
||||||
|
}
|
||||||
|
|
||||||
|
serverPubKey, err := c.GetServerPublicKey()
|
||||||
|
if err != nil {
|
||||||
|
log.Debugf("failed getting Management Service public key: %s", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
syncMetaReq, err := encryption.EncryptMessage(*serverPubKey, c.key, &proto.SyncMetaRequest{Meta: infoToMetaData(sysInfo)})
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("failed to encrypt message: %s", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
mgmCtx, cancel := context.WithTimeout(c.ctx, ConnectTimeout)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
_, err = c.realClient.SyncMeta(mgmCtx, &proto.EncryptedMessage{
|
||||||
|
WgPubKey: c.key.PublicKey().String(),
|
||||||
|
Body: syncMetaReq,
|
||||||
|
})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func (c *GrpcClient) notifyDisconnected(err error) {
|
func (c *GrpcClient) notifyDisconnected(err error) {
|
||||||
c.connStateCallbackLock.RLock()
|
c.connStateCallbackLock.RLock()
|
||||||
defer c.connStateCallbackLock.RUnlock()
|
defer c.connStateCallbackLock.RUnlock()
|
||||||
@ -463,6 +492,15 @@ func infoToMetaData(info *system.Info) *proto.PeerSystemMeta {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
files := make([]*proto.File, 0, len(info.Files))
|
||||||
|
for _, file := range info.Files {
|
||||||
|
files = append(files, &proto.File{
|
||||||
|
Path: file.Path,
|
||||||
|
Exist: file.Exist,
|
||||||
|
ProcessIsRunning: file.ProcessIsRunning,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return &proto.PeerSystemMeta{
|
return &proto.PeerSystemMeta{
|
||||||
Hostname: info.Hostname,
|
Hostname: info.Hostname,
|
||||||
GoOS: info.GoOS,
|
GoOS: info.GoOS,
|
||||||
@ -482,5 +520,6 @@ func infoToMetaData(info *system.Info) *proto.PeerSystemMeta {
|
|||||||
Cloud: info.Environment.Cloud,
|
Cloud: info.Environment.Cloud,
|
||||||
Platform: info.Environment.Platform,
|
Platform: info.Environment.Platform,
|
||||||
},
|
},
|
||||||
|
Files: files,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,12 +9,13 @@ import (
|
|||||||
|
|
||||||
type MockClient struct {
|
type MockClient struct {
|
||||||
CloseFunc func() error
|
CloseFunc func() error
|
||||||
SyncFunc func(msgHandler func(msg *proto.SyncResponse) error) error
|
SyncFunc func(sysInfo *system.Info, msgHandler func(msg *proto.SyncResponse) error) error
|
||||||
GetServerPublicKeyFunc func() (*wgtypes.Key, error)
|
GetServerPublicKeyFunc func() (*wgtypes.Key, error)
|
||||||
RegisterFunc func(serverKey wgtypes.Key, setupKey string, jwtToken string, info *system.Info, sshKey []byte) (*proto.LoginResponse, error)
|
RegisterFunc func(serverKey wgtypes.Key, setupKey string, jwtToken string, info *system.Info, sshKey []byte) (*proto.LoginResponse, error)
|
||||||
LoginFunc func(serverKey wgtypes.Key, info *system.Info, sshKey []byte) (*proto.LoginResponse, error)
|
LoginFunc func(serverKey wgtypes.Key, info *system.Info, sshKey []byte) (*proto.LoginResponse, error)
|
||||||
GetDeviceAuthorizationFlowFunc func(serverKey wgtypes.Key) (*proto.DeviceAuthorizationFlow, error)
|
GetDeviceAuthorizationFlowFunc func(serverKey wgtypes.Key) (*proto.DeviceAuthorizationFlow, error)
|
||||||
GetPKCEAuthorizationFlowFunc func(serverKey wgtypes.Key) (*proto.PKCEAuthorizationFlow, error)
|
GetPKCEAuthorizationFlowFunc func(serverKey wgtypes.Key) (*proto.PKCEAuthorizationFlow, error)
|
||||||
|
SyncMetaFunc func(sysInfo *system.Info) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MockClient) IsHealthy() bool {
|
func (m *MockClient) IsHealthy() bool {
|
||||||
@ -28,11 +29,11 @@ func (m *MockClient) Close() error {
|
|||||||
return m.CloseFunc()
|
return m.CloseFunc()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MockClient) Sync(msgHandler func(msg *proto.SyncResponse) error) error {
|
func (m *MockClient) Sync(sysInfo *system.Info, msgHandler func(msg *proto.SyncResponse) error) error {
|
||||||
if m.SyncFunc == nil {
|
if m.SyncFunc == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return m.SyncFunc(msgHandler)
|
return m.SyncFunc(sysInfo, msgHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MockClient) GetServerPublicKey() (*wgtypes.Key, error) {
|
func (m *MockClient) GetServerPublicKey() (*wgtypes.Key, error) {
|
||||||
@ -71,6 +72,13 @@ func (m *MockClient) GetPKCEAuthorizationFlow(serverKey wgtypes.Key) (*proto.PKC
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetNetworkMap mock implementation of GetNetworkMap from mgm.Client interface
|
// GetNetworkMap mock implementation of GetNetworkMap from mgm.Client interface
|
||||||
func (m *MockClient) GetNetworkMap() (*proto.NetworkMap, error) {
|
func (m *MockClient) GetNetworkMap(_ *system.Info) (*proto.NetworkMap, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *MockClient) SyncMeta(sysInfo *system.Info) error {
|
||||||
|
if m.SyncMetaFunc == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return m.SyncMetaFunc(sysInfo)
|
||||||
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -38,6 +38,12 @@ service ManagementService {
|
|||||||
// EncryptedMessage of the request has a body of PKCEAuthorizationFlowRequest.
|
// EncryptedMessage of the request has a body of PKCEAuthorizationFlowRequest.
|
||||||
// EncryptedMessage of the response has a body of PKCEAuthorizationFlow.
|
// EncryptedMessage of the response has a body of PKCEAuthorizationFlow.
|
||||||
rpc GetPKCEAuthorizationFlow(EncryptedMessage) returns (EncryptedMessage) {}
|
rpc GetPKCEAuthorizationFlow(EncryptedMessage) returns (EncryptedMessage) {}
|
||||||
|
|
||||||
|
// SyncMeta is used to sync metadata of the peer.
|
||||||
|
// After sync the peer if there is a change in peer posture check which needs to be evaluated by the client,
|
||||||
|
// sync meta will evaluate the checks and update the peer meta with the result.
|
||||||
|
// EncryptedMessage of the request has a body of Empty.
|
||||||
|
rpc SyncMeta(EncryptedMessage) returns (Empty) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
message EncryptedMessage {
|
message EncryptedMessage {
|
||||||
@ -50,7 +56,10 @@ message EncryptedMessage {
|
|||||||
int32 version = 3;
|
int32 version = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message SyncRequest {}
|
message SyncRequest {
|
||||||
|
// Meta data of the peer
|
||||||
|
PeerSystemMeta meta = 1;
|
||||||
|
}
|
||||||
|
|
||||||
// SyncResponse represents a state that should be applied to the local peer (e.g. Wiretrustee servers config as well as local peer and remote peers configs)
|
// SyncResponse represents a state that should be applied to the local peer (e.g. Wiretrustee servers config as well as local peer and remote peers configs)
|
||||||
message SyncResponse {
|
message SyncResponse {
|
||||||
@ -69,6 +78,14 @@ message SyncResponse {
|
|||||||
bool remotePeersIsEmpty = 4;
|
bool remotePeersIsEmpty = 4;
|
||||||
|
|
||||||
NetworkMap NetworkMap = 5;
|
NetworkMap NetworkMap = 5;
|
||||||
|
|
||||||
|
// Posture checks to be evaluated by client
|
||||||
|
repeated Checks Checks = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SyncMetaRequest {
|
||||||
|
// Meta data of the peer
|
||||||
|
PeerSystemMeta meta = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message LoginRequest {
|
message LoginRequest {
|
||||||
@ -82,6 +99,7 @@ message LoginRequest {
|
|||||||
PeerKeys peerKeys = 4;
|
PeerKeys peerKeys = 4;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PeerKeys is additional peer info like SSH pub key and WireGuard public key.
|
// PeerKeys is additional peer info like SSH pub key and WireGuard public key.
|
||||||
// This message is sent on Login or register requests, or when a key rotation has to happen.
|
// This message is sent on Login or register requests, or when a key rotation has to happen.
|
||||||
message PeerKeys {
|
message PeerKeys {
|
||||||
@ -100,6 +118,16 @@ message Environment {
|
|||||||
string platform = 2;
|
string platform = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// File represents a file on the system.
|
||||||
|
message File {
|
||||||
|
// path is the path to the file.
|
||||||
|
string path = 1;
|
||||||
|
// exist indicate whether the file exists.
|
||||||
|
bool exist = 2;
|
||||||
|
// processIsRunning indicates whether the file is a running process or not.
|
||||||
|
bool processIsRunning = 3;
|
||||||
|
}
|
||||||
|
|
||||||
// PeerSystemMeta is machine meta data like OS and version.
|
// PeerSystemMeta is machine meta data like OS and version.
|
||||||
message PeerSystemMeta {
|
message PeerSystemMeta {
|
||||||
string hostname = 1;
|
string hostname = 1;
|
||||||
@ -117,6 +145,7 @@ message PeerSystemMeta {
|
|||||||
string sysProductName = 13;
|
string sysProductName = 13;
|
||||||
string sysManufacturer = 14;
|
string sysManufacturer = 14;
|
||||||
Environment environment = 15;
|
Environment environment = 15;
|
||||||
|
repeated File files = 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
message LoginResponse {
|
message LoginResponse {
|
||||||
@ -124,6 +153,8 @@ message LoginResponse {
|
|||||||
WiretrusteeConfig wiretrusteeConfig = 1;
|
WiretrusteeConfig wiretrusteeConfig = 1;
|
||||||
// Peer local config
|
// Peer local config
|
||||||
PeerConfig peerConfig = 2;
|
PeerConfig peerConfig = 2;
|
||||||
|
// Posture checks to be evaluated by client
|
||||||
|
repeated Checks Checks = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ServerKeyResponse {
|
message ServerKeyResponse {
|
||||||
@ -371,3 +402,7 @@ message NetworkAddress {
|
|||||||
string netIP = 1;
|
string netIP = 1;
|
||||||
string mac = 2;
|
string mac = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message Checks {
|
||||||
|
repeated string Files= 1;
|
||||||
|
}
|
||||||
|
@ -43,6 +43,11 @@ type ManagementServiceClient interface {
|
|||||||
// EncryptedMessage of the request has a body of PKCEAuthorizationFlowRequest.
|
// EncryptedMessage of the request has a body of PKCEAuthorizationFlowRequest.
|
||||||
// EncryptedMessage of the response has a body of PKCEAuthorizationFlow.
|
// EncryptedMessage of the response has a body of PKCEAuthorizationFlow.
|
||||||
GetPKCEAuthorizationFlow(ctx context.Context, in *EncryptedMessage, opts ...grpc.CallOption) (*EncryptedMessage, error)
|
GetPKCEAuthorizationFlow(ctx context.Context, in *EncryptedMessage, opts ...grpc.CallOption) (*EncryptedMessage, error)
|
||||||
|
// SyncMeta is used to sync metadata of the peer.
|
||||||
|
// After sync the peer if there is a change in peer posture check which needs to be evaluated by the client,
|
||||||
|
// sync meta will evaluate the checks and update the peer meta with the result.
|
||||||
|
// EncryptedMessage of the request has a body of Empty.
|
||||||
|
SyncMeta(ctx context.Context, in *EncryptedMessage, opts ...grpc.CallOption) (*Empty, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type managementServiceClient struct {
|
type managementServiceClient struct {
|
||||||
@ -130,6 +135,15 @@ func (c *managementServiceClient) GetPKCEAuthorizationFlow(ctx context.Context,
|
|||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *managementServiceClient) SyncMeta(ctx context.Context, in *EncryptedMessage, opts ...grpc.CallOption) (*Empty, error) {
|
||||||
|
out := new(Empty)
|
||||||
|
err := c.cc.Invoke(ctx, "/management.ManagementService/SyncMeta", in, out, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
// ManagementServiceServer is the server API for ManagementService service.
|
// ManagementServiceServer is the server API for ManagementService service.
|
||||||
// All implementations must embed UnimplementedManagementServiceServer
|
// All implementations must embed UnimplementedManagementServiceServer
|
||||||
// for forward compatibility
|
// for forward compatibility
|
||||||
@ -159,6 +173,11 @@ type ManagementServiceServer interface {
|
|||||||
// EncryptedMessage of the request has a body of PKCEAuthorizationFlowRequest.
|
// EncryptedMessage of the request has a body of PKCEAuthorizationFlowRequest.
|
||||||
// EncryptedMessage of the response has a body of PKCEAuthorizationFlow.
|
// EncryptedMessage of the response has a body of PKCEAuthorizationFlow.
|
||||||
GetPKCEAuthorizationFlow(context.Context, *EncryptedMessage) (*EncryptedMessage, error)
|
GetPKCEAuthorizationFlow(context.Context, *EncryptedMessage) (*EncryptedMessage, error)
|
||||||
|
// SyncMeta is used to sync metadata of the peer.
|
||||||
|
// After sync the peer if there is a change in peer posture check which needs to be evaluated by the client,
|
||||||
|
// sync meta will evaluate the checks and update the peer meta with the result.
|
||||||
|
// EncryptedMessage of the request has a body of Empty.
|
||||||
|
SyncMeta(context.Context, *EncryptedMessage) (*Empty, error)
|
||||||
mustEmbedUnimplementedManagementServiceServer()
|
mustEmbedUnimplementedManagementServiceServer()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,6 +203,9 @@ func (UnimplementedManagementServiceServer) GetDeviceAuthorizationFlow(context.C
|
|||||||
func (UnimplementedManagementServiceServer) GetPKCEAuthorizationFlow(context.Context, *EncryptedMessage) (*EncryptedMessage, error) {
|
func (UnimplementedManagementServiceServer) GetPKCEAuthorizationFlow(context.Context, *EncryptedMessage) (*EncryptedMessage, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method GetPKCEAuthorizationFlow not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method GetPKCEAuthorizationFlow not implemented")
|
||||||
}
|
}
|
||||||
|
func (UnimplementedManagementServiceServer) SyncMeta(context.Context, *EncryptedMessage) (*Empty, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method SyncMeta not implemented")
|
||||||
|
}
|
||||||
func (UnimplementedManagementServiceServer) mustEmbedUnimplementedManagementServiceServer() {}
|
func (UnimplementedManagementServiceServer) mustEmbedUnimplementedManagementServiceServer() {}
|
||||||
|
|
||||||
// UnsafeManagementServiceServer may be embedded to opt out of forward compatibility for this service.
|
// UnsafeManagementServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||||
@ -308,6 +330,24 @@ func _ManagementService_GetPKCEAuthorizationFlow_Handler(srv interface{}, ctx co
|
|||||||
return interceptor(ctx, in, info, handler)
|
return interceptor(ctx, in, info, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func _ManagementService_SyncMeta_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(EncryptedMessage)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(ManagementServiceServer).SyncMeta(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: "/management.ManagementService/SyncMeta",
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(ManagementServiceServer).SyncMeta(ctx, req.(*EncryptedMessage))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
// ManagementService_ServiceDesc is the grpc.ServiceDesc for ManagementService service.
|
// ManagementService_ServiceDesc is the grpc.ServiceDesc for ManagementService service.
|
||||||
// It's only intended for direct use with grpc.RegisterService,
|
// It's only intended for direct use with grpc.RegisterService,
|
||||||
// and not to be introspected or modified (even as a copy)
|
// and not to be introspected or modified (even as a copy)
|
||||||
@ -335,6 +375,10 @@ var ManagementService_ServiceDesc = grpc.ServiceDesc{
|
|||||||
MethodName: "GetPKCEAuthorizationFlow",
|
MethodName: "GetPKCEAuthorizationFlow",
|
||||||
Handler: _ManagementService_GetPKCEAuthorizationFlow_Handler,
|
Handler: _ManagementService_GetPKCEAuthorizationFlow_Handler,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
MethodName: "SyncMeta",
|
||||||
|
Handler: _ManagementService_SyncMeta_Handler,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Streams: []grpc.StreamDesc{
|
Streams: []grpc.StreamDesc{
|
||||||
{
|
{
|
||||||
|
@ -114,6 +114,7 @@ type AccountManager interface {
|
|||||||
GetDNSSettings(accountID string, userID string) (*DNSSettings, error)
|
GetDNSSettings(accountID string, userID string) (*DNSSettings, error)
|
||||||
SaveDNSSettings(accountID string, userID string, dnsSettingsToSave *DNSSettings) error
|
SaveDNSSettings(accountID string, userID string, dnsSettingsToSave *DNSSettings) error
|
||||||
GetPeer(accountID, peerID, userID string) (*nbpeer.Peer, error)
|
GetPeer(accountID, peerID, userID string) (*nbpeer.Peer, error)
|
||||||
|
GetPeerAppliedPostureChecks(peerKey string) ([]posture.Checks, error)
|
||||||
UpdateAccountSettings(accountID, userID string, newSettings *Settings) (*Account, error)
|
UpdateAccountSettings(accountID, userID string, newSettings *Settings) (*Account, error)
|
||||||
LoginPeer(login PeerLogin) (*nbpeer.Peer, *NetworkMap, error) // used by peer gRPC API
|
LoginPeer(login PeerLogin) (*nbpeer.Peer, *NetworkMap, error) // used by peer gRPC API
|
||||||
SyncPeer(sync PeerSync) (*nbpeer.Peer, *NetworkMap, error) // used by peer gRPC API
|
SyncPeer(sync PeerSync) (*nbpeer.Peer, *NetworkMap, error) // used by peer gRPC API
|
||||||
|
@ -134,7 +134,14 @@ func (s *GRPCServer) Sync(req *proto.EncryptedMessage, srv proto.ManagementServi
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
peer, netMap, err := s.accountManager.SyncPeer(PeerSync{WireGuardPubKey: peerKey.String()})
|
if syncReq.GetMeta() == nil {
|
||||||
|
log.Tracef("peer system meta has to be provided on sync. Peer %s, remote addr %s", peerKey.String(), realIP)
|
||||||
|
}
|
||||||
|
|
||||||
|
peer, netMap, err := s.accountManager.SyncPeer(PeerSync{
|
||||||
|
WireGuardPubKey: peerKey.String(),
|
||||||
|
Meta: extractPeerMeta(syncReq.GetMeta()),
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return mapError(err)
|
return mapError(err)
|
||||||
}
|
}
|
||||||
@ -255,14 +262,18 @@ func mapError(err error) error {
|
|||||||
return status.Errorf(codes.Internal, "failed handling request")
|
return status.Errorf(codes.Internal, "failed handling request")
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractPeerMeta(loginReq *proto.LoginRequest) nbpeer.PeerSystemMeta {
|
func extractPeerMeta(meta *proto.PeerSystemMeta) nbpeer.PeerSystemMeta {
|
||||||
osVersion := loginReq.GetMeta().GetOSVersion()
|
if meta == nil {
|
||||||
if osVersion == "" {
|
return nbpeer.PeerSystemMeta{}
|
||||||
osVersion = loginReq.GetMeta().GetCore()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
networkAddresses := make([]nbpeer.NetworkAddress, 0, len(loginReq.GetMeta().GetNetworkAddresses()))
|
osVersion := meta.GetOSVersion()
|
||||||
for _, addr := range loginReq.GetMeta().GetNetworkAddresses() {
|
if osVersion == "" {
|
||||||
|
osVersion = meta.GetCore()
|
||||||
|
}
|
||||||
|
|
||||||
|
networkAddresses := make([]nbpeer.NetworkAddress, 0, len(meta.GetNetworkAddresses()))
|
||||||
|
for _, addr := range meta.GetNetworkAddresses() {
|
||||||
netAddr, err := netip.ParsePrefix(addr.GetNetIP())
|
netAddr, err := netip.ParsePrefix(addr.GetNetIP())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf("failed to parse netip address, %s: %v", addr.GetNetIP(), err)
|
log.Warnf("failed to parse netip address, %s: %v", addr.GetNetIP(), err)
|
||||||
@ -274,24 +285,34 @@ func extractPeerMeta(loginReq *proto.LoginRequest) nbpeer.PeerSystemMeta {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
files := make([]nbpeer.File, 0, len(meta.GetFiles()))
|
||||||
|
for _, file := range meta.GetFiles() {
|
||||||
|
files = append(files, nbpeer.File{
|
||||||
|
Path: file.GetPath(),
|
||||||
|
Exist: file.GetExist(),
|
||||||
|
ProcessIsRunning: file.GetProcessIsRunning(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return nbpeer.PeerSystemMeta{
|
return nbpeer.PeerSystemMeta{
|
||||||
Hostname: loginReq.GetMeta().GetHostname(),
|
Hostname: meta.GetHostname(),
|
||||||
GoOS: loginReq.GetMeta().GetGoOS(),
|
GoOS: meta.GetGoOS(),
|
||||||
Kernel: loginReq.GetMeta().GetKernel(),
|
Kernel: meta.GetKernel(),
|
||||||
Platform: loginReq.GetMeta().GetPlatform(),
|
Platform: meta.GetPlatform(),
|
||||||
OS: loginReq.GetMeta().GetOS(),
|
OS: meta.GetOS(),
|
||||||
OSVersion: osVersion,
|
OSVersion: osVersion,
|
||||||
WtVersion: loginReq.GetMeta().GetWiretrusteeVersion(),
|
WtVersion: meta.GetWiretrusteeVersion(),
|
||||||
UIVersion: loginReq.GetMeta().GetUiVersion(),
|
UIVersion: meta.GetUiVersion(),
|
||||||
KernelVersion: loginReq.GetMeta().GetKernelVersion(),
|
KernelVersion: meta.GetKernelVersion(),
|
||||||
NetworkAddresses: networkAddresses,
|
NetworkAddresses: networkAddresses,
|
||||||
SystemSerialNumber: loginReq.GetMeta().GetSysSerialNumber(),
|
SystemSerialNumber: meta.GetSysSerialNumber(),
|
||||||
SystemProductName: loginReq.GetMeta().GetSysProductName(),
|
SystemProductName: meta.GetSysProductName(),
|
||||||
SystemManufacturer: loginReq.GetMeta().GetSysManufacturer(),
|
SystemManufacturer: meta.GetSysManufacturer(),
|
||||||
Environment: nbpeer.Environment{
|
Environment: nbpeer.Environment{
|
||||||
Cloud: loginReq.GetMeta().GetEnvironment().GetCloud(),
|
Cloud: meta.GetEnvironment().GetCloud(),
|
||||||
Platform: loginReq.GetMeta().GetEnvironment().GetPlatform(),
|
Platform: meta.GetEnvironment().GetPlatform(),
|
||||||
},
|
},
|
||||||
|
Files: files,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -366,7 +387,7 @@ func (s *GRPCServer) Login(ctx context.Context, req *proto.EncryptedMessage) (*p
|
|||||||
peer, netMap, err := s.accountManager.LoginPeer(PeerLogin{
|
peer, netMap, err := s.accountManager.LoginPeer(PeerLogin{
|
||||||
WireGuardPubKey: peerKey.String(),
|
WireGuardPubKey: peerKey.String(),
|
||||||
SSHKey: string(sshKey),
|
SSHKey: string(sshKey),
|
||||||
Meta: extractPeerMeta(loginReq),
|
Meta: extractPeerMeta(loginReq.GetMeta()),
|
||||||
UserID: userID,
|
UserID: userID,
|
||||||
SetupKey: loginReq.GetSetupKey(),
|
SetupKey: loginReq.GetSetupKey(),
|
||||||
ConnectionIP: realIP,
|
ConnectionIP: realIP,
|
||||||
@ -386,6 +407,7 @@ func (s *GRPCServer) Login(ctx context.Context, req *proto.EncryptedMessage) (*p
|
|||||||
loginResp := &proto.LoginResponse{
|
loginResp := &proto.LoginResponse{
|
||||||
WiretrusteeConfig: toWiretrusteeConfig(s.config, nil),
|
WiretrusteeConfig: toWiretrusteeConfig(s.config, nil),
|
||||||
PeerConfig: toPeerConfig(peer, netMap.Network, s.accountManager.GetDNSDomain()),
|
PeerConfig: toPeerConfig(peer, netMap.Network, s.accountManager.GetDNSDomain()),
|
||||||
|
Checks: toPeerChecks(s.accountManager, peerKey.String()),
|
||||||
}
|
}
|
||||||
encryptedResp, err := encryption.EncryptMessage(peerKey, s.wgKey, loginResp)
|
encryptedResp, err := encryption.EncryptMessage(peerKey, s.wgKey, loginResp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -482,7 +504,7 @@ func toRemotePeerConfig(peers []*nbpeer.Peer, dnsName string) []*proto.RemotePee
|
|||||||
return remotePeers
|
return remotePeers
|
||||||
}
|
}
|
||||||
|
|
||||||
func toSyncResponse(config *Config, peer *nbpeer.Peer, turnCredentials *TURNCredentials, networkMap *NetworkMap, dnsName string) *proto.SyncResponse {
|
func toSyncResponse(accountManager AccountManager, config *Config, peer *nbpeer.Peer, turnCredentials *TURNCredentials, networkMap *NetworkMap, dnsName string) *proto.SyncResponse {
|
||||||
wtConfig := toWiretrusteeConfig(config, turnCredentials)
|
wtConfig := toWiretrusteeConfig(config, turnCredentials)
|
||||||
|
|
||||||
pConfig := toPeerConfig(peer, networkMap.Network, dnsName)
|
pConfig := toPeerConfig(peer, networkMap.Network, dnsName)
|
||||||
@ -513,6 +535,7 @@ func toSyncResponse(config *Config, peer *nbpeer.Peer, turnCredentials *TURNCred
|
|||||||
FirewallRules: firewallRules,
|
FirewallRules: firewallRules,
|
||||||
FirewallRulesIsEmpty: len(firewallRules) == 0,
|
FirewallRulesIsEmpty: len(firewallRules) == 0,
|
||||||
},
|
},
|
||||||
|
Checks: toPeerChecks(accountManager, peer.Key),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -531,7 +554,7 @@ func (s *GRPCServer) sendInitialSync(peerKey wgtypes.Key, peer *nbpeer.Peer, net
|
|||||||
} else {
|
} else {
|
||||||
turnCredentials = nil
|
turnCredentials = nil
|
||||||
}
|
}
|
||||||
plainResp := toSyncResponse(s.config, peer, turnCredentials, networkMap, s.accountManager.GetDNSDomain())
|
plainResp := toSyncResponse(s.accountManager, s.config, peer, turnCredentials, networkMap, s.accountManager.GetDNSDomain())
|
||||||
|
|
||||||
encryptedResp, err := encryption.EncryptMessage(peerKey, s.wgKey, plainResp)
|
encryptedResp, err := encryption.EncryptMessage(peerKey, s.wgKey, plainResp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -648,3 +671,62 @@ func (s *GRPCServer) GetPKCEAuthorizationFlow(_ context.Context, req *proto.Encr
|
|||||||
Body: encryptedResp,
|
Body: encryptedResp,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SyncMeta endpoint is used to synchronize peer's system metadata and notifies the connected,
|
||||||
|
// peer's under the same account of any updates.
|
||||||
|
func (s *GRPCServer) SyncMeta(ctx context.Context, req *proto.EncryptedMessage) (*proto.Empty, error) {
|
||||||
|
realIP := getRealIP(ctx)
|
||||||
|
log.Debugf("Sync meta request from peer [%s] [%s]", req.WgPubKey, realIP.String())
|
||||||
|
|
||||||
|
syncMetaReq := &proto.SyncMetaRequest{}
|
||||||
|
peerKey, err := s.parseRequest(req, syncMetaReq)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if syncMetaReq.GetMeta() == nil {
|
||||||
|
msg := status.Errorf(codes.FailedPrecondition,
|
||||||
|
"peer system meta has to be provided on sync. Peer %s, remote addr %s", peerKey.String(), realIP)
|
||||||
|
log.Warn(msg)
|
||||||
|
return nil, msg
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, err = s.accountManager.SyncPeer(PeerSync{
|
||||||
|
WireGuardPubKey: peerKey.String(),
|
||||||
|
Meta: extractPeerMeta(syncMetaReq.GetMeta()),
|
||||||
|
UpdateAccountPeers: true,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, mapError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &proto.Empty{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// toPeerChecks returns posture checks for the peer that needs to be evaluated on the client side.
|
||||||
|
func toPeerChecks(accountManager AccountManager, peerKey string) []*proto.Checks {
|
||||||
|
postureChecks, err := accountManager.GetPeerAppliedPostureChecks(peerKey)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("failed getting peer's: %s posture checks: %v", peerKey, err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
protoChecks := make([]*proto.Checks, 0)
|
||||||
|
for _, postureCheck := range postureChecks {
|
||||||
|
protoCheck := &proto.Checks{}
|
||||||
|
|
||||||
|
if check := postureCheck.Checks.ProcessCheck; check != nil {
|
||||||
|
for _, process := range check.Processes {
|
||||||
|
if process.Path != "" {
|
||||||
|
protoCheck.Files = append(protoCheck.Files, process.Path)
|
||||||
|
}
|
||||||
|
if process.WindowsPath != "" {
|
||||||
|
protoCheck.Files = append(protoCheck.Files, process.WindowsPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
protoChecks = append(protoChecks, protoCheck)
|
||||||
|
}
|
||||||
|
|
||||||
|
return protoChecks
|
||||||
|
}
|
||||||
|
@ -134,7 +134,8 @@ func Test_SyncProtocol(t *testing.T) {
|
|||||||
// take the first registered peer as a base for the test. Total four.
|
// take the first registered peer as a base for the test. Total four.
|
||||||
key := *peers[0]
|
key := *peers[0]
|
||||||
|
|
||||||
message, err := encryption.EncryptMessage(*serverKey, key, &mgmtProto.SyncRequest{})
|
syncReq := &mgmtProto.SyncRequest{Meta: &mgmtProto.PeerSystemMeta{}}
|
||||||
|
message, err := encryption.EncryptMessage(*serverKey, key, syncReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
return
|
return
|
||||||
|
@ -93,7 +93,8 @@ var _ = Describe("Management service", func() {
|
|||||||
key, _ := wgtypes.GenerateKey()
|
key, _ := wgtypes.GenerateKey()
|
||||||
loginPeerWithValidSetupKey(serverPubKey, key, client)
|
loginPeerWithValidSetupKey(serverPubKey, key, client)
|
||||||
|
|
||||||
encryptedBytes, err := encryption.EncryptMessage(serverPubKey, key, &mgmtProto.SyncRequest{})
|
syncReq := &mgmtProto.SyncRequest{Meta: &mgmtProto.PeerSystemMeta{}}
|
||||||
|
encryptedBytes, err := encryption.EncryptMessage(serverPubKey, key, syncReq)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
sync, err := client.Sync(context.TODO(), &mgmtProto.EncryptedMessage{
|
sync, err := client.Sync(context.TODO(), &mgmtProto.EncryptedMessage{
|
||||||
@ -143,7 +144,7 @@ var _ = Describe("Management service", func() {
|
|||||||
loginPeerWithValidSetupKey(serverPubKey, key1, client)
|
loginPeerWithValidSetupKey(serverPubKey, key1, client)
|
||||||
loginPeerWithValidSetupKey(serverPubKey, key2, client)
|
loginPeerWithValidSetupKey(serverPubKey, key2, client)
|
||||||
|
|
||||||
messageBytes, err := pb.Marshal(&mgmtProto.SyncRequest{})
|
messageBytes, err := pb.Marshal(&mgmtProto.SyncRequest{Meta: &mgmtProto.PeerSystemMeta{}})
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
encryptedBytes, err := encryption.Encrypt(messageBytes, serverPubKey, key)
|
encryptedBytes, err := encryption.Encrypt(messageBytes, serverPubKey, key)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
@ -176,7 +177,7 @@ var _ = Describe("Management service", func() {
|
|||||||
key, _ := wgtypes.GenerateKey()
|
key, _ := wgtypes.GenerateKey()
|
||||||
loginPeerWithValidSetupKey(serverPubKey, key, client)
|
loginPeerWithValidSetupKey(serverPubKey, key, client)
|
||||||
|
|
||||||
messageBytes, err := pb.Marshal(&mgmtProto.SyncRequest{})
|
messageBytes, err := pb.Marshal(&mgmtProto.SyncRequest{Meta: &mgmtProto.PeerSystemMeta{}})
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
encryptedBytes, err := encryption.Encrypt(messageBytes, serverPubKey, key)
|
encryptedBytes, err := encryption.Encrypt(messageBytes, serverPubKey, key)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
@ -329,7 +330,7 @@ var _ = Describe("Management service", func() {
|
|||||||
|
|
||||||
var clients []mgmtProto.ManagementService_SyncClient
|
var clients []mgmtProto.ManagementService_SyncClient
|
||||||
for _, peer := range peers {
|
for _, peer := range peers {
|
||||||
messageBytes, err := pb.Marshal(&mgmtProto.SyncRequest{})
|
messageBytes, err := pb.Marshal(&mgmtProto.SyncRequest{Meta: &mgmtProto.PeerSystemMeta{}})
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
encryptedBytes, err := encryption.Encrypt(messageBytes, serverPubKey, peer)
|
encryptedBytes, err := encryption.Encrypt(messageBytes, serverPubKey, peer)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
@ -394,7 +395,8 @@ var _ = Describe("Management service", func() {
|
|||||||
defer GinkgoRecover()
|
defer GinkgoRecover()
|
||||||
key, _ := wgtypes.GenerateKey()
|
key, _ := wgtypes.GenerateKey()
|
||||||
loginPeerWithValidSetupKey(serverPubKey, key, client)
|
loginPeerWithValidSetupKey(serverPubKey, key, client)
|
||||||
encryptedBytes, err := encryption.EncryptMessage(serverPubKey, key, &mgmtProto.SyncRequest{})
|
syncReq := &mgmtProto.SyncRequest{Meta: &mgmtProto.PeerSystemMeta{}}
|
||||||
|
encryptedBytes, err := encryption.EncryptMessage(serverPubKey, key, syncReq)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
// open stream
|
// open stream
|
||||||
|
@ -80,6 +80,7 @@ type MockAccountManager struct {
|
|||||||
GetDNSSettingsFunc func(accountID, userID string) (*server.DNSSettings, error)
|
GetDNSSettingsFunc func(accountID, userID string) (*server.DNSSettings, error)
|
||||||
SaveDNSSettingsFunc func(accountID, userID string, dnsSettingsToSave *server.DNSSettings) error
|
SaveDNSSettingsFunc func(accountID, userID string, dnsSettingsToSave *server.DNSSettings) error
|
||||||
GetPeerFunc func(accountID, peerID, userID string) (*nbpeer.Peer, error)
|
GetPeerFunc func(accountID, peerID, userID string) (*nbpeer.Peer, error)
|
||||||
|
GetPeerAppliedPostureChecksFunc func(peerKey string) ([]posture.Checks, error)
|
||||||
UpdateAccountSettingsFunc func(accountID, userID string, newSettings *server.Settings) (*server.Account, error)
|
UpdateAccountSettingsFunc func(accountID, userID string, newSettings *server.Settings) (*server.Account, error)
|
||||||
LoginPeerFunc func(login server.PeerLogin) (*nbpeer.Peer, *server.NetworkMap, error)
|
LoginPeerFunc func(login server.PeerLogin) (*nbpeer.Peer, *server.NetworkMap, error)
|
||||||
SyncPeerFunc func(sync server.PeerSync) (*nbpeer.Peer, *server.NetworkMap, error)
|
SyncPeerFunc func(sync server.PeerSync) (*nbpeer.Peer, *server.NetworkMap, error)
|
||||||
@ -609,6 +610,14 @@ func (am *MockAccountManager) GetPeer(accountID, peerID, userID string) (*nbpeer
|
|||||||
return nil, status.Errorf(codes.Unimplemented, "method GetPeer is not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method GetPeer is not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPeerAppliedPostureChecks mocks GetPeerAppliedPostureChecks of the AccountManager interface
|
||||||
|
func (am *MockAccountManager) GetPeerAppliedPostureChecks(peerKey string) ([]posture.Checks, error) {
|
||||||
|
if am.GetPeerAppliedPostureChecksFunc != nil {
|
||||||
|
return am.GetPeerAppliedPostureChecksFunc(peerKey)
|
||||||
|
}
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method GetPeerAppliedPostureChecks is not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
// UpdateAccountSettings mocks UpdateAccountSettings of the AccountManager interface
|
// UpdateAccountSettings mocks UpdateAccountSettings of the AccountManager interface
|
||||||
func (am *MockAccountManager) UpdateAccountSettings(accountID, userID string, newSettings *server.Settings) (*server.Account, error) {
|
func (am *MockAccountManager) UpdateAccountSettings(accountID, userID string, newSettings *server.Settings) (*server.Account, error) {
|
||||||
if am.UpdateAccountSettingsFunc != nil {
|
if am.UpdateAccountSettingsFunc != nil {
|
||||||
|
@ -3,9 +3,10 @@ package mock_server
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/management/proto"
|
|
||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
"google.golang.org/grpc/status"
|
"google.golang.org/grpc/status"
|
||||||
|
|
||||||
|
"github.com/netbirdio/netbird/management/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ManagementServiceServerMock struct {
|
type ManagementServiceServerMock struct {
|
||||||
@ -17,6 +18,7 @@ type ManagementServiceServerMock struct {
|
|||||||
IsHealthyFunc func(context.Context, *proto.Empty) (*proto.Empty, error)
|
IsHealthyFunc func(context.Context, *proto.Empty) (*proto.Empty, error)
|
||||||
GetDeviceAuthorizationFlowFunc func(ctx context.Context, req *proto.EncryptedMessage) (*proto.EncryptedMessage, error)
|
GetDeviceAuthorizationFlowFunc func(ctx context.Context, req *proto.EncryptedMessage) (*proto.EncryptedMessage, error)
|
||||||
GetPKCEAuthorizationFlowFunc func(ctx context.Context, req *proto.EncryptedMessage) (*proto.EncryptedMessage, error)
|
GetPKCEAuthorizationFlowFunc func(ctx context.Context, req *proto.EncryptedMessage) (*proto.EncryptedMessage, error)
|
||||||
|
SyncMetaFunc func(ctx context.Context, req *proto.EncryptedMessage) (*proto.Empty, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m ManagementServiceServerMock) Login(ctx context.Context, req *proto.EncryptedMessage) (*proto.EncryptedMessage, error) {
|
func (m ManagementServiceServerMock) Login(ctx context.Context, req *proto.EncryptedMessage) (*proto.EncryptedMessage, error) {
|
||||||
@ -60,3 +62,10 @@ func (m ManagementServiceServerMock) GetPKCEAuthorizationFlow(ctx context.Contex
|
|||||||
}
|
}
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method GetPKCEAuthorizationFlow not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method GetPKCEAuthorizationFlow not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m ManagementServiceServerMock) SyncMeta(ctx context.Context, req *proto.EncryptedMessage) (*proto.Empty, error) {
|
||||||
|
if m.SyncMetaFunc != nil {
|
||||||
|
return m.SyncMetaFunc(ctx, req)
|
||||||
|
}
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method SyncMeta not implemented")
|
||||||
|
}
|
||||||
|
@ -3,6 +3,7 @@ package server
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -12,6 +13,7 @@ import (
|
|||||||
"github.com/netbirdio/netbird/management/proto"
|
"github.com/netbirdio/netbird/management/proto"
|
||||||
"github.com/netbirdio/netbird/management/server/activity"
|
"github.com/netbirdio/netbird/management/server/activity"
|
||||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
||||||
|
"github.com/netbirdio/netbird/management/server/posture"
|
||||||
"github.com/netbirdio/netbird/management/server/status"
|
"github.com/netbirdio/netbird/management/server/status"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -19,6 +21,11 @@ import (
|
|||||||
type PeerSync struct {
|
type PeerSync struct {
|
||||||
// WireGuardPubKey is a peers WireGuard public key
|
// WireGuardPubKey is a peers WireGuard public key
|
||||||
WireGuardPubKey string
|
WireGuardPubKey string
|
||||||
|
// Meta is the system information passed by peer, must be always present
|
||||||
|
Meta nbpeer.PeerSystemMeta
|
||||||
|
// UpdateAccountPeers indicate updating account peers,
|
||||||
|
// which occurs when the peer's metadata is updated
|
||||||
|
UpdateAccountPeers bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// PeerLogin used as a data object between the gRPC API and AccountManager on Login request.
|
// PeerLogin used as a data object between the gRPC API and AccountManager on Login request.
|
||||||
@ -551,6 +558,18 @@ func (am *DefaultAccountManager) SyncPeer(sync PeerSync) (*nbpeer.Peer, *Network
|
|||||||
return nil, nil, status.Errorf(status.PermissionDenied, "peer login has expired, please log in once more")
|
return nil, nil, status.Errorf(status.PermissionDenied, "peer login has expired, please log in once more")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
peer, updated := updatePeerMeta(peer, sync.Meta, account)
|
||||||
|
if updated {
|
||||||
|
err = am.Store.SaveAccount(account)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if sync.UpdateAccountPeers {
|
||||||
|
am.updateAccountPeers(account)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
requiresApproval, isStatusChanged := am.integratedPeerValidator.IsNotValidPeer(account.Id, peer, account.GetPeerGroupsList(peer.ID), account.Settings.Extra)
|
requiresApproval, isStatusChanged := am.integratedPeerValidator.IsNotValidPeer(account.Id, peer, account.GetPeerGroupsList(peer.ID), account.Settings.Extra)
|
||||||
if requiresApproval {
|
if requiresApproval {
|
||||||
emptyMap := &NetworkMap{
|
emptyMap := &NetworkMap{
|
||||||
@ -866,7 +885,65 @@ func (am *DefaultAccountManager) updateAccountPeers(account *Account) {
|
|||||||
}
|
}
|
||||||
for _, peer := range peers {
|
for _, peer := range peers {
|
||||||
remotePeerNetworkMap := account.GetPeerNetworkMap(peer.ID, am.dnsDomain, approvedPeersMap)
|
remotePeerNetworkMap := account.GetPeerNetworkMap(peer.ID, am.dnsDomain, approvedPeersMap)
|
||||||
update := toSyncResponse(nil, peer, nil, remotePeerNetworkMap, am.GetDNSDomain())
|
update := toSyncResponse(am, nil, peer, nil, remotePeerNetworkMap, am.GetDNSDomain())
|
||||||
am.peersUpdateManager.SendUpdate(peer.ID, &UpdateMessage{Update: update})
|
am.peersUpdateManager.SendUpdate(peer.ID, &UpdateMessage{Update: update})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPeerAppliedPostureChecks returns posture checks that are applied to the peer.
|
||||||
|
func (am *DefaultAccountManager) GetPeerAppliedPostureChecks(peerKey string) ([]posture.Checks, error) {
|
||||||
|
account, err := am.Store.GetAccountByPeerPubKey(peerKey)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("failed while getting peer %s: %v", peerKey, err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
peer, err := account.FindPeerByPubKey(peerKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Errorf(status.NotFound, "peer is not registered")
|
||||||
|
}
|
||||||
|
if peer == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
peerPostureChecks := make(map[string]posture.Checks)
|
||||||
|
for _, policy := range account.Policies {
|
||||||
|
if !policy.Enabled {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
outerLoop:
|
||||||
|
for _, rule := range policy.Rules {
|
||||||
|
if !rule.Enabled {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, sourceGroup := range rule.Sources {
|
||||||
|
group, ok := account.Groups[sourceGroup]
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if peer is in the rule source group
|
||||||
|
if slices.Contains(group.Peers, peer.ID) {
|
||||||
|
for _, sourcePostureCheckID := range policy.SourcePostureChecks {
|
||||||
|
for _, postureChecks := range account.PostureChecks {
|
||||||
|
if postureChecks.ID == sourcePostureCheckID {
|
||||||
|
peerPostureChecks[sourcePostureCheckID] = *postureChecks
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break outerLoop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
postureChecksList := make([]posture.Checks, 0, len(peerPostureChecks))
|
||||||
|
for _, check := range peerPostureChecks {
|
||||||
|
postureChecksList = append(postureChecksList, check)
|
||||||
|
}
|
||||||
|
|
||||||
|
return postureChecksList, nil
|
||||||
|
}
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
"slices"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -79,9 +80,11 @@ type Environment struct {
|
|||||||
Platform string
|
Platform string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process represents an active process on the peer's system.
|
// File is a file on the system.
|
||||||
type Process struct {
|
type File struct {
|
||||||
Path string
|
Path string
|
||||||
|
Exist bool
|
||||||
|
ProcessIsRunning bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// PeerSystemMeta is a metadata of a Peer machine system
|
// PeerSystemMeta is a metadata of a Peer machine system
|
||||||
@ -101,25 +104,22 @@ type PeerSystemMeta struct { //nolint:revive
|
|||||||
SystemProductName string
|
SystemProductName string
|
||||||
SystemManufacturer string
|
SystemManufacturer string
|
||||||
Environment Environment `gorm:"serializer:json"`
|
Environment Environment `gorm:"serializer:json"`
|
||||||
Processes []Process `gorm:"-"`
|
Files []File `gorm:"serializer:json"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p PeerSystemMeta) isEqual(other PeerSystemMeta) bool {
|
func (p PeerSystemMeta) isEqual(other PeerSystemMeta) bool {
|
||||||
if len(p.NetworkAddresses) != len(other.NetworkAddresses) {
|
equalNetworkAddresses := slices.EqualFunc(p.NetworkAddresses, other.NetworkAddresses, func(addr NetworkAddress, oAddr NetworkAddress) bool {
|
||||||
|
return addr.Mac == oAddr.Mac && addr.NetIP == oAddr.NetIP
|
||||||
|
})
|
||||||
|
if !equalNetworkAddresses {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, addr := range p.NetworkAddresses {
|
equalFiles := slices.EqualFunc(p.Files, other.Files, func(file File, oFile File) bool {
|
||||||
var found bool
|
return file.Path == oFile.Path && file.Exist == oFile.Exist && file.ProcessIsRunning == oFile.ProcessIsRunning
|
||||||
for _, oAddr := range other.NetworkAddresses {
|
})
|
||||||
if addr.Mac == oAddr.Mac && addr.NetIP == oAddr.NetIP {
|
if !equalFiles {
|
||||||
found = true
|
return false
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !found {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return p.Hostname == other.Hostname &&
|
return p.Hostname == other.Hostname &&
|
||||||
@ -139,6 +139,26 @@ func (p PeerSystemMeta) isEqual(other PeerSystemMeta) bool {
|
|||||||
p.Environment.Platform == other.Environment.Platform
|
p.Environment.Platform == other.Environment.Platform
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p PeerSystemMeta) isEmpty() bool {
|
||||||
|
return p.Hostname == "" &&
|
||||||
|
p.GoOS == "" &&
|
||||||
|
p.Kernel == "" &&
|
||||||
|
p.Core == "" &&
|
||||||
|
p.Platform == "" &&
|
||||||
|
p.OS == "" &&
|
||||||
|
p.OSVersion == "" &&
|
||||||
|
p.WtVersion == "" &&
|
||||||
|
p.UIVersion == "" &&
|
||||||
|
p.KernelVersion == "" &&
|
||||||
|
len(p.NetworkAddresses) == 0 &&
|
||||||
|
p.SystemSerialNumber == "" &&
|
||||||
|
p.SystemProductName == "" &&
|
||||||
|
p.SystemManufacturer == "" &&
|
||||||
|
p.Environment.Cloud == "" &&
|
||||||
|
p.Environment.Platform == "" &&
|
||||||
|
len(p.Files) == 0
|
||||||
|
}
|
||||||
|
|
||||||
// AddedWithSSOLogin indicates whether this peer has been added with an SSO login by a user.
|
// AddedWithSSOLogin indicates whether this peer has been added with an SSO login by a user.
|
||||||
func (p *Peer) AddedWithSSOLogin() bool {
|
func (p *Peer) AddedWithSSOLogin() bool {
|
||||||
return p.UserID != ""
|
return p.UserID != ""
|
||||||
@ -174,6 +194,10 @@ func (p *Peer) Copy() *Peer {
|
|||||||
// UpdateMetaIfNew updates peer's system metadata if new information is provided
|
// UpdateMetaIfNew updates peer's system metadata if new information is provided
|
||||||
// returns true if meta was updated, false otherwise
|
// returns true if meta was updated, false otherwise
|
||||||
func (p *Peer) UpdateMetaIfNew(meta PeerSystemMeta) bool {
|
func (p *Peer) UpdateMetaIfNew(meta PeerSystemMeta) bool {
|
||||||
|
if meta.isEmpty() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// Avoid overwriting UIVersion if the update was triggered sole by the CLI client
|
// Avoid overwriting UIVersion if the update was triggered sole by the CLI client
|
||||||
if meta.UIVersion == "" {
|
if meta.UIVersion == "" {
|
||||||
meta.UIVersion = p.Meta.UIVersion
|
meta.UIVersion = p.Meta.UIVersion
|
||||||
|
@ -19,9 +19,11 @@ type ProcessCheck struct {
|
|||||||
var _ Check = (*ProcessCheck)(nil)
|
var _ Check = (*ProcessCheck)(nil)
|
||||||
|
|
||||||
func (p *ProcessCheck) Check(peer nbpeer.Peer) (bool, error) {
|
func (p *ProcessCheck) Check(peer nbpeer.Peer) (bool, error) {
|
||||||
peerActiveProcesses := make([]string, 0, len(peer.Meta.Processes))
|
peerActiveProcesses := make([]string, 0, len(peer.Meta.Files))
|
||||||
for _, process := range peer.Meta.Processes {
|
for _, file := range peer.Meta.Files {
|
||||||
peerActiveProcesses = append(peerActiveProcesses, process.Path)
|
if file.ProcessIsRunning {
|
||||||
|
peerActiveProcesses = append(peerActiveProcesses, file.Path)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch peer.Meta.GoOS {
|
switch peer.Meta.GoOS {
|
||||||
|
@ -17,13 +17,14 @@ func TestProcessCheck_Check(t *testing.T) {
|
|||||||
isValid bool
|
isValid bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "darwin with matching processes",
|
name: "darwin with matching running processes",
|
||||||
input: peer.Peer{
|
input: peer.Peer{
|
||||||
Meta: peer.PeerSystemMeta{
|
Meta: peer.PeerSystemMeta{
|
||||||
GoOS: "darwin",
|
GoOS: "darwin",
|
||||||
Processes: []peer.Process{
|
Files: []peer.File{
|
||||||
{Path: "/Applications/process1.app"},
|
{Path: "/Applications/process1.app", ProcessIsRunning: true},
|
||||||
{Path: "/Applications/process2.app"}},
|
{Path: "/Applications/process2.app", ProcessIsRunning: true},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
check: ProcessCheck{
|
check: ProcessCheck{
|
||||||
@ -40,9 +41,9 @@ func TestProcessCheck_Check(t *testing.T) {
|
|||||||
input: peer.Peer{
|
input: peer.Peer{
|
||||||
Meta: peer.PeerSystemMeta{
|
Meta: peer.PeerSystemMeta{
|
||||||
GoOS: "darwin",
|
GoOS: "darwin",
|
||||||
Processes: []peer.Process{
|
Files: []peer.File{
|
||||||
{Path: "/Applications/process1.app"},
|
{Path: "/Applications/process1.app", ProcessIsRunning: true},
|
||||||
{Path: "/Applications/process2.app"},
|
{Path: "/Applications/process2.app", ProcessIsRunning: true},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -56,13 +57,13 @@ func TestProcessCheck_Check(t *testing.T) {
|
|||||||
isValid: false,
|
isValid: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "linux with matching processes",
|
name: "linux with matching running processes",
|
||||||
input: peer.Peer{
|
input: peer.Peer{
|
||||||
Meta: peer.PeerSystemMeta{
|
Meta: peer.PeerSystemMeta{
|
||||||
GoOS: "linux",
|
GoOS: "linux",
|
||||||
Processes: []peer.Process{
|
Files: []peer.File{
|
||||||
{Path: "/usr/bin/process1"},
|
{Path: "/usr/bin/process1", ProcessIsRunning: true},
|
||||||
{Path: "/usr/bin/process2"},
|
{Path: "/usr/bin/process2", ProcessIsRunning: true},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -75,13 +76,33 @@ func TestProcessCheck_Check(t *testing.T) {
|
|||||||
wantErr: false,
|
wantErr: false,
|
||||||
isValid: true,
|
isValid: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "linux with matching no running processes",
|
||||||
|
input: peer.Peer{
|
||||||
|
Meta: peer.PeerSystemMeta{
|
||||||
|
GoOS: "linux",
|
||||||
|
Files: []peer.File{
|
||||||
|
{Path: "/usr/bin/process1", ProcessIsRunning: true},
|
||||||
|
{Path: "/usr/bin/process2", ProcessIsRunning: false},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
check: ProcessCheck{
|
||||||
|
Processes: []Process{
|
||||||
|
{Path: "/usr/bin/process1"},
|
||||||
|
{Path: "/usr/bin/process2"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
isValid: false,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "linux with windows process paths",
|
name: "linux with windows process paths",
|
||||||
input: peer.Peer{
|
input: peer.Peer{
|
||||||
Meta: peer.PeerSystemMeta{
|
Meta: peer.PeerSystemMeta{
|
||||||
GoOS: "linux",
|
GoOS: "linux",
|
||||||
Processes: []peer.Process{
|
Files: []peer.File{
|
||||||
{Path: "/usr/bin/process1"},
|
{Path: "/usr/bin/process1", ProcessIsRunning: true},
|
||||||
{Path: "/usr/bin/process2"},
|
{Path: "/usr/bin/process2"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -100,7 +121,7 @@ func TestProcessCheck_Check(t *testing.T) {
|
|||||||
input: peer.Peer{
|
input: peer.Peer{
|
||||||
Meta: peer.PeerSystemMeta{
|
Meta: peer.PeerSystemMeta{
|
||||||
GoOS: "linux",
|
GoOS: "linux",
|
||||||
Processes: []peer.Process{
|
Files: []peer.File{
|
||||||
{Path: "/usr/bin/process3"},
|
{Path: "/usr/bin/process3"},
|
||||||
{Path: "/usr/bin/process4"},
|
{Path: "/usr/bin/process4"},
|
||||||
},
|
},
|
||||||
@ -116,13 +137,13 @@ func TestProcessCheck_Check(t *testing.T) {
|
|||||||
isValid: false,
|
isValid: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "windows with matching processes",
|
name: "windows with matching running processes",
|
||||||
input: peer.Peer{
|
input: peer.Peer{
|
||||||
Meta: peer.PeerSystemMeta{
|
Meta: peer.PeerSystemMeta{
|
||||||
GoOS: "windows",
|
GoOS: "windows",
|
||||||
Processes: []peer.Process{
|
Files: []peer.File{
|
||||||
{Path: "C:\\Program Files\\process1.exe"},
|
{Path: "C:\\Program Files\\process1.exe", ProcessIsRunning: true},
|
||||||
{Path: "C:\\Program Files\\process1.exe"},
|
{Path: "C:\\Program Files\\process1.exe", ProcessIsRunning: true},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -140,7 +161,7 @@ func TestProcessCheck_Check(t *testing.T) {
|
|||||||
input: peer.Peer{
|
input: peer.Peer{
|
||||||
Meta: peer.PeerSystemMeta{
|
Meta: peer.PeerSystemMeta{
|
||||||
GoOS: "windows",
|
GoOS: "windows",
|
||||||
Processes: []peer.Process{
|
Files: []peer.File{
|
||||||
{Path: "C:\\Program Files\\process1.exe"},
|
{Path: "C:\\Program Files\\process1.exe"},
|
||||||
{Path: "C:\\Program Files\\process1.exe"},
|
{Path: "C:\\Program Files\\process1.exe"},
|
||||||
},
|
},
|
||||||
@ -160,7 +181,7 @@ func TestProcessCheck_Check(t *testing.T) {
|
|||||||
input: peer.Peer{
|
input: peer.Peer{
|
||||||
Meta: peer.PeerSystemMeta{
|
Meta: peer.PeerSystemMeta{
|
||||||
GoOS: "windows",
|
GoOS: "windows",
|
||||||
Processes: []peer.Process{
|
Files: []peer.File{
|
||||||
{Path: "C:\\Program Files\\process3.exe"},
|
{Path: "C:\\Program Files\\process3.exe"},
|
||||||
{Path: "C:\\Program Files\\process4.exe"},
|
{Path: "C:\\Program Files\\process4.exe"},
|
||||||
},
|
},
|
||||||
|
Reference in New Issue
Block a user