mirror of
https://github.com/netbirdio/netbird.git
synced 2026-10-24 14:29:07 +02:00
Merge branch 'main' into android-dns-routes
This commit is contained in:
@@ -9,7 +9,7 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
|
|
||||||
env:
|
env:
|
||||||
SIGN_PIPE_VER: "v0.0.18"
|
SIGN_PIPE_VER: "v0.0.20"
|
||||||
GORELEASER_VER: "v2.3.2"
|
GORELEASER_VER: "v2.3.2"
|
||||||
PRODUCT_NAME: "NetBird"
|
PRODUCT_NAME: "NetBird"
|
||||||
COPYRIGHT: "NetBird GmbH"
|
COPYRIGHT: "NetBird GmbH"
|
||||||
|
|||||||
@@ -134,6 +134,7 @@ jobs:
|
|||||||
NETBIRD_STORE_ENGINE_MYSQL_DSN: '${{ env.NETBIRD_STORE_ENGINE_MYSQL_DSN }}$'
|
NETBIRD_STORE_ENGINE_MYSQL_DSN: '${{ env.NETBIRD_STORE_ENGINE_MYSQL_DSN }}$'
|
||||||
CI_NETBIRD_MGMT_IDP_SIGNKEY_REFRESH: false
|
CI_NETBIRD_MGMT_IDP_SIGNKEY_REFRESH: false
|
||||||
CI_NETBIRD_TURN_EXTERNAL_IP: "1.2.3.4"
|
CI_NETBIRD_TURN_EXTERNAL_IP: "1.2.3.4"
|
||||||
|
CI_NETBIRD_MGMT_DISABLE_DEFAULT_POLICY: false
|
||||||
|
|
||||||
run: |
|
run: |
|
||||||
set -x
|
set -x
|
||||||
@@ -180,6 +181,7 @@ jobs:
|
|||||||
grep -A 7 Relay management.json | egrep '"Secret": ".+"'
|
grep -A 7 Relay management.json | egrep '"Secret": ".+"'
|
||||||
grep DisablePromptLogin management.json | grep 'true'
|
grep DisablePromptLogin management.json | grep 'true'
|
||||||
grep LoginFlag management.json | grep 0
|
grep LoginFlag management.json | grep 0
|
||||||
|
grep DisableDefaultPolicy management.json | grep "$CI_NETBIRD_MGMT_DISABLE_DEFAULT_POLICY"
|
||||||
|
|
||||||
- name: Install modules
|
- name: Install modules
|
||||||
run: go mod tidy
|
run: go mod tidy
|
||||||
|
|||||||
+4
-1
@@ -1,6 +1,9 @@
|
|||||||
FROM alpine:3.21.3
|
FROM alpine:3.21.3
|
||||||
# iproute2: busybox doesn't display ip rules properly
|
# iproute2: busybox doesn't display ip rules properly
|
||||||
RUN apk add --no-cache ca-certificates ip6tables iproute2 iptables
|
RUN apk add --no-cache ca-certificates ip6tables iproute2 iptables
|
||||||
|
|
||||||
|
ARG NETBIRD_BINARY=netbird
|
||||||
|
COPY ${NETBIRD_BINARY} /usr/local/bin/netbird
|
||||||
|
|
||||||
ENV NB_FOREGROUND_MODE=true
|
ENV NB_FOREGROUND_MODE=true
|
||||||
ENTRYPOINT [ "/usr/local/bin/netbird","up"]
|
ENTRYPOINT [ "/usr/local/bin/netbird","up"]
|
||||||
COPY netbird /usr/local/bin/netbird
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
FROM alpine:3.21.0
|
FROM alpine:3.21.0
|
||||||
|
|
||||||
COPY netbird /usr/local/bin/netbird
|
ARG NETBIRD_BINARY=netbird
|
||||||
|
COPY ${NETBIRD_BINARY} /usr/local/bin/netbird
|
||||||
|
|
||||||
RUN apk add --no-cache ca-certificates \
|
RUN apk add --no-cache ca-certificates \
|
||||||
&& adduser -D -h /var/lib/netbird netbird
|
&& adduser -D -h /var/lib/netbird netbird
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ func getStatus(ctx context.Context) (*proto.StatusResponse, error) {
|
|||||||
}
|
}
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
resp, err := proto.NewDaemonServiceClient(conn).Status(ctx, &proto.StatusRequest{GetFullPeerStatus: true})
|
resp, err := proto.NewDaemonServiceClient(conn).Status(ctx, &proto.StatusRequest{GetFullPeerStatus: true, ShouldRunProbes: true})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("status failed: %v", status.Convert(err).Message())
|
return nil, fmt.Errorf("status failed: %v", status.Convert(err).Message())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ func startManagement(t *testing.T, config *types.Config, testFile string) (*grpc
|
|||||||
Return(&types.Settings{}, nil).
|
Return(&types.Settings{}, nil).
|
||||||
AnyTimes()
|
AnyTimes()
|
||||||
|
|
||||||
accountManager, err := mgmt.BuildManager(context.Background(), store, peersUpdateManager, nil, "", "netbird.selfhosted", eventStore, nil, false, iv, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManagerMock)
|
accountManager, err := mgmt.BuildManager(context.Background(), store, peersUpdateManager, nil, "", "netbird.selfhosted", eventStore, nil, false, iv, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManagerMock, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -398,11 +398,15 @@ func (d *DefaultManager) squashAcceptRules(
|
|||||||
//
|
//
|
||||||
// We zeroed this to notify squash function that this protocol can't be squashed.
|
// We zeroed this to notify squash function that this protocol can't be squashed.
|
||||||
addRuleToCalculationMap := func(i int, r *mgmProto.FirewallRule, protocols map[mgmProto.RuleProtocol]*protoMatch) {
|
addRuleToCalculationMap := func(i int, r *mgmProto.FirewallRule, protocols map[mgmProto.RuleProtocol]*protoMatch) {
|
||||||
drop := r.Action == mgmProto.RuleAction_DROP || r.Port != ""
|
hasPortRestrictions := r.Action == mgmProto.RuleAction_DROP ||
|
||||||
if drop {
|
r.Port != "" || !portInfoEmpty(r.PortInfo)
|
||||||
|
|
||||||
|
if hasPortRestrictions {
|
||||||
|
// Don't squash rules with port restrictions
|
||||||
protocols[r.Protocol] = &protoMatch{ips: map[string]int{}}
|
protocols[r.Protocol] = &protoMatch{ips: map[string]int{}}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := protocols[r.Protocol]; !ok {
|
if _, ok := protocols[r.Protocol]; !ok {
|
||||||
protocols[r.Protocol] = &protoMatch{
|
protocols[r.Protocol] = &protoMatch{
|
||||||
ips: map[string]int{},
|
ips: map[string]int{},
|
||||||
|
|||||||
@@ -330,6 +330,434 @@ func TestDefaultManagerSquashRulesNoAffect(t *testing.T) {
|
|||||||
assert.Equal(t, len(networkMap.FirewallRules), len(rules))
|
assert.Equal(t, len(networkMap.FirewallRules), len(rules))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDefaultManagerSquashRulesWithPortRestrictions(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
rules []*mgmProto.FirewallRule
|
||||||
|
expectedCount int
|
||||||
|
description string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "should not squash rules with port ranges",
|
||||||
|
rules: []*mgmProto.FirewallRule{
|
||||||
|
{
|
||||||
|
PeerIP: "10.93.0.1",
|
||||||
|
Direction: mgmProto.RuleDirection_IN,
|
||||||
|
Action: mgmProto.RuleAction_ACCEPT,
|
||||||
|
Protocol: mgmProto.RuleProtocol_TCP,
|
||||||
|
PortInfo: &mgmProto.PortInfo{
|
||||||
|
PortSelection: &mgmProto.PortInfo_Range_{
|
||||||
|
Range: &mgmProto.PortInfo_Range{
|
||||||
|
Start: 8080,
|
||||||
|
End: 8090,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PeerIP: "10.93.0.2",
|
||||||
|
Direction: mgmProto.RuleDirection_IN,
|
||||||
|
Action: mgmProto.RuleAction_ACCEPT,
|
||||||
|
Protocol: mgmProto.RuleProtocol_TCP,
|
||||||
|
PortInfo: &mgmProto.PortInfo{
|
||||||
|
PortSelection: &mgmProto.PortInfo_Range_{
|
||||||
|
Range: &mgmProto.PortInfo_Range{
|
||||||
|
Start: 8080,
|
||||||
|
End: 8090,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PeerIP: "10.93.0.3",
|
||||||
|
Direction: mgmProto.RuleDirection_IN,
|
||||||
|
Action: mgmProto.RuleAction_ACCEPT,
|
||||||
|
Protocol: mgmProto.RuleProtocol_TCP,
|
||||||
|
PortInfo: &mgmProto.PortInfo{
|
||||||
|
PortSelection: &mgmProto.PortInfo_Range_{
|
||||||
|
Range: &mgmProto.PortInfo_Range{
|
||||||
|
Start: 8080,
|
||||||
|
End: 8090,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PeerIP: "10.93.0.4",
|
||||||
|
Direction: mgmProto.RuleDirection_IN,
|
||||||
|
Action: mgmProto.RuleAction_ACCEPT,
|
||||||
|
Protocol: mgmProto.RuleProtocol_TCP,
|
||||||
|
PortInfo: &mgmProto.PortInfo{
|
||||||
|
PortSelection: &mgmProto.PortInfo_Range_{
|
||||||
|
Range: &mgmProto.PortInfo_Range{
|
||||||
|
Start: 8080,
|
||||||
|
End: 8090,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedCount: 4,
|
||||||
|
description: "Rules with port ranges should not be squashed even if they cover all peers",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "should not squash rules with specific ports",
|
||||||
|
rules: []*mgmProto.FirewallRule{
|
||||||
|
{
|
||||||
|
PeerIP: "10.93.0.1",
|
||||||
|
Direction: mgmProto.RuleDirection_IN,
|
||||||
|
Action: mgmProto.RuleAction_ACCEPT,
|
||||||
|
Protocol: mgmProto.RuleProtocol_TCP,
|
||||||
|
PortInfo: &mgmProto.PortInfo{
|
||||||
|
PortSelection: &mgmProto.PortInfo_Port{
|
||||||
|
Port: 80,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PeerIP: "10.93.0.2",
|
||||||
|
Direction: mgmProto.RuleDirection_IN,
|
||||||
|
Action: mgmProto.RuleAction_ACCEPT,
|
||||||
|
Protocol: mgmProto.RuleProtocol_TCP,
|
||||||
|
PortInfo: &mgmProto.PortInfo{
|
||||||
|
PortSelection: &mgmProto.PortInfo_Port{
|
||||||
|
Port: 80,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PeerIP: "10.93.0.3",
|
||||||
|
Direction: mgmProto.RuleDirection_IN,
|
||||||
|
Action: mgmProto.RuleAction_ACCEPT,
|
||||||
|
Protocol: mgmProto.RuleProtocol_TCP,
|
||||||
|
PortInfo: &mgmProto.PortInfo{
|
||||||
|
PortSelection: &mgmProto.PortInfo_Port{
|
||||||
|
Port: 80,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PeerIP: "10.93.0.4",
|
||||||
|
Direction: mgmProto.RuleDirection_IN,
|
||||||
|
Action: mgmProto.RuleAction_ACCEPT,
|
||||||
|
Protocol: mgmProto.RuleProtocol_TCP,
|
||||||
|
PortInfo: &mgmProto.PortInfo{
|
||||||
|
PortSelection: &mgmProto.PortInfo_Port{
|
||||||
|
Port: 80,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedCount: 4,
|
||||||
|
description: "Rules with specific ports should not be squashed even if they cover all peers",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "should not squash rules with legacy port field",
|
||||||
|
rules: []*mgmProto.FirewallRule{
|
||||||
|
{
|
||||||
|
PeerIP: "10.93.0.1",
|
||||||
|
Direction: mgmProto.RuleDirection_IN,
|
||||||
|
Action: mgmProto.RuleAction_ACCEPT,
|
||||||
|
Protocol: mgmProto.RuleProtocol_TCP,
|
||||||
|
Port: "443",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PeerIP: "10.93.0.2",
|
||||||
|
Direction: mgmProto.RuleDirection_IN,
|
||||||
|
Action: mgmProto.RuleAction_ACCEPT,
|
||||||
|
Protocol: mgmProto.RuleProtocol_TCP,
|
||||||
|
Port: "443",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PeerIP: "10.93.0.3",
|
||||||
|
Direction: mgmProto.RuleDirection_IN,
|
||||||
|
Action: mgmProto.RuleAction_ACCEPT,
|
||||||
|
Protocol: mgmProto.RuleProtocol_TCP,
|
||||||
|
Port: "443",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PeerIP: "10.93.0.4",
|
||||||
|
Direction: mgmProto.RuleDirection_IN,
|
||||||
|
Action: mgmProto.RuleAction_ACCEPT,
|
||||||
|
Protocol: mgmProto.RuleProtocol_TCP,
|
||||||
|
Port: "443",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedCount: 4,
|
||||||
|
description: "Rules with legacy port field should not be squashed",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "should not squash rules with DROP action",
|
||||||
|
rules: []*mgmProto.FirewallRule{
|
||||||
|
{
|
||||||
|
PeerIP: "10.93.0.1",
|
||||||
|
Direction: mgmProto.RuleDirection_IN,
|
||||||
|
Action: mgmProto.RuleAction_DROP,
|
||||||
|
Protocol: mgmProto.RuleProtocol_TCP,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PeerIP: "10.93.0.2",
|
||||||
|
Direction: mgmProto.RuleDirection_IN,
|
||||||
|
Action: mgmProto.RuleAction_DROP,
|
||||||
|
Protocol: mgmProto.RuleProtocol_TCP,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PeerIP: "10.93.0.3",
|
||||||
|
Direction: mgmProto.RuleDirection_IN,
|
||||||
|
Action: mgmProto.RuleAction_DROP,
|
||||||
|
Protocol: mgmProto.RuleProtocol_TCP,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PeerIP: "10.93.0.4",
|
||||||
|
Direction: mgmProto.RuleDirection_IN,
|
||||||
|
Action: mgmProto.RuleAction_DROP,
|
||||||
|
Protocol: mgmProto.RuleProtocol_TCP,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedCount: 4,
|
||||||
|
description: "Rules with DROP action should not be squashed",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "should squash rules without port restrictions",
|
||||||
|
rules: []*mgmProto.FirewallRule{
|
||||||
|
{
|
||||||
|
PeerIP: "10.93.0.1",
|
||||||
|
Direction: mgmProto.RuleDirection_IN,
|
||||||
|
Action: mgmProto.RuleAction_ACCEPT,
|
||||||
|
Protocol: mgmProto.RuleProtocol_TCP,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PeerIP: "10.93.0.2",
|
||||||
|
Direction: mgmProto.RuleDirection_IN,
|
||||||
|
Action: mgmProto.RuleAction_ACCEPT,
|
||||||
|
Protocol: mgmProto.RuleProtocol_TCP,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PeerIP: "10.93.0.3",
|
||||||
|
Direction: mgmProto.RuleDirection_IN,
|
||||||
|
Action: mgmProto.RuleAction_ACCEPT,
|
||||||
|
Protocol: mgmProto.RuleProtocol_TCP,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PeerIP: "10.93.0.4",
|
||||||
|
Direction: mgmProto.RuleDirection_IN,
|
||||||
|
Action: mgmProto.RuleAction_ACCEPT,
|
||||||
|
Protocol: mgmProto.RuleProtocol_TCP,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedCount: 1,
|
||||||
|
description: "Rules without port restrictions should be squashed into a single 0.0.0.0 rule",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "mixed rules should not squash protocol with port restrictions",
|
||||||
|
rules: []*mgmProto.FirewallRule{
|
||||||
|
{
|
||||||
|
PeerIP: "10.93.0.1",
|
||||||
|
Direction: mgmProto.RuleDirection_IN,
|
||||||
|
Action: mgmProto.RuleAction_ACCEPT,
|
||||||
|
Protocol: mgmProto.RuleProtocol_TCP,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PeerIP: "10.93.0.2",
|
||||||
|
Direction: mgmProto.RuleDirection_IN,
|
||||||
|
Action: mgmProto.RuleAction_ACCEPT,
|
||||||
|
Protocol: mgmProto.RuleProtocol_TCP,
|
||||||
|
PortInfo: &mgmProto.PortInfo{
|
||||||
|
PortSelection: &mgmProto.PortInfo_Port{
|
||||||
|
Port: 80,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PeerIP: "10.93.0.3",
|
||||||
|
Direction: mgmProto.RuleDirection_IN,
|
||||||
|
Action: mgmProto.RuleAction_ACCEPT,
|
||||||
|
Protocol: mgmProto.RuleProtocol_TCP,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PeerIP: "10.93.0.4",
|
||||||
|
Direction: mgmProto.RuleDirection_IN,
|
||||||
|
Action: mgmProto.RuleAction_ACCEPT,
|
||||||
|
Protocol: mgmProto.RuleProtocol_TCP,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedCount: 4,
|
||||||
|
description: "TCP should not be squashed because one rule has port restrictions",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "should squash UDP but not TCP when TCP has port restrictions",
|
||||||
|
rules: []*mgmProto.FirewallRule{
|
||||||
|
// TCP rules with port restrictions - should NOT be squashed
|
||||||
|
{
|
||||||
|
PeerIP: "10.93.0.1",
|
||||||
|
Direction: mgmProto.RuleDirection_IN,
|
||||||
|
Action: mgmProto.RuleAction_ACCEPT,
|
||||||
|
Protocol: mgmProto.RuleProtocol_TCP,
|
||||||
|
Port: "443",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PeerIP: "10.93.0.2",
|
||||||
|
Direction: mgmProto.RuleDirection_IN,
|
||||||
|
Action: mgmProto.RuleAction_ACCEPT,
|
||||||
|
Protocol: mgmProto.RuleProtocol_TCP,
|
||||||
|
Port: "443",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PeerIP: "10.93.0.3",
|
||||||
|
Direction: mgmProto.RuleDirection_IN,
|
||||||
|
Action: mgmProto.RuleAction_ACCEPT,
|
||||||
|
Protocol: mgmProto.RuleProtocol_TCP,
|
||||||
|
Port: "443",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PeerIP: "10.93.0.4",
|
||||||
|
Direction: mgmProto.RuleDirection_IN,
|
||||||
|
Action: mgmProto.RuleAction_ACCEPT,
|
||||||
|
Protocol: mgmProto.RuleProtocol_TCP,
|
||||||
|
Port: "443",
|
||||||
|
},
|
||||||
|
// UDP rules without port restrictions - SHOULD be squashed
|
||||||
|
{
|
||||||
|
PeerIP: "10.93.0.1",
|
||||||
|
Direction: mgmProto.RuleDirection_IN,
|
||||||
|
Action: mgmProto.RuleAction_ACCEPT,
|
||||||
|
Protocol: mgmProto.RuleProtocol_UDP,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PeerIP: "10.93.0.2",
|
||||||
|
Direction: mgmProto.RuleDirection_IN,
|
||||||
|
Action: mgmProto.RuleAction_ACCEPT,
|
||||||
|
Protocol: mgmProto.RuleProtocol_UDP,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PeerIP: "10.93.0.3",
|
||||||
|
Direction: mgmProto.RuleDirection_IN,
|
||||||
|
Action: mgmProto.RuleAction_ACCEPT,
|
||||||
|
Protocol: mgmProto.RuleProtocol_UDP,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PeerIP: "10.93.0.4",
|
||||||
|
Direction: mgmProto.RuleDirection_IN,
|
||||||
|
Action: mgmProto.RuleAction_ACCEPT,
|
||||||
|
Protocol: mgmProto.RuleProtocol_UDP,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedCount: 5, // 4 TCP rules + 1 squashed UDP rule (0.0.0.0)
|
||||||
|
description: "UDP should be squashed to 0.0.0.0 rule, but TCP should remain as individual rules due to port restrictions",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
networkMap := &mgmProto.NetworkMap{
|
||||||
|
RemotePeers: []*mgmProto.RemotePeerConfig{
|
||||||
|
{AllowedIps: []string{"10.93.0.1"}},
|
||||||
|
{AllowedIps: []string{"10.93.0.2"}},
|
||||||
|
{AllowedIps: []string{"10.93.0.3"}},
|
||||||
|
{AllowedIps: []string{"10.93.0.4"}},
|
||||||
|
},
|
||||||
|
FirewallRules: tt.rules,
|
||||||
|
}
|
||||||
|
|
||||||
|
manager := &DefaultManager{}
|
||||||
|
rules, _ := manager.squashAcceptRules(networkMap)
|
||||||
|
|
||||||
|
assert.Equal(t, tt.expectedCount, len(rules), tt.description)
|
||||||
|
|
||||||
|
// For squashed rules, verify we get the expected 0.0.0.0 rule
|
||||||
|
if tt.expectedCount == 1 {
|
||||||
|
assert.Equal(t, "0.0.0.0", rules[0].PeerIP)
|
||||||
|
assert.Equal(t, mgmProto.RuleDirection_IN, rules[0].Direction)
|
||||||
|
assert.Equal(t, mgmProto.RuleAction_ACCEPT, rules[0].Action)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPortInfoEmpty(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
portInfo *mgmProto.PortInfo
|
||||||
|
expected bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "nil PortInfo should be empty",
|
||||||
|
portInfo: nil,
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "PortInfo with zero port should be empty",
|
||||||
|
portInfo: &mgmProto.PortInfo{
|
||||||
|
PortSelection: &mgmProto.PortInfo_Port{
|
||||||
|
Port: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "PortInfo with valid port should not be empty",
|
||||||
|
portInfo: &mgmProto.PortInfo{
|
||||||
|
PortSelection: &mgmProto.PortInfo_Port{
|
||||||
|
Port: 80,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "PortInfo with nil range should be empty",
|
||||||
|
portInfo: &mgmProto.PortInfo{
|
||||||
|
PortSelection: &mgmProto.PortInfo_Range_{
|
||||||
|
Range: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "PortInfo with zero start range should be empty",
|
||||||
|
portInfo: &mgmProto.PortInfo{
|
||||||
|
PortSelection: &mgmProto.PortInfo_Range_{
|
||||||
|
Range: &mgmProto.PortInfo_Range{
|
||||||
|
Start: 0,
|
||||||
|
End: 100,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "PortInfo with zero end range should be empty",
|
||||||
|
portInfo: &mgmProto.PortInfo{
|
||||||
|
PortSelection: &mgmProto.PortInfo_Range_{
|
||||||
|
Range: &mgmProto.PortInfo_Range{
|
||||||
|
Start: 80,
|
||||||
|
End: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "PortInfo with valid range should not be empty",
|
||||||
|
portInfo: &mgmProto.PortInfo{
|
||||||
|
PortSelection: &mgmProto.PortInfo_Range_{
|
||||||
|
Range: &mgmProto.PortInfo_Range{
|
||||||
|
Start: 8080,
|
||||||
|
End: 8090,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
result := portInfoEmpty(tt.portInfo)
|
||||||
|
assert.Equal(t, tt.expected, result)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestDefaultManagerEnableSSHRules(t *testing.T) {
|
func TestDefaultManagerEnableSSHRules(t *testing.T) {
|
||||||
networkMap := &mgmProto.NetworkMap{
|
networkMap := &mgmProto.NetworkMap{
|
||||||
PeerConfig: &mgmProto.PeerConfig{
|
PeerConfig: &mgmProto.PeerConfig{
|
||||||
|
|||||||
@@ -319,10 +319,6 @@ func (config *Config) apply(input ConfigInput) (updated bool, err error) {
|
|||||||
*input.WireguardPort, config.WgPort)
|
*input.WireguardPort, config.WgPort)
|
||||||
config.WgPort = *input.WireguardPort
|
config.WgPort = *input.WireguardPort
|
||||||
updated = true
|
updated = true
|
||||||
} else if config.WgPort == 0 {
|
|
||||||
config.WgPort = iface.DefaultWgPort
|
|
||||||
log.Infof("using default Wireguard port %d", config.WgPort)
|
|
||||||
updated = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if input.InterfaceName != nil && *input.InterfaceName != config.WgIface {
|
if input.InterfaceName != nil && *input.InterfaceName != config.WgIface {
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ func (e *ConnMgr) AddPeerConn(ctx context.Context, peerKey string, conn *peer.Co
|
|||||||
PeerConnID: conn.ConnID(),
|
PeerConnID: conn.ConnID(),
|
||||||
Log: conn.Log,
|
Log: conn.Log,
|
||||||
}
|
}
|
||||||
excluded, err := e.lazyConnMgr.AddPeer(lazyPeerCfg)
|
excluded, err := e.lazyConnMgr.AddPeer(e.lazyCtx, lazyPeerCfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
conn.Log.Errorf("failed to add peer to lazyconn manager: %v", err)
|
conn.Log.Errorf("failed to add peer to lazyconn manager: %v", err)
|
||||||
if err := conn.Open(ctx); err != nil {
|
if err := conn.Open(ctx); err != nil {
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import (
|
|||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
gstatus "google.golang.org/grpc/status"
|
gstatus "google.golang.org/grpc/status"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/client/iface"
|
|
||||||
"github.com/netbirdio/netbird/client/iface/device"
|
"github.com/netbirdio/netbird/client/iface/device"
|
||||||
"github.com/netbirdio/netbird/client/internal/dns"
|
"github.com/netbirdio/netbird/client/internal/dns"
|
||||||
"github.com/netbirdio/netbird/client/internal/listener"
|
"github.com/netbirdio/netbird/client/internal/listener"
|
||||||
@@ -526,17 +525,13 @@ func statusRecorderToSignalConnStateNotifier(statusRecorder *peer.Status) signal
|
|||||||
|
|
||||||
// freePort attempts to determine if the provided port is available, if not it will ask the system for a free port.
|
// freePort attempts to determine if the provided port is available, if not it will ask the system for a free port.
|
||||||
func freePort(initPort int) (int, error) {
|
func freePort(initPort int) (int, error) {
|
||||||
addr := net.UDPAddr{}
|
addr := net.UDPAddr{Port: initPort}
|
||||||
if initPort == 0 {
|
|
||||||
initPort = iface.DefaultWgPort
|
|
||||||
}
|
|
||||||
|
|
||||||
addr.Port = initPort
|
|
||||||
|
|
||||||
conn, err := net.ListenUDP("udp", &addr)
|
conn, err := net.ListenUDP("udp", &addr)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
returnPort := conn.LocalAddr().(*net.UDPAddr).Port
|
||||||
closeConnWithLog(conn)
|
closeConnWithLog(conn)
|
||||||
return initPort, nil
|
return returnPort, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the port is already in use, ask the system for a free port
|
// if the port is already in use, ask the system for a free port
|
||||||
|
|||||||
@@ -13,10 +13,10 @@ func Test_freePort(t *testing.T) {
|
|||||||
shouldMatch bool
|
shouldMatch bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "not provided, fallback to default",
|
name: "when port is 0 use random port",
|
||||||
port: 0,
|
port: 0,
|
||||||
want: 51820,
|
want: 0,
|
||||||
shouldMatch: true,
|
shouldMatch: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "provided and available",
|
name: "provided and available",
|
||||||
@@ -31,7 +31,7 @@ func Test_freePort(t *testing.T) {
|
|||||||
shouldMatch: false,
|
shouldMatch: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
c1, err := net.ListenUDP("udp", &net.UDPAddr{Port: 51830})
|
c1, err := net.ListenUDP("udp", &net.UDPAddr{Port: 0})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("freePort error = %v", err)
|
t.Errorf("freePort error = %v", err)
|
||||||
}
|
}
|
||||||
@@ -39,6 +39,14 @@ func Test_freePort(t *testing.T) {
|
|||||||
_ = c1.Close()
|
_ = c1.Close()
|
||||||
}(c1)
|
}(c1)
|
||||||
|
|
||||||
|
if tests[1].port == c1.LocalAddr().(*net.UDPAddr).Port {
|
||||||
|
tests[1].port++
|
||||||
|
tests[1].want++
|
||||||
|
}
|
||||||
|
|
||||||
|
tests[2].port = c1.LocalAddr().(*net.UDPAddr).Port
|
||||||
|
tests[2].want = c1.LocalAddr().(*net.UDPAddr).Port
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
|||||||
@@ -1476,7 +1476,7 @@ func startManagement(t *testing.T, dataDir, testFile string) (*grpc.Server, stri
|
|||||||
|
|
||||||
permissionsManager := permissions.NewManager(store)
|
permissionsManager := permissions.NewManager(store)
|
||||||
|
|
||||||
accountManager, err := server.BuildManager(context.Background(), store, peersUpdateManager, nil, "", "netbird.selfhosted", eventStore, nil, false, ia, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager)
|
accountManager, err := server.BuildManager(context.Background(), store, peersUpdateManager, nil, "", "netbird.selfhosted", eventStore, nil, false, ia, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,3 +68,8 @@ func (i *Monitor) PauseTimer() {
|
|||||||
func (i *Monitor) ResetTimer() {
|
func (i *Monitor) ResetTimer() {
|
||||||
i.timer.Reset(i.inactivityThreshold)
|
i.timer.Reset(i.inactivityThreshold)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (i *Monitor) ResetMonitor(ctx context.Context, timeoutChan chan peer.ConnID) {
|
||||||
|
i.Stop()
|
||||||
|
go i.Start(ctx, timeoutChan)
|
||||||
|
}
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ type Manager struct {
|
|||||||
// Route HA group management
|
// Route HA group management
|
||||||
peerToHAGroups map[string][]route.HAUniqueID // peer ID -> HA groups they belong to
|
peerToHAGroups map[string][]route.HAUniqueID // peer ID -> HA groups they belong to
|
||||||
haGroupToPeers map[route.HAUniqueID][]string // HA group -> peer IDs in the group
|
haGroupToPeers map[route.HAUniqueID][]string // HA group -> peer IDs in the group
|
||||||
routesMu sync.RWMutex // protects route mappings
|
routesMu sync.RWMutex
|
||||||
|
|
||||||
onInactive chan peerid.ConnID
|
onInactive chan peerid.ConnID
|
||||||
}
|
}
|
||||||
@@ -146,7 +146,7 @@ func (m *Manager) Start(ctx context.Context) {
|
|||||||
case peerConnID := <-m.activityManager.OnActivityChan:
|
case peerConnID := <-m.activityManager.OnActivityChan:
|
||||||
m.onPeerActivity(ctx, peerConnID)
|
m.onPeerActivity(ctx, peerConnID)
|
||||||
case peerConnID := <-m.onInactive:
|
case peerConnID := <-m.onInactive:
|
||||||
m.onPeerInactivityTimedOut(peerConnID)
|
m.onPeerInactivityTimedOut(ctx, peerConnID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -197,7 +197,7 @@ func (m *Manager) ExcludePeer(ctx context.Context, peerConfigs []lazyconn.PeerCo
|
|||||||
return added
|
return added
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Manager) AddPeer(peerCfg lazyconn.PeerConfig) (bool, error) {
|
func (m *Manager) AddPeer(ctx context.Context, peerCfg lazyconn.PeerConfig) (bool, error) {
|
||||||
m.managedPeersMu.Lock()
|
m.managedPeersMu.Lock()
|
||||||
defer m.managedPeersMu.Unlock()
|
defer m.managedPeersMu.Unlock()
|
||||||
|
|
||||||
@@ -225,6 +225,13 @@ func (m *Manager) AddPeer(peerCfg lazyconn.PeerConfig) (bool, error) {
|
|||||||
peerCfg: &peerCfg,
|
peerCfg: &peerCfg,
|
||||||
expectedWatcher: watcherActivity,
|
expectedWatcher: watcherActivity,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if this peer should be activated because its HA group peers are active
|
||||||
|
if group, ok := m.shouldActivateNewPeer(peerCfg.PublicKey); ok {
|
||||||
|
peerCfg.Log.Debugf("peer belongs to active HA group %s, will activate immediately", group)
|
||||||
|
m.activateNewPeerInActiveGroup(ctx, peerCfg)
|
||||||
|
}
|
||||||
|
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,36 +322,38 @@ func (m *Manager) activateSinglePeer(ctx context.Context, cfg *lazyconn.PeerConf
|
|||||||
|
|
||||||
// activateHAGroupPeers activates all peers in HA groups that the given peer belongs to
|
// activateHAGroupPeers activates all peers in HA groups that the given peer belongs to
|
||||||
func (m *Manager) activateHAGroupPeers(ctx context.Context, triggerPeerID string) {
|
func (m *Manager) activateHAGroupPeers(ctx context.Context, triggerPeerID string) {
|
||||||
|
var peersToActivate []string
|
||||||
|
|
||||||
m.routesMu.RLock()
|
m.routesMu.RLock()
|
||||||
haGroups := m.peerToHAGroups[triggerPeerID]
|
haGroups := m.peerToHAGroups[triggerPeerID]
|
||||||
m.routesMu.RUnlock()
|
|
||||||
|
|
||||||
if len(haGroups) == 0 {
|
if len(haGroups) == 0 {
|
||||||
|
m.routesMu.RUnlock()
|
||||||
log.Debugf("peer %s is not part of any HA groups", triggerPeerID)
|
log.Debugf("peer %s is not part of any HA groups", triggerPeerID)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
activatedCount := 0
|
|
||||||
for _, haGroup := range haGroups {
|
for _, haGroup := range haGroups {
|
||||||
m.routesMu.RLock()
|
|
||||||
peers := m.haGroupToPeers[haGroup]
|
peers := m.haGroupToPeers[haGroup]
|
||||||
m.routesMu.RUnlock()
|
|
||||||
|
|
||||||
for _, peerID := range peers {
|
for _, peerID := range peers {
|
||||||
if peerID == triggerPeerID {
|
if peerID != triggerPeerID {
|
||||||
continue
|
peersToActivate = append(peersToActivate, peerID)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m.routesMu.RUnlock()
|
||||||
|
|
||||||
cfg, mp := m.getPeerForActivation(peerID)
|
activatedCount := 0
|
||||||
if cfg == nil {
|
for _, peerID := range peersToActivate {
|
||||||
continue
|
cfg, mp := m.getPeerForActivation(peerID)
|
||||||
}
|
if cfg == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if m.activateSinglePeer(ctx, cfg, mp) {
|
if m.activateSinglePeer(ctx, cfg, mp) {
|
||||||
activatedCount++
|
activatedCount++
|
||||||
cfg.Log.Infof("activated peer as part of HA group %s (triggered by %s)", haGroup, triggerPeerID)
|
cfg.Log.Infof("activated peer as part of HA group (triggered by %s)", triggerPeerID)
|
||||||
m.peerStore.PeerConnOpen(m.engineCtx, cfg.PublicKey)
|
m.peerStore.PeerConnOpen(m.engineCtx, cfg.PublicKey)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -354,6 +363,51 @@ func (m *Manager) activateHAGroupPeers(ctx context.Context, triggerPeerID string
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// shouldActivateNewPeer checks if a newly added peer should be activated
|
||||||
|
// because other peers in its HA groups are already active
|
||||||
|
func (m *Manager) shouldActivateNewPeer(peerID string) (route.HAUniqueID, bool) {
|
||||||
|
m.routesMu.RLock()
|
||||||
|
defer m.routesMu.RUnlock()
|
||||||
|
|
||||||
|
haGroups := m.peerToHAGroups[peerID]
|
||||||
|
if len(haGroups) == 0 {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, haGroup := range haGroups {
|
||||||
|
peers := m.haGroupToPeers[haGroup]
|
||||||
|
for _, groupPeerID := range peers {
|
||||||
|
if groupPeerID == peerID {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg, ok := m.managedPeers[groupPeerID]
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if mp, ok := m.managedPeersByConnID[cfg.PeerConnID]; ok && mp.expectedWatcher == watcherInactivity {
|
||||||
|
return haGroup, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
// activateNewPeerInActiveGroup activates a newly added peer that should be active due to HA group
|
||||||
|
func (m *Manager) activateNewPeerInActiveGroup(ctx context.Context, peerCfg lazyconn.PeerConfig) {
|
||||||
|
mp, ok := m.managedPeersByConnID[peerCfg.PeerConnID]
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !m.activateSinglePeer(ctx, &peerCfg, mp) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
peerCfg.Log.Infof("activated newly added peer due to active HA group peers")
|
||||||
|
m.peerStore.PeerConnOpen(m.engineCtx, peerCfg.PublicKey)
|
||||||
|
}
|
||||||
|
|
||||||
func (m *Manager) addActivePeer(ctx context.Context, peerCfg lazyconn.PeerConfig) error {
|
func (m *Manager) addActivePeer(ctx context.Context, peerCfg lazyconn.PeerConfig) error {
|
||||||
if _, ok := m.managedPeers[peerCfg.PublicKey]; ok {
|
if _, ok := m.managedPeers[peerCfg.PublicKey]; ok {
|
||||||
peerCfg.Log.Warnf("peer already managed")
|
peerCfg.Log.Warnf("peer already managed")
|
||||||
@@ -415,6 +469,48 @@ func (m *Manager) close() {
|
|||||||
log.Infof("lazy connection manager closed")
|
log.Infof("lazy connection manager closed")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// shouldDeferIdleForHA checks if peer should stay connected due to HA group requirements
|
||||||
|
func (m *Manager) shouldDeferIdleForHA(peerID string) bool {
|
||||||
|
m.routesMu.RLock()
|
||||||
|
defer m.routesMu.RUnlock()
|
||||||
|
|
||||||
|
haGroups := m.peerToHAGroups[peerID]
|
||||||
|
if len(haGroups) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, haGroup := range haGroups {
|
||||||
|
groupPeers := m.haGroupToPeers[haGroup]
|
||||||
|
|
||||||
|
for _, groupPeerID := range groupPeers {
|
||||||
|
if groupPeerID == peerID {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg, ok := m.managedPeers[groupPeerID]
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
groupMp, ok := m.managedPeersByConnID[cfg.PeerConnID]
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if groupMp.expectedWatcher != watcherInactivity {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Other member is still connected, defer idle
|
||||||
|
if peer, ok := m.peerStore.PeerConn(groupPeerID); ok && peer.IsConnected() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func (m *Manager) onPeerActivity(ctx context.Context, peerConnID peerid.ConnID) {
|
func (m *Manager) onPeerActivity(ctx context.Context, peerConnID peerid.ConnID) {
|
||||||
m.managedPeersMu.Lock()
|
m.managedPeersMu.Lock()
|
||||||
defer m.managedPeersMu.Unlock()
|
defer m.managedPeersMu.Unlock()
|
||||||
@@ -441,7 +537,7 @@ func (m *Manager) onPeerActivity(ctx context.Context, peerConnID peerid.ConnID)
|
|||||||
m.peerStore.PeerConnOpen(m.engineCtx, mp.peerCfg.PublicKey)
|
m.peerStore.PeerConnOpen(m.engineCtx, mp.peerCfg.PublicKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Manager) onPeerInactivityTimedOut(peerConnID peerid.ConnID) {
|
func (m *Manager) onPeerInactivityTimedOut(ctx context.Context, peerConnID peerid.ConnID) {
|
||||||
m.managedPeersMu.Lock()
|
m.managedPeersMu.Lock()
|
||||||
defer m.managedPeersMu.Unlock()
|
defer m.managedPeersMu.Unlock()
|
||||||
|
|
||||||
@@ -456,6 +552,17 @@ func (m *Manager) onPeerInactivityTimedOut(peerConnID peerid.ConnID) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if m.shouldDeferIdleForHA(mp.peerCfg.PublicKey) {
|
||||||
|
iw, ok := m.inactivityMonitors[peerConnID]
|
||||||
|
if ok {
|
||||||
|
mp.peerCfg.Log.Debugf("resetting inactivity timer due to HA group requirements")
|
||||||
|
iw.ResetMonitor(ctx, m.onInactive)
|
||||||
|
} else {
|
||||||
|
mp.peerCfg.Log.Errorf("inactivity monitor not found for HA defer reset")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
mp.peerCfg.Log.Infof("connection timed out")
|
mp.peerCfg.Log.Infof("connection timed out")
|
||||||
|
|
||||||
// this is blocking operation, potentially can be optimized
|
// this is blocking operation, potentially can be optimized
|
||||||
@@ -489,7 +596,7 @@ func (m *Manager) onPeerConnected(peerConnID peerid.ConnID) {
|
|||||||
|
|
||||||
iw, ok := m.inactivityMonitors[mp.peerCfg.PeerConnID]
|
iw, ok := m.inactivityMonitors[mp.peerCfg.PeerConnID]
|
||||||
if !ok {
|
if !ok {
|
||||||
mp.peerCfg.Log.Errorf("inactivity monitor not found for peer")
|
mp.peerCfg.Log.Warnf("inactivity monitor not found for peer")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -317,12 +317,12 @@ func (conn *Conn) WgConfig() WgConfig {
|
|||||||
return conn.config.WgConfig
|
return conn.config.WgConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsConnected unit tests only
|
// IsConnected returns true if the peer is connected
|
||||||
// refactor unit test to use status recorder use refactor status recorded to manage connection status in peer.Conn
|
|
||||||
func (conn *Conn) IsConnected() bool {
|
func (conn *Conn) IsConnected() bool {
|
||||||
conn.mu.Lock()
|
conn.mu.Lock()
|
||||||
defer conn.mu.Unlock()
|
defer conn.mu.Unlock()
|
||||||
return conn.currentConnPriority != conntype.None
|
|
||||||
|
return conn.evalStatus() == StatusConnected
|
||||||
}
|
}
|
||||||
|
|
||||||
func (conn *Conn) GetKey() string {
|
func (conn *Conn) GetKey() string {
|
||||||
|
|||||||
@@ -28,7 +28,10 @@ func (n Nexthop) String() string {
|
|||||||
if n.Intf == nil {
|
if n.Intf == nil {
|
||||||
return n.IP.String()
|
return n.IP.String()
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%s @ %d (%s)", n.IP.String(), n.Intf.Index, n.Intf.Name)
|
if n.IP.IsValid() {
|
||||||
|
return fmt.Sprintf("%s @ %d (%s)", n.IP.String(), n.Intf.Index, n.Intf.Name)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("no-ip @ %d (%s)", n.Intf.Index, n.Intf.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
type wgIface interface {
|
type wgIface interface {
|
||||||
|
|||||||
+5
-22
@@ -1,8 +1,10 @@
|
|||||||
<Wix
|
<Wix
|
||||||
xmlns="http://wixtoolset.org/schemas/v4/wxs">
|
xmlns="http://wixtoolset.org/schemas/v4/wxs"
|
||||||
|
xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util">
|
||||||
<Package Name="NetBird" Version="$(env.NETBIRD_VERSION)" Manufacturer="NetBird GmbH" Language="1033" UpgradeCode="6456ec4e-3ad6-4b9b-a2be-98e81cb21ccf"
|
<Package Name="NetBird" Version="$(env.NETBIRD_VERSION)" Manufacturer="NetBird GmbH" Language="1033" UpgradeCode="6456ec4e-3ad6-4b9b-a2be-98e81cb21ccf"
|
||||||
InstallerVersion="500" Compressed="yes" Codepage="utf-8" >
|
InstallerVersion="500" Compressed="yes" Codepage="utf-8" >
|
||||||
|
|
||||||
|
|
||||||
<MediaTemplate EmbedCab="yes" />
|
<MediaTemplate EmbedCab="yes" />
|
||||||
|
|
||||||
<Feature Id="NetbirdFeature" Title="Netbird" Level="1">
|
<Feature Id="NetbirdFeature" Title="Netbird" Level="1">
|
||||||
@@ -46,29 +48,10 @@
|
|||||||
<ComponentRef Id="NetbirdFiles" />
|
<ComponentRef Id="NetbirdFiles" />
|
||||||
</ComponentGroup>
|
</ComponentGroup>
|
||||||
|
|
||||||
<Property Id="cmd" Value="cmd.exe"/>
|
<util:CloseApplication Id="CloseNetBird" CloseMessage="no" Target="netbird.exe" RebootPrompt="no" />
|
||||||
|
<util:CloseApplication Id="CloseNetBirdUI" CloseMessage="no" Target="netbird-ui.exe" RebootPrompt="no" />
|
||||||
|
|
||||||
<CustomAction Id="KillDaemon"
|
|
||||||
ExeCommand='/c "taskkill /im netbird.exe"'
|
|
||||||
Execute="deferred"
|
|
||||||
Property="cmd"
|
|
||||||
Impersonate="no"
|
|
||||||
Return="ignore"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<CustomAction Id="KillUI"
|
|
||||||
ExeCommand='/c "taskkill /im netbird-ui.exe"'
|
|
||||||
Execute="deferred"
|
|
||||||
Property="cmd"
|
|
||||||
Impersonate="no"
|
|
||||||
Return="ignore"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<InstallExecuteSequence>
|
|
||||||
<!-- For Uninstallation -->
|
|
||||||
<Custom Action="KillDaemon" Before="RemoveFiles" Condition="Installed"/>
|
|
||||||
<Custom Action="KillUI" After="KillDaemon" Condition="Installed"/>
|
|
||||||
</InstallExecuteSequence>
|
|
||||||
|
|
||||||
<!-- Icons -->
|
<!-- Icons -->
|
||||||
<Icon Id="NetbirdIcon" SourceFile=".\client\ui\assets\netbird.ico" />
|
<Icon Id="NetbirdIcon" SourceFile=".\client\ui\assets\netbird.ico" />
|
||||||
|
|||||||
+794
-1862
File diff suppressed because it is too large
Load Diff
@@ -158,6 +158,7 @@ message UpResponse {}
|
|||||||
|
|
||||||
message StatusRequest{
|
message StatusRequest{
|
||||||
bool getFullPeerStatus = 1;
|
bool getFullPeerStatus = 1;
|
||||||
|
bool shouldRunProbes = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message StatusResponse{
|
message StatusResponse{
|
||||||
|
|||||||
+113
-79
@@ -1,4 +1,8 @@
|
|||||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// - protoc-gen-go-grpc v1.5.1
|
||||||
|
// - protoc v5.29.3
|
||||||
|
// source: daemon.proto
|
||||||
|
|
||||||
package proto
|
package proto
|
||||||
|
|
||||||
@@ -11,8 +15,31 @@ import (
|
|||||||
|
|
||||||
// This is a compile-time assertion to ensure that this generated file
|
// This is a compile-time assertion to ensure that this generated file
|
||||||
// is compatible with the grpc package it is being compiled against.
|
// is compatible with the grpc package it is being compiled against.
|
||||||
// Requires gRPC-Go v1.32.0 or later.
|
// Requires gRPC-Go v1.64.0 or later.
|
||||||
const _ = grpc.SupportPackageIsVersion7
|
const _ = grpc.SupportPackageIsVersion9
|
||||||
|
|
||||||
|
const (
|
||||||
|
DaemonService_Login_FullMethodName = "/daemon.DaemonService/Login"
|
||||||
|
DaemonService_WaitSSOLogin_FullMethodName = "/daemon.DaemonService/WaitSSOLogin"
|
||||||
|
DaemonService_Up_FullMethodName = "/daemon.DaemonService/Up"
|
||||||
|
DaemonService_Status_FullMethodName = "/daemon.DaemonService/Status"
|
||||||
|
DaemonService_Down_FullMethodName = "/daemon.DaemonService/Down"
|
||||||
|
DaemonService_GetConfig_FullMethodName = "/daemon.DaemonService/GetConfig"
|
||||||
|
DaemonService_ListNetworks_FullMethodName = "/daemon.DaemonService/ListNetworks"
|
||||||
|
DaemonService_SelectNetworks_FullMethodName = "/daemon.DaemonService/SelectNetworks"
|
||||||
|
DaemonService_DeselectNetworks_FullMethodName = "/daemon.DaemonService/DeselectNetworks"
|
||||||
|
DaemonService_ForwardingRules_FullMethodName = "/daemon.DaemonService/ForwardingRules"
|
||||||
|
DaemonService_DebugBundle_FullMethodName = "/daemon.DaemonService/DebugBundle"
|
||||||
|
DaemonService_GetLogLevel_FullMethodName = "/daemon.DaemonService/GetLogLevel"
|
||||||
|
DaemonService_SetLogLevel_FullMethodName = "/daemon.DaemonService/SetLogLevel"
|
||||||
|
DaemonService_ListStates_FullMethodName = "/daemon.DaemonService/ListStates"
|
||||||
|
DaemonService_CleanState_FullMethodName = "/daemon.DaemonService/CleanState"
|
||||||
|
DaemonService_DeleteState_FullMethodName = "/daemon.DaemonService/DeleteState"
|
||||||
|
DaemonService_SetNetworkMapPersistence_FullMethodName = "/daemon.DaemonService/SetNetworkMapPersistence"
|
||||||
|
DaemonService_TracePacket_FullMethodName = "/daemon.DaemonService/TracePacket"
|
||||||
|
DaemonService_SubscribeEvents_FullMethodName = "/daemon.DaemonService/SubscribeEvents"
|
||||||
|
DaemonService_GetEvents_FullMethodName = "/daemon.DaemonService/GetEvents"
|
||||||
|
)
|
||||||
|
|
||||||
// DaemonServiceClient is the client API for DaemonService service.
|
// DaemonServiceClient is the client API for DaemonService service.
|
||||||
//
|
//
|
||||||
@@ -53,7 +80,7 @@ type DaemonServiceClient interface {
|
|||||||
// SetNetworkMapPersistence enables or disables network map persistence
|
// SetNetworkMapPersistence enables or disables network map persistence
|
||||||
SetNetworkMapPersistence(ctx context.Context, in *SetNetworkMapPersistenceRequest, opts ...grpc.CallOption) (*SetNetworkMapPersistenceResponse, error)
|
SetNetworkMapPersistence(ctx context.Context, in *SetNetworkMapPersistenceRequest, opts ...grpc.CallOption) (*SetNetworkMapPersistenceResponse, error)
|
||||||
TracePacket(ctx context.Context, in *TracePacketRequest, opts ...grpc.CallOption) (*TracePacketResponse, error)
|
TracePacket(ctx context.Context, in *TracePacketRequest, opts ...grpc.CallOption) (*TracePacketResponse, error)
|
||||||
SubscribeEvents(ctx context.Context, in *SubscribeRequest, opts ...grpc.CallOption) (DaemonService_SubscribeEventsClient, error)
|
SubscribeEvents(ctx context.Context, in *SubscribeRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[SystemEvent], error)
|
||||||
GetEvents(ctx context.Context, in *GetEventsRequest, opts ...grpc.CallOption) (*GetEventsResponse, error)
|
GetEvents(ctx context.Context, in *GetEventsRequest, opts ...grpc.CallOption) (*GetEventsResponse, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,8 +93,9 @@ func NewDaemonServiceClient(cc grpc.ClientConnInterface) DaemonServiceClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *daemonServiceClient) Login(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error) {
|
func (c *daemonServiceClient) Login(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(LoginResponse)
|
out := new(LoginResponse)
|
||||||
err := c.cc.Invoke(ctx, "/daemon.DaemonService/Login", in, out, opts...)
|
err := c.cc.Invoke(ctx, DaemonService_Login_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -75,8 +103,9 @@ func (c *daemonServiceClient) Login(ctx context.Context, in *LoginRequest, opts
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *daemonServiceClient) WaitSSOLogin(ctx context.Context, in *WaitSSOLoginRequest, opts ...grpc.CallOption) (*WaitSSOLoginResponse, error) {
|
func (c *daemonServiceClient) WaitSSOLogin(ctx context.Context, in *WaitSSOLoginRequest, opts ...grpc.CallOption) (*WaitSSOLoginResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(WaitSSOLoginResponse)
|
out := new(WaitSSOLoginResponse)
|
||||||
err := c.cc.Invoke(ctx, "/daemon.DaemonService/WaitSSOLogin", in, out, opts...)
|
err := c.cc.Invoke(ctx, DaemonService_WaitSSOLogin_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -84,8 +113,9 @@ func (c *daemonServiceClient) WaitSSOLogin(ctx context.Context, in *WaitSSOLogin
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *daemonServiceClient) Up(ctx context.Context, in *UpRequest, opts ...grpc.CallOption) (*UpResponse, error) {
|
func (c *daemonServiceClient) Up(ctx context.Context, in *UpRequest, opts ...grpc.CallOption) (*UpResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(UpResponse)
|
out := new(UpResponse)
|
||||||
err := c.cc.Invoke(ctx, "/daemon.DaemonService/Up", in, out, opts...)
|
err := c.cc.Invoke(ctx, DaemonService_Up_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -93,8 +123,9 @@ func (c *daemonServiceClient) Up(ctx context.Context, in *UpRequest, opts ...grp
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *daemonServiceClient) Status(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (*StatusResponse, error) {
|
func (c *daemonServiceClient) Status(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (*StatusResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(StatusResponse)
|
out := new(StatusResponse)
|
||||||
err := c.cc.Invoke(ctx, "/daemon.DaemonService/Status", in, out, opts...)
|
err := c.cc.Invoke(ctx, DaemonService_Status_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -102,8 +133,9 @@ func (c *daemonServiceClient) Status(ctx context.Context, in *StatusRequest, opt
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *daemonServiceClient) Down(ctx context.Context, in *DownRequest, opts ...grpc.CallOption) (*DownResponse, error) {
|
func (c *daemonServiceClient) Down(ctx context.Context, in *DownRequest, opts ...grpc.CallOption) (*DownResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(DownResponse)
|
out := new(DownResponse)
|
||||||
err := c.cc.Invoke(ctx, "/daemon.DaemonService/Down", in, out, opts...)
|
err := c.cc.Invoke(ctx, DaemonService_Down_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -111,8 +143,9 @@ func (c *daemonServiceClient) Down(ctx context.Context, in *DownRequest, opts ..
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *daemonServiceClient) GetConfig(ctx context.Context, in *GetConfigRequest, opts ...grpc.CallOption) (*GetConfigResponse, error) {
|
func (c *daemonServiceClient) GetConfig(ctx context.Context, in *GetConfigRequest, opts ...grpc.CallOption) (*GetConfigResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(GetConfigResponse)
|
out := new(GetConfigResponse)
|
||||||
err := c.cc.Invoke(ctx, "/daemon.DaemonService/GetConfig", in, out, opts...)
|
err := c.cc.Invoke(ctx, DaemonService_GetConfig_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -120,8 +153,9 @@ func (c *daemonServiceClient) GetConfig(ctx context.Context, in *GetConfigReques
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *daemonServiceClient) ListNetworks(ctx context.Context, in *ListNetworksRequest, opts ...grpc.CallOption) (*ListNetworksResponse, error) {
|
func (c *daemonServiceClient) ListNetworks(ctx context.Context, in *ListNetworksRequest, opts ...grpc.CallOption) (*ListNetworksResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(ListNetworksResponse)
|
out := new(ListNetworksResponse)
|
||||||
err := c.cc.Invoke(ctx, "/daemon.DaemonService/ListNetworks", in, out, opts...)
|
err := c.cc.Invoke(ctx, DaemonService_ListNetworks_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -129,8 +163,9 @@ func (c *daemonServiceClient) ListNetworks(ctx context.Context, in *ListNetworks
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *daemonServiceClient) SelectNetworks(ctx context.Context, in *SelectNetworksRequest, opts ...grpc.CallOption) (*SelectNetworksResponse, error) {
|
func (c *daemonServiceClient) SelectNetworks(ctx context.Context, in *SelectNetworksRequest, opts ...grpc.CallOption) (*SelectNetworksResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(SelectNetworksResponse)
|
out := new(SelectNetworksResponse)
|
||||||
err := c.cc.Invoke(ctx, "/daemon.DaemonService/SelectNetworks", in, out, opts...)
|
err := c.cc.Invoke(ctx, DaemonService_SelectNetworks_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -138,8 +173,9 @@ func (c *daemonServiceClient) SelectNetworks(ctx context.Context, in *SelectNetw
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *daemonServiceClient) DeselectNetworks(ctx context.Context, in *SelectNetworksRequest, opts ...grpc.CallOption) (*SelectNetworksResponse, error) {
|
func (c *daemonServiceClient) DeselectNetworks(ctx context.Context, in *SelectNetworksRequest, opts ...grpc.CallOption) (*SelectNetworksResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(SelectNetworksResponse)
|
out := new(SelectNetworksResponse)
|
||||||
err := c.cc.Invoke(ctx, "/daemon.DaemonService/DeselectNetworks", in, out, opts...)
|
err := c.cc.Invoke(ctx, DaemonService_DeselectNetworks_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -147,8 +183,9 @@ func (c *daemonServiceClient) DeselectNetworks(ctx context.Context, in *SelectNe
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *daemonServiceClient) ForwardingRules(ctx context.Context, in *EmptyRequest, opts ...grpc.CallOption) (*ForwardingRulesResponse, error) {
|
func (c *daemonServiceClient) ForwardingRules(ctx context.Context, in *EmptyRequest, opts ...grpc.CallOption) (*ForwardingRulesResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(ForwardingRulesResponse)
|
out := new(ForwardingRulesResponse)
|
||||||
err := c.cc.Invoke(ctx, "/daemon.DaemonService/ForwardingRules", in, out, opts...)
|
err := c.cc.Invoke(ctx, DaemonService_ForwardingRules_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -156,8 +193,9 @@ func (c *daemonServiceClient) ForwardingRules(ctx context.Context, in *EmptyRequ
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *daemonServiceClient) DebugBundle(ctx context.Context, in *DebugBundleRequest, opts ...grpc.CallOption) (*DebugBundleResponse, error) {
|
func (c *daemonServiceClient) DebugBundle(ctx context.Context, in *DebugBundleRequest, opts ...grpc.CallOption) (*DebugBundleResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(DebugBundleResponse)
|
out := new(DebugBundleResponse)
|
||||||
err := c.cc.Invoke(ctx, "/daemon.DaemonService/DebugBundle", in, out, opts...)
|
err := c.cc.Invoke(ctx, DaemonService_DebugBundle_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -165,8 +203,9 @@ func (c *daemonServiceClient) DebugBundle(ctx context.Context, in *DebugBundleRe
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *daemonServiceClient) GetLogLevel(ctx context.Context, in *GetLogLevelRequest, opts ...grpc.CallOption) (*GetLogLevelResponse, error) {
|
func (c *daemonServiceClient) GetLogLevel(ctx context.Context, in *GetLogLevelRequest, opts ...grpc.CallOption) (*GetLogLevelResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(GetLogLevelResponse)
|
out := new(GetLogLevelResponse)
|
||||||
err := c.cc.Invoke(ctx, "/daemon.DaemonService/GetLogLevel", in, out, opts...)
|
err := c.cc.Invoke(ctx, DaemonService_GetLogLevel_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -174,8 +213,9 @@ func (c *daemonServiceClient) GetLogLevel(ctx context.Context, in *GetLogLevelRe
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *daemonServiceClient) SetLogLevel(ctx context.Context, in *SetLogLevelRequest, opts ...grpc.CallOption) (*SetLogLevelResponse, error) {
|
func (c *daemonServiceClient) SetLogLevel(ctx context.Context, in *SetLogLevelRequest, opts ...grpc.CallOption) (*SetLogLevelResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(SetLogLevelResponse)
|
out := new(SetLogLevelResponse)
|
||||||
err := c.cc.Invoke(ctx, "/daemon.DaemonService/SetLogLevel", in, out, opts...)
|
err := c.cc.Invoke(ctx, DaemonService_SetLogLevel_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -183,8 +223,9 @@ func (c *daemonServiceClient) SetLogLevel(ctx context.Context, in *SetLogLevelRe
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *daemonServiceClient) ListStates(ctx context.Context, in *ListStatesRequest, opts ...grpc.CallOption) (*ListStatesResponse, error) {
|
func (c *daemonServiceClient) ListStates(ctx context.Context, in *ListStatesRequest, opts ...grpc.CallOption) (*ListStatesResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(ListStatesResponse)
|
out := new(ListStatesResponse)
|
||||||
err := c.cc.Invoke(ctx, "/daemon.DaemonService/ListStates", in, out, opts...)
|
err := c.cc.Invoke(ctx, DaemonService_ListStates_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -192,8 +233,9 @@ func (c *daemonServiceClient) ListStates(ctx context.Context, in *ListStatesRequ
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *daemonServiceClient) CleanState(ctx context.Context, in *CleanStateRequest, opts ...grpc.CallOption) (*CleanStateResponse, error) {
|
func (c *daemonServiceClient) CleanState(ctx context.Context, in *CleanStateRequest, opts ...grpc.CallOption) (*CleanStateResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(CleanStateResponse)
|
out := new(CleanStateResponse)
|
||||||
err := c.cc.Invoke(ctx, "/daemon.DaemonService/CleanState", in, out, opts...)
|
err := c.cc.Invoke(ctx, DaemonService_CleanState_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -201,8 +243,9 @@ func (c *daemonServiceClient) CleanState(ctx context.Context, in *CleanStateRequ
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *daemonServiceClient) DeleteState(ctx context.Context, in *DeleteStateRequest, opts ...grpc.CallOption) (*DeleteStateResponse, error) {
|
func (c *daemonServiceClient) DeleteState(ctx context.Context, in *DeleteStateRequest, opts ...grpc.CallOption) (*DeleteStateResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(DeleteStateResponse)
|
out := new(DeleteStateResponse)
|
||||||
err := c.cc.Invoke(ctx, "/daemon.DaemonService/DeleteState", in, out, opts...)
|
err := c.cc.Invoke(ctx, DaemonService_DeleteState_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -210,8 +253,9 @@ func (c *daemonServiceClient) DeleteState(ctx context.Context, in *DeleteStateRe
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *daemonServiceClient) SetNetworkMapPersistence(ctx context.Context, in *SetNetworkMapPersistenceRequest, opts ...grpc.CallOption) (*SetNetworkMapPersistenceResponse, error) {
|
func (c *daemonServiceClient) SetNetworkMapPersistence(ctx context.Context, in *SetNetworkMapPersistenceRequest, opts ...grpc.CallOption) (*SetNetworkMapPersistenceResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(SetNetworkMapPersistenceResponse)
|
out := new(SetNetworkMapPersistenceResponse)
|
||||||
err := c.cc.Invoke(ctx, "/daemon.DaemonService/SetNetworkMapPersistence", in, out, opts...)
|
err := c.cc.Invoke(ctx, DaemonService_SetNetworkMapPersistence_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -219,20 +263,22 @@ func (c *daemonServiceClient) SetNetworkMapPersistence(ctx context.Context, in *
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *daemonServiceClient) TracePacket(ctx context.Context, in *TracePacketRequest, opts ...grpc.CallOption) (*TracePacketResponse, error) {
|
func (c *daemonServiceClient) TracePacket(ctx context.Context, in *TracePacketRequest, opts ...grpc.CallOption) (*TracePacketResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(TracePacketResponse)
|
out := new(TracePacketResponse)
|
||||||
err := c.cc.Invoke(ctx, "/daemon.DaemonService/TracePacket", in, out, opts...)
|
err := c.cc.Invoke(ctx, DaemonService_TracePacket_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *daemonServiceClient) SubscribeEvents(ctx context.Context, in *SubscribeRequest, opts ...grpc.CallOption) (DaemonService_SubscribeEventsClient, error) {
|
func (c *daemonServiceClient) SubscribeEvents(ctx context.Context, in *SubscribeRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[SystemEvent], error) {
|
||||||
stream, err := c.cc.NewStream(ctx, &DaemonService_ServiceDesc.Streams[0], "/daemon.DaemonService/SubscribeEvents", opts...)
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
|
stream, err := c.cc.NewStream(ctx, &DaemonService_ServiceDesc.Streams[0], DaemonService_SubscribeEvents_FullMethodName, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
x := &daemonServiceSubscribeEventsClient{stream}
|
x := &grpc.GenericClientStream[SubscribeRequest, SystemEvent]{ClientStream: stream}
|
||||||
if err := x.ClientStream.SendMsg(in); err != nil {
|
if err := x.ClientStream.SendMsg(in); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -242,26 +288,13 @@ func (c *daemonServiceClient) SubscribeEvents(ctx context.Context, in *Subscribe
|
|||||||
return x, nil
|
return x, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type DaemonService_SubscribeEventsClient interface {
|
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||||
Recv() (*SystemEvent, error)
|
type DaemonService_SubscribeEventsClient = grpc.ServerStreamingClient[SystemEvent]
|
||||||
grpc.ClientStream
|
|
||||||
}
|
|
||||||
|
|
||||||
type daemonServiceSubscribeEventsClient struct {
|
|
||||||
grpc.ClientStream
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *daemonServiceSubscribeEventsClient) Recv() (*SystemEvent, error) {
|
|
||||||
m := new(SystemEvent)
|
|
||||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return m, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *daemonServiceClient) GetEvents(ctx context.Context, in *GetEventsRequest, opts ...grpc.CallOption) (*GetEventsResponse, error) {
|
func (c *daemonServiceClient) GetEvents(ctx context.Context, in *GetEventsRequest, opts ...grpc.CallOption) (*GetEventsResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(GetEventsResponse)
|
out := new(GetEventsResponse)
|
||||||
err := c.cc.Invoke(ctx, "/daemon.DaemonService/GetEvents", in, out, opts...)
|
err := c.cc.Invoke(ctx, DaemonService_GetEvents_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -270,7 +303,7 @@ func (c *daemonServiceClient) GetEvents(ctx context.Context, in *GetEventsReques
|
|||||||
|
|
||||||
// DaemonServiceServer is the server API for DaemonService service.
|
// DaemonServiceServer is the server API for DaemonService service.
|
||||||
// All implementations must embed UnimplementedDaemonServiceServer
|
// All implementations must embed UnimplementedDaemonServiceServer
|
||||||
// for forward compatibility
|
// for forward compatibility.
|
||||||
type DaemonServiceServer interface {
|
type DaemonServiceServer interface {
|
||||||
// Login uses setup key to prepare configuration for the daemon.
|
// Login uses setup key to prepare configuration for the daemon.
|
||||||
Login(context.Context, *LoginRequest) (*LoginResponse, error)
|
Login(context.Context, *LoginRequest) (*LoginResponse, error)
|
||||||
@@ -307,14 +340,17 @@ type DaemonServiceServer interface {
|
|||||||
// SetNetworkMapPersistence enables or disables network map persistence
|
// SetNetworkMapPersistence enables or disables network map persistence
|
||||||
SetNetworkMapPersistence(context.Context, *SetNetworkMapPersistenceRequest) (*SetNetworkMapPersistenceResponse, error)
|
SetNetworkMapPersistence(context.Context, *SetNetworkMapPersistenceRequest) (*SetNetworkMapPersistenceResponse, error)
|
||||||
TracePacket(context.Context, *TracePacketRequest) (*TracePacketResponse, error)
|
TracePacket(context.Context, *TracePacketRequest) (*TracePacketResponse, error)
|
||||||
SubscribeEvents(*SubscribeRequest, DaemonService_SubscribeEventsServer) error
|
SubscribeEvents(*SubscribeRequest, grpc.ServerStreamingServer[SystemEvent]) error
|
||||||
GetEvents(context.Context, *GetEventsRequest) (*GetEventsResponse, error)
|
GetEvents(context.Context, *GetEventsRequest) (*GetEventsResponse, error)
|
||||||
mustEmbedUnimplementedDaemonServiceServer()
|
mustEmbedUnimplementedDaemonServiceServer()
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnimplementedDaemonServiceServer must be embedded to have forward compatible implementations.
|
// UnimplementedDaemonServiceServer must be embedded to have
|
||||||
type UnimplementedDaemonServiceServer struct {
|
// forward compatible implementations.
|
||||||
}
|
//
|
||||||
|
// NOTE: this should be embedded by value instead of pointer to avoid a nil
|
||||||
|
// pointer dereference when methods are called.
|
||||||
|
type UnimplementedDaemonServiceServer struct{}
|
||||||
|
|
||||||
func (UnimplementedDaemonServiceServer) Login(context.Context, *LoginRequest) (*LoginResponse, error) {
|
func (UnimplementedDaemonServiceServer) Login(context.Context, *LoginRequest) (*LoginResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method Login not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method Login not implemented")
|
||||||
@@ -370,13 +406,14 @@ func (UnimplementedDaemonServiceServer) SetNetworkMapPersistence(context.Context
|
|||||||
func (UnimplementedDaemonServiceServer) TracePacket(context.Context, *TracePacketRequest) (*TracePacketResponse, error) {
|
func (UnimplementedDaemonServiceServer) TracePacket(context.Context, *TracePacketRequest) (*TracePacketResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method TracePacket not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method TracePacket not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedDaemonServiceServer) SubscribeEvents(*SubscribeRequest, DaemonService_SubscribeEventsServer) error {
|
func (UnimplementedDaemonServiceServer) SubscribeEvents(*SubscribeRequest, grpc.ServerStreamingServer[SystemEvent]) error {
|
||||||
return status.Errorf(codes.Unimplemented, "method SubscribeEvents not implemented")
|
return status.Errorf(codes.Unimplemented, "method SubscribeEvents not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedDaemonServiceServer) GetEvents(context.Context, *GetEventsRequest) (*GetEventsResponse, error) {
|
func (UnimplementedDaemonServiceServer) GetEvents(context.Context, *GetEventsRequest) (*GetEventsResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method GetEvents not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method GetEvents not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedDaemonServiceServer) mustEmbedUnimplementedDaemonServiceServer() {}
|
func (UnimplementedDaemonServiceServer) mustEmbedUnimplementedDaemonServiceServer() {}
|
||||||
|
func (UnimplementedDaemonServiceServer) testEmbeddedByValue() {}
|
||||||
|
|
||||||
// UnsafeDaemonServiceServer may be embedded to opt out of forward compatibility for this service.
|
// UnsafeDaemonServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||||
// Use of this interface is not recommended, as added methods to DaemonServiceServer will
|
// Use of this interface is not recommended, as added methods to DaemonServiceServer will
|
||||||
@@ -386,6 +423,13 @@ type UnsafeDaemonServiceServer interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func RegisterDaemonServiceServer(s grpc.ServiceRegistrar, srv DaemonServiceServer) {
|
func RegisterDaemonServiceServer(s grpc.ServiceRegistrar, srv DaemonServiceServer) {
|
||||||
|
// If the following call pancis, it indicates UnimplementedDaemonServiceServer was
|
||||||
|
// embedded by pointer and is nil. This will cause panics if an
|
||||||
|
// unimplemented method is ever invoked, so we test this at initialization
|
||||||
|
// time to prevent it from happening at runtime later due to I/O.
|
||||||
|
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
|
||||||
|
t.testEmbeddedByValue()
|
||||||
|
}
|
||||||
s.RegisterService(&DaemonService_ServiceDesc, srv)
|
s.RegisterService(&DaemonService_ServiceDesc, srv)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -399,7 +443,7 @@ func _DaemonService_Login_Handler(srv interface{}, ctx context.Context, dec func
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/daemon.DaemonService/Login",
|
FullMethod: DaemonService_Login_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(DaemonServiceServer).Login(ctx, req.(*LoginRequest))
|
return srv.(DaemonServiceServer).Login(ctx, req.(*LoginRequest))
|
||||||
@@ -417,7 +461,7 @@ func _DaemonService_WaitSSOLogin_Handler(srv interface{}, ctx context.Context, d
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/daemon.DaemonService/WaitSSOLogin",
|
FullMethod: DaemonService_WaitSSOLogin_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(DaemonServiceServer).WaitSSOLogin(ctx, req.(*WaitSSOLoginRequest))
|
return srv.(DaemonServiceServer).WaitSSOLogin(ctx, req.(*WaitSSOLoginRequest))
|
||||||
@@ -435,7 +479,7 @@ func _DaemonService_Up_Handler(srv interface{}, ctx context.Context, dec func(in
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/daemon.DaemonService/Up",
|
FullMethod: DaemonService_Up_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(DaemonServiceServer).Up(ctx, req.(*UpRequest))
|
return srv.(DaemonServiceServer).Up(ctx, req.(*UpRequest))
|
||||||
@@ -453,7 +497,7 @@ func _DaemonService_Status_Handler(srv interface{}, ctx context.Context, dec fun
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/daemon.DaemonService/Status",
|
FullMethod: DaemonService_Status_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(DaemonServiceServer).Status(ctx, req.(*StatusRequest))
|
return srv.(DaemonServiceServer).Status(ctx, req.(*StatusRequest))
|
||||||
@@ -471,7 +515,7 @@ func _DaemonService_Down_Handler(srv interface{}, ctx context.Context, dec func(
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/daemon.DaemonService/Down",
|
FullMethod: DaemonService_Down_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(DaemonServiceServer).Down(ctx, req.(*DownRequest))
|
return srv.(DaemonServiceServer).Down(ctx, req.(*DownRequest))
|
||||||
@@ -489,7 +533,7 @@ func _DaemonService_GetConfig_Handler(srv interface{}, ctx context.Context, dec
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/daemon.DaemonService/GetConfig",
|
FullMethod: DaemonService_GetConfig_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(DaemonServiceServer).GetConfig(ctx, req.(*GetConfigRequest))
|
return srv.(DaemonServiceServer).GetConfig(ctx, req.(*GetConfigRequest))
|
||||||
@@ -507,7 +551,7 @@ func _DaemonService_ListNetworks_Handler(srv interface{}, ctx context.Context, d
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/daemon.DaemonService/ListNetworks",
|
FullMethod: DaemonService_ListNetworks_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(DaemonServiceServer).ListNetworks(ctx, req.(*ListNetworksRequest))
|
return srv.(DaemonServiceServer).ListNetworks(ctx, req.(*ListNetworksRequest))
|
||||||
@@ -525,7 +569,7 @@ func _DaemonService_SelectNetworks_Handler(srv interface{}, ctx context.Context,
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/daemon.DaemonService/SelectNetworks",
|
FullMethod: DaemonService_SelectNetworks_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(DaemonServiceServer).SelectNetworks(ctx, req.(*SelectNetworksRequest))
|
return srv.(DaemonServiceServer).SelectNetworks(ctx, req.(*SelectNetworksRequest))
|
||||||
@@ -543,7 +587,7 @@ func _DaemonService_DeselectNetworks_Handler(srv interface{}, ctx context.Contex
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/daemon.DaemonService/DeselectNetworks",
|
FullMethod: DaemonService_DeselectNetworks_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(DaemonServiceServer).DeselectNetworks(ctx, req.(*SelectNetworksRequest))
|
return srv.(DaemonServiceServer).DeselectNetworks(ctx, req.(*SelectNetworksRequest))
|
||||||
@@ -561,7 +605,7 @@ func _DaemonService_ForwardingRules_Handler(srv interface{}, ctx context.Context
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/daemon.DaemonService/ForwardingRules",
|
FullMethod: DaemonService_ForwardingRules_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(DaemonServiceServer).ForwardingRules(ctx, req.(*EmptyRequest))
|
return srv.(DaemonServiceServer).ForwardingRules(ctx, req.(*EmptyRequest))
|
||||||
@@ -579,7 +623,7 @@ func _DaemonService_DebugBundle_Handler(srv interface{}, ctx context.Context, de
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/daemon.DaemonService/DebugBundle",
|
FullMethod: DaemonService_DebugBundle_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(DaemonServiceServer).DebugBundle(ctx, req.(*DebugBundleRequest))
|
return srv.(DaemonServiceServer).DebugBundle(ctx, req.(*DebugBundleRequest))
|
||||||
@@ -597,7 +641,7 @@ func _DaemonService_GetLogLevel_Handler(srv interface{}, ctx context.Context, de
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/daemon.DaemonService/GetLogLevel",
|
FullMethod: DaemonService_GetLogLevel_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(DaemonServiceServer).GetLogLevel(ctx, req.(*GetLogLevelRequest))
|
return srv.(DaemonServiceServer).GetLogLevel(ctx, req.(*GetLogLevelRequest))
|
||||||
@@ -615,7 +659,7 @@ func _DaemonService_SetLogLevel_Handler(srv interface{}, ctx context.Context, de
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/daemon.DaemonService/SetLogLevel",
|
FullMethod: DaemonService_SetLogLevel_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(DaemonServiceServer).SetLogLevel(ctx, req.(*SetLogLevelRequest))
|
return srv.(DaemonServiceServer).SetLogLevel(ctx, req.(*SetLogLevelRequest))
|
||||||
@@ -633,7 +677,7 @@ func _DaemonService_ListStates_Handler(srv interface{}, ctx context.Context, dec
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/daemon.DaemonService/ListStates",
|
FullMethod: DaemonService_ListStates_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(DaemonServiceServer).ListStates(ctx, req.(*ListStatesRequest))
|
return srv.(DaemonServiceServer).ListStates(ctx, req.(*ListStatesRequest))
|
||||||
@@ -651,7 +695,7 @@ func _DaemonService_CleanState_Handler(srv interface{}, ctx context.Context, dec
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/daemon.DaemonService/CleanState",
|
FullMethod: DaemonService_CleanState_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(DaemonServiceServer).CleanState(ctx, req.(*CleanStateRequest))
|
return srv.(DaemonServiceServer).CleanState(ctx, req.(*CleanStateRequest))
|
||||||
@@ -669,7 +713,7 @@ func _DaemonService_DeleteState_Handler(srv interface{}, ctx context.Context, de
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/daemon.DaemonService/DeleteState",
|
FullMethod: DaemonService_DeleteState_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(DaemonServiceServer).DeleteState(ctx, req.(*DeleteStateRequest))
|
return srv.(DaemonServiceServer).DeleteState(ctx, req.(*DeleteStateRequest))
|
||||||
@@ -687,7 +731,7 @@ func _DaemonService_SetNetworkMapPersistence_Handler(srv interface{}, ctx contex
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/daemon.DaemonService/SetNetworkMapPersistence",
|
FullMethod: DaemonService_SetNetworkMapPersistence_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(DaemonServiceServer).SetNetworkMapPersistence(ctx, req.(*SetNetworkMapPersistenceRequest))
|
return srv.(DaemonServiceServer).SetNetworkMapPersistence(ctx, req.(*SetNetworkMapPersistenceRequest))
|
||||||
@@ -705,7 +749,7 @@ func _DaemonService_TracePacket_Handler(srv interface{}, ctx context.Context, de
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/daemon.DaemonService/TracePacket",
|
FullMethod: DaemonService_TracePacket_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(DaemonServiceServer).TracePacket(ctx, req.(*TracePacketRequest))
|
return srv.(DaemonServiceServer).TracePacket(ctx, req.(*TracePacketRequest))
|
||||||
@@ -718,21 +762,11 @@ func _DaemonService_SubscribeEvents_Handler(srv interface{}, stream grpc.ServerS
|
|||||||
if err := stream.RecvMsg(m); err != nil {
|
if err := stream.RecvMsg(m); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return srv.(DaemonServiceServer).SubscribeEvents(m, &daemonServiceSubscribeEventsServer{stream})
|
return srv.(DaemonServiceServer).SubscribeEvents(m, &grpc.GenericServerStream[SubscribeRequest, SystemEvent]{ServerStream: stream})
|
||||||
}
|
}
|
||||||
|
|
||||||
type DaemonService_SubscribeEventsServer interface {
|
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||||
Send(*SystemEvent) error
|
type DaemonService_SubscribeEventsServer = grpc.ServerStreamingServer[SystemEvent]
|
||||||
grpc.ServerStream
|
|
||||||
}
|
|
||||||
|
|
||||||
type daemonServiceSubscribeEventsServer struct {
|
|
||||||
grpc.ServerStream
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *daemonServiceSubscribeEventsServer) Send(m *SystemEvent) error {
|
|
||||||
return x.ServerStream.SendMsg(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
func _DaemonService_GetEvents_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
func _DaemonService_GetEvents_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
in := new(GetEventsRequest)
|
in := new(GetEventsRequest)
|
||||||
@@ -744,7 +778,7 @@ func _DaemonService_GetEvents_Handler(srv interface{}, ctx context.Context, dec
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/daemon.DaemonService/GetEvents",
|
FullMethod: DaemonService_GetEvents_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(DaemonServiceServer).GetEvents(ctx, req.(*GetEventsRequest))
|
return srv.(DaemonServiceServer).GetEvents(ctx, req.(*GetEventsRequest))
|
||||||
|
|||||||
@@ -707,7 +707,9 @@ func (s *Server) Status(
|
|||||||
s.statusRecorder.UpdateRosenpass(s.config.RosenpassEnabled, s.config.RosenpassPermissive)
|
s.statusRecorder.UpdateRosenpass(s.config.RosenpassEnabled, s.config.RosenpassPermissive)
|
||||||
|
|
||||||
if msg.GetFullPeerStatus {
|
if msg.GetFullPeerStatus {
|
||||||
s.runProbes()
|
if msg.ShouldRunProbes {
|
||||||
|
s.runProbes()
|
||||||
|
}
|
||||||
|
|
||||||
fullStatus := s.statusRecorder.GetFullStatus()
|
fullStatus := s.statusRecorder.GetFullStatus()
|
||||||
pbFullStatus := toProtoFullStatus(fullStatus)
|
pbFullStatus := toProtoFullStatus(fullStatus)
|
||||||
|
|||||||
@@ -206,7 +206,7 @@ func startManagement(t *testing.T, signalAddr string, counter *int) (*grpc.Serve
|
|||||||
settingsMockManager := settings.NewMockManager(ctrl)
|
settingsMockManager := settings.NewMockManager(ctrl)
|
||||||
permissionsManagerMock := permissions.NewMockManager(ctrl)
|
permissionsManagerMock := permissions.NewMockManager(ctrl)
|
||||||
|
|
||||||
accountManager, err := server.BuildManager(context.Background(), store, peersUpdateManager, nil, "", "netbird.selfhosted", eventStore, nil, false, ia, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManagerMock)
|
accountManager, err := server.BuildManager(context.Background(), store, peersUpdateManager, nil, "", "netbird.selfhosted", eventStore, nil, false, ia, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManagerMock, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
|
|||||||
+30
-18
@@ -280,7 +280,7 @@ func newServiceClient(addr string, logFile string, a fyne.App, showSettings bool
|
|||||||
|
|
||||||
showAdvancedSettings: showSettings,
|
showAdvancedSettings: showSettings,
|
||||||
showNetworks: showNetworks,
|
showNetworks: showNetworks,
|
||||||
update: version.NewUpdate(),
|
update: version.NewUpdate("nb/client-ui"),
|
||||||
}
|
}
|
||||||
|
|
||||||
s.eventHandler = newEventHandler(s)
|
s.eventHandler = newEventHandler(s)
|
||||||
@@ -879,7 +879,7 @@ func (s *serviceClient) onUpdateAvailable() {
|
|||||||
func (s *serviceClient) onSessionExpire() {
|
func (s *serviceClient) onSessionExpire() {
|
||||||
s.sendNotification = true
|
s.sendNotification = true
|
||||||
if s.sendNotification {
|
if s.sendNotification {
|
||||||
s.eventHandler.runSelfCommand("login-url", "true")
|
go s.eventHandler.runSelfCommand(s.ctx, "login-url", "true")
|
||||||
s.sendNotification = false
|
s.sendNotification = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -992,21 +992,6 @@ func (s *serviceClient) restartClient(loginRequest *proto.LoginRequest) error {
|
|||||||
// showLoginURL creates a borderless window styled like a pop-up in the top-right corner using s.wLoginURL.
|
// showLoginURL creates a borderless window styled like a pop-up in the top-right corner using s.wLoginURL.
|
||||||
func (s *serviceClient) showLoginURL() {
|
func (s *serviceClient) showLoginURL() {
|
||||||
|
|
||||||
resp, err := s.login(false)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("failed to fetch login URL: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
verificationURL := resp.VerificationURIComplete
|
|
||||||
if verificationURL == "" {
|
|
||||||
verificationURL = resp.VerificationURI
|
|
||||||
}
|
|
||||||
|
|
||||||
if verificationURL == "" {
|
|
||||||
log.Error("no verification URL provided in the login response")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
resIcon := fyne.NewStaticResource("netbird.png", iconAbout)
|
resIcon := fyne.NewStaticResource("netbird.png", iconAbout)
|
||||||
|
|
||||||
if s.wLoginURL == nil {
|
if s.wLoginURL == nil {
|
||||||
@@ -1025,6 +1010,21 @@ func (s *serviceClient) showLoginURL() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resp, err := s.login(false)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("failed to fetch login URL: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
verificationURL := resp.VerificationURIComplete
|
||||||
|
if verificationURL == "" {
|
||||||
|
verificationURL = resp.VerificationURI
|
||||||
|
}
|
||||||
|
|
||||||
|
if verificationURL == "" {
|
||||||
|
log.Error("no verification URL provided in the login response")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if err := openURL(verificationURL); err != nil {
|
if err := openURL(verificationURL); err != nil {
|
||||||
log.Errorf("failed to open login URL: %v", err)
|
log.Errorf("failed to open login URL: %v", err)
|
||||||
return
|
return
|
||||||
@@ -1038,7 +1038,19 @@ func (s *serviceClient) showLoginURL() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
label.SetText("Re-authentication successful.\nReconnecting")
|
label.SetText("Re-authentication successful.\nReconnecting")
|
||||||
time.Sleep(300 * time.Millisecond)
|
status, err := conn.Status(s.ctx, &proto.StatusRequest{})
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("get service status: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if status.Status == string(internal.StatusConnected) {
|
||||||
|
label.SetText("Already connected.\nClosing this window.")
|
||||||
|
time.Sleep(2 * time.Second)
|
||||||
|
s.wLoginURL.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
_, err = conn.Up(s.ctx, &proto.UpRequest{})
|
_, err = conn.Up(s.ctx, &proto.UpRequest{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
label.SetText("Reconnecting failed, please create \na debug bundle in the settings and contact support.")
|
label.SetText("Reconnecting failed, please create \na debug bundle in the settings and contact support.")
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ func (h *eventHandler) handleAdvancedSettingsClick() {
|
|||||||
go func() {
|
go func() {
|
||||||
defer h.client.mAdvancedSettings.Enable()
|
defer h.client.mAdvancedSettings.Enable()
|
||||||
defer h.client.getSrvConfig()
|
defer h.client.getSrvConfig()
|
||||||
h.runSelfCommand("settings", "true")
|
h.runSelfCommand(h.client.ctx, "settings", "true")
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,7 +130,7 @@ func (h *eventHandler) handleCreateDebugBundleClick() {
|
|||||||
h.client.mCreateDebugBundle.Disable()
|
h.client.mCreateDebugBundle.Disable()
|
||||||
go func() {
|
go func() {
|
||||||
defer h.client.mCreateDebugBundle.Enable()
|
defer h.client.mCreateDebugBundle.Enable()
|
||||||
h.runSelfCommand("debug", "true")
|
h.runSelfCommand(h.client.ctx, "debug", "true")
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,7 +154,7 @@ func (h *eventHandler) handleNetworksClick() {
|
|||||||
h.client.mNetworks.Disable()
|
h.client.mNetworks.Disable()
|
||||||
go func() {
|
go func() {
|
||||||
defer h.client.mNetworks.Enable()
|
defer h.client.mNetworks.Enable()
|
||||||
h.runSelfCommand("networks", "true")
|
h.runSelfCommand(h.client.ctx, "networks", "true")
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,14 +172,14 @@ func (h *eventHandler) updateConfigWithErr() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *eventHandler) runSelfCommand(command, arg string) {
|
func (h *eventHandler) runSelfCommand(ctx context.Context, command, arg string) {
|
||||||
proc, err := os.Executable()
|
proc, err := os.Executable()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("error getting executable path: %v", err)
|
log.Errorf("error getting executable path: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := exec.Command(proc,
|
cmd := exec.CommandContext(ctx, proc,
|
||||||
fmt.Sprintf("--%s=%s", command, arg),
|
fmt.Sprintf("--%s=%s", command, arg),
|
||||||
fmt.Sprintf("--daemon-addr=%s", h.client.addr),
|
fmt.Sprintf("--daemon-addr=%s", h.client.addr),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ NETBIRD_MGMT_API_CERT_KEY_FILE="/etc/letsencrypt/live/$NETBIRD_LETSENCRYPT_DOMAI
|
|||||||
NETBIRD_MGMT_SINGLE_ACCOUNT_MODE_DOMAIN=$NETBIRD_DOMAIN
|
NETBIRD_MGMT_SINGLE_ACCOUNT_MODE_DOMAIN=$NETBIRD_DOMAIN
|
||||||
NETBIRD_MGMT_DNS_DOMAIN=${NETBIRD_MGMT_DNS_DOMAIN:-netbird.selfhosted}
|
NETBIRD_MGMT_DNS_DOMAIN=${NETBIRD_MGMT_DNS_DOMAIN:-netbird.selfhosted}
|
||||||
NETBIRD_MGMT_IDP_SIGNKEY_REFRESH=${NETBIRD_MGMT_IDP_SIGNKEY_REFRESH:-false}
|
NETBIRD_MGMT_IDP_SIGNKEY_REFRESH=${NETBIRD_MGMT_IDP_SIGNKEY_REFRESH:-false}
|
||||||
|
NETBIRD_MGMT_DISABLE_DEFAULT_POLICY=${NETBIRD_MGMT_DISABLE_DEFAULT_POLICY:-false}
|
||||||
|
|
||||||
# Signal
|
# Signal
|
||||||
NETBIRD_SIGNAL_PROTOCOL="http"
|
NETBIRD_SIGNAL_PROTOCOL="http"
|
||||||
@@ -60,7 +61,7 @@ NETBIRD_TOKEN_SOURCE=${NETBIRD_TOKEN_SOURCE:-accessToken}
|
|||||||
NETBIRD_AUTH_PKCE_REDIRECT_URL_PORTS=${NETBIRD_AUTH_PKCE_REDIRECT_URL_PORTS:-"53000"}
|
NETBIRD_AUTH_PKCE_REDIRECT_URL_PORTS=${NETBIRD_AUTH_PKCE_REDIRECT_URL_PORTS:-"53000"}
|
||||||
NETBIRD_AUTH_PKCE_USE_ID_TOKEN=${NETBIRD_AUTH_PKCE_USE_ID_TOKEN:-false}
|
NETBIRD_AUTH_PKCE_USE_ID_TOKEN=${NETBIRD_AUTH_PKCE_USE_ID_TOKEN:-false}
|
||||||
NETBIRD_AUTH_PKCE_DISABLE_PROMPT_LOGIN=${NETBIRD_AUTH_PKCE_DISABLE_PROMPT_LOGIN:-false}
|
NETBIRD_AUTH_PKCE_DISABLE_PROMPT_LOGIN=${NETBIRD_AUTH_PKCE_DISABLE_PROMPT_LOGIN:-false}
|
||||||
NETBIRD_AUTH_PKCE_LOGIN_FLAG=${NETBIRD_AUTH_PKCE_LOGIN_FLAG:-1}
|
NETBIRD_AUTH_PKCE_LOGIN_FLAG=${NETBIRD_AUTH_PKCE_LOGIN_FLAG:-0}
|
||||||
NETBIRD_AUTH_PKCE_AUDIENCE=$NETBIRD_AUTH_AUDIENCE
|
NETBIRD_AUTH_PKCE_AUDIENCE=$NETBIRD_AUTH_AUDIENCE
|
||||||
|
|
||||||
# Dashboard
|
# Dashboard
|
||||||
@@ -139,3 +140,4 @@ export NETBIRD_RELAY_PORT
|
|||||||
export NETBIRD_RELAY_ENDPOINT
|
export NETBIRD_RELAY_ENDPOINT
|
||||||
export NETBIRD_RELAY_AUTH_SECRET
|
export NETBIRD_RELAY_AUTH_SECRET
|
||||||
export NETBIRD_RELAY_TAG
|
export NETBIRD_RELAY_TAG
|
||||||
|
export NETBIRD_MGMT_DISABLE_DEFAULT_POLICY
|
||||||
|
|||||||
@@ -791,7 +791,6 @@ services:
|
|||||||
- '443:443'
|
- '443:443'
|
||||||
- '443:443/udp'
|
- '443:443/udp'
|
||||||
- '80:80'
|
- '80:80'
|
||||||
- '8080:8080'
|
|
||||||
volumes:
|
volumes:
|
||||||
- netbird_caddy_data:/data
|
- netbird_caddy_data:/data
|
||||||
- ./Caddyfile:/etc/caddy/Caddyfile
|
- ./Caddyfile:/etc/caddy/Caddyfile
|
||||||
|
|||||||
@@ -38,6 +38,7 @@
|
|||||||
"0.0.0.0/0"
|
"0.0.0.0/0"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"DisableDefaultPolicy": $NETBIRD_MGMT_DISABLE_DEFAULT_POLICY,
|
||||||
"Datadir": "",
|
"Datadir": "",
|
||||||
"DataStoreEncryptionKey": "$NETBIRD_DATASTORE_ENC_KEY",
|
"DataStoreEncryptionKey": "$NETBIRD_DATASTORE_ENC_KEY",
|
||||||
"StoreConfig": {
|
"StoreConfig": {
|
||||||
|
|||||||
@@ -92,7 +92,8 @@ NETBIRD_LETSENCRYPT_EMAIL=""
|
|||||||
NETBIRD_DISABLE_ANONYMOUS_METRICS=false
|
NETBIRD_DISABLE_ANONYMOUS_METRICS=false
|
||||||
# DNS DOMAIN configures the domain name used for peer resolution. By default it is netbird.selfhosted
|
# DNS DOMAIN configures the domain name used for peer resolution. By default it is netbird.selfhosted
|
||||||
NETBIRD_MGMT_DNS_DOMAIN=netbird.selfhosted
|
NETBIRD_MGMT_DNS_DOMAIN=netbird.selfhosted
|
||||||
|
# Disable default all-to-all policy for new accounts
|
||||||
|
NETBIRD_MGMT_DISABLE_DEFAULT_POLICY=false
|
||||||
# -------------------------------------------
|
# -------------------------------------------
|
||||||
# Relay settings
|
# Relay settings
|
||||||
# -------------------------------------------
|
# -------------------------------------------
|
||||||
|
|||||||
@@ -29,3 +29,4 @@ NETBIRD_TURN_EXTERNAL_IP=1.2.3.4
|
|||||||
NETBIRD_RELAY_PORT=33445
|
NETBIRD_RELAY_PORT=33445
|
||||||
NETBIRD_AUTH_PKCE_DISABLE_PROMPT_LOGIN=true
|
NETBIRD_AUTH_PKCE_DISABLE_PROMPT_LOGIN=true
|
||||||
NETBIRD_AUTH_PKCE_LOGIN_FLAG=0
|
NETBIRD_AUTH_PKCE_LOGIN_FLAG=0
|
||||||
|
NETBIRD_MGMT_DISABLE_DEFAULT_POLICY=$CI_NETBIRD_MGMT_DISABLE_DEFAULT_POLICY
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ func startManagement(t *testing.T) (*grpc.Server, net.Listener) {
|
|||||||
Return(true, nil).
|
Return(true, nil).
|
||||||
AnyTimes()
|
AnyTimes()
|
||||||
|
|
||||||
accountManager, err := mgmt.BuildManager(context.Background(), store, peersUpdateManager, nil, "", "netbird.selfhosted", eventStore, nil, false, ia, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManagerMock)
|
accountManager, err := mgmt.BuildManager(context.Background(), store, peersUpdateManager, nil, "", "netbird.selfhosted", eventStore, nil, false, ia, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManagerMock, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -215,7 +215,7 @@ var (
|
|||||||
peersManager := peers.NewManager(store, permissionsManager)
|
peersManager := peers.NewManager(store, permissionsManager)
|
||||||
proxyController := integrations.NewController(store)
|
proxyController := integrations.NewController(store)
|
||||||
accountManager, err := server.BuildManager(ctx, store, peersUpdateManager, idpManager, mgmtSingleAccModeDomain,
|
accountManager, err := server.BuildManager(ctx, store, peersUpdateManager, idpManager, mgmtSingleAccModeDomain,
|
||||||
dnsDomain, eventStore, geo, userDeleteFromIDPEnabled, integratedPeerValidator, appMetrics, proxyController, settingsManager, permissionsManager)
|
dnsDomain, eventStore, geo, userDeleteFromIDPEnabled, integratedPeerValidator, appMetrics, proxyController, settingsManager, permissionsManager, config.DisableDefaultPolicy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to build default manager: %v", err)
|
return fmt.Errorf("failed to build default manager: %v", err)
|
||||||
}
|
}
|
||||||
@@ -357,6 +357,13 @@ var (
|
|||||||
log.WithContext(ctx).Infof("running HTTP server and gRPC server on the same port: %s", listener.Addr().String())
|
log.WithContext(ctx).Infof("running HTTP server and gRPC server on the same port: %s", listener.Addr().String())
|
||||||
serveGRPCWithHTTP(ctx, listener, rootHandler, tlsEnabled)
|
serveGRPCWithHTTP(ctx, listener, rootHandler, tlsEnabled)
|
||||||
|
|
||||||
|
update := version.NewUpdate("nb/management")
|
||||||
|
update.SetDaemonVersion(version.NetbirdVersion())
|
||||||
|
update.SetOnUpdateListener(func() {
|
||||||
|
log.WithContext(ctx).Infof("your management version, \"%s\", is outdated, a new management version is available. Learn more here: https://github.com/netbirdio/netbird/releases", version.NetbirdVersion())
|
||||||
|
})
|
||||||
|
defer update.StopWatch()
|
||||||
|
|
||||||
SetupCloseHandler()
|
SetupCloseHandler()
|
||||||
|
|
||||||
<-stopCh
|
<-stopCh
|
||||||
|
|||||||
@@ -102,6 +102,8 @@ type DefaultAccountManager struct {
|
|||||||
|
|
||||||
accountUpdateLocks sync.Map
|
accountUpdateLocks sync.Map
|
||||||
updateAccountPeersBufferInterval atomic.Int64
|
updateAccountPeersBufferInterval atomic.Int64
|
||||||
|
|
||||||
|
disableDefaultPolicy bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// getJWTGroupsChanges calculates the changes needed to sync a user's JWT groups.
|
// getJWTGroupsChanges calculates the changes needed to sync a user's JWT groups.
|
||||||
@@ -170,6 +172,7 @@ func BuildManager(
|
|||||||
proxyController port_forwarding.Controller,
|
proxyController port_forwarding.Controller,
|
||||||
settingsManager settings.Manager,
|
settingsManager settings.Manager,
|
||||||
permissionsManager permissions.Manager,
|
permissionsManager permissions.Manager,
|
||||||
|
disableDefaultPolicy bool,
|
||||||
) (*DefaultAccountManager, error) {
|
) (*DefaultAccountManager, error) {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
defer func() {
|
defer func() {
|
||||||
@@ -195,6 +198,7 @@ func BuildManager(
|
|||||||
proxyController: proxyController,
|
proxyController: proxyController,
|
||||||
settingsManager: settingsManager,
|
settingsManager: settingsManager,
|
||||||
permissionsManager: permissionsManager,
|
permissionsManager: permissionsManager,
|
||||||
|
disableDefaultPolicy: disableDefaultPolicy,
|
||||||
}
|
}
|
||||||
|
|
||||||
am.startWarmup(ctx)
|
am.startWarmup(ctx)
|
||||||
@@ -543,7 +547,7 @@ func (am *DefaultAccountManager) newAccount(ctx context.Context, userID, domain
|
|||||||
log.WithContext(ctx).Warnf("an account with ID already exists, retrying...")
|
log.WithContext(ctx).Warnf("an account with ID already exists, retrying...")
|
||||||
continue
|
continue
|
||||||
case statusErr.Type() == status.NotFound:
|
case statusErr.Type() == status.NotFound:
|
||||||
newAccount := newAccountWithId(ctx, accountId, userID, domain)
|
newAccount := newAccountWithId(ctx, accountId, userID, domain, am.disableDefaultPolicy)
|
||||||
am.StoreEvent(ctx, userID, newAccount.Id, accountId, activity.AccountCreated, nil)
|
am.StoreEvent(ctx, userID, newAccount.Id, accountId, activity.AccountCreated, nil)
|
||||||
return newAccount, nil
|
return newAccount, nil
|
||||||
default:
|
default:
|
||||||
@@ -1688,7 +1692,7 @@ func (am *DefaultAccountManager) GetAccountSettings(ctx context.Context, account
|
|||||||
}
|
}
|
||||||
|
|
||||||
// newAccountWithId creates a new Account with a default SetupKey (doesn't store in a Store) and provided id
|
// newAccountWithId creates a new Account with a default SetupKey (doesn't store in a Store) and provided id
|
||||||
func newAccountWithId(ctx context.Context, accountID, userID, domain string) *types.Account {
|
func newAccountWithId(ctx context.Context, accountID, userID, domain string, disableDefaultPolicy bool) *types.Account {
|
||||||
log.WithContext(ctx).Debugf("creating new account")
|
log.WithContext(ctx).Debugf("creating new account")
|
||||||
|
|
||||||
network := types.NewNetwork()
|
network := types.NewNetwork()
|
||||||
@@ -1731,7 +1735,7 @@ func newAccountWithId(ctx context.Context, accountID, userID, domain string) *ty
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := acc.AddAllGroup(); err != nil {
|
if err := acc.AddAllGroup(disableDefaultPolicy); err != nil {
|
||||||
log.WithContext(ctx).Errorf("error adding all group to account %s: %v", acc.Id, err)
|
log.WithContext(ctx).Errorf("error adding all group to account %s: %v", acc.Id, err)
|
||||||
}
|
}
|
||||||
return acc
|
return acc
|
||||||
@@ -1833,7 +1837,7 @@ func (am *DefaultAccountManager) GetOrCreateAccountByPrivateDomain(ctx context.C
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := newAccount.AddAllGroup(); err != nil {
|
if err := newAccount.AddAllGroup(am.disableDefaultPolicy); err != nil {
|
||||||
return nil, false, status.Errorf(status.Internal, "failed to add all group to new account by private domain")
|
return nil, false, status.Errorf(status.Internal, "failed to add all group to new account by private domain")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1853,40 +1857,49 @@ func (am *DefaultAccountManager) GetOrCreateAccountByPrivateDomain(ctx context.C
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (am *DefaultAccountManager) UpdateToPrimaryAccount(ctx context.Context, accountId string) (*types.Account, error) {
|
func (am *DefaultAccountManager) UpdateToPrimaryAccount(ctx context.Context, accountId string) (*types.Account, error) {
|
||||||
account, err := am.Store.GetAccount(ctx, accountId)
|
var account *types.Account
|
||||||
|
err := am.Store.ExecuteInTransaction(ctx, func(transaction store.Store) error {
|
||||||
|
var err error
|
||||||
|
account, err = transaction.GetAccount(ctx, accountId)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if account.IsDomainPrimaryAccount {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
existingPrimaryAccountID, err := transaction.GetAccountIDByPrivateDomain(ctx, store.LockingStrengthShare, account.Domain)
|
||||||
|
|
||||||
|
// error is not a not found error
|
||||||
|
if handleNotFound(err) != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// a primary account already exists for this private domain
|
||||||
|
if err == nil {
|
||||||
|
log.WithContext(ctx).WithFields(log.Fields{
|
||||||
|
"accountId": accountId,
|
||||||
|
"existingAccountId": existingPrimaryAccountID,
|
||||||
|
}).Errorf("cannot update account to primary, another account already exists as primary for the same domain")
|
||||||
|
return status.Errorf(status.Internal, "cannot update account to primary")
|
||||||
|
}
|
||||||
|
|
||||||
|
account.IsDomainPrimaryAccount = true
|
||||||
|
|
||||||
|
if err := transaction.SaveAccount(ctx, account); err != nil {
|
||||||
|
log.WithContext(ctx).WithFields(log.Fields{
|
||||||
|
"accountId": accountId,
|
||||||
|
}).Errorf("failed to update account to primary: %v", err)
|
||||||
|
return status.Errorf(status.Internal, "failed to update account to primary")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if account.IsDomainPrimaryAccount {
|
|
||||||
return account, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
existingPrimaryAccountID, err := am.Store.GetAccountIDByPrivateDomain(ctx, store.LockingStrengthShare, account.Domain)
|
|
||||||
|
|
||||||
// error is not a not found error
|
|
||||||
if handleNotFound(err) != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// a primary account already exists for this private domain
|
|
||||||
if err == nil {
|
|
||||||
log.WithContext(ctx).WithFields(log.Fields{
|
|
||||||
"accountId": accountId,
|
|
||||||
"existingAccountId": existingPrimaryAccountID,
|
|
||||||
}).Errorf("cannot update account to primary, another account already exists as primary for the same domain")
|
|
||||||
return nil, status.Errorf(status.Internal, "cannot update account to primary")
|
|
||||||
}
|
|
||||||
|
|
||||||
account.IsDomainPrimaryAccount = true
|
|
||||||
|
|
||||||
if err := am.Store.SaveAccount(ctx, account); err != nil {
|
|
||||||
log.WithContext(ctx).WithFields(log.Fields{
|
|
||||||
"accountId": accountId,
|
|
||||||
}).Errorf("failed to update account to primary: %v", err)
|
|
||||||
return nil, status.Errorf(status.Internal, "failed to update account to primary")
|
|
||||||
}
|
|
||||||
|
|
||||||
return account, nil
|
return account, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -373,7 +373,7 @@ func TestAccount_GetPeerNetworkMap(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, testCase := range tt {
|
for _, testCase := range tt {
|
||||||
account := newAccountWithId(context.Background(), "account-1", userID, "netbird.io")
|
account := newAccountWithId(context.Background(), "account-1", userID, "netbird.io", false)
|
||||||
account.UpdateSettings(&testCase.accountSettings)
|
account.UpdateSettings(&testCase.accountSettings)
|
||||||
account.Network = network
|
account.Network = network
|
||||||
account.Peers = testCase.peers
|
account.Peers = testCase.peers
|
||||||
@@ -398,7 +398,7 @@ func TestNewAccount(t *testing.T) {
|
|||||||
domain := "netbird.io"
|
domain := "netbird.io"
|
||||||
userId := "account_creator"
|
userId := "account_creator"
|
||||||
accountID := "account_id"
|
accountID := "account_id"
|
||||||
account := newAccountWithId(context.Background(), accountID, userId, domain)
|
account := newAccountWithId(context.Background(), accountID, userId, domain, false)
|
||||||
verifyNewAccountHasDefaultFields(t, account, userId, domain, []string{userId})
|
verifyNewAccountHasDefaultFields(t, account, userId, domain, []string{userId})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -640,7 +640,7 @@ func TestDefaultAccountManager_GetAccountIDFromToken(t *testing.T) {
|
|||||||
func TestDefaultAccountManager_SyncUserJWTGroups(t *testing.T) {
|
func TestDefaultAccountManager_SyncUserJWTGroups(t *testing.T) {
|
||||||
userId := "user-id"
|
userId := "user-id"
|
||||||
domain := "test.domain"
|
domain := "test.domain"
|
||||||
_ = newAccountWithId(context.Background(), "", userId, domain)
|
_ = newAccountWithId(context.Background(), "", userId, domain, false)
|
||||||
manager, err := createManager(t)
|
manager, err := createManager(t)
|
||||||
require.NoError(t, err, "unable to create account manager")
|
require.NoError(t, err, "unable to create account manager")
|
||||||
accountID, err := manager.GetAccountIDByUserID(context.Background(), userId, domain)
|
accountID, err := manager.GetAccountIDByUserID(context.Background(), userId, domain)
|
||||||
@@ -793,7 +793,7 @@ func TestAccountManager_GetAccountByUserID(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func createAccount(am *DefaultAccountManager, accountID, userID, domain string) (*types.Account, error) {
|
func createAccount(am *DefaultAccountManager, accountID, userID, domain string) (*types.Account, error) {
|
||||||
account := newAccountWithId(context.Background(), accountID, userID, domain)
|
account := newAccountWithId(context.Background(), accountID, userID, domain, false)
|
||||||
err := am.Store.SaveAccount(context.Background(), account)
|
err := am.Store.SaveAccount(context.Background(), account)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -1208,6 +1208,14 @@ func TestAccountManager_NetworkUpdates_DeletePolicy(t *testing.T) {
|
|||||||
updMsg := manager.peersUpdateManager.CreateChannel(context.Background(), peer1.ID)
|
updMsg := manager.peersUpdateManager.CreateChannel(context.Background(), peer1.ID)
|
||||||
defer manager.peersUpdateManager.CloseChannel(context.Background(), peer1.ID)
|
defer manager.peersUpdateManager.CloseChannel(context.Background(), peer1.ID)
|
||||||
|
|
||||||
|
// Ensure that we do not receive an update message before the policy is deleted
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
select {
|
||||||
|
case <-updMsg:
|
||||||
|
t.Logf("received addPeer update message before policy deletion")
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
wg := sync.WaitGroup{}
|
wg := sync.WaitGroup{}
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
@@ -2879,7 +2887,7 @@ func createManager(t testing.TB) (*DefaultAccountManager, error) {
|
|||||||
|
|
||||||
permissionsManager := permissions.NewManager(store)
|
permissionsManager := permissions.NewManager(store)
|
||||||
|
|
||||||
manager, err := BuildManager(context.Background(), store, NewPeersUpdateManager(nil), nil, "", "netbird.cloud", eventStore, nil, false, MocIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager)
|
manager, err := BuildManager(context.Background(), store, NewPeersUpdateManager(nil), nil, "", "netbird.cloud", eventStore, nil, false, MocIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -217,7 +217,7 @@ func createDNSManager(t *testing.T) (*DefaultAccountManager, error) {
|
|||||||
|
|
||||||
settingsMockManager := settings.NewMockManager(ctrl)
|
settingsMockManager := settings.NewMockManager(ctrl)
|
||||||
permissionsManager := permissions.NewManager(store)
|
permissionsManager := permissions.NewManager(store)
|
||||||
return BuildManager(context.Background(), store, NewPeersUpdateManager(nil), nil, "", "netbird.test", eventStore, nil, false, MocIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager)
|
return BuildManager(context.Background(), store, NewPeersUpdateManager(nil), nil, "", "netbird.test", eventStore, nil, false, MocIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func createDNSStore(t *testing.T) (store.Store, error) {
|
func createDNSStore(t *testing.T) (store.Store, error) {
|
||||||
@@ -267,7 +267,7 @@ func initTestDNSAccount(t *testing.T, am *DefaultAccountManager) (*types.Account
|
|||||||
|
|
||||||
domain := "example.com"
|
domain := "example.com"
|
||||||
|
|
||||||
account := newAccountWithId(context.Background(), dnsAccountID, dnsAdminUserID, domain)
|
account := newAccountWithId(context.Background(), dnsAccountID, dnsAdminUserID, domain, false)
|
||||||
|
|
||||||
account.Users[dnsRegularUserID] = &types.User{
|
account.Users[dnsRegularUserID] = &types.User{
|
||||||
Id: dnsRegularUserID,
|
Id: dnsRegularUserID,
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ func TestNewManagerPeerDisconnected(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func seedPeers(store *MockStore, numberOfPeers int, numberOfEphemeralPeers int) {
|
func seedPeers(store *MockStore, numberOfPeers int, numberOfEphemeralPeers int) {
|
||||||
store.account = newAccountWithId(context.Background(), "my account", "", "")
|
store.account = newAccountWithId(context.Background(), "my account", "", "", false)
|
||||||
|
|
||||||
for i := 0; i < numberOfPeers; i++ {
|
for i := 0; i < numberOfPeers; i++ {
|
||||||
peerId := fmt.Sprintf("peer_%d", i)
|
peerId := fmt.Sprintf("peer_%d", i)
|
||||||
|
|||||||
@@ -369,7 +369,7 @@ func initTestGroupAccount(am *DefaultAccountManager) (*DefaultAccountManager, *t
|
|||||||
Id: "example user",
|
Id: "example user",
|
||||||
AutoGroups: []string{groupForUsers.ID},
|
AutoGroups: []string{groupForUsers.ID},
|
||||||
}
|
}
|
||||||
account := newAccountWithId(context.Background(), accountID, groupAdminUserID, domain)
|
account := newAccountWithId(context.Background(), accountID, groupAdminUserID, domain, false)
|
||||||
account.Routes[routeResource.ID] = routeResource
|
account.Routes[routeResource.ID] = routeResource
|
||||||
account.Routes[routePeerGroupResource.ID] = routePeerGroupResource
|
account.Routes[routePeerGroupResource.ID] = routePeerGroupResource
|
||||||
account.NameServerGroups[nameServerGroup.ID] = nameServerGroup
|
account.NameServerGroups[nameServerGroup.ID] = nameServerGroup
|
||||||
|
|||||||
@@ -426,6 +426,10 @@ components:
|
|||||||
items:
|
items:
|
||||||
type: string
|
type: string
|
||||||
example: "stage-host-1"
|
example: "stage-host-1"
|
||||||
|
ephemeral:
|
||||||
|
description: Indicates whether the peer is ephemeral or not
|
||||||
|
type: boolean
|
||||||
|
example: false
|
||||||
required:
|
required:
|
||||||
- city_name
|
- city_name
|
||||||
- connected
|
- connected
|
||||||
@@ -450,6 +454,7 @@ components:
|
|||||||
- approval_required
|
- approval_required
|
||||||
- serial_number
|
- serial_number
|
||||||
- extra_dns_labels
|
- extra_dns_labels
|
||||||
|
- ephemeral
|
||||||
AccessiblePeer:
|
AccessiblePeer:
|
||||||
allOf:
|
allOf:
|
||||||
- $ref: '#/components/schemas/PeerMinimum'
|
- $ref: '#/components/schemas/PeerMinimum'
|
||||||
|
|||||||
@@ -1016,6 +1016,9 @@ type Peer struct {
|
|||||||
// DnsLabel Peer's DNS label is the parsed peer name for domain resolution. It is used to form an FQDN by appending the account's domain to the peer label. e.g. peer-dns-label.netbird.cloud
|
// DnsLabel Peer's DNS label is the parsed peer name for domain resolution. It is used to form an FQDN by appending the account's domain to the peer label. e.g. peer-dns-label.netbird.cloud
|
||||||
DnsLabel string `json:"dns_label"`
|
DnsLabel string `json:"dns_label"`
|
||||||
|
|
||||||
|
// Ephemeral Indicates whether the peer is ephemeral or not
|
||||||
|
Ephemeral bool `json:"ephemeral"`
|
||||||
|
|
||||||
// ExtraDnsLabels Extra DNS labels added to the peer
|
// ExtraDnsLabels Extra DNS labels added to the peer
|
||||||
ExtraDnsLabels []string `json:"extra_dns_labels"`
|
ExtraDnsLabels []string `json:"extra_dns_labels"`
|
||||||
|
|
||||||
@@ -1097,6 +1100,9 @@ type PeerBatch struct {
|
|||||||
// DnsLabel Peer's DNS label is the parsed peer name for domain resolution. It is used to form an FQDN by appending the account's domain to the peer label. e.g. peer-dns-label.netbird.cloud
|
// DnsLabel Peer's DNS label is the parsed peer name for domain resolution. It is used to form an FQDN by appending the account's domain to the peer label. e.g. peer-dns-label.netbird.cloud
|
||||||
DnsLabel string `json:"dns_label"`
|
DnsLabel string `json:"dns_label"`
|
||||||
|
|
||||||
|
// Ephemeral Indicates whether the peer is ephemeral or not
|
||||||
|
Ephemeral bool `json:"ephemeral"`
|
||||||
|
|
||||||
// ExtraDnsLabels Extra DNS labels added to the peer
|
// ExtraDnsLabels Extra DNS labels added to the peer
|
||||||
ExtraDnsLabels []string `json:"extra_dns_labels"`
|
ExtraDnsLabels []string `json:"extra_dns_labels"`
|
||||||
|
|
||||||
|
|||||||
@@ -365,6 +365,7 @@ func toSinglePeerResponse(peer *nbpeer.Peer, groupsInfo []api.GroupMinimum, dnsD
|
|||||||
CityName: peer.Location.CityName,
|
CityName: peer.Location.CityName,
|
||||||
SerialNumber: peer.Meta.SystemSerialNumber,
|
SerialNumber: peer.Meta.SystemSerialNumber,
|
||||||
InactivityExpirationEnabled: peer.InactivityExpirationEnabled,
|
InactivityExpirationEnabled: peer.InactivityExpirationEnabled,
|
||||||
|
Ephemeral: peer.Ephemeral,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
package testing_tools
|
package testing_tools
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
@@ -138,7 +137,7 @@ func BuildApiBlackBoxWithDBState(t TB, sqlFile string, expectedPeerUpdate *serve
|
|||||||
userManager := users.NewManager(store)
|
userManager := users.NewManager(store)
|
||||||
permissionsManager := permissions.NewManager(store)
|
permissionsManager := permissions.NewManager(store)
|
||||||
settingsManager := settings.NewManager(store, userManager, integrations.NewManager(&activity.InMemoryEventStore{}), permissionsManager)
|
settingsManager := settings.NewManager(store, userManager, integrations.NewManager(&activity.InMemoryEventStore{}), permissionsManager)
|
||||||
am, err := server.BuildManager(context.Background(), store, peersUpdateManager, nil, "", "", &activity.InMemoryEventStore{}, geoMock, false, validatorMock, metrics, proxyController, settingsManager, permissionsManager)
|
am, err := server.BuildManager(context.Background(), store, peersUpdateManager, nil, "", "", &activity.InMemoryEventStore{}, geoMock, false, validatorMock, metrics, proxyController, settingsManager, permissionsManager, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create manager: %v", err)
|
t.Fatalf("Failed to create manager: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,21 +37,23 @@ func (am *DefaultAccountManager) UpdateIntegratedValidatorGroups(ctx context.Con
|
|||||||
unlock := am.Store.AcquireWriteLockByUID(ctx, accountID)
|
unlock := am.Store.AcquireWriteLockByUID(ctx, accountID)
|
||||||
defer unlock()
|
defer unlock()
|
||||||
|
|
||||||
a, err := am.Store.GetAccountByUser(ctx, userID)
|
return am.Store.ExecuteInTransaction(ctx, func(transaction store.Store) error {
|
||||||
if err != nil {
|
a, err := transaction.GetAccountByUser(ctx, userID)
|
||||||
return err
|
if err != nil {
|
||||||
}
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
var extra *types.ExtraSettings
|
var extra *types.ExtraSettings
|
||||||
|
|
||||||
if a.Settings.Extra != nil {
|
if a.Settings.Extra != nil {
|
||||||
extra = a.Settings.Extra
|
extra = a.Settings.Extra
|
||||||
} else {
|
} else {
|
||||||
extra = &types.ExtraSettings{}
|
extra = &types.ExtraSettings{}
|
||||||
a.Settings.Extra = extra
|
a.Settings.Extra = extra
|
||||||
}
|
}
|
||||||
extra.IntegratedValidatorGroups = groups
|
extra.IntegratedValidatorGroups = groups
|
||||||
return am.Store.SaveAccount(ctx, a)
|
return transaction.SaveAccount(ctx, a)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (am *DefaultAccountManager) GroupValidation(ctx context.Context, accountID string, groupIDs []string) (bool, error) {
|
func (am *DefaultAccountManager) GroupValidation(ctx context.Context, accountID string, groupIDs []string) (bool, error) {
|
||||||
@@ -81,15 +83,12 @@ func (am *DefaultAccountManager) GetValidatedPeers(ctx context.Context, accountI
|
|||||||
var peers []*nbpeer.Peer
|
var peers []*nbpeer.Peer
|
||||||
var settings *types.Settings
|
var settings *types.Settings
|
||||||
|
|
||||||
err = am.Store.ExecuteInTransaction(ctx, func(transaction store.Store) error {
|
groups, err = am.Store.GetAccountGroups(ctx, store.LockingStrengthShare, accountID)
|
||||||
groups, err = transaction.GetAccountGroups(ctx, store.LockingStrengthShare, accountID)
|
if err != nil {
|
||||||
if err != nil {
|
return nil, err
|
||||||
return err
|
}
|
||||||
}
|
|
||||||
|
|
||||||
peers, err = transaction.GetAccountPeers(ctx, store.LockingStrengthShare, accountID, "", "")
|
peers, err = am.Store.GetAccountPeers(ctx, store.LockingStrengthShare, accountID, "", "")
|
||||||
return err
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -444,7 +444,7 @@ func startManagementForTest(t *testing.T, testFile string, config *types.Config)
|
|||||||
permissionsManager := permissions.NewManager(store)
|
permissionsManager := permissions.NewManager(store)
|
||||||
|
|
||||||
accountManager, err := BuildManager(ctx, store, peersUpdateManager, nil, "", "netbird.selfhosted",
|
accountManager, err := BuildManager(ctx, store, peersUpdateManager, nil, "", "netbird.selfhosted",
|
||||||
eventStore, nil, false, MocIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager)
|
eventStore, nil, false, MocIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cleanup()
|
cleanup()
|
||||||
|
|||||||
@@ -211,7 +211,7 @@ func startServer(
|
|||||||
port_forwarding.NewControllerMock(),
|
port_forwarding.NewControllerMock(),
|
||||||
settingsMockManager,
|
settingsMockManager,
|
||||||
permissionsManager,
|
permissionsManager,
|
||||||
)
|
false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed creating an account manager: %v", err)
|
t.Fatalf("failed creating an account manager: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -184,7 +184,9 @@ func (w *Worker) generateProperties(ctx context.Context) properties {
|
|||||||
ephemeralPeersSKs int
|
ephemeralPeersSKs int
|
||||||
ephemeralPeersSKUsage int
|
ephemeralPeersSKUsage int
|
||||||
activePeersLastDay int
|
activePeersLastDay int
|
||||||
|
activeUserPeersLastDay int
|
||||||
osPeers map[string]int
|
osPeers map[string]int
|
||||||
|
activeUsersLastDay map[string]struct{}
|
||||||
userPeers int
|
userPeers int
|
||||||
rules int
|
rules int
|
||||||
rulesProtocol map[string]int
|
rulesProtocol map[string]int
|
||||||
@@ -203,6 +205,7 @@ func (w *Worker) generateProperties(ctx context.Context) properties {
|
|||||||
version string
|
version string
|
||||||
peerActiveVersions []string
|
peerActiveVersions []string
|
||||||
osUIClients map[string]int
|
osUIClients map[string]int
|
||||||
|
rosenpassEnabled int
|
||||||
)
|
)
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
metricsProperties := make(properties)
|
metricsProperties := make(properties)
|
||||||
@@ -210,6 +213,7 @@ func (w *Worker) generateProperties(ctx context.Context) properties {
|
|||||||
osUIClients = make(map[string]int)
|
osUIClients = make(map[string]int)
|
||||||
rulesProtocol = make(map[string]int)
|
rulesProtocol = make(map[string]int)
|
||||||
rulesDirection = make(map[string]int)
|
rulesDirection = make(map[string]int)
|
||||||
|
activeUsersLastDay = make(map[string]struct{})
|
||||||
uptime = time.Since(w.startupTime).Seconds()
|
uptime = time.Since(w.startupTime).Seconds()
|
||||||
connections := w.connManager.GetAllConnectedPeers()
|
connections := w.connManager.GetAllConnectedPeers()
|
||||||
version = nbversion.NetbirdVersion()
|
version = nbversion.NetbirdVersion()
|
||||||
@@ -277,10 +281,14 @@ func (w *Worker) generateProperties(ctx context.Context) properties {
|
|||||||
for _, peer := range account.Peers {
|
for _, peer := range account.Peers {
|
||||||
peers++
|
peers++
|
||||||
|
|
||||||
if peer.SSHEnabled {
|
if peer.SSHEnabled || peer.Meta.Flags.ServerSSHAllowed {
|
||||||
peersSSHEnabled++
|
peersSSHEnabled++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if peer.Meta.Flags.RosenpassEnabled {
|
||||||
|
rosenpassEnabled++
|
||||||
|
}
|
||||||
|
|
||||||
if peer.UserID != "" {
|
if peer.UserID != "" {
|
||||||
userPeers++
|
userPeers++
|
||||||
}
|
}
|
||||||
@@ -299,6 +307,10 @@ func (w *Worker) generateProperties(ctx context.Context) properties {
|
|||||||
_, connected := connections[peer.ID]
|
_, connected := connections[peer.ID]
|
||||||
if connected || peer.Status.LastSeen.After(w.lastRun) {
|
if connected || peer.Status.LastSeen.After(w.lastRun) {
|
||||||
activePeersLastDay++
|
activePeersLastDay++
|
||||||
|
if peer.UserID != "" {
|
||||||
|
activeUserPeersLastDay++
|
||||||
|
activeUsersLastDay[peer.UserID] = struct{}{}
|
||||||
|
}
|
||||||
osActiveKey := osKey + "_active"
|
osActiveKey := osKey + "_active"
|
||||||
osActiveCount := osPeers[osActiveKey]
|
osActiveCount := osPeers[osActiveKey]
|
||||||
osPeers[osActiveKey] = osActiveCount + 1
|
osPeers[osActiveKey] = osActiveCount + 1
|
||||||
@@ -320,6 +332,8 @@ func (w *Worker) generateProperties(ctx context.Context) properties {
|
|||||||
metricsProperties["ephemeral_peers_setup_keys"] = ephemeralPeersSKs
|
metricsProperties["ephemeral_peers_setup_keys"] = ephemeralPeersSKs
|
||||||
metricsProperties["ephemeral_peers_setup_keys_usage"] = ephemeralPeersSKUsage
|
metricsProperties["ephemeral_peers_setup_keys_usage"] = ephemeralPeersSKUsage
|
||||||
metricsProperties["active_peers_last_day"] = activePeersLastDay
|
metricsProperties["active_peers_last_day"] = activePeersLastDay
|
||||||
|
metricsProperties["active_user_peers_last_day"] = activeUserPeersLastDay
|
||||||
|
metricsProperties["active_users_last_day"] = len(activeUsersLastDay)
|
||||||
metricsProperties["user_peers"] = userPeers
|
metricsProperties["user_peers"] = userPeers
|
||||||
metricsProperties["rules"] = rules
|
metricsProperties["rules"] = rules
|
||||||
metricsProperties["rules_with_src_posture_checks"] = rulesWithSrcPostureChecks
|
metricsProperties["rules_with_src_posture_checks"] = rulesWithSrcPostureChecks
|
||||||
@@ -338,6 +352,7 @@ func (w *Worker) generateProperties(ctx context.Context) properties {
|
|||||||
metricsProperties["ui_clients"] = uiClient
|
metricsProperties["ui_clients"] = uiClient
|
||||||
metricsProperties["idp_manager"] = w.idpManager
|
metricsProperties["idp_manager"] = w.idpManager
|
||||||
metricsProperties["store_engine"] = w.dataSource.GetStoreEngine()
|
metricsProperties["store_engine"] = w.dataSource.GetStoreEngine()
|
||||||
|
metricsProperties["rosenpass_enabled"] = rosenpassEnabled
|
||||||
|
|
||||||
for protocol, count := range rulesProtocol {
|
for protocol, count := range rulesProtocol {
|
||||||
metricsProperties["rules_protocol_"+protocol] = count
|
metricsProperties["rules_protocol_"+protocol] = count
|
||||||
|
|||||||
@@ -47,8 +47,8 @@ func (mockDatasource) GetAllAccounts(_ context.Context) []*types.Account {
|
|||||||
"1": {
|
"1": {
|
||||||
ID: "1",
|
ID: "1",
|
||||||
UserID: "test",
|
UserID: "test",
|
||||||
SSHEnabled: true,
|
SSHEnabled: false,
|
||||||
Meta: nbpeer.PeerSystemMeta{GoOS: "linux", WtVersion: "0.0.1"},
|
Meta: nbpeer.PeerSystemMeta{GoOS: "linux", WtVersion: "0.0.1", Flags: nbpeer.Flags{ServerSSHAllowed: true, RosenpassEnabled: true}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Policies: []*types.Policy{
|
Policies: []*types.Policy{
|
||||||
@@ -312,7 +312,19 @@ func TestGenerateProperties(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if properties["posture_checks"] != 2 {
|
if properties["posture_checks"] != 2 {
|
||||||
t.Errorf("expected 1 posture_checks, got %d", properties["posture_checks"])
|
t.Errorf("expected 2 posture_checks, got %d", properties["posture_checks"])
|
||||||
|
}
|
||||||
|
|
||||||
|
if properties["rosenpass_enabled"] != 1 {
|
||||||
|
t.Errorf("expected 1 rosenpass_enabled, got %d", properties["rosenpass_enabled"])
|
||||||
|
}
|
||||||
|
|
||||||
|
if properties["active_user_peers_last_day"] != 2 {
|
||||||
|
t.Errorf("expected 2 active_user_peers_last_day, got %d", properties["active_user_peers_last_day"])
|
||||||
|
}
|
||||||
|
|
||||||
|
if properties["active_users_last_day"] != 1 {
|
||||||
|
t.Errorf("expected 1 active_users_last_day, got %d", properties["active_users_last_day"])
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -779,7 +779,7 @@ func createNSManager(t *testing.T) (*DefaultAccountManager, error) {
|
|||||||
t.Cleanup(ctrl.Finish)
|
t.Cleanup(ctrl.Finish)
|
||||||
settingsMockManager := settings.NewMockManager(ctrl)
|
settingsMockManager := settings.NewMockManager(ctrl)
|
||||||
permissionsManager := permissions.NewManager(store)
|
permissionsManager := permissions.NewManager(store)
|
||||||
return BuildManager(context.Background(), store, NewPeersUpdateManager(nil), nil, "", "netbird.selfhosted", eventStore, nil, false, MocIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager)
|
return BuildManager(context.Background(), store, NewPeersUpdateManager(nil), nil, "", "netbird.selfhosted", eventStore, nil, false, MocIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func createNSStore(t *testing.T) (store.Store, error) {
|
func createNSStore(t *testing.T) (store.Store, error) {
|
||||||
@@ -848,7 +848,7 @@ func initTestNSAccount(t *testing.T, am *DefaultAccountManager) (*types.Account,
|
|||||||
userID := testUserID
|
userID := testUserID
|
||||||
domain := "example.com"
|
domain := "example.com"
|
||||||
|
|
||||||
account := newAccountWithId(context.Background(), accountID, userID, domain)
|
account := newAccountWithId(context.Background(), accountID, userID, domain, false)
|
||||||
|
|
||||||
account.NameServerGroups[existingNSGroup.ID] = &existingNSGroup
|
account.NameServerGroups[existingNSGroup.ID] = &existingNSGroup
|
||||||
|
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ func (am *DefaultAccountManager) getUserAccessiblePeers(ctx context.Context, acc
|
|||||||
|
|
||||||
// fetch all the peers that have access to the user's peers
|
// fetch all the peers that have access to the user's peers
|
||||||
for _, peer := range peers {
|
for _, peer := range peers {
|
||||||
aclPeers, _ := account.GetPeerConnectionResources(ctx, peer.ID, approvedPeersMap)
|
aclPeers, _ := account.GetPeerConnectionResources(ctx, peer, approvedPeersMap)
|
||||||
for _, p := range aclPeers {
|
for _, p := range aclPeers {
|
||||||
peersMap[p.ID] = p
|
peersMap[p.ID] = p
|
||||||
}
|
}
|
||||||
@@ -1149,7 +1149,7 @@ func (am *DefaultAccountManager) checkIfUserOwnsPeer(ctx context.Context, accoun
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, p := range userPeers {
|
for _, p := range userPeers {
|
||||||
aclPeers, _ := account.GetPeerConnectionResources(ctx, p.ID, approvedPeersMap)
|
aclPeers, _ := account.GetPeerConnectionResources(ctx, p, approvedPeersMap)
|
||||||
for _, aclPeer := range aclPeers {
|
for _, aclPeer := range aclPeers {
|
||||||
if aclPeer.ID == peer.ID {
|
if aclPeer.ID == peer.ID {
|
||||||
return peer, nil
|
return peer, nil
|
||||||
@@ -1169,7 +1169,7 @@ func (am *DefaultAccountManager) UpdateAccountPeers(ctx context.Context, account
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
start := time.Now()
|
globalStart := time.Now()
|
||||||
|
|
||||||
approvedPeersMap, err := am.integratedPeerValidator.GetValidatedPeers(account.Id, maps.Values(account.Groups), maps.Values(account.Peers), account.Settings.Extra)
|
approvedPeersMap, err := am.integratedPeerValidator.GetValidatedPeers(account.Id, maps.Values(account.Groups), maps.Values(account.Peers), account.Settings.Extra)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1204,18 +1204,27 @@ func (am *DefaultAccountManager) UpdateAccountPeers(ctx context.Context, account
|
|||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
defer func() { <-semaphore }()
|
defer func() { <-semaphore }()
|
||||||
|
|
||||||
|
start := time.Now()
|
||||||
|
|
||||||
postureChecks, err := am.getPeerPostureChecks(account, p.ID)
|
postureChecks, err := am.getPeerPostureChecks(account, p.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithContext(ctx).Debugf("failed to get posture checks for peer %s: %v", peer.ID, err)
|
log.WithContext(ctx).Debugf("failed to get posture checks for peer %s: %v", peer.ID, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
am.metrics.UpdateChannelMetrics().CountCalcPostureChecksDuration(time.Since(start))
|
||||||
|
start = time.Now()
|
||||||
|
|
||||||
remotePeerNetworkMap := account.GetPeerNetworkMap(ctx, p.ID, customZone, approvedPeersMap, resourcePolicies, routers, am.metrics.AccountManagerMetrics())
|
remotePeerNetworkMap := account.GetPeerNetworkMap(ctx, p.ID, customZone, approvedPeersMap, resourcePolicies, routers, am.metrics.AccountManagerMetrics())
|
||||||
|
|
||||||
|
am.metrics.UpdateChannelMetrics().CountCalcPeerNetworkMapDuration(time.Since(start))
|
||||||
|
start = time.Now()
|
||||||
|
|
||||||
proxyNetworkMap, ok := proxyNetworkMaps[p.ID]
|
proxyNetworkMap, ok := proxyNetworkMaps[p.ID]
|
||||||
if ok {
|
if ok {
|
||||||
remotePeerNetworkMap.Merge(proxyNetworkMap)
|
remotePeerNetworkMap.Merge(proxyNetworkMap)
|
||||||
}
|
}
|
||||||
|
am.metrics.UpdateChannelMetrics().CountMergeNetworkMapDuration(time.Since(start))
|
||||||
|
|
||||||
extraSetting, err := am.settingsManager.GetExtraSettings(ctx, accountID)
|
extraSetting, err := am.settingsManager.GetExtraSettings(ctx, accountID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1223,7 +1232,10 @@ func (am *DefaultAccountManager) UpdateAccountPeers(ctx context.Context, account
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
start = time.Now()
|
||||||
update := toSyncResponse(ctx, nil, p, nil, nil, remotePeerNetworkMap, dnsDomain, postureChecks, dnsCache, account.Settings, extraSetting)
|
update := toSyncResponse(ctx, nil, p, nil, nil, remotePeerNetworkMap, dnsDomain, postureChecks, dnsCache, account.Settings, extraSetting)
|
||||||
|
am.metrics.UpdateChannelMetrics().CountToSyncResponseDuration(time.Since(start))
|
||||||
|
|
||||||
am.peersUpdateManager.SendUpdate(ctx, p.ID, &UpdateMessage{Update: update, NetworkMap: remotePeerNetworkMap})
|
am.peersUpdateManager.SendUpdate(ctx, p.ID, &UpdateMessage{Update: update, NetworkMap: remotePeerNetworkMap})
|
||||||
}(peer)
|
}(peer)
|
||||||
}
|
}
|
||||||
@@ -1232,7 +1244,7 @@ func (am *DefaultAccountManager) UpdateAccountPeers(ctx context.Context, account
|
|||||||
|
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
if am.metrics != nil {
|
if am.metrics != nil {
|
||||||
am.metrics.AccountManagerMetrics().CountUpdateAccountPeersDuration(time.Since(start))
|
am.metrics.AccountManagerMetrics().CountUpdateAccountPeersDuration(time.Since(globalStart))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -480,7 +480,7 @@ func TestDefaultAccountManager_GetPeer(t *testing.T) {
|
|||||||
accountID := "test_account"
|
accountID := "test_account"
|
||||||
adminUser := "account_creator"
|
adminUser := "account_creator"
|
||||||
someUser := "some_user"
|
someUser := "some_user"
|
||||||
account := newAccountWithId(context.Background(), accountID, adminUser, "")
|
account := newAccountWithId(context.Background(), accountID, adminUser, "", false)
|
||||||
account.Users[someUser] = &types.User{
|
account.Users[someUser] = &types.User{
|
||||||
Id: someUser,
|
Id: someUser,
|
||||||
Role: types.UserRoleUser,
|
Role: types.UserRoleUser,
|
||||||
@@ -667,7 +667,7 @@ func TestDefaultAccountManager_GetPeers(t *testing.T) {
|
|||||||
accountID := "test_account"
|
accountID := "test_account"
|
||||||
adminUser := "account_creator"
|
adminUser := "account_creator"
|
||||||
someUser := "some_user"
|
someUser := "some_user"
|
||||||
account := newAccountWithId(context.Background(), accountID, adminUser, "")
|
account := newAccountWithId(context.Background(), accountID, adminUser, "", false)
|
||||||
account.Users[someUser] = &types.User{
|
account.Users[someUser] = &types.User{
|
||||||
Id: someUser,
|
Id: someUser,
|
||||||
Role: testCase.role,
|
Role: testCase.role,
|
||||||
@@ -737,7 +737,7 @@ func setupTestAccountManager(b testing.TB, peers int, groups int) (*DefaultAccou
|
|||||||
adminUser := "account_creator"
|
adminUser := "account_creator"
|
||||||
regularUser := "regular_user"
|
regularUser := "regular_user"
|
||||||
|
|
||||||
account := newAccountWithId(context.Background(), accountID, adminUser, "")
|
account := newAccountWithId(context.Background(), accountID, adminUser, "", false)
|
||||||
account.Users[regularUser] = &types.User{
|
account.Users[regularUser] = &types.User{
|
||||||
Id: regularUser,
|
Id: regularUser,
|
||||||
Role: types.UserRoleUser,
|
Role: types.UserRoleUser,
|
||||||
@@ -1267,7 +1267,7 @@ func Test_RegisterPeerByUser(t *testing.T) {
|
|||||||
settingsMockManager := settings.NewMockManager(ctrl)
|
settingsMockManager := settings.NewMockManager(ctrl)
|
||||||
permissionsManager := permissions.NewManager(s)
|
permissionsManager := permissions.NewManager(s)
|
||||||
|
|
||||||
am, err := BuildManager(context.Background(), s, NewPeersUpdateManager(nil), nil, "", "netbird.cloud", eventStore, nil, false, MocIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager)
|
am, err := BuildManager(context.Background(), s, NewPeersUpdateManager(nil), nil, "", "netbird.cloud", eventStore, nil, false, MocIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
existingAccountID := "bf1c8084-ba50-4ce7-9439-34653001fc3b"
|
existingAccountID := "bf1c8084-ba50-4ce7-9439-34653001fc3b"
|
||||||
@@ -1342,7 +1342,7 @@ func Test_RegisterPeerBySetupKey(t *testing.T) {
|
|||||||
settingsMockManager := settings.NewMockManager(ctrl)
|
settingsMockManager := settings.NewMockManager(ctrl)
|
||||||
permissionsManager := permissions.NewManager(s)
|
permissionsManager := permissions.NewManager(s)
|
||||||
|
|
||||||
am, err := BuildManager(context.Background(), s, NewPeersUpdateManager(nil), nil, "", "netbird.cloud", eventStore, nil, false, MocIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager)
|
am, err := BuildManager(context.Background(), s, NewPeersUpdateManager(nil), nil, "", "netbird.cloud", eventStore, nil, false, MocIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
existingAccountID := "bf1c8084-ba50-4ce7-9439-34653001fc3b"
|
existingAccountID := "bf1c8084-ba50-4ce7-9439-34653001fc3b"
|
||||||
@@ -1477,7 +1477,7 @@ func Test_RegisterPeerRollbackOnFailure(t *testing.T) {
|
|||||||
|
|
||||||
permissionsManager := permissions.NewManager(s)
|
permissionsManager := permissions.NewManager(s)
|
||||||
|
|
||||||
am, err := BuildManager(context.Background(), s, NewPeersUpdateManager(nil), nil, "", "netbird.cloud", eventStore, nil, false, MocIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager)
|
am, err := BuildManager(context.Background(), s, NewPeersUpdateManager(nil), nil, "", "netbird.cloud", eventStore, nil, false, MocIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
existingAccountID := "bf1c8084-ba50-4ce7-9439-34653001fc3b"
|
existingAccountID := "bf1c8084-ba50-4ce7-9439-34653001fc3b"
|
||||||
@@ -1546,7 +1546,7 @@ func Test_LoginPeer(t *testing.T) {
|
|||||||
settingsMockManager := settings.NewMockManager(ctrl)
|
settingsMockManager := settings.NewMockManager(ctrl)
|
||||||
permissionsManager := permissions.NewManager(s)
|
permissionsManager := permissions.NewManager(s)
|
||||||
|
|
||||||
am, err := BuildManager(context.Background(), s, NewPeersUpdateManager(nil), nil, "", "netbird.cloud", eventStore, nil, false, MocIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager)
|
am, err := BuildManager(context.Background(), s, NewPeersUpdateManager(nil), nil, "", "netbird.cloud", eventStore, nil, false, MocIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
existingAccountID := "bf1c8084-ba50-4ce7-9439-34653001fc3b"
|
existingAccountID := "bf1c8084-ba50-4ce7-9439-34653001fc3b"
|
||||||
@@ -2052,7 +2052,7 @@ func Test_DeletePeer(t *testing.T) {
|
|||||||
// account with an admin and a regular user
|
// account with an admin and a regular user
|
||||||
accountID := "test_account"
|
accountID := "test_account"
|
||||||
adminUser := "account_creator"
|
adminUser := "account_creator"
|
||||||
account := newAccountWithId(context.Background(), accountID, adminUser, "")
|
account := newAccountWithId(context.Background(), accountID, adminUser, "", false)
|
||||||
account.Peers = map[string]*nbpeer.Peer{
|
account.Peers = map[string]*nbpeer.Peer{
|
||||||
"peer1": {
|
"peer1": {
|
||||||
ID: "peer1",
|
ID: "peer1",
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ func TestAccount_getPeersByPolicy(t *testing.T) {
|
|||||||
ID: "peerB",
|
ID: "peerB",
|
||||||
IP: net.ParseIP("100.65.80.39"),
|
IP: net.ParseIP("100.65.80.39"),
|
||||||
Status: &nbpeer.PeerStatus{},
|
Status: &nbpeer.PeerStatus{},
|
||||||
|
Meta: nbpeer.PeerSystemMeta{WtVersion: "0.48.0"},
|
||||||
},
|
},
|
||||||
"peerC": {
|
"peerC": {
|
||||||
ID: "peerC",
|
ID: "peerC",
|
||||||
@@ -63,6 +64,12 @@ func TestAccount_getPeersByPolicy(t *testing.T) {
|
|||||||
IP: net.ParseIP("100.65.31.2"),
|
IP: net.ParseIP("100.65.31.2"),
|
||||||
Status: &nbpeer.PeerStatus{},
|
Status: &nbpeer.PeerStatus{},
|
||||||
},
|
},
|
||||||
|
"peerK": {
|
||||||
|
ID: "peerK",
|
||||||
|
IP: net.ParseIP("100.32.80.1"),
|
||||||
|
Status: &nbpeer.PeerStatus{},
|
||||||
|
Meta: nbpeer.PeerSystemMeta{WtVersion: "0.30.0"},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Groups: map[string]*types.Group{
|
Groups: map[string]*types.Group{
|
||||||
"GroupAll": {
|
"GroupAll": {
|
||||||
@@ -111,6 +118,13 @@ func TestAccount_getPeersByPolicy(t *testing.T) {
|
|||||||
"peerI",
|
"peerI",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"GroupWorkflow": {
|
||||||
|
ID: "GroupWorkflow",
|
||||||
|
Name: "workflow",
|
||||||
|
Peers: []string{
|
||||||
|
"peerK",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Policies: []*types.Policy{
|
Policies: []*types.Policy{
|
||||||
{
|
{
|
||||||
@@ -189,6 +203,39 @@ func TestAccount_getPeersByPolicy(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
ID: "RuleWorkflow",
|
||||||
|
Name: "Workflow",
|
||||||
|
Description: "No description",
|
||||||
|
Enabled: true,
|
||||||
|
Rules: []*types.PolicyRule{
|
||||||
|
{
|
||||||
|
ID: "RuleWorkflow",
|
||||||
|
Name: "Workflow",
|
||||||
|
Description: "No description",
|
||||||
|
Bidirectional: true,
|
||||||
|
Enabled: true,
|
||||||
|
Protocol: types.PolicyRuleProtocolTCP,
|
||||||
|
Action: types.PolicyTrafficActionAccept,
|
||||||
|
PortRanges: []types.RulePortRange{
|
||||||
|
{
|
||||||
|
Start: 8088,
|
||||||
|
End: 8088,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Start: 9090,
|
||||||
|
End: 9095,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Sources: []string{
|
||||||
|
"GroupWorkflow",
|
||||||
|
},
|
||||||
|
Destinations: []string{
|
||||||
|
"GroupDMZ",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,14 +246,14 @@ func TestAccount_getPeersByPolicy(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("check that all peers get map", func(t *testing.T) {
|
t.Run("check that all peers get map", func(t *testing.T) {
|
||||||
for _, p := range account.Peers {
|
for _, p := range account.Peers {
|
||||||
peers, firewallRules := account.GetPeerConnectionResources(context.Background(), p.ID, validatedPeers)
|
peers, firewallRules := account.GetPeerConnectionResources(context.Background(), p, validatedPeers)
|
||||||
assert.GreaterOrEqual(t, len(peers), 2, "minimum number peers should present")
|
assert.GreaterOrEqual(t, len(peers), 1, "minimum number peers should present")
|
||||||
assert.GreaterOrEqual(t, len(firewallRules), 2, "minimum number of firewall rules should present")
|
assert.GreaterOrEqual(t, len(firewallRules), 1, "minimum number of firewall rules should present")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("check first peer map details", func(t *testing.T) {
|
t.Run("check first peer map details", func(t *testing.T) {
|
||||||
peers, firewallRules := account.GetPeerConnectionResources(context.Background(), "peerB", validatedPeers)
|
peers, firewallRules := account.GetPeerConnectionResources(context.Background(), account.Peers["peerB"], validatedPeers)
|
||||||
assert.Len(t, peers, 8)
|
assert.Len(t, peers, 8)
|
||||||
assert.Contains(t, peers, account.Peers["peerA"])
|
assert.Contains(t, peers, account.Peers["peerA"])
|
||||||
assert.Contains(t, peers, account.Peers["peerC"])
|
assert.Contains(t, peers, account.Peers["peerC"])
|
||||||
@@ -364,6 +411,32 @@ func TestAccount_getPeersByPolicy(t *testing.T) {
|
|||||||
assert.True(t, contains, "rule not found in expected rules %#v", rule)
|
assert.True(t, contains, "rule not found in expected rules %#v", rule)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("check port ranges support for older peers", func(t *testing.T) {
|
||||||
|
peers, firewallRules := account.GetPeerConnectionResources(context.Background(), account.Peers["peerK"], validatedPeers)
|
||||||
|
assert.Len(t, peers, 1)
|
||||||
|
assert.Contains(t, peers, account.Peers["peerI"])
|
||||||
|
|
||||||
|
expectedFirewallRules := []*types.FirewallRule{
|
||||||
|
{
|
||||||
|
PeerIP: "100.65.31.2",
|
||||||
|
Direction: types.FirewallRuleDirectionIN,
|
||||||
|
Action: "accept",
|
||||||
|
Protocol: "tcp",
|
||||||
|
Port: "8088",
|
||||||
|
PolicyID: "RuleWorkflow",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PeerIP: "100.65.31.2",
|
||||||
|
Direction: types.FirewallRuleDirectionOUT,
|
||||||
|
Action: "accept",
|
||||||
|
Protocol: "tcp",
|
||||||
|
Port: "8088",
|
||||||
|
PolicyID: "RuleWorkflow",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
assert.ElementsMatch(t, firewallRules, expectedFirewallRules)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAccount_getPeersByPolicyDirect(t *testing.T) {
|
func TestAccount_getPeersByPolicyDirect(t *testing.T) {
|
||||||
@@ -466,10 +539,10 @@ func TestAccount_getPeersByPolicyDirect(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
t.Run("check first peer map", func(t *testing.T) {
|
t.Run("check first peer map", func(t *testing.T) {
|
||||||
peers, firewallRules := account.GetPeerConnectionResources(context.Background(), "peerB", approvedPeers)
|
peers, firewallRules := account.GetPeerConnectionResources(context.Background(), account.Peers["peerB"], approvedPeers)
|
||||||
assert.Contains(t, peers, account.Peers["peerC"])
|
assert.Contains(t, peers, account.Peers["peerC"])
|
||||||
|
|
||||||
epectedFirewallRules := []*types.FirewallRule{
|
expectedFirewallRules := []*types.FirewallRule{
|
||||||
{
|
{
|
||||||
PeerIP: "100.65.254.139",
|
PeerIP: "100.65.254.139",
|
||||||
Direction: types.FirewallRuleDirectionIN,
|
Direction: types.FirewallRuleDirectionIN,
|
||||||
@@ -487,19 +560,19 @@ func TestAccount_getPeersByPolicyDirect(t *testing.T) {
|
|||||||
PolicyID: "RuleSwarm",
|
PolicyID: "RuleSwarm",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
assert.Len(t, firewallRules, len(epectedFirewallRules))
|
assert.Len(t, firewallRules, len(expectedFirewallRules))
|
||||||
slices.SortFunc(epectedFirewallRules, sortFunc())
|
slices.SortFunc(expectedFirewallRules, sortFunc())
|
||||||
slices.SortFunc(firewallRules, sortFunc())
|
slices.SortFunc(firewallRules, sortFunc())
|
||||||
for i := range firewallRules {
|
for i := range firewallRules {
|
||||||
assert.Equal(t, epectedFirewallRules[i], firewallRules[i])
|
assert.Equal(t, expectedFirewallRules[i], firewallRules[i])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("check second peer map", func(t *testing.T) {
|
t.Run("check second peer map", func(t *testing.T) {
|
||||||
peers, firewallRules := account.GetPeerConnectionResources(context.Background(), "peerC", approvedPeers)
|
peers, firewallRules := account.GetPeerConnectionResources(context.Background(), account.Peers["peerC"], approvedPeers)
|
||||||
assert.Contains(t, peers, account.Peers["peerB"])
|
assert.Contains(t, peers, account.Peers["peerB"])
|
||||||
|
|
||||||
epectedFirewallRules := []*types.FirewallRule{
|
expectedFirewallRules := []*types.FirewallRule{
|
||||||
{
|
{
|
||||||
PeerIP: "100.65.80.39",
|
PeerIP: "100.65.80.39",
|
||||||
Direction: types.FirewallRuleDirectionIN,
|
Direction: types.FirewallRuleDirectionIN,
|
||||||
@@ -517,21 +590,21 @@ func TestAccount_getPeersByPolicyDirect(t *testing.T) {
|
|||||||
PolicyID: "RuleSwarm",
|
PolicyID: "RuleSwarm",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
assert.Len(t, firewallRules, len(epectedFirewallRules))
|
assert.Len(t, firewallRules, len(expectedFirewallRules))
|
||||||
slices.SortFunc(epectedFirewallRules, sortFunc())
|
slices.SortFunc(expectedFirewallRules, sortFunc())
|
||||||
slices.SortFunc(firewallRules, sortFunc())
|
slices.SortFunc(firewallRules, sortFunc())
|
||||||
for i := range firewallRules {
|
for i := range firewallRules {
|
||||||
assert.Equal(t, epectedFirewallRules[i], firewallRules[i])
|
assert.Equal(t, expectedFirewallRules[i], firewallRules[i])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
account.Policies[1].Rules[0].Bidirectional = false
|
account.Policies[1].Rules[0].Bidirectional = false
|
||||||
|
|
||||||
t.Run("check first peer map directional only", func(t *testing.T) {
|
t.Run("check first peer map directional only", func(t *testing.T) {
|
||||||
peers, firewallRules := account.GetPeerConnectionResources(context.Background(), "peerB", approvedPeers)
|
peers, firewallRules := account.GetPeerConnectionResources(context.Background(), account.Peers["peerB"], approvedPeers)
|
||||||
assert.Contains(t, peers, account.Peers["peerC"])
|
assert.Contains(t, peers, account.Peers["peerC"])
|
||||||
|
|
||||||
epectedFirewallRules := []*types.FirewallRule{
|
expectedFirewallRules := []*types.FirewallRule{
|
||||||
{
|
{
|
||||||
PeerIP: "100.65.254.139",
|
PeerIP: "100.65.254.139",
|
||||||
Direction: types.FirewallRuleDirectionOUT,
|
Direction: types.FirewallRuleDirectionOUT,
|
||||||
@@ -541,19 +614,19 @@ func TestAccount_getPeersByPolicyDirect(t *testing.T) {
|
|||||||
PolicyID: "RuleSwarm",
|
PolicyID: "RuleSwarm",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
assert.Len(t, firewallRules, len(epectedFirewallRules))
|
assert.Len(t, firewallRules, len(expectedFirewallRules))
|
||||||
slices.SortFunc(epectedFirewallRules, sortFunc())
|
slices.SortFunc(expectedFirewallRules, sortFunc())
|
||||||
slices.SortFunc(firewallRules, sortFunc())
|
slices.SortFunc(firewallRules, sortFunc())
|
||||||
for i := range firewallRules {
|
for i := range firewallRules {
|
||||||
assert.Equal(t, epectedFirewallRules[i], firewallRules[i])
|
assert.Equal(t, expectedFirewallRules[i], firewallRules[i])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("check second peer map directional only", func(t *testing.T) {
|
t.Run("check second peer map directional only", func(t *testing.T) {
|
||||||
peers, firewallRules := account.GetPeerConnectionResources(context.Background(), "peerC", approvedPeers)
|
peers, firewallRules := account.GetPeerConnectionResources(context.Background(), account.Peers["peerC"], approvedPeers)
|
||||||
assert.Contains(t, peers, account.Peers["peerB"])
|
assert.Contains(t, peers, account.Peers["peerB"])
|
||||||
|
|
||||||
epectedFirewallRules := []*types.FirewallRule{
|
expectedFirewallRules := []*types.FirewallRule{
|
||||||
{
|
{
|
||||||
PeerIP: "100.65.80.39",
|
PeerIP: "100.65.80.39",
|
||||||
Direction: types.FirewallRuleDirectionIN,
|
Direction: types.FirewallRuleDirectionIN,
|
||||||
@@ -563,11 +636,11 @@ func TestAccount_getPeersByPolicyDirect(t *testing.T) {
|
|||||||
PolicyID: "RuleSwarm",
|
PolicyID: "RuleSwarm",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
assert.Len(t, firewallRules, len(epectedFirewallRules))
|
assert.Len(t, firewallRules, len(expectedFirewallRules))
|
||||||
slices.SortFunc(epectedFirewallRules, sortFunc())
|
slices.SortFunc(expectedFirewallRules, sortFunc())
|
||||||
slices.SortFunc(firewallRules, sortFunc())
|
slices.SortFunc(firewallRules, sortFunc())
|
||||||
for i := range firewallRules {
|
for i := range firewallRules {
|
||||||
assert.Equal(t, epectedFirewallRules[i], firewallRules[i])
|
assert.Equal(t, expectedFirewallRules[i], firewallRules[i])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -748,7 +821,7 @@ func TestAccount_getPeersByPolicyPostureChecks(t *testing.T) {
|
|||||||
t.Run("verify peer's network map with default group peer list", func(t *testing.T) {
|
t.Run("verify peer's network map with default group peer list", func(t *testing.T) {
|
||||||
// peerB doesn't fulfill the NB posture check but is included in the destination group Swarm,
|
// peerB doesn't fulfill the NB posture check but is included in the destination group Swarm,
|
||||||
// will establish a connection with all source peers satisfying the NB posture check.
|
// will establish a connection with all source peers satisfying the NB posture check.
|
||||||
peers, firewallRules := account.GetPeerConnectionResources(context.Background(), "peerB", approvedPeers)
|
peers, firewallRules := account.GetPeerConnectionResources(context.Background(), account.Peers["peerB"], approvedPeers)
|
||||||
assert.Len(t, peers, 4)
|
assert.Len(t, peers, 4)
|
||||||
assert.Len(t, firewallRules, 4)
|
assert.Len(t, firewallRules, 4)
|
||||||
assert.Contains(t, peers, account.Peers["peerA"])
|
assert.Contains(t, peers, account.Peers["peerA"])
|
||||||
@@ -758,7 +831,7 @@ func TestAccount_getPeersByPolicyPostureChecks(t *testing.T) {
|
|||||||
|
|
||||||
// peerC satisfy the NB posture check, should establish connection to all destination group peer's
|
// peerC satisfy the NB posture check, should establish connection to all destination group peer's
|
||||||
// We expect a single permissive firewall rule which all outgoing connections
|
// We expect a single permissive firewall rule which all outgoing connections
|
||||||
peers, firewallRules = account.GetPeerConnectionResources(context.Background(), "peerC", approvedPeers)
|
peers, firewallRules = account.GetPeerConnectionResources(context.Background(), account.Peers["peerC"], approvedPeers)
|
||||||
assert.Len(t, peers, len(account.Groups["GroupSwarm"].Peers))
|
assert.Len(t, peers, len(account.Groups["GroupSwarm"].Peers))
|
||||||
assert.Len(t, firewallRules, 1)
|
assert.Len(t, firewallRules, 1)
|
||||||
expectedFirewallRules := []*types.FirewallRule{
|
expectedFirewallRules := []*types.FirewallRule{
|
||||||
@@ -775,7 +848,7 @@ func TestAccount_getPeersByPolicyPostureChecks(t *testing.T) {
|
|||||||
|
|
||||||
// peerE doesn't fulfill the NB posture check and exists in only destination group Swarm,
|
// peerE doesn't fulfill the NB posture check and exists in only destination group Swarm,
|
||||||
// all source group peers satisfying the NB posture check should establish connection
|
// all source group peers satisfying the NB posture check should establish connection
|
||||||
peers, firewallRules = account.GetPeerConnectionResources(context.Background(), "peerE", approvedPeers)
|
peers, firewallRules = account.GetPeerConnectionResources(context.Background(), account.Peers["peerE"], approvedPeers)
|
||||||
assert.Len(t, peers, 4)
|
assert.Len(t, peers, 4)
|
||||||
assert.Len(t, firewallRules, 4)
|
assert.Len(t, firewallRules, 4)
|
||||||
assert.Contains(t, peers, account.Peers["peerA"])
|
assert.Contains(t, peers, account.Peers["peerA"])
|
||||||
@@ -785,7 +858,7 @@ func TestAccount_getPeersByPolicyPostureChecks(t *testing.T) {
|
|||||||
|
|
||||||
// peerI doesn't fulfill the OS version posture check and exists in only destination group Swarm,
|
// peerI doesn't fulfill the OS version posture check and exists in only destination group Swarm,
|
||||||
// all source group peers satisfying the NB posture check should establish connection
|
// all source group peers satisfying the NB posture check should establish connection
|
||||||
peers, firewallRules = account.GetPeerConnectionResources(context.Background(), "peerI", approvedPeers)
|
peers, firewallRules = account.GetPeerConnectionResources(context.Background(), account.Peers["peerI"], approvedPeers)
|
||||||
assert.Len(t, peers, 4)
|
assert.Len(t, peers, 4)
|
||||||
assert.Len(t, firewallRules, 4)
|
assert.Len(t, firewallRules, 4)
|
||||||
assert.Contains(t, peers, account.Peers["peerA"])
|
assert.Contains(t, peers, account.Peers["peerA"])
|
||||||
@@ -800,19 +873,19 @@ func TestAccount_getPeersByPolicyPostureChecks(t *testing.T) {
|
|||||||
|
|
||||||
// peerB doesn't satisfy the NB posture check, and doesn't exist in destination group peer's
|
// peerB doesn't satisfy the NB posture check, and doesn't exist in destination group peer's
|
||||||
// no connection should be established to any peer of destination group
|
// no connection should be established to any peer of destination group
|
||||||
peers, firewallRules := account.GetPeerConnectionResources(context.Background(), "peerB", approvedPeers)
|
peers, firewallRules := account.GetPeerConnectionResources(context.Background(), account.Peers["peerB"], approvedPeers)
|
||||||
assert.Len(t, peers, 0)
|
assert.Len(t, peers, 0)
|
||||||
assert.Len(t, firewallRules, 0)
|
assert.Len(t, firewallRules, 0)
|
||||||
|
|
||||||
// peerI doesn't satisfy the OS version posture check, and doesn't exist in destination group peer's
|
// peerI doesn't satisfy the OS version posture check, and doesn't exist in destination group peer's
|
||||||
// no connection should be established to any peer of destination group
|
// no connection should be established to any peer of destination group
|
||||||
peers, firewallRules = account.GetPeerConnectionResources(context.Background(), "peerI", approvedPeers)
|
peers, firewallRules = account.GetPeerConnectionResources(context.Background(), account.Peers["peerI"], approvedPeers)
|
||||||
assert.Len(t, peers, 0)
|
assert.Len(t, peers, 0)
|
||||||
assert.Len(t, firewallRules, 0)
|
assert.Len(t, firewallRules, 0)
|
||||||
|
|
||||||
// peerC satisfy the NB posture check, should establish connection to all destination group peer's
|
// peerC satisfy the NB posture check, should establish connection to all destination group peer's
|
||||||
// We expect a single permissive firewall rule which all outgoing connections
|
// We expect a single permissive firewall rule which all outgoing connections
|
||||||
peers, firewallRules = account.GetPeerConnectionResources(context.Background(), "peerC", approvedPeers)
|
peers, firewallRules = account.GetPeerConnectionResources(context.Background(), account.Peers["peerC"], approvedPeers)
|
||||||
assert.Len(t, peers, len(account.Groups["GroupSwarm"].Peers))
|
assert.Len(t, peers, len(account.Groups["GroupSwarm"].Peers))
|
||||||
assert.Len(t, firewallRules, len(account.Groups["GroupSwarm"].Peers))
|
assert.Len(t, firewallRules, len(account.Groups["GroupSwarm"].Peers))
|
||||||
|
|
||||||
@@ -827,14 +900,14 @@ func TestAccount_getPeersByPolicyPostureChecks(t *testing.T) {
|
|||||||
|
|
||||||
// peerE doesn't fulfill the NB posture check and exists in only destination group Swarm,
|
// peerE doesn't fulfill the NB posture check and exists in only destination group Swarm,
|
||||||
// all source group peers satisfying the NB posture check should establish connection
|
// all source group peers satisfying the NB posture check should establish connection
|
||||||
peers, firewallRules = account.GetPeerConnectionResources(context.Background(), "peerE", approvedPeers)
|
peers, firewallRules = account.GetPeerConnectionResources(context.Background(), account.Peers["peerE"], approvedPeers)
|
||||||
assert.Len(t, peers, 3)
|
assert.Len(t, peers, 3)
|
||||||
assert.Len(t, firewallRules, 3)
|
assert.Len(t, firewallRules, 3)
|
||||||
assert.Contains(t, peers, account.Peers["peerA"])
|
assert.Contains(t, peers, account.Peers["peerA"])
|
||||||
assert.Contains(t, peers, account.Peers["peerC"])
|
assert.Contains(t, peers, account.Peers["peerC"])
|
||||||
assert.Contains(t, peers, account.Peers["peerD"])
|
assert.Contains(t, peers, account.Peers["peerD"])
|
||||||
|
|
||||||
peers, firewallRules = account.GetPeerConnectionResources(context.Background(), "peerA", approvedPeers)
|
peers, firewallRules = account.GetPeerConnectionResources(context.Background(), account.Peers["peerA"], approvedPeers)
|
||||||
assert.Len(t, peers, 5)
|
assert.Len(t, peers, 5)
|
||||||
// assert peers from Group Swarm
|
// assert peers from Group Swarm
|
||||||
assert.Contains(t, peers, account.Peers["peerD"])
|
assert.Contains(t, peers, account.Peers["peerD"])
|
||||||
|
|||||||
@@ -24,20 +24,12 @@ func sanitizeVersion(version string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (n *NBVersionCheck) Check(ctx context.Context, peer nbpeer.Peer) (bool, error) {
|
func (n *NBVersionCheck) Check(ctx context.Context, peer nbpeer.Peer) (bool, error) {
|
||||||
peerVersion := sanitizeVersion(peer.Meta.WtVersion)
|
meetsMin, err := MeetsMinVersion(n.MinVersion, peer.Meta.WtVersion)
|
||||||
minVersion := sanitizeVersion(n.MinVersion)
|
|
||||||
|
|
||||||
peerNBVersion, err := version.NewVersion(peerVersion)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
constraints, err := version.NewConstraint(">= " + minVersion)
|
if meetsMin {
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if constraints.Check(peerNBVersion) {
|
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,3 +52,21 @@ func (n *NBVersionCheck) Validate() error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MeetsMinVersion checks if the peer's version meets or exceeds the minimum required version
|
||||||
|
func MeetsMinVersion(minVer, peerVer string) (bool, error) {
|
||||||
|
peerVer = sanitizeVersion(peerVer)
|
||||||
|
minVer = sanitizeVersion(minVer)
|
||||||
|
|
||||||
|
peerNBVer, err := version.NewVersion(peerVer)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
constraints, err := version.NewConstraint(">= " + minVer)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return constraints.Check(peerNBVer), nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -139,3 +139,68 @@ func TestNBVersionCheck_Validate(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMeetsMinVersion(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
minVer string
|
||||||
|
peerVer string
|
||||||
|
want bool
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Peer version greater than min version",
|
||||||
|
minVer: "0.26.0",
|
||||||
|
peerVer: "0.60.1",
|
||||||
|
want: true,
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Peer version equals min version",
|
||||||
|
minVer: "1.0.0",
|
||||||
|
peerVer: "1.0.0",
|
||||||
|
want: true,
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Peer version less than min version",
|
||||||
|
minVer: "1.0.0",
|
||||||
|
peerVer: "0.9.9",
|
||||||
|
want: false,
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Peer version with pre-release tag greater than min version",
|
||||||
|
minVer: "1.0.0",
|
||||||
|
peerVer: "1.0.1-alpha",
|
||||||
|
want: true,
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Invalid peer version format",
|
||||||
|
minVer: "1.0.0",
|
||||||
|
peerVer: "dev",
|
||||||
|
want: false,
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Invalid min version format",
|
||||||
|
minVer: "invalid.version",
|
||||||
|
peerVer: "1.0.0",
|
||||||
|
want: false,
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got, err := MeetsMinVersion(tt.minVer, tt.peerVer)
|
||||||
|
if tt.wantErr {
|
||||||
|
assert.Error(t, err)
|
||||||
|
} else {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
assert.Equal(t, tt.want, got)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ func initTestPostureChecksAccount(am *DefaultAccountManager) (*types.Account, er
|
|||||||
Role: types.UserRoleUser,
|
Role: types.UserRoleUser,
|
||||||
}
|
}
|
||||||
|
|
||||||
account := newAccountWithId(context.Background(), accountID, groupAdminUserID, domain)
|
account := newAccountWithId(context.Background(), accountID, groupAdminUserID, domain, false)
|
||||||
account.Users[admin.Id] = admin
|
account.Users[admin.Id] = admin
|
||||||
account.Users[user.Id] = user
|
account.Users[user.Id] = user
|
||||||
|
|
||||||
|
|||||||
@@ -1284,7 +1284,7 @@ func createRouterManager(t *testing.T) (*DefaultAccountManager, error) {
|
|||||||
|
|
||||||
permissionsManager := permissions.NewManager(store)
|
permissionsManager := permissions.NewManager(store)
|
||||||
|
|
||||||
return BuildManager(context.Background(), store, NewPeersUpdateManager(nil), nil, "", "netbird.selfhosted", eventStore, nil, false, MocIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager)
|
return BuildManager(context.Background(), store, NewPeersUpdateManager(nil), nil, "", "netbird.selfhosted", eventStore, nil, false, MocIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func createRouterStore(t *testing.T) (store.Store, error) {
|
func createRouterStore(t *testing.T) (store.Store, error) {
|
||||||
@@ -1305,7 +1305,7 @@ func initTestRouteAccount(t *testing.T, am *DefaultAccountManager) (*types.Accou
|
|||||||
accountID := "testingAcc"
|
accountID := "testingAcc"
|
||||||
domain := "example.com"
|
domain := "example.com"
|
||||||
|
|
||||||
account := newAccountWithId(context.Background(), accountID, userID, domain)
|
account := newAccountWithId(context.Background(), accountID, userID, domain, false)
|
||||||
err := am.Store.SaveAccount(context.Background(), account)
|
err := am.Store.SaveAccount(context.Background(), account)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -1184,7 +1184,7 @@ func NewSqliteStoreFromFileStore(ctx context.Context, fileStore *FileStore, data
|
|||||||
for _, account := range fileStore.GetAllAccounts(ctx) {
|
for _, account := range fileStore.GetAllAccounts(ctx) {
|
||||||
_, err = account.GetGroupAll()
|
_, err = account.GetGroupAll()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err := account.AddAllGroup(); err != nil {
|
if err := account.AddAllGroup(false); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2044,7 +2044,7 @@ func newAccountWithId(ctx context.Context, accountID, userID, domain string) *ty
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := acc.AddAllGroup(); err != nil {
|
if err := acc.AddAllGroup(false); err != nil {
|
||||||
log.WithContext(ctx).Errorf("error adding all group to account %s: %v", acc.Id, err)
|
log.WithContext(ctx).Errorf("error adding all group to account %s: %v", acc.Id, err)
|
||||||
}
|
}
|
||||||
return acc
|
return acc
|
||||||
|
|||||||
@@ -391,7 +391,7 @@ func addAllGroupToAccount(ctx context.Context, store Store) error {
|
|||||||
|
|
||||||
_, err := account.GetGroupAll()
|
_, err := account.GetGroupAll()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err := account.AddAllGroup(); err != nil {
|
if err := account.AddAllGroup(false); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
shouldSave = true
|
shouldSave = true
|
||||||
|
|||||||
@@ -18,6 +18,10 @@ type UpdateChannelMetrics struct {
|
|||||||
getAllConnectedPeersDurationMicro metric.Int64Histogram
|
getAllConnectedPeersDurationMicro metric.Int64Histogram
|
||||||
getAllConnectedPeers metric.Int64Histogram
|
getAllConnectedPeers metric.Int64Histogram
|
||||||
hasChannelDurationMicro metric.Int64Histogram
|
hasChannelDurationMicro metric.Int64Histogram
|
||||||
|
calcPostureChecksDurationMicro metric.Int64Histogram
|
||||||
|
calcPeerNetworkMapDurationMs metric.Int64Histogram
|
||||||
|
mergeNetworkMapDurationMicro metric.Int64Histogram
|
||||||
|
toSyncResponseDurationMicro metric.Int64Histogram
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,6 +93,38 @@ func NewUpdateChannelMetrics(ctx context.Context, meter metric.Meter) (*UpdateCh
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
calcPostureChecksDurationMicro, err := meter.Int64Histogram("management.updatechannel.calc.posturechecks.duration.micro",
|
||||||
|
metric.WithUnit("microseconds"),
|
||||||
|
metric.WithDescription("Duration of how long it takes to get the posture checks for a peer"),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
calcPeerNetworkMapDurationMs, err := meter.Int64Histogram("management.updatechannel.calc.networkmap.duration.ms",
|
||||||
|
metric.WithUnit("milliseconds"),
|
||||||
|
metric.WithDescription("Duration of how long it takes to calculate the network map for a peer"),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
mergeNetworkMapDurationMicro, err := meter.Int64Histogram("management.updatechannel.merge.networkmap.duration.micro",
|
||||||
|
metric.WithUnit("microseconds"),
|
||||||
|
metric.WithDescription("Duration of how long it takes to merge the network maps for a peer"),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
toSyncResponseDurationMicro, err := meter.Int64Histogram("management.updatechannel.tosyncresponse.duration.micro",
|
||||||
|
metric.WithUnit("microseconds"),
|
||||||
|
metric.WithDescription("Duration of how long it takes to convert the network map to sync response"),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return &UpdateChannelMetrics{
|
return &UpdateChannelMetrics{
|
||||||
createChannelDurationMicro: createChannelDurationMicro,
|
createChannelDurationMicro: createChannelDurationMicro,
|
||||||
closeChannelDurationMicro: closeChannelDurationMicro,
|
closeChannelDurationMicro: closeChannelDurationMicro,
|
||||||
@@ -98,6 +134,10 @@ func NewUpdateChannelMetrics(ctx context.Context, meter metric.Meter) (*UpdateCh
|
|||||||
getAllConnectedPeersDurationMicro: getAllConnectedPeersDurationMicro,
|
getAllConnectedPeersDurationMicro: getAllConnectedPeersDurationMicro,
|
||||||
getAllConnectedPeers: getAllConnectedPeers,
|
getAllConnectedPeers: getAllConnectedPeers,
|
||||||
hasChannelDurationMicro: hasChannelDurationMicro,
|
hasChannelDurationMicro: hasChannelDurationMicro,
|
||||||
|
calcPostureChecksDurationMicro: calcPostureChecksDurationMicro,
|
||||||
|
calcPeerNetworkMapDurationMs: calcPeerNetworkMapDurationMs,
|
||||||
|
mergeNetworkMapDurationMicro: mergeNetworkMapDurationMicro,
|
||||||
|
toSyncResponseDurationMicro: toSyncResponseDurationMicro,
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
@@ -137,3 +177,19 @@ func (metrics *UpdateChannelMetrics) CountGetAllConnectedPeersDuration(duration
|
|||||||
func (metrics *UpdateChannelMetrics) CountHasChannelDuration(duration time.Duration) {
|
func (metrics *UpdateChannelMetrics) CountHasChannelDuration(duration time.Duration) {
|
||||||
metrics.hasChannelDurationMicro.Record(metrics.ctx, duration.Microseconds())
|
metrics.hasChannelDurationMicro.Record(metrics.ctx, duration.Microseconds())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (metrics *UpdateChannelMetrics) CountCalcPostureChecksDuration(duration time.Duration) {
|
||||||
|
metrics.calcPostureChecksDurationMicro.Record(metrics.ctx, duration.Microseconds())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (metrics *UpdateChannelMetrics) CountCalcPeerNetworkMapDuration(duration time.Duration) {
|
||||||
|
metrics.calcPeerNetworkMapDurationMs.Record(metrics.ctx, duration.Milliseconds())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (metrics *UpdateChannelMetrics) CountMergeNetworkMapDuration(duration time.Duration) {
|
||||||
|
metrics.mergeNetworkMapDurationMicro.Record(metrics.ctx, duration.Microseconds())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (metrics *UpdateChannelMetrics) CountToSyncResponseDuration(duration time.Duration) {
|
||||||
|
metrics.toSyncResponseDurationMicro.Record(metrics.ctx, duration.Microseconds())
|
||||||
|
}
|
||||||
|
|||||||
@@ -36,6 +36,9 @@ const (
|
|||||||
PublicCategory = "public"
|
PublicCategory = "public"
|
||||||
PrivateCategory = "private"
|
PrivateCategory = "private"
|
||||||
UnknownCategory = "unknown"
|
UnknownCategory = "unknown"
|
||||||
|
|
||||||
|
// firewallRuleMinPortRangesVer defines the minimum peer version that supports port range rules.
|
||||||
|
firewallRuleMinPortRangesVer = "0.48.0"
|
||||||
)
|
)
|
||||||
|
|
||||||
type LookupMap map[string]struct{}
|
type LookupMap map[string]struct{}
|
||||||
@@ -248,7 +251,7 @@ func (a *Account) GetPeerNetworkMap(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
aclPeers, firewallRules := a.GetPeerConnectionResources(ctx, peerID, validatedPeersMap)
|
aclPeers, firewallRules := a.GetPeerConnectionResources(ctx, peer, validatedPeersMap)
|
||||||
// exclude expired peers
|
// exclude expired peers
|
||||||
var peersToConnect []*nbpeer.Peer
|
var peersToConnect []*nbpeer.Peer
|
||||||
var expiredPeers []*nbpeer.Peer
|
var expiredPeers []*nbpeer.Peer
|
||||||
@@ -961,8 +964,9 @@ func (a *Account) UserGroupsRemoveFromPeers(userID string, groups ...string) map
|
|||||||
// GetPeerConnectionResources for a given peer
|
// GetPeerConnectionResources for a given peer
|
||||||
//
|
//
|
||||||
// This function returns the list of peers and firewall rules that are applicable to a given peer.
|
// This function returns the list of peers and firewall rules that are applicable to a given peer.
|
||||||
func (a *Account) GetPeerConnectionResources(ctx context.Context, peerID string, validatedPeersMap map[string]struct{}) ([]*nbpeer.Peer, []*FirewallRule) {
|
func (a *Account) GetPeerConnectionResources(ctx context.Context, peer *nbpeer.Peer, validatedPeersMap map[string]struct{}) ([]*nbpeer.Peer, []*FirewallRule) {
|
||||||
generateResources, getAccumulatedResources := a.connResourcesGenerator(ctx)
|
generateResources, getAccumulatedResources := a.connResourcesGenerator(ctx, peer)
|
||||||
|
|
||||||
for _, policy := range a.Policies {
|
for _, policy := range a.Policies {
|
||||||
if !policy.Enabled {
|
if !policy.Enabled {
|
||||||
continue
|
continue
|
||||||
@@ -973,8 +977,8 @@ func (a *Account) GetPeerConnectionResources(ctx context.Context, peerID string,
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
sourcePeers, peerInSources := a.getAllPeersFromGroups(ctx, rule.Sources, peerID, policy.SourcePostureChecks, validatedPeersMap)
|
sourcePeers, peerInSources := a.getAllPeersFromGroups(ctx, rule.Sources, peer.ID, policy.SourcePostureChecks, validatedPeersMap)
|
||||||
destinationPeers, peerInDestinations := a.getAllPeersFromGroups(ctx, rule.Destinations, peerID, nil, validatedPeersMap)
|
destinationPeers, peerInDestinations := a.getAllPeersFromGroups(ctx, rule.Destinations, peer.ID, nil, validatedPeersMap)
|
||||||
|
|
||||||
if rule.Bidirectional {
|
if rule.Bidirectional {
|
||||||
if peerInSources {
|
if peerInSources {
|
||||||
@@ -1003,7 +1007,7 @@ func (a *Account) GetPeerConnectionResources(ctx context.Context, peerID string,
|
|||||||
// The generator function is used to generate the list of peers and firewall rules that are applicable to a given peer.
|
// The generator function is used to generate the list of peers and firewall rules that are applicable to a given peer.
|
||||||
// It safe to call the generator function multiple times for same peer and different rules no duplicates will be
|
// It safe to call the generator function multiple times for same peer and different rules no duplicates will be
|
||||||
// generated. The accumulator function returns the result of all the generator calls.
|
// generated. The accumulator function returns the result of all the generator calls.
|
||||||
func (a *Account) connResourcesGenerator(ctx context.Context) (func(*PolicyRule, []*nbpeer.Peer, int), func() ([]*nbpeer.Peer, []*FirewallRule)) {
|
func (a *Account) connResourcesGenerator(ctx context.Context, targetPeer *nbpeer.Peer) (func(*PolicyRule, []*nbpeer.Peer, int), func() ([]*nbpeer.Peer, []*FirewallRule)) {
|
||||||
rulesExists := make(map[string]struct{})
|
rulesExists := make(map[string]struct{})
|
||||||
peersExists := make(map[string]struct{})
|
peersExists := make(map[string]struct{})
|
||||||
rules := make([]*FirewallRule, 0)
|
rules := make([]*FirewallRule, 0)
|
||||||
@@ -1051,17 +1055,7 @@ func (a *Account) connResourcesGenerator(ctx context.Context) (func(*PolicyRule,
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, port := range rule.Ports {
|
rules = append(rules, expandPortsAndRanges(fr, rule, targetPeer)...)
|
||||||
pr := fr // clone rule and add set new port
|
|
||||||
pr.Port = port
|
|
||||||
rules = append(rules, &pr)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, portRange := range rule.PortRanges {
|
|
||||||
pr := fr
|
|
||||||
pr.PortRange = portRange
|
|
||||||
rules = append(rules, &pr)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, func() ([]*nbpeer.Peer, []*FirewallRule) {
|
}, func() ([]*nbpeer.Peer, []*FirewallRule) {
|
||||||
return peers, rules
|
return peers, rules
|
||||||
@@ -1552,7 +1546,7 @@ func getPoliciesSourcePeers(policies []*Policy, groups map[string]*Group) map[st
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AddAllGroup to account object if it doesn't exist
|
// AddAllGroup to account object if it doesn't exist
|
||||||
func (a *Account) AddAllGroup() error {
|
func (a *Account) AddAllGroup(disableDefaultPolicy bool) error {
|
||||||
if len(a.Groups) == 0 {
|
if len(a.Groups) == 0 {
|
||||||
allGroup := &Group{
|
allGroup := &Group{
|
||||||
ID: xid.New().String(),
|
ID: xid.New().String(),
|
||||||
@@ -1564,6 +1558,10 @@ func (a *Account) AddAllGroup() error {
|
|||||||
}
|
}
|
||||||
a.Groups = map[string]*Group{allGroup.ID: allGroup}
|
a.Groups = map[string]*Group{allGroup.ID: allGroup}
|
||||||
|
|
||||||
|
if disableDefaultPolicy {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
id := xid.New().String()
|
id := xid.New().String()
|
||||||
|
|
||||||
defaultPolicy := &Policy{
|
defaultPolicy := &Policy{
|
||||||
@@ -1590,3 +1588,45 @@ func (a *Account) AddAllGroup() error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// expandPortsAndRanges expands Ports and PortRanges of a rule into individual firewall rules
|
||||||
|
func expandPortsAndRanges(base FirewallRule, rule *PolicyRule, peer *nbpeer.Peer) []*FirewallRule {
|
||||||
|
var expanded []*FirewallRule
|
||||||
|
|
||||||
|
if len(rule.Ports) > 0 {
|
||||||
|
for _, port := range rule.Ports {
|
||||||
|
fr := base
|
||||||
|
fr.Port = port
|
||||||
|
expanded = append(expanded, &fr)
|
||||||
|
}
|
||||||
|
return expanded
|
||||||
|
}
|
||||||
|
|
||||||
|
supportPortRanges := peerSupportsPortRanges(peer.Meta.WtVersion)
|
||||||
|
for _, portRange := range rule.PortRanges {
|
||||||
|
fr := base
|
||||||
|
|
||||||
|
if supportPortRanges {
|
||||||
|
fr.PortRange = portRange
|
||||||
|
} else {
|
||||||
|
// Peer doesn't support port ranges, only allow single-port ranges
|
||||||
|
if portRange.Start != portRange.End {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fr.Port = strconv.FormatUint(uint64(portRange.Start), 10)
|
||||||
|
}
|
||||||
|
expanded = append(expanded, &fr)
|
||||||
|
}
|
||||||
|
|
||||||
|
return expanded
|
||||||
|
}
|
||||||
|
|
||||||
|
// peerSupportsPortRanges checks if the peer version supports port ranges.
|
||||||
|
func peerSupportsPortRanges(peerVer string) bool {
|
||||||
|
if strings.Contains(peerVer, "dev") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
meetMinVer, err := posture.MeetsMinVersion(firewallRuleMinPortRangesVer, peerVer)
|
||||||
|
return err == nil && meetMinVer
|
||||||
|
}
|
||||||
|
|||||||
@@ -53,6 +53,9 @@ type Config struct {
|
|||||||
StoreConfig StoreConfig
|
StoreConfig StoreConfig
|
||||||
|
|
||||||
ReverseProxy ReverseProxy
|
ReverseProxy ReverseProxy
|
||||||
|
|
||||||
|
// disable default all-to-all policy
|
||||||
|
DisableDefaultPolicy bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAuthAudiences returns the audience from the http config and device authorization flow config
|
// GetAuthAudiences returns the audience from the http config and device authorization flow config
|
||||||
|
|||||||
@@ -76,7 +76,6 @@ func generateRouteFirewallRules(ctx context.Context, route *nbroute.Route, rule
|
|||||||
rules = append(rules, generateRulesWithPortRanges(baseRule, rule, rulesExists)...)
|
rules = append(rules, generateRulesWithPortRanges(baseRule, rule, rulesExists)...)
|
||||||
} else {
|
} else {
|
||||||
rules = append(rules, generateRulesWithPorts(ctx, baseRule, rule, rulesExists)...)
|
rules = append(rules, generateRulesWithPorts(ctx, baseRule, rule, rulesExists)...)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: generate IPv6 rules for dynamic routes
|
// TODO: generate IPv6 rules for dynamic routes
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ func TestUser_CreatePAT_ForSameUser(t *testing.T) {
|
|||||||
}
|
}
|
||||||
t.Cleanup(cleanup)
|
t.Cleanup(cleanup)
|
||||||
|
|
||||||
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "")
|
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "", false)
|
||||||
|
|
||||||
err = s.SaveAccount(context.Background(), account)
|
err = s.SaveAccount(context.Background(), account)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -103,7 +103,7 @@ func TestUser_CreatePAT_ForDifferentUser(t *testing.T) {
|
|||||||
}
|
}
|
||||||
t.Cleanup(cleanup)
|
t.Cleanup(cleanup)
|
||||||
|
|
||||||
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "")
|
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "", false)
|
||||||
account.Users[mockTargetUserId] = &types.User{
|
account.Users[mockTargetUserId] = &types.User{
|
||||||
Id: mockTargetUserId,
|
Id: mockTargetUserId,
|
||||||
IsServiceUser: false,
|
IsServiceUser: false,
|
||||||
@@ -131,7 +131,7 @@ func TestUser_CreatePAT_ForServiceUser(t *testing.T) {
|
|||||||
}
|
}
|
||||||
t.Cleanup(cleanup)
|
t.Cleanup(cleanup)
|
||||||
|
|
||||||
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "")
|
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "", false)
|
||||||
account.Users[mockTargetUserId] = &types.User{
|
account.Users[mockTargetUserId] = &types.User{
|
||||||
Id: mockTargetUserId,
|
Id: mockTargetUserId,
|
||||||
IsServiceUser: true,
|
IsServiceUser: true,
|
||||||
@@ -163,7 +163,7 @@ func TestUser_CreatePAT_WithWrongExpiration(t *testing.T) {
|
|||||||
}
|
}
|
||||||
t.Cleanup(cleanup)
|
t.Cleanup(cleanup)
|
||||||
|
|
||||||
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "")
|
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "", false)
|
||||||
|
|
||||||
err = store.SaveAccount(context.Background(), account)
|
err = store.SaveAccount(context.Background(), account)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -188,7 +188,7 @@ func TestUser_CreatePAT_WithEmptyName(t *testing.T) {
|
|||||||
}
|
}
|
||||||
t.Cleanup(cleanup)
|
t.Cleanup(cleanup)
|
||||||
|
|
||||||
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "")
|
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "", false)
|
||||||
|
|
||||||
err = store.SaveAccount(context.Background(), account)
|
err = store.SaveAccount(context.Background(), account)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -213,7 +213,7 @@ func TestUser_DeletePAT(t *testing.T) {
|
|||||||
}
|
}
|
||||||
t.Cleanup(cleanup)
|
t.Cleanup(cleanup)
|
||||||
|
|
||||||
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "")
|
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "", false)
|
||||||
account.Users[mockUserID] = &types.User{
|
account.Users[mockUserID] = &types.User{
|
||||||
Id: mockUserID,
|
Id: mockUserID,
|
||||||
PATs: map[string]*types.PersonalAccessToken{
|
PATs: map[string]*types.PersonalAccessToken{
|
||||||
@@ -256,7 +256,7 @@ func TestUser_GetPAT(t *testing.T) {
|
|||||||
}
|
}
|
||||||
t.Cleanup(cleanup)
|
t.Cleanup(cleanup)
|
||||||
|
|
||||||
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "")
|
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "", false)
|
||||||
account.Users[mockUserID] = &types.User{
|
account.Users[mockUserID] = &types.User{
|
||||||
Id: mockUserID,
|
Id: mockUserID,
|
||||||
AccountID: mockAccountID,
|
AccountID: mockAccountID,
|
||||||
@@ -296,7 +296,7 @@ func TestUser_GetAllPATs(t *testing.T) {
|
|||||||
}
|
}
|
||||||
t.Cleanup(cleanup)
|
t.Cleanup(cleanup)
|
||||||
|
|
||||||
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "")
|
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "", false)
|
||||||
account.Users[mockUserID] = &types.User{
|
account.Users[mockUserID] = &types.User{
|
||||||
Id: mockUserID,
|
Id: mockUserID,
|
||||||
AccountID: mockAccountID,
|
AccountID: mockAccountID,
|
||||||
@@ -406,7 +406,7 @@ func TestUser_CreateServiceUser(t *testing.T) {
|
|||||||
}
|
}
|
||||||
t.Cleanup(cleanup)
|
t.Cleanup(cleanup)
|
||||||
|
|
||||||
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "")
|
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "", false)
|
||||||
|
|
||||||
err = store.SaveAccount(context.Background(), account)
|
err = store.SaveAccount(context.Background(), account)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -453,7 +453,7 @@ func TestUser_CreateUser_ServiceUser(t *testing.T) {
|
|||||||
}
|
}
|
||||||
t.Cleanup(cleanup)
|
t.Cleanup(cleanup)
|
||||||
|
|
||||||
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "")
|
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "", false)
|
||||||
|
|
||||||
err = store.SaveAccount(context.Background(), account)
|
err = store.SaveAccount(context.Background(), account)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -501,7 +501,7 @@ func TestUser_CreateUser_RegularUser(t *testing.T) {
|
|||||||
}
|
}
|
||||||
t.Cleanup(cleanup)
|
t.Cleanup(cleanup)
|
||||||
|
|
||||||
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "")
|
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "", false)
|
||||||
|
|
||||||
err = store.SaveAccount(context.Background(), account)
|
err = store.SaveAccount(context.Background(), account)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -532,7 +532,7 @@ func TestUser_InviteNewUser(t *testing.T) {
|
|||||||
}
|
}
|
||||||
t.Cleanup(cleanup)
|
t.Cleanup(cleanup)
|
||||||
|
|
||||||
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "")
|
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "", false)
|
||||||
|
|
||||||
err = store.SaveAccount(context.Background(), account)
|
err = store.SaveAccount(context.Background(), account)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -639,7 +639,7 @@ func TestUser_DeleteUser_ServiceUser(t *testing.T) {
|
|||||||
}
|
}
|
||||||
t.Cleanup(cleanup)
|
t.Cleanup(cleanup)
|
||||||
|
|
||||||
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "")
|
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "", false)
|
||||||
account.Users[mockServiceUserID] = tt.serviceUser
|
account.Users[mockServiceUserID] = tt.serviceUser
|
||||||
|
|
||||||
err = store.SaveAccount(context.Background(), account)
|
err = store.SaveAccount(context.Background(), account)
|
||||||
@@ -678,7 +678,7 @@ func TestUser_DeleteUser_SelfDelete(t *testing.T) {
|
|||||||
}
|
}
|
||||||
t.Cleanup(cleanup)
|
t.Cleanup(cleanup)
|
||||||
|
|
||||||
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "")
|
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "", false)
|
||||||
|
|
||||||
err = store.SaveAccount(context.Background(), account)
|
err = store.SaveAccount(context.Background(), account)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -705,7 +705,7 @@ func TestUser_DeleteUser_regularUser(t *testing.T) {
|
|||||||
}
|
}
|
||||||
t.Cleanup(cleanup)
|
t.Cleanup(cleanup)
|
||||||
|
|
||||||
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "")
|
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "", false)
|
||||||
|
|
||||||
targetId := "user2"
|
targetId := "user2"
|
||||||
account.Users[targetId] = &types.User{
|
account.Users[targetId] = &types.User{
|
||||||
@@ -792,7 +792,7 @@ func TestUser_DeleteUser_RegularUsers(t *testing.T) {
|
|||||||
}
|
}
|
||||||
t.Cleanup(cleanup)
|
t.Cleanup(cleanup)
|
||||||
|
|
||||||
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "")
|
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "", false)
|
||||||
|
|
||||||
targetId := "user2"
|
targetId := "user2"
|
||||||
account.Users[targetId] = &types.User{
|
account.Users[targetId] = &types.User{
|
||||||
@@ -952,7 +952,7 @@ func TestDefaultAccountManager_GetUser(t *testing.T) {
|
|||||||
}
|
}
|
||||||
t.Cleanup(cleanup)
|
t.Cleanup(cleanup)
|
||||||
|
|
||||||
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "")
|
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "", false)
|
||||||
|
|
||||||
err = store.SaveAccount(context.Background(), account)
|
err = store.SaveAccount(context.Background(), account)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -988,7 +988,7 @@ func TestDefaultAccountManager_ListUsers(t *testing.T) {
|
|||||||
}
|
}
|
||||||
t.Cleanup(cleanup)
|
t.Cleanup(cleanup)
|
||||||
|
|
||||||
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "")
|
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "", false)
|
||||||
account.Users["normal_user1"] = types.NewRegularUser("normal_user1")
|
account.Users["normal_user1"] = types.NewRegularUser("normal_user1")
|
||||||
account.Users["normal_user2"] = types.NewRegularUser("normal_user2")
|
account.Users["normal_user2"] = types.NewRegularUser("normal_user2")
|
||||||
|
|
||||||
@@ -1030,7 +1030,7 @@ func TestDefaultAccountManager_ExternalCache(t *testing.T) {
|
|||||||
}
|
}
|
||||||
t.Cleanup(cleanup)
|
t.Cleanup(cleanup)
|
||||||
|
|
||||||
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "")
|
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "", false)
|
||||||
externalUser := &types.User{
|
externalUser := &types.User{
|
||||||
Id: "externalUser",
|
Id: "externalUser",
|
||||||
Role: types.UserRoleUser,
|
Role: types.UserRoleUser,
|
||||||
@@ -1098,7 +1098,7 @@ func TestUser_GetUsersFromAccount_ForAdmin(t *testing.T) {
|
|||||||
}
|
}
|
||||||
t.Cleanup(cleanup)
|
t.Cleanup(cleanup)
|
||||||
|
|
||||||
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "")
|
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "", false)
|
||||||
account.Users[mockServiceUserID] = &types.User{
|
account.Users[mockServiceUserID] = &types.User{
|
||||||
Id: mockServiceUserID,
|
Id: mockServiceUserID,
|
||||||
Role: "user",
|
Role: "user",
|
||||||
@@ -1132,7 +1132,7 @@ func TestUser_GetUsersFromAccount_ForUser(t *testing.T) {
|
|||||||
}
|
}
|
||||||
t.Cleanup(cleanup)
|
t.Cleanup(cleanup)
|
||||||
|
|
||||||
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "")
|
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "", false)
|
||||||
account.Users[mockServiceUserID] = &types.User{
|
account.Users[mockServiceUserID] = &types.User{
|
||||||
Id: mockServiceUserID,
|
Id: mockServiceUserID,
|
||||||
Role: "user",
|
Role: "user",
|
||||||
@@ -1499,7 +1499,7 @@ func TestSaveOrAddUser_PreventAccountSwitch(t *testing.T) {
|
|||||||
}
|
}
|
||||||
t.Cleanup(cleanup)
|
t.Cleanup(cleanup)
|
||||||
|
|
||||||
account1 := newAccountWithId(context.Background(), "account1", "ownerAccount1", "")
|
account1 := newAccountWithId(context.Background(), "account1", "ownerAccount1", "", false)
|
||||||
targetId := "user2"
|
targetId := "user2"
|
||||||
account1.Users[targetId] = &types.User{
|
account1.Users[targetId] = &types.User{
|
||||||
Id: targetId,
|
Id: targetId,
|
||||||
@@ -1508,7 +1508,7 @@ func TestSaveOrAddUser_PreventAccountSwitch(t *testing.T) {
|
|||||||
}
|
}
|
||||||
require.NoError(t, s.SaveAccount(context.Background(), account1))
|
require.NoError(t, s.SaveAccount(context.Background(), account1))
|
||||||
|
|
||||||
account2 := newAccountWithId(context.Background(), "account2", "ownerAccount2", "")
|
account2 := newAccountWithId(context.Background(), "account2", "ownerAccount2", "", false)
|
||||||
require.NoError(t, s.SaveAccount(context.Background(), account2))
|
require.NoError(t, s.SaveAccount(context.Background(), account2))
|
||||||
|
|
||||||
permissionsManager := permissions.NewManager(s)
|
permissionsManager := permissions.NewManager(s)
|
||||||
@@ -1535,7 +1535,7 @@ func TestDefaultAccountManager_GetCurrentUserInfo(t *testing.T) {
|
|||||||
}
|
}
|
||||||
t.Cleanup(cleanup)
|
t.Cleanup(cleanup)
|
||||||
|
|
||||||
account1 := newAccountWithId(context.Background(), "account1", "account1Owner", "")
|
account1 := newAccountWithId(context.Background(), "account1", "account1Owner", "", false)
|
||||||
account1.Settings.RegularUsersViewBlocked = false
|
account1.Settings.RegularUsersViewBlocked = false
|
||||||
account1.Users["blocked-user"] = &types.User{
|
account1.Users["blocked-user"] = &types.User{
|
||||||
Id: "blocked-user",
|
Id: "blocked-user",
|
||||||
@@ -1557,7 +1557,7 @@ func TestDefaultAccountManager_GetCurrentUserInfo(t *testing.T) {
|
|||||||
}
|
}
|
||||||
require.NoError(t, store.SaveAccount(context.Background(), account1))
|
require.NoError(t, store.SaveAccount(context.Background(), account1))
|
||||||
|
|
||||||
account2 := newAccountWithId(context.Background(), "account2", "account2Owner", "")
|
account2 := newAccountWithId(context.Background(), "account2", "account2Owner", "", false)
|
||||||
account2.Users["settings-blocked-user"] = &types.User{
|
account2.Users["settings-blocked-user"] = &types.User{
|
||||||
Id: "settings-blocked-user",
|
Id: "settings-blocked-user",
|
||||||
Role: types.UserRoleUser,
|
Role: types.UserRoleUser,
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ repo_gpgcheck=1
|
|||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
add_aur_repo() {
|
install_aur_package() {
|
||||||
INSTALL_PKGS="git base-devel go"
|
INSTALL_PKGS="git base-devel go"
|
||||||
REMOVE_PKGS=""
|
REMOVE_PKGS=""
|
||||||
|
|
||||||
@@ -154,8 +154,10 @@ add_aur_repo() {
|
|||||||
cd netbird-ui && makepkg -sri --noconfirm
|
cd netbird-ui && makepkg -sri --noconfirm
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Clean up the installed packages
|
if [ -n "$REMOVE_PKGS" ]; then
|
||||||
${SUDO} pacman -Rs "$REMOVE_PKGS" --noconfirm
|
# Clean up the installed packages
|
||||||
|
${SUDO} pacman -Rs "$REMOVE_PKGS" --noconfirm
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
prepare_tun_module() {
|
prepare_tun_module() {
|
||||||
@@ -277,7 +279,9 @@ install_netbird() {
|
|||||||
;;
|
;;
|
||||||
pacman)
|
pacman)
|
||||||
${SUDO} pacman -Syy
|
${SUDO} pacman -Syy
|
||||||
add_aur_repo
|
install_aur_package
|
||||||
|
# in-line with the docs at https://wiki.archlinux.org/title/Netbird
|
||||||
|
${SUDO} systemctl enable --now netbird@main.service
|
||||||
;;
|
;;
|
||||||
pkg)
|
pkg)
|
||||||
# Check if the package is already installed
|
# Check if the package is already installed
|
||||||
|
|||||||
+12
-2
@@ -21,6 +21,7 @@ var (
|
|||||||
// Update fetch the version info periodically and notify the onUpdateListener in case the UI version or the
|
// Update fetch the version info periodically and notify the onUpdateListener in case the UI version or the
|
||||||
// daemon version are deprecated
|
// daemon version are deprecated
|
||||||
type Update struct {
|
type Update struct {
|
||||||
|
httpAgent string
|
||||||
uiVersion *goversion.Version
|
uiVersion *goversion.Version
|
||||||
daemonVersion *goversion.Version
|
daemonVersion *goversion.Version
|
||||||
latestAvailable *goversion.Version
|
latestAvailable *goversion.Version
|
||||||
@@ -34,7 +35,7 @@ type Update struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewUpdate instantiate Update and start to fetch the new version information
|
// NewUpdate instantiate Update and start to fetch the new version information
|
||||||
func NewUpdate() *Update {
|
func NewUpdate(httpAgent string) *Update {
|
||||||
currentVersion, err := goversion.NewVersion(version)
|
currentVersion, err := goversion.NewVersion(version)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
currentVersion, _ = goversion.NewVersion("0.0.0")
|
currentVersion, _ = goversion.NewVersion("0.0.0")
|
||||||
@@ -43,6 +44,7 @@ func NewUpdate() *Update {
|
|||||||
latestAvailable, _ := goversion.NewVersion("0.0.0")
|
latestAvailable, _ := goversion.NewVersion("0.0.0")
|
||||||
|
|
||||||
u := &Update{
|
u := &Update{
|
||||||
|
httpAgent: httpAgent,
|
||||||
latestAvailable: latestAvailable,
|
latestAvailable: latestAvailable,
|
||||||
uiVersion: currentVersion,
|
uiVersion: currentVersion,
|
||||||
fetchTicker: time.NewTicker(fetchPeriod),
|
fetchTicker: time.NewTicker(fetchPeriod),
|
||||||
@@ -112,7 +114,15 @@ func (u *Update) startFetcher() {
|
|||||||
func (u *Update) fetchVersion() bool {
|
func (u *Update) fetchVersion() bool {
|
||||||
log.Debugf("fetching version info from %s", versionURL)
|
log.Debugf("fetching version info from %s", versionURL)
|
||||||
|
|
||||||
resp, err := http.Get(versionURL)
|
req, err := http.NewRequest("GET", versionURL, nil)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("failed to create request for version info: %s", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Header.Set("User-Agent", u.httpAgent)
|
||||||
|
|
||||||
|
resp, err := http.DefaultClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("failed to fetch version info: %s", err)
|
log.Errorf("failed to fetch version info: %s", err)
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const httpAgent = "pkg/test"
|
||||||
|
|
||||||
func TestNewUpdate(t *testing.T) {
|
func TestNewUpdate(t *testing.T) {
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
@@ -21,7 +23,7 @@ func TestNewUpdate(t *testing.T) {
|
|||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
|
|
||||||
onUpdate := false
|
onUpdate := false
|
||||||
u := NewUpdate()
|
u := NewUpdate(httpAgent)
|
||||||
defer u.StopWatch()
|
defer u.StopWatch()
|
||||||
u.SetOnUpdateListener(func() {
|
u.SetOnUpdateListener(func() {
|
||||||
onUpdate = true
|
onUpdate = true
|
||||||
@@ -46,7 +48,7 @@ func TestDoNotUpdate(t *testing.T) {
|
|||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
|
|
||||||
onUpdate := false
|
onUpdate := false
|
||||||
u := NewUpdate()
|
u := NewUpdate(httpAgent)
|
||||||
defer u.StopWatch()
|
defer u.StopWatch()
|
||||||
u.SetOnUpdateListener(func() {
|
u.SetOnUpdateListener(func() {
|
||||||
onUpdate = true
|
onUpdate = true
|
||||||
@@ -71,7 +73,7 @@ func TestDaemonUpdate(t *testing.T) {
|
|||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
|
|
||||||
onUpdate := false
|
onUpdate := false
|
||||||
u := NewUpdate()
|
u := NewUpdate(httpAgent)
|
||||||
defer u.StopWatch()
|
defer u.StopWatch()
|
||||||
u.SetOnUpdateListener(func() {
|
u.SetOnUpdateListener(func() {
|
||||||
onUpdate = true
|
onUpdate = true
|
||||||
|
|||||||
Reference in New Issue
Block a user